#+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('active_damping/matlab/sim_nass_active_damping.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 = 'sim_nass_active_damping'; %% Input/Output definition clear io; io_i = 1; io(io_i) = linio([mdl, '/Fnl'], 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 = 'sim_nass_active_damping'; %% Input/Output definition clear io; io_i = 1; io(io_i) = linio([mdl, '/Fnl'], 1, 'openinput'); io_i = io_i + 1; % Actuator Inputs io(io_i) = linio([mdl, '/Compute Error in NASS base'], 2, 'openoutput'); 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_simscape.mat'); set_param(conf_simscape, 'StopTime', '4.5'); #+end_src And we simulate the system. #+begin_src matlab sim('sim_nass_active_damping'); #+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('active_damping/matlab/sim_nass_active_damping.slx') load('mat/conf_simscape.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 = 'sim_nass_active_damping'; %% Input/Output definition clear io; io_i = 1; io(io_i) = linio([mdl, '/Fnl'], 1, 'openinput'); io_i = io_i + 1; 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 = 'sim_nass_active_damping'; %% Input/Output definition clear io; io_i = 1; io(io_i) = linio([mdl, '/Fnl'], 1, 'openinput'); io_i = io_i + 1; 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 = 'sim_nass_active_damping'; %% Input/Output definition clear io; io_i = 1; io(io_i) = linio([mdl, '/Fnl'], 1, 'openinput'); io_i = io_i + 1; 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 = 'sim_nass_active_damping'; %% Input/Output definition clear io; io_i = 1; io(io_i) = linio([mdl, '/Fnl'], 1, 'openinput'); io_i = io_i + 1; 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 = 'sim_nass_active_damping'; %% Input/Output definition clear io; io_i = 1; io(io_i) = linio([mdl, '/Fnl'], 1, 'openinput'); io_i = io_i + 1; 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('active_damping/matlab/sim_nass_active_damping.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'); save('./mat/controllers.mat', 'K_iff', '-append'); #+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 = 'sim_nass_active_damping'; %% Input/Output definition clear io; io_i = 1; io(io_i) = linio([mdl, '/Fnl'], 1, 'openinput'); io_i = io_i + 1; io(io_i) = linio([mdl, '/Compute Error in NASS base'], 2, 'openoutput'); 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'); save('./mat/controllers.mat', 'K_iff', '-append'); #+end_src We change the simulation stop time. #+begin_src matlab load('mat/conf_simscape.mat'); set_param(conf_simscape, 'StopTime', '4.5'); #+end_src And we simulate the system. #+begin_src matlab sim('sim_nass_active_damping'); #+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('active_damping/matlab/sim_nass_active_damping.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'); save('./mat/controllers.mat', 'K_dvf', '-append'); #+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 = 'sim_nass_active_damping'; %% Input/Output definition clear io; io_i = 1; io(io_i) = linio([mdl, '/Fnl'], 1, 'openinput'); io_i = io_i + 1; io(io_i) = linio([mdl, '/Compute Error in NASS base'], 2, 'openoutput'); 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'); save('./mat/controllers.mat', 'K_dvf', '-append'); #+end_src We change the simulation stop time. #+begin_src matlab load('mat/conf_simscape.mat'); set_param(conf_simscape, 'StopTime', '4.5'); #+end_src And we simulate the system. #+begin_src matlab sim('sim_nass_active_damping'); #+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('active_damping/matlab/sim_nass_active_damping.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'); save('./mat/controllers.mat', 'K_ine', '-append'); #+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 = 'sim_nass_active_damping'; %% Input/Output definition clear io; io_i = 1; io(io_i) = linio([mdl, '/Fnl'], 1, 'openinput'); io_i = io_i + 1; io(io_i) = linio([mdl, '/Compute Error in NASS base'], 2, 'openoutput'); 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 And all the controllers are set to 0. #+begin_src matlab K = tf(zeros(6)); save('./mat/controllers.mat', 'K', '-append'); K_ine = tf(zeros(6)); save('./mat/controllers.mat', 'K_ine', '-append'); K_iff = tf(zeros(6)); save('./mat/controllers.mat', 'K_iff', '-append'); K_dvf = tf(zeros(6)); save('./mat/controllers.mat', 'K_dvf', '-append'); #+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 And all the controllers are set to 0. #+begin_src matlab K = tf(zeros(6)); save('./mat/controllers.mat', 'K', '-append'); K_ine = tf(zeros(6)); save('./mat/controllers.mat', 'K_ine', '-append'); K_iff = tf(zeros(6)); save('./mat/controllers.mat', 'K_iff', '-append'); K_dvf = tf(zeros(6)); save('./mat/controllers.mat', 'K_dvf', '-append'); #+end_src * TODO Order :noexport: ** Undamped *** Identification of the transfer function from disturbance to position error #+begin_src matlab %% Options for Linearized options = linearizeOptions; options.SampleTime = 0; %% Name of the Simulink File mdl = 'sim_nass_active_damping'; %% Input/Output definition clear io; io_i = 1; io(io_i) = linio([mdl, '/Disturbances'], 1, 'openinput', [], 'Dwx'); io_i = io_i + 1; io(io_i) = linio([mdl, '/Disturbances'], 1, 'openinput', [], 'Dwy'); io_i = io_i + 1; io(io_i) = linio([mdl, '/Disturbances'], 1, 'openinput', [], 'Dwz'); io_i = io_i + 1; io(io_i) = linio([mdl, '/Compute Error in NASS base'], 2, 'openoutput'); io_i = io_i + 1; %% Run the linearization G = linearize(mdl, io, options); G.InputName = {'Dwx', 'Dwy', 'Dwz'}; G.OutputName = {'Edx', 'Edy', 'Edz', 'Erx', 'Ery', 'Erz'}; #+end_src *** Identification of the plant #+begin_src matlab %% Options for Linearized options = linearizeOptions; options.SampleTime = 0; %% Name of the Simulink File mdl = 'sim_nass_active_damping'; %% Input/Output definition clear io; io_i = 1; io(io_i) = linio([mdl, '/Fnl'], 1, 'openinput'); io_i = io_i + 1; io(io_i) = linio([mdl, '/Compute Error in NASS base'], 2, 'openoutput'); io_i = io_i + 1; %% Run the linearization G = linearize(mdl, io, options); G.InputName = {'Fnl1', 'Fnl2', 'Fnl3', 'Fnl4', 'Fnl5', 'Fnl6'}; G.OutputName = {'Edx', 'Edy', 'Edz', 'Erx', 'Ery', 'Erz'}; #+end_src #+begin_src matlab load('mat/stages.mat', 'nano_hexapod'); G_cart = G*inv(nano_hexapod.J'); G_cart.InputName = {'Fnx', 'Fny', 'Fnz', 'Mnx', 'Mny', 'Mnz'}; #+end_src #+begin_src matlab :exports none freqs = logspace(0, 3, 1000); figure; ax1 = subplot(2, 1, 1); hold on; plot(freqs, abs(squeeze(freqresp(G_cart('Edx', 'Fnx'), freqs, 'Hz'))), 'DisplayName', '$T_{x}$'); plot(freqs, abs(squeeze(freqresp(G_cart('Edy', 'Fny'), freqs, 'Hz'))), 'DisplayName', '$T_{y}$'); plot(freqs, abs(squeeze(freqresp(G_cart('Edz', 'Fnz'), freqs, 'Hz'))), 'DisplayName', '$T_{z}$'); hold off; set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log'); ylabel('Amplitude [m/N]'); set(gca, 'XTickLabel',[]); legend('location', 'southwest') ax2 = subplot(2, 1, 2); hold on; plot(freqs, 180/pi*angle(squeeze(freqresp(G_cart('Edx', 'Fnx'), freqs, 'Hz')))); plot(freqs, 180/pi*angle(squeeze(freqresp(G_cart('Edy', 'Fny'), freqs, 'Hz')))); plot(freqs, 180/pi*angle(squeeze(freqresp(G_cart('Edz', 'Fnz'), freqs, 'Hz')))); 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 #+begin_src matlab :exports none freqs = logspace(0, 3, 1000); figure; ax1 = subplot(2, 1, 1); hold on; plot(freqs, abs(squeeze(freqresp(G_cart('Erx', 'Mnx'), freqs, 'Hz'))), 'DisplayName', '$R_{x}$'); plot(freqs, abs(squeeze(freqresp(G_cart('Ery', 'Mny'), freqs, 'Hz'))), 'DisplayName', '$R_{y}$'); plot(freqs, abs(squeeze(freqresp(G_cart('Erz', 'Mnz'), freqs, 'Hz'))), 'DisplayName', '$R_{z}$'); hold off; set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log'); ylabel('Amplitude [m/N]'); set(gca, 'XTickLabel',[]); legend('location', 'southwest') ax2 = subplot(2, 1, 2); hold on; plot(freqs, 180/pi*angle(squeeze(freqresp(G_cart('Erx', 'Mnx'), freqs, 'Hz')))); plot(freqs, 180/pi*angle(squeeze(freqresp(G_cart('Ery', 'Mny'), freqs, 'Hz')))); plot(freqs, 180/pi*angle(squeeze(freqresp(G_cart('Erz', 'Mnz'), freqs, 'Hz')))); 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 *** TODO test #+begin_src matlab %% Options for Linearized options = linearizeOptions; options.SampleTime = 0; %% Name of the Simulink File mdl = 'sim_nass_active_damping'; %% Input/Output definition clear io; io_i = 1; io(io_i) = linio([mdl, '/Micro-Station/Dy'], 1, 'openinput'); io_i = io_i + 1; io(io_i) = linio([mdl, '/Compute Error in NASS base'], 2, 'openoutput'); io_i = io_i + 1; %% Run the linearization G = linearize(mdl, io, options); G.InputName = {'Dy'}; G.OutputName = {'Edx', 'Edy', 'Edz', 'Erx', 'Ery', 'Erz'}; #+end_src #+begin_important Why is the transfer function from Ty displacement to position error is equal to 1 at all frequencies? Why don't we see any resonance? #+end_important #+begin_src matlab :exports none freqs = logspace(0, 3, 1000); figure; ax1 = subplot(2, 1, 1); hold on; plot(freqs, abs(squeeze(freqresp(G('Edy', 'Dy(1)'), freqs, 'Hz'))), 'DisplayName', '$T_{x}$'); hold off; set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log'); ylabel('Amplitude [m/N]'); set(gca, 'XTickLabel',[]); legend('location', 'southwest') ax2 = subplot(2, 1, 2); hold on; plot(freqs, 180/pi*angle(squeeze(freqresp(G('Edy', 'Dy(1)'), freqs, 'Hz')))); 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 *** TODO test on hexapod #+begin_src matlab %% Options for Linearized options = linearizeOptions; options.SampleTime = 0; %% Name of the Simulink File mdl = 'test_nano_hexapod'; %% Input/Output definition clear io; io_i = 1; io(io_i) = linio([mdl, '/Fnl'], 1, 'openinput'); io_i = io_i + 1; io(io_i) = linio([mdl, '/x'], 1, 'openoutput'); io_i = io_i + 1; io(io_i) = linio([mdl, '/y'], 1, 'openoutput'); io_i = io_i + 1; io(io_i) = linio([mdl, '/z'], 1, 'openoutput'); io_i = io_i + 1; %% Run the linearization G = linearize(mdl, io, options); G.InputName = {'Fnl1', 'Fnl2', 'Fnl3', 'Fnl4', 'Fnl5', 'Fnl6'}; G.OutputName = {'x', 'y', 'z'}; #+end_src #+begin_src matlab %% Options for Linearized options = linearizeOptions; options.SampleTime = 0; %% Name of the Simulink File mdl = 'test_nano_hexapod'; %% Input/Output definition clear io; io_i = 1; io(io_i) = linio([mdl, '/Fx'], 1, 'openinput'); io_i = io_i + 1; io(io_i) = linio([mdl, '/x'], 1, 'openoutput'); io_i = io_i + 1; io(io_i) = linio([mdl, '/y'], 1, 'openoutput'); io_i = io_i + 1; io(io_i) = linio([mdl, '/z'], 1, 'openoutput'); io_i = io_i + 1; %% Run the linearization G = linearize(mdl, io, options); G.InputName = {'Fx'}; G.OutputName = {'x', 'y', 'z'}; #+end_src #+begin_src matlab :exports none freqs = logspace(0, 3, 1000); figure; ax1 = subplot(2, 1, 1); hold on; plot(freqs, abs(squeeze(freqresp(G('Edy', 'Dy(1)'), freqs, 'Hz'))), 'DisplayName', '$T_{x}$'); hold off; set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log'); ylabel('Amplitude [m/N]'); set(gca, 'XTickLabel',[]); legend('location', 'southwest') ax2 = subplot(2, 1, 2); hold on; plot(freqs, 180/pi*angle(squeeze(freqresp(G('Edy', 'Dy(1)'), freqs, 'Hz')))); 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 #+begin_src matlab :exports none freqs = logspace(0, 3, 1000); figure; ax1 = subplot(2, 1, 1); hold on; plot(freqs, abs(squeeze(freqresp(G_cart('Erx', 'Mnx'), freqs, 'Hz'))), 'DisplayName', '$R_{x}$'); plot(freqs, abs(squeeze(freqresp(G_cart('Ery', 'Mny'), freqs, 'Hz'))), 'DisplayName', '$R_{y}$'); plot(freqs, abs(squeeze(freqresp(G_cart('Erz', 'Mnz'), freqs, 'Hz'))), 'DisplayName', '$R_{z}$'); hold off; set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log'); ylabel('Amplitude [m/N]'); set(gca, 'XTickLabel',[]); legend('location', 'southwest') ax2 = subplot(2, 1, 2); hold on; plot(freqs, 180/pi*angle(squeeze(freqresp(G_cart('Erx', 'Mnx'), freqs, 'Hz')))); plot(freqs, 180/pi*angle(squeeze(freqresp(G_cart('Ery', 'Mny'), freqs, 'Hz')))); plot(freqs, 180/pi*angle(squeeze(freqresp(G_cart('Erz', 'Mnz'), freqs, 'Hz')))); 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 *** Sensitivity to disturbances The sensitivity to disturbances are shown on figure [[fig:sensitivity_dist_undamped]]. #+begin_src matlab :exports none freqs = logspace(0, 3, 1000); figure; subplot(2, 1, 1); title('$D_g$ to $D$'); hold on; plot(freqs, abs(squeeze(freqresp(G.G_gm('Dx', 'Dgx'), freqs, 'Hz'))), 'DisplayName', '$\left|D_x / D_{g,x}\right|$'); plot(freqs, abs(squeeze(freqresp(G.G_gm('Dy', 'Dgy'), freqs, 'Hz'))), 'DisplayName', '$\left|D_y / D_{g,y}\right|$'); plot(freqs, abs(squeeze(freqresp(G.G_gm('Dz', 'Dgz'), freqs, 'Hz'))), 'DisplayName', '$\left|D_z / D_{g,z}\right|$'); set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log'); ylabel('Amplitude [m/m]'); xlabel('Frequency [Hz]'); legend('location', 'southeast'); subplot(2, 1, 2); title('$F_s$ to $D$'); hold on; plot(freqs, abs(squeeze(freqresp(G.G_fs('Dx', 'Fsx'), freqs, 'Hz'))), 'DisplayName', '$\left|D_x / F_{s,x}\right|$'); plot(freqs, abs(squeeze(freqresp(G.G_fs('Dy', 'Fsy'), freqs, 'Hz'))), 'DisplayName', '$\left|D_y / F_{s,y}\right|$'); plot(freqs, abs(squeeze(freqresp(G.G_fs('Dz', 'Fsz'), freqs, 'Hz'))), 'DisplayName', '$\left|D_z / F_{s,z}\right|$'); 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_dist_undamped.pdf" :var figsize="full-tall" :post pdf2svg(file=*this*, ext="png") <> #+end_src #+name: fig:sensitivity_dist_undamped #+caption: Undamped sensitivity to disturbances ([[./figs/sensitivity_dist_undamped.png][png]], [[./figs/sensitivity_dist_undamped.pdf][pdf]]) [[file:figs/sensitivity_dist_undamped.png]] #+begin_src matlab :exports none freqs = logspace(0, 3, 1000); figure; hold on; plot(freqs, abs(squeeze(freqresp(G.G_dist('Dz', 'Frzz'), freqs, 'Hz'))), 'DisplayName', '$\left|D_z / F_{rz, z}\right|$'); plot(freqs, abs(squeeze(freqresp(G.G_dist('Dz', 'Ftyz'), freqs, 'Hz'))), 'DisplayName', '$\left|D_z / F_{ty, z}\right|$'); plot(freqs, abs(squeeze(freqresp(G.G_dist('Dx', 'Ftyx'), freqs, 'Hz'))), 'DisplayName', '$\left|D_x / F_{ty, x}\right|$'); 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_dist_stages.pdf" :var figsize="full-tall" :post pdf2svg(file=*this*, ext="png") <> #+end_src #+name: fig:sensitivity_dist_stages #+caption: Sensitivity to force disturbances in various stages ([[./figs/sensitivity_dist_stages.png][png]], [[./figs/sensitivity_dist_stages.pdf][pdf]]) [[file:figs/sensitivity_dist_stages.png]] *** Undamped Plant The "plant" (transfer function from forces applied by the nano-hexapod to the measured displacement of the sample with respect to the granite) bode plot is shown on figure [[fig:sensitivity_dist_undamped]]. #+begin_src matlab :exports none freqs = logspace(0, 3, 1000); figure; ax1 = subplot(2, 1, 1); hold on; plot(freqs, abs(squeeze(freqresp(G.G_cart('Dx', 'Fnx'), freqs, 'Hz')))); plot(freqs, abs(squeeze(freqresp(G.G_cart('Dy', 'Fny'), freqs, 'Hz')))); plot(freqs, abs(squeeze(freqresp(G.G_cart('Dz', 'Fnz'), freqs, 'Hz')))); hold off; set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log'); ylabel('Amplitude [m/N]'); set(gca, 'XTickLabel',[]); ax2 = subplot(2, 1, 2); hold on; plot(freqs, 180/pi*angle(squeeze(freqresp(G.G_cart('Dx', 'Fnx'), freqs, 'Hz'))), 'DisplayName', '$D_x / F_x$'); plot(freqs, 180/pi*angle(squeeze(freqresp(G.G_cart('Dy', 'Fny'), freqs, 'Hz'))), 'DisplayName', '$D_y / F_y$'); plot(freqs, 180/pi*angle(squeeze(freqresp(G.G_cart('Dz', 'Fnz'), freqs, 'Hz'))), 'DisplayName', '$D_z / F_z$'); 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/plant_undamped.pdf" :var figsize="full-tall" :post pdf2svg(file=*this*, ext="png") <> #+end_src #+name: fig:plant_undamped #+caption: Transfer Function from cartesian forces to displacement for the undamped plant ([[./figs/plant_undamped.png][png]], [[./figs/plant_undamped.pdf][pdf]]) [[file:figs/plant_undamped.png]] ** Direct Velocity Feedback *** One degree-of-freedom example :PROPERTIES: :header-args:matlab+: :tangle no :END: <> **** Equations #+begin_src latex :file rmc_1dof.pdf :post pdf2svg(file=*this*, ext="png") :exports results \begin{tikzpicture} % Ground \draw (-1, 0) -- (1, 0); % Ground Displacement \draw[dashed] (-1, 0) -- ++(-0.5, 0) coordinate(w); \draw[->] (w) -- ++(0, 0.5) node[left]{$w$}; % Mass \draw[fill=white] (-1, 1) rectangle ++(2, 0.8) node[pos=0.5]{$m$}; % Displacement of the mass \draw[dashed] (-1, 1.8) -- ++(-0.5, 0) coordinate(x); \draw[->] (x) -- ++(0, 0.5) node[left]{$x$}; % Spring, Damper, and Actuator \draw[spring] (-0.8, 0) -- (-0.8, 1) node[midway, left=0.1]{$k$}; \draw[damper] (0, 0) -- (0, 1) node[midway, left=0.2]{$c$}; \draw[actuator={0.4}{0.2}] (0.8, 0) -- (0.8, 1) coordinate[midway, right=0.1](F); % Measured deformation \draw[dashed] (1, 0) -- ++(2, 0) coordinate(d_bot); \draw[dashed] (1, 1) -- ++(2, 0) coordinate(d_top); \draw[<->] (d_bot) --coordinate[midway](d) (d_top); % Displacements \node[block={0.8cm}{0.6cm}, right=0.6 of F] (Krmc) {$K$}; \draw[->] (Krmc.west) -- (F) node[above right]{$F$}; \draw[->] (d)node[above left]{$d$} -- (Krmc.east); \end{tikzpicture} #+end_src #+name: fig:rmc_1dof #+caption: Relative Motion Control applied to a 1dof system #+RESULTS: [[file:figs/rmc_1dof.png]] The dynamic of the system is: \begin{equation} ms^2x = F_d - kx - csx + kw + csw + F \end{equation} In terms of the stage deformation $d = x - w$: \begin{equation} (ms^2 + cs + k) d = -ms^2 w + F_d + F \end{equation} The relative motion control law is: \begin{equation} K = -g s \end{equation} Thus, the applied force is: \begin{equation} F = -g s d \end{equation} And the new dynamics will be: \begin{equation} d = w \frac{-ms^2}{ms^2 + (c + g)s + k} + F_d \frac{1}{ms^2 + (c + g)s + k} + F \frac{1}{ms^2 + (c + g)s + k} \end{equation} And thus damping is added. If critical damping is wanted: \begin{equation} \xi = \frac{1}{2}\frac{c + g}{\sqrt{km}} = \frac{1}{2} \end{equation} This corresponds to a gain: \begin{equation} g = \sqrt{km} - c \end{equation} **** 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 **** Matlab Example Let define the system parameters. #+begin_src matlab m = 50; % [kg] k = 1e6; % [N/m] c = 1e3; % [N/(m/s)] #+end_src The state space model of the system is defined below. #+begin_src matlab A = [-c/m -k/m; 1 0]; B = [1/m 1/m -1; 0 0 0]; C = [ 0 1; -c -k]; D = [0 0 0; 1 0 0]; sys = ss(A, B, C, D); sys.InputName = {'F', 'Fd', 'wddot'}; sys.OutputName = {'d', 'Fm'}; sys.StateName = {'ddot', 'd'}; #+end_src The controller $K_\text{RMC}$ is: #+begin_src matlab Krmc = -(sqrt(k*m)-c)*s; Krmc.InputName = {'d'}; Krmc.OutputName = {'F'}; #+end_src And the closed loop system is computed below. #+begin_src matlab sys_rmc = feedback(sys, Krmc, 'name', +1); #+end_src #+begin_src matlab :exports none freqs = logspace(-1, 3, 1000); figure; subplot(2, 2, 1); title('Fd to d') hold on; plot(freqs, abs(squeeze(freqresp(sys('d', 'Fd'), freqs, 'Hz')))); plot(freqs, abs(squeeze(freqresp(sys_rmc('d', 'Fd'), freqs, 'Hz')))); set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log'); ylabel('Amplitude [m/N]'); xlabel('Frequency [Hz]'); xlim([freqs(1), freqs(end)]); subplot(2, 2, 3); title('Fd to x') hold on; plot(freqs, abs(squeeze(freqresp(sys('d', 'Fd'), freqs, 'Hz')))); plot(freqs, abs(squeeze(freqresp(sys_rmc('d', 'Fd'), freqs, 'Hz')))); set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log'); ylabel('Amplitude [m/N]'); xlabel('Frequency [Hz]'); xlim([freqs(1), freqs(end)]); subplot(2, 2, 2); title('w to d') hold on; plot(freqs, abs(squeeze(freqresp(sys('d', 'wddot')*s^2, freqs, 'Hz')))); plot(freqs, abs(squeeze(freqresp(sys_rmc('d', 'wddot')*s^2, freqs, 'Hz')))); set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log'); ylabel('Amplitude [m/m]'); xlabel('Frequency [Hz]'); xlim([freqs(1), freqs(end)]); subplot(2, 2, 4); title('w to x') hold on; plot(freqs, abs(squeeze(freqresp(1+sys('d', 'wddot')*s^2, freqs, 'Hz')))); plot(freqs, abs(squeeze(freqresp(1+sys_rmc('d', 'wddot')*s^2, freqs, 'Hz')))); set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log'); ylabel('Amplitude [m/m]'); xlabel('Frequency [Hz]'); xlim([freqs(1), freqs(end)]); #+end_src #+HEADER: :tangle no :exports results :results none :noweb yes #+begin_src matlab :var filepath="figs/rmc_1dof_sensitivitiy.pdf" :var figsize="full-tall" :post pdf2svg(file=*this*, ext="png") <> #+end_src #+name: fig:rmc_1dof_sensitivitiy #+caption: Sensitivity to disturbance when RMC is applied on the 1dof system ([[./figs/rmc_1dof_sensitivitiy.png][png]], [[./figs/rmc_1dof_sensitivitiy.pdf][pdf]]) [[file:figs/rmc_1dof_sensitivitiy.png]] ** Inertial Control *** One degree-of-freedom example :PROPERTIES: :header-args:matlab+: :tangle no :END: <> **** Equations #+begin_src latex :file ine_1dof.pdf :post pdf2svg(file=*this*, ext="png") :exports results \begin{tikzpicture} % Ground \draw (-1, 0) -- (1, 0); % Ground Displacement \draw[dashed] (-1, 0) -- ++(-0.5, 0) coordinate(w); \draw[->] (w) -- ++(0, 0.5) node[left]{$w$}; % Mass \draw[fill=white] (-1, 1) rectangle ++(2, 0.8) node[pos=0.5]{$m$}; % Velocity Sensor \node[inertialsensor={0.3}] (velg) at (1, 1.8){}; \node[above] at (velg.north) {$\dot{x}$}; % Displacement of the mass \draw[dashed] (-1, 1.8) -- ++(-0.5, 0) coordinate(x); \draw[->] (x) -- ++(0, 0.5) node[left]{$x$}; % Spring, Damper, and Actuator \draw[spring] (-0.8, 0) -- (-0.8, 1) node[midway, left=0.1]{$k$}; \draw[damper] (0, 0) -- (0, 1) node[midway, left=0.2]{$c$}; \draw[actuator={0.4}{0.2}] (0.8, 0) -- (0.8, 1) coordinate[midway, right=0.1](F); % Control \node[block={0.8cm}{0.6cm}, right=0.6 of F] (Kine) {$K$}; \draw[->] (Kine.west) -- (F) node[above right]{$F$}; \draw[<-] (Kine.east) -- ++(0.5, 0) |- (velg.east); \end{tikzpicture} #+end_src #+name: fig:ine_1dof #+caption: Direct Velocity Feedback applied to a 1dof system #+RESULTS: [[file:figs/ine_1dof.png]] The dynamic of the system is: \begin{equation} ms^2x = F_d - kx - csx + kw + csw + F \end{equation} In terms of the stage deformation $d = x - w$: \begin{equation} (ms^2 + cs + k) d = -ms^2 w + F_d + F \end{equation} The direct velocity feedback law shown in figure [[fig:ine_1dof]] is: \begin{equation} K = -g \end{equation} Thus, the applied force is: \begin{equation} F = -g \dot{x} \end{equation} And the new dynamics will be: \begin{equation} d = w \frac{-ms^2 - gs}{ms^2 + (c + g)s + k} + F_d \frac{1}{ms^2 + (c + g)s + k} + F \frac{1}{ms^2 + (c + g)s + k} \end{equation} And thus damping is added. If critical damping is wanted: \begin{equation} \xi = \frac{1}{2}\frac{c + g}{\sqrt{km}} = \frac{1}{2} \end{equation} This corresponds to a gain: \begin{equation} g = \sqrt{km} - c \end{equation} **** 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 **** Matlab Example Let define the system parameters. #+begin_src matlab m = 50; % [kg] k = 1e6; % [N/m] c = 1e3; % [N/(m/s)] #+end_src The state space model of the system is defined below. #+begin_src matlab A = [-c/m -k/m; 1 0]; B = [1/m 1/m -1; 0 0 0]; C = [1 0; 0 1; 0 0]; D = [0 0 0; 0 0 0; 0 0 1]; sys = ss(A, B, C, D); sys.InputName = {'F', 'Fd', 'wddot'}; sys.OutputName = {'ddot', 'd', 'wddot'}; sys.StateName = {'ddot', 'd'}; #+end_src Because we need $\dot{x}$ for feedback, we compute it from the outputs #+begin_src matlab G_xdot = [1, 0, 1/s; 0, 1, 0]; G_xdot.InputName = {'ddot', 'd', 'wddot'}; G_xdot.OutputName = {'xdot', 'd'}; #+end_src Finally, the system is described by =sys= as defined below. #+begin_src matlab sys = series(sys, G_xdot, [1 2 3], [1 2 3]); #+end_src The controller $K_\text{INE}$ is: #+begin_src matlab Kine = tf(-(sqrt(k*m)-c)); Kine.InputName = {'xdot'}; Kine.OutputName = {'F'}; #+end_src And the closed loop system is computed below. #+begin_src matlab sys_ine = feedback(sys, Kine, 'name', +1); #+end_src The obtained sensitivity to disturbances is shown in figure [[fig:ine_1dof_sensitivitiy]]. #+begin_src matlab :exports none freqs = logspace(-1, 3, 1000); figure; subplot(2, 2, 1); title('Fd to d') hold on; plot(freqs, abs(squeeze(freqresp(sys('d', 'Fd'), freqs, 'Hz')))); plot(freqs, abs(squeeze(freqresp(sys_ine('d', 'Fd'), freqs, 'Hz')))); set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log'); ylabel('Amplitude [m/N]'); xlabel('Frequency [Hz]'); xlim([freqs(1), freqs(end)]); subplot(2, 2, 3); title('Fd to x') hold on; plot(freqs, abs(squeeze(freqresp(sys('xdot', 'Fd')/s, freqs, 'Hz')))); plot(freqs, abs(squeeze(freqresp(sys_ine('xdot', 'Fd')/s, freqs, 'Hz')))); set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log'); ylabel('Amplitude [m/N]'); xlabel('Frequency [Hz]'); xlim([freqs(1), freqs(end)]); subplot(2, 2, 2); title('w to d') hold on; plot(freqs, abs(squeeze(freqresp(sys('d', 'wddot')*s^2, freqs, 'Hz')))); plot(freqs, abs(squeeze(freqresp(sys_ine('d', 'wddot')*s^2, freqs, 'Hz')))); set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log'); ylabel('Amplitude [m/m]'); xlabel('Frequency [Hz]'); xlim([freqs(1), freqs(end)]); subplot(2, 2, 4); title('w to x') hold on; plot(freqs, abs(squeeze(freqresp(1+sys('d', 'wddot')*s^2, freqs, 'Hz')))); plot(freqs, abs(squeeze(freqresp(1+sys_ine('d', 'wddot')*s^2, freqs, 'Hz')))); set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log'); ylabel('Amplitude [m/m]'); xlabel('Frequency [Hz]'); xlim([freqs(1), freqs(end)]); #+end_src #+HEADER: :tangle no :exports results :results none :noweb yes #+begin_src matlab :var filepath="figs/ine_1dof_sensitivitiy.pdf" :var figsize="full-tall" :post pdf2svg(file=*this*, ext="png") <> #+end_src #+name: fig:ine_1dof_sensitivitiy #+caption: Sensitivity to disturbance when INE is applied on the 1dof system ([[./figs/ine_1dof_sensitivitiy.png][png]], [[./figs/ine_1dof_sensitivitiy.pdf][pdf]]) [[file:figs/ine_1dof_sensitivitiy.png]]