#+TITLE: Active Damping :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 matlab/modal_frf_coh.m #+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: * Analysis of the nano-hexapod transfer functions :noexport: ** 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 :tangle no simulinkproject('../'); #+end_src ** Init #+begin_src matlab %% Initialize Ground initializeGround(); %% Initialize Granite initializeGranite(struct('rigid', false)); %% Initialize Translation stage initializeTy(struct('rigid', false)); %% Initialize Tilt Stage initializeRy(struct('rigid', false)); %% Initialize Spindle initializeRz(struct('rigid', false)); %% Initialize Hexapod Symétrie initializeMicroHexapod(struct('rigid', false)); %% Initialize Center of gravity compensation initializeAxisc(); %% Initialize the mirror initializeMirror(); %% Initialize the Nano Hexapod initializeNanoHexapod(struct('actuator', 'piezo')); %% Initialize the Sample initializeSample(struct('mass', 50)); #+end_src #+begin_src matlab K = tf(zeros(6)); save('./mat/controllers.mat', 'K', '-append'); K_iff = tf(zeros(6)); save('./mat/controllers.mat', 'K_iff', '-append'); #+end_src ** Identification #+begin_src matlab G = identifyPlant(); #+end_src ** Force Sensor #+begin_src matlab figure; hold on; for i=1:6 plot(freqs, abs(squeeze(freqresp(G.G_iff(['Fm', num2str(i)], ['F', num2str(i)]), freqs, 'Hz')))); end set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log'); ylabel('Amplitude [N/N]'); xlabel('Frequency [Hz]'); #+end_src * Introduction :ignore: First, in section [[sec:undamped]], we will looked at the undamped system. Then, we will compare three active damping techniques: - In section [[sec:iff]]: the integral force feedback is used - In section [[sec:rmc]]: the relative motion control is used - In section [[sec:dvf]]: the direct velocity feedback is used For each of the active damping technique, we will: - Compare the sensitivity from disturbances - Look at the damped plant The disturbances are: - Ground motion - Direct forces - Motion errors of all the stages * Undamped System <> ** Introduction :ignore: We first look at the undamped system. The performance of this undamped system will be compared with the damped system using various 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 open 'simscape/sim_nano_station_id.slx' #+end_src ** Init We initialize all the stages with the default parameters. The nano-hexapod is a piezoelectric hexapod and the sample has a mass of 50kg. #+begin_src matlab initializeGround(); initializeGranite(); initializeTy(); initializeRy(); initializeRz(); initializeMicroHexapod(); initializeAxisc(); initializeMirror(); initializeNanoHexapod(struct('actuator', 'piezo')); initializeSample(struct('mass', 50)); #+end_src All the controllers are set to 0. #+begin_src matlab K = tf(zeros(6)); save('./mat/controllers.mat', 'K', '-append'); K_iff = tf(zeros(6)); save('./mat/controllers.mat', 'K_iff', '-append'); K_rmc = tf(zeros(6)); save('./mat/controllers.mat', 'K_rmc', '-append'); K_dvf = tf(zeros(6)); save('./mat/controllers.mat', 'K_dvf', '-append'); #+end_src ** Identification We identify the various transfer functions of the system #+begin_src matlab G = identifyPlant(); #+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]] ** 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]] ** Save #+begin_src matlab save('./active_damping/mat/plants.mat', 'G', '-append'); #+end_src * Integral Force Feedback <> ** Introduction :ignore: Integral Force Feedback is applied. In section [[sec:iff_1dof]], IFF is applied on a uni-axial system to understand its behavior. Then, it is applied on the simscape model. ** One degree-of-freedom example <> *** Equations #+begin_src latex :file iff_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.4) rectangle ++(2, 0.8) node[pos=0.5]{$m$}; \node[forcesensor={0.4}{0.4}] (fsensn) at (0, 1){}; \draw[] (-0.8, 1) -- (0.8, 1); \node[left] at (fsensn.west) {$F_m$}; % Displacement of the mass \draw[dashed] (-1, 2.2) -- ++(-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); % Displacements \node[block={0.8cm}{0.6cm}, right=0.6 of F] (Kiff) {$K$}; \draw[->] (Kiff.west) -- (F) node[above right]{$F$}; \draw[<-] (Kiff.east) -- ++(0.5, 0) |- (fsensn.east); \end{tikzpicture} #+end_src #+name: fig:iff_1dof #+caption: Integral Force Feedback applied to a 1dof system #+RESULTS: [[file:figs/iff_1dof.png]] The dynamic of the system is described by the following equation: \begin{equation} ms^2x = F_d - kx - csx + kw + csw + F \end{equation} The measured force $F_m$ is: \begin{align} F_m &= F - kx - csx + kw + csw \\ &= ms^2 x - F_d \end{align} The Integral Force Feedback controller is $K = -\frac{g}{s}$, and thus the applied force by this controller is: \begin{equation} F_{\text{IFF}} = -\frac{g}{s} F_m = -\frac{g}{s} (ms^2 x - F_d) \end{equation} Once the IFF is applied, the new dynamics of the system is: \begin{equation} ms^2x = F_d + F - kx - csx + kw + csw - \frac{g}{s} (ms^2x - F_d) \end{equation} And finally: \begin{equation} x = F_d \frac{1 + \frac{g}{s}}{ms^2 + (mg + c)s + k} + F \frac{1}{ms^2 + (mg + c)s + k} + w \frac{k + cs}{ms^2 + (mg + c)s + k} \end{equation} We can see that this: - adds damping to the system by a value $mg$ - lower the compliance as low frequency by a factor: $1 + g/s$ If we want critical damping: \begin{equation} \xi = \frac{1}{2} \frac{c + gm}{\sqrt{km}} = \frac{1}{2} \end{equation} This is attainable if we have: \begin{equation} g = \frac{\sqrt{km} - c}{m} \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{IFF}$ is: #+begin_src matlab Kiff = -((sqrt(k*m)-c)/m)/s; Kiff.InputName = {'Fm'}; Kiff.OutputName = {'F'}; #+end_src And the closed loop system is computed below. #+begin_src matlab sys_iff = feedback(sys, Kiff, 'name', +1); #+end_src #+begin_src matlab :exports none freqs = logspace(0, 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_iff('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_iff('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_iff('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_iff('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/iff_1dof_sensitivitiy.pdf" :var figsize="full-tall" :post pdf2svg(file=*this*, ext="png") <> #+end_src #+NAME: fig:iff_1dof_sensitivitiy #+CAPTION: Sensitivity to disturbance when IFF is applied on the 1dof system ([[./figs/iff_1dof_sensitivitiy.png][png]], [[./figs/iff_1dof_sensitivitiy.pdf][pdf]]) [[file:figs/iff_1dof_sensitivitiy.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 open 'simscape/sim_nano_station_id.slx' #+end_src ** Control Design Let's load the undamped plant: #+begin_src matlab load('./active_damping/mat/plants.mat', 'G'); #+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(0, 3, 1000); figure; ax1 = subplot(2, 1, 1); hold on; for i=1:6 plot(freqs, abs(squeeze(freqresp(G.G_iff(['Fm', num2str(i)], ['F', 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.G_iff(['Fm', num2str(i)], ['F', 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/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]] The controller for each pair of actuator/sensor is: #+begin_src matlab K_iff = -1000/s; #+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:6 plot(freqs, abs(squeeze(freqresp(K_iff*G.G_iff(['Fm', num2str(i)], ['F', 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(K_iff*G.G_iff(['Fm', num2str(i)], ['F', 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/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]] ** Sensitivity to disturbances Let's initialize the system prior to identification. #+begin_src matlab initializeGround(); initializeGranite(); initializeTy(); initializeRy(); initializeRz(); initializeMicroHexapod(); initializeAxisc(); initializeMirror(); initializeNanoHexapod(struct('actuator', 'piezo')); initializeSample(struct('mass', 50)); #+end_src All the controllers are set to 0. #+begin_src matlab K = tf(zeros(6)); save('./mat/controllers.mat', 'K', '-append'); K_iff = -K_iff*eye(6); save('./mat/controllers.mat', 'K_iff', '-append'); K_rmc = tf(zeros(6)); save('./mat/controllers.mat', 'K_rmc', '-append'); K_dvf = tf(zeros(6)); save('./mat/controllers.mat', 'K_dvf', '-append'); #+end_src We identify the system dynamics now that the IFF controller is ON. #+begin_src matlab G_iff = identifyPlant(); #+end_src As shown on figure [[fig:sensitivity_dist_iff]]: - The top platform of the nano-hexapod how behaves as a "free-mass". - The transfer function from direct forces $F_s$ to the relative displacement $D$ is equivalent to the one of an isolated mass. - The transfer function from ground motion $D_g$ to the relative displacement $D$ tends to the transfer function from $D_g$ to the displacement of the granite (the sample is being isolated thanks to IFF). However, as the goal is to make the relative displacement $D$ as small as possible (e.g. to make the sample motion follows the granite motion), this is not a good thing. #+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,'ColorOrderIndex',1); plot(freqs, abs(squeeze(freqresp(G_iff.G_gm('Dx', 'Dgx'), freqs, 'Hz'))), '--', 'HandleVisibility', 'off'); plot(freqs, abs(squeeze(freqresp(G_iff.G_gm('Dy', 'Dgy'), freqs, 'Hz'))), '--', 'HandleVisibility', 'off'); plot(freqs, abs(squeeze(freqresp(G_iff.G_gm('Dz', 'Dgz'), freqs, 'Hz'))), '--', 'HandleVisibility', 'off'); set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log'); ylabel('Amplitude [m/m]'); xlabel('Frequency [Hz]'); legend('location', 'northeast'); 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,'ColorOrderIndex',1); plot(freqs, abs(squeeze(freqresp(G_iff.G_fs('Dx', 'Fsx'), freqs, 'Hz'))), '--', 'HandleVisibility', 'off'); plot(freqs, abs(squeeze(freqresp(G_iff.G_fs('Dy', 'Fsy'), freqs, 'Hz'))), '--', 'HandleVisibility', 'off'); plot(freqs, abs(squeeze(freqresp(G_iff.G_fs('Dz', 'Fsz'), freqs, 'Hz'))), '--', 'HandleVisibility', 'off'); 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_iff.pdf" :var figsize="full-tall" :post pdf2svg(file=*this*, ext="png") <> #+end_src #+NAME: fig:sensitivity_dist_iff #+CAPTION: Sensitivity to disturbance once the IFF controller is applied to the system ([[./figs/sensitivity_dist_iff.png][png]], [[./figs/sensitivity_dist_iff.pdf][pdf]]) [[file:figs/sensitivity_dist_iff.png]] #+begin_warning The order of the models are very high and thus the plots may be wrong. For instance, the plots are not the same when using =minreal=. #+end_warning #+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,'ColorOrderIndex',1); plot(freqs, abs(squeeze(freqresp(minreal(prescale(G_iff.G_dist('Dz', 'Frzz'), {2*pi, 2*pi*1e3})), freqs, 'Hz'))), '--', 'HandleVisibility', 'off'); plot(freqs, abs(squeeze(freqresp(minreal(G_iff.G_dist('Dz', 'Ftyz')), freqs, 'Hz'))), '--', 'HandleVisibility', 'off'); plot(freqs, abs(squeeze(freqresp(minreal(G_iff.G_dist('Dx', 'Ftyx')), freqs, 'Hz'))), '--', 'HandleVisibility', 'off'); 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_iff.pdf" :var figsize="full-normal" :post pdf2svg(file=*this*, ext="png") <> #+end_src #+NAME: fig:sensitivity_dist_stages_iff #+CAPTION: Sensitivity to force disturbances in various stages when IFF is applied ([[./figs/sensitivity_dist_stages_iff.png][png]], [[./figs/sensitivity_dist_stages_iff.pdf][pdf]]) [[file:figs/sensitivity_dist_stages_iff.png]] ** Damped Plant Now, look at the new damped plant to control. 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, 2, 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')))); set(gca,'ColorOrderIndex',1); plot(freqs, abs(squeeze(freqresp(G_iff.G_cart('Dx', 'Fnx'), freqs, 'Hz'))), '--'); plot(freqs, abs(squeeze(freqresp(G_iff.G_cart('Dy', 'Fny'), freqs, 'Hz'))), '--'); plot(freqs, abs(squeeze(freqresp(G_iff.G_cart('Dz', 'Fnz'), freqs, 'Hz'))), '--'); set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log'); ylabel('Amplitude [m/N]'); xlabel('Frequency [Hz]'); ax2 = subplot(2, 2, 2); hold on; plot(freqs, abs(squeeze(freqresp(G.G_cart('Rx', 'Mnx'), freqs, 'Hz')))); plot(freqs, abs(squeeze(freqresp(G.G_cart('Ry', 'Mny'), freqs, 'Hz')))); plot(freqs, abs(squeeze(freqresp(G.G_cart('Rz', 'Mnz'), freqs, 'Hz')))); set(gca,'ColorOrderIndex',1); plot(freqs, abs(squeeze(freqresp(G_iff.G_cart('Rx', 'Mnx'), freqs, 'Hz'))), '--'); plot(freqs, abs(squeeze(freqresp(G_iff.G_cart('Ry', 'Mny'), freqs, 'Hz'))), '--'); plot(freqs, abs(squeeze(freqresp(G_iff.G_cart('Rz', 'Mnz'), freqs, 'Hz'))), '--'); set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log'); ylabel('Amplitude [rad/(Nm)]'); xlabel('Frequency [Hz]'); ax3 = subplot(2, 2, 3); hold on; plot(freqs, 180/pi*angle(squeeze(freqresp(G.G_cart('Dx', 'Fnx'), freqs, 'Hz'))), 'DisplayName', '$\left|D_x / F_{n,x}\right|$'); plot(freqs, 180/pi*angle(squeeze(freqresp(G.G_cart('Dy', 'Fny'), freqs, 'Hz'))), 'DisplayName', '$\left|D_y / F_{n,y}\right|$'); plot(freqs, 180/pi*angle(squeeze(freqresp(G.G_cart('Dz', 'Fnz'), freqs, 'Hz'))), 'DisplayName', '$\left|D_z / F_{n,z}\right|$'); set(gca,'ColorOrderIndex',1); plot(freqs, 180/pi*angle(squeeze(freqresp(G_iff.G_cart('Dx', 'Fnx'), freqs, 'Hz'))), '--', 'HandleVisibility', 'off'); plot(freqs, 180/pi*angle(squeeze(freqresp(G_iff.G_cart('Dy', 'Fny'), freqs, 'Hz'))), '--', 'HandleVisibility', 'off'); plot(freqs, 180/pi*angle(squeeze(freqresp(G_iff.G_cart('Dz', 'Fnz'), freqs, 'Hz'))), '--', 'HandleVisibility', 'off'); 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', 'northwest'); ax4 = subplot(2, 2, 4); hold on; plot(freqs, 180/pi*angle(squeeze(freqresp(G.G_cart('Rx', 'Mnx'), freqs, 'Hz'))), 'DisplayName', '$\left|R_x / M_{n,x}\right|$'); plot(freqs, 180/pi*angle(squeeze(freqresp(G.G_cart('Ry', 'Mny'), freqs, 'Hz'))), 'DisplayName', '$\left|R_y / M_{n,y}\right|$'); plot(freqs, 180/pi*angle(squeeze(freqresp(G.G_cart('Rz', 'Mnz'), freqs, 'Hz'))), 'DisplayName', '$\left|R_z / M_{n,z}\right|$'); set(gca,'ColorOrderIndex',1); plot(freqs, 180/pi*angle(squeeze(freqresp(G_iff.G_cart('Rx', 'Mnx'), freqs, 'Hz'))), '--', 'HandleVisibility', 'off'); plot(freqs, 180/pi*angle(squeeze(freqresp(G_iff.G_cart('Ry', 'Mny'), freqs, 'Hz'))), '--', 'HandleVisibility', 'off'); plot(freqs, 180/pi*angle(squeeze(freqresp(G_iff.G_cart('Rz', 'Mnz'), freqs, 'Hz'))), '--', 'HandleVisibility', 'off'); 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', 'northwest'); linkaxes([ax1,ax2,ax3,ax4],'x'); #+end_src #+HEADER: :tangle no :exports results :results none :noweb yes #+begin_src matlab :var filepath="figs/plant_iff_damped.pdf" :var figsize="full-tall" :post pdf2svg(file=*this*, ext="png") <> #+end_src #+NAME: fig:plant_iff_damped #+CAPTION: Damped Plant after IFF is applied ([[./figs/plant_iff_damped.png][png]], [[./figs/plant_iff_damped.pdf][pdf]]) [[file:figs/plant_iff_damped.png]] However, it increases coupling at low frequency (figure [[fig:plant_iff_coupling]]). #+begin_src matlab :exports none freqs = logspace(0, 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.G_cart(ix, iy), freqs, 'Hz'))), 'k-'); plot(freqs, abs(squeeze(freqresp(G_iff.G_cart(ix, iy), freqs, 'Hz'))), 'k--'); set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log'); ylim([1e-12, 1e-5]); 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]] ** Save #+begin_src matlab save('./active_damping/mat/plants.mat', 'G_iff', '-append'); #+end_src ** Conclusion #+begin_important Integral Force Feedback: - Robust (guaranteed stability) - Acceptable Damping - Increase the sensitivity to disturbances at low frequencies #+end_important * Relative Motion Control <> ** Introduction :ignore: In the Relative Motion Control (RMC), a derivative feedback is applied between the measured actuator displacement to the actuator force input. ** One degree-of-freedom example <> *** 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]] ** 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 open 'simscape/sim_nano_station_id.slx' #+end_src ** Control Design Let's load the undamped plant: #+begin_src matlab load('./active_damping/mat/plants.mat', 'G'); #+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:rmc_plant]]). #+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.G_dleg(['Dm', num2str(i)], ['F', 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.G_dleg(['Dm', num2str(i)], ['F', 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/rmc_plant.pdf" :var figsize="full-tall" :post pdf2svg(file=*this*, ext="png") <> #+end_src #+NAME: fig:rmc_plant #+CAPTION: Transfer function from forces applied in the legs to leg displacement sensor ([[./figs/rmc_plant.png][png]], [[./figs/rmc_plant.pdf][pdf]]) [[file:figs/rmc_plant.png]] The Relative Motion Controller is defined below. A Low pass Filter is added to make the controller transfer function proper. #+begin_src matlab K_rmc = s*50000/(1 + s/2/pi/10000); #+end_src The obtained loop gains are shown in figure [[fig:rmc_open_loop]]. #+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(K_rmc*G.G_dleg(['Dm', num2str(i)], ['F', 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(K_rmc*G.G_dleg(['Dm', num2str(i)], ['F', 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/rmc_open_loop.pdf" :var figsize="full-tall" :post pdf2svg(file=*this*, ext="png") <> #+end_src #+NAME: fig:rmc_open_loop #+CAPTION: Loop Gain for the Integral Force Feedback ([[./figs/rmc_open_loop.png][png]], [[./figs/rmc_open_loop.pdf][pdf]]) [[file:figs/rmc_open_loop.png]] ** Sensitivity to disturbances Let's initialize the system prior to identification. #+begin_src matlab initializeGround(); initializeGranite(); initializeTy(); initializeRy(); initializeRz(); initializeMicroHexapod(); initializeAxisc(); initializeMirror(); initializeNanoHexapod(struct('actuator', 'piezo')); initializeSample(struct('mass', 50)); #+end_src And initialize the controllers. #+begin_src matlab K = tf(zeros(6)); save('./mat/controllers.mat', 'K', '-append'); K_iff = tf(zeros(6)); save('./mat/controllers.mat', 'K_iff', '-append'); K_rmc = -K_rmc*eye(6); save('./mat/controllers.mat', 'K_rmc', '-append'); K_dvf = tf(zeros(6)); save('./mat/controllers.mat', 'K_dvf', '-append'); #+end_src We identify the system dynamics now that the RMC controller is ON. #+begin_src matlab G_rmc = identifyPlant(); #+end_src As shown in figure [[fig:sensitivity_dist_rmc]], RMC control succeed in lowering the sensitivity to disturbances near resonance of the system. #+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,'ColorOrderIndex',1); plot(freqs, abs(squeeze(freqresp(G_rmc.G_gm('Dx', 'Dgx'), freqs, 'Hz'))), '--', 'HandleVisibility', 'off'); plot(freqs, abs(squeeze(freqresp(G_rmc.G_gm('Dy', 'Dgy'), freqs, 'Hz'))), '--', 'HandleVisibility', 'off'); plot(freqs, abs(squeeze(freqresp(G_rmc.G_gm('Dz', 'Dgz'), freqs, 'Hz'))), '--', 'HandleVisibility', 'off'); set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log'); ylabel('Amplitude [m/m]'); xlabel('Frequency [Hz]'); legend('location', 'northeast'); 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,'ColorOrderIndex',1); plot(freqs, abs(squeeze(freqresp(G_rmc.G_fs('Dx', 'Fsx'), freqs, 'Hz'))), '--', 'HandleVisibility', 'off'); plot(freqs, abs(squeeze(freqresp(G_rmc.G_fs('Dy', 'Fsy'), freqs, 'Hz'))), '--', 'HandleVisibility', 'off'); plot(freqs, abs(squeeze(freqresp(G_rmc.G_fs('Dz', 'Fsz'), freqs, 'Hz'))), '--', 'HandleVisibility', 'off'); 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_rmc.pdf" :var figsize="full-tall" :post pdf2svg(file=*this*, ext="png") <> #+end_src #+NAME: fig:sensitivity_dist_rmc #+CAPTION: Sensitivity to disturbance once the RMC controller is applied to the system ([[./figs/sensitivity_dist_rmc.png][png]], [[./figs/sensitivity_dist_rmc.pdf][pdf]]) [[file:figs/sensitivity_dist_rmc.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,'ColorOrderIndex',1); plot(freqs, abs(squeeze(freqresp(G_rmc.G_dist('Dz', 'Frzz'), freqs, 'Hz'))), '--', 'HandleVisibility', 'off'); plot(freqs, abs(squeeze(freqresp(G_rmc.G_dist('Dz', 'Ftyz'), freqs, 'Hz'))), '--', 'HandleVisibility', 'off'); plot(freqs, abs(squeeze(freqresp(G_rmc.G_dist('Dx', 'Ftyx'), freqs, 'Hz'))), '--', 'HandleVisibility', 'off'); 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_rmc.pdf" :var figsize="full-normal" :post pdf2svg(file=*this*, ext="png") <> #+end_src #+NAME: fig:sensitivity_dist_stages_rmc #+CAPTION: Sensitivity to force disturbances in various stages when RMC is applied ([[./figs/sensitivity_dist_stages_rmc.png][png]], [[./figs/sensitivity_dist_stages_rmc.pdf][pdf]]) [[file:figs/sensitivity_dist_stages_rmc.png]] ** Damped Plant #+begin_src matlab :exports none freqs = logspace(0, 3, 1000); figure; ax1 = subplot(2, 2, 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')))); set(gca,'ColorOrderIndex',1); plot(freqs, abs(squeeze(freqresp(G_rmc.G_cart('Dx', 'Fnx'), freqs, 'Hz'))), '--'); plot(freqs, abs(squeeze(freqresp(G_rmc.G_cart('Dy', 'Fny'), freqs, 'Hz'))), '--'); plot(freqs, abs(squeeze(freqresp(G_rmc.G_cart('Dz', 'Fnz'), freqs, 'Hz'))), '--'); set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log'); ylabel('Amplitude [m/N]'); xlabel('Frequency [Hz]'); ax2 = subplot(2, 2, 2); hold on; plot(freqs, abs(squeeze(freqresp(G.G_cart('Rx', 'Mnx'), freqs, 'Hz')))); plot(freqs, abs(squeeze(freqresp(G.G_cart('Ry', 'Mny'), freqs, 'Hz')))); plot(freqs, abs(squeeze(freqresp(G.G_cart('Rz', 'Mnz'), freqs, 'Hz')))); set(gca,'ColorOrderIndex',1); plot(freqs, abs(squeeze(freqresp(G_rmc.G_cart('Rx', 'Mnx'), freqs, 'Hz'))), '--'); plot(freqs, abs(squeeze(freqresp(G_rmc.G_cart('Ry', 'Mny'), freqs, 'Hz'))), '--'); plot(freqs, abs(squeeze(freqresp(G_rmc.G_cart('Rz', 'Mnz'), freqs, 'Hz'))), '--'); set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log'); ylabel('Amplitude [rad/(Nm)]'); xlabel('Frequency [Hz]'); ax3 = subplot(2, 2, 3); hold on; plot(freqs, 180/pi*angle(squeeze(freqresp(G.G_cart('Dx', 'Fnx'), freqs, 'Hz'))), 'DisplayName', '$\left|D_x / F_{n,x}\right|$'); plot(freqs, 180/pi*angle(squeeze(freqresp(G.G_cart('Dy', 'Fny'), freqs, 'Hz'))), 'DisplayName', '$\left|D_y / F_{n,y}\right|$'); plot(freqs, 180/pi*angle(squeeze(freqresp(G.G_cart('Dz', 'Fnz'), freqs, 'Hz'))), 'DisplayName', '$\left|D_z / F_{n,z}\right|$'); set(gca,'ColorOrderIndex',1); plot(freqs, 180/pi*angle(squeeze(freqresp(G_rmc.G_cart('Dx', 'Fnx'), freqs, 'Hz'))), '--', 'HandleVisibility', 'off'); plot(freqs, 180/pi*angle(squeeze(freqresp(G_rmc.G_cart('Dy', 'Fny'), freqs, 'Hz'))), '--', 'HandleVisibility', 'off'); plot(freqs, 180/pi*angle(squeeze(freqresp(G_rmc.G_cart('Dz', 'Fnz'), freqs, 'Hz'))), '--', 'HandleVisibility', 'off'); 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', 'northwest'); ax4 = subplot(2, 2, 4); hold on; plot(freqs, 180/pi*angle(squeeze(freqresp(G.G_cart('Rx', 'Mnx'), freqs, 'Hz'))), 'DisplayName', '$\left|R_x / M_{n,x}\right|$'); plot(freqs, 180/pi*angle(squeeze(freqresp(G.G_cart('Ry', 'Mny'), freqs, 'Hz'))), 'DisplayName', '$\left|R_y / M_{n,y}\right|$'); plot(freqs, 180/pi*angle(squeeze(freqresp(G.G_cart('Rz', 'Mnz'), freqs, 'Hz'))), 'DisplayName', '$\left|R_z / M_{n,z}\right|$'); set(gca,'ColorOrderIndex',1); plot(freqs, 180/pi*angle(squeeze(freqresp(G_rmc.G_cart('Rx', 'Mnx'), freqs, 'Hz'))), '--', 'HandleVisibility', 'off'); plot(freqs, 180/pi*angle(squeeze(freqresp(G_rmc.G_cart('Ry', 'Mny'), freqs, 'Hz'))), '--', 'HandleVisibility', 'off'); plot(freqs, 180/pi*angle(squeeze(freqresp(G_rmc.G_cart('Rz', 'Mnz'), freqs, 'Hz'))), '--', 'HandleVisibility', 'off'); 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', 'northwest'); linkaxes([ax1,ax2,ax3,ax4],'x'); #+end_src #+HEADER: :tangle no :exports results :results none :noweb yes #+begin_src matlab :var filepath="figs/plant_rmc_damped.pdf" :var figsize="full-tall" :post pdf2svg(file=*this*, ext="png") <> #+end_src #+NAME: fig:plant_rmc_damped #+CAPTION: Damped Plant after RMC is applied ([[./figs/plant_rmc_damped.png][png]], [[./figs/plant_rmc_damped.pdf][pdf]]) [[file:figs/plant_rmc_damped.png]] ** Save #+begin_src matlab save('./active_damping/mat/plants.mat', 'G_rmc', '-append'); #+end_src ** Conclusion #+begin_important Relative Motion Control: - #+end_important * Direct Velocity Feedback <> ** Introduction :ignore: In the Relative Motion Control (RMC), a feedback is applied between the measured velocity of the platform to the actuator force input. ** One degree-of-freedom example <> *** Equations #+begin_src latex :file dvf_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] (Kdvf) {$K$}; \draw[->] (Kdvf.west) -- (F) node[above right]{$F$}; \draw[<-] (Kdvf.east) -- ++(0.5, 0) |- (velg.east); \end{tikzpicture} #+end_src #+name: fig:dvf_1dof #+caption: Direct Velocity Feedback applied to a 1dof system #+RESULTS: [[file:figs/dvf_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:dvf_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{DVF}$ is: #+begin_src matlab Kdvf = tf(-(sqrt(k*m)-c)); Kdvf.InputName = {'xdot'}; Kdvf.OutputName = {'F'}; #+end_src And the closed loop system is computed below. #+begin_src matlab sys_dvf = feedback(sys, Kdvf, 'name', +1); #+end_src The obtained sensitivity to disturbances is shown in figure [[fig:dvf_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_dvf('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_dvf('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_dvf('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_dvf('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/dvf_1dof_sensitivitiy.pdf" :var figsize="full-tall" :post pdf2svg(file=*this*, ext="png") <> #+end_src #+NAME: fig:dvf_1dof_sensitivitiy #+CAPTION: Sensitivity to disturbance when DVF is applied on the 1dof system ([[./figs/dvf_1dof_sensitivitiy.png][png]], [[./figs/dvf_1dof_sensitivitiy.pdf][pdf]]) [[file:figs/dvf_1dof_sensitivitiy.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 open 'simscape/sim_nano_station_id.slx' #+end_src ** Control Design Let's load the undamped plant: #+begin_src matlab load('./active_damping/mat/plants.mat', 'G'); #+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:dvf_plant]]). The plant looks to complicated to be reasonably controlled. #+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.G_geoph(['Vm', num2str(i)], ['F', 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.G_geoph(['Vm', num2str(i)], ['F', 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/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 velocity sensor ([[./figs/dvf_plant.png][png]], [[./figs/dvf_plant.pdf][pdf]]) [[file:figs/dvf_plant.png]] ** Conclusion #+begin_important Direct Velocity Feedback: - Not usable #+end_important * Comparison <> ** 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 ** Comparison #+begin_src matlab load('./active_damping/mat/plants.mat', 'G', 'G_iff', 'G_rmc'); #+end_src #+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', 'Undamped'); plot(freqs, abs(squeeze(freqresp(G_iff.G_gm('Dx', 'Dgx'), freqs, 'Hz'))), 'DisplayName', 'IFF'); plot(freqs, abs(squeeze(freqresp(G_rmc.G_gm('Dx', 'Dgx'), freqs, 'Hz'))), 'DisplayName', 'RMC'); set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log'); ylabel('Amplitude [m/m]'); xlabel('Frequency [Hz]'); legend('location', 'northeast'); subplot(2, 1, 2); title('$F_s$ to $D$'); hold on; plot(freqs, abs(squeeze(freqresp(G.G_fs( 'Dx', 'Fsx'), freqs, 'Hz'))), 'DisplayName', 'Undamped'); plot(freqs, abs(squeeze(freqresp(G_iff.G_fs('Dx', 'Fsx'), freqs, 'Hz'))), 'DisplayName', 'IFF'); plot(freqs, abs(squeeze(freqresp(G_rmc.G_fs('Dx', 'Fsx'), freqs, 'Hz'))), 'DisplayName', 'RMC'); set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log'); ylabel('Amplitude [m/N]'); xlabel('Frequency [Hz]'); legend('location', 'northeast'); #+end_src * Conclusion <>