#+TITLE: Active Damping applied on the Simscape Model
:DRAWER:
#+STARTUP: overview
#+LANGUAGE: en
#+EMAIL: dehaeze.thomas@gmail.com
#+AUTHOR: Dehaeze Thomas
#+HTML_LINK_HOME: ../index.html
#+HTML_LINK_UP: ../index.html
#+HTML_HEAD:
#+HTML_HEAD:
#+HTML_HEAD:
#+HTML_HEAD:
#+HTML_HEAD:
#+HTML_HEAD:
#+HTML_HEAD:
#+HTML_MATHJAX: align: center tagside: right font: TeX
#+PROPERTY: header-args:matlab :session *MATLAB*
#+PROPERTY: header-args:matlab+ :comments org
#+PROPERTY: header-args:matlab+ :results none
#+PROPERTY: header-args:matlab+ :exports both
#+PROPERTY: header-args:matlab+ :eval no-export
#+PROPERTY: header-args:matlab+ :output-dir figs
#+PROPERTY: header-args:matlab+ :tangle no
#+PROPERTY: header-args:matlab+ :mkdirp yes
#+PROPERTY: header-args:shell :eval no-export
#+PROPERTY: header-args:latex :headers '("\\usepackage{tikz}" "\\usepackage{import}" "\\import{$HOME/Cloud/thesis/latex/}{config.tex}")
#+PROPERTY: header-args:latex+ :imagemagick t :fit yes
#+PROPERTY: header-args:latex+ :iminoptions -scale 100% -density 150
#+PROPERTY: header-args:latex+ :imoutoptions -quality 100
#+PROPERTY: header-args:latex+ :results raw replace :buffer no
#+PROPERTY: header-args:latex+ :eval no-export
#+PROPERTY: header-args:latex+ :exports both
#+PROPERTY: header-args:latex+ :mkdirp yes
#+PROPERTY: header-args:latex+ :output-dir figs
:END:
* Introduction :ignore:
The goal of this file is to study the use of active damping for the control of the NASS.
In general, three sensors can be used for Active Damping:
- A force sensor
- A relative motion sensor such as a capacitive sensor
- An inertial sensor such as an accelerometer of geophone
First, in section [[sec:undamped_system]], we look at the undamped system and we identify the dynamics from the actuators to the three sensor types.
Then, in section [[sec:act_damp_variability_plant]], we study the change of dynamics for the active damping plants with respect to various experimental conditions such as the sample mass and the spindle rotation speed.
Then, we will apply and compare the results of three active damping techniques:
- In section [[sec:iff]]: Integral Force Feedback is applied
- In section [[sec:dvf]]: Direct Velocity Feedback using a relative motion sensor is applied
- In section [[sec:ine]]: Inertial Control using a geophone is applied
For each of the active damping technique, we:
- Look at the obtain damped plant that will be used for High Authority control
- Simulate tomography experiments
- Compare the sensitivity from disturbances
* Undamped System
:PROPERTIES:
:header-args:matlab+: :tangle matlab/undamped_system.m
:header-args:matlab+: :comments none :mkdirp yes
:END:
<>
** Introduction :ignore:
In this section, we identify the dynamic of the system from forces applied in the nano-hexapod legs to the various sensors included in the nano-hexapod that could be use for Active Damping, namely:
- A relative motion sensor, measuring the relative displacement of each of the leg
- A force sensor measuring the total force transmitted to the top part of the leg in the direction of the leg
- A absolute velocity sensor measuring the absolute velocity of the top part of the leg in the direction of the leg
After that, a tomography experiment is simulation without any active damping techniques.
** Matlab Init :noexport:ignore:
#+begin_src matlab :tangle no :exports none :results silent :noweb yes :var current_dir=(file-name-directory buffer-file-name)
<>
#+end_src
#+begin_src matlab :exports none :results silent :noweb yes
<>
#+end_src
#+begin_src matlab :tangle no
simulinkproject('../');
#+end_src
#+begin_src matlab
addpath('active_damping/src/');
#+end_src
#+begin_src matlab
open('nass_model.slx')
#+end_src
** Identification of the dynamics for Active Damping
*** Identification
We initialize all the stages with the default parameters.
#+begin_src matlab
prepareLinearizeIdentification();
#+end_src
We identify the dynamics of the system using the =linearize= function.
#+begin_src matlab
%% Options for Linearized
options = linearizeOptions;
options.SampleTime = 0;
%% Name of the Simulink File
mdl = 'nass_model';
%% Input/Output definition
clear io; io_i = 1;
io(io_i) = linio([mdl, '/Controller'], 1, 'openinput'); io_i = io_i + 1; % Actuator Inputs
io(io_i) = linio([mdl, '/Micro-Station'], 3, 'openoutput', [], 'Dnlm'); io_i = io_i + 1; % Relative Motion Outputs
io(io_i) = linio([mdl, '/Micro-Station'], 3, 'openoutput', [], 'Fnlm'); io_i = io_i + 1; % Force Sensors
io(io_i) = linio([mdl, '/Micro-Station'], 3, 'openoutput', [], 'Vlm'); io_i = io_i + 1; % Absolute Velocity Outputs
%% Run the linearization
G = linearize(mdl, io, 0.5, options);
G.InputName = {'Fnl1', 'Fnl2', 'Fnl3', 'Fnl4', 'Fnl5', 'Fnl6'};
G.OutputName = {'Dnlm1', 'Dnlm2', 'Dnlm3', 'Dnlm4', 'Dnlm5', 'Dnlm6', ...
'Fnlm1', 'Fnlm2', 'Fnlm3', 'Fnlm4', 'Fnlm5', 'Fnlm6', ...
'Vnlm1', 'Vnlm2', 'Vnlm3', 'Vnlm4', 'Vnlm5', 'Vnlm6'};
#+end_src
We then create transfer functions corresponding to the active damping plants.
#+begin_src matlab
G_iff = minreal(G({'Fnlm1', 'Fnlm2', 'Fnlm3', 'Fnlm4', 'Fnlm5', 'Fnlm6'}, {'Fnl1', 'Fnl2', 'Fnl3', 'Fnl4', 'Fnl5', 'Fnl6'}));
G_dvf = minreal(G({'Dnlm1', 'Dnlm2', 'Dnlm3', 'Dnlm4', 'Dnlm5', 'Dnlm6'}, {'Fnl1', 'Fnl2', 'Fnl3', 'Fnl4', 'Fnl5', 'Fnl6'}));
G_ine = minreal(G({'Vnlm1', 'Vnlm2', 'Vnlm3', 'Vnlm4', 'Vnlm5', 'Vnlm6'}, {'Fnl1', 'Fnl2', 'Fnl3', 'Fnl4', 'Fnl5', 'Fnl6'}));
#+end_src
And we save them for further analysis.
#+begin_src matlab
save('./active_damping/mat/undamped_plants.mat', 'G_iff', 'G_dvf', 'G_ine');
#+end_src
*** Obtained Plants for Active Damping
#+begin_src matlab
load('./active_damping/mat/undamped_plants.mat', 'G_iff', 'G_dvf', 'G_ine');
#+end_src
#+begin_src matlab :exports none
freqs = logspace(0, 3, 1000);
figure;
ax1 = subplot(2, 1, 1);
hold on;
for i = 1:6
plot(freqs, abs(squeeze(freqresp(G_iff(['Fnlm', num2str(i)], ['Fnl', num2str(i)]), freqs, 'Hz'))));
end
hold off;
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
ylabel('Amplitude [N/N]'); set(gca, 'XTickLabel',[]);
ax2 = subplot(2, 1, 2);
hold on;
for i = 1:6
plot(freqs, 180/pi*angle(squeeze(freqresp(G_iff(['Fnlm', num2str(i)], ['Fnl', num2str(i)]), freqs, 'Hz'))));
end
hold off;
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'lin');
ylabel('Phase [deg]'); xlabel('Frequency [Hz]');
ylim([-180, 180]);
yticks([-180, -90, 0, 90, 180]);
linkaxes([ax1,ax2],'x');
#+end_src
#+HEADER: :tangle no :exports results :results none :noweb yes
#+begin_src matlab :var filepath="figs/nass_active_damping_iff_plant.pdf" :var figsize="full-tall" :post pdf2svg(file=*this*, ext="png")
<>
#+end_src
#+name: fig:nass_active_damping_iff_plant
#+caption: =G_iff=: Transfer functions from forces applied in the actuators to the force sensor in each actuator ([[./figs/nass_active_damping_iff_plant.png][png]], [[./figs/nass_active_damping_iff_plant.pdf][pdf]])
[[file:figs/nass_active_damping_iff_plant.png]]
#+begin_src matlab :exports none
freqs = logspace(0, 3, 1000);
figure;
ax1 = subplot(2, 1, 1);
hold on;
for i = 1:6
plot(freqs, abs(squeeze(freqresp(G_dvf(['Dnlm', num2str(i)], ['Fnl', num2str(i)]), freqs, 'Hz'))));
end
hold off;
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
ylabel('Amplitude [m/N]'); set(gca, 'XTickLabel',[]);
ax2 = subplot(2, 1, 2);
hold on;
for i = 1:6
plot(freqs, 180/pi*angle(squeeze(freqresp(G_dvf(['Dnlm', num2str(i)], ['Fnl', num2str(i)]), freqs, 'Hz'))));
end
hold off;
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'lin');
ylabel('Phase [deg]'); xlabel('Frequency [Hz]');
ylim([-180, 180]);
yticks([-180, -90, 0, 90, 180]);
linkaxes([ax1,ax2],'x');
#+end_src
#+HEADER: :tangle no :exports results :results none :noweb yes
#+begin_src matlab :var filepath="figs/nass_active_damping_dvf_plant.pdf" :var figsize="full-tall" :post pdf2svg(file=*this*, ext="png")
<>
#+end_src
#+name: fig:nass_active_damping_dvf_plant
#+caption: =G_dvf=: Transfer functions from forces applied in the actuators to the relative motion sensor in each actuator ([[./figs/nass_active_damping_dvf_plant.png][png]], [[./figs/nass_active_damping_dvf_plant.pdf][pdf]])
[[file:figs/nass_active_damping_dvf_plant.png]]
#+begin_src matlab :exports none
freqs = logspace(0, 3, 1000);
figure;
ax1 = subplot(2, 1, 1);
hold on;
for i = 1:6
plot(freqs, abs(squeeze(freqresp(G_ine(['Vnlm', num2str(i)], ['Fnl', num2str(i)]), freqs, 'Hz'))));
end
hold off;
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
ylabel('Amplitude [$\frac{m/s}{N}$]'); set(gca, 'XTickLabel',[]);
ax2 = subplot(2, 1, 2);
hold on;
for i = 1:6
plot(freqs, 180/pi*angle(squeeze(freqresp(G_ine(['Vnlm', num2str(i)], ['Fnl', num2str(i)]), freqs, 'Hz'))));
end
hold off;
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'lin');
ylabel('Phase [deg]'); xlabel('Frequency [Hz]');
ylim([-180, 180]);
yticks([-180, -90, 0, 90, 180]);
linkaxes([ax1,ax2],'x');
#+end_src
#+HEADER: :tangle no :exports results :results none :noweb yes
#+begin_src matlab :var filepath="figs/nass_active_damping_inertial_plant.pdf" :var figsize="full-tall" :post pdf2svg(file=*this*, ext="png")
<>
#+end_src
#+name: fig:nass_active_damping_inertial_plant
#+caption: =G_ine=: Transfer functions from forces applied in the actuators to the geophone located in each leg measuring the absolute velocity of the top part of the leg in the direction of the leg ([[./figs/nass_active_damping_inertial_plant.png][png]], [[./figs/nass_active_damping_inertial_plant.pdf][pdf]])
[[file:figs/nass_active_damping_inertial_plant.png]]
** Identification of the dynamics for High Authority Control
*** Identification
We initialize all the stages with the default parameters.
#+begin_src matlab
prepareLinearizeIdentification();
#+end_src
We identify the dynamics of the system using the =linearize= function.
#+begin_src matlab
%% Options for Linearized
options = linearizeOptions;
options.SampleTime = 0;
%% Name of the Simulink File
mdl = 'nass_model';
%% Input/Output definition
clear io; io_i = 1;
io(io_i) = linio([mdl, '/Controller'], 1, 'openinput'); io_i = io_i + 1; % Actuator Inputs
io(io_i) = linio([mdl, '/Tracking Error'], 1, 'openoutput', [], 'En'); io_i = io_i + 1; % Metrology Outputs
#+end_src
#+begin_src matlab
masses = [1, 10, 50]; % [kg]
#+end_src
#+begin_src matlab :exports none
G_cart = {zeros(length(masses))};
load('mat/stages.mat', 'nano_hexapod');
for i = 1:length(masses)
initializeSample('mass', masses(i));
%% Run the linearization
G = linearize(mdl, io, 0.3, options);
G.InputName = {'Fnl1', 'Fnl2', 'Fnl3', 'Fnl4', 'Fnl5', 'Fnl6'};
G.OutputName = {'Dnx', 'Dny', 'Dnz', 'Rnx', 'Rny', 'Rnz'};
G_cart_i = G*inv(nano_hexapod.J');
G_cart_i.InputName = {'Fnx', 'Fny', 'Fnz', 'Mnx', 'Mny', 'Mnz'};
G_cart(i) = {G_cart_i};
end
#+end_src
And we save them for further analysis.
#+begin_src matlab
save('./active_damping/mat/cart_plants.mat', 'G_cart', 'masses');
#+end_src
*** Obtained Plants
#+begin_src matlab
load('./active_damping/mat/cart_plants.mat', 'G_cart', 'masses');
#+end_src
#+begin_src matlab :exports none
freqs = logspace(0, 3, 1000);
figure;
ax1 = subplot(2, 1, 1);
hold on;
for i = 1:length(masses)
set(gca,'ColorOrderIndex',i);
p1 = plot(freqs, abs(squeeze(freqresp(G_cart{i}('Dnx', 'Fnx'), freqs, 'Hz'))));
set(gca,'ColorOrderIndex',i);
p2 = plot(freqs, abs(squeeze(freqresp(G_cart{i}('Dny', 'Fny'), freqs, 'Hz'))), '--');
set(gca,'ColorOrderIndex',i);
p3 = plot(freqs, abs(squeeze(freqresp(G_cart{i}('Dnz', 'Fnz'), freqs, 'Hz'))), ':');
end
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
ylabel('Amplitude [m/N]'); xlabel('Frequency [Hz]');
legend([p1,p2,p3], {'Fx/Dx', 'Fy/Dx', 'Fz/Dz'});
ax2 = subplot(2, 1, 2);
hold on;
for i = 1:length(masses)
set(gca,'ColorOrderIndex',i);
plot(freqs, 180/pi*unwrap(angle(squeeze(freqresp(G_cart{i}('Dnx', 'Fnx'), freqs, 'Hz')))), ...
'DisplayName', sprintf('$M = %.0f$ [kg]', masses(i)));
set(gca,'ColorOrderIndex',i);
plot(freqs, 180/pi*unwrap(angle(squeeze(freqresp(G_cart{i}('Dny', 'Fny'), freqs, 'Hz')))), '--', 'HandleVisibility', 'off');
set(gca,'ColorOrderIndex',i);
plot(freqs, 180/pi*unwrap(angle(squeeze(freqresp(G_cart{i}('Dnz', 'Fnz'), freqs, 'Hz')))), ':', 'HandleVisibility', 'off');
end
hold off;
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'lin');
ylabel('Phase [deg]'); xlabel('Frequency [Hz]');
yticks([-540:180:540]);
legend('location', 'northeast');
linkaxes([ax1,ax2],'x');
#+end_src
#+HEADER: :tangle no :exports results :results none :noweb yes
#+begin_src matlab :var filepath="figs/undamped_hac_plant_translations.pdf" :var figsize="full-tall" :post pdf2svg(file=*this*, ext="png")
<>
#+end_src
#+name: fig:undamped_hac_plant_translations
#+caption: Undamped Plant - Translations ([[./figs/undamped_hac_plant_translations.png][png]], [[./figs/undamped_hac_plant_translations.pdf][pdf]])
[[file:figs/undamped_hac_plant_translations.png]]
#+begin_src matlab :exports none
freqs = logspace(0, 3, 1000);
figure;
ax1 = subplot(2, 1, 1);
hold on;
for i = 1:length(masses)
set(gca,'ColorOrderIndex',i);
p1 = plot(freqs, abs(squeeze(freqresp(G_cart{i}('Rnx', 'Mnx'), freqs, 'Hz'))));
set(gca,'ColorOrderIndex',i);
p2 = plot(freqs, abs(squeeze(freqresp(G_cart{i}('Rny', 'Mny'), freqs, 'Hz'))), '--');
set(gca,'ColorOrderIndex',i);
p3 = plot(freqs, abs(squeeze(freqresp(G_cart{i}('Rnz', 'Mnz'), freqs, 'Hz'))), ':');
end
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
ylabel('Amplitude [m/N]'); xlabel('Frequency [Hz]');
legend([p1,p2,p3], {'Rx/Mx', 'Ry/Mx', 'Rz/Mz'});
ax2 = subplot(2, 1, 2);
hold on;
for i = 1:length(masses)
set(gca,'ColorOrderIndex',i);
plot(freqs, 180/pi*unwrap(angle(squeeze(freqresp(G_cart{i}('Rnx', 'Mnx'), freqs, 'Hz')))), ...
'DisplayName', sprintf('$M = %.0f$ [kg]', masses(i)));
set(gca,'ColorOrderIndex',i);
plot(freqs, 180/pi*unwrap(angle(squeeze(freqresp(G_cart{i}('Rny', 'Mny'), freqs, 'Hz')))), '--', 'HandleVisibility', 'off');
set(gca,'ColorOrderIndex',i);
plot(freqs, 180/pi*unwrap(angle(squeeze(freqresp(G_cart{i}('Rnz', 'Mnz'), freqs, 'Hz')))), ':', 'HandleVisibility', 'off');
end
hold off;
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'lin');
ylabel('Phase [deg]'); xlabel('Frequency [Hz]');
yticks([-540:180:540]);
legend('location', 'northeast');
linkaxes([ax1,ax2],'x');
#+end_src
#+HEADER: :tangle no :exports results :results none :noweb yes
#+begin_src matlab :var filepath="figs/undamped_hac_plant_rotations.pdf" :var figsize="full-tall" :post pdf2svg(file=*this*, ext="png")
<>
#+end_src
#+name: fig:undamped_hac_plant_rotations
#+caption: Undamped Plant - Rotations ([[./figs/undamped_hac_plant_rotations.png][png]], [[./figs/undamped_hac_plant_rotations.pdf][pdf]])
[[file:figs/undamped_hac_plant_rotations.png]]
** Tomography Experiment
*** Simulation
We initialize elements for the tomography experiment.
#+begin_src matlab
prepareTomographyExperiment();
#+end_src
We change the simulation stop time.
#+begin_src matlab
load('mat/conf_simulink.mat');
set_param(conf_simulink, 'StopTime', '4.5');
#+end_src
And we simulate the system.
#+begin_src matlab
sim('nass_model');
#+end_src
Finally, we save the simulation results for further analysis
#+begin_src matlab
save('./active_damping/mat/tomo_exp.mat', 'En', 'Eg', '-append');
#+end_src
*** Results
We load the results of tomography experiments.
#+begin_src matlab
load('./active_damping/mat/tomo_exp.mat', 'En');
Fs = 1e3; % Sampling Frequency of the Data
t = (1/Fs)*[0:length(En(:,1))-1];
#+end_src
#+begin_src matlab :exports none
figure;
ax1 = subplot(3, 1, 1);
hold on;
plot(t, En(:,1), 'DisplayName', '$\epsilon_{x}$')
legend('location', 'southwest');
ax2 = subplot(3, 1, 2);
hold on;
plot(t, En(:,2), 'DisplayName', '$\epsilon_{y}$')
legend('location', 'southwest');
ylabel('Position Error [m]');
ax3 = subplot(3, 1, 3);
hold on;
plot(t, En(:,3), 'DisplayName', '$\epsilon_{z}$')
legend('location', 'northwest');
xlabel('Time [s]');
linkaxes([ax1,ax2,ax3],'x');
xlim([0.5,inf]);
#+end_src
#+HEADER: :tangle no :exports results :results none :noweb yes
#+begin_src matlab :var filepath="figs/nass_act_damp_undamped_sim_tomo_trans.pdf" :var figsize="full-tall" :post pdf2svg(file=*this*, ext="png")
<>
#+end_src
#+name: fig:nass_act_damp_undamped_sim_tomo_trans
#+caption: Position Error during tomography experiment - Translations ([[./figs/nass_act_damp_undamped_sim_tomo_trans.png][png]], [[./figs/nass_act_damp_undamped_sim_tomo_trans.pdf][pdf]])
[[file:figs/nass_act_damp_undamped_sim_tomo_trans.png]]
#+begin_src matlab :exports none
figure;
ax1 = subplot(3, 1, 1);
hold on;
plot(t, En(:,4), 'DisplayName', '$\epsilon_{\theta_x}$')
legend('location', 'northwest');
ax2 = subplot(3, 1, 2);
hold on;
plot(t, En(:,5), 'DisplayName', '$\epsilon_{\theta_y}$')
legend('location', 'southwest');
ylabel('Position Error [rad]');
ax3 = subplot(3, 1, 3);
hold on;
plot(t, En(:,6), 'DisplayName', '$\epsilon_{\theta_z}$')
legend();
xlabel('Time [s]');
linkaxes([ax1,ax2,ax3],'x');
xlim([0.5,inf]);
#+end_src
#+HEADER: :tangle no :exports results :results none :noweb yes
#+begin_src matlab :var filepath="figs/nass_act_damp_undamped_sim_tomo_rot.pdf" :var figsize="full-tall" :post pdf2svg(file=*this*, ext="png")
<>
#+end_src
#+name: fig:nass_act_damp_undamped_sim_tomo_rot
#+caption: Position Error during tomography experiment - Rotations ([[./figs/nass_act_damp_undamped_sim_tomo_rot.png][png]], [[./figs/nass_act_damp_undamped_sim_tomo_rot.pdf][pdf]])
[[file:figs/nass_act_damp_undamped_sim_tomo_rot.png]]
* Variability of the system dynamics for Active Damping
:PROPERTIES:
:header-args:matlab+: :tangle matlab/act_damp_variability_plant.m
:header-args:matlab+: :comments org :mkdirp yes
:END:
<>
** Introduction :ignore:
The goal of this section is to study how the dynamics of the Active Damping plants are changing with the experimental conditions.
These experimental conditions are:
- The mass of the sample (section [[sec:variability_sample_mass]])
- The spindle angle with a null rotating speed (section [[sec:variability_spindle_angle]])
- The spindle rotation speed (section [[sec:variability_rotation_speed]])
- The tilt angle (section [[sec:variability_tilt_angle]])
- The scans of the translation stage (section [[sec:variability_ty_scans]])
For the identification of the dynamics, the system is simulation for $\approx 0.5s$ before the linearization is performed.
This is done in order for the transient phase to be over.
** Matlab Init :noexport:ignore:
#+begin_src matlab :tangle no :exports none :results silent :noweb yes :var current_dir=(file-name-directory buffer-file-name)
<>
#+end_src
#+begin_src matlab :exports none :results silent :noweb yes
<>
#+end_src
#+begin_src matlab :tangle no
simulinkproject('../');
addpath('active_damping/src/');
#+end_src
#+begin_src matlab
open('nass_model.slx')
load('mat/conf_simulink.mat');
#+end_src
** Variation of the Sample Mass
<>
*** Introduction :ignore:
For all the identifications, the disturbances are disabled and no controller are used.
*** Identification :ignore:
We initialize all the stages with the default parameters.
#+begin_src matlab
prepareLinearizeIdentification();
#+end_src
#+begin_src matlab :exports none
%% Options for Linearized
options = linearizeOptions;
options.SampleTime = 0;
%% Name of the Simulink File
mdl = 'nass_model';
%% Input/Output definition
clear io; io_i = 1;
io(io_i) = linio([mdl, '/Controller'], 1, 'openinput'); io_i = io_i + 1; % Actuator Inputs
io(io_i) = linio([mdl, '/Micro-Station'], 3, 'openoutput', [], 'Dnlm'); io_i = io_i + 1;
io(io_i) = linio([mdl, '/Micro-Station'], 3, 'openoutput', [], 'Fnlm'); io_i = io_i + 1;
io(io_i) = linio([mdl, '/Micro-Station'], 3, 'openoutput', [], 'Vlm'); io_i = io_i + 1;
#+end_src
We identify the dynamics for the following sample mass.
#+begin_src matlab
masses = [1, 10, 50]; % [kg]
#+end_src
#+begin_src matlab :exports none
Gm = {zeros(length(masses))};
Gm_iff = {zeros(length(masses))};
Gm_dvf = {zeros(length(masses))};
Gm_ine = {zeros(length(masses))};
for i = 1:length(masses)
initializeSample('mass', masses(i));
%% Run the linearization
G = linearize(mdl, io, 0.3, options);
G.InputName = {'Fnl1', 'Fnl2', 'Fnl3', 'Fnl4', 'Fnl5', 'Fnl6'};
G.OutputName = {'Dnlm1', 'Dnlm2', 'Dnlm3', 'Dnlm4', 'Dnlm5', 'Dnlm6', ...
'Fnlm1', 'Fnlm2', 'Fnlm3', 'Fnlm4', 'Fnlm5', 'Fnlm6', ...
'Vnlm1', 'Vnlm2', 'Vnlm3', 'Vnlm4', 'Vnlm5', 'Vnlm6'};
Gm(i) = {G};
Gm_iff(i) = {minreal(G({'Fnlm1', 'Fnlm2', 'Fnlm3', 'Fnlm4', 'Fnlm5', 'Fnlm6'}, {'Fnl1', 'Fnl2', 'Fnl3', 'Fnl4', 'Fnl5', 'Fnl6'}))};
Gm_dvf(i) = {minreal(G({'Dnlm1', 'Dnlm2', 'Dnlm3', 'Dnlm4', 'Dnlm5', 'Dnlm6'}, {'Fnl1', 'Fnl2', 'Fnl3', 'Fnl4', 'Fnl5', 'Fnl6'}))};
Gm_ine(i) = {minreal(G({'Vnlm1', 'Vnlm2', 'Vnlm3', 'Vnlm4', 'Vnlm5', 'Vnlm6'}, {'Fnl1', 'Fnl2', 'Fnl3', 'Fnl4', 'Fnl5', 'Fnl6'}))};
end
#+end_src
#+begin_src matlab :exports none
save('./active_damping/mat/plants_variable.mat', 'masses', 'Gm_iff', 'Gm_dvf', 'Gm_ine', '-append');
#+end_src
*** Plots :ignore:
#+begin_src matlab :exports none
load('./active_damping/mat/plants_variable.mat', 'masses', 'Gm_iff', 'Gm_dvf', 'Gm_ine');
#+end_src
#+begin_src matlab :exports none
freqs = logspace(0, 3, 1000);
figure;
ax1 = subplot(2, 1, 1);
hold on;
for i = 1:length(Gm_iff)
plot(freqs, abs(squeeze(freqresp(Gm_iff{i}('Fnlm1', 'Fnl1'), freqs, 'Hz'))));
end
hold off;
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
ylabel('Amplitude [N/N]'); set(gca, 'XTickLabel',[]);
ax2 = subplot(2, 1, 2);
hold on;
for i = 1:length(Gm_iff)
plot(freqs, 180/pi*angle(squeeze(freqresp(Gm_iff{i}('Fnlm1', 'Fnl1'), freqs, 'Hz'))), ...
'DisplayName', sprintf('$M = %.0f$ [kg]', masses(i)));
end
hold off;
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'lin');
ylabel('Phase [deg]'); xlabel('Frequency [Hz]');
ylim([-180, 180]);
yticks([-180, -90, 0, 90, 180]);
legend('location', 'southwest');
linkaxes([ax1,ax2],'x');
xlim([freqs(1), freqs(end)]);
#+end_src
#+HEADER: :tangle no :exports results :results none :noweb yes
#+begin_src matlab :var filepath="figs/act_damp_variability_iff_sample_mass.pdf" :var figsize="full-tall" :post pdf2svg(file=*this*, ext="png")
<>
#+end_src
#+name: fig:act_damp_variability_iff_sample_mass
#+caption: Variability of the dynamics from actuator force to force sensor with the Sample Mass ([[./figs/act_damp_variability_iff_sample_mass.png][png]], [[./figs/act_damp_variability_iff_sample_mass.pdf][pdf]])
[[file:figs/act_damp_variability_iff_sample_mass.png]]
#+begin_src matlab :exports none
freqs = logspace(0, 3, 1000);
figure;
ax1 = subplot(2, 1, 1);
hold on;
for i = 1:length(Gm_dvf)
plot(freqs, abs(squeeze(freqresp(Gm_dvf{i}('Dnlm1', 'Fnl1'), freqs, 'Hz'))));
end
hold off;
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
ylabel('Amplitude [m/N]'); set(gca, 'XTickLabel',[]);
ax2 = subplot(2, 1, 2);
hold on;
for i = 1:length(Gm_dvf)
plot(freqs, 180/pi*angle(squeeze(freqresp(Gm_dvf{i}('Dnlm1', 'Fnl1'), freqs, 'Hz'))), 'DisplayName', sprintf('$M = %.0f$ [kg]', masses(i)));
end
hold off;
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'lin');
ylabel('Phase [deg]'); xlabel('Frequency [Hz]');
ylim([-180, 180]);
yticks([-180, -90, 0, 90, 180]);
legend('location', 'southwest');
linkaxes([ax1,ax2],'x');
xlim([freqs(1), freqs(end)]);
#+end_src
#+HEADER: :tangle no :exports results :results none :noweb yes
#+begin_src matlab :var filepath="figs/act_damp_variability_dvf_sample_mass.pdf" :var figsize="full-tall" :post pdf2svg(file=*this*, ext="png")
<>
#+end_src
#+name: fig:act_damp_variability_dvf_sample_mass
#+caption: Variability of the dynamics from actuator force to relative motion sensor with the Sample Mass ([[./figs/act_damp_variability_dvf_sample_mass.png][png]], [[./figs/act_damp_variability_dvf_sample_mass.pdf][pdf]])
[[file:figs/act_damp_variability_dvf_sample_mass.png]]
#+begin_src matlab :exports none
freqs = logspace(0, 3, 1000);
figure;
ax1 = subplot(2, 1, 1);
hold on;
for i = 1:length(Gm_ine)
plot(freqs, abs(squeeze(freqresp(Gm_ine{i}('Vnlm1', 'Fnl1'), freqs, 'Hz'))));
end
hold off;
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
ylabel('Amplitude [$\frac{m/s}{N}$]'); set(gca, 'XTickLabel',[]);
ax2 = subplot(2, 1, 2);
hold on;
for i = 1:length(Gm_ine)
plot(freqs, 180/pi*angle(squeeze(freqresp(Gm_ine{i}('Vnlm1', 'Fnl1'), freqs, 'Hz'))), 'DisplayName', sprintf('$M = %.0f$ [kg]', masses(i)));
end
hold off;
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'lin');
ylabel('Phase [deg]'); xlabel('Frequency [Hz]');
ylim([-180, 180]);
yticks([-180, -90, 0, 90, 180]);
legend('location', 'southwest');
linkaxes([ax1,ax2],'x');
xlim([freqs(1), freqs(end)]);
#+end_src
#+HEADER: :tangle no :exports results :results none :noweb yes
#+begin_src matlab :var filepath="figs/act_damp_variability_ine_sample_mass.pdf" :var figsize="full-tall" :post pdf2svg(file=*this*, ext="png")
<>
#+end_src
#+name: fig:act_damp_variability_ine_sample_mass
#+caption: Variability of the dynamics from actuator force to absolute velocity with the Sample Mass ([[./figs/act_damp_variability_ine_sample_mass.png][png]], [[./figs/act_damp_variability_ine_sample_mass.pdf][pdf]])
[[file:figs/act_damp_variability_ine_sample_mass.png]]
** Variation of the Spindle Angle
<>
*** Introduction :ignore:
*** Identification :ignore:
We initialize all the stages with the default parameters.
#+begin_src matlab
prepareLinearizeIdentification();
#+end_src
#+begin_src matlab :exports none
%% Options for Linearized
options = linearizeOptions;
options.SampleTime = 0;
%% Name of the Simulink File
mdl = 'nass_model';
%% Input/Output definition
clear io; io_i = 1;
io(io_i) = linio([mdl, '/Controller'], 1, 'openinput'); io_i = io_i + 1; % Actuator Inputs
io(io_i) = linio([mdl, '/Micro-Station'], 3, 'openoutput', [], 'Dnlm'); io_i = io_i + 1;
io(io_i) = linio([mdl, '/Micro-Station'], 3, 'openoutput', [], 'Fnlm'); io_i = io_i + 1;
io(io_i) = linio([mdl, '/Micro-Station'], 3, 'openoutput', [], 'Vlm'); io_i = io_i + 1;
#+end_src
We identify the dynamics for the following Spindle angles.
#+begin_src matlab
Rz_amplitudes = [0, pi/4, pi/2, pi]; % [rad]
#+end_src
#+begin_src matlab :exports none
Ga = {zeros(length(Rz_amplitudes))};
Ga_iff = {zeros(length(Rz_amplitudes))};
Ga_dvf = {zeros(length(Rz_amplitudes))};
Ga_ine = {zeros(length(Rz_amplitudes))};
for i = 1:length(Rz_amplitudes)
initializeReferences('Rz_type', 'constant', 'Rz_amplitude', Rz_amplitudes(i))
%% Run the linearization
G = linearize(mdl, io, 0.3, options);
G.InputName = {'Fnl1', 'Fnl2', 'Fnl3', 'Fnl4', 'Fnl5', 'Fnl6'};
G.OutputName = {'Dnlm1', 'Dnlm2', 'Dnlm3', 'Dnlm4', 'Dnlm5', 'Dnlm6', ...
'Fnlm1', 'Fnlm2', 'Fnlm3', 'Fnlm4', 'Fnlm5', 'Fnlm6', ...
'Vnlm1', 'Vnlm2', 'Vnlm3', 'Vnlm4', 'Vnlm5', 'Vnlm6'};
Ga(i) = {G};
Ga_iff(i) = {minreal(G({'Fnlm1', 'Fnlm2', 'Fnlm3', 'Fnlm4', 'Fnlm5', 'Fnlm6'}, {'Fnl1', 'Fnl2', 'Fnl3', 'Fnl4', 'Fnl5', 'Fnl6'}))};
Ga_dvf(i) = {minreal(G({'Dnlm1', 'Dnlm2', 'Dnlm3', 'Dnlm4', 'Dnlm5', 'Dnlm6'}, {'Fnl1', 'Fnl2', 'Fnl3', 'Fnl4', 'Fnl5', 'Fnl6'}))};
Ga_ine(i) = {minreal(G({'Vnlm1', 'Vnlm2', 'Vnlm3', 'Vnlm4', 'Vnlm5', 'Vnlm6'}, {'Fnl1', 'Fnl2', 'Fnl3', 'Fnl4', 'Fnl5', 'Fnl6'}))};
end
#+end_src
#+begin_src matlab :exports none
save('./active_damping/mat/plants_variable.mat', 'Rz_amplitudes', 'Ga_iff', 'Ga_dvf', 'Ga_ine', '-append');
#+end_src
*** Plots :ignore:
#+begin_src matlab :exports none
load('./active_damping/mat/plants_variable.mat', 'Rz_amplitudes', 'Ga_iff', 'Ga_dvf', 'Ga_ine');
#+end_src
#+begin_src matlab :exports none
freqs = logspace(0, 3, 1000);
figure;
ax1 = subplot(2, 1, 1);
hold on;
for i = 1:length(Ga_iff)
plot(freqs, abs(squeeze(freqresp(Ga_iff{i}('Fnlm1', 'Fnl1'), freqs, 'Hz'))));
end
hold off;
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
ylabel('Amplitude [N/N]'); set(gca, 'XTickLabel',[]);
ax2 = subplot(2, 1, 2);
hold on;
for i = 1:length(Ga_iff)
plot(freqs, 180/pi*angle(squeeze(freqresp(Ga_iff{i}('Fnlm1', 'Fnl1'), freqs, 'Hz'))), 'DisplayName', sprintf('$Rz = %.0f$ [deg]', Rz_amplitudes(i)*180/pi));
end
hold off;
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'lin');
ylabel('Phase [deg]'); xlabel('Frequency [Hz]');
ylim([-180, 180]);
yticks([-180, -90, 0, 90, 180]);
legend('location', 'southwest');
linkaxes([ax1,ax2],'x');
xlim([freqs(1), freqs(end)]);
#+end_src
#+HEADER: :tangle no :exports results :results none :noweb yes
#+begin_src matlab :var filepath="figs/act_damp_variability_iff_spindle_angle.pdf" :var figsize="full-tall" :post pdf2svg(file=*this*, ext="png")
<>
#+end_src
#+name: fig:act_damp_variability_iff_spindle_angle
#+caption: Variability of the dynamics from the actuator force to the force sensor with the Spindle Angle ([[./figs/act_damp_variability_iff_spindle_angle.png][png]], [[./figs/act_damp_variability_iff_spindle_angle.pdf][pdf]])
[[file:figs/act_damp_variability_iff_spindle_angle.png]]
#+begin_src matlab :exports none
freqs = logspace(0, 3, 1000);
figure;
ax1 = subplot(2, 1, 1);
hold on;
for i = 1:length(Ga_dvf)
plot(freqs, abs(squeeze(freqresp(Ga_dvf{i}('Dnlm1', 'Fnl1'), freqs, 'Hz'))));
end
hold off;
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
ylabel('Amplitude [m/N]'); set(gca, 'XTickLabel',[]);
ax2 = subplot(2, 1, 2);
hold on;
for i = 1:length(Ga_dvf)
plot(freqs, 180/pi*angle(squeeze(freqresp(Ga_dvf{i}('Dnlm1', 'Fnl1'), freqs, 'Hz'))), 'DisplayName', sprintf('$Rz = %.0f$ [deg]', Rz_amplitudes(i)*180/pi));
end
hold off;
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'lin');
ylabel('Phase [deg]'); xlabel('Frequency [Hz]');
ylim([-180, 180]);
yticks([-180, -90, 0, 90, 180]);
legend('location', 'southwest');
linkaxes([ax1,ax2],'x');
xlim([freqs(1), freqs(end)]);
#+end_src
#+HEADER: :tangle no :exports results :results none :noweb yes
#+begin_src matlab :var filepath="figs/act_damp_variability_dvf_spindle_angle.pdf" :var figsize="full-tall" :post pdf2svg(file=*this*, ext="png")
<>
#+end_src
#+name: fig:act_damp_variability_dvf_spindle_angle
#+caption: Variability of the dynamics from actuator force to relative motion sensor with the Spindle Angle ([[./figs/act_damp_variability_dvf_spindle_angle.png][png]], [[./figs/act_damp_variability_dvf_spindle_angle.pdf][pdf]])
[[file:figs/act_damp_variability_dvf_spindle_angle.png]]
#+begin_src matlab :exports none
freqs = logspace(0, 3, 1000);
figure;
ax1 = subplot(2, 1, 1);
hold on;
for i = 1:length(Ga_ine)
plot(freqs, abs(squeeze(freqresp(Ga_ine{i}('Vnlm1', 'Fnl1'), freqs, 'Hz'))));
end
hold off;
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
ylabel('Amplitude [$\frac{m/s}{N}$]'); set(gca, 'XTickLabel',[]);
ax2 = subplot(2, 1, 2);
hold on;
for i = 1:length(Ga_ine)
plot(freqs, 180/pi*angle(squeeze(freqresp(Ga_ine{i}('Vnlm1', 'Fnl1'), freqs, 'Hz'))), 'DisplayName', sprintf('$Rz = %.0f$ [deg]', Rz_amplitudes(i)*180/pi));
end
hold off;
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'lin');
ylabel('Phase [deg]'); xlabel('Frequency [Hz]');
ylim([-180, 180]);
yticks([-180, -90, 0, 90, 180]);
legend('location', 'southwest');
linkaxes([ax1,ax2],'x');
xlim([freqs(1), freqs(end)]);
#+end_src
#+HEADER: :tangle no :exports results :results none :noweb yes
#+begin_src matlab :var filepath="figs/act_damp_variability_ine_spindle_angle.pdf" :var figsize="full-tall" :post pdf2svg(file=*this*, ext="png")
<>
#+end_src
#+name: fig:act_damp_variability_ine_spindle_angle
#+caption: Variability of the dynamics from actuator force to absolute velocity with the Spindle Angle ([[./figs/act_damp_variability_ine_spindle_angle.png][png]], [[./figs/act_damp_variability_ine_spindle_angle.pdf][pdf]])
[[file:figs/act_damp_variability_ine_spindle_angle.png]]
** Variation of the Spindle Rotation Speed
<>
*** Introduction :ignore:
*** Identification :ignore:
We initialize all the stages with the default parameters.
#+begin_src matlab
prepareLinearizeIdentification();
#+end_src
#+begin_src matlab :exports none
%% Options for Linearized
options = linearizeOptions;
options.SampleTime = 0;
%% Name of the Simulink File
mdl = 'nass_model';
%% Input/Output definition
clear io; io_i = 1;
io(io_i) = linio([mdl, '/Controller'], 1, 'openinput'); io_i = io_i + 1; % Actuator Inputs
io(io_i) = linio([mdl, '/Micro-Station'], 3, 'openoutput', [], 'Dnlm'); io_i = io_i + 1;
io(io_i) = linio([mdl, '/Micro-Station'], 3, 'openoutput', [], 'Fnlm'); io_i = io_i + 1;
io(io_i) = linio([mdl, '/Micro-Station'], 3, 'openoutput', [], 'Vlm'); io_i = io_i + 1;
#+end_src
We identify the dynamics for the following Spindle rotation periods.
#+begin_src matlab
Rz_periods = [60, 6, 2, 1]; % [s]
#+end_src
The identification of the dynamics is done at the same Spindle angle position.
#+begin_src matlab :exports none
Gw = {zeros(length(Rz_periods))};
Gw_iff = {zeros(length(Rz_periods))};
Gw_dvf = {zeros(length(Rz_periods))};
Gw_ine = {zeros(length(Rz_periods))};
for i = 1:length(Rz_periods)
initializeReferences('Rz_type', 'rotating', ...
'Rz_period', Rz_periods(i), ... % Rotation period [s]
'Rz_amplitude', -0.5*(2*pi/Rz_periods(i))); % Angle offset [rad]
load('mat/nass_references.mat', 'Rz'); % We load the reference for the Spindle
[~, i_end] = min(abs(Rz.signals.values)); % Obtain the indice where the spindle angle is zero
t_sim = Rz.time(i_end) % Simulation time before identification [s]
%% Run the linearization
G = linearize(mdl, io, t_sim, options);
G.InputName = {'Fnl1', 'Fnl2', 'Fnl3', 'Fnl4', 'Fnl5', 'Fnl6'};
G.OutputName = {'Dnlm1', 'Dnlm2', 'Dnlm3', 'Dnlm4', 'Dnlm5', 'Dnlm6', ...
'Fnlm1', 'Fnlm2', 'Fnlm3', 'Fnlm4', 'Fnlm5', 'Fnlm6', ...
'Vnlm1', 'Vnlm2', 'Vnlm3', 'Vnlm4', 'Vnlm5', 'Vnlm6'};
Gw(i) = {G};
Gw_iff(i) = {minreal(G({'Fnlm1', 'Fnlm2', 'Fnlm3', 'Fnlm4', 'Fnlm5', 'Fnlm6'}, {'Fnl1', 'Fnl2', 'Fnl3', 'Fnl4', 'Fnl5', 'Fnl6'}))};
Gw_dvf(i) = {minreal(G({'Dnlm1', 'Dnlm2', 'Dnlm3', 'Dnlm4', 'Dnlm5', 'Dnlm6'}, {'Fnl1', 'Fnl2', 'Fnl3', 'Fnl4', 'Fnl5', 'Fnl6'}))};
Gw_ine(i) = {minreal(G({'Vnlm1', 'Vnlm2', 'Vnlm3', 'Vnlm4', 'Vnlm5', 'Vnlm6'}, {'Fnl1', 'Fnl2', 'Fnl3', 'Fnl4', 'Fnl5', 'Fnl6'}))};
end
#+end_src
#+begin_src matlab :exports none
save('./active_damping/mat/plants_variable.mat', 'Rz_periods', 'Gw_iff', 'Gw_dvf', 'Gw_ine', '-append');
#+end_src
*** Dynamics of the Active Damping plants
#+begin_src matlab :exports none
load('./active_damping/mat/plants_variable.mat', 'Rz_periods', 'Gw_iff', 'Gw_dvf', 'Gw_ine');
load('./active_damping/mat/undamped_plants.mat', 'G_iff', 'G_dvf', 'G_ine');
#+end_src
#+begin_src matlab :exports none
freqs = logspace(0, 3, 10000);
figure;
ax1 = subplot(2, 1, 1);
hold on;
for i = 1:length(Gw_iff)
plot(freqs, abs(squeeze(freqresp(Gw_iff{i}('Fnlm1', 'Fnl1'), freqs, 'Hz'))));
end
plot(freqs, abs(squeeze(freqresp(G_iff('Fnlm1', 'Fnl1'), freqs, 'Hz'))), 'k--');
hold off;
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
ylabel('Amplitude [N/N]'); set(gca, 'XTickLabel',[]);
ax2 = subplot(2, 1, 2);
hold on;
for i = 1:length(Gw_iff)
plot(freqs, 180/pi*angle(squeeze(freqresp(Gw_iff{i}('Fnlm1', 'Fnl1'), freqs, 'Hz'))), 'DisplayName', sprintf('$Rz = %.0f$ [rpm]', 60/Rz_periods(i)));
end
plot(freqs, 180/pi*angle(squeeze(freqresp(G_iff('Fnlm1', 'Fnl1'), freqs, 'Hz'))), 'k--', 'DisplayName', 'No Rotation');
hold off;
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'lin');
ylabel('Phase [deg]'); xlabel('Frequency [Hz]');
ylim([-180, 180]);
yticks([-180, -90, 0, 90, 180]);
legend('location', 'southwest');
linkaxes([ax1,ax2],'x');
xlim([freqs(1), freqs(end)]);
#+end_src
#+HEADER: :tangle no :exports results :results none :noweb yes
#+begin_src matlab :var filepath="figs/act_damp_variability_iff_spindle_speed.pdf" :var figsize="full-tall" :post pdf2svg(file=*this*, ext="png")
<>
#+end_src
#+name: fig:act_damp_variability_iff_spindle_speed
#+caption: Variability of the dynamics from the actuator force to the force sensor with the Spindle rotation speed ([[./figs/act_damp_variability_iff_spindle_speed.png][png]], [[./figs/act_damp_variability_iff_spindle_speed.pdf][pdf]])
[[file:figs/act_damp_variability_iff_spindle_speed.png]]
#+begin_src matlab :exports none
xlim([20, 30]);
#+end_src
#+HEADER: :tangle no :exports results :results none :noweb yes
#+begin_src matlab :var filepath="figs/act_damp_variability_iff_spindle_speed_zoom.pdf" :var figsize="wide-normal" :post pdf2svg(file=*this*, ext="png")
<>
#+end_src
#+name: fig:act_damp_variability_iff_spindle_speed_zoom
#+caption: Variability of the dynamics from the actuator force to the force sensor with the Spindle rotation speed ([[./figs/act_damp_variability_iff_spindle_speed_zoom.png][png]], [[./figs/act_damp_variability_iff_spindle_speed_zoom.pdf][pdf]])
[[file:figs/act_damp_variability_iff_spindle_speed_zoom.png]]
#+begin_src matlab :exports none
freqs = logspace(0, 3, 5000);
figure;
ax1 = subplot(2, 1, 1);
hold on;
for i = 1:length(Gw_dvf)
plot(freqs, abs(squeeze(freqresp(Gw_dvf{i}('Dnlm1', 'Fnl1'), freqs, 'Hz'))));
end
plot(freqs, abs(squeeze(freqresp(G_dvf('Dnlm1', 'Fnl1'), freqs, 'Hz'))), 'k--');
hold off;
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
ylabel('Amplitude [m/N]'); set(gca, 'XTickLabel',[]);
ax2 = subplot(2, 1, 2);
hold on;
for i = 1:length(Gw_dvf)
plot(freqs, 180/pi*angle(squeeze(freqresp(Gw_dvf{i}('Dnlm1', 'Fnl1'), freqs, 'Hz'))), 'DisplayName', sprintf('$Rz = %.0f$ [rpm]', 60/Rz_periods(i)));
end
plot(freqs, 180/pi*angle(squeeze(freqresp(G_dvf('Dnlm1', 'Fnl1'), freqs, 'Hz'))), 'k--', 'DisplayName', 'No Rotation');
hold off;
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'lin');
ylabel('Phase [deg]'); xlabel('Frequency [Hz]');
ylim([-180, 180]);
yticks([-180, -90, 0, 90, 180]);
legend('location', 'southwest');
linkaxes([ax1,ax2],'x');
xlim([freqs(1), freqs(end)]);
#+end_src
#+HEADER: :tangle no :exports results :results none :noweb yes
#+begin_src matlab :var filepath="figs/act_damp_variability_dvf_spindle_speed.pdf" :var figsize="full-tall" :post pdf2svg(file=*this*, ext="png")
<>
#+end_src
#+name: fig:act_damp_variability_dvf_spindle_speed
#+caption: Variability of the dynamics from the actuator force to the relative motion sensor with the Spindle rotation speed ([[./figs/act_damp_variability_dvf_spindle_speed.png][png]], [[./figs/act_damp_variability_dvf_spindle_speed.pdf][pdf]])
[[file:figs/act_damp_variability_dvf_spindle_speed.png]]
#+begin_src matlab :exports none
xlim([20, 30]);
#+end_src
#+HEADER: :tangle no :exports results :results none :noweb yes
#+begin_src matlab :var filepath="figs/act_damp_variability_dvf_spindle_speed_zoom.pdf" :var figsize="wide-normal" :post pdf2svg(file=*this*, ext="png")
<>
#+end_src
#+name: fig:act_damp_variability_dvf_spindle_speed_zoom
#+caption: Variability of the dynamics from the actuator force to the relative motion sensor with the Spindle rotation speed ([[./figs/act_damp_variability_dvf_spindle_speed_zoom.png][png]], [[./figs/act_damp_variability_dvf_spindle_speed_zoom.pdf][pdf]])
[[file:figs/act_damp_variability_dvf_spindle_speed_zoom.png]]
#+begin_src matlab :exports none
freqs = logspace(0, 3, 5000);
figure;
ax1 = subplot(2, 1, 1);
hold on;
for i = 1:length(Gw_ine)
plot(freqs, abs(squeeze(freqresp(Gw_ine{i}('Vnlm1', 'Fnl1'), freqs, 'Hz'))));
end
plot(freqs, abs(squeeze(freqresp(G_ine('Vnlm1', 'Fnl1'), freqs, 'Hz'))), 'k--');
hold off;
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
ylabel('Amplitude [$\frac{m/s}{N}$]'); set(gca, 'XTickLabel',[]);
ax2 = subplot(2, 1, 2);
hold on;
for i = 1:length(Gw_ine)
plot(freqs, 180/pi*angle(squeeze(freqresp(Gw_ine{i}('Vnlm1', 'Fnl1'), freqs, 'Hz'))), 'DisplayName', sprintf('$Rz = %.0f$ [rpm]', 60/Rz_periods(i)));
end
plot(freqs, 180/pi*angle(squeeze(freqresp(G_ine('Vnlm1', 'Fnl1'), freqs, 'Hz'))), 'k--', 'DisplayName', 'No Rotation');
hold off;
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'lin');
ylabel('Phase [deg]'); xlabel('Frequency [Hz]');
ylim([-180, 180]);
yticks([-180, -90, 0, 90, 180]);
legend('location', 'southwest');
linkaxes([ax1,ax2],'x');
xlim([freqs(1), freqs(end)]);
#+end_src
#+HEADER: :tangle no :exports results :results none :noweb yes
#+begin_src matlab :var filepath="figs/act_damp_variability_ine_spindle_speed.pdf" :var figsize="full-tall" :post pdf2svg(file=*this*, ext="png")
<>
#+end_src
#+name: fig:act_damp_variability_ine_spindle_speed
#+caption: Variability of the dynamics from the actuator force to the absolute velocity sensor with the Spindle rotation speed ([[./figs/act_damp_variability_ine_spindle_speed.png][png]], [[./figs/act_damp_variability_ine_spindle_speed.pdf][pdf]])
[[file:figs/act_damp_variability_ine_spindle_speed.png]]
#+begin_src matlab :exports none
xlim([20, 30]);
#+end_src
#+HEADER: :tangle no :exports results :results none :noweb yes
#+begin_src matlab :var filepath="figs/act_damp_variability_ine_spindle_speed_zoom.pdf" :var figsize="wide-normal" :post pdf2svg(file=*this*, ext="png")
<>
#+end_src
#+name: fig:act_damp_variability_ine_spindle_speed_zoom
#+caption: Variability of the dynamics from the actuator force to the absolute velocity sensor with the Spindle rotation speed ([[./figs/act_damp_variability_ine_spindle_speed_zoom.png][png]], [[./figs/act_damp_variability_ine_spindle_speed_zoom.pdf][pdf]])
[[file:figs/act_damp_variability_ine_spindle_speed_zoom.png]]
*** Variation of the poles and zeros with the Spindle rotation frequency
#+begin_src matlab :exports none
load('./active_damping/mat/plants_variable.mat', 'Rz_periods', 'Gw_iff', 'Gw_dvf', 'Gw_ine');
load('./active_damping/mat/undamped_plants.mat', 'G_iff', 'G_dvf', 'G_ine');
#+end_src
#+begin_src matlab :exports none
figure;
subplot(1,2,1);
hold on;
for i = 1:length(Gw_iff)
G_poles = pole(Gw_iff{i}('Fnlm1', 'Fnl1'));
plot(1/Rz_periods(i), real(G_poles(imag(G_poles)<2*pi*30 & imag(G_poles)>2*pi*22)), 'kx');
end
G_poles = pole(G_iff('Fnlm1', 'Fnl1'));
plot(0, real(G_poles(imag(G_poles)<2*pi*30 & imag(G_poles)>2*pi*22)), 'kx');
hold off;
ylim([-inf, 0]);
xlabel('Rotation Speed [Hz]');
ylabel('Real Part');
subplot(1,2,2);
hold on;
for i = 1:length(Gw_iff)
G_poles = pole(Gw_iff{i}('Fnlm1', 'Fnl1'));
plot(1/Rz_periods(i), imag(G_poles(imag(G_poles)<2*pi*30 & imag(G_poles)>2*pi*22)), 'kx');
end
G_poles = pole(G_iff('Fnlm1', 'Fnl1'));
plot(0, imag(G_poles(imag(G_poles)<2*pi*30 & imag(G_poles)>2*pi*22)), 'kx');
hold off;
ylim([0, inf]);
xlabel('Rotation Speed [Hz]');
ylabel('Imaginary Part');
#+end_src
#+HEADER: :tangle no :exports results :results none :noweb yes
#+begin_src matlab :var filepath="figs/campbell_diagram_spindle_rotation.pdf" :var figsize="full-normal" :post pdf2svg(file=*this*, ext="png")
<>
#+end_src
#+name: fig:campbell_diagram_spindle_rotation
#+caption: Evolution of the pole with respect to the spindle rotation speed ([[./figs/campbell_diagram_spindle_rotation.png][png]], [[./figs/campbell_diagram_spindle_rotation.pdf][pdf]])
[[file:figs/campbell_diagram_spindle_rotation.png]]
#+begin_src matlab :exports none
figure;
subplot(1,2,1);
hold on;
for i = 1:length(Gw_ine)
set(gca,'ColorOrderIndex',1);
G_zeros = zero(Gw_ine{i}('Vnlm1', 'Fnl1'));
plot(1/Rz_periods(i), real(G_zeros(imag(G_zeros)<2*pi*25 & imag(G_zeros)>2*pi*22)), 'o');
set(gca,'ColorOrderIndex',2);
G_zeros = zero(Gw_iff{i}('Fnlm1', 'Fnl1'));
plot(1/Rz_periods(i), real(G_zeros(imag(G_zeros)<2*pi*25 & imag(G_zeros)>2*pi*22)), 'o');
set(gca,'ColorOrderIndex',3);
G_zeros = zero(Gw_dvf{i}('Dnlm1', 'Fnl1'));
plot(1/Rz_periods(i), real(G_zeros(imag(G_zeros)<2*pi*25 & imag(G_zeros)>2*pi*22)), 'o');
end
hold off;
xlabel('Rotation Speed [Hz]');
ylabel('Real Part');
subplot(1,2,2);
hold on;
for i = 1:length(Gw_ine)
set(gca,'ColorOrderIndex',1);
G_zeros = zero(Gw_ine{i}('Vnlm1', 'Fnl1'));
p_ine = plot(1/Rz_periods(i), imag(G_zeros(imag(G_zeros)<2*pi*25 & imag(G_zeros)>2*pi*22)), 'o');
set(gca,'ColorOrderIndex',2);
G_zeros = zero(Gw_iff{i}('Fnlm1', 'Fnl1'));
p_iff = plot(1/Rz_periods(i), imag(G_zeros(imag(G_zeros)<2*pi*25 & imag(G_zeros)>2*pi*22)), 'o');
set(gca,'ColorOrderIndex',3);
G_zeros = zero(Gw_dvf{i}('Dnlm1', 'Fnl1'));
p_dvf = plot(1/Rz_periods(i), imag(G_zeros(imag(G_zeros)<2*pi*25 & imag(G_zeros)>2*pi*22)), 'o');
end
hold off;
xlabel('Rotation Speed [Hz]');
ylabel('Imaginary Part');
legend([p_ine p_iff p_dvf],{'Inertial Sensor','Force Sensor', 'Relative Motion Sensor'}, 'location', 'southwest');
#+end_src
#+HEADER: :tangle no :exports results :results none :noweb yes
#+begin_src matlab :var filepath="figs/variation_zeros_active_damping_plants.pdf" :var figsize="full-normal" :post pdf2svg(file=*this*, ext="png")
<>
#+end_src
#+name: fig:variation_zeros_active_damping_plants
#+caption: Evolution of the zero with respect to the spindle rotation speed ([[./figs/variation_zeros_active_damping_plants.png][png]], [[./figs/variation_zeros_active_damping_plants.pdf][pdf]])
[[file:figs/variation_zeros_active_damping_plants.png]]
** Variation of the Tilt Angle
<>
*** Introduction :ignore:
*** Identification :ignore:
We initialize all the stages with the default parameters.
#+begin_src matlab
prepareLinearizeIdentification();
#+end_src
#+begin_src matlab :exports none
%% Options for Linearized
options = linearizeOptions;
options.SampleTime = 0;
%% Name of the Simulink File
mdl = 'nass_model';
%% Input/Output definition
clear io; io_i = 1;
io(io_i) = linio([mdl, '/Controller'], 1, 'openinput'); io_i = io_i + 1; % Actuator Inputs
io(io_i) = linio([mdl, '/Micro-Station'], 3, 'openoutput', [], 'Dnlm'); io_i = io_i + 1;
io(io_i) = linio([mdl, '/Micro-Station'], 3, 'openoutput', [], 'Fnlm'); io_i = io_i + 1;
io(io_i) = linio([mdl, '/Micro-Station'], 3, 'openoutput', [], 'Vlm'); io_i = io_i + 1;
#+end_src
We identify the dynamics for the following Tilt stage angles.
#+begin_src matlab
Ry_amplitudes = [-3*pi/180, 3*pi/180]; % [rad]
#+end_src
#+begin_src matlab :exports none
Gy = {zeros(length(Ry_amplitudes))};
Gy_iff = {zeros(length(Ry_amplitudes))};
Gy_dvf = {zeros(length(Ry_amplitudes))};
Gy_ine = {zeros(length(Ry_amplitudes))};
for i = 1:length(Ry_amplitudes)
initializeReferences('Ry_type', 'constant', 'Ry_amplitude', Ry_amplitudes(i))
%% Run the linearization
G = linearize(mdl, io, 0.3, options);
G.InputName = {'Fnl1', 'Fnl2', 'Fnl3', 'Fnl4', 'Fnl5', 'Fnl6'};
G.OutputName = {'Dnlm1', 'Dnlm2', 'Dnlm3', 'Dnlm4', 'Dnlm5', 'Dnlm6', ...
'Fnlm1', 'Fnlm2', 'Fnlm3', 'Fnlm4', 'Fnlm5', 'Fnlm6', ...
'Vnlm1', 'Vnlm2', 'Vnlm3', 'Vnlm4', 'Vnlm5', 'Vnlm6'};
Gy(i) = {G};
Gy_iff(i) = {minreal(G({'Fnlm1', 'Fnlm2', 'Fnlm3', 'Fnlm4', 'Fnlm5', 'Fnlm6'}, {'Fnl1', 'Fnl2', 'Fnl3', 'Fnl4', 'Fnl5', 'Fnl6'}))};
Gy_dvf(i) = {minreal(G({'Dnlm1', 'Dnlm2', 'Dnlm3', 'Dnlm4', 'Dnlm5', 'Dnlm6'}, {'Fnl1', 'Fnl2', 'Fnl3', 'Fnl4', 'Fnl5', 'Fnl6'}))};
Gy_ine(i) = {minreal(G({'Vnlm1', 'Vnlm2', 'Vnlm3', 'Vnlm4', 'Vnlm5', 'Vnlm6'}, {'Fnl1', 'Fnl2', 'Fnl3', 'Fnl4', 'Fnl5', 'Fnl6'}))};
end
#+end_src
#+begin_src matlab :exports none
save('./active_damping/mat/plants_variable.mat', 'Ry_amplitudes', 'Gy_iff', 'Gy_dvf', 'Gy_ine', '-append');
#+end_src
*** Plots :ignore:
#+begin_src matlab :exports none
load('./active_damping/mat/plants_variable.mat', 'Ry_amplitudes', 'Gy_iff', 'Gy_dvf', 'Gy_ine');
load('./active_damping/mat/undamped_plants.mat', 'G_iff', 'G_dvf', 'G_ine');
#+end_src
#+begin_src matlab :exports none
freqs = logspace(0, 3, 1000);
figure;
ax1 = subplot(2, 1, 1);
hold on;
for i = 1:length(Gy_iff)
plot(freqs, abs(squeeze(freqresp(Gy_iff{i}('Fnlm1', 'Fnl1'), freqs, 'Hz'))));
end
plot(freqs, abs(squeeze(freqresp(G_iff('Fnlm1', 'Fnl1'), freqs, 'Hz'))), 'k--');
hold off;
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
ylabel('Amplitude [N/N]'); set(gca, 'XTickLabel',[]);
ax2 = subplot(2, 1, 2);
hold on;
for i = 1:length(Gy_iff)
plot(freqs, 180/pi*angle(squeeze(freqresp(Gy_iff{i}('Fnlm1', 'Fnl1'), freqs, 'Hz'))), 'DisplayName', sprintf('$Ry = %.0f$ [deg]', Ry_amplitudes(i)*180/pi));
end
plot(freqs, 180/pi*angle(squeeze(freqresp(G_iff('Fnlm1', 'Fnl1'), freqs, 'Hz'))), 'k--', 'DisplayName', '$Ry = 0$ [deg]');
hold off;
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'lin');
ylabel('Phase [deg]'); xlabel('Frequency [Hz]');
ylim([-180, 180]);
yticks([-180, -90, 0, 90, 180]);
legend('location', 'southwest');
linkaxes([ax1,ax2],'x');
xlim([freqs(1), freqs(end)]);
#+end_src
#+HEADER: :tangle no :exports results :results none :noweb yes
#+begin_src matlab :var filepath="figs/act_damp_variability_iff_tilt_angle.pdf" :var figsize="full-tall" :post pdf2svg(file=*this*, ext="png")
<>
#+end_src
#+name: fig:act_damp_variability_iff_tilt_angle
#+caption: Variability of the dynamics from the actuator force to the force sensor with the Tilt stage Angle ([[./figs/act_damp_variability_iff_tilt_angle.png][png]], [[./figs/act_damp_variability_iff_tilt_angle.pdf][pdf]])
[[file:figs/act_damp_variability_iff_tilt_angle.png]]
#+begin_src matlab :exports none
freqs = logspace(0, 3, 1000);
figure;
ax1 = subplot(2, 1, 1);
hold on;
for i = 1:length(Gy_dvf)
plot(freqs, abs(squeeze(freqresp(Gy_dvf{i}('Dnlm1', 'Fnl1'), freqs, 'Hz'))));
end
plot(freqs, abs(squeeze(freqresp(G_dvf('Dnlm1', 'Fnl1'), freqs, 'Hz'))), 'k--');
hold off;
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
ylabel('Amplitude [m/N]'); set(gca, 'XTickLabel',[]);
ax2 = subplot(2, 1, 2);
hold on;
for i = 1:length(Gy_dvf)
plot(freqs, 180/pi*angle(squeeze(freqresp(Gy_dvf{i}('Dnlm1', 'Fnl1'), freqs, 'Hz'))), 'DisplayName', sprintf('$Ry = %.0f$ [deg]', Ry_amplitudes(i)*180/pi));
end
plot(freqs, 180/pi*angle(squeeze(freqresp(G_dvf('Dnlm1', 'Fnl1'), freqs, 'Hz'))), 'k--', 'DisplayName', '$Ry = 0$ [deg]');
hold off;
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'lin');
ylabel('Phase [deg]'); xlabel('Frequency [Hz]');
ylim([-180, 180]);
yticks([-180, -90, 0, 90, 180]);
legend('location', 'southwest');
linkaxes([ax1,ax2],'x');
xlim([freqs(1), freqs(end)]);
#+end_src
#+HEADER: :tangle no :exports results :results none :noweb yes
#+begin_src matlab :var filepath="figs/act_damp_variability_dvf_tilt_angle.pdf" :var figsize="full-tall" :post pdf2svg(file=*this*, ext="png")
<>
#+end_src
#+name: fig:act_damp_variability_dvf_tilt_angle
#+caption: Variability of the dynamics from the actuator force to the relative motion sensor with the Tilt Angle ([[./figs/act_damp_variability_dvf_tilt_angle.png][png]], [[./figs/act_damp_variability_dvf_tilt_angle.pdf][pdf]])
[[file:figs/act_damp_variability_dvf_tilt_angle.png]]
#+begin_src matlab :exports none
freqs = logspace(0, 3, 1000);
figure;
ax1 = subplot(2, 1, 1);
hold on;
for i = 1:length(Gy_ine)
plot(freqs, abs(squeeze(freqresp(Gy_ine{i}('Vnlm1', 'Fnl1'), freqs, 'Hz'))));
end
plot(freqs, abs(squeeze(freqresp(G_ine('Vnlm1', 'Fnl1'), freqs, 'Hz'))), 'k--');
hold off;
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
ylabel('Amplitude [$\frac{m/s}{N}$]'); set(gca, 'XTickLabel',[]);
ax2 = subplot(2, 1, 2);
hold on;
for i = 1:length(Gy_ine)
plot(freqs, 180/pi*angle(squeeze(freqresp(Gy_ine{i}('Vnlm1', 'Fnl1'), freqs, 'Hz'))), 'DisplayName', sprintf('$Ry = %.0f$ [deg]', Ry_amplitudes(i)*180/pi));
end
plot(freqs, 180/pi*angle(squeeze(freqresp(G_ine('Vnlm1', 'Fnl1'), freqs, 'Hz'))), 'k--', 'DisplayName', '$Ry = 0$ [deg]');
hold off;
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'lin');
ylabel('Phase [deg]'); xlabel('Frequency [Hz]');
ylim([-180, 180]);
yticks([-180, -90, 0, 90, 180]);
legend('location', 'southwest');
linkaxes([ax1,ax2],'x');
xlim([freqs(1), freqs(end)]);
#+end_src
#+HEADER: :tangle no :exports results :results none :noweb yes
#+begin_src matlab :var filepath="figs/act_damp_variability_ine_tilt_angle.pdf" :var figsize="full-tall" :post pdf2svg(file=*this*, ext="png")
<>
#+end_src
#+name: fig:act_damp_variability_ine_tilt_angle
#+caption: Variability of the dynamics from the actuator force to the absolute velocity sensor with the Tilt Angle ([[./figs/act_damp_variability_ine_tilt_angle.png][png]], [[./figs/act_damp_variability_ine_tilt_angle.pdf][pdf]])
[[file:figs/act_damp_variability_ine_tilt_angle.png]]
** Scans of the Translation Stage
<>
*** Introduction :ignore:
We want here to verify if the dynamics used for Active damping is varying when using the translation stage for scans.
*** Identification :ignore:
We initialize all the stages with the default parameters.
#+begin_src matlab
prepareLinearizeIdentification();
#+end_src
#+begin_src matlab :exports none
%% Options for Linearized
options = linearizeOptions;
options.SampleTime = 0;
%% Name of the Simulink File
mdl = 'nass_model';
%% Input/Output definition
clear io; io_i = 1;
io(io_i) = linio([mdl, '/Controller'], 1, 'openinput'); io_i = io_i + 1; % Actuator Inputs
io(io_i) = linio([mdl, '/Micro-Station'], 3, 'openoutput', [], 'Dnlm'); io_i = io_i + 1;
io(io_i) = linio([mdl, '/Micro-Station'], 3, 'openoutput', [], 'Fnlm'); io_i = io_i + 1;
io(io_i) = linio([mdl, '/Micro-Station'], 3, 'openoutput', [], 'Vlm'); io_i = io_i + 1;
#+end_src
We initialize the translation stage reference to be a sinus with an amplitude of 5mm and a period of 1s (Figure [[fig:ty_scanning_reference_sinus]]).
#+begin_src matlab
initializeReferences('Dy_type', 'sinusoidal', ...
'Dy_amplitude', 5e-3, ... % [m]
'Dy_period', 1); % [s]
#+end_src
#+begin_src matlab :exports none
load('mat/nass_references.mat', 'Dy');
figure;
plot(Dy.time, Dy.signals.values);
xlabel('Time [s]'); ylabel('Dy - Position [m]');
xlim([0, 2]);
#+end_src
#+HEADER: :tangle no :exports results :results none :noweb yes
#+begin_src matlab :var filepath="figs/ty_scanning_reference_sinus.pdf" :var figsize="wide-normal" :post pdf2svg(file=*this*, ext="png")
<>
#+end_src
#+name: fig:ty_scanning_reference_sinus
#+caption: Reference path for the translation stage ([[./figs/ty_scanning_reference_sinus.png][png]], [[./figs/ty_scanning_reference_sinus.pdf][pdf]])
[[file:figs/ty_scanning_reference_sinus.png]]
We identify the dynamics at different positions (times) when scanning with the Translation stage.
#+begin_src matlab
t_lin = [0.5, 0.75, 1, 1.25];
#+end_src
#+begin_src matlab :exports none
Gty = {zeros(length(t_lin))};
Gty_iff = {zeros(length(t_lin))};
Gty_dvf = {zeros(length(t_lin))};
Gty_ine = {zeros(length(t_lin))};
%% Run the linearization
G = linearize(mdl, io, t_lin, options);
G.InputName = {'Fnl1', 'Fnl2', 'Fnl3', 'Fnl4', 'Fnl5', 'Fnl6'};
G.OutputName = {'Dnlm1', 'Dnlm2', 'Dnlm3', 'Dnlm4', 'Dnlm5', 'Dnlm6', ...
'Fnlm1', 'Fnlm2', 'Fnlm3', 'Fnlm4', 'Fnlm5', 'Fnlm6', ...
'Vnlm1', 'Vnlm2', 'Vnlm3', 'Vnlm4', 'Vnlm5', 'Vnlm6'};
for i = 1:length(t_lin)
Gty(i) = {G(:,:,i)};
Gty_iff(i) = {minreal(G({'Fnlm1', 'Fnlm2', 'Fnlm3', 'Fnlm4', 'Fnlm5', 'Fnlm6'}, {'Fnl1', 'Fnl2', 'Fnl3', 'Fnl4', 'Fnl5', 'Fnl6'}, i))};
Gty_dvf(i) = {minreal(G({'Dnlm1', 'Dnlm2', 'Dnlm3', 'Dnlm4', 'Dnlm5', 'Dnlm6'}, {'Fnl1', 'Fnl2', 'Fnl3', 'Fnl4', 'Fnl5', 'Fnl6'}, i))};
Gty_ine(i) = {minreal(G({'Vnlm1', 'Vnlm2', 'Vnlm3', 'Vnlm4', 'Vnlm5', 'Vnlm6'}, {'Fnl1', 'Fnl2', 'Fnl3', 'Fnl4', 'Fnl5', 'Fnl6'}, i))};
end
#+end_src
#+begin_src matlab :exports none
Gty_tlin = t_lin;
save('./active_damping/mat/plants_variable.mat', 'Gty_tlin', 'Dy', 'Gty_iff', 'Gty_dvf', 'Gty_ine', '-append');
#+end_src
*** Plots :ignore:
#+begin_src matlab :exports none
load('./active_damping/mat/plants_variable.mat', 'Gty_tlin', 'Dy', 'Gty_iff', 'Gty_dvf', 'Gty_ine');
load('./active_damping/mat/undamped_plants.mat', 'G_iff', 'G_dvf', 'G_ine');
#+end_src
#+begin_src matlab :exports none
freqs = logspace(0, 3, 1000);
figure;
ax1 = subplot(2, 1, 1);
hold on;
for i = 1:length(Gty_iff)
plot(freqs, abs(squeeze(freqresp(Gty_iff{i}('Fnlm1', 'Fnl1'), freqs, 'Hz'))));
end
plot(freqs, abs(squeeze(freqresp(G_iff('Fnlm1', 'Fnl1'), freqs, 'Hz'))), 'k--');
hold off;
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
ylabel('Amplitude [N/N]'); set(gca, 'XTickLabel',[]);
ax2 = subplot(2, 1, 2);
hold on;
for i = 1:length(Gty_iff)
[~, i_t] = min(abs(Dy.time - Gty_tlin(i)));
plot(freqs, 180/pi*angle(squeeze(freqresp(Gty_iff{i}('Fnlm1', 'Fnl1'), freqs, 'Hz'))), 'DisplayName', sprintf('$Dy = %.0f$ [mm]', 1e3*Dy.signals.values(i_t)));
end
plot(freqs, 180/pi*angle(squeeze(freqresp(G_iff('Fnlm1', 'Fnl1'), freqs, 'Hz'))), 'k--', 'DisplayName', '$Ry = 0$ [deg]');
hold off;
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'lin');
ylabel('Phase [deg]'); xlabel('Frequency [Hz]');
ylim([-180, 180]);
yticks([-180, -90, 0, 90, 180]);
legend('location', 'southwest');
linkaxes([ax1,ax2],'x');
xlim([freqs(1), freqs(end)]);
#+end_src
#+HEADER: :tangle no :exports results :results none :noweb yes
#+begin_src matlab :var filepath="figs/act_damp_variability_iff_ty_scans.pdf" :var figsize="full-tall" :post pdf2svg(file=*this*, ext="png")
<>
#+end_src
#+name: fig:act_damp_variability_iff_ty_scans
#+caption: Variability of the dynamics from the actuator force to the absolute velocity sensor plant at different Ty scan positions ([[./figs/act_damp_variability_iff_ty_scans.png][png]], [[./figs/act_damp_variability_iff_ty_scans.pdf][pdf]])
[[file:figs/act_damp_variability_iff_ty_scans.png]]
#+begin_src matlab :exports none
freqs = logspace(0, 3, 1000);
figure;
ax1 = subplot(2, 1, 1);
hold on;
for i = 1:length(Gty_dvf)
plot(freqs, abs(squeeze(freqresp(Gty_dvf{i}('Dnlm1', 'Fnl1'), freqs, 'Hz'))));
end
plot(freqs, abs(squeeze(freqresp(G_dvf('Dnlm1', 'Fnl1'), freqs, 'Hz'))), 'k--');
hold off;
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
ylabel('Amplitude [m/N]'); set(gca, 'XTickLabel',[]);
ax2 = subplot(2, 1, 2);
hold on;
for i = 1:length(Gty_dvf)
[~, i_t] = min(abs(Dy.time - Gty_tlin(i)));
plot(freqs, 180/pi*angle(squeeze(freqresp(Gty_dvf{i}('Dnlm1', 'Fnl1'), freqs, 'Hz'))), 'DisplayName', sprintf('$Dy = %.0f$ [mm]', 1e3*Dy.signals.values(i_t)));
end
plot(freqs, 180/pi*angle(squeeze(freqresp(G_dvf('Dnlm1', 'Fnl1'), freqs, 'Hz'))), 'k--', 'DisplayName', '$Ry = 0$ [deg]');
hold off;
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'lin');
ylabel('Phase [deg]'); xlabel('Frequency [Hz]');
ylim([-180, 180]);
yticks([-180, -90, 0, 90, 180]);
legend('location', 'southwest');
linkaxes([ax1,ax2],'x');
xlim([freqs(1), freqs(end)]);
#+end_src
#+HEADER: :tangle no :exports results :results none :noweb yes
#+begin_src matlab :var filepath="figs/act_damp_variability_dvf_ty_scans.pdf" :var figsize="full-tall" :post pdf2svg(file=*this*, ext="png")
<>
#+end_src
#+name: fig:act_damp_variability_dvf_ty_scans
#+caption: Variability of the dynamics from actuator force to relative displacement sensor at different Ty scan positions ([[./figs/act_damp_variability_dvf_ty_scans.png][png]], [[./figs/act_damp_variability_dvf_ty_scans.pdf][pdf]])
[[file:figs/act_damp_variability_dvf_ty_scans.png]]
#+begin_src matlab :exports none
freqs = logspace(0, 3, 1000);
figure;
ax1 = subplot(2, 1, 1);
hold on;
for i = 1:length(Gty_ine)
plot(freqs, abs(squeeze(freqresp(Gty_ine{i}('Vnlm1', 'Fnl1'), freqs, 'Hz'))));
end
plot(freqs, abs(squeeze(freqresp(G_ine('Vnlm1', 'Fnl1'), freqs, 'Hz'))), 'k--');
hold off;
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
ylabel('Amplitude [$\frac{m/s}{N}$]'); set(gca, 'XTickLabel',[]);
ax2 = subplot(2, 1, 2);
hold on;
for i = 1:length(Gty_ine)
[~, i_t] = min(abs(Dy.time - Gty_tlin(i)));
plot(freqs, 180/pi*angle(squeeze(freqresp(Gty_ine{i}('Vnlm1', 'Fnl1'), freqs, 'Hz'))), 'DisplayName', sprintf('$Dy = %.0f$ [mm]', 1e3*Dy.signals.values(i_t)));
end
plot(freqs, 180/pi*angle(squeeze(freqresp(G_ine('Vnlm1', 'Fnl1'), freqs, 'Hz'))), 'k--', 'DisplayName', '$Ry = 0$ [deg]');
hold off;
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'lin');
ylabel('Phase [deg]'); xlabel('Frequency [Hz]');
ylim([-180, 180]);
yticks([-180, -90, 0, 90, 180]);
legend('location', 'southwest');
linkaxes([ax1,ax2],'x');
xlim([freqs(1), freqs(end)]);
#+end_src
#+HEADER: :tangle no :exports results :results none :noweb yes
#+begin_src matlab :var filepath="figs/act_damp_variability_ine_ty_scans.pdf" :var figsize="full-tall" :post pdf2svg(file=*this*, ext="png")
<>
#+end_src
#+name: fig:act_damp_variability_ine_ty_scans
#+caption: Variability of the Inertial plant at different Ty scan positions ([[./figs/act_damp_variability_ine_ty_scans.png][png]], [[./figs/act_damp_variability_ine_ty_scans.pdf][pdf]])
[[file:figs/act_damp_variability_ine_ty_scans.png]]
** Conclusion
#+name: tab:active_damping_plant_variability
#+caption: Conclusion on the variability of the system dynamics for active damping
| | |
| | *Change of Dynamics* |
|---------------------------+--------------------------------------------|
| *Sample Mass* | Large |
| *Spindle Angle* | Small |
| *Spindle Rotation Speed* | First resonance is split in two resonances |
| *Tilt Angle* | Negligible |
| *Translation Stage scans* | Negligible |
Also, for the Inertial Sensor, a RHP zero may appear when the spindle is rotating fast.
#+begin_important
When using either a force sensor or a relative motion sensor for active damping, the only "parameter" that induce a large change for the dynamics to be controlled is the *sample mass*.
Thus, the developed damping techniques should be robust to variations of the sample mass.
#+end_important
* Integral Force Feedback
:PROPERTIES:
:header-args:matlab+: :tangle matlab/iff.m
:header-args:matlab+: :comments none :mkdirp yes
:END:
<>
** ZIP file containing the data and matlab files :ignore:
#+begin_src bash :exports none :results none
if [ matlab/iff.m -nt data/iff.zip ]; then
cp matlab/iff.m iff.m;
zip data/iff \
mat/plant.mat \
iff.m
rm iff.m;
fi
#+end_src
#+begin_note
All the files (data and Matlab scripts) are accessible [[file:data/iff.zip][here]].
#+end_note
** Introduction :ignore:
Here, we study the use of *Integral Force Feedback* (IFF) to actively damp the resonances.
The IFF control is applied in a decentralized way: there is on controller for each leg.
The control architecture is represented in figure [[fig:iff_1dof]] where one of the 6 nano-hexapod legs is represented.
#+name: fig:iff_1dof
#+caption: Integral Force Feedback applied to a 1dof system
#+RESULTS:
[[file:figs/iff_1dof.png]]
** Matlab Init :noexport:ignore:
#+begin_src matlab :tangle no :exports none :results silent :noweb yes :var current_dir=(file-name-directory buffer-file-name)
<>
#+end_src
#+begin_src matlab :exports none :results silent :noweb yes
<>
#+end_src
#+begin_src matlab :tangle no
simulinkproject('../');
#+end_src
#+begin_src matlab
addpath('active_damping/src/');
#+end_src
#+begin_src matlab
open('nass_model.slx')
#+end_src
** Control Design
*** Plant
Let's load the previously identified undamped plant:
#+begin_src matlab
load('./active_damping/mat/undamped_plants.mat', 'G_iff');
load('./active_damping/mat/plants_variable.mat', 'masses', 'Gm_iff');
#+end_src
Let's look at the transfer function from actuator forces in the nano-hexapod to the force sensor in the nano-hexapod legs for all 6 pairs of actuator/sensor (figure [[fig:iff_plant]]).
#+begin_src matlab :exports none
freqs = logspace(-2, 3, 1000);
figure;
ax1 = subplot(2, 1, 1);
hold on;
for i=1:length(masses)
plot(freqs, abs(squeeze(freqresp(-Gm_iff{i}('Fnlm1', 'Fnl1'), freqs, 'Hz'))));
end
hold off;
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
ylabel('Amplitude [N/N]'); set(gca, 'XTickLabel',[]);
ax2 = subplot(2, 1, 2);
hold on;
for i=1:length(masses)
plot(freqs, 180/pi*angle(squeeze(freqresp(-Gm_iff{i}('Fnlm1', 'Fnl1'), freqs, 'Hz'))), ...
'DisplayName', sprintf('$M = %.0f$ [kg]', masses(i)));
end
hold off;
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'lin');
ylabel('Phase [deg]'); xlabel('Frequency [Hz]');
ylim([-180, 180]);
yticks([-180, -90, 0, 90, 180]);
legend('location', 'southwest');
linkaxes([ax1,ax2],'x');
#+end_src
#+HEADER: :tangle no :exports results :results none :noweb yes
#+begin_src matlab :var filepath="figs/iff_plant.pdf" :var figsize="full-tall" :post pdf2svg(file=*this*, ext="png")
<>
#+end_src
#+name: fig:iff_plant
#+caption: Transfer function from forces applied in the legs to force sensor ([[./figs/iff_plant.png][png]], [[./figs/iff_plant.pdf][pdf]])
[[file:figs/iff_plant.png]]
*** Control Design
The controller for each pair of actuator/sensor is:
#+begin_src matlab
w0 = 2*pi*50;
K_iff = -5000/s * (s/w0)/(1 + s/w0);
#+end_src
The corresponding loop gains are shown in figure [[fig:iff_open_loop]].
#+begin_src matlab :exports none
freqs = logspace(0, 3, 1000);
figure;
ax1 = subplot(2, 1, 1);
hold on;
for i=1:length(masses)
plot(freqs, abs(squeeze(freqresp(K_iff*Gm_iff{i}('Fnlm1', 'Fnl1'), freqs, 'Hz'))));
end
hold off;
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
ylabel('Amplitude [N/N]'); set(gca, 'XTickLabel',[]);
ax2 = subplot(2, 1, 2);
hold on;
for i=1:length(masses)
plot(freqs, 180/pi*angle(squeeze(freqresp(K_iff*Gm_iff{i}('Fnlm1', 'Fnl1'), freqs, 'Hz'))), ...
'DisplayName', sprintf('$M = %.0f$ [kg]', masses(i)));
end
hold off;
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'lin');
ylabel('Phase [deg]'); xlabel('Frequency [Hz]');
ylim([-180, 180]);
yticks([-180, -90, 0, 90, 180]);
legend('location', 'southwest');
linkaxes([ax1,ax2],'x');
#+end_src
#+HEADER: :tangle no :exports results :results none :noweb yes
#+begin_src matlab :var filepath="figs/iff_open_loop.pdf" :var figsize="full-tall" :post pdf2svg(file=*this*, ext="png")
<>
#+end_src
#+name: fig:iff_open_loop
#+caption: Loop Gain for the Integral Force Feedback ([[./figs/iff_open_loop.png][png]], [[./figs/iff_open_loop.pdf][pdf]])
[[file:figs/iff_open_loop.png]]
*** Diagonal Controller
We create the diagonal controller and we add a minus sign as we have a positive
feedback architecture.
#+begin_src matlab
K_iff = -K_iff*eye(6);
#+end_src
We save the controller for further analysis.
#+begin_src matlab
save('./active_damping/mat/K_iff.mat', 'K_iff');
#+end_src
** Identification of the damped plant :noexport:
*** Identification
We initialize all the stages with the default parameters.
#+begin_src matlab
prepareLinearizeIdentification();
#+end_src
We set the IFF controller.
#+begin_src matlab
load('./active_damping/mat/K_iff.mat', 'K_iff');
initializeController('type', 'iff', 'K', K_iff);
#+end_src
We identify the dynamics of the system using the =linearize= function.
#+begin_src matlab
%% Options for Linearized
options = linearizeOptions;
options.SampleTime = 0;
%% Name of the Simulink File
mdl = 'nass_model';
%% Input/Output definition
clear io; io_i = 1;
io(io_i) = linio([mdl, '/Controller'], 1, 'openinput'); io_i = io_i + 1; % Actuator Inputs
io(io_i) = linio([mdl, '/Tracking Error'], 1, 'output', [], 'En'); io_i = io_i + 1;
#+end_src
We identify the dynamics for the following sample mass.
#+begin_src matlab
load('./active_damping/mat/cart_plants.mat', 'masses');
#+end_src
#+begin_src matlab :exports none
G_cart_iff = {zeros(length(masses))};
load('mat/stages.mat', 'nano_hexapod');
for i = 1:length(masses)
initializeSample('mass', masses(i));
%% Run the linearization
G = linearize(mdl, io, 0.3, options);
G.InputName = {'Fnl1', 'Fnl2', 'Fnl3', 'Fnl4', 'Fnl5', 'Fnl6'};
G.OutputName = {'Dnx', 'Dny', 'Dnz', 'Rnx', 'Rny', 'Rnz'};
G_cart = G*inv(nano_hexapod.J');
G_cart.InputName = {'Fnx', 'Fny', 'Fnz', 'Mnx', 'Mny', 'Mnz'};
G_cart_iff(i) = {G_cart};
end
#+end_src
And we save them for further analysis.
#+begin_src matlab
save('./active_damping/mat/cart_plants.mat', 'G_cart_iff', '-append');
#+end_src
*** Damped Plant
Now, look at the new damped plant to control.
#+begin_src matlab
load('./active_damping/mat/cart_plants.mat', 'masses', 'G_cart', 'G_cart_iff');
#+end_src
It damps the plant (resonance of the nano hexapod as well as other resonances) as shown in figure [[fig:plant_iff_damped]].
#+begin_src matlab :exports none
freqs = logspace(0, 3, 1000);
figure;
ax1 = subplot(2, 1, 1);
hold on;
for i = 1:length(masses)
set(gca,'ColorOrderIndex',i);
p1 = plot(freqs, abs(squeeze(freqresp(G_cart_iff{i}('Dnx', 'Fnx'), freqs, 'Hz'))));
set(gca,'ColorOrderIndex',i);
p2 = plot(freqs, abs(squeeze(freqresp(G_cart_iff{i}('Dny', 'Fny'), freqs, 'Hz'))), '--');
set(gca,'ColorOrderIndex',i);
p3 = plot(freqs, abs(squeeze(freqresp(G_cart_iff{i}('Dnz', 'Fnz'), freqs, 'Hz'))), ':');
end
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
ylabel('Amplitude [m/N]'); xlabel('Frequency [Hz]');
legend([p1,p2,p3], {'Fx/Dx', 'Fy/Dx', 'Fz/Dz'});
ax2 = subplot(2, 1, 2);
hold on;
for i = 1:length(masses)
set(gca,'ColorOrderIndex',i);
plot(freqs, 180/pi*unwrap(angle(squeeze(freqresp(G_cart_iff{i}('Dnx', 'Fnx'), freqs, 'Hz')))), ...
'DisplayName', sprintf('$M = %.0f$ [kg]', masses(i)));
set(gca,'ColorOrderIndex',i);
plot(freqs, 180/pi*unwrap(angle(squeeze(freqresp(G_cart_iff{i}('Dny', 'Fny'), freqs, 'Hz')))), '--', 'HandleVisibility', 'off');
set(gca,'ColorOrderIndex',i);
plot(freqs, 180/pi*unwrap(angle(squeeze(freqresp(G_cart_iff{i}('Dnz', 'Fnz'), freqs, 'Hz')))), ':', 'HandleVisibility', 'off');
end
hold off;
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'lin');
ylabel('Phase [deg]'); xlabel('Frequency [Hz]');
yticks([-540:180:540]);
legend('location', 'northeast');
linkaxes([ax1,ax2],'x');
#+end_src
#+HEADER: :tangle no :exports results :results none :noweb yes
#+begin_src matlab :var filepath="figs/plant_iff_damped_translations.pdf" :var figsize="full-tall" :post pdf2svg(file=*this*, ext="png")
<>
#+end_src
#+name: fig:plant_iff_damped_translations
#+caption: Damped Plant for the translations after IFF is applied ([[./figs/plant_iff_damped_translations.png][png]], [[./figs/plant_iff_damped_translations.pdf][pdf]])
[[file:figs/plant_iff_damped_translations.png]]
#+begin_src matlab :exports none
freqs = logspace(0, 3, 1000);
figure;
ax1 = subplot(2, 1, 1);
hold on;
for i = 1:length(masses)
set(gca,'ColorOrderIndex',i);
p1 = plot(freqs, abs(squeeze(freqresp(G_cart_iff{i}('Rnx', 'Mnx'), freqs, 'Hz'))));
set(gca,'ColorOrderIndex',i);
p2 = plot(freqs, abs(squeeze(freqresp(G_cart_iff{i}('Rny', 'Mny'), freqs, 'Hz'))), '--');
set(gca,'ColorOrderIndex',i);
p3 = plot(freqs, abs(squeeze(freqresp(G_cart_iff{i}('Rnz', 'Mnz'), freqs, 'Hz'))), ':');
end
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
ylabel('Amplitude [m/N]'); xlabel('Frequency [Hz]');
legend([p1,p2,p3], {'Fx/Dx', 'Fy/Dx', 'Fz/Dz'});
ax2 = subplot(2, 1, 2);
hold on;
for i = 1:length(masses)
set(gca,'ColorOrderIndex',i);
plot(freqs, 180/pi*unwrap(angle(squeeze(freqresp(G_cart_iff{i}('Rnx', 'Mnx'), freqs, 'Hz')))), ...
'DisplayName', sprintf('$M = %.0f$ [kg]', masses(i)));
set(gca,'ColorOrderIndex',i);
plot(freqs, 180/pi*unwrap(angle(squeeze(freqresp(G_cart_iff{i}('Rny', 'Mny'), freqs, 'Hz')))), '--', 'HandleVisibility', 'off');
set(gca,'ColorOrderIndex',i);
plot(freqs, 180/pi*unwrap(angle(squeeze(freqresp(G_cart_iff{i}('Rnz', 'Mnz'), freqs, 'Hz')))), ':', 'HandleVisibility', 'off');
end
hold off;
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'lin');
ylabel('Phase [deg]'); xlabel('Frequency [Hz]');
yticks([-540:180:540]);
legend('location', 'northeast');
linkaxes([ax1,ax2],'x');
#+end_src
#+HEADER: :tangle no :exports results :results none :noweb yes
#+begin_src matlab :var filepath="figs/plant_iff_damped_rotations.pdf" :var figsize="full-tall" :post pdf2svg(file=*this*, ext="png")
<>
#+end_src
#+name: fig:plant_iff_damped_rotations
#+caption: Damped Plant for the Rotations after IFF is applied ([[./figs/plant_iff_damped_rotations.png][png]], [[./figs/plant_iff_damped_rotations.pdf][pdf]])
[[file:figs/plant_iff_damped_rotations.png]]
However, it increases coupling at low frequency (figure [[fig:plant_iff_coupling]]).
#+begin_src matlab :exports none
freqs = logspace(1, 3, 1000);
figure;
for ix = 1:6
for iy = 1:6
subplot(6, 6, (ix-1)*6 + iy);
hold on;
plot(freqs, abs(squeeze(freqresp(G_cart{1}(ix, iy), freqs, 'Hz'))), 'k-');
plot(freqs, abs(squeeze(freqresp(G_cart_iff{1}(ix, iy), freqs, 'Hz'))), 'k--');
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
ylim([1e-13, 1e-4]);
xticks([])
yticks([])
end
end
#+end_src
#+HEADER: :tangle no :exports results :results none :noweb yes
#+begin_src matlab :var filepath="figs/plant_iff_coupling.pdf" :var figsize="full-tall" :post pdf2svg(file=*this*, ext="png")
<>
#+end_src
#+name: fig:plant_iff_coupling
#+caption: Coupling induced by IFF ([[./figs/plant_iff_coupling.png][png]], [[./figs/plant_iff_coupling.pdf][pdf]])
[[file:figs/plant_iff_coupling.png]]
** Tomography Experiment
*** Simulation with IFF Controller
We initialize elements for the tomography experiment.
#+begin_src matlab
prepareTomographyExperiment();
#+end_src
We set the IFF controller.
#+begin_src matlab
load('./active_damping/mat/K_iff.mat', 'K_iff');
initializeController('type', 'iff', 'K', K_iff);
#+end_src
We change the simulation stop time.
#+begin_src matlab
load('mat/conf_simulink.mat');
set_param(conf_simulink, 'StopTime', '4.5');
#+end_src
And we simulate the system.
#+begin_src matlab
sim('nass_model');
#+end_src
Finally, we save the simulation results for further analysis
#+begin_src matlab
En_iff = En;
Eg_iff = Eg;
save('./active_damping/mat/tomo_exp.mat', 'En_iff', 'Eg_iff', '-append');
#+end_src
*** Compare with Undamped system
#+begin_src matlab :exports none
load('./active_damping/mat/tomo_exp.mat', 'En', 'En_iff');
Fs = 1e3; % Sampling Frequency of the Data
t = (1/Fs)*[0:length(En(:,1))-1];
#+end_src
#+begin_src matlab :exports none
figure;
hold on;
plot(En(:,1), En(:,2), 'DisplayName', '$\epsilon_{x,y}$ - OL')
plot(En_iff(:,1), En_iff(:,2), 'DisplayName', '$\epsilon_{x,y}$ - IFF')
xlabel('X Motion [m]'); ylabel('Y Motion [m]');
legend('location', 'northwest');
#+end_src
#+HEADER: :tangle no :exports results :results none :noweb yes
#+begin_src matlab :var filepath="figs/nass_act_damp_iff_sim_tomo_xy.pdf" :var figsize="small-normal" :post pdf2svg(file=*this*, ext="png")
<>
#+end_src
#+name: fig:nass_act_damp_iff_sim_tomo_xy
#+caption: Position Error during tomography experiment - XY Motion ([[./figs/nass_act_damp_iff_sim_tomo_xy.png][png]], [[./figs/nass_act_damp_iff_sim_tomo_xy.pdf][pdf]])
[[file:figs/nass_act_damp_iff_sim_tomo_xy.png]]
#+begin_src matlab :exports none
figure;
ax1 = subplot(3, 1, 1);
hold on;
plot(t, En(:,1), 'DisplayName', '$\epsilon_{x}$')
plot(t, En_iff(:,1), 'DisplayName', '$\epsilon_{x}$ - IFF')
legend('location', 'southwest');
ax2 = subplot(3, 1, 2);
hold on;
plot(t, En(:,2), 'DisplayName', '$\epsilon_{y}$')
plot(t, En_iff(:,2), 'DisplayName', '$\epsilon_{y}$ - IFF')
legend('location', 'southwest');
ylabel('Position Error [m]');
ax3 = subplot(3, 1, 3);
hold on;
plot(t, En(:,3), 'DisplayName', '$\epsilon_{z}$')
plot(t, En_iff(:,3), 'DisplayName', '$\epsilon_{z}$ - IFF')
legend('location', 'northwest');
xlabel('Time [s]');
linkaxes([ax1,ax2,ax3],'x');
xlim([0.5,inf]);
#+end_src
#+HEADER: :tangle no :exports results :results none :noweb yes
#+begin_src matlab :var filepath="figs/nass_act_damp_iff_sim_tomo_trans.pdf" :var figsize="full-tall" :post pdf2svg(file=*this*, ext="png")
<>
#+end_src
#+name: fig:nass_act_damp_iff_sim_tomo_trans
#+caption: Position Error during tomography experiment - Translations ([[./figs/nass_act_damp_iff_sim_tomo_trans.png][png]], [[./figs/nass_act_damp_iff_sim_tomo_trans.pdf][pdf]])
[[file:figs/nass_act_damp_iff_sim_tomo_trans.png]]
#+begin_src matlab :exports none
figure;
ax1 = subplot(3, 1, 1);
hold on;
plot(t, En(:,4), 'DisplayName', '$\epsilon_{\theta_x}$')
plot(t, En_iff(:,4), 'DisplayName', '$\epsilon_{\theta_x}$ - IFF')
legend('location', 'northwest');
ax2 = subplot(3, 1, 2);
hold on;
plot(t, En(:,5), 'DisplayName', '$\epsilon_{\theta_y}$')
plot(t, En_iff(:,5), 'DisplayName', '$\epsilon_{\theta_y}$ - IFF')
legend('location', 'southwest');
ylabel('Position Error [rad]');
ax3 = subplot(3, 1, 3);
hold on;
plot(t, En(:,6), 'DisplayName', '$\epsilon_{\theta_z}$')
plot(t, En_iff(:,6), 'DisplayName', '$\epsilon_{\theta_z}$ - IFF')
legend();
xlabel('Time [s]');
linkaxes([ax1,ax2,ax3],'x');
xlim([0.5,inf]);
#+end_src
#+HEADER: :tangle no :exports results :results none :noweb yes
#+begin_src matlab :var filepath="figs/nass_act_damp_iff_sim_tomo_rot.pdf" :var figsize="full-tall" :post pdf2svg(file=*this*, ext="png")
<>
#+end_src
#+name: fig:nass_act_damp_iff_sim_tomo_rot
#+caption: Position Error during tomography experiment - Rotations ([[./figs/nass_act_damp_iff_sim_tomo_rot.png][png]], [[./figs/nass_act_damp_iff_sim_tomo_rot.pdf][pdf]])
[[file:figs/nass_act_damp_iff_sim_tomo_rot.png]]
** Conclusion
#+begin_important
Integral Force Feedback using a force sensor:
- Robust (guaranteed stability)
- Acceptable Damping
- Increase the sensitivity to disturbances at low frequencies
#+end_important
* Direct Velocity Feedback
:PROPERTIES:
:header-args:matlab+: :tangle matlab/dvf.m
:header-args:matlab+: :comments none :mkdirp yes
:END:
<>
** ZIP file containing the data and matlab files :ignore:
#+begin_src bash :exports none :results none
if [ matlab/dvf.m -nt data/dvf.zip ]; then
cp matlab/dvf.m dvf.m;
zip data/dvf \
mat/plant.mat \
dvf.m
rm dvf.m;
fi
#+end_src
#+begin_note
All the files (data and Matlab scripts) are accessible [[file:data/dvf.zip][here]].
#+end_note
** Introduction :ignore:
In the Direct Velocity Feedback (DVF), a derivative feedback is applied between the measured actuator displacement to the actuator force input.
The actuator displacement can be measured with a capacitive sensor for instance.
** Matlab Init :noexport:ignore:
#+begin_src matlab :tangle no :exports none :results silent :noweb yes :var current_dir=(file-name-directory buffer-file-name)
<>
#+end_src
#+begin_src matlab :exports none :results silent :noweb yes
<>
#+end_src
#+begin_src matlab :tangle no
simulinkproject('../');
#+end_src
#+begin_src matlab
addpath('active_damping/src/');
#+end_src
#+begin_src matlab
open('nass_model.slx')
#+end_src
** Control Design
*** Plant
Let's load the undamped plant:
#+begin_src matlab
load('./active_damping/mat/undamped_plants.mat', 'G_dvf');
load('./active_damping/mat/plants_variable.mat', 'masses', 'Gm_dvf');
#+end_src
Let's look at the transfer function from actuator forces in the nano-hexapod to the measured displacement of the actuator for all 6 pairs of actuator/sensor (figure [[fig:dvf_plant]]).
#+begin_src matlab :exports none
freqs = logspace(0, 3, 1000);
figure;
ax1 = subplot(2, 1, 1);
hold on;
for i=1:length(masses)
plot(freqs, abs(squeeze(freqresp(-Gm_dvf{i}('Dnlm1', 'Fnl1'), freqs, 'Hz'))));
end
hold off;
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
ylabel('Amplitude [m/N]'); set(gca, 'XTickLabel',[]);
ax2 = subplot(2, 1, 2);
hold on;
for i=1:length(masses)
plot(freqs, 180/pi*angle(squeeze(freqresp(-Gm_dvf{i}('Dnlm1', 'Fnl1'), freqs, 'Hz'))), ...
'DisplayName', sprintf('$M = %.0f$ [kg]', masses(i)));
end
hold off;
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'lin');
ylabel('Phase [deg]'); xlabel('Frequency [Hz]');
ylim([-180, 180]);
yticks([-180, -90, 0, 90, 180]);
legend('location', 'southwest');
linkaxes([ax1,ax2],'x');
#+end_src
#+HEADER: :tangle no :exports results :results none :noweb yes
#+begin_src matlab :var filepath="figs/dvf_plant.pdf" :var figsize="full-tall" :post pdf2svg(file=*this*, ext="png")
<>
#+end_src
#+name: fig:dvf_plant
#+caption: Transfer function from forces applied in the legs to leg displacement sensor ([[./figs/dvf_plant.png][png]], [[./figs/dvf_plant.pdf][pdf]])
[[file:figs/dvf_plant.png]]
*** Control Design
The Direct Velocity Feedback is defined below.
A Low pass Filter is added to make the controller transfer function proper.
#+begin_src matlab
K_dvf = s*30000/(1 + s/2/pi/10000);
#+end_src
The obtained loop gains are shown in figure [[fig:dvf_open_loop]].
#+begin_src matlab :exports none
freqs = logspace(0, 3, 1000);
figure;
ax1 = subplot(2, 1, 1);
hold on;
for i=1:length(masses)
plot(freqs, abs(squeeze(freqresp(K_dvf*Gm_dvf{i}('Dnlm1', 'Fnl1'), freqs, 'Hz'))));
end
hold off;
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
ylabel('Loop Gain'); set(gca, 'XTickLabel',[]);
ax2 = subplot(2, 1, 2);
hold on;
for i=1:length(masses)
plot(freqs, 180/pi*angle(squeeze(freqresp(K_dvf*Gm_dvf{i}('Dnlm1', 'Fnl1'), freqs, 'Hz'))), ...
'DisplayName', sprintf('$M = %.0f$ [kg]', masses(i)));
end
hold off;
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'lin');
ylabel('Phase [deg]'); xlabel('Frequency [Hz]');
ylim([-180, 180]);
yticks([-180, -90, 0, 90, 180]);
legend('location', 'southwest');
linkaxes([ax1,ax2],'x');
#+end_src
#+HEADER: :tangle no :exports results :results none :noweb yes
#+begin_src matlab :var filepath="figs/dvf_open_loop.pdf" :var figsize="full-tall" :post pdf2svg(file=*this*, ext="png")
<>
#+end_src
#+name: fig:dvf_open_loop
#+caption: Loop Gain for the Integral Force Feedback ([[./figs/dvf_open_loop.png][png]], [[./figs/dvf_open_loop.pdf][pdf]])
[[file:figs/dvf_open_loop.png]]
*** Diagonal Controller
We create the diagonal controller and we add a minus sign as we have a positive feedback architecture.
#+begin_src matlab
K_dvf = -K_dvf*eye(6);
#+end_src
We save the controller for further analysis.
#+begin_src matlab
save('./active_damping/mat/K_dvf.mat', 'K_dvf');
#+end_src
** Identification of the damped plant :noexport:
*** Identification
We initialize all the stages with the default parameters.
#+begin_src matlab
prepareLinearizeIdentification();
#+end_src
We set the DVF controller.
#+begin_src matlab
load('./active_damping/mat/K_dvf.mat', 'K_dvf');
initializeController('type', 'dvf', 'K', K_dvf);
#+end_src
We identify the dynamics of the system using the =linearize= function.
#+begin_src matlab
%% Options for Linearized
options = linearizeOptions;
options.SampleTime = 0;
%% Name of the Simulink File
mdl = 'nass_model';
%% Input/Output definition
clear io; io_i = 1;
io(io_i) = linio([mdl, '/Controller'], 1, 'openinput'); io_i = io_i + 1; % Actuator Inputs
io(io_i) = linio([mdl, '/Tracking Error'], 1, 'output', [], 'En'); io_i = io_i + 1;
#+end_src
We identify the dynamics for the following sample mass.
#+begin_src matlab
load('./active_damping/mat/cart_plants.mat', 'masses');
#+end_src
#+begin_src matlab :exports none
G_cart_dvf = {zeros(length(masses))};
load('mat/stages.mat', 'nano_hexapod');
for i = 1:length(masses)
initializeSample('mass', masses(i));
%% Run the linearization
G = linearize(mdl, io, 0.3, options);
G.InputName = {'Fnl1', 'Fnl2', 'Fnl3', 'Fnl4', 'Fnl5', 'Fnl6'};
G.OutputName = {'Dnx', 'Dny', 'Dnz', 'Rnx', 'Rny', 'Rnz'};
G_cart = G*inv(nano_hexapod.J');
G_cart.InputName = {'Fnx', 'Fny', 'Fnz', 'Mnx', 'Mny', 'Mnz'};
G_cart_dvf(i) = {G_cart};
end
#+end_src
And we save them for further analysis.
#+begin_src matlab
save('./active_damping/mat/cart_plants.mat', 'G_cart_dvf', '-append');
#+end_src
*** Damped Plant
Now, look at the new damped plant to control.
#+begin_src matlab
load('./active_damping/mat/cart_plants.mat', 'masses', 'G_cart', 'G_cart_dvf');
#+end_src
It damps the plant (resonance of the nano hexapod as well as other resonances) as shown in figure [[fig:plant_dvf_damped]].
#+begin_src matlab :exports none
freqs = logspace(0, 3, 1000);
figure;
ax1 = subplot(2, 1, 1);
hold on;
for i = 1:length(masses)
set(gca,'ColorOrderIndex',i);
p1 = plot(freqs, abs(squeeze(freqresp(G_cart_dvf{i}('Dnx', 'Fnx'), freqs, 'Hz'))));
set(gca,'ColorOrderIndex',i);
p2 = plot(freqs, abs(squeeze(freqresp(G_cart_dvf{i}('Dny', 'Fny'), freqs, 'Hz'))), '--');
set(gca,'ColorOrderIndex',i);
p3 = plot(freqs, abs(squeeze(freqresp(G_cart_dvf{i}('Dnz', 'Fnz'), freqs, 'Hz'))), ':');
end
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
ylabel('Amplitude [m/N]'); xlabel('Frequency [Hz]');
legend([p1,p2,p3], {'Fx/Dx', 'Fy/Dx', 'Fz/Dz'});
ax2 = subplot(2, 1, 2);
hold on;
for i = 1:length(masses)
set(gca,'ColorOrderIndex',i);
plot(freqs, 180/pi*unwrap(angle(squeeze(freqresp(G_cart_dvf{i}('Dnx', 'Fnx'), freqs, 'Hz')))), ...
'DisplayName', sprintf('$M = %.0f$ [kg]', masses(i)));
set(gca,'ColorOrderIndex',i);
plot(freqs, 180/pi*unwrap(angle(squeeze(freqresp(G_cart_dvf{i}('Dny', 'Fny'), freqs, 'Hz')))), '--', 'HandleVisibility', 'off');
set(gca,'ColorOrderIndex',i);
plot(freqs, 180/pi*unwrap(angle(squeeze(freqresp(G_cart_dvf{i}('Dnz', 'Fnz'), freqs, 'Hz')))), ':', 'HandleVisibility', 'off');
end
hold off;
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'lin');
ylabel('Phase [deg]'); xlabel('Frequency [Hz]');
yticks([-540:180:540]);
legend('location', 'northeast');
linkaxes([ax1,ax2],'x');
#+end_src
#+HEADER: :tangle no :exports results :results none :noweb yes
#+begin_src matlab :var filepath="figs/plant_dvf_damped_translations.pdf" :var figsize="full-tall" :post pdf2svg(file=*this*, ext="png")
<>
#+end_src
#+name: fig:plant_dvf_damped_translations
#+caption: Damped Plant for the translations after DVF is applied ([[./figs/plant_dvf_damped_translations.png][png]], [[./figs/plant_dvf_damped_translations.pdf][pdf]])
[[file:figs/plant_dvf_damped_translations.png]]
#+begin_src matlab :exports none
freqs = logspace(0, 3, 1000);
figure;
ax1 = subplot(2, 1, 1);
hold on;
for i = 1:length(masses)
set(gca,'ColorOrderIndex',i);
p1 = plot(freqs, abs(squeeze(freqresp(G_cart_dvf{i}('Rnx', 'Mnx'), freqs, 'Hz'))));
set(gca,'ColorOrderIndex',i);
p2 = plot(freqs, abs(squeeze(freqresp(G_cart_dvf{i}('Rny', 'Mny'), freqs, 'Hz'))), '--');
set(gca,'ColorOrderIndex',i);
p3 = plot(freqs, abs(squeeze(freqresp(G_cart_dvf{i}('Rnz', 'Mnz'), freqs, 'Hz'))), ':');
end
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
ylabel('Amplitude [m/N]'); xlabel('Frequency [Hz]');
legend([p1,p2,p3], {'Fx/Dx', 'Fy/Dx', 'Fz/Dz'});
ax2 = subplot(2, 1, 2);
hold on;
for i = 1:length(masses)
set(gca,'ColorOrderIndex',i);
plot(freqs, 180/pi*unwrap(angle(squeeze(freqresp(G_cart_dvf{i}('Rnx', 'Mnx'), freqs, 'Hz')))), ...
'DisplayName', sprintf('$M = %.0f$ [kg]', masses(i)));
set(gca,'ColorOrderIndex',i);
plot(freqs, 180/pi*unwrap(angle(squeeze(freqresp(G_cart_dvf{i}('Rny', 'Mny'), freqs, 'Hz')))), '--', 'HandleVisibility', 'off');
set(gca,'ColorOrderIndex',i);
plot(freqs, 180/pi*unwrap(angle(squeeze(freqresp(G_cart_dvf{i}('Rnz', 'Mnz'), freqs, 'Hz')))), ':', 'HandleVisibility', 'off');
end
hold off;
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'lin');
ylabel('Phase [deg]'); xlabel('Frequency [Hz]');
yticks([-540:180:540]);
legend('location', 'northeast');
linkaxes([ax1,ax2],'x');
#+end_src
#+HEADER: :tangle no :exports results :results none :noweb yes
#+begin_src matlab :var filepath="figs/plant_dvf_damped_rotations.pdf" :var figsize="full-tall" :post pdf2svg(file=*this*, ext="png")
<>
#+end_src
#+name: fig:plant_dvf_damped_rotations
#+caption: Damped Plant for the Rotations after DVF is applied ([[./figs/plant_dvf_damped_rotations.png][png]], [[./figs/plant_dvf_damped_rotations.pdf][pdf]])
[[file:figs/plant_dvf_damped_rotations.png]]
However, it does not change the 6x6 plant away from the resonances (figure [[fig:plant_dvf_coupling]]).
#+begin_src matlab :exports none
freqs = logspace(1, 3, 1000);
figure;
for ix = 1:6
for iy = 1:6
subplot(6, 6, (ix-1)*6 + iy);
hold on;
plot(freqs, abs(squeeze(freqresp(G_cart{1}(ix, iy), freqs, 'Hz'))), 'k-');
plot(freqs, abs(squeeze(freqresp(G_cart_dvf{1}(ix, iy), freqs, 'Hz'))), 'k--');
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
ylim([1e-13, 1e-4]);
xticks([])
yticks([])
end
end
#+end_src
#+HEADER: :tangle no :exports results :results none :noweb yes
#+begin_src matlab :var filepath="figs/plant_dvf_coupling.pdf" :var figsize="full-tall" :post pdf2svg(file=*this*, ext="png")
<>
#+end_src
#+name: fig:plant_dvf_coupling
#+caption: Coupling induced by DVF actuative damping technique ([[./figs/plant_dvf_coupling.png][png]], [[./figs/plant_dvf_coupling.pdf][pdf]])
[[file:figs/plant_dvf_coupling.png]]
** Tomography Experiment
*** Initialize the Simulation
We initialize elements for the tomography experiment.
#+begin_src matlab
prepareTomographyExperiment();
#+end_src
We set the DVF controller.
#+begin_src matlab
load('./active_damping/mat/K_dvf.mat', 'K_dvf');
initializeController('type', 'dvf', 'K', K_dvf);
#+end_src
We change the simulation stop time.
#+begin_src matlab
load('mat/conf_simulink.mat');
set_param(conf_simulink, 'StopTime', '4.5');
#+end_src
And we simulate the system.
#+begin_src matlab
sim('nass_model');
#+end_src
Finally, we save the simulation results for further analysis
#+begin_src matlab
En_dvf = En;
Eg_dvf = Eg;
save('./active_damping/mat/tomo_exp.mat', 'En_dvf', 'Eg_dvf', '-append');
#+end_src
*** Compare with Undamped system
#+begin_src matlab :exports none
load('./active_damping/mat/tomo_exp.mat', 'En', 'En_dvf');
Fs = 1e3; % Sampling Frequency of the Data
t = (1/Fs)*[0:length(En(:,1))-1];
#+end_src
#+begin_src matlab :exports none
figure;
hold on;
plot(En(:,1), En(:,2), 'DisplayName', '$\epsilon_{x,y}$ - OL')
plot(En_dvf(:,1), En_dvf(:,2), 'DisplayName', '$\epsilon_{x,y}$ - DVF')
xlabel('X Motion [m]'); ylabel('Y Motion [m]');
legend();
#+end_src
#+HEADER: :tangle no :exports results :results none :noweb yes
#+begin_src matlab :var filepath="figs/nass_act_damp_dvf_sim_tomo_xy.pdf" :var figsize="small-normal" :post pdf2svg(file=*this*, ext="png")
<>
#+end_src
#+name: fig:nass_act_damp_dvf_sim_tomo_xy
#+caption: Position Error during tomography experiment - XY Motion ([[./figs/nass_act_damp_dvf_sim_tomo_xy.png][png]], [[./figs/nass_act_damp_dvf_sim_tomo_xy.pdf][pdf]])
[[file:figs/nass_act_damp_dvf_sim_tomo_xy.png]]
#+begin_src matlab :exports none
figure;
ax1 = subplot(3, 1, 1);
hold on;
plot(t, En(:,1), 'DisplayName', '$\epsilon_{x}$')
plot(t, En_dvf(:,1), 'DisplayName', '$\epsilon_{x}$ - DVF')
legend();
ax2 = subplot(3, 1, 2);
hold on;
plot(t, En(:,2), 'DisplayName', '$\epsilon_{y}$')
plot(t, En_dvf(:,2), 'DisplayName', '$\epsilon_{y}$ - DVF')
legend();
ylabel('Position Error [m]');
ax3 = subplot(3, 1, 3);
hold on;
plot(t, En(:,3), 'DisplayName', '$\epsilon_{z}$')
plot(t, En_dvf(:,3), 'DisplayName', '$\epsilon_{z}$ - DVF')
legend();
xlabel('Time [s]');
linkaxes([ax1,ax2,ax3],'x');
xlim([0.5,inf]);
#+end_src
#+HEADER: :tangle no :exports results :results none :noweb yes
#+begin_src matlab :var filepath="figs/nass_act_damp_dvf_sim_tomo_trans.pdf" :var figsize="full-tall" :post pdf2svg(file=*this*, ext="png")
<>
#+end_src
#+name: fig:nass_act_damp_dvf_sim_tomo_trans
#+caption: Position Error during tomography experiment - Translations ([[./figs/nass_act_damp_dvf_sim_tomo_trans.png][png]], [[./figs/nass_act_damp_dvf_sim_tomo_trans.pdf][pdf]])
[[file:figs/nass_act_damp_dvf_sim_tomo_trans.png]]
#+begin_src matlab :exports none
figure;
ax1 = subplot(3, 1, 1);
hold on;
plot(t, En(:,4), 'DisplayName', '$\epsilon_{\theta_x}$')
plot(t, En_dvf(:,4), 'DisplayName', '$\epsilon_{\theta_x}$ - DVF')
legend();
ax2 = subplot(3, 1, 2);
hold on;
plot(t, En(:,5), 'DisplayName', '$\epsilon_{\theta_y}$')
plot(t, En_dvf(:,5), 'DisplayName', '$\epsilon_{\theta_y}$ - DVF')
legend();
ylabel('Position Error [rad]');
ax3 = subplot(3, 1, 3);
hold on;
plot(t, En(:,6), 'DisplayName', '$\epsilon_{\theta_z}$')
plot(t, En_dvf(:,6), 'DisplayName', '$\epsilon_{\theta_z}$ - DVF')
legend();
xlabel('Time [s]');
linkaxes([ax1,ax2,ax3],'x');
xlim([0.5,inf]);
#+end_src
#+HEADER: :tangle no :exports results :results none :noweb yes
#+begin_src matlab :var filepath="figs/nass_act_damp_dvf_sim_tomo_rot.pdf" :var figsize="full-tall" :post pdf2svg(file=*this*, ext="png")
<>
#+end_src
#+name: fig:nass_act_damp_dvf_sim_tomo_rot
#+caption: Position Error during tomography experiment - Rotations ([[./figs/nass_act_damp_dvf_sim_tomo_rot.png][png]], [[./figs/nass_act_damp_dvf_sim_tomo_rot.pdf][pdf]])
[[file:figs/nass_act_damp_dvf_sim_tomo_rot.png]]
** Conclusion
#+begin_important
Direct Velocity Feedback using a relative motion sensor:
- Robust (guaranteed stability)
#+end_important
* Inertial Control
:PROPERTIES:
:header-args:matlab+: :tangle matlab/ine.m
:header-args:matlab+: :comments none :mkdirp yes
:END:
<>
** ZIP file containing the data and matlab files :ignore:
#+begin_src bash :exports none :results none
if [ matlab/ine.m -nt data/ine.zip ]; then
cp matlab/ine.m ine.m;
zip data/ine \
mat/plant.mat \
ine.m
rm ine.m;
fi
#+end_src
#+begin_note
All the files (data and Matlab scripts) are accessible [[file:data/ine.zip][here]].
#+end_note
** Introduction :ignore:
In Inertial Control, a feedback is applied between the measured *absolute* motion (velocity or acceleration) of the platform to the actuator force input.
** Matlab Init :noexport:ignore:
#+begin_src matlab :tangle no :exports none :results silent :noweb yes :var current_dir=(file-name-directory buffer-file-name)
<>
#+end_src
#+begin_src matlab :exports none :results silent :noweb yes
<>
#+end_src
#+begin_src matlab :tangle no
simulinkproject('../');
#+end_src
#+begin_src matlab
addpath('active_damping/src/');
#+end_src
#+begin_src matlab
open('nass_model.slx')
#+end_src
** Control Design
*** Plant
Let's load the undamped plant:
#+begin_src matlab
load('./active_damping/mat/undamped_plants.mat', 'G_ine');
load('./active_damping/mat/plants_variable.mat', 'masses', 'Gm_ine');
#+end_src
Let's look at the transfer function from actuator forces in the nano-hexapod to the measured velocity of the nano-hexapod platform in the direction of the corresponding actuator for all 6 pairs of actuator/sensor (figure [[fig:ine_plant]]).
#+begin_src matlab :exports none
freqs = logspace(0, 3, 1000);
figure;
ax1 = subplot(2, 1, 1);
hold on;
for i=1:length(masses)
plot(freqs, abs(squeeze(freqresp(Gm_ine{i}('Vnlm1', 'Fnl1'), freqs, 'Hz'))));
end
hold off;
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
ylabel('Amplitude [(m/s)/N]'); set(gca, 'XTickLabel',[]);
ax2 = subplot(2, 1, 2);
hold on;
for i=1:length(masses)
plot(freqs, 180/pi*angle(squeeze(freqresp(Gm_ine{i}('Vnlm1', 'Fnl1'), freqs, 'Hz'))), ...
'DisplayName', sprintf('$M = %.0f$ [kg]', masses(i)));
end
hold off;
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'lin');
ylabel('Phase [deg]'); xlabel('Frequency [Hz]');
ylim([-180, 180]);
yticks([-180, -90, 0, 90, 180]);
legend('location', 'southwest');
linkaxes([ax1,ax2],'x');
#+end_src
#+HEADER: :tangle no :exports results :results none :noweb yes
#+begin_src matlab :var filepath="figs/ine_plant.pdf" :var figsize="full-tall" :post pdf2svg(file=*this*, ext="png")
<>
#+end_src
#+name: fig:ine_plant
#+caption: Transfer function from forces applied in the legs to leg velocity sensor ([[./figs/ine_plant.png][png]], [[./figs/ine_plant.pdf][pdf]])
[[file:figs/ine_plant.png]]
*** Control Design
The controller is defined below and the obtained loop gain is shown in figure [[fig:ine_open_loop_gain]].
#+begin_src matlab
K_ine = 2.5e4;
#+end_src
#+begin_src matlab :exports none
freqs = logspace(0, 3, 1000);
figure;
ax1 = subplot(2, 1, 1);
hold on;
for i=1:length(masses)
plot(freqs, abs(squeeze(freqresp(K_ine*Gm_ine{i}('Vnlm1', 'Fnl1'), freqs, 'Hz'))));
end
hold off;
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
ylabel('Loop Gain'); set(gca, 'XTickLabel',[]);
ax2 = subplot(2, 1, 2);
hold on;
for i=1:length(masses)
plot(freqs, 180/pi*angle(squeeze(freqresp(K_ine*Gm_ine{i}('Vnlm1', 'Fnl1'), freqs, 'Hz'))), ...
'DisplayName', sprintf('$M = %.0f$ [kg]', masses(i)));
end
hold off;
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'lin');
ylabel('Phase [deg]'); xlabel('Frequency [Hz]');
ylim([-180, 180]);
yticks([-180, -90, 0, 90, 180]);
legend('location', 'southwest');
linkaxes([ax1,ax2],'x');
#+end_src
#+HEADER: :tangle no :exports results :results none :noweb yes
#+begin_src matlab :var filepath="figs/ine_open_loop_gain.pdf" :var figsize="full-tall" :post pdf2svg(file=*this*, ext="png")
<>
#+end_src
#+name: fig:ine_open_loop_gain
#+caption: Loop Gain for Inertial Control ([[./figs/ine_open_loop_gain.png][png]], [[./figs/ine_open_loop_gain.pdf][pdf]])
[[file:figs/ine_open_loop_gain.png]]
*** Diagonal Controller
We create the diagonal controller and we add a minus sign as we have a positive feedback architecture.
#+begin_src matlab
K_ine = -K_ine*eye(6);
#+end_src
We save the controller for further analysis.
#+begin_src matlab
save('./active_damping/mat/K_ine.mat', 'K_ine');
#+end_src
** Identification of the damped plant :noexport:
*** Identification
We initialize all the stages with the default parameters.
#+begin_src matlab
prepareLinearizeIdentification();
#+end_src
We set the Inertial controller.
#+begin_src matlab
load('./active_damping/mat/K_ine.mat', 'K_ine');
initializeController('type', 'ine', 'K', K_ine);
#+end_src
We identify the dynamics of the system using the =linearize= function.
#+begin_src matlab
%% Options for Linearized
options = linearizeOptions;
options.SampleTime = 0;
%% Name of the Simulink File
mdl = 'nass_model';
%% Input/Output definition
clear io; io_i = 1;
io(io_i) = linio([mdl, '/Controller'], 1, 'openinput'); io_i = io_i + 1; % Actuator Inputs
io(io_i) = linio([mdl, '/Tracking Error'], 1, 'output', [], 'En'); io_i = io_i + 1;
#+end_src
We identify the dynamics for the following sample mass.
#+begin_src matlab
load('./active_damping/mat/cart_plants.mat', 'masses');
#+end_src
#+begin_src matlab :exports none
G_cart_ine = {zeros(length(masses))};
load('mat/stages.mat', 'nano_hexapod');
for i = 1:length(masses)
initializeSample('mass', masses(i));
%% Run the linearization
G = linearize(mdl, io, 0.3, options);
G.InputName = {'Fnl1', 'Fnl2', 'Fnl3', 'Fnl4', 'Fnl5', 'Fnl6'};
G.OutputName = {'Dnx', 'Dny', 'Dnz', 'Rnx', 'Rny', 'Rnz'};
G_cart = G*inv(nano_hexapod.J');
G_cart.InputName = {'Fnx', 'Fny', 'Fnz', 'Mnx', 'Mny', 'Mnz'};
G_cart_ine(i) = {G_cart};
end
#+end_src
And we save them for further analysis.
#+begin_src matlab
save('./active_damping/mat/cart_plants.mat', 'G_cart_dvf', '-append');
#+end_src
*** Damped Plant
Now, look at the new damped plant to control.
#+begin_src matlab
load('./active_damping/mat/cart_plants.mat', 'masses', 'G_cart', 'G_cart_ine');
#+end_src
It damps the plant (resonance of the nano hexapod as well as other resonances) as shown in figure [[fig:plant_ine_damped]].
#+begin_src matlab :exports none
freqs = logspace(0, 3, 1000);
figure;
ax1 = subplot(2, 1, 1);
hold on;
for i = 1:length(masses)
set(gca,'ColorOrderIndex',i);
p1 = plot(freqs, abs(squeeze(freqresp(G_cart_ine{i}('Dnx', 'Fnx'), freqs, 'Hz'))));
set(gca,'ColorOrderIndex',i);
p2 = plot(freqs, abs(squeeze(freqresp(G_cart_ine{i}('Dny', 'Fny'), freqs, 'Hz'))), '--');
set(gca,'ColorOrderIndex',i);
p3 = plot(freqs, abs(squeeze(freqresp(G_cart_ine{i}('Dnz', 'Fnz'), freqs, 'Hz'))), ':');
end
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
ylabel('Amplitude [m/N]'); xlabel('Frequency [Hz]');
legend([p1,p2,p3], {'Fx/Dx', 'Fy/Dx', 'Fz/Dz'});
ax2 = subplot(2, 1, 2);
hold on;
for i = 1:length(masses)
set(gca,'ColorOrderIndex',i);
plot(freqs, 180/pi*unwrap(angle(squeeze(freqresp(G_cart_ine{i}('Dnx', 'Fnx'), freqs, 'Hz')))), ...
'DisplayName', sprintf('$M = %.0f$ [kg]', masses(i)));
set(gca,'ColorOrderIndex',i);
plot(freqs, 180/pi*unwrap(angle(squeeze(freqresp(G_cart_ine{i}('Dny', 'Fny'), freqs, 'Hz')))), '--', 'HandleVisibility', 'off');
set(gca,'ColorOrderIndex',i);
plot(freqs, 180/pi*unwrap(angle(squeeze(freqresp(G_cart_ine{i}('Dnz', 'Fnz'), freqs, 'Hz')))), ':', 'HandleVisibility', 'off');
end
hold off;
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'lin');
ylabel('Phase [deg]'); xlabel('Frequency [Hz]');
yticks([-540:180:540]);
legend('location', 'northeast');
linkaxes([ax1,ax2],'x');
#+end_src
#+HEADER: :tangle no :exports results :results none :noweb yes
#+begin_src matlab :var filepath="figs/plant_ine_damped_translations.pdf" :var figsize="full-tall" :post pdf2svg(file=*this*, ext="png")
<>
#+end_src
#+name: fig:plant_ine_damped_translations
#+caption: Damped Plant for the translations after INE is applied ([[./figs/plant_ine_damped_translations.png][png]], [[./figs/plant_ine_damped_translations.pdf][pdf]])
[[file:figs/plant_ine_damped_translations.png]]
#+begin_src matlab :exports none
freqs = logspace(0, 3, 1000);
figure;
ax1 = subplot(2, 1, 1);
hold on;
for i = 1:length(masses)
set(gca,'ColorOrderIndex',i);
p1 = plot(freqs, abs(squeeze(freqresp(G_cart_ine{i}('Rnx', 'Mnx'), freqs, 'Hz'))));
set(gca,'ColorOrderIndex',i);
p2 = plot(freqs, abs(squeeze(freqresp(G_cart_ine{i}('Rny', 'Mny'), freqs, 'Hz'))), '--');
set(gca,'ColorOrderIndex',i);
p3 = plot(freqs, abs(squeeze(freqresp(G_cart_ine{i}('Rnz', 'Mnz'), freqs, 'Hz'))), ':');
end
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
ylabel('Amplitude [m/N]'); xlabel('Frequency [Hz]');
legend([p1,p2,p3], {'Fx/Dx', 'Fy/Dx', 'Fz/Dz'});
ax2 = subplot(2, 1, 2);
hold on;
for i = 1:length(masses)
set(gca,'ColorOrderIndex',i);
plot(freqs, 180/pi*unwrap(angle(squeeze(freqresp(G_cart_ine{i}('Rnx', 'Mnx'), freqs, 'Hz')))), ...
'DisplayName', sprintf('$M = %.0f$ [kg]', masses(i)));
set(gca,'ColorOrderIndex',i);
plot(freqs, 180/pi*unwrap(angle(squeeze(freqresp(G_cart_ine{i}('Rny', 'Mny'), freqs, 'Hz')))), '--', 'HandleVisibility', 'off');
set(gca,'ColorOrderIndex',i);
plot(freqs, 180/pi*unwrap(angle(squeeze(freqresp(G_cart_ine{i}('Rnz', 'Mnz'), freqs, 'Hz')))), ':', 'HandleVisibility', 'off');
end
hold off;
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'lin');
ylabel('Phase [deg]'); xlabel('Frequency [Hz]');
yticks([-540:180:540]);
legend('location', 'northeast');
linkaxes([ax1,ax2],'x');
#+end_src
#+HEADER: :tangle no :exports results :results none :noweb yes
#+begin_src matlab :var filepath="figs/plant_ine_damped_rotations.pdf" :var figsize="full-tall" :post pdf2svg(file=*this*, ext="png")
<>
#+end_src
#+name: fig:plant_ine_damped_rotations
#+caption: Damped Plant for the Rotations after INE is applied ([[./figs/plant_ine_damped_rotations.png][png]], [[./figs/plant_ine_damped_rotations.pdf][pdf]])
[[file:figs/plant_ine_damped_rotations.png]]
#+begin_src matlab :exports none
freqs = logspace(1, 3, 1000);
figure;
for ix = 1:6
for iy = 1:6
subplot(6, 6, (ix-1)*6 + iy);
hold on;
plot(freqs, abs(squeeze(freqresp(G_cart{1}(ix, iy), freqs, 'Hz'))), 'k-');
plot(freqs, abs(squeeze(freqresp(G_cart_ine{1}(ix, iy), freqs, 'Hz'))), 'k--');
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
ylim([1e-13, 1e-4]);
xticks([])
yticks([])
end
end
#+end_src
#+HEADER: :tangle no :exports results :results none :noweb yes
#+begin_src matlab :var filepath="figs/plant_ine_coupling.pdf" :var figsize="full-tall" :post pdf2svg(file=*this*, ext="png")
<>
#+end_src
#+name: fig:plant_ine_coupling
#+caption: Coupling induced by INE ([[./figs/plant_ine_coupling.png][png]], [[./figs/plant_ine_coupling.pdf][pdf]])
[[file:figs/plant_ine_coupling.png]]
** Conclusion
#+begin_important
Inertial Control should not be used.
#+end_important
* TODO Comparison
<>
** Introduction :ignore:
** Matlab Init :noexport:ignore:
#+begin_src matlab :tangle no :exports none :results silent :noweb yes :var current_dir=(file-name-directory buffer-file-name)
<>
#+end_src
#+begin_src matlab :exports none :results silent :noweb yes
<>
#+end_src
#+begin_src matlab
cd('../');
#+end_src
** Load the plants
#+begin_src matlab
load('./active_damping/mat/plants.mat', 'G', 'G_iff', 'G_ine', 'G_dvf');
#+end_src
** TODO Sensitivity to Disturbance
#+begin_src matlab :exports none
freqs = logspace(0, 3, 1000);
figure;
title('$D_{g,z}$ to $D_z$');
hold on;
plot(freqs, abs(squeeze(freqresp(G.G_gm( 'Dz', 'Dgz'), freqs, 'Hz'))), 'k-' , 'DisplayName', 'Undamped');
plot(freqs, abs(squeeze(freqresp(G_iff.G_gm('Dz', 'Dgz'), freqs, 'Hz'))), 'k:' , 'DisplayName', 'IFF');
plot(freqs, abs(squeeze(freqresp(G_ine.G_gm('Dz', 'Dgz'), freqs, 'Hz'))), 'k--', 'DisplayName', 'INE');
plot(freqs, abs(squeeze(freqresp(G_dvf.G_gm('Dz', 'Dgz'), freqs, 'Hz'))), 'k-.', 'DisplayName', 'DVF');
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
ylabel('Amplitude [m/m]'); xlabel('Frequency [Hz]');
legend('location', 'northeast');
#+end_src
#+HEADER: :tangle no :exports results :results none :noweb yes
#+begin_src matlab :var filepath="figs/sensitivity_comp_ground_motion_z.pdf" :var figsize="full-tall" :post pdf2svg(file=*this*, ext="png")
<>
#+end_src
#+name: fig:sensitivity_comp_ground_motion_z
#+caption: Sensitivity to ground motion in the Z direction on the Z motion error ([[./figs/sensitivity_comp_ground_motion_z.png][png]], [[./figs/sensitivity_comp_ground_motion_z.pdf][pdf]])
[[file:figs/sensitivity_comp_ground_motion_z.png]]
#+begin_src matlab :exports none
freqs = logspace(0, 3, 1000);
figure;
title('$F_{s,z}$ to $D_z$');
hold on;
plot(freqs, abs(squeeze(freqresp(G.G_fs( 'Dz', 'Fsz'), freqs, 'Hz'))), 'k-' , 'DisplayName', 'Undamped');
plot(freqs, abs(squeeze(freqresp(G_iff.G_fs('Dz', 'Fsz'), freqs, 'Hz'))), 'k:' , 'DisplayName', 'IFF');
plot(freqs, abs(squeeze(freqresp(G_ine.G_fs('Dz', 'Fsz'), freqs, 'Hz'))), 'k--', 'DisplayName', 'INE');
plot(freqs, abs(squeeze(freqresp(G_dvf.G_fs('Dz', 'Fsz'), freqs, 'Hz'))), 'k-.', 'DisplayName', 'DVF');
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
ylabel('Amplitude [m/N]'); xlabel('Frequency [Hz]');
legend('location', 'northeast');
#+end_src
#+HEADER: :tangle no :exports results :results none :noweb yes
#+begin_src matlab :var filepath="figs/sensitivity_comp_direct_forces_z.pdf" :var figsize="full-tall" :post pdf2svg(file=*this*, ext="png")
<>
#+end_src
#+name: fig:sensitivity_comp_direct_forces_z
#+caption: Compliance in the Z direction: Sensitivity of direct forces applied on the sample in the Z direction on the Z motion error ([[./figs/sensitivity_comp_direct_forces_z.png][png]], [[./figs/sensitivity_comp_direct_forces_z.pdf][pdf]])
[[file:figs/sensitivity_comp_direct_forces_z.png]]
#+begin_src matlab :exports none
freqs = logspace(0, 3, 1000);
figure;
title('$F_{rz,z}$ to $D_z$');
hold on;
plot(freqs, abs(squeeze(freqresp(G.G_dist( 'Dz', 'Frzz'), freqs, 'Hz'))), 'k-' , 'DisplayName', 'Undamped');
plot(freqs, abs(squeeze(freqresp(G_iff.G_dist('Dz', 'Frzz'), freqs, 'Hz'))), 'k:' , 'DisplayName', 'IFF');
plot(freqs, abs(squeeze(freqresp(G_ine.G_dist('Dz', 'Frzz'), freqs, 'Hz'))), 'k--', 'DisplayName', 'INE');
plot(freqs, abs(squeeze(freqresp(G_dvf.G_dist('Dz', 'Frzz'), freqs, 'Hz'))), 'k-.', 'DisplayName', 'DVF');
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
ylabel('Amplitude [m/N]'); xlabel('Frequency [Hz]');
legend('location', 'northeast');
#+end_src
#+HEADER: :tangle no :exports results :results none :noweb yes
#+begin_src matlab :var filepath="figs/sensitivity_comp_spindle_z.pdf" :var figsize="full-tall" :post pdf2svg(file=*this*, ext="png")
<>
#+end_src
#+name: fig:sensitivity_comp_spindle_z
#+caption: Sensitivity to forces applied in the Z direction by the Spindle on the Z motion error ([[./figs/sensitivity_comp_spindle_z.png][png]], [[./figs/sensitivity_comp_spindle_z.pdf][pdf]])
[[file:figs/sensitivity_comp_spindle_z.png]]
#+begin_src matlab :exports none
freqs = logspace(0, 3, 1000);
figure;
title('$F_{ty,z}$ to $D_z$');
hold on;
plot(freqs, abs(squeeze(freqresp(G.G_dist( 'Dz', 'Ftyz'), freqs, 'Hz'))), 'k-' , 'DisplayName', 'Undamped');
plot(freqs, abs(squeeze(freqresp(G_iff.G_dist('Dz', 'Ftyz'), freqs, 'Hz'))), 'k:' , 'DisplayName', 'IFF');
plot(freqs, abs(squeeze(freqresp(G_ine.G_dist('Dz', 'Ftyz'), freqs, 'Hz'))), 'k--', 'DisplayName', 'INE');
plot(freqs, abs(squeeze(freqresp(G_dvf.G_dist('Dz', 'Ftyz'), freqs, 'Hz'))), 'k-.', 'DisplayName', 'DVF');
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
ylabel('Amplitude [m/N]'); xlabel('Frequency [Hz]');
legend('location', 'northeast');
#+end_src
#+HEADER: :tangle no :exports results :results none :noweb yes
#+begin_src matlab :var filepath="figs/sensitivity_comp_ty_z.pdf" :var figsize="full-tall" :post pdf2svg(file=*this*, ext="png")
<>
#+end_src
#+name: fig:sensitivity_comp_ty_z
#+caption: Sensitivity to forces applied in the Z direction by the Y translation stage on the Z motion error ([[./figs/sensitivity_comp_ty_z.png][png]], [[./figs/sensitivity_comp_ty_z.pdf][pdf]])
[[file:figs/sensitivity_comp_ty_z.png]]
#+begin_src matlab :exports none
freqs = logspace(0, 3, 1000);
figure;
title('$F_{ty,x}$ to $D_x$');
hold on;
plot(freqs, abs(squeeze(freqresp(G.G_dist( 'Dx', 'Ftyx'), freqs, 'Hz'))), 'k-' , 'DisplayName', 'Undamped');
plot(freqs, abs(squeeze(freqresp(G_iff.G_dist('Dx', 'Ftyx'), freqs, 'Hz'))), 'k:' , 'DisplayName', 'IFF');
plot(freqs, abs(squeeze(freqresp(G_ine.G_dist('Dx', 'Ftyx'), freqs, 'Hz'))), 'k--', 'DisplayName', 'INE');
plot(freqs, abs(squeeze(freqresp(G_dvf.G_dist('Dx', 'Ftyx'), freqs, 'Hz'))), 'k-.', 'DisplayName', 'DVF');
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
ylabel('Amplitude [m/N]'); xlabel('Frequency [Hz]');
legend('location', 'northeast');
#+end_src
#+HEADER: :tangle no :exports results :results none :noweb yes
#+begin_src matlab :var filepath="figs/sensitivity_comp_ty_x.pdf" :var figsize="full-tall" :post pdf2svg(file=*this*, ext="png")
<>
#+end_src
#+name: fig:sensitivity_comp_ty_x
#+caption: Sensitivity to forces applied in the X direction by the Y translation stage on the X motion error ([[./figs/sensitivity_comp_ty_x.png][png]], [[./figs/sensitivity_comp_ty_x.pdf][pdf]])
[[file:figs/sensitivity_comp_ty_x.png]]
** TODO Damped Plant
#+begin_src matlab :exports none
freqs = logspace(0, 3, 1000);
figure;
title('$F_{n,z}$ to $D_z$');
ax1 = subplot(2, 1, 1);
hold on;
plot(freqs, abs(squeeze(freqresp(G.G_cart( 'Dz', 'Fnz'), freqs, 'Hz'))), 'k-' , 'DisplayName', 'Undamped');
plot(freqs, abs(squeeze(freqresp(G_iff.G_cart('Dz', 'Fnz'), freqs, 'Hz'))), 'k:' , 'DisplayName', 'IFF');
plot(freqs, abs(squeeze(freqresp(G_ine.G_cart('Dz', 'Fnz'), freqs, 'Hz'))), 'k--', 'DisplayName', 'INE');
plot(freqs, abs(squeeze(freqresp(G_dvf.G_cart('Dz', 'Fnz'), freqs, 'Hz'))), 'k-.', 'DisplayName', 'DVF');
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
ylabel('Amplitude [m/N]'); set(gca, 'XTickLabel',[]);
legend('location', 'northeast');
ax2 = subplot(2, 1, 2);
hold on;
plot(freqs, 180/pi*angle(squeeze(freqresp(G.G_cart ('Dz', 'Fnz'), freqs, 'Hz'))), 'k-');
plot(freqs, 180/pi*angle(squeeze(freqresp(G_iff.G_cart('Dz', 'Fnz'), freqs, 'Hz'))), 'k:');
plot(freqs, 180/pi*angle(squeeze(freqresp(G_ine.G_cart('Dz', 'Fnz'), freqs, 'Hz'))), 'k--');
plot(freqs, 180/pi*angle(squeeze(freqresp(G_dvf.G_cart('Dz', 'Fnz'), freqs, 'Hz'))), 'k-.');
hold off;
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'lin');
ylabel('Phase [deg]'); xlabel('Frequency [Hz]');
ylim([-180, 180]);
yticks([-180, -90, 0, 90, 180]);
linkaxes([ax1,ax2],'x');
#+end_src
#+HEADER: :tangle no :exports results :results none :noweb yes
#+begin_src matlab :var filepath="figs/plant_comp_damping_z.pdf" :var figsize="full-tall" :post pdf2svg(file=*this*, ext="png")
<>
#+end_src
#+name: fig:plant_comp_damping_z
#+caption: Plant for the $z$ direction for different active damping technique used ([[./figs/plant_comp_damping_z.png][png]], [[./figs/plant_comp_damping_z.pdf][pdf]])
[[file:figs/plant_comp_damping_z.png]]
#+begin_src matlab :exports none
freqs = logspace(0, 3, 1000);
figure;
title('$F_{n,z}$ to $D_z$');
ax1 = subplot(2, 1, 1);
hold on;
plot(freqs, abs(squeeze(freqresp(G.G_cart( 'Dx', 'Fnx'), freqs, 'Hz'))), 'k-' , 'DisplayName', 'Undamped');
plot(freqs, abs(squeeze(freqresp(G_iff.G_cart('Dx', 'Fnx'), freqs, 'Hz'))), 'k:' , 'DisplayName', 'IFF');
plot(freqs, abs(squeeze(freqresp(G_ine.G_cart('Dx', 'Fnx'), freqs, 'Hz'))), 'k--', 'DisplayName', 'INE');
plot(freqs, abs(squeeze(freqresp(G_dvf.G_cart('Dx', 'Fnx'), freqs, 'Hz'))), 'k-.', 'DisplayName', 'DVF');
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
ylabel('Amplitude [m/N]'); set(gca, 'XTickLabel',[]);
legend('location', 'northeast');
ax2 = subplot(2, 1, 2);
hold on;
plot(freqs, 180/pi*angle(squeeze(freqresp(G.G_cart ('Dx', 'Fnx'), freqs, 'Hz'))), 'k-');
plot(freqs, 180/pi*angle(squeeze(freqresp(G_iff.G_cart('Dx', 'Fnx'), freqs, 'Hz'))), 'k:');
plot(freqs, 180/pi*angle(squeeze(freqresp(G_ine.G_cart('Dx', 'Fnx'), freqs, 'Hz'))), 'k--');
plot(freqs, 180/pi*angle(squeeze(freqresp(G_dvf.G_cart('Dx', 'Fnx'), freqs, 'Hz'))), 'k-.');
hold off;
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'lin');
ylabel('Phase [deg]'); xlabel('Frequency [Hz]');
ylim([-180, 180]);
yticks([-180, -90, 0, 90, 180]);
linkaxes([ax1,ax2],'x');
#+end_src
#+HEADER: :tangle no :exports results :results none :noweb yes
#+begin_src matlab :var filepath="figs/plant_comp_damping_x.pdf" :var figsize="full-tall" :post pdf2svg(file=*this*, ext="png")
<>
#+end_src
#+name: fig:plant_comp_damping_x
#+caption: Plant for the $x$ direction for different active damping technique used ([[./figs/plant_comp_damping_x.png][png]], [[./figs/plant_comp_damping_x.pdf][pdf]])
[[file:figs/plant_comp_damping_x.png]]
#+begin_src matlab :exports none
freqs = logspace(0, 3, 1000);
figure;
title('$F_{n,x}$ to $R_z$');
ax1 = subplot(2, 1, 1);
hold on;
plot(freqs, abs(squeeze(freqresp(G.G_cart( 'Rz', 'Fnx'), freqs, 'Hz'))), 'k-' , 'DisplayName', 'Undamped');
plot(freqs, abs(squeeze(freqresp(G_iff.G_cart('Rz', 'Fnx'), freqs, 'Hz'))), 'k:' , 'DisplayName', 'IFF');
plot(freqs, abs(squeeze(freqresp(G_ine.G_cart('Rz', 'Fnx'), freqs, 'Hz'))), 'k--', 'DisplayName', 'INE');
plot(freqs, abs(squeeze(freqresp(G_dvf.G_cart('Rz', 'Fnx'), freqs, 'Hz'))), 'k-.', 'DisplayName', 'DVF');
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
ylabel('Amplitude [m/N]'); set(gca, 'XTickLabel',[]);
legend('location', 'northeast');
ax2 = subplot(2, 1, 2);
hold on;
plot(freqs, 180/pi*angle(squeeze(freqresp(G.G_cart ('Ry', 'Fnx'), freqs, 'Hz'))), 'k-');
plot(freqs, 180/pi*angle(squeeze(freqresp(G_iff.G_cart('Ry', 'Fnx'), freqs, 'Hz'))), 'k:');
plot(freqs, 180/pi*angle(squeeze(freqresp(G_ine.G_cart('Ry', 'Fnx'), freqs, 'Hz'))), 'k--');
plot(freqs, 180/pi*angle(squeeze(freqresp(G_dvf.G_cart('Ry', 'Fnx'), freqs, 'Hz'))), 'k-.');
hold off;
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'lin');
ylabel('Phase [deg]'); xlabel('Frequency [Hz]');
ylim([-180, 180]);
yticks([-180, -90, 0, 90, 180]);
linkaxes([ax1,ax2],'x');
#+end_src
#+HEADER: :tangle no :exports results :results none :noweb yes
#+begin_src matlab :var filepath="figs/plant_comp_damping_coupling.pdf" :var figsize="full-tall" :post pdf2svg(file=*this*, ext="png")
<>
#+end_src
#+name: fig:plant_comp_damping_coupling
#+caption: Comparison of one off-diagonal plant for different damping technique applied ([[./figs/plant_comp_damping_coupling.png][png]], [[./figs/plant_comp_damping_coupling.pdf][pdf]])
[[file:figs/plant_comp_damping_coupling.png]]
** Tomography Experiment - Frequency Domain analysis
#+begin_src matlab
load('./active_damping/mat/tomo_exp.mat', 'En', 'En_iff', 'En_dvf');
Fs = 1e3; % Sampling Frequency of the Data
t = (1/Fs)*[0:length(En(:,1))-1];
#+end_src
We remove the first 0.5 seconds where the transient behavior is fading out.
#+begin_src matlab
[~, i_start] = min(abs(t - 0.5)); % find the indice corresponding to 0.5s
t = t(i_start:end) - t(i_start);
En = En(i_start:end, :);
En_dvf = En_dvf(i_start:end, :);
En_iff = En_iff(i_start:end, :);
#+end_src
Window used for =pwelch= function.
#+begin_src matlab
n_av = 4;
han_win = hanning(ceil(length(En(:, 1))/n_av));
#+end_src
#+begin_src matlab :exports none
Ts = t(2)-t(1); % Sample Time for the Data [s]
[pxx, f] = pwelch(En(:, 1), han_win, [], [], 1/Ts);
[pxx_dvf, ~] = pwelch(En_dvf(:, 1), han_win, [], [], 1/Ts);
[pxx_iff, ~] = pwelch(En_iff(:, 1), han_win, [], [], 1/Ts);
[pyy, ~] = pwelch(En(:, 2), han_win, [], [], 1/Ts);
[pyy_dvf, ~] = pwelch(En_dvf(:, 2), han_win, [], [], 1/Ts);
[pyy_iff, ~] = pwelch(En_iff(:, 2), han_win, [], [], 1/Ts);
[pzz, ~] = pwelch(En(:, 3), han_win, [], [], 1/Ts);
[pzz_dvf, ~] = pwelch(En_dvf(:, 3), han_win, [], [], 1/Ts);
[pzz_iff, ~] = pwelch(En_iff(:, 3), han_win, [], [], 1/Ts);
[prx, ~] = pwelch(En(:, 4), han_win, [], [], 1/Ts);
[prx_dvf, ~] = pwelch(En_dvf(:, 4), han_win, [], [], 1/Ts);
[prx_iff, ~] = pwelch(En_iff(:, 4), han_win, [], [], 1/Ts);
[pry, ~] = pwelch(En(:, 5), han_win, [], [], 1/Ts);
[pry_dvf, ~] = pwelch(En_dvf(:, 5), han_win, [], [], 1/Ts);
[pry_iff, ~] = pwelch(En_iff(:, 5), han_win, [], [], 1/Ts);
[prz, ~] = pwelch(En(:, 6), han_win, [], [], 1/Ts);
[prz_dvf, ~] = pwelch(En_dvf(:, 6), han_win, [], [], 1/Ts);
[prz_iff, ~] = pwelch(En_iff(:, 6), han_win, [], [], 1/Ts);
#+end_src
#+begin_src matlab :exports none
figure;
hold on;
plot(f, pxx_dvf, 'DisplayName', 'DVF')
plot(f, pxx_iff, 'DisplayName', 'IFF')
plot(f, pxx, 'k--', 'DisplayName', 'Undamped')
hold off;
xlabel('Frequency [Hz]');
ylabel('Power Spectral Density [$m^2/Hz$]');
set(gca, 'xscale', 'log'); set(gca, 'yscale', 'log');
legend('location', 'northeast');
xlim([1, 500]);
#+end_src
#+HEADER: :tangle no :exports results :results none :noweb yes
#+begin_src matlab :var filepath="figs/act_damp_tomo_exp_comp_psd_trans.pdf" :var figsize="full-tall" :post pdf2svg(file=*this*, ext="png")
<>
#+end_src
#+name: fig:act_damp_tomo_exp_comp_psd_trans
#+caption: PSD of the translation errors in the X direction for applied Active Damping techniques ([[./figs/act_damp_tomo_exp_comp_psd_trans.png][png]], [[./figs/act_damp_tomo_exp_comp_psd_trans.pdf][pdf]])
[[file:figs/act_damp_tomo_exp_comp_psd_trans.png]]
#+begin_src matlab :exports none
figure;
hold on;
plot(f, prx_dvf, 'DisplayName', 'DVF')
plot(f, prx_iff, 'DisplayName', 'IFF')
plot(f, prx, 'k--', 'DisplayName', 'Undamped')
hold off;
xlabel('Frequency [Hz]');
ylabel('Power Spectral Density [$rad^2/Hz$]');
set(gca, 'xscale', 'log'); set(gca, 'yscale', 'log');
legend('location', 'northeast');
xlim([1, 500]);
#+end_src
#+HEADER: :tangle no :exports results :results none :noweb yes
#+begin_src matlab :var filepath="figs/act_damp_tomo_exp_comp_psd_rot.pdf" :var figsize="full-tall" :post pdf2svg(file=*this*, ext="png")
<>
#+end_src
#+name: fig:act_damp_tomo_exp_comp_psd_rot
#+caption: PSD of the rotation errors in the X direction for applied Active Damping techniques ([[./figs/act_damp_tomo_exp_comp_psd_rot.png][png]], [[./figs/act_damp_tomo_exp_comp_psd_rot.pdf][pdf]])
[[file:figs/act_damp_tomo_exp_comp_psd_rot.png]]
#+begin_src matlab :exports none
figure;
hold on;
plot(f, flip(-cumtrapz(flip(f), flip(pxx_dvf))), 'DisplayName', 'DVF')
plot(f, flip(-cumtrapz(flip(f), flip(pxx_iff))), 'DisplayName', 'IFF')
plot(f, flip(-cumtrapz(flip(f), flip(pxx))), 'k--', 'DisplayName', 'Undamped')
hold off;
xlabel('Frequency [Hz]');
ylabel('Cumulative Power Spectrum [$m^2$]');
set(gca, 'xscale', 'log'); set(gca, 'yscale', 'log');
legend('location', 'northeast');
xlim([1, 500]);
#+end_src
#+HEADER: :tangle no :exports results :results none :noweb yes
#+begin_src matlab :var filepath="figs/act_damp_tomo_exp_comp_cps_trans.pdf" :var figsize="full-tall" :post pdf2svg(file=*this*, ext="png")
<>
#+end_src
#+name: fig:act_damp_tomo_exp_comp_cps_trans
#+caption: CPS of the translation errors in the X direction for applied Active Damping techniques ([[./figs/act_damp_tomo_exp_comp_cps_trans.png][png]], [[./figs/act_damp_tomo_exp_comp_cps_trans.pdf][pdf]])
[[file:figs/act_damp_tomo_exp_comp_cps_trans.png]]
#+begin_src matlab :exports none
figure;
hold on;
plot(f, flip(-cumtrapz(flip(f), flip(prx_dvf))), 'DisplayName', 'DVF')
plot(f, flip(-cumtrapz(flip(f), flip(prx_iff))), 'DisplayName', 'IFF')
plot(f, flip(-cumtrapz(flip(f), flip(prx))), 'k--', 'DisplayName', 'Undamped')
hold off;
xlabel('Frequency [Hz]');
ylabel('Cumulative Power Spectrum [$rad^2$]');
set(gca, 'xscale', 'log'); set(gca, 'yscale', 'log');
legend('location', 'northeast');
xlim([1, 400]);
#+end_src
#+HEADER: :tangle no :exports results :results none :noweb yes
#+begin_src matlab :var filepath="figs/act_damp_tomo_exp_comp_cps_rot.pdf" :var figsize="full-tall" :post pdf2svg(file=*this*, ext="png")
<>
#+end_src
#+name: fig:act_damp_tomo_exp_comp_cps_rot
#+caption: CPS of the rotation errors in the X direction for applied Active Damping techniques ([[./figs/act_damp_tomo_exp_comp_cps_rot.png][png]], [[./figs/act_damp_tomo_exp_comp_cps_rot.pdf][pdf]])
[[file:figs/act_damp_tomo_exp_comp_cps_rot.png]]
* Useful Functions
** prepareLinearizeIdentification
:PROPERTIES:
:header-args:matlab+: :tangle src/prepareLinearizeIdentification.m
:header-args:matlab+: :comments none :mkdirp yes :eval no
:END:
<>
This Matlab function is accessible [[file:src/prepareLinearizeIdentification.m][here]].
*** Function Description
:PROPERTIES:
:UNNUMBERED: t
:END:
#+begin_src matlab
function [] = prepareLinearizeIdentification(args)
#+end_src
*** Optional Parameters
:PROPERTIES:
:UNNUMBERED: t
:END:
#+begin_src matlab
arguments
args.nass_actuator char {mustBeMember(args.nass_actuator,{'piezo', 'lorentz'})} = 'piezo'
args.sample_mass (1,1) double {mustBeNumeric, mustBePositive} = 50 % [kg]
end
#+end_src
*** Initialize the Simulation
:PROPERTIES:
:UNNUMBERED: t
:END:
We initialize all the stages with the default parameters.
#+begin_src matlab
initializeGround();
initializeGranite();
initializeTy();
initializeRy();
initializeRz();
initializeMicroHexapod();
initializeAxisc();
initializeMirror();
#+end_src
The nano-hexapod is a piezoelectric hexapod and the sample has a mass of 50kg.
#+begin_src matlab
initializeNanoHexapod('actuator', args.nass_actuator);
initializeSample('mass', args.sample_mass);
#+end_src
We set the references and disturbances to zero.
#+begin_src matlab
initializeReferences();
initializeDisturbances('enable', false);
#+end_src
We set the controller type to Open-Loop.
#+begin_src matlab
initializeController('type', 'open-loop');
#+end_src
And we put some gravity.
#+begin_src matlab
initializeSimscapeConfiguration('gravity', true);
#+end_src
We do not need to log any signal.
#+begin_src matlab
initializeLoggingConfiguration('log', 'none');
#+end_src
** prepareTomographyExperiment
:PROPERTIES:
:header-args:matlab+: :tangle src/prepareTomographyExperiment.m
:header-args:matlab+: :comments none :mkdirp yes :eval no
:END:
<>
This Matlab function is accessible [[file:src/prepareTomographyExperiment.m][here]].
*** Function Description
:PROPERTIES:
:UNNUMBERED: t
:END:
#+begin_src matlab
function [] = prepareTomographyExperiment(args)
#+end_src
*** Optional Parameters
:PROPERTIES:
:UNNUMBERED: t
:END:
#+begin_src matlab
arguments
args.nass_actuator char {mustBeMember(args.nass_actuator,{'piezo', 'lorentz'})} = 'piezo'
args.sample_mass (1,1) double {mustBeNumeric, mustBePositive} = 50 % [kg]
args.Rz_period (1,1) double {mustBeNumeric, mustBePositive} = 1 % [s]
end
#+end_src
*** Initialize the Simulation
:PROPERTIES:
:UNNUMBERED: t
:END:
We initialize all the stages with the default parameters.
#+begin_src matlab
initializeGround();
initializeGranite();
initializeTy();
initializeRy();
initializeRz();
initializeMicroHexapod();
initializeAxisc();
initializeMirror();
#+end_src
The nano-hexapod is a piezoelectric hexapod and the sample has a mass of 50kg.
#+begin_src matlab
initializeNanoHexapod('actuator', args.nass_actuator);
initializeSample('mass', args.sample_mass);
#+end_src
We set the references that corresponds to a tomography experiment.
#+begin_src matlab
initializeReferences('Rz_type', 'rotating', 'Rz_period', args.Rz_period);
#+end_src
#+begin_src matlab
initializeDisturbances();
#+end_src
Open Loop.
#+begin_src matlab
initializeController('type', 'open-loop');
#+end_src
And we put some gravity.
#+begin_src matlab
initializeSimscapeConfiguration('gravity', true);
#+end_src
We log the signals.
#+begin_src matlab
initializeLoggingConfiguration('log', 'all');
#+end_src