#+TITLE: NASS - Uniaxial Model :DRAWER: #+LANGUAGE: en #+EMAIL: dehaeze.thomas@gmail.com #+AUTHOR: Dehaeze Thomas #+HTML_LINK_HOME: ../index.html #+HTML_LINK_UP: ../index.html #+HTML_HEAD: #+HTML_HEAD: #+BIND: org-latex-image-default-option "scale=1" #+BIND: org-latex-image-default-width "" #+LaTeX_CLASS: scrreprt #+LaTeX_CLASS_OPTIONS: [a4paper, 10pt, DIV=12, parskip=full] #+LaTeX_HEADER_EXTRA: \input{preamble.tex} #+PROPERTY: header-args:matlab :session *MATLAB* #+PROPERTY: header-args:matlab+ :comments org #+PROPERTY: header-args:matlab+ :exports both #+PROPERTY: header-args:matlab+ :results none #+PROPERTY: header-args:matlab+ :eval no-export #+PROPERTY: header-args:matlab+ :noweb yes #+PROPERTY: header-args:matlab+ :mkdirp yes #+PROPERTY: header-args:matlab+ :output-dir figs #+PROPERTY: header-args:matlab+ :tangle no #+PROPERTY: header-args:latex :headers '("\\usepackage{tikz}" "\\usepackage{import}" "\\import{$HOME/Cloud/tikz/org/}{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 file raw replace #+PROPERTY: header-args:latex+ :buffer no #+PROPERTY: header-args:latex+ :tangle no #+PROPERTY: header-args:latex+ :eval no-export #+PROPERTY: header-args:latex+ :exports results #+PROPERTY: header-args:latex+ :mkdirp yes #+PROPERTY: header-args:latex+ :output-dir figs #+PROPERTY: header-args:latex+ :post pdf2svg(file=*this*, ext="png") :END: #+begin_export html

This report is also available as a pdf.


#+end_export #+latex: \clearpage * Introduction :ignore: In this report, a uniaxial model of the Nano Active Stabilization System (NASS) is developed and used to have a first idea of the challenges involved in this complex system. Note that in this document, only the vertical direction is considered (which is the most stiff), but other directions were considered as well and yields similar conclusions. The model is schematically shown in Figure ref:fig:uniaxial_overview_model_sections where the colors are representing the studied parts in different sections. In order to have a relevant model, the micro-station dynamics is first identified and its model is tuned to match the measurements (Section ref:sec:micro_station_model). Then, a model of the nano-hexapod is added on top of the micro-station. With added sample and sensors, this gives a uniaxial dynamical model of the NASS that will be used for further analysis (Section ref:sec:nano_station_model). The disturbances affecting the position accuracy are identified experimentally (Section ref:sec:uniaxial_disturbances) and included in the model for dynamical noise budgeting (Section ref:sec:uniaxial_noise_budgeting). In all the following analysis, there nano-hexapod stiffnesses are considered to better understand the trade-offs and to find the most adequate stiffness. Three sample masses are also considered to verify the robustness of the applied control strategies to a change of sample. Three active damping techniques are then applied on the nano-hexapod. This helps to reduce the effect of disturbances as well as render the system easier to control afterwards (Section ref:sec:uniaxial_active_damping). Once the system is well damped, a feedback position controller is applied, and the obtained performances are compared (Section ref:sec:uniaxial_position_control). Conclusion remarks are given in Section ref:sec:conclusion. #+begin_src latex :file uniaxial_overview_model_sections.pdf \begin{tikzpicture} % ==================== % Parameters % ==================== \def\massw{2.2} % Width of the masses \def\massh{0.8} % Height of the masses \def\spaceh{1.2} % Height of the springs/dampers \def\dispw{0.4} % Width of the dashed line for the displacement \def\disph{0.3} % Height of the arrow for the displacements \def\bracs{0.05} % Brace spacing vertically \def\brach{-12pt} % Brace shift horizontaly \def\fsensh{0.2} % Height of the force sensor \def\velsize{0.2} % Size of the velocity sensor % ==================== % IFF % ==================== % Ground % ==================== \draw[draw=colorblue] (-0.5*\massw, 0) -- (0.5*\massw, 0); \draw[dashed,draw=coloryellow] (0.5*\massw, 0) -- ++(\dispw, 0); \draw[->, color=coloryellow] (0.5*\massw+0.5*\dispw, 0) -- ++(0, 2*\disph) node[right, color=coloryellow]{$x_{f}$}; % ==================== % ==================== % Granite \begin{scope}[shift={(0, 0)}] % Mass \draw[draw=colorblue,fill=colorblue!10!white] (-0.5*\massw, \spaceh) rectangle (0.5*\massw, \spaceh+\massh) node[pos=0.5,color=colorblue]{$m_{g}$}; % Spring, Damper, and Actuator \draw[spring,draw=colorblue] (-0.4*\massw, 0) -- (-0.4*\massw, \spaceh) node[midway, left=0.1, color=colorblue]{$k_{g}$}; \draw[damper={colorblue}{}{}] (0, 0) -- ( 0, \spaceh) node[midway, left=0.2, color=colorblue]{$c_{g}$}; % Legend \draw[decorate, decoration={brace, amplitude=8pt}, xshift=\brach] % (-0.5*\massw, \bracs) -- (-0.5*\massw, \spaceh+\massh-\bracs) node[midway,rotate=90,anchor=south,yshift=10pt]{Granite}; % Displacements \draw[dashed, draw=colorpurple] (0.5*\massw, \spaceh+\massh) -- ++(7.5*\dispw, 0) coordinate(xg); \end{scope} % ==================== % ==================== % Stages \begin{scope}[shift={(0, \spaceh+\massh)}] % Mass \draw[draw=colorblue,fill=colorblue!10!white] (-0.5*\massw, \spaceh) rectangle (0.5*\massw, \spaceh+\massh) node[pos=0.5,color=colorblue]{$m_{t}$}; % Spring, Damper, and Actuator \draw[spring,draw=colorblue] (-0.4*\massw, 0) -- (-0.4*\massw, \spaceh) node[midway, left=0.1,color=colorblue]{$k_{t}$}; \draw[damper={colorblue}{}{}] (0, 0) -- ( 0, \spaceh) node[midway, left=0.2,color=colorblue]{$c_{t}$}; % Disturbance \draw[actuator={0.45}{0.2}{coloryellow}] ( 0.3*\massw, 0) -- (0.3*\massw, \spaceh) node[midway, right=0.1, color=coloryellow](ft){$f_{t}$}; % Legend \draw[decorate, decoration={brace, amplitude=8pt}, xshift=\brach] % (-0.5*\massw, \bracs) -- (-0.5*\massw, \spaceh+\massh-\bracs) node[midway,rotate=90,anchor=south,yshift=10pt]{$T_y$/$R_y$/$R_z$}; \end{scope} % ==================== % ==================== % Hexapod \begin{scope}[shift={(0, 2*(\spaceh+\massh))}] % Mass \draw[draw=colorblue,fill=colorblue!10!white] (-0.5*\massw, \spaceh) rectangle (0.5*\massw, \spaceh+\massh) node[pos=0.5,color=colorblue]{$m_h$}; % Spring, Damper, and Actuator \draw[spring,draw=colorblue] (-0.4*\massw, 0) -- (-0.4*\massw, \spaceh) node[midway, left=0.1,color=colorblue]{$k_h$}; \draw[damper={colorblue}{}{}] (0, 0) -- ( 0, \spaceh) node[midway, left=0.2,color=colorblue]{$c_h$}; % Legend \draw[decorate, decoration={brace, amplitude=8pt}, xshift=\brach] % (-0.5*\massw, \bracs) -- (-0.5*\massw, \spaceh+\massh-\bracs) node[midway,rotate=90,anchor=south,yshift=10pt]{$\mu\text{-hexa}$}; \end{scope} % ==================== % ==================== % NASS \begin{scope}[shift={(0, 3*(\spaceh+\massh))}] % Mass \draw[draw=colorred,fill=colorred!10!white] (-0.5*\massw, \spaceh) rectangle (0.5*\massw, \spaceh+\massh) node[pos=0.5,color=colorred]{$m_{n}$}; % Force Sensor \node[forcesensor={\massw}{\fsensh}{colorgreen}] (fsensn) at (0, \spaceh-\fsensh){}; \node[right, color=colorgreen] (fn) at (fsensn.east) {$f_n$}; % Spring, Damper, and Actuator \draw[spring,draw=colorred] (-0.4*\massw, 0) -- (-0.4*\massw, \spaceh-\fsensh) node[midway, left=0.1,color=colorred]{$k_{n}$}; \draw[damper={colorred}{}{}] (0, 0) -- ( 0, \spaceh-\fsensh) node[midway, left=0.2,color=colorred]{$c_{n}$}; \draw[actuator={0.4}{0.2}{colorred}] ( 0.3*\massw, 0) -- (0.3*\massw, \spaceh-\fsensh) node[midway, right=0.1,color=colorred](f){$f$}; % Legend \draw[decorate, decoration={brace, amplitude=8pt}, xshift=\brach] % (-0.5*\massw, \bracs) -- (-0.5*\massw, \spaceh+\massh-\bracs) node[midway,rotate=90,anchor=south,yshift=10pt]{$\nu\text{-hexa}$}; % Displacements \draw[dashed,draw=colorpurple] (0.5*\massw, \spaceh+\massh) -- ++(7.5*\dispw, 0) coordinate(xnpos); \end{scope} % ==================== % ==================== % sample \begin{scope}[shift={(0, 4*(\spaceh+\massh))}] % Mass \draw[draw=colorred,fill=colorred!10!white] (-0.3*\massw, 0) rectangle (0.3*\massw, \massh) node[pos=0.5,color=colorred]{$m_{s}$}; % External Force \draw[->, color=coloryellow] (0, \massh) node[]{$\bullet$} -- ++(0, 0.5*\massh) node[right, color=coloryellow]{$f_s$}; \end{scope} % ==================== % Measured displacement \draw[<->, dashed, draw=colorpurple] ($(xg)+(-0.1, 0)$) -- node[left, color=colorpurple](d){$d$} ($(xnpos)+(-0.1, 0)$); % ==================== % IFF Control \node[block={2em}{2em}, right=1.0 of fn, color=colorgreen, fill=colorgreen!10!white] (iff) {$K_{\textsc{IFF}}$}; \node[addb, draw=colorgreen, fill=colorgreen!10!white, right=0.5 of f.east] (ctrladd) {}; \node[block={2em}{2em}, color=colorpurple, fill=colorpurple!10!white] (Khac) at (ctrladd|-d) {$K_{\textsc{HAC}}$}; \draw[->, draw=colorgreen] (fn.east) -- (iff.west); \draw[->, draw=colorgreen] (iff.south) |- (ctrladd.east); \draw[->, draw=colorgreen] (ctrladd.west) -- (f.east); \draw[->, draw=colorpurple] (d.west) -- (Khac.east); \draw[->, draw=colorpurple] (Khac.north) -- (ctrladd.south) node[below right, color=colorpurple]{$f^{\prime}$}; % ==================== \end{tikzpicture} #+end_src #+name: fig:uniaxial_overview_model_sections #+caption: Uniaxial Micro-Station model in blue (Section ref:sec:micro_station_model), Nano-Hexapod and sample models in red (Section ref:sec:nano_station_model), Disturbances in yellow (Section ref:sec:uniaxial_disturbances), Active Damping in green (Section ref:sec:uniaxial_active_damping) and Position control in purple (Section ref:sec:uniaxial_position_control) #+RESULTS: [[file:figs/uniaxial_overview_model_sections.png]] * Micro Station Model :PROPERTIES: :HEADER-ARGS:matlab+: :tangle matlab/uniaxial_1_micro_station_model.m :END: <> ** Introduction :ignore: In this section, a uni-axial model of the micro-station is tuned in order to match measurements made on the micro-station The measurement setup is shown in Figure ref:fig:micro_station_first_meas_dynamics where several geophones are fixed to the micro-station and an instrumented hammer is used to inject forces on different stages of the micro-station. From the measured frequency response functions (FRF), the model can be tuned to approximate the uniaxial dynamics of the micro-station. #+name: fig:micro_station_first_meas_dynamics #+caption: Experimental Setup for the first dynamical measurements on the Micro-Station. Geophones are fixed to the micro-station, and the granite as well as the micro-hexapod's top platform are impact with an instrumented hammer #+attr_latex: :width \linewidth [[file:figs/micro_station_first_meas_dynamics.jpg]] ** 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 :noweb yes <> #+end_src #+begin_src matlab :eval no :noweb yes <> #+end_src #+begin_src matlab :noweb yes <> #+end_src #+begin_src matlab %% Uniaxial Simscape model name mdl = 'nass_uniaxial_model'; #+end_src #+begin_src matlab %% Frequency Vector [Hz] freqs = logspace(0, 3, 1000); #+end_src ** Measured dynamics The measurement setup is schematically shown in Figure ref:fig:micro_station_meas_dynamics_schematic where: - Two hammer hits are performed, one on the Granite (force $F_g$), and one on the micro-hexapod's top platform (force $F_h$) - The inertial motion of the granite $x_g$ and the micro-hexapod's top platform $x_h$ are measured using geophones. From the forces applied by the instrumented hammer and the responses of the geophones, the following frequency response functions can be computed: - from $F_h$ to $d_h$ (i.e. the compliance of the micro-station) - from $F_g$ to $d_h$ (or from $F_h$ to $d_g$) - from $F_g$ to $d_g$ #+begin_src latex :file micro_station_meas_dynamics_schematic.pdf \begin{tikzpicture} % Parameters \def\blockw{6.0cm} \def\blockh{1.2cm} \def\tiltdeg{0} \coordinate[] (rotationpoint) at (0, 4.5*\blockh); \begin{scope}[rotate around={\tiltdeg:(rotationpoint)}] % Tilt \path[] ([shift=(-120:4*\blockh)]rotationpoint) coordinate(beginarc) arc (-120:-110:4*\blockh) % -- ([shift=(-70:4*\blockh)]rotationpoint) arc (-70:-60:4*\blockh)% |- ++(-0.15*\blockw, 0.6*\blockh) coordinate (spindlene)% |- ($(beginarc) + (0.15*\blockw, 0.2*\blockh)$) coordinate (spindlesw) -- ++(0, 0.4*\blockh) coordinate(tiltte) -| cycle; % Spindle \coordinate[] (spindlese) at (spindlesw-|spindlene); \draw[fill=black!30] ($(spindlese)+(-0.1,0.1)+(-0.1*\blockw, 0)$) -| ($(spindlene)+(-0.1, 0)$) -| coordinate[pos=0.25](spindletop) ($(spindlesw)+(0.1,0.1)$) -| ++(0.1*\blockw, -\blockh) -| coordinate[pos=0.25](spindlebot) cycle; % \draw[dashed, color=black!60] ($(spindletop)+(0, 0.2)$) -- ($(spindlebot)+(0,-0.2)$); % Tilt \draw[fill=black!60] ([shift=(-120:4*\blockh)]rotationpoint) coordinate(beginarc) arc (-120:-110:4*\blockh) % -- ([shift=(-70:4*\blockh)]rotationpoint) arc (-70:-60:4*\blockh)% |- coordinate (tiltne) ++(-0.15*\blockw, 0.6*\blockh) coordinate (spindlene)% |- ($(beginarc) + (0.15*\blockw, 0.2*\blockh)$) coordinate (spindlesw) -- ++(0, 0.4*\blockh) -| cycle; % Micro-Hexapod \begin{scope}[shift={(spindletop)}] % Parameters definitions \def\baseh{0.22*\blockh} % Height of the base \def\naceh{0.18*\blockh} % Height of the nacelle \def\baser{0.22*\blockw} % Radius of the base \def\nacer{0.18*\blockw} % Radius of the nacelle \def\armr{0.2*\blockh} % Radius of the arms \def\basearmborder{0.2} \def\nacearmborder{0.2} \def\xnace{0} \def\ynace{\blockh-\naceh} \def\anace{0} \def\xbase{0} \def\ybase{0} \def\abase{0} % Hexapod1 \begin{scope}[shift={(\xbase, \ybase)}, rotate=\abase] % Base \draw[fill=white] (-\baser, 0) coordinate[](uhexabot) rectangle (\baser, \baseh); \coordinate[] (armbasel) at (-\baser+\basearmborder+\armr, \baseh); \coordinate[] (armbasec) at (0, \baseh); \coordinate[] (armbaser) at (\baser-\basearmborder-\armr, \baseh); \begin{scope}[shift={(\xnace, \ynace)}, rotate=\anace] \draw[fill=white] (-\nacer, 0) rectangle (\nacer, \naceh); \coordinate[] (uhexatop) at (0, \naceh); \coordinate[] (armnacel) at (-\nacer+\nacearmborder+\armr, 0); \coordinate[] (armnacec) at (0, 0); \coordinate[] (armnacer) at (\nacer-\nacearmborder-\armr, 0); \end{scope} \draw[] (armbasec) -- (armnacer); \draw[] (armbasec) -- (armnacel); \draw[] (armbasel) -- coordinate(mhexaw) (armnacel); \draw[] (armbasel) -- (armnacec); \draw[] (armbaser) -- (armnacec); \draw[] (armbaser) -- coordinate(mhexae) (armnacer); \end{scope} \end{scope} \begin{scope}[shift={(uhexatop)}] % Geophone - Hexapod \draw[draw=colorgreen, fill=colorgreen!10!white] (-0.3, 0) rectangle node[midway, color=colorgreen, rotate=90]{\tiny geophone} (0.3, 1.2); \draw[rounded corners=0.1, draw=colorgreen, fill=colorgreen!10!white] (-0.1, 1.2) -- ++(0, 0.1) -- ++(0.1, 0.1) -- ++(0.1, -0.1) -- ++(0, -0.1) --cycle; \node[fill,shape=circle,minimum size=3pt,inner sep=0pt, color=colorgreen] at (0, 1.4){}; \draw[out=90, in=180, draw=colorgreen] (0, 1.4) to ++(0.4, 0.2) node[right, color=colorgreen]{$x_h$}; \end{scope} \begin{scope}[shift={(uhexatop)}] % Instrumented Hammer - Hexapod \begin{scope}[shift={(-1.5, 0)}] \draw[fill=white, rounded corners=0.2, draw=colorblue, fill=colorblue!10!white] (-0.5, 0.42) rectangle (0.5, 0.58); \draw[fill=white, rounded corners=0.2, draw=colorblue, fill=colorblue!10!white] (0.5, 0.15) rectangle (0.7, 0.8); \draw[fill=white, rounded corners=0.2, color=colorblue] (0.55, 0.15) rectangle (0.65, 0); \draw[out=180, in=0, draw=colorblue] (-0.5, 0.5) to ++(-0.6, -0.1) node[above, color=colorblue]{$F_h$}; \node[fill,shape=circle,minimum size=3pt,inner sep=0pt, color=colorblue] at (-0.5, 0.5){}; \end{scope} \end{scope} \end{scope} \begin{scope}[shift={(0, -0.3*\blockh)}] % Translation Stage - fixed part \draw[fill=black!40] (-0.5*\blockw, 0) coordinate[](tyb) rectangle (0.5*\blockw, 0.15*\blockh); \coordinate[] (measposbot) at (0.5*\blockw, 0); % Translation Stage - mobile part \draw[fill=black!10, fill opacity=0.5] (-0.5*\blockw, 0.2*\blockh) -- (-0.5*\blockw, 1.5*\blockh) coordinate[](tyt) -- (0.5*\blockw, 1.5*\blockh) -- (0.5*\blockw, 0.2*\blockh) -- (0.35*\blockw, 0.2*\blockh) -- (0.35*\blockw, 0.8*\blockh) -- (-0.35*\blockw, 0.8*\blockh) -- (-0.35*\blockw, 0.2*\blockh) -- cycle; % Translation Guidance \draw[dashed, color=black!60] ($(-0.5*\blockw, 0)+( 0.075*\blockw,0.5*\blockh)$) circle (0.2*\blockh); \draw[dashed, color=black!60] ($( 0.5*\blockw, 0)+(-0.075*\blockw,0.5*\blockh)$) circle (0.2*\blockh); % \draw[fill, color=black] ($( 0.5*\blockw, 0)+(-0.075*\blockw,0.5*\blockh)$) circle (0.04); % \node[draw, circle, inner sep=0pt, minimum size=0.3cm, label=above:$T_y$] at ($( 0.5*\blockw, 0)+(-0.075*\blockw,0.5*\blockh)$){}; % Tilt Guidance \draw[dashed, color=black!60] ([shift=(-107:4.1*\blockh)]rotationpoint) arc (-107:-120:4.1*\blockh); \draw[dashed, color=black!60] ([shift=( -73:4.1*\blockh)]rotationpoint) arc (-73:-60:4.1*\blockh); \begin{scope}[shift={(4.0, 0)}] % Geophone - Granite \draw[draw=colorgreen, fill=colorgreen!10!white] (-0.3, 0) rectangle node[midway, color=colorgreen, rotate=90]{\tiny geophone} (0.3, 1.2); \draw[rounded corners=0.1, draw=colorgreen, fill=colorgreen!10!white] (-0.1, 1.2) -- ++(0, 0.1) -- ++(0.1, 0.1) -- ++(0.1, -0.1) -- ++(0, -0.1) --cycle; \node[fill,shape=circle,minimum size=3pt,inner sep=0pt, color=colorgreen] at (0, 1.4){}; \draw[out=90, in=180, draw=colorgreen] (0, 1.4) to ++(0.4, 0.2) node[right, color=colorgreen]{$x_g$}; \end{scope} \begin{scope}[shift={(-4.0, 0)}] % Instrumented Hammer - Granite \draw[fill=white, rounded corners=0.2, draw=colorblue, fill=colorblue!10!white] (-0.5, 0.42) rectangle (0.5, 0.58); \draw[fill=white, rounded corners=0.2, draw=colorblue, fill=colorblue!10!white] (0.5, 0.15) rectangle (0.7, 0.8); \draw[fill=white, rounded corners=0.2, color=colorblue] (0.55, 0.15) rectangle (0.65, 0); \draw[out=180, in=0, draw=colorblue] (-0.5, 0.5) to ++(-0.6, -0.1) node[above, color=colorblue]{$F_g$}; \node[fill,shape=circle,minimum size=3pt,inner sep=0pt, color=colorblue] at (-0.5, 0.5){}; \end{scope} \end{scope} % Granite \draw[fill=black!40] (-0.8*\blockw, -0.3*\blockh) rectangle node[midway]{Granite} (0.8*\blockw, -1.5*\blockh); % Vertical line % \draw[dashed, color=black] (spindlebot) -- ++(0, 2*\blockh); % \node[] at ($(spindlebot)+(0, 1.1*\blockh)$) {\AxisRotator[rotate=-90]}; % \node[right, shift={(0.3,0)}] at ($(spindlebot)+(0, 1.1*\blockh)$) {$\theta_z$}; % Axis \begin{scope}[shift={(-0.6*\blockw, 2.5*\blockh)}] \def\axissize{0.8cm} \draw[->] (0, 0) -- ++(0, \axissize) node[right]{$z$}; \draw[->] (0, 0) -- ++(-\axissize, 0) node[above]{$x$}; \draw[fill, color=black] (0, 0) circle (0.05*\axissize); \node[draw, circle, inner sep=0pt, minimum size=0.4*\axissize, label=right:$y$] (yaxis) at (0, 0){}; \end{scope} \end{tikzpicture} #+end_src #+name: fig:micro_station_meas_dynamics_schematic #+caption: Measurement setup - Schematic #+RESULTS: [[file:figs/micro_station_meas_dynamics_schematic.png]] Due to the bad coherence at low frequency, the frequency response functions are only shown between 20 and 200Hz (Figure ref:fig:uniaxial_measured_frf_vertical). #+begin_src matlab %% Load measured FRF load('meas_microstation_frf.mat'); #+end_src #+begin_src matlab :exports none :results none %% Measured Frequency Response Functions in the vertical direction figure; tiledlayout(3, 1, 'TileSpacing', 'Compact', 'Padding', 'None'); ax1 = nexttile([2,1]); hold on; plot(f(f>20), abs(frf_Fhx_to_Dhx(f>20)), ... 'DisplayName', '$D_{h}/F_{h}$'); plot(f(f>20), abs(frf_Fgx_to_Dhx(f>20)), ... 'DisplayName', '$D_{h}/F_{g}$'); plot(f(f>20), abs(frf_Fgx_to_Dgx(f>20)), ... 'DisplayName', '$D_{g}/F_{g}$'); hold off; set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log'); ylabel('Amplitude [m/N]'); set(gca, 'XTickLabel',[]); ylim([1e-10, 2e-6]); legend('location', 'northwest', 'FontSize', 8, 'NumColumns', 1); ax2 = nexttile; hold on; plot(f(f>20), 180/pi*unwrap(angle(frf_Fhx_to_Dhx(f>20)))); plot(f(f>30), 180/pi*unwrap(angle(frf_Fgx_to_Dhx(f>30)))); plot(f(f>20), 180/pi*unwrap(angle(frf_Fgx_to_Dgx(f>20)))); hold off; set(gca, 'XScale', 'log'); set(gca, 'YScale', 'lin'); xlabel('Frequency [Hz]'); ylabel('Phase [deg]'); hold off; yticks(-360:90:360); ylim([-360, 10]); linkaxes([ax1,ax2],'x'); xlim([1, 500]); #+end_src #+begin_src matlab :tangle no :exports results :results file replace exportFig('figs/uniaxial_measured_frf_vertical.pdf', 'width', 'wide', 'height', 'tall'); #+end_src #+name: fig:uniaxial_measured_frf_vertical #+caption: Measured Frequency Response Functions in the vertical direction #+RESULTS: [[file:figs/uniaxial_measured_frf_vertical.png]] ** Uniaxial Model The uni-axial model of the micro-station is shown in Figure ref:fig:uniaxial_comp_frf_meas_model, with: - Disturbances: - $x_f$: Floor motion - $f_t$: Stage vibrations - Hammer impacts: $F_h$ and $F_g$. - Geophones: $x_h$ and $x_g$ #+begin_src latex :file uniaxial_model_micro_station.pdf \begin{tikzpicture} % ==================== % Parameters % ==================== \def\massw{2.2} % Width of the masses \def\massh{0.8} % Height of the masses \def\spaceh{1.2} % Height of the springs/dampers \def\dispw{0.4} % Width of the dashed line for the displacement \def\disph{0.4} % Height of the arrow for the displacements \def\bracs{0.05} % Brace spacing vertically \def\brach{-12pt} % Brace shift horizontaly \def\fsensh{0.2} % Height of the force sensor \def\velsize{0.2} % Size of the velocity sensor % ==================== % ==================== % Floor % ==================== \draw (-0.5*\massw, 0) -- (0.5*\massw, 0); \draw[dashed] (0.5*\massw, 0) -- ++(\dispw, 0); \draw[->, draw=colorred] (0.5*\massw+0.5*\dispw, 0) -- ++(0, \disph) node[right, color=colorred]{$x_{f}$}; % ==================== % ==================== % Granite \begin{scope}[shift={(0, 0)}] % Mass \draw[fill=white] (-0.5*\massw, \spaceh) rectangle (0.5*\massw, \spaceh+\massh) node[pos=0.5]{$m_{g}$}; % Spring, Damper, and Actuator \draw[spring] (-0.4*\massw, 0) -- (-0.4*\massw, \spaceh) node[midway, left=0.1]{$k_{g}$}; \draw[damper] (0, 0) -- ( 0, \spaceh) node[midway, left=0.2]{$c_{g}$}; % Legend \draw[decorate, decoration={brace, amplitude=8pt}, xshift=\brach] % (-0.5*\massw, \bracs) -- (-0.5*\massw, \spaceh+\massh-\bracs) node[midway,rotate=90,anchor=south,yshift=10pt]{Granite}; % Displacement \draw[dashed] (0.5*\massw, \spaceh+\massh) -- ++(\dispw, 0); \draw[->] (0.5*\massw+0.5*\dispw, \spaceh+\massh) -- ++(0, \disph) node[right]{$x_{g}$}; \end{scope} % ==================== % ==================== % Stages \begin{scope}[shift={(0, \spaceh+\massh)}] % Mass \draw[fill=white] (-0.5*\massw, \spaceh) rectangle (0.5*\massw, \spaceh+\massh) node[pos=0.5]{$m_{t}$}; % Spring, Damper, and Actuator \draw[spring] (-0.4*\massw, 0) -- (-0.4*\massw, \spaceh) node[midway, left=0.1]{$k_{t}$}; \draw[damper] (0, 0) -- ( 0, \spaceh) node[midway, left=0.2]{$c_{t}$}; % Disturbance \draw[actuator={0.45}{0.2}{colorred}] ( 0.3*\massw, 0) -- (0.3*\massw, \spaceh) node[midway, right=0.1, color=colorred](ft){$f_t$}; % Legend \draw[decorate, decoration={brace, amplitude=8pt}, xshift=\brach] % (-0.5*\massw, \bracs) -- (-0.5*\massw, \spaceh+\massh-\bracs) node[midway,rotate=90,anchor=south,yshift=10pt]{$T_y$/$R_y$/$R_z$}; % External Force \draw[->, color=colorblue] (0, 0)node[branch] -- ++(0, 1.5*\dispw) node[below right]{$F_g$}; % % Displacement % \draw[dashed] (0.5*\massw, \spaceh+\massh) -- ++(\dispw, 0); % \draw[->] (0.5*\massw+0.5*\dispw, \spaceh+\massh) -- ++(0, \disph) node[right]{$x_{t}$}; \end{scope} % ==================== % ==================== % Hexapod \begin{scope}[shift={(0, 2*(\spaceh+\massh))}] % Mass \draw[fill=white] (-0.5*\massw, \spaceh) rectangle (0.5*\massw, \spaceh+\massh) node[pos=0.5]{$m_{h}$}; % Spring, Damper, and Actuator \draw[spring] (-0.4*\massw, 0) -- (-0.4*\massw, \spaceh) node[midway, left=0.1]{$k_{h}$}; \draw[damper] (0, 0) -- ( 0, \spaceh) node[midway, left=0.2]{$c_{h}$}; % Legend \draw[decorate, decoration={brace, amplitude=8pt}, xshift=\brach] % (-0.5*\massw, \bracs) -- (-0.5*\massw, \spaceh+\massh-\bracs) node[midway,rotate=90,anchor=south,yshift=10pt]{$\mu\text{Hexa}$}; % Displacement \draw[dashed] (0.5*\massw, \spaceh+\massh) -- ++(\dispw, 0); \draw[->] (0.5*\massw+0.5*\dispw, \spaceh+\massh) -- ++(0, \disph) node[right]{$x_{h}$}; % External Force \draw[->, color=colorblue] (0, \spaceh+\massh)node[branch] -- ++(0, 1.5*\dispw) node[below right]{$F_h$}; \end{scope} % ==================== \end{tikzpicture} #+end_src #+name: fig:uniaxial_model_micro_station #+caption: Uniaxial model of the micro-station #+RESULTS: [[file:figs/uniaxial_model_micro_station.png]] Masses are estimated from the CAD. #+BEGIN_SRC matlab %% Parameters - Mass mh = 15; % Micro Hexapod [kg] mt = 1200; % Ty + Ry + Rz [kg] mg = 2500; % Granite [kg] #+END_SRC And stiffnesses from the data-sheet of stage manufacturers. #+BEGIN_SRC matlab %% Parameters - Stiffnesses kh = 6.11e+07; % [N/m] kt = 5.19e+08; % [N/m] kg = 9.50e+08; % [N/m] #+END_SRC The damping coefficients are tuned to match the identified damping from the measurements. #+BEGIN_SRC matlab %% Parameters - damping ch = 2*0.05*sqrt(kh*mh); % [N/(m/s)] ct = 2*0.05*sqrt(kt*mt); % [N/(m/s)] cg = 2*0.08*sqrt(kg*mg); % [N/(m/s)] #+END_SRC #+begin_src matlab :exports none :tangle no %% Save model parameters save('./matlab/mat/uniaxial_micro_station_parameters.mat', 'mh', 'mt', 'mg', 'ch', 'ct', 'cg', 'kh', 'kt', 'kg') #+end_src #+begin_src matlab :exports none :eval no %% Save model parameters save('./mat/uniaxial_micro_station_parameters.mat', 'mh', 'mt', 'mg', 'ch', 'ct', 'cg', 'kh', 'kt', 'kg') #+end_src #+begin_src matlab :exports none %% Disable the Nano-Hexpod for now model_config = struct(); model_config.nhexa = "none"; model_config.controller = "open_loop"; %% Identify the transfer function from u to taum clear io; io_i = 1; io(io_i) = linio([mdl, '/micro_station/Fg'], 1, 'openinput'); io_i = io_i + 1; % Hammer on Granite io(io_i) = linio([mdl, '/micro_station/Fh'], 1, 'openinput'); io_i = io_i + 1; % Hammer on Hexapod io(io_i) = linio([mdl, '/micro_station/xg'], 1, 'openoutput'); io_i = io_i + 1; % Absolute motion of Granite io(io_i) = linio([mdl, '/micro_station/xh'], 1, 'openoutput'); io_i = io_i + 1; % Absolute motion of Hexapod %% Perform the model extraction G_id = linearize(mdl, io, 0.0); G_id.InputName = {'Fg', 'Fh'}; G_id.OutputName = {'Dg', 'Dh'}; #+end_src ** Comparison of the model and measurements The comparison between the measurements and the model is done in Figure ref:fig:uniaxial_comp_frf_meas_model. As the model is simplistic, the goal is not to match exactly the measurement but to have a first approximation. More accurate models will be used later on. #+begin_src matlab :exports none :results none %% Comparison of the measured FRF and identified ones from the uni-axial model figure; tiledlayout(3, 1, 'TileSpacing', 'Compact', 'Padding', 'None'); ax1 = nexttile([2,1]); hold on; plot(f(f>20), abs(frf_Fhz_to_Dhz(f>20)), '-', 'color', colors(1,:), 'DisplayName', '$D_{h,z}/F_{h,z}$'); plot(f(f>20), abs(frf_Fgz_to_Dhz(f>20)), '-', 'color', colors(2,:), 'DisplayName', '$D_{h,z}/F_{g,z}$'); plot(f(f>20), abs(frf_Fgz_to_Dgz(f>20)), '-', 'color', colors(3,:), 'DisplayName', '$D_{g,z}/F_{g,z}$'); plot(freqs, abs(squeeze(freqresp(G_id('Dh', 'Fh'), freqs, 'Hz'))), '--', 'color', colors(1,:), 'DisplayName', '$D_{h,z}/F_{h,z}$ (model)'); plot(freqs, abs(squeeze(freqresp(G_id('Dh', 'Fg'), freqs, 'Hz'))), '--', 'color', colors(2,:), 'DisplayName', '$D_{h,z}/F_{g,z}$ (model)'); plot(freqs, abs(squeeze(freqresp(G_id('Dg', 'Fg'), freqs, 'Hz'))), '--', 'color', colors(3,:), 'DisplayName', '$D_{g,z}/F_{g,z}$ (model)'); hold off; set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log'); ylabel('Amplitude [m/N]'); set(gca, 'XTickLabel',[]); ylim([1e-10, 2e-7]); legend('location', 'northwest', 'FontSize', 8, 'NumColumns', 2); ax2 = nexttile; hold on; plot(freqs, 180/pi*unwrap(angle(squeeze(freqresp(G_id('Dh', 'Fh'), freqs, 'Hz')))), '--', 'color', colors(1,:)); plot(freqs, 180/pi*unwrap(angle(squeeze(freqresp(G_id('Dh', 'Fg'), freqs, 'Hz')))), '--', 'color', colors(2,:)); plot(freqs, 180/pi*unwrap(angle(squeeze(freqresp(G_id('Dg', 'Fg'), freqs, 'Hz')))), '--', 'color', colors(3,:)); plot(f(f>20), 180/pi*unwrap(angle(frf_Fhx_to_Dhx(f>20))), '-', 'color', colors(1,:)); plot(f(f>30), 180/pi*unwrap(angle(frf_Fgx_to_Dhx(f>30))), '-', 'color', colors(2,:)); plot(f(f>20), 180/pi*unwrap(angle(frf_Fgx_to_Dgx(f>20))), '-', 'color', colors(3,:)); hold off; set(gca, 'XScale', 'log'); set(gca, 'YScale', 'lin'); xlabel('Frequency [Hz]'); ylabel('Phase [deg]'); hold off; yticks(-360:90:360); ylim([-360, 90]); linkaxes([ax1,ax2],'x'); xlim([1, 500]); #+end_src #+begin_src matlab :tangle no :exports results :results file replace exportFig('figs/uniaxial_comp_frf_meas_model.pdf', 'width', 'wide', 'height', 'tall'); #+end_src #+name: fig:uniaxial_comp_frf_meas_model #+caption: Comparison of the measured FRF and identified ones from the uni-axial model #+RESULTS: [[file:figs/uniaxial_comp_frf_meas_model.png]] * Nano-Hexapod Model :PROPERTIES: :HEADER-ARGS:matlab+: :tangle matlab/uniaxial_2_nano_hexapod_model.m :END: <> ** Introduction :ignore: A model of the nano-hexapod and sample is now added on top of the uni-axial model of the micro-station (Figure ref:fig:uniaxial_model_micro_station-nass). Disturbances (shown in red) are: - $f_s$: direct forces applied to the sample (for instance cable forces) - $f_t$: disturbances coming from the imperfect stage scanning performances - $x_f$: floor motion The control signal is the force applied by the nano-hexapod $f$ and the measurement is the relative motion between the sample and the granite $d$. The sample is here considered as a rigid body and rigidly fixed to the nano-hexapod. The effect of having resonances between the sample's point of interest and the nano-hexapod actuator will be considered in further analysis. #+begin_src latex :file uniaxial_model_micro_station-nass.pdf \begin{tikzpicture} % ==================== % Parameters % ==================== \def\massw{2.2} % Width of the masses \def\massh{0.8} % Height of the masses \def\spaceh{1.2} % Height of the springs/dampers \def\dispw{0.4} % Width of the dashed line for the displacement \def\disph{0.3} % Height of the arrow for the displacements \def\bracs{0.05} % Brace spacing vertically \def\brach{-12pt} % Brace shift horizontaly \def\fsensh{0.2} % Height of the force sensor \def\velsize{0.2} % Size of the velocity sensor % ==================== % ==================== % Ground % ==================== \draw (-0.5*\massw, 0) -- (0.5*\massw, 0); \draw[dashed] (0.5*\massw, 0) -- ++(\dispw, 0); \draw[->, color=colorred] (0.5*\massw+0.5*\dispw, 0) -- ++(0, 2*\disph) node[right, color=colorred]{$x_{f}$}; % ==================== % ==================== % Marble \begin{scope}[shift={(0, 0)}] % Mass \draw[fill=white] (-0.5*\massw, \spaceh) rectangle (0.5*\massw, \spaceh+\massh) node[pos=0.5]{$m_{g}$}; % Spring, Damper, and Actuator \draw[spring] (-0.4*\massw, 0) -- (-0.4*\massw, \spaceh) node[midway, left=0.1]{$k_{g}$}; \draw[damper] (0, 0) -- ( 0, \spaceh) node[midway, left=0.2]{$c_{g}$}; % Legend \draw[decorate, decoration={brace, amplitude=8pt}, xshift=\brach] % (-0.5*\massw, \bracs) -- (-0.5*\massw, \spaceh+\massh-\bracs) node[midway,rotate=90,anchor=south,yshift=10pt]{Granite}; % Displacements \draw[dashed] (0.5*\massw, \spaceh+\massh) -- ++(2*\dispw, 0) coordinate(xm) -- ++(\dispw, 0) coordinate(dbot); \end{scope} % ==================== % ==================== % Stages \begin{scope}[shift={(0, \spaceh+\massh)}] % Mass \draw[fill=white] (-0.5*\massw, \spaceh) rectangle (0.5*\massw, \spaceh+\massh) node[pos=0.5]{$m_{t}$}; % % Spring, Damper, and Actuator \draw[spring] (-0.4*\massw, 0) -- (-0.4*\massw, \spaceh) node[midway, left=0.1]{$k_{t}$}; \draw[damper] (0, 0) -- ( 0, \spaceh) node[midway, left=0.2]{$c_{t}$}; \draw[actuator={0.45}{0.2}{colorred}] ( 0.3*\massw, 0) -- (0.3*\massw, \spaceh) node[midway, right=0.1, color=colorred](ft){$f_{t}$}; Legend \draw[decorate, decoration={brace, amplitude=8pt}, xshift=\brach] % (-0.5*\massw, \bracs) -- (-0.5*\massw, \spaceh+\massh-\bracs) node[midway,rotate=90,anchor=south,yshift=10pt]{$T_y$/$R_y$/$R_z$}; \end{scope} % ==================== % ==================== % Hexapod \begin{scope}[shift={(0, 2*(\spaceh+\massh))}] % Mass \draw[fill=white] (-0.5*\massw, \spaceh) rectangle (0.5*\massw, \spaceh+\massh) node[pos=0.5]{$m_{h}$}; % Spring, Damper, and Actuator \draw[spring] (-0.4*\massw, 0) -- (-0.4*\massw, \spaceh) node[midway, left=0.1]{$k_{h}$}; \draw[damper] (0, 0) -- ( 0, \spaceh) node[midway, left=0.2]{$c_{h}$}; % Legend \draw[decorate, decoration={brace, amplitude=8pt}, xshift=\brach] % (-0.5*\massw, \bracs) -- (-0.5*\massw, \spaceh+\massh-\bracs) node[midway,rotate=90,anchor=south,yshift=10pt]{$\mu\text{-hexa}$}; \end{scope} % ==================== % ==================== % NASS \begin{scope}[shift={(0, 3*(\spaceh+\massh))}] % Mass \draw[fill=colorblue!10!white, draw=colorblue] (-0.5*\massw, \spaceh) rectangle (0.5*\massw, \spaceh+\massh) node[pos=0.5,color=colorblue]{$m_{n}$}; % Spring, Damper, and Actuator \draw[spring, draw=colorblue] (-0.4*\massw, 0) -- (-0.4*\massw, \spaceh) node[midway, left=0.1, color=colorblue]{$k_{n}$}; \draw[damper={colorblue}{}{}] (0, 0) -- ( 0, \spaceh) node[midway, left=0.2, color=colorblue]{$c_{n}$}; \draw[actuator={0.4}{0.2}{colorblue}] ( 0.3*\massw, 0) -- (0.3*\massw, \spaceh) node[midway, right=0.1, color=colorblue](F){$f$}; % Displacements \draw[dashed] (0.5*\massw, \spaceh+\massh) -- ++(2*\dispw, 0) coordinate(xn) -- ++(\dispw, 0) coordinate(drtop); % Legend \draw[decorate, decoration={brace, amplitude=8pt}, xshift=\brach] % (-0.5*\massw, \bracs) -- (-0.5*\massw, \spaceh+\massh-\bracs) node[midway,rotate=90,anchor=south,yshift=10pt]{$\nu\text{-hexa}$}; \end{scope} % ==================== % ==================== % sample \begin{scope}[shift={(0, 4*(\spaceh+\massh))}] % Mass \draw[fill=colorgreen!10!white, draw=colorgreen] (-0.3*\massw, 0) rectangle (0.3*\massw, \massh) node[pos=0.5,color=colorgreen]{$m_{s}$}; % External Force \draw[->, color=colorred] (0, \massh) node[]{$\bullet$} -- ++(0, 0.5*\massh) node[right, color=colorred]{$f_s$}; \end{scope} % ==================== % ==================== % Measured Displacement \draw[<->, dashed] (xm) -- node[midway, right]{$d$} (xn); % ==================== \end{tikzpicture} #+end_src #+name: fig:uniaxial_model_micro_station-nass #+caption: Uni-axial model of the micro-station with added nano-hexapod (represented in blue) and sample (represented in green) #+RESULTS: [[file:figs/uniaxial_model_micro_station-nass.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 :noweb yes <> #+end_src #+begin_src matlab :eval no :noweb yes <> #+end_src #+begin_src matlab :noweb yes <> #+end_src #+begin_src matlab %% Uniaxial Simscape model name mdl = 'nass_uniaxial_model'; #+end_src #+begin_src matlab %% Frequency Vector [Hz] freqs = logspace(0, 3, 1000); #+end_src #+begin_src matlab %% Load the micro-station parameters load('uniaxial_micro_station_parameters.mat') #+end_src ** Nano-Hexapod Parameters The parameters for the nano-hexapod and sample are: - $m_s$ the sample mass that can vary from 1kg up to 50kg - $m_n$ the nano-hexapod mass which is set to 15kg - $k_n$ the nano-hexapod stiffness, which can vary depending on the chosen architecture/technology As a first example, let's choose a nano-hexapod stiffness of $10\,N/\mu m$ and a sample mass of 10kg. #+begin_src matlab %% Nano-Hexapod Parameters mn = 15; % [kg] kn = 1e7; % [N/m] cn = 2*0.01*sqrt(mn*kn); % [N/(m/s)] %% Sample Mass ms = 10; % [kg] #+end_src ** Obtained Dynamics The sensitivity to disturbances (i.e. $x_f$, $f_t$ and $f_s$) are shown in Figure ref:fig:uniaxial_sensitivity_dist_first_params. The /plant/ (i.e. the transfer function from actuator force $f$ to measured displacement $d$) is shown in Figure ref:fig:uniaxial_plant_first_params. For further analysis, 9 configurations are considered: three nano-hexapod stiffnesses ($k_n = 0.01\,N/\mu m$, $k_n = 1\,N/\mu m$ and $k_n = 100\,N/\mu m$) combined with three sample's masses ($m_s = 1\,kg$, $m_s = 25\,kg$ and $m_s = 50\,kg$). #+begin_src matlab :exports none %% Use 1DoF Nano-Hexpod model model_config = struct(); model_config.nhexa = "1dof"; model_config.controller = "open_loop"; %% Identify the transfer function from disturbances and force actuator to d clear io; io_i = 1; io(io_i) = linio([mdl, '/controller'], 1, 'openinput'); io_i = io_i + 1; % Force Actuator io(io_i) = linio([mdl, '/fs'], 1, 'openinput'); io_i = io_i + 1; % Force applied on the sample io(io_i) = linio([mdl, '/micro_station/xf'], 1, 'openinput'); io_i = io_i + 1; % Floor Motion io(io_i) = linio([mdl, '/micro_station/ft'], 1, 'openinput'); io_i = io_i + 1; % Stage disturbances io(io_i) = linio([mdl, '/d'] , 1, 'openoutput'); io_i = io_i + 1; % Metrology %% Perform the model extraction G_ol = linearize(mdl, io, 0.0); G_ol.InputName = {'f', 'fs', 'xf', 'ft'}; G_ol.OutputName = {'d'}; #+end_src #+begin_src matlab :exports none :results none %% Sensitivity to disturbances figure; tiledlayout(1, 3, 'TileSpacing', 'Compact', 'Padding', 'None'); ax1 = nexttile(); hold on; plot(freqs, abs(squeeze(freqresp(G_ol('d', 'fs'), freqs, 'Hz')))); hold off; set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log'); ylabel('Amplitude $d/f_{s}$ [m/N]'); xlabel('Frequency [Hz]'); xticks([1e0, 1e1, 1e2]); ax2 = nexttile(); hold on; plot(freqs, abs(squeeze(freqresp(G_ol('d', 'ft'), freqs, 'Hz')))); hold off; set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log'); ylabel('Amplitude $d/f_{t}$ [m/N]'); xlabel('Frequency [Hz]'); xticks([1e0, 1e1, 1e2]); ax3 = nexttile(); hold on; plot(freqs, abs(squeeze(freqresp(G_ol('d', 'xf'), freqs, 'Hz')))); hold off; set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log'); ylabel('Amplitude $d/x_{f}$ [m/m]'); xlabel('Frequency [Hz]'); xticks([1e0, 1e1, 1e2]); linkaxes([ax1,ax2,ax3],'x'); xlim([1, 500]); #+end_src #+begin_src matlab :tangle no :exports results :results file replace exportFig('figs/uniaxial_sensitivity_dist_first_params.pdf', 'width', 'full', 'height', 'normal'); #+end_src #+name: fig:uniaxial_sensitivity_dist_first_params #+caption: Sensitivity to disturbances #+RESULTS: [[file:figs/uniaxial_sensitivity_dist_first_params.png]] #+begin_src matlab :exports none :results none %% Bode Plot of the transfer function from actuator forces to measured displacement by the metrology figure; tiledlayout(3, 1, 'TileSpacing', 'Compact', 'Padding', 'None'); ax1 = nexttile([2,1]); hold on; plot(freqs, abs(squeeze(freqresp(G_ol('d', 'f'), freqs, 'Hz')))); hold off; set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log'); ylabel('Amplitude $d/f$ [m/N]'); set(gca, 'XTickLabel',[]); ax2 = nexttile; hold on; plot(freqs, 180/pi*angle(squeeze(freqresp(G_ol('d', 'f'), freqs, 'Hz')))); hold off; set(gca, 'XScale', 'log'); set(gca, 'YScale', 'lin'); xlabel('Frequency [Hz]'); ylabel('Phase [deg]'); hold off; yticks(-360:90:360); ylim([-180, 0]); linkaxes([ax1,ax2],'x'); xlim([1, 500]); #+end_src #+begin_src matlab :tangle no :exports results :results file replace exportFig('figs/uniaxial_plant_first_params.pdf', 'width', 'normal', 'height', 600); #+end_src #+name: fig:uniaxial_plant_first_params #+caption: Bode Plot of the transfer function from actuator forces to measured displacement by the metrology #+RESULTS: [[file:figs/uniaxial_plant_first_params.png]] ** Identification of all combination of stiffnesses / masses :noexport: #+begin_src matlab :exports none %% Use 1DoF Nano-Hexpod model model_config = struct(); model_config.nhexa = "1dof"; model_config.controller = "open_loop"; %% Nano-Hexapod Mass mn = 15; % Nano-Hexapod mass [kg] %% Identification of all combination of stiffnesses / masses clear io; io_i = 1; io(io_i) = linio([mdl, '/controller'], 1, 'openinput'); io_i = io_i + 1; % Actuator Force io(io_i) = linio([mdl, '/micro_station/xf'], 1, 'openinput'); io_i = io_i + 1; % Floor Motion io(io_i) = linio([mdl, '/micro_station/ft'], 1, 'openinput'); io_i = io_i + 1; % Stage vibrations io(io_i) = linio([mdl, '/fs'], 1, 'openinput'); io_i = io_i + 1; % Direct sample forces io(io_i) = linio([mdl, '/dL'], 1, 'openoutput'); io_i = io_i + 1; % Relative Motion Sensor io(io_i) = linio([mdl, '/fm'], 1, 'openoutput'); io_i = io_i + 1; % Force Sensor io(io_i) = linio([mdl, '/vn'] , 1, 'openoutput'); io_i = io_i + 1; % Geophone io(io_i) = linio([mdl, '/d'] , 1, 'openoutput'); io_i = io_i + 1; % Metrology Output #+end_src #+begin_src matlab :exports none %% Light Sample ms = 1; % Sample Mass [kg] % Voice Coil (i.e. soft) Nano-Hexapod kn = 1e4; % Nano-Hexapod Stiffness [N/m] cn = 2*0.01*sqrt((ms + mn)*kn); % Nano-Hexapod Damping [N/(m/s)] G_vc_light = linearize(mdl, io, 0.0); G_vc_light.InputName = {'f', 'xf', 'ft', 'fs'}; G_vc_light.OutputName = {'dL', 'fm', 'vn', 'd'}; % APA (i.e. relatively stiff) Nano-Hexapod kn = 1e6; % Nano-Hexapod Stiffness [N/m] cn = 2*0.01*sqrt((ms + mn)*kn); % Nano-Hexapod Damping [N/(m/s)] G_md_light = linearize(mdl, io, 0.0); G_md_light.InputName = {'f', 'xf', 'ft', 'fs'}; G_md_light.OutputName = {'dL', 'fm', 'vn', 'd'}; % Piezoelectric (i.e. stiff) Nano-Hexapod kn = 1e8; % Nano-Hexapod Stiffness [N/m] cn = 2*0.01*sqrt((ms + mn)*kn); % Nano-Hexapod Damping [N/(m/s)] G_pz_light = linearize(mdl, io, 0.0); G_pz_light.InputName = {'f', 'xf', 'ft', 'fs'}; G_pz_light.OutputName = {'dL', 'fm', 'vn', 'd'}; %% Mid Sample ms = 25; % Sample Mass [kg] % Voice Coil (i.e. soft) Nano-Hexapod kn = 1e4; % Nano-Hexapod Stiffness [N/m] cn = 2*0.01*sqrt((ms + mn)*kn); % Nano-Hexapod Damping [N/(m/s)] G_vc_mid = linearize(mdl, io, 0.0); G_vc_mid.InputName = {'f', 'xf', 'ft', 'fs'}; G_vc_mid.OutputName = {'dL', 'fm', 'vn', 'd'}; % APA (i.e. relatively stiff) Nano-Hexapod kn = 1e6; % Nano-Hexapod Stiffness [N/m] cn = 2*0.01*sqrt((ms + mn)*kn); % Nano-Hexapod Damping [N/(m/s)] G_md_mid = linearize(mdl, io, 0.0); G_md_mid.InputName = {'f', 'xf', 'ft', 'fs'}; G_md_mid.OutputName = {'dL', 'fm', 'vn', 'd'}; % Piezoelectric (i.e. stiff) Nano-Hexapod kn = 1e8; % Nano-Hexapod Stiffness [N/m] cn = 2*0.01*sqrt((ms + mn)*kn); % Nano-Hexapod Damping [N/(m/s)] G_pz_mid = linearize(mdl, io, 0.0); G_pz_mid.InputName = {'f', 'xf', 'ft', 'fs'}; G_pz_mid.OutputName = {'dL', 'fm', 'vn', 'd'}; %% Heavy Sample ms = 50; % Sample Mass [kg] % Voice Coil (i.e. soft) Nano-Hexapod kn = 1e4; % Nano-Hexapod Stiffness [N/m] cn = 2*0.01*sqrt((ms + mn)*kn); % Nano-Hexapod Damping [N/(m/s)] G_vc_heavy = linearize(mdl, io, 0.0); G_vc_heavy.InputName = {'f', 'xf', 'ft', 'fs'}; G_vc_heavy.OutputName = {'dL', 'fm', 'vn', 'd'}; % APA (i.e. relatively stiff) Nano-Hexapod kn = 1e6; % Nano-Hexapod Stiffness [N/m] cn = 2*0.01*sqrt((ms + mn)*kn); % Nano-Hexapod Damping [N/(m/s)] G_md_heavy = linearize(mdl, io, 0.0); G_md_heavy.InputName = {'f', 'xf', 'ft', 'fs'}; G_md_heavy.OutputName = {'dL', 'fm', 'vn', 'd'}; % Piezoelectric (i.e. stiff) Nano-Hexapod kn = 1e8; % Nano-Hexapod Stiffness [N/m] cn = 2*0.01*sqrt((ms + mn)*kn); % Nano-Hexapod Damping [N/(m/s)] G_pz_heavy = linearize(mdl, io, 0.0); G_pz_heavy.InputName = {'f', 'xf', 'ft', 'fs'}; G_pz_heavy.OutputName = {'dL', 'fm', 'vn', 'd'}; #+end_src #+begin_src matlab :exports none :tangle no %% Save All Identified Plants save('./matlab/mat/uniaxial_plants.mat', 'G_vc_light', 'G_md_light', 'G_pz_light', ... 'G_vc_mid', 'G_md_mid', 'G_pz_mid', ... 'G_vc_heavy', 'G_md_heavy', 'G_pz_heavy'); #+end_src #+begin_src matlab :exports none :eval no %% Save All Identified Plants save('./mat/uniaxial_plants.mat', 'G_vc_light', 'G_md_light', 'G_pz_light', ... 'G_vc_mid', 'G_md_mid', 'G_pz_mid', ... 'G_vc_heavy', 'G_md_heavy', 'G_pz_heavy'); #+end_src * Disturbance Identification :PROPERTIES: :HEADER-ARGS:matlab+: :tangle matlab/uniaxial_3_disturbances.m :END: <> ** Introduction :ignore: In order to measure disturbances, two geophones are used, on located on the floor and on on the micro-hexapod's top platform (see Figure ref:fig:micro_station_meas_disturbances). The geophone on the floor is used to measured the floor motion $x_f$ while the geophone on the micro-hexapod is used to measure vibrations introduced by scanning of the $T_y$ stage and $R_z$ stage. #+begin_src latex :file micro_station_meas_disturbances.pdf \begin{tikzpicture} % Parameters \def\blockw{6.0cm} \def\blockh{1.2cm} \def\tiltdeg{0} \coordinate[] (rotationpoint) at (0, 4.5*\blockh); \begin{scope}[rotate around={\tiltdeg:(rotationpoint)}] % Tilt \path[] ([shift=(-120:4*\blockh)]rotationpoint) coordinate(beginarc) arc (-120:-110:4*\blockh) % -- ([shift=(-70:4*\blockh)]rotationpoint) arc (-70:-60:4*\blockh)% |- ++(-0.15*\blockw, 0.6*\blockh) coordinate (spindlene)% |- ($(beginarc) + (0.15*\blockw, 0.2*\blockh)$) coordinate (spindlesw) -- ++(0, 0.4*\blockh) coordinate(tiltte) -| cycle; % Spindle \coordinate[] (spindlese) at (spindlesw-|spindlene); \draw[fill=black!30] ($(spindlese)+(-0.1,0.1)+(-0.1*\blockw, 0)$) -| ($(spindlene)+(-0.1, 0)$) -| coordinate[pos=0.25](spindletop) ($(spindlesw)+(0.1,0.1)$) -| ++(0.1*\blockw, -\blockh) -| coordinate[pos=0.25](spindlebot) cycle; % \draw[dashed, color=black!60] ($(spindletop)+(0, 0.2)$) -- ($(spindlebot)+(0,-0.2)$); % Tilt \draw[fill=black!60] ([shift=(-120:4*\blockh)]rotationpoint) coordinate(beginarc) arc (-120:-110:4*\blockh) % -- ([shift=(-70:4*\blockh)]rotationpoint) arc (-70:-60:4*\blockh)% |- coordinate (tiltne) ++(-0.15*\blockw, 0.6*\blockh) coordinate (spindlene)% |- ($(beginarc) + (0.15*\blockw, 0.2*\blockh)$) coordinate (spindlesw) -- ++(0, 0.4*\blockh) -| cycle; % Micro-Hexapod \begin{scope}[shift={(spindletop)}] % Parameters definitions \def\baseh{0.22*\blockh} % Height of the base \def\naceh{0.18*\blockh} % Height of the nacelle \def\baser{0.22*\blockw} % Radius of the base \def\nacer{0.18*\blockw} % Radius of the nacelle \def\armr{0.2*\blockh} % Radius of the arms \def\basearmborder{0.2} \def\nacearmborder{0.2} \def\xnace{0} \def\ynace{\blockh-\naceh} \def\anace{0} \def\xbase{0} \def\ybase{0} \def\abase{0} % Hexapod \begin{scope}[shift={(\xbase, \ybase)}, rotate=\abase] % Base \draw[fill=white] (-\baser, 0) coordinate[](uhexabot) rectangle (\baser, \baseh); \coordinate[] (armbasel) at (-\baser+\basearmborder+\armr, \baseh); \coordinate[] (armbasec) at (0, \baseh); \coordinate[] (armbaser) at (\baser-\basearmborder-\armr, \baseh); \begin{scope}[shift={(\xnace, \ynace)}, rotate=\anace] \draw[fill=white] (-\nacer, 0) rectangle (\nacer, \naceh); \coordinate[] (uhexatop) at (0, \naceh); \coordinate[] (armnacel) at (-\nacer+\nacearmborder+\armr, 0); \coordinate[] (armnacec) at (0, 0); \coordinate[] (armnacer) at (\nacer-\nacearmborder-\armr, 0); \end{scope} \draw[] (armbasec) -- (armnacer); \draw[] (armbasec) -- (armnacel); \draw[] (armbasel) -- coordinate(mhexaw) (armnacel); \draw[] (armbasel) -- (armnacec); \draw[] (armbaser) -- (armnacec); \draw[] (armbaser) -- coordinate(mhexae) (armnacer); \end{scope} \end{scope} \begin{scope}[shift={(uhexatop)}] % Geophone - Hexapod \draw[rounded corners=0.1, draw=colorred, fill=colorred!10!white] (-0.5, 0.2) -- ++(0, -0.1) -- ++(0.1, -0.1) -- ++(0.1, 0.1) -- ++(0, 0.1) --cycle; \draw[rounded corners=0.1, draw=colorred, fill=colorred!10!white] ( 0.3, 0.2) -- ++(0, -0.1) -- ++(0.1, -0.1) -- ++(0.1, 0.1) -- ++(0, 0.1) --cycle; \draw[draw=colorred, fill=colorred!10!white] (0.6, 0.4) rectangle ++(0.2, 0.2); \node[shape=circle,minimum size=3pt,inner sep=0pt, draw=colorred, fill=colorred] at (0.8, 0.5){}; \draw[out=0, in=180, draw=colorred] (0.8, 0.5) to ++(0.6, -0.1) node[above, color=colorred]{$x_h$}; \draw[draw=colorred, fill=colorred!10!white] (-0.6, 0.2) rectangle node[midway, color=colorred]{\tiny geophone} (0.6, 0.8); \end{scope} \end{scope} \begin{scope}[shift={(0, -0.3*\blockh)}] % Translation Stage - fixed part \draw[fill=black!40] (-0.5*\blockw, 0) coordinate[](tyb) rectangle (0.5*\blockw, 0.15*\blockh); \coordinate[] (measposbot) at (0.5*\blockw, 0); % Translation Stage - mobile part \draw[fill=black!10, fill opacity=0.5] (-0.5*\blockw, 0.2*\blockh) -- (-0.5*\blockw, 1.5*\blockh) coordinate[](tyt) -- (0.5*\blockw, 1.5*\blockh) -- (0.5*\blockw, 0.2*\blockh) -- (0.35*\blockw, 0.2*\blockh) -- (0.35*\blockw, 0.8*\blockh) -- (-0.35*\blockw, 0.8*\blockh) -- (-0.35*\blockw, 0.2*\blockh) -- cycle; % Translation Guidance \draw[dashed, color=black!60] ($(-0.5*\blockw, 0)+( 0.075*\blockw,0.5*\blockh)$) circle (0.2*\blockh); \draw[dashed, color=black!60] ($( 0.5*\blockw, 0)+(-0.075*\blockw,0.5*\blockh)$) circle (0.2*\blockh); \draw[fill, color=black] ($( 0.5*\blockw, 0)+(-0.075*\blockw,0.5*\blockh)$) circle (0.04); \node[draw, circle, inner sep=0pt, minimum size=0.3cm, label=above:$T_y$] at ($( 0.5*\blockw, 0)+(-0.075*\blockw,0.5*\blockh)$){}; % Tilt Guidance \draw[dashed, color=black!60] ([shift=(-107:4.1*\blockh)]rotationpoint) arc (-107:-120:4.1*\blockh); \draw[dashed, color=black!60] ([shift=( -73:4.1*\blockh)]rotationpoint) arc (-73:-60:4.1*\blockh); \begin{scope}[shift={(4.0, 0)}] % Geophone - Granite \draw[rounded corners=0.1, draw=colorred, fill=colorred!10!white] (-0.5, 0.2) -- ++(0, -0.1) -- ++(0.1, -0.1) -- ++(0.1, 0.1) -- ++(0, 0.1) --cycle; \draw[rounded corners=0.1, draw=colorred, fill=colorred!10!white] ( 0.3, 0.2) -- ++(0, -0.1) -- ++(0.1, -0.1) -- ++(0.1, 0.1) -- ++(0, 0.1) --cycle; \draw[draw=colorred, fill=colorred!10!white] (0.6, 0.4) rectangle ++(0.2, 0.2); \node[shape=circle,minimum size=3pt,inner sep=0pt, draw=colorred, fill=colorred] at (0.8, 0.5){}; \draw[out=0, in=180, draw=colorred] (0.8, 0.5) to ++(0.6, -0.1) node[above, color=colorred]{$x_g$}; \draw[draw=colorred, fill=colorred!10!white] (-0.6, 0.2) rectangle node[midway, color=colorred]{\tiny geophone} (0.6, 0.8); \end{scope} \end{scope} % Granite \draw[fill=black!40] (-0.8*\blockw, -0.3*\blockh) rectangle node[midway]{Granite} (0.8*\blockw, -1.5*\blockh); \begin{scope}[shift={(4.0, -1.5*\blockh)}] % Geophone - Floor \draw[rounded corners=0.1, draw=colorred, fill=colorred!10!white] (-0.5, 0.2) -- ++(0, -0.1) -- ++(0.1, -0.1) -- ++(0.1, 0.1) -- ++(0, 0.1) --cycle; \draw[rounded corners=0.1, draw=colorred, fill=colorred!10!white] ( 0.3, 0.2) -- ++(0, -0.1) -- ++(0.1, -0.1) -- ++(0.1, 0.1) -- ++(0, 0.1) --cycle; \draw[draw=colorred, fill=colorred!10!white] (0.6, 0.4) rectangle ++(0.2, 0.2); \node[shape=circle,minimum size=3pt,inner sep=0pt, draw=colorred, fill=colorred] at (0.8, 0.5){}; \draw[out=0, in=180, draw=colorred] (0.8, 0.5) to ++(0.6, -0.1) node[above, color=colorred]{$x_f$}; \draw[draw=colorred, fill=colorred!10!white] (-0.6, 0.2) rectangle node[midway, color=colorred]{\tiny geophone} (0.6, 0.8); \end{scope} % Vertical line \draw[dashed, color=black] (spindlebot) -- ++(0, 2*\blockh); \node[] at ($(spindlebot)+(0, 1.1*\blockh)$) {\AxisRotator[rotate=-90]}; \node[right, shift={(0.3,0)}] at ($(spindlebot)+(0, 1.1*\blockh)$) {$\theta_z$}; % Axis \begin{scope}[shift={(-0.6*\blockw, 2.5*\blockh)}] \def\axissize{0.8cm} \draw[->] (0, 0) -- ++(0, \axissize) node[right]{$z$}; \draw[->] (0, 0) -- ++(-\axissize, 0) node[above]{$x$}; \draw[fill, color=black] (0, 0) circle (0.05*\axissize); \node[draw, circle, inner sep=0pt, minimum size=0.4*\axissize, label=right:$y$] (yaxis) at (0, 0){}; \end{scope} \end{tikzpicture} #+end_src #+name: fig:micro_station_meas_disturbances #+caption: Disturbance measurement setup - Schematic #+RESULTS: [[file:figs/micro_station_meas_disturbances.png]] #+name: fig:micro_station_dynamical_id_setup #+caption: Two geophones are used to measure the micro-station vibrations induced by the scanning of the $T_y$ and $R_z$ stages #+attr_latex: :width 0.6\linewidth [[file:figs/micro_station_dynamical_id_setup.jpg]] ** 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 :noweb yes <> #+end_src #+begin_src matlab :eval no :noweb yes <> #+end_src #+begin_src matlab :noweb yes <> #+end_src #+begin_src matlab %% Uniaxial Simscape model name mdl = 'nass_uniaxial_model'; #+end_src #+begin_src matlab %% Frequency Vector [Hz] freqs = logspace(0, 3, 1000); #+end_src #+begin_src matlab %% Load the micro-station parameters load('uniaxial_micro_station_parameters.mat'); #+end_src ** Ground Motion The geophone fixed to the floor to measure the floor motion. #+begin_src matlab %% Load floor motion data % t: time in [s] % V: measured voltage genrated by the geophone and amplified by a 60dB gain voltage amplifier [V] load('ground_motion_measurement.mat', 't', 'V'); #+end_src The voltage generated by each geophone is amplified using a voltage amplifier (gain of 60dB) before going to the ADC. The sensitivity of the geophone as well as the gain of the voltage amplifier are then taken into account to reconstruct the floor displacement. #+begin_src matlab %% Sensitivity of the geophone S0 = 88; % Sensitivity [V/(m/s)] f0 = 2; % Cut-off frequency [Hz] S = S0*(s/2/pi/f0)/(1+s/2/pi/f0); % Geophone's transfer function [V/(m/s)] %% Gain of the voltage amplifier G0_db = 60; % [dB] G0 = 10^(G0_db/20); % [abs] %% Transfer function from measured voltage to displacement G_geo = 1/S/G0/s; % [m/V] #+end_src The PSD $S_{V_f}$ of the measured voltage $V_f$ is computed. #+begin_src matlab %% Compute measured voltage PSD Fs = 1/(t(2)-t(1)); % Sampling Frequency [Hz] win = hanning(ceil(2*Fs)); % Hanning window [psd_V, f] = pwelch(V, win, [], [], Fs); % [V^2/Hz] #+end_src The PSD of the corresponding displacement can be computed as follows: \begin{equation} S_{x_f}(\omega) = \frac{S_{V_f}(\omega)}{|S_{\text{geo}}(j\omega)| \cdot G_{\text{amp}} \cdot \omega} \end{equation} with: - $S_{\text{geo}}$ the sensitivity of the Geophone in $[Vs/m]$ - $G_{\text{amp}}$ the gain of the voltage amplifier - $\omega$ is here to integrate and have the displacement instead of the velocity #+begin_src matlab %% Ground Motion ASD psd_xf = psd_V.*abs(squeeze(freqresp(G_geo, f, 'Hz'))).^2; % [m^2/Hz] #+end_src The amplitude spectral density $\Gamma_{x_f}$ of the measured displacement $x_f$ is shown in Figure ref:fig:asd_floor_motion_id31. #+begin_src matlab :exports none :results none %% Measured Amplitude Spectral Density of the Floor motion on ID31 figure; hold on; plot(f, sqrt(psd_xf), 'DisplayName', '$\Gamma_{x_{f}}$'); hold off; set(gca, 'xscale', 'log'); set(gca, 'yscale', 'log'); xlabel('Frequency [Hz]'); ylabel('Ampl. Spectral Density $\left[\frac{m}{\sqrt{Hz}}\right]$') xlim([1, 500]); legend('location', 'northeast', 'FontSize', 8, 'NumColumns', 1); #+end_src #+begin_src matlab :tangle no :exports results :results file replace exportFig('figs/asd_floor_motion_id31.pdf', 'width', 'wide', 'height', 'normal'); #+end_src #+name: fig:asd_floor_motion_id31 #+caption: Measured Amplitude Spectral Density of the Floor motion on ID31 #+RESULTS: [[file:figs/asd_floor_motion_id31.png]] ** Stage Vibration During Spindle rotation (here at 6rpm), the granite velocity and micro-hexapod's top platform velocity are measured with the geophones. #+begin_src matlab %% Measured velocity of granite and hexapod during spindle rotation % t: time in [s] % vg: measured granite velocity [m/s] % vg: measured micro-hexapod's top platform velocity [m/s] load('meas_spindle_on.mat', 't', 'vg', 'vh'); spindle_off = load('meas_spindle_off.mat', 't', 'vg', 'vh'); % No Rotation #+end_src The Power Spectral Density of the relative velocity between the hexapod and the granite is computed. #+begin_src matlab %% Compute Power Spectral Density of the relative velocity between granite and hexapod during spindle rotation Fs = 1/(t(2)-t(1)); % Sampling Frequency [Hz] win = hanning(ceil(2*Fs)); % Hanning window [psd_vft, f] = pwelch(vh-vg, win, [], [], Fs); % [(m/s)^2/Hz] [psd_off, ~] = pwelch(spindle_off.vh-spindle_off.vg, win, [], [], Fs); % [(m/s)^2/Hz] #+end_src It is then integrated to obtain the Amplitude Spectral Density of the relative motion which is compared with a non-rotating case (Figure ref:fig:asd_vibration_spindle_rotation). It is shown that the spindle rotation induces vibrations in a wide frequency spectrum. #+begin_src matlab :exports none :results none %% Measured Amplitude Spectral Density of the relative motion between the granite and the micro-hexapod's top platform during Spindle rotating figure; hold on; plot(f, sqrt(psd_vft)./(2*pi*f), 'DisplayName', '6rpm'); plot(f, sqrt(psd_off)./(2*pi*f), 'DisplayName', '0rpm'); hold off; set(gca, 'xscale', 'log'); set(gca, 'yscale', 'log'); xlabel('Frequency [Hz]'); ylabel('Ampl. Spectral Density $\left[\frac{m}{\sqrt{Hz}}\right]$') legend('location', 'northeast', 'FontSize', 8, 'NumColumns', 1); xlim([1, 500]); ylim([1e-12, 1e-7]) #+end_src #+begin_src matlab :tangle no :exports results :results file replace exportFig('figs/asd_vibration_spindle_rotation.pdf', 'width', 'wide', 'height', 'normal'); #+end_src #+name: fig:asd_vibration_spindle_rotation #+caption: Measured Amplitude Spectral Density of the relative motion between the granite and the micro-hexapod's top platform during Spindle rotating #+RESULTS: [[file:figs/asd_vibration_spindle_rotation.png]] In order to compute the equivalent disturbance force $f_t$ that induces such motion, the transfer function from $f_t$ to the relative motion of the hexapod's top platform and the granite is extracted from the model. #+begin_src matlab :exports none %% Disable the Nano-Hexpod for now model_config = struct(); model_config.nhexa = "none"; model_config.controller = "open_loop"; %% Identify the transfer function from u to taum clear io; io_i = 1; io(io_i) = linio([mdl, '/micro_station/ft'], 1, 'openinput'); io_i = io_i + 1; % Stage Disturbance Force io(io_i) = linio([mdl, '/micro_station/xg'], 1, 'openoutput'); io_i = io_i + 1; % Absolute motion of Granite io(io_i) = linio([mdl, '/micro_station/xh'], 1, 'openoutput'); io_i = io_i + 1; % Absolute motion of Hexapod %% Perform the model extraction G = linearize(mdl, io, 0.0); G.InputName = {'ft'}; G.OutputName = {'Dg', 'Dh'}; #+end_src The power spectral density $\Gamma_{f_{t}}$ of the disturbance force can be computed as follows: \begin{equation} \Gamma_{f_{t}}(\omega) = \frac{\Gamma_{v_{t}}(\omega)}{|G_{\text{model}}(j\omega)|^2} \end{equation} with: - $\Gamma_{v_{t}}$ the measured power spectral density of the relative motion between the micro-hexapod's top platform and the granite during the spindle's rotation - $G_{\text{model}}$ the transfer function (extracted from the uniaxial model) from $f_t$ to the relative motion between the micro-hexapod's top platform and the granite #+begin_src matlab :exports none %% Power Spectral Density of the equivalent force ft psd_ft = (psd_vft./(2*pi*f).^2)./abs(squeeze(freqresp(G('Dh', 'ft') - G('Dg', 'ft'), f, 'Hz'))).^2; #+end_src The obtained amplitude spectral density of the disturbance force $f_t$ is shown in Figure ref:fig:asd_disturbance_force. #+begin_src matlab :exports none :results none %% Estimated disturbance force ft from measurement and uniaxial model figure; hold on; plot(f, sqrt(psd_ft), 'DisplayName', '$\Gamma_{f_{t}}$'); hold off; set(gca, 'xscale', 'log'); set(gca, 'yscale', 'log'); xlabel('Frequency [Hz]'); ylabel('Ampl. Spectral Density $\left[\frac{N}{\sqrt{Hz}}\right]$') xlim([1, 500]); legend('location', 'northeast', 'FontSize', 8, 'NumColumns', 1); #+end_src #+begin_src matlab :tangle no :exports results :results file replace exportFig('figs/asd_disturbance_force.pdf', 'width', 'wide', 'height', 'normal'); #+end_src #+name: fig:asd_disturbance_force #+caption: Estimated disturbance force ft from measurement and uniaxial model #+RESULTS: [[file:figs/asd_disturbance_force.png]] The vibrations induced by the $T_y$ stage are not considered here as: - the induced vibrations have less amplitude than the vibrations induced by the $R_z$ stage - it can be scanned at lower velocities if the induced vibrations are an issue #+begin_src matlab :exports none :tangle no %% Save PSD of disturbances save('./matlab/mat/uniaxial_disturbance_psd.mat', 'f', 'psd_ft', 'psd_xf'); #+end_src #+begin_src matlab :exports none :eval no %% Save PSD of disturbances save('./mat/uniaxial_disturbance_psd.mat', 'f', 'psd_ft', 'psd_xf'); #+end_src * Open-Loop Dynamic Noise Budgeting :PROPERTIES: :HEADER-ARGS:matlab+: :tangle matlab/uniaxial_4_dynamic_noise_budget.m :END: <> ** Introduction :ignore: Now that we have a model of the NASS and an estimation of the power spectral density of the disturbances, it is possible to perform an /open-loop dynamic noise budgeting/. ** 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 :noweb yes <> #+end_src #+begin_src matlab :eval no :noweb yes <> #+end_src #+begin_src matlab :noweb yes <> #+end_src #+begin_src matlab %% Frequency Vector [Hz] freqs = logspace(0, 3, 1000); #+end_src #+begin_src matlab %% Load the PSD of disturbances load('uniaxial_disturbance_psd.mat', 'f', 'psd_ft', 'psd_xf'); %% Load Plants Dynamics load('uniaxial_plants.mat', 'G_vc_light', 'G_md_light', 'G_pz_light', ... 'G_vc_mid', 'G_md_mid', 'G_pz_mid', ... 'G_vc_heavy', 'G_md_heavy', 'G_pz_heavy'); #+end_src ** Sensitivity to disturbances From the Uni-axial model, the transfer function from the disturbances ($f_s$, $x_f$ and $f_t$) to the displacement $d$ are computed. This is done for *two extreme sample masses* $m_s = 1\,\text{kg}$ and $m_s = 50\,\text{kg}$ and *three nano-hexapod stiffnesses*: - $k_n = 0.01\,N/\mu m$ that could represent a voice coil actuator with soft flexible guiding - $k_n = 1\,N/\mu m$ that could represent a voice coil actuator with a stiff flexible guiding or a mechanically amplified piezoelectric actuator - $k_n = 100\,N/\mu m$ that could represent a stiff piezoelectric stack actuator The obtained sensitivity to disturbances for the three nano-hexapod stiffnesses are shown in Figure ref:fig:uniaxial_sensitivity_disturbances_nano_hexapod_stiffnesses for the light sample (same conclusions can be drawn with the heavy one). #+begin_important From Figure ref:fig:uniaxial_sensitivity_disturbances_nano_hexapod_stiffnesses, following can be concluded for the *soft nano-hexapod*: - It is more sensitive to forces applied on the sample (cable forces for instance), which is expected due to the lower stiffness - Between the suspension mode of the nano-hexapod (here at 5Hz) and the first mode of the micro-station (here at 70Hz), the disturbances induced by the stage vibrations are filtered out. - Above the suspension mode of the nano-hexapod, the sample's motion is unaffected by the floor motion, and therefore the sensitivity to floor motion is almost $1$. #+end_important #+begin_src matlab :exports none :results none %% Sensitivity to disturbances for three different nano-hexpod stiffnesses figure; tiledlayout(1, 3, 'TileSpacing', 'Compact', 'Padding', 'None'); ax1 = nexttile(); hold on; plot(freqs, abs(squeeze(freqresp(G_vc_light('d', 'fs'), freqs, 'Hz')))); plot(freqs, abs(squeeze(freqresp(G_md_light('d', 'fs'), freqs, 'Hz')))); plot(freqs, abs(squeeze(freqresp(G_pz_light('d', 'fs'), freqs, 'Hz')))); hold off; set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log'); ylabel('Amplitude $d/f_{s}$ [m/N]'); xlabel('Frequency [Hz]'); xticks([1e0, 1e1, 1e2]); ax2 = nexttile(); hold on; plot(freqs, abs(squeeze(freqresp(G_vc_light('d', 'ft'), freqs, 'Hz')))); plot(freqs, abs(squeeze(freqresp(G_md_light('d', 'ft'), freqs, 'Hz')))); plot(freqs, abs(squeeze(freqresp(G_pz_light('d', 'ft'), freqs, 'Hz')))); hold off; set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log'); ylabel('Amplitude $d/f_{t}$ [m/N]'); xlabel('Frequency [Hz]'); xticks([1e0, 1e1, 1e2]); ax3 = nexttile(); hold on; plot(freqs, abs(squeeze(freqresp(G_vc_light('d', 'xf'), freqs, 'Hz'))), 'DisplayName', '$k_n = 0.01\,N/\mu m$'); plot(freqs, abs(squeeze(freqresp(G_md_light('d', 'xf'), freqs, 'Hz'))), 'DisplayName', '$k_n = 1 \,N/\mu m$'); plot(freqs, abs(squeeze(freqresp(G_pz_light('d', 'xf'), freqs, 'Hz'))), 'DisplayName', '$k_n = 100 \,N/\mu m$'); hold off; set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log'); ylabel('Amplitude $d/x_{f}$ [m/m]'); xlabel('Frequency [Hz]'); xticks([1e0, 1e1, 1e2]); legend('location', 'southeast', 'FontSize', 8, 'NumColumns', 1); linkaxes([ax1,ax2,ax3],'x'); xlim([1, 500]); #+end_src #+begin_src matlab :tangle no :exports results :results file replace exportFig('figs/uniaxial_sensitivity_disturbances_nano_hexapod_stiffnesses.pdf', 'width', 'full', 'height', 'normal'); #+end_src #+name: fig:uniaxial_sensitivity_disturbances_nano_hexapod_stiffnesses #+caption: Sensitivity to disturbances for three different nano-hexpod stiffnesses #+RESULTS: [[file:figs/uniaxial_sensitivity_disturbances_nano_hexapod_stiffnesses.png]] ** Open-Loop Dynamic Noise Budgeting Now, the power spectral density of the disturbances is taken into account to estimate the residual motion $d$ in each case. The Cumulative Amplitude Spectrum of the relative motion $d$ due to both the floor motion $x_f$ and the stage vibrations $f_t$ are shown in Figure ref:fig:uniaxial_cas_d_disturbances_stiffnesses for the three nano-hexapod stiffnesses. It is shown that the effect of the floor motion is much less than the stage vibrations, except for the soft nano-hexapod below 5Hz. #+begin_src matlab :exports none :results none %% Cumulative Amplitude Spectrum of the relative motion d, due to both the floor motion and the stage vibrations figure; tiledlayout(1, 1, 'TileSpacing', 'Compact', 'Padding', 'None'); ax1 = nexttile(); hold on; plot(f, sqrt(flip(-cumtrapz(flip(f), flip(psd_ft.*abs(squeeze(freqresp(G_vc_light('d', 'ft'), f, 'Hz'))).^2)))), '-', 'color', colors(1,:), 'DisplayName', '$f_t$'); plot(f, sqrt(flip(-cumtrapz(flip(f), flip(psd_ft.*abs(squeeze(freqresp(G_md_light('d', 'ft'), f, 'Hz'))).^2)))), '-', 'color', colors(2,:), 'DisplayName', '$f_t$'); plot(f, sqrt(flip(-cumtrapz(flip(f), flip(psd_ft.*abs(squeeze(freqresp(G_pz_light('d', 'ft'), f, 'Hz'))).^2)))), '-', 'color', colors(3,:), 'DisplayName', '$f_t$'); plot(f, sqrt(flip(-cumtrapz(flip(f), flip(psd_xf.*abs(squeeze(freqresp(G_vc_light('d', 'xf'), f, 'Hz'))).^2)))), '--', 'color', colors(1,:), 'DisplayName', '$x_f$ ($k_n = 0.01\,N/\mu m$)'); plot(f, sqrt(flip(-cumtrapz(flip(f), flip(psd_xf.*abs(squeeze(freqresp(G_md_light('d', 'xf'), f, 'Hz'))).^2)))), '--', 'color', colors(2,:), 'DisplayName', '$x_f$ ($k_n = 1 \,N/\mu m$)'); plot(f, sqrt(flip(-cumtrapz(flip(f), flip(psd_xf.*abs(squeeze(freqresp(G_pz_light('d', 'xf'), f, 'Hz'))).^2)))), '--', 'color', colors(3,:), 'DisplayName', '$x_f$ ($k_n = 100 \,N/\mu m$)'); hold off; set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log'); ylabel('Cumulative Ampl. Spectrum [m]'); xlabel('Frequency [Hz]'); legend('location', 'southwest', 'FontSize', 8, 'NumColumns', 2); xlim([1, 500]); ylim([1e-12, 1e-6]) #+end_src #+begin_src matlab :tangle no :exports results :results file replace exportFig('figs/uniaxial_cas_d_disturbances_stiffnesses.pdf', 'width', 'wide', 'height', 'normal'); #+end_src #+name: fig:uniaxial_cas_d_disturbances_stiffnesses #+caption: Cumulative Amplitude Spectrum of the relative motion d, due to both the floor motion and the stage vibrations (light sample) #+RESULTS: [[file:figs/uniaxial_cas_d_disturbances_stiffnesses.png]] The total cumulative amplitude spectrum for the three nano-hexapod stiffnesses and for the two sample's masses are shown in Figure ref:fig:uniaxial_cas_d_disturbances_payload_masses. The conclusion is that the sample's mass has little effect on the cumulative amplitude spectrum of the relative motion $d$. #+begin_src matlab :exports none :results none %% Cumulative Amplitude Spectrum of the relative motion d due to all disturbances, for two sample masses figure; tiledlayout(1, 1, 'TileSpacing', 'Compact', 'Padding', 'None'); ax1 = nexttile(); hold on; plot(f, sqrt(flip(-cumtrapz(flip(f), flip(psd_ft.*abs(squeeze(freqresp(G_vc_light('d', 'ft'), f, 'Hz'))).^2 + ... psd_xf.*abs(squeeze(freqresp(G_vc_light('d', 'xf'), f, 'Hz'))).^2)))), '-', ... 'color', colors(1,:), 'DisplayName', '$m_s = 1\,kg$'); plot(f, sqrt(flip(-cumtrapz(flip(f), flip(psd_ft.*abs(squeeze(freqresp(G_md_light('d', 'ft'), f, 'Hz'))).^2 + ... psd_xf.*abs(squeeze(freqresp(G_md_light('d', 'xf'), f, 'Hz'))).^2)))), '-', ... 'color', colors(2,:), 'DisplayName', '$m_s = 1\,kg$'); plot(f, sqrt(flip(-cumtrapz(flip(f), flip(psd_ft.*abs(squeeze(freqresp(G_pz_light('d', 'ft'), f, 'Hz'))).^2 + ... psd_xf.*abs(squeeze(freqresp(G_pz_light('d', 'xf'), f, 'Hz'))).^2)))), '-', ... 'color', colors(3,:), 'DisplayName', '$m_s = 1\,kg$'); plot(f, sqrt(flip(-cumtrapz(flip(f), flip(psd_ft.*abs(squeeze(freqresp(G_vc_heavy('d', 'ft'), f, 'Hz'))).^2 + ... psd_xf.*abs(squeeze(freqresp(G_vc_heavy('d', 'xf'), f, 'Hz'))).^2)))), '--', ... 'color', colors(1,:), 'DisplayName', '$m_s = 50\,kg$ ($k_n = 0.01\,N/\mu m$)'); plot(f, sqrt(flip(-cumtrapz(flip(f), flip(psd_ft.*abs(squeeze(freqresp(G_md_heavy('d', 'ft'), f, 'Hz'))).^2 + ... psd_xf.*abs(squeeze(freqresp(G_md_heavy('d', 'xf'), f, 'Hz'))).^2)))), '--', ... 'color', colors(2,:), 'DisplayName', '$m_s = 50\,kg$ ($k_n = 1\,N/\mu m$)'); plot(f, sqrt(flip(-cumtrapz(flip(f), flip(psd_ft.*abs(squeeze(freqresp(G_pz_heavy('d', 'ft'), f, 'Hz'))).^2 + ... psd_xf.*abs(squeeze(freqresp(G_pz_heavy('d', 'xf'), f, 'Hz'))).^2)))), '--', ... 'color', colors(3,:), 'DisplayName', '$m_s = 50\,kg$ ($k_n = 100\,N/\mu m$)'); hold off; set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log'); ylabel('Cumulative Ampl. Spectrum [m]'); xlabel('Frequency [Hz]'); legend('location', 'southwest', 'FontSize', 8, 'NumColumns', 2); xlim([1, 500]); ylim([1e-11, 3e-6]) #+end_src #+begin_src matlab :tangle no :exports results :results file replace exportFig('figs/uniaxial_cas_d_disturbances_payload_masses.pdf', 'width', 'wide', 'height', 'normal'); #+end_src #+name: fig:uniaxial_cas_d_disturbances_payload_masses #+caption: Cumulative Amplitude Spectrum of the relative motion d due to all disturbances, for two sample masses #+RESULTS: [[file:figs/uniaxial_cas_d_disturbances_payload_masses.png]] ** Conclusion #+begin_important The conclusion is that in order to have a closed-loop residual vibration $d \approx 20\,nm\text{ rms}$, if a simple feedback controller is used, the required closed-loop bandwidth would be: - $\approx 10\,\text{Hz}$ for the soft nano-hexapod ($k_n = 0.01\,N/\mu m$) - $\approx 50\,\text{Hz}$ for the relatively stiff nano-hexapod ($k_n = 1\,N/\mu m$) - $\approx 100\,\text{Hz}$ for the stiff nano-hexapod ($k_n = 100\,N/\mu m$) This can be explain by the fact that above the suspension mode of the nano-hexapod, the stage vibrations are filtered out (see Figure ref:fig:uniaxial_sensitivity_disturbances_nano_hexapod_stiffnesses). This gives a first advantage to having a soft nano-hexapod. #+end_important * Active Damping :PROPERTIES: :HEADER-ARGS:matlab+: :tangle matlab/uniaxial_5_active_damping.m :END: <> ** Introduction :ignore: In this section, three active damping are applied on the nano-hexapod (see Figure ref:fig:uniaxial_active_damping_strategies): Integral Force Feedback (IFF), Relative Damping Control (RDC) and Direct Velocity Feedback (DVF). These active damping techniques are compared in terms of: - Reduction of the effect of disturbances (i.e. $x_f$, $f_t$ and $f_s$) on the displacement $d$ - Achievable damping - Robustness to a change of sample's mass #+begin_src latex :file uniaxial_active_damping_strategies.pdf \begin{tikzpicture} % ==================== % Parameters % ==================== \def\massw{2.2} % Width of the masses \def\massh{0.8} % Height of the masses \def\spaceh{1.2} % Height of the springs/dampers \def\dispw{0.4} % Width of the dashed line for the displacement \def\disph{0.3} % Height of the arrow for the displacements \def\bracs{0.05} % Brace spacing vertically \def\brach{-12pt} % Brace shift horizontaly \def\fsensh{0.2} % Height of the force sensor \def\velsize{0.2} % Size of the velocity sensor % ==================== % IFF \begin{scope} % ==================== % Ground % ==================== \draw (-0.5*\massw, 0) -- (0.5*\massw, 0); \draw[dashed] (0.5*\massw, 0) -- ++(\dispw, 0); \draw[->, color=colorpurple] (0.5*\massw+0.5*\dispw, 0) -- ++(0, 2*\disph) node[right, color=colorpurple]{$x_{f}$}; % ==================== % ==================== % Granite \begin{scope}[shift={(0, 0)}] % Mass \draw[fill=white] (-0.5*\massw, \spaceh) rectangle (0.5*\massw, \spaceh+\massh) node[pos=0.5]{$m_{g}$}; % Spring, Damper, and Actuator \draw[spring] (-0.4*\massw, 0) -- (-0.4*\massw, \spaceh) node[midway, left=0.1]{$k_{g}$}; \draw[damper] (0, 0) -- ( 0, \spaceh) node[midway, left=0.2]{$c_{g}$}; % Legend \draw[decorate, decoration={brace, amplitude=8pt}, xshift=\brach] % (-0.5*\massw, \bracs) -- (-0.5*\massw, \spaceh+\massh-\bracs) node[midway,rotate=90,anchor=south,yshift=10pt]{Granite}; \end{scope} % ==================== % ==================== % Stages \begin{scope}[shift={(0, \spaceh+\massh)}] % Mass \draw[fill=white] (-0.5*\massw, \spaceh) rectangle (0.5*\massw, \spaceh+\massh) node[pos=0.5]{$m_{t}$}; % Spring, Damper, and Actuator \draw[spring] (-0.4*\massw, 0) -- (-0.4*\massw, \spaceh) node[midway, left=0.1]{$k_{t}$}; \draw[damper] (0, 0) -- ( 0, \spaceh) node[midway, left=0.2]{$c_{t}$}; \draw[actuator={0.45}{0.2}{colorpurple}] ( 0.3*\massw, 0) -- (0.3*\massw, \spaceh) node[midway, right=0.1, color=colorpurple](ft){$f_{t}$}; % Legend \draw[decorate, decoration={brace, amplitude=8pt}, xshift=\brach] % (-0.5*\massw, \bracs) -- (-0.5*\massw, \spaceh+\massh-\bracs) node[midway,rotate=90,anchor=south,yshift=10pt]{$T_y$/$R_y$/$R_z$}; \end{scope} % ==================== % ==================== % Hexapod \begin{scope}[shift={(0, 2*(\spaceh+\massh))}] % Mass \draw[fill=white] (-0.5*\massw, \spaceh) rectangle (0.5*\massw, \spaceh+\massh) node[pos=0.5]{$m_h$}; % Spring, Damper, and Actuator \draw[spring] (-0.4*\massw, 0) -- (-0.4*\massw, \spaceh) node[midway, left=0.1]{$k_h$}; \draw[damper] (0, 0) -- ( 0, \spaceh) node[midway, left=0.2]{$c_h$}; % Legend \draw[decorate, decoration={brace, amplitude=8pt}, xshift=\brach] % (-0.5*\massw, \bracs) -- (-0.5*\massw, \spaceh+\massh-\bracs) node[midway,rotate=90,anchor=south,yshift=10pt]{$\mu\text{-hexa}$}; \end{scope} % ==================== % ==================== % NASS \begin{scope}[shift={(0, 3*(\spaceh+\massh))}] % Mass \draw[fill=white] (-0.5*\massw, \spaceh) rectangle (0.5*\massw, \spaceh+\massh) node[pos=0.5]{$m_{n}$}; % Force Sensor \node[forcesensor={\massw}{\fsensh}{colorblue}] (fsensn) at (0, \spaceh-\fsensh){}; \node[right, color=colorblue] (fn) at (fsensn.east) {$f_n$}; % Spring, Damper, and Actuator \draw[spring] (-0.4*\massw, 0) -- (-0.4*\massw, \spaceh-\fsensh) node[midway, left=0.1]{$k_{n}$}; \draw[damper] (0, 0) -- ( 0, \spaceh-\fsensh) node[midway, left=0.2]{$c_{n}$}; \draw[actuator={0.4}{0.2}{black}] ( 0.3*\massw, 0) -- ( 0.3*\massw, \spaceh-\fsensh) node[midway, right=0.1](f){$f$}; % Legend \draw[decorate, decoration={brace, amplitude=8pt}, xshift=\brach] % (-0.5*\massw, \bracs) -- (-0.5*\massw, \spaceh+\massh-\bracs) node[midway,rotate=90,anchor=south,yshift=10pt]{$\nu\text{-hexa}$}; \end{scope} % ==================== % ==================== % sample \begin{scope}[shift={(0, 4*(\spaceh+\massh))}] % Mass \draw[fill=white] (-0.3*\massw, 0) rectangle (0.3*\massw, \massh) node[pos=0.5]{$m_{s}$}; % External Force \draw[->, color=colorpurple] (0, \massh) node[]{$\bullet$} -- ++(0, 0.5*\massh) node[right, color=colorpurple]{$f_s$}; \end{scope} % ==================== % ==================== % IFF Control \node[block={2em}{2em}, right=0.3 of fn, color=colorblue, fill=colorblue!10!white] (iff) {$K_{\text{IFF}}$}; \draw[->, draw=colorblue] (fn.east) -- (iff.west); \draw[->, draw=colorblue] (iff.south) |- (f.east); % ==================== \end{scope} \begin{scope}[shift={(5,0)}] % ==================== % Ground % ==================== \draw (-0.5*\massw, 0) -- (0.5*\massw, 0); \draw[dashed] (0.5*\massw, 0) -- ++(\dispw, 0); \draw[->, color=colorpurple] (0.5*\massw+0.5*\dispw, 0) -- ++(0, 2*\disph) node[right, color=colorpurple]{$x_{f}$}; % ==================== % ==================== % Granite \begin{scope}[shift={(0, 0)}] % Mass \draw[fill=white] (-0.5*\massw, \spaceh) rectangle (0.5*\massw, \spaceh+\massh) node[pos=0.5]{$m_{g}$}; % Spring, Damper, and Actuator \draw[spring] (-0.4*\massw, 0) -- (-0.4*\massw, \spaceh) node[midway, left=0.1]{$k_{g}$}; \draw[damper] (0, 0) -- ( 0, \spaceh) node[midway, left=0.2]{$c_{g}$}; \end{scope} % ==================== % ==================== % Stages \begin{scope}[shift={(0, \spaceh+\massh)}] % Mass \draw[fill=white] (-0.5*\massw, \spaceh) rectangle (0.5*\massw, \spaceh+\massh) node[pos=0.5]{$m_{t}$}; % Spring, Damper, and Actuator \draw[spring] (-0.4*\massw, 0) -- (-0.4*\massw, \spaceh) node[midway, left=0.1]{$k_{t}$}; \draw[damper] (0, 0) -- ( 0, \spaceh) node[midway, left=0.2]{$c_{t}$}; \draw[actuator={0.45}{0.2}{colorpurple}] ( 0.3*\massw, 0) -- (0.3*\massw, \spaceh) node[midway, right=0.1, color=colorpurple](ft){$f_{t}$}; \end{scope} % ==================== % ==================== % Hexapod \begin{scope}[shift={(0, 2*(\spaceh+\massh))}] % Mass \draw[fill=white] (-0.5*\massw, \spaceh) rectangle (0.5*\massw, \spaceh+\massh) node[pos=0.5]{$m_h$}; % Spring, Damper, and Actuator \draw[spring] (-0.4*\massw, 0) -- (-0.4*\massw, \spaceh) node[midway, left=0.1]{$k_h$}; \draw[damper] (0, 0) -- ( 0, \spaceh) node[midway, left=0.2]{$c_h$}; \draw[dashed] (0.5*\massw, \spaceh+\massh) -- ++(2*\dispw, 0) coordinate(drbot); \end{scope} % ==================== % ==================== % NASS \begin{scope}[shift={(0, 3*(\spaceh+\massh))}] % Mass \draw[fill=white] (-0.5*\massw, \spaceh) rectangle (0.5*\massw, \spaceh+\massh) node[pos=0.5]{$m_{n}$}; % Spring, Damper, and Actuator \draw[spring] (-0.4*\massw, 0) -- (-0.4*\massw, \spaceh) node[midway, left=0.1]{$k_{n}$}; \draw[damper] (0, 0) -- ( 0, \spaceh) node[midway, left=0.2]{$c_{n}$}; \draw[actuator={0.4}{0.2}{black}] ( 0.3*\massw, 0) -- (0.3*\massw, \spaceh) node[midway, right=0.1](f){$f$}; \draw[dashed, draw=colorred] (0.5*\massw, \spaceh+\massh) -- ++(2*\dispw, 0) coordinate(drtop); \end{scope} % ==================== % ==================== % sample \begin{scope}[shift={(0, 4*(\spaceh+\massh))}] % Mass \draw[fill=white] (-0.3*\massw, 0) rectangle (0.3*\massw, \massh) node[pos=0.5]{$m_{s}$}; % External Force \draw[->, color=colorpurple] (0, \massh) node[]{$\bullet$} -- ++(0, 0.5*\massh) node[right, color=colorpurple]{$f_s$}; \end{scope} % ==================== \draw[<->, dashed, draw=colorred] ($(drbot)+(-0.1, 0)$) -- ($(drtop)+(-0.1, 0)$) node[right, color=colorred](dr){$d\mathcal{L}$}; % ==================== % RDC Control \node[block={2em}{2em}, below right=0.2 and -0.2 of dr, color=colorred, fill=colorred!10!white] (rdc) {$K_{\text{RDC}}$}; \draw[->, draw=colorred] (dr.east) -| (rdc.north); \draw[->, draw=colorred] (rdc.south) |- (f.east); % ==================== \end{scope} \begin{scope}[shift={(10,0)}] % ==================== % Ground % ==================== \draw (-0.5*\massw, 0) -- (0.5*\massw, 0); \draw[dashed] (0.5*\massw, 0) -- ++(\dispw, 0); \draw[->, color=colorpurple] (0.5*\massw+0.5*\dispw, 0) -- ++(0, 2*\disph) node[right, color=colorpurple]{$x_{f}$}; % ==================== % ==================== % Marble \begin{scope}[shift={(0, 0)}] % Mass \draw[fill=white] (-0.5*\massw, \spaceh) rectangle (0.5*\massw, \spaceh+\massh) node[pos=0.5]{$m_{g}$}; % Spring, Damper, and Actuator \draw[spring] (-0.4*\massw, 0) -- (-0.4*\massw, \spaceh) node[midway, left=0.1]{$k_{g}$}; \draw[damper] (0, 0) -- ( 0, \spaceh) node[midway, left=0.2]{$c_{g}$}; \end{scope} % ==================== % ==================== % Stages \begin{scope}[shift={(0, \spaceh+\massh)}] % Mass \draw[fill=white] (-0.5*\massw, \spaceh) rectangle (0.5*\massw, \spaceh+\massh) node[pos=0.5]{$m_{t}$}; % Spring, Damper, and Actuator \draw[spring] (-0.4*\massw, 0) -- (-0.4*\massw, \spaceh) node[midway, left=0.1]{$k_{t}$}; \draw[damper] (0, 0) -- ( 0, \spaceh) node[midway, left=0.2]{$c_{t}$}; \draw[actuator={0.45}{0.2}{colorpurple}] ( 0.3*\massw, 0) -- (0.3*\massw, \spaceh) node[midway, right=0.1, color=colorpurple](ft){$f_{t}$}; \end{scope} % ==================== % ==================== % Hexapod \begin{scope}[shift={(0, 2*(\spaceh+\massh))}] % Mass \draw[fill=white] (-0.5*\massw, \spaceh) rectangle (0.5*\massw, \spaceh+\massh) node[pos=0.5]{$m_{h}$}; % Spring, Damper, and Actuator \draw[spring] (-0.4*\massw, 0) -- (-0.4*\massw, \spaceh) node[midway, left=0.1]{$k_{h}$}; \draw[damper] (0, 0) -- ( 0, \spaceh) node[midway, left=0.2]{$c_{h}$}; \end{scope} % ==================== % ==================== % NASS \begin{scope}[shift={(0, 3*(\spaceh+\massh))}] % Mass \draw[fill=white] (-0.5*\massw, \spaceh) rectangle (0.5*\massw, \spaceh+\massh) node[pos=0.5]{$m_{n}$}; % Spring, Damper, and Actuator \draw[spring] (-0.4*\massw, 0) -- (-0.4*\massw, \spaceh) node[midway, left=0.1]{$k_{n}$}; \draw[damper] (0, 0) -- ( 0, \spaceh) node[midway, left=0.2]{$c_{n}$}; \draw[actuator={0.4}{0.2}{black}] ( 0.3*\massw, 0) -- (0.3*\massw, \spaceh) node[midway, right=0.1](f){$f$}; % Velocity Sensor \node[inertialsensor={\velsize}{coloryellow}] (veln) at (0.5*\massw, \spaceh+\massh) {}; \node[right, color=coloryellow] (xn) at (veln.north east) {$v_n$}; \end{scope} % ==================== % ==================== % sample \begin{scope}[shift={(0, 4*(\spaceh+\massh))}] % Mass \draw[fill=white] (-0.3*\massw, 0) rectangle (0.3*\massw, \massh) node[pos=0.5]{$m_{s}$}; % External Force \draw[->, color=colorpurple] (0, \massh) node[]{$\bullet$} -- ++(0, 0.5*\massh) node[right, color=colorpurple]{$f_s$}; \end{scope} % ==================== % ==================== % DVF Control \node[block={2em}{2em}, below right=0.4 and 0.1 of xn, color=coloryellow, fill=coloryellow!10!white] (ppf) {$K_{\text{DVF}}$}; \draw[->, draw=coloryellow] (xn.east) -| (ppf.north); \draw[->, draw=coloryellow] (ppf.south) |- (f.east); % ==================== \end{scope} \end{tikzpicture} #+end_src #+name: fig:uniaxial_active_damping_strategies #+caption: Three active damping strategies: Integral Force Feedback (IFF) using a force sensor, Relative Damping Control (RDC) using a relative displacement sensor, and Direct Velocity Feedback (DVF) using a geophone #+RESULTS: [[file:figs/uniaxial_active_damping_strategies.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 :noweb yes <> #+end_src #+begin_src matlab :eval no :noweb yes <> #+end_src #+begin_src matlab :noweb yes <> #+end_src #+begin_src matlab %% Frequency Vector [Hz] freqs = logspace(0, 3, 1000); #+end_src #+begin_src matlab %% Load the PSD of disturbances load('uniaxial_disturbance_psd.mat', 'f', 'psd_ft', 'psd_xf'); #+end_src #+begin_src matlab %% Load Plants Dynamics load('uniaxial_plants.mat', 'G_vc_light', 'G_md_light', 'G_pz_light', ... 'G_vc_mid', 'G_md_mid', 'G_pz_mid', ... 'G_vc_heavy', 'G_md_heavy', 'G_pz_heavy'); #+end_src ** Active Damping Strategies The Integral Force Feedback strategy consists of using a force sensor in series with the actuator (see Figure ref:fig:uniaxial_active_damping_iff_equiv, left). The control strategy consists of integrating the measured force and feeding it back to the actuator: \begin{equation} K_{\text{IFF}}(s) = \frac{g}{s} \end{equation} The mechanical equivalent of this strategy is to add a dashpot in series with the actuator stiffness with a damping coefficient equal to the stiffness of the actuator divided by the controller gain $k/g$ (see Figure ref:fig:uniaxial_active_damping_iff_equiv, right). #+begin_src latex :file uniaxial_active_damping_iff_equiv.pdf \begin{tikzpicture} % ==================== % Parameters % ==================== \def\massw{2.2} % Width of the masses \def\massh{0.8} % Height of the masses \def\spaceh{1.2} % Height of the springs/dampers \def\dispw{0.4} % Width of the dashed line for the displacement \def\disph{0.3} % Height of the arrow for the displacements \def\bracs{0.05} % Brace spacing vertically \def\brach{-12pt} % Brace shift horizontaly \def\fsensh{0.2} % Height of the force sensor \def\velsize{0.2} % Size of the velocity sensor % ==================== \begin{scope} % ==================== % Stage Below \begin{scope} \draw[fill=white] (-0.5*\massw, \spaceh) rectangle (0.5*\massw, \spaceh+\massh); \draw[spring] (-0.25*\massw, 0) -- (-0.25*\massw, \spaceh); \draw[damper] ( 0.25*\massw, 0) -- ( 0.25*\massw, \spaceh); \draw[decorate,decoration={zigzag,segment length=6pt},draw=black!50!white,very thick] (-0.5*\massw, 0) -- (0.5*\massw, 0); \draw[draw=black!50!white,very thick, dashed] (-0.5*\massw, 0) -- ++(-0.5, 0); \draw[draw=black!50!white,very thick, dashed] ( 0.5*\massw, 0) -- ++( 0.5, 0); \end{scope} % ==================== % ==================== % NASS \begin{scope}[shift={(0, \spaceh+\massh)}] \draw[fill=white] (-0.5*\massw, \spaceh) rectangle (0.5*\massw, \spaceh+\massh) node[pos=0.5]{$m$}; \node[forcesensor={\massw}{\fsensh}{colorblue}] (fsensn) at (0, \spaceh-\fsensh){}; \node[right, color=colorblue] (fn) at (fsensn.east) {$f_m$}; \draw[spring] (-0.25*\massw, 0) -- (-0.25*\massw, \spaceh-\fsensh) node[midway, left=0.1]{$k$}; \draw[actuator={0.4}{0.2}{black}] ( 0.25*\massw, 0) -- (0.25*\massw, \spaceh-\fsensh) coordinate[midway, shift={(0.1,0)}](f); \end{scope} % ==================== % ==================== % Stage Above \begin{scope}[shift={(0, 2*(\spaceh+\massh))}] \draw[spring] (-0.25*\massw, 0) -- (-0.25*\massw, \spaceh); \draw[damper] ( 0.25*\massw, 0) -- ( 0.25*\massw, \spaceh); \draw[decorate,decoration={zigzag,segment length=6pt},draw=black!50!white,very thick] (-0.5*\massw, \spaceh) -- (0.5*\massw, \spaceh); \draw[draw=black!50!white,very thick, dashed] (-0.5*\massw, \spaceh) -- ++(-0.5, 0); \draw[draw=black!50!white,very thick, dashed] ( 0.5*\massw, \spaceh) -- ++( 0.5, 0); \end{scope} % ==================== % ==================== % IFF Control \node[block={2em}{2em}, right=1.0 of f, color=colorblue, fill=colorblue!10!white] (iff) {$g/s$}; \draw[->, draw=colorblue] (fn.east) -- ++(1.0, 0) |- (iff.east); \draw[->, draw=colorblue] (iff.west) -- (f.east) node[above right, color=colorblue]{$f$}; % ==================== \end{scope} \begin{scope}[shift={(6, 0)}] % ==================== % Stage Below \begin{scope} \draw[fill=white] (-0.5*\massw, 0.8*\spaceh) rectangle (0.5*\massw, 0.8*\spaceh+\massh); \draw[spring] (-0.25*\massw, 0) -- (-0.25*\massw, 0.8*\spaceh); \draw[damper] ( 0.25*\massw, 0) -- ( 0.25*\massw, 0.8*\spaceh); \draw[decorate,decoration={zigzag,segment length=6pt},draw=black!50!white,very thick] (-0.5*\massw, 0) -- (0.5*\massw, 0); \draw[draw=black!50!white,very thick, dashed] (-0.5*\massw, 0) -- ++(-0.5, 0); \draw[draw=black!50!white,very thick, dashed] ( 0.5*\massw, 0) -- ++( 0.5, 0); \end{scope} % ==================== % ==================== % NASS \begin{scope}[shift={(0, 0.8*\spaceh+\massh)}] \draw[fill=white] (-0.5*\massw, 1.4*\spaceh) rectangle (0.5*\massw, 1.4*\spaceh+\massh) node[pos=0.5]{$m$}; \draw[spring] (0, 0) -- node[midway, left=0.1]{$k$} (0, 0.8*\spaceh); \draw[damper={colorblue}{}{}] (0, 0.8*\spaceh) node[branch]{} -- (0, 1.4*\spaceh) node[midway, left=0.2, color=colorblue]{$k/g$}; \end{scope} % ==================== % ==================== % Stage Above \begin{scope}[shift={(0, 0.8*\spaceh+\massh+1.4*\spaceh+\massh)}] \draw[spring] (-0.25*\massw, 0) -- (-0.25*\massw, 0.8*\spaceh); \draw[damper] ( 0.25*\massw, 0) -- ( 0.25*\massw, 0.8*\spaceh); \draw[decorate,decoration={zigzag,segment length=6pt},draw=black!50!white,very thick] (-0.5*\massw, 0.8*\spaceh) -- (0.5*\massw, 0.8*\spaceh); \draw[draw=black!50!white,very thick, dashed] (-0.5*\massw, 0.8*\spaceh) -- ++(-0.5, 0); \draw[draw=black!50!white,very thick, dashed] ( 0.5*\massw, 0.8*\spaceh) -- ++( 0.5, 0); \end{scope} % ==================== \end{scope} % Equiv \draw[double, <->, draw=colorblue, double distance=1.5] (3.0, 1.5*\spaceh+\massh) -- ++(1.5,0); \end{tikzpicture} #+end_src #+name: fig:uniaxial_active_damping_iff_equiv #+caption: Integral Force Feedback is equivalent as to add a damper in series with the stiffness (the initial damping is here neglected for simplicity) #+RESULTS: [[file:figs/uniaxial_active_damping_iff_equiv.png]] For the Relative Damping Control strategy, a relative motion sensor that measures the motion of the actuator is used (see Figure ref:fig:uniaxial_active_damping_rdc_equiv, left). The derivative of this relative motion is used for the feedback signal: \begin{equation} K_{\text{RDC}}(s) = - g \cdot s \end{equation} The mechanical equivalent is to add a dashpot in parallel with the actuator with a damping coefficient equal to the controller gain $g$ (see Figure ref:fig:uniaxial_active_damping_rdc_equiv, right). #+begin_src latex :file uniaxial_active_damping_rdc_equiv.pdf \begin{tikzpicture} % ==================== % Parameters % ==================== \def\massw{2.2} % Width of the masses \def\massh{0.8} % Height of the masses \def\spaceh{1.2} % Height of the springs/dampers \def\dispw{0.4} % Width of the dashed line for the displacement \def\disph{0.3} % Height of the arrow for the displacements \def\bracs{0.05} % Brace spacing vertically \def\brach{-12pt} % Brace shift horizontaly \def\fsensh{0.2} % Height of the force sensor \def\velsize{0.2} % Size of the velocity sensor % ==================== \begin{scope} % ==================== % Stage Below \begin{scope} \draw[fill=white] (-0.5*\massw, \spaceh) rectangle (0.5*\massw, \spaceh+\massh); \draw[spring] (-0.25*\massw, 0) -- (-0.25*\massw, \spaceh); \draw[damper] ( 0.25*\massw, 0) -- ( 0.25*\massw, \spaceh); \draw[dashed, draw=colorred] (0.5*\massw, \spaceh+\massh) -- ++(1*\dispw, 0) coordinate(drbot); \draw[decorate,decoration={zigzag,segment length=6pt},draw=black!50!white,very thick] (-0.5*\massw, 0) -- (0.5*\massw, 0); \draw[draw=black!50!white,very thick, dashed] (-0.5*\massw, 0) -- ++(-0.5, 0); \draw[draw=black!50!white,very thick, dashed] ( 0.5*\massw, 0) -- ++( 0.5, 0); \end{scope} % ==================== % ==================== % NASS \begin{scope}[shift={(0, \spaceh+\massh)}] \draw[fill=white] (-0.5*\massw, \spaceh) rectangle (0.5*\massw, \spaceh+\massh) node[pos=0.5]{$m$}; \draw[spring] (-0.4*\massw, 0) -- (-0.4*\massw, \spaceh) node[midway, left=0.1]{$k$}; \draw[damper] (0, 0) -- ( 0, \spaceh) node[midway, left=0.2]{$c$}; \draw[actuator={0.4}{0.2}{black}] ( 0.3*\massw, 0) -- (0.3*\massw, \spaceh) coordinate[midway, shift={(0.1,0)}](f); \draw[dashed, draw=colorred] (0.5*\massw, \spaceh+\massh) -- ++(1*\dispw, 0) coordinate(drtop); \end{scope} % ==================== % ==================== % Stage Above \begin{scope}[shift={(0, 2*(\spaceh+\massh))}] \draw[spring] (-0.25*\massw, 0) -- (-0.25*\massw, \spaceh); \draw[damper] ( 0.25*\massw, 0) -- ( 0.25*\massw, \spaceh); \draw[decorate,decoration={zigzag,segment length=6pt},draw=black!50!white,very thick] (-0.5*\massw, \spaceh) -- (0.5*\massw, \spaceh); \draw[draw=black!50!white,very thick, dashed] (-0.5*\massw, \spaceh) -- ++(-0.5, 0); \draw[draw=black!50!white,very thick, dashed] ( 0.5*\massw, \spaceh) -- ++( 0.5, 0); \end{scope} % ==================== \draw[<->, dashed, draw=colorred] ($(drbot)+(-0.1, 0)$) -- ($(drtop)+(-0.1, 0)$) node[right, color=colorred](dr){$d\mathcal{L}$}; % ==================== % RDC Control \node[block={2em}{2em}, below right=0.2 and -0.3 of dr, color=colorred, fill=colorred!10!white] (rdc) {$-g \cdot s$}; \draw[->, draw=colorred] (dr.east) -| (rdc.north); \draw[->, draw=colorred] (rdc.south) |- (f.east) node[above right, color=colorred]{$f$}; % ==================== \end{scope} \begin{scope}[shift={(6, 0)}] % ==================== % Stage Below \begin{scope} \draw[fill=white] (-0.5*\massw, \spaceh) rectangle (0.5*\massw, \spaceh+\massh); \draw[spring] (-0.25*\massw, 0) -- (-0.25*\massw, \spaceh); \draw[damper] ( 0.25*\massw, 0) -- ( 0.25*\massw, \spaceh); \draw[decorate,decoration={zigzag,segment length=6pt},draw=black!50!white,very thick] (-0.5*\massw, 0) -- (0.5*\massw, 0); \draw[draw=black!50!white,very thick, dashed] (-0.5*\massw, 0) -- ++(-0.5, 0); \draw[draw=black!50!white,very thick, dashed] ( 0.5*\massw, 0) -- ++( 0.5, 0); \end{scope} % ==================== % ==================== % NASS \begin{scope}[shift={(0, \spaceh+\massh)}] \draw[fill=white] (-0.5*\massw, \spaceh) rectangle (0.5*\massw, \spaceh+\massh) node[pos=0.5]{$m$}; \draw[spring] (-0.4*\massw, 0) -- (-0.4*\massw, \spaceh) node[midway, left=0.1]{$k$}; \draw[damper] (0, 0) -- ( 0, \spaceh) node[midway, left=0.2]{$c$}; \draw[damper={colorred}{}{}] ( 0.4*\massw, 0) -- ( 0.4*\massw, \spaceh) node[midway, left=0.15, color=colorred]{$g$}; \end{scope} % ==================== % ==================== % Stage Above \begin{scope}[shift={(0, 2*(\spaceh+\massh))}] \draw[spring] (-0.25*\massw, 0) -- (-0.25*\massw, \spaceh); \draw[damper] ( 0.25*\massw, 0) -- ( 0.25*\massw, \spaceh); \draw[decorate,decoration={zigzag,segment length=6pt},draw=black!50!white,very thick] (-0.5*\massw, \spaceh) -- (0.5*\massw, \spaceh); \draw[draw=black!50!white,very thick, dashed] (-0.5*\massw, \spaceh) -- ++(-0.5, 0); \draw[draw=black!50!white,very thick, dashed] ( 0.5*\massw, \spaceh) -- ++( 0.5, 0); \end{scope} % ==================== \end{scope} % Equiv \draw[double, <->, draw=colorred, double distance=1.5] (3.0, 1.5*\spaceh+\massh) -- ++(1.5,0); \end{tikzpicture} #+end_src #+name: fig:uniaxial_active_damping_rdc_equiv #+caption: Relative Damping Control is equivalent as adding a damper in parallel with the actuator/relative motion sensor #+RESULTS: [[file:figs/uniaxial_active_damping_rdc_equiv.png]] Finally, the Direct Velocity Feedback strategy consists of using an inertial sensor (usually a geophone), that measured the "absolute" velocity of the body fixed on top of the actuator (se Figure ref:fig:uniaxial_active_damping_dvf_equiv, left). The measured velocity is then fed back to the actuator: \begin{equation} K_{\text{DVF}}(s) = - g \end{equation} This is equivalent as to fix a dashpot (with a damping coefficient equal to the controller gain $g$) between the body (one which the inertial sensor is fixed) and an inertial reference frame (see Figure ref:fig:uniaxial_active_damping_dvf_equiv, right). This is usually refers to as "/sky hook damper/". #+begin_src latex :file uniaxial_active_damping_dvf_equiv.pdf \begin{tikzpicture} % ==================== % Parameters % ==================== \def\massw{2.2} % Width of the masses \def\massh{0.8} % Height of the masses \def\spaceh{1.2} % Height of the springs/dampers \def\dispw{0.4} % Width of the dashed line for the displacement \def\disph{0.3} % Height of the arrow for the displacements \def\bracs{0.05} % Brace spacing vertically \def\brach{-12pt} % Brace shift horizontaly \def\fsensh{0.2} % Height of the force sensor \def\velsize{0.2} % Size of the velocity sensor % ==================== \begin{scope} % ==================== % Stage Below \begin{scope} \draw[fill=white] (-0.5*\massw, \spaceh) rectangle (0.5*\massw, \spaceh+\massh); \draw[spring] (-0.25*\massw, 0) -- (-0.25*\massw, \spaceh); \draw[damper] ( 0.25*\massw, 0) -- ( 0.25*\massw, \spaceh); \draw[decorate,decoration={zigzag,segment length=6pt},draw=black!50!white,very thick] (-0.5*\massw, 0) -- (0.5*\massw, 0); \draw[draw=black!50!white,very thick, dashed] (-0.5*\massw, 0) -- ++(-0.5, 0); \draw[draw=black!50!white,very thick, dashed] ( 0.5*\massw, 0) -- ++( 0.5, 0); \end{scope} % ==================== % ==================== % NASS \begin{scope}[shift={(0, \spaceh+\massh)}] \draw[fill=white] (-0.5*\massw, \spaceh) rectangle (0.5*\massw, \spaceh+\massh) node[pos=0.5]{$m$}; \draw[spring] (-0.4*\massw, 0) -- (-0.4*\massw, \spaceh) node[midway, left=0.1]{$k$}; \draw[damper] (0, 0) -- ( 0, \spaceh) node[midway, left=0.2]{$c$}; \draw[actuator={0.4}{0.2}{black}] ( 0.3*\massw, 0) -- (0.3*\massw, \spaceh) coordinate[midway, shift={(0.1,0)}](f); % Velocity Sensor \node[inertialsensor={\velsize}{coloryellow}] (veln) at (0.5*\massw, \spaceh+\massh) {}; \end{scope} % ==================== % ==================== % Stage Above \begin{scope}[shift={(0, 2*(\spaceh+\massh))}] \draw[spring] (-0.25*\massw, 0) -- (-0.25*\massw, \spaceh); \draw[damper] ( 0.25*\massw, 0) -- ( 0.25*\massw, \spaceh); \draw[decorate,decoration={zigzag,segment length=6pt},draw=black!50!white,very thick] (-0.5*\massw, \spaceh) -- (0.5*\massw, \spaceh); \draw[draw=black!50!white,very thick, dashed] (-0.5*\massw, \spaceh) -- ++(-0.5, 0); \draw[draw=black!50!white,very thick, dashed] ( 0.5*\massw, \spaceh) -- ++( 0.5, 0); \end{scope} % ==================== % ==================== % DVF Control \node[block={2em}{2em}, below right=0.3 and 0.4 of veln, color=coloryellow, fill=coloryellow!10!white] (ppf) {$-g$}; \draw[->, draw=coloryellow] (veln.east) node[above right, color=coloryellow]{$v$} -| (ppf.north); \draw[->, draw=coloryellow] (ppf.south) |- (f.east) node[above right, color=coloryellow]{$f$}; % ==================== \end{scope} \begin{scope}[shift={(6, 0)}] % ==================== % Stage Below \begin{scope} \draw[fill=white] (-0.5*\massw, \spaceh) rectangle (0.5*\massw, \spaceh+\massh); \draw[spring] (-0.25*\massw, 0) -- (-0.25*\massw, \spaceh); \draw[damper] ( 0.25*\massw, 0) -- ( 0.25*\massw, \spaceh); \draw[decorate,decoration={zigzag,segment length=6pt},draw=black!50!white,very thick] (-0.5*\massw, 0) -- (0.5*\massw, 0); \draw[draw=black!50!white,very thick, dashed] (-0.5*\massw, 0) -- ++(-0.5, 0); \draw[draw=black!50!white,very thick, dashed] ( 0.5*\massw, 0) -- ++( 0.5, 0); \end{scope} % ==================== % ==================== % NASS \begin{scope}[shift={(0, \spaceh+\massh)}] \draw[fill=white] (-0.5*\massw, \spaceh) rectangle (0.5*\massw, \spaceh+\massh) node[pos=0.5]{$m$}; \draw[spring] (-0.4*\massw, 0) -- (-0.4*\massw, \spaceh) node[midway, left=0.1]{$k$}; \draw[damper] (0, 0) -- ( 0, \spaceh) node[midway, left=0.2]{$c$}; \draw[damper={coloryellow}{}{}] ( 0.8*\massw, \massh) -- ( 0.8*\massw, \massh+\spaceh)node[midway, left=0.2, color=coloryellow]{$g$}; \draw[draw=coloryellow] (0.5*\massw, \massh+\spaceh) -- ( 0.8*\massw, \massh+\spaceh); \node[mground={0.5}{0.3}{coloryellow}] at (0.8*\massw, \massh); \end{scope} % ==================== % ==================== % Stage Above \begin{scope}[shift={(0, 2*(\spaceh+\massh))}] \draw[spring] (-0.25*\massw, 0) -- (-0.25*\massw, \spaceh); \draw[damper] ( 0.25*\massw, 0) -- ( 0.25*\massw, \spaceh); \draw[decorate,decoration={zigzag,segment length=6pt},draw=black!50!white,very thick] (-0.5*\massw, \spaceh) -- (0.5*\massw, \spaceh); \draw[draw=black!50!white,very thick, dashed] (-0.5*\massw, \spaceh) -- ++(-0.5, 0); \draw[draw=black!50!white,very thick, dashed] ( 0.5*\massw, \spaceh) -- ++( 0.5, 0); \end{scope} % ==================== \end{scope} % Equiv \draw[double, <->, draw=coloryellow, double distance=1.5] (2.5, 1.5*\spaceh+\massh) -- ++(1.5,0); \end{tikzpicture} #+end_src #+name: fig:uniaxial_active_damping_dvf_equiv #+caption: Direct velocity Feedback using an inertial sensor is equivalent to a "sky hook damper" #+RESULTS: [[file:figs/uniaxial_active_damping_dvf_equiv.png]] ** Plant Dynamics for Active Damping The plant dynamics for all three active damping techniques are shown in Figure ref:fig:uniaxial_plant_active_damping_techniques. All have *alternating poles and zeros* meaning that the phase is bounded to $\pm 90\,\text{deg}$ which makes the controller very robust. When the nano-hexapod's suspension modes are at lower frequencies than the resonances of the micro-station (blue and red curves in Figure ref:fig:uniaxial_plant_active_damping_techniques), the resonances of the micro-stations have little impact on the transfer functions from IFF and DVF. For the stiff nano-hexapod, the micro-station dynamics can be seen on the transfer functions in Figure ref:fig:uniaxial_plant_active_damping_techniques. Therefore, it is expected that the micro-station dynamics might impact the achievable damping if a stiff nano-hexapod is used. #+begin_src matlab :exports none :results none %% Damped plants for three considered payload masses - Comparison of active damping techniques figure; tiledlayout(3, 3, 'TileSpacing', 'Compact', 'Padding', 'None'); ax1 = nexttile([2,1]); hold on; plot(freqs, abs(squeeze(freqresp(G_vc_light('fm', 'f'), freqs, 'Hz'))), '-', 'color', colors(1,:), 'DisplayName', '$m_s = 1\,kg$'); plot(freqs, abs(squeeze(freqresp(G_vc_mid( 'fm', 'f'), freqs, 'Hz'))), '-.', 'color', colors(1,:), 'DisplayName', '$m_s = 25\,kg$'); plot(freqs, abs(squeeze(freqresp(G_vc_heavy('fm', 'f'), freqs, 'Hz'))), '--', 'color', colors(1,:), 'DisplayName', '$m_s = 50\,kg$'); plot(freqs, abs(squeeze(freqresp(G_md_light('fm', 'f'), freqs, 'Hz'))), '-', 'color', colors(2,:), 'HandleVisibility', 'off'); plot(freqs, abs(squeeze(freqresp(G_md_mid( 'fm', 'f'), freqs, 'Hz'))), '-.', 'color', colors(2,:), 'HandleVisibility', 'off'); plot(freqs, abs(squeeze(freqresp(G_md_heavy('fm', 'f'), freqs, 'Hz'))), '--', 'color', colors(2,:), 'HandleVisibility', 'off'); plot(freqs, abs(squeeze(freqresp(G_pz_light('fm', 'f'), freqs, 'Hz'))), '-', 'color', colors(3,:), 'HandleVisibility', 'off'); plot(freqs, abs(squeeze(freqresp(G_pz_mid( 'fm', 'f'), freqs, 'Hz'))), '-.', 'color', colors(3,:), 'HandleVisibility', 'off'); plot(freqs, abs(squeeze(freqresp(G_pz_heavy('fm', 'f'), freqs, 'Hz'))), '--', 'color', colors(3,:), 'HandleVisibility', 'off'); hold off; set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log'); ylabel('Amplitude [N/N]'); set(gca, 'XTickLabel',[]); title('IFF: $f_m/f$'); ldg = legend('location', 'southeast', 'FontSize', 8, 'NumColumns', 1); ldg.ItemTokenSize = [20, 1]; ax2 = nexttile([2,1]); hold on; plot(freqs, abs(squeeze(freqresp(G_vc_light('dL', 'f'), freqs, 'Hz'))), '-', 'color', colors(1,:)); plot(freqs, abs(squeeze(freqresp(G_vc_mid( 'dL', 'f'), freqs, 'Hz'))), '-.', 'color', colors(1,:)); plot(freqs, abs(squeeze(freqresp(G_vc_heavy('dL', 'f'), freqs, 'Hz'))), '--', 'color', colors(1,:)); plot(freqs, abs(squeeze(freqresp(G_md_light('dL', 'f'), freqs, 'Hz'))), '-', 'color', colors(2,:)); plot(freqs, abs(squeeze(freqresp(G_md_mid( 'dL', 'f'), freqs, 'Hz'))), '-.', 'color', colors(2,:)); plot(freqs, abs(squeeze(freqresp(G_md_heavy('dL', 'f'), freqs, 'Hz'))), '--', 'color', colors(2,:)); plot(freqs, abs(squeeze(freqresp(G_pz_light('dL', 'f'), freqs, 'Hz'))), '-', 'color', colors(3,:)); plot(freqs, abs(squeeze(freqresp(G_pz_mid( 'dL', 'f'), freqs, 'Hz'))), '-.', 'color', colors(3,:)); plot(freqs, abs(squeeze(freqresp(G_pz_heavy('dL', 'f'), freqs, 'Hz'))), '--', 'color', colors(3,:)); hold off; set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log'); ylabel('Amplitude [m/N]'); set(gca, 'XTickLabel',[]); title('RDC: $d\mathcal{L}/f$'); ax3 = nexttile([2,1]); hold on; plot(freqs, abs(squeeze(freqresp(G_vc_light('vn', 'f'), freqs, 'Hz'))), '-', 'color', colors(1,:), 'DisplayName', '$k_n = 0.01\,N/\mu m$'); plot(freqs, abs(squeeze(freqresp(G_vc_mid( 'vn', 'f'), freqs, 'Hz'))), '-.', 'color', colors(1,:), 'HandleVisibility', 'off'); plot(freqs, abs(squeeze(freqresp(G_vc_heavy('vn', 'f'), freqs, 'Hz'))), '--', 'color', colors(1,:), 'HandleVisibility', 'off'); plot(freqs, abs(squeeze(freqresp(G_md_light('vn', 'f'), freqs, 'Hz'))), '-', 'color', colors(2,:), 'DisplayName', '$k_n = 1\,N/\mu m$'); plot(freqs, abs(squeeze(freqresp(G_md_mid( 'vn', 'f'), freqs, 'Hz'))), '-.', 'color', colors(2,:), 'HandleVisibility', 'off'); plot(freqs, abs(squeeze(freqresp(G_md_heavy('vn', 'f'), freqs, 'Hz'))), '--', 'color', colors(2,:), 'HandleVisibility', 'off'); plot(freqs, abs(squeeze(freqresp(G_pz_light('vn', 'f'), freqs, 'Hz'))), '-', 'color', colors(3,:), 'DisplayName', '$k_n = 100\,N/\mu m$'); plot(freqs, abs(squeeze(freqresp(G_pz_mid( 'vn', 'f'), freqs, 'Hz'))), '-.', 'color', colors(3,:), 'HandleVisibility', 'off'); plot(freqs, abs(squeeze(freqresp(G_pz_heavy('vn', 'f'), freqs, 'Hz'))), '--', 'color', colors(3,:), 'HandleVisibility', 'off'); hold off; set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log'); ylabel('Amplitude [m/s/N]'); set(gca, 'XTickLabel',[]); title('DVF: $v_n/f$'); ldg = legend('location', 'southeast', 'FontSize', 8, 'NumColumns', 1); ldg.ItemTokenSize = [20, 1]; ax1b = nexttile(); hold on; plot(freqs, 180/pi*unwrap(angle(squeeze(freqresp(G_vc_light('fm', 'f'), freqs, 'Hz')))), '-', 'color', colors(1,:)); plot(freqs, 180/pi*unwrap(angle(squeeze(freqresp(G_vc_mid( 'fm', 'f'), freqs, 'Hz')))), '-.', 'color', colors(1,:)); plot(freqs, 180/pi*unwrap(angle(squeeze(freqresp(G_vc_heavy('fm', 'f'), freqs, 'Hz')))), '--', 'color', colors(1,:)); plot(freqs, 180/pi*unwrap(angle(squeeze(freqresp(G_md_light('fm', 'f'), freqs, 'Hz')))), '-', 'color', colors(2,:)); plot(freqs, 180/pi*unwrap(angle(squeeze(freqresp(G_md_mid( 'fm', 'f'), freqs, 'Hz')))), '-.', 'color', colors(2,:)); plot(freqs, 180/pi*unwrap(angle(squeeze(freqresp(G_md_heavy('fm', 'f'), freqs, 'Hz')))), '--', 'color', colors(2,:)); plot(freqs, 180/pi*unwrap(angle(squeeze(freqresp(G_pz_light('fm', 'f'), freqs, 'Hz')))), '-', 'color', colors(3,:)); plot(freqs, 180/pi*unwrap(angle(squeeze(freqresp(G_pz_mid( 'fm', 'f'), freqs, 'Hz')))), '-.', 'color', colors(3,:)); plot(freqs, 180/pi*unwrap(angle(squeeze(freqresp(G_pz_heavy('fm', 'f'), freqs, 'Hz')))), '--', 'color', colors(3,:)); hold off; set(gca, 'XScale', 'log'); set(gca, 'YScale', 'lin'); xlabel('Frequency [Hz]'); ylabel('Phase [deg]'); xticks([1e0, 1e1, 1e2]); yticks(-360:90:360); ylim([-200, 20]); ax2b = nexttile(); hold on; plot(freqs, 180/pi*unwrap(angle(squeeze(freqresp(G_vc_light('dL', 'f'), freqs, 'Hz')))), '-', 'color', colors(1,:)); plot(freqs, 180/pi*unwrap(angle(squeeze(freqresp(G_vc_mid( 'dL', 'f'), freqs, 'Hz')))), '-.', 'color', colors(1,:)); plot(freqs, 180/pi*unwrap(angle(squeeze(freqresp(G_vc_heavy('dL', 'f'), freqs, 'Hz')))), '--', 'color', colors(1,:)); plot(freqs, 180/pi*unwrap(angle(squeeze(freqresp(G_md_light('dL', 'f'), freqs, 'Hz')))), '-', 'color', colors(2,:)); plot(freqs, 180/pi*unwrap(angle(squeeze(freqresp(G_md_mid( 'dL', 'f'), freqs, 'Hz')))), '-.', 'color', colors(2,:)); plot(freqs, 180/pi*unwrap(angle(squeeze(freqresp(G_md_heavy('dL', 'f'), freqs, 'Hz')))), '--', 'color', colors(2,:)); plot(freqs, 180/pi*unwrap(angle(squeeze(freqresp(G_pz_light('dL', 'f'), freqs, 'Hz')))), '-', 'color', colors(3,:)); plot(freqs, 180/pi*unwrap(angle(squeeze(freqresp(G_pz_mid( 'dL', 'f'), freqs, 'Hz')))), '-.', 'color', colors(3,:)); plot(freqs, 180/pi*unwrap(angle(squeeze(freqresp(G_pz_heavy('dL', 'f'), freqs, 'Hz')))), '--', 'color', colors(3,:)); hold off; set(gca, 'XScale', 'log'); set(gca, 'YScale', 'lin'); xlabel('Frequency [Hz]'); ylabel('Phase [deg]'); xticks([1e0, 1e1, 1e2]); yticks(-360:90:360); ylim([-200, 20]); ax3b = nexttile(); hold on; plot(freqs, 180/pi*unwrap(angle(squeeze(freqresp(G_vc_light('vn', 'f'), freqs, 'Hz')))), '-', 'color', colors(1,:)); plot(freqs, 180/pi*unwrap(angle(squeeze(freqresp(G_vc_mid( 'vn', 'f'), freqs, 'Hz')))), '-.', 'color', colors(1,:)); plot(freqs, 180/pi*unwrap(angle(squeeze(freqresp(G_vc_heavy('vn', 'f'), freqs, 'Hz')))), '--', 'color', colors(1,:)); plot(freqs, 180/pi*unwrap(angle(squeeze(freqresp(G_md_light('vn', 'f'), freqs, 'Hz')))), '-', 'color', colors(2,:)); plot(freqs, 180/pi*unwrap(angle(squeeze(freqresp(G_md_mid( 'vn', 'f'), freqs, 'Hz')))), '-.', 'color', colors(2,:)); plot(freqs, 180/pi*unwrap(angle(squeeze(freqresp(G_md_heavy('vn', 'f'), freqs, 'Hz')))), '--', 'color', colors(2,:)); plot(freqs, 180/pi*unwrap(angle(squeeze(freqresp(G_pz_light('vn', 'f'), freqs, 'Hz')))), '-', 'color', colors(3,:)); plot(freqs, 180/pi*unwrap(angle(squeeze(freqresp(G_pz_mid( 'vn', 'f'), freqs, 'Hz')))), '-.', 'color', colors(3,:)); plot(freqs, 180/pi*unwrap(angle(squeeze(freqresp(G_pz_heavy('vn', 'f'), freqs, 'Hz')))), '--', 'color', colors(3,:)); hold off; set(gca, 'XScale', 'log'); set(gca, 'YScale', 'lin'); xlabel('Frequency [Hz]'); ylabel('Phase [deg]'); xticks([1e0, 1e1, 1e2]); yticks(-360:90:360); ylim([-110, 110]); linkaxes([ax1,ax2,ax3,ax1b,ax2b,ax3b],'x'); xlim([1, 1000]); #+end_src #+begin_src matlab :tangle no :exports results :results file replace exportFig('figs/uniaxial_plant_active_damping_techniques.pdf', 'width', 'full', 'height', 'tall'); #+end_src #+name: fig:uniaxial_plant_active_damping_techniques #+caption: Plant dynamics for the three active damping techniques (IFF: right, RDC: middle, DVF: left), for three nano-hexapod stiffnesses ($k_n = 0.01\,N/\mu m$ in blue, $k_n = 1\,N/\mu m$ in red and $k_n = 100\,N/\mu m$ in yellow) and three sample's masses ($m_s = 1\,kg$: solid curves, $m_s = 25\,kg$: dot-dashed curves, and $m_s = 50\,kg$: dashed curves). #+RESULTS: [[file:figs/uniaxial_plant_active_damping_techniques.png]] ** Achievable Damping - Root Locus The Root Locus are computed for the three nano-hexapod stiffnesses and for the three active damping techniques. They are shown in Figure ref:fig:uniaxial_root_locus_damping_techniques. All three active damping approach can lead to *critical damping* of the nano-hexapod suspension mode. There is even a little bit of authority on micro-station modes with IFF and DVF applied on the stiff nano-hexapod (Figure ref:fig:uniaxial_root_locus_damping_techniques, right) and with RDC for a soft nano-hexapod (Figure ref:fig:uniaxial_root_locus_damping_techniques_micro_station_mode). This can be explained by the fact that above the suspension mode of the soft nano-hexapod, the relative motion sensor acts as an inertial sensor for the micro-station top platform. Therefore, it is like DVF was applied (the nano-hexapod acts as a geophone!). #+begin_src matlab :exports none %% Active Damping Robustness to change of sample's mass - Root Locus for all three damping techniques with 3 different sample's masses figure; tiledlayout(1, 3, 'TileSpacing', 'Compact', 'Padding', 'None'); %% Soft Nano-Hexapod ax1 = nexttile(); hold on; % IFF plot(real(pole(G_vc_light('fm', 'f'))), imag(pole(G_vc_light('fm', 'f'))), 'x', 'color', colors(1,:), ... 'HandleVisibility', 'off'); plot(real(zero(G_vc_light('fm', 'f'))), imag(zero(G_vc_light('fm', 'f'))), 'o', 'color', colors(1,:), ... 'DisplayName', 'IFF'); for g = logspace(0, 2, 400) clpoles = pole(feedback(G_vc_light('fm', 'f'), g/s, +1)); plot(real(clpoles), imag(clpoles), '.', 'color', colors(1,:), ... 'HandleVisibility', 'off'); end % RDC plot(real(pole(G_vc_light('dL', 'f'))), imag(pole(G_vc_light('dL', 'f'))), 'x', 'color', colors(2,:), ... 'HandleVisibility', 'off'); plot(real(zero(G_vc_light('dL', 'f'))), imag(zero(G_vc_light('dL', 'f'))), 'o', 'color', colors(2,:), ... 'DisplayName', 'RDC'); for g = logspace(1,3,400) clpoles = pole(feedback(G_vc_light('dL', 'f'), -g*s, +1)); plot(real(clpoles), imag(clpoles), '.', 'color', colors(2,:), ... 'HandleVisibility', 'off'); end % DVF plot(real(pole(G_vc_light('vn', 'f'))), imag(pole(G_vc_light('vn', 'f'))), 'x', 'color', colors(3,:), ... 'HandleVisibility', 'off'); plot(real(zero(G_vc_light('vn', 'f'))), imag(zero(G_vc_light('vn', 'f'))), 'o', 'color', colors(3,:), ... 'DisplayName', 'DVF'); for g = logspace(1,3,400) clpoles = pole(feedback(G_vc_light('vn', 'f'), -g, +1)); plot(real(clpoles), imag(clpoles), '.', 'color', colors(3,:), ... 'HandleVisibility', 'off'); end hold off; axis square; xlabel('Real Part'); ylabel('Imaginary Part'); title('$k_n = 0.01\,N/\mu m$') ldg = legend('location', 'northwest', 'FontSize', 8, 'NumColumns', 1); ldg.ItemTokenSize = [10, 1]; xlim([-30, 0]); ylim([0, 30]); %% Medium-Stiff Nano-Hexapod ax2 = nexttile(); hold on; % IFF plot(real(pole(G_md_light('fm', 'f'))), imag(pole(G_md_light('fm', 'f'))), 'x', 'color', colors(1,:), ... 'HandleVisibility', 'off'); plot(real(zero(G_md_light('fm', 'f'))), imag(zero(G_md_light('fm', 'f'))), 'o', 'color', colors(1,:), ... 'HandleVisibility', 'off'); for g = logspace(0,3,400) clpoles = pole(feedback(G_md_light('fm', 'f'), g/s, +1)); plot(real(clpoles), imag(clpoles), '.', 'color', colors(1,:), ... 'HandleVisibility', 'off'); end % RDC plot(real(pole(G_md_light('dL', 'f'))), imag(pole(G_md_light('dL', 'f'))), 'x', 'color', colors(2,:), ... 'HandleVisibility', 'off'); plot(real(zero(G_md_light('dL', 'f'))), imag(zero(G_md_light('dL', 'f'))), 'o', 'color', colors(2,:), ... 'HandleVisibility', 'off'); for g = logspace(2,4,400) clpoles = pole(feedback(G_md_light('dL', 'f'), -g*s, +1)); plot(real(clpoles), imag(clpoles), '.', 'color', colors(2,:), ... 'HandleVisibility', 'off'); end % DVF plot(real(pole(G_md_light('vn', 'f'))), imag(pole(G_md_light('vn', 'f'))), 'x', 'color', colors(3,:), ... 'HandleVisibility', 'off'); plot(real(zero(G_md_light('vn', 'f'))), imag(zero(G_md_light('vn', 'f'))), 'o', 'color', colors(3,:), ... 'HandleVisibility', 'off'); for g = logspace(2,4,400) clpoles = pole(feedback(G_md_light('vn', 'f'), -g, +1)); plot(real(clpoles), imag(clpoles), '.', 'color', colors(3,:), ... 'HandleVisibility', 'off'); end hold off; axis square; xlabel('Real Part'); ylabel('Imaginary Part'); title('$k_n = 1\,N/\mu m$') xlim([-300, 0]); ylim([0, 300]); %% Stiff Nano-Hexapod ax3 = nexttile(); hold on; % IFF plot(real(pole(G_pz_light('fm', 'f'))), imag(pole(G_pz_light('fm', 'f'))), 'x', 'color', colors(1,:), ... 'HandleVisibility', 'off'); plot(real(zero(G_pz_light('fm', 'f'))), imag(zero(G_pz_light('fm', 'f'))), 'o', 'color', colors(1,:), ... 'HandleVisibility', 'off'); for g = logspace(2,5,400) clpoles = pole(feedback(G_pz_light('fm', 'f'), g/s, +1)); plot(real(clpoles), imag(clpoles), '.', 'color', colors(1,:), ... 'HandleVisibility', 'off'); end % RDC plot(real(pole(G_pz_light('dL', 'f'))), imag(pole(G_pz_light('dL', 'f'))), 'x', 'color', colors(2,:), ... 'HandleVisibility', 'off'); plot(real(zero(G_pz_light('dL', 'f'))), imag(zero(G_pz_light('dL', 'f'))), 'o', 'color', colors(2,:), ... 'HandleVisibility', 'off'); for g = logspace(3,6,400) clpoles = pole(feedback(G_pz_light('dL', 'f'), -g*s, +1)); plot(real(clpoles), imag(clpoles), '.', 'color', colors(2,:), ... 'HandleVisibility', 'off'); end % DVF plot(real(pole(G_pz_light('vn', 'f'))), imag(pole(G_pz_light('vn', 'f'))), 'x', 'color', colors(3,:), ... 'HandleVisibility', 'off'); plot(real(zero(G_pz_light('vn', 'f'))), imag(zero(G_pz_light('vn', 'f'))), 'o', 'color', colors(3,:), ... 'HandleVisibility', 'off'); for g = logspace(3,6,400) clpoles = pole(feedback(G_pz_light('vn', 'f'), -g, +1)); plot(real(clpoles), imag(clpoles), '.', 'color', colors(3,:), ... 'HandleVisibility', 'off'); end hold off; axis square; xlabel('Real Part'); ylabel('Imaginary Part'); title('$k_n = 100\,N/\mu m$') xlim([-4000, 0]); ylim([0, 4000]); #+end_src #+begin_src matlab :tangle no :exports results :results file replace exportFig('figs/uniaxial_root_locus_damping_techniques.pdf', 'width', 'full', 'height', 'normal'); #+end_src #+name: fig:uniaxial_root_locus_damping_techniques #+caption: Root Loci for the three active damping techniques (IFF in blue, RDC in red and DVF in yellow). This is shown for three nano-hexapod stiffnesses. #+RESULTS: [[file:figs/uniaxial_root_locus_damping_techniques.png]] #+begin_src matlab :exports none :results none %% Root Locus for the three damping techniques figure; hold on; % IFF plot(real(pole(G_md_mid('fm', 'f'))), imag(pole(G_md_mid('fm', 'f'))), 'x', 'color', colors(1,:), ... 'DisplayName', 'IFF'); plot(real(zero(G_md_mid('fm', 'f'))), imag(zero(G_md_mid('fm', 'f'))), 'o', 'color', colors(1,:), ... 'HandleVisibility', 'off'); for g = logspace(1,4,500) clpoles = pole(feedback(G_md_mid('fm', 'f'), g/s, +1)); plot(real(clpoles), imag(clpoles), '.', 'color', colors(1,:), ... 'HandleVisibility', 'off'); end % RDC plot(real(pole(G_md_mid('dL', 'f'))), imag(pole(G_md_mid('dL', 'f'))), 'x', 'color', colors(2,:), ... 'DisplayName', 'RDC'); plot(real(zero(G_md_mid('dL', 'f'))), imag(zero(G_md_mid('dL', 'f'))), 'o', 'color', colors(2,:), ... 'HandleVisibility', 'off'); for g = logspace(2,5,500) clpoles = pole(feedback(G_md_mid('dL', 'f'), -g*s, +1)); plot(real(clpoles), imag(clpoles), '.', 'color', colors(2,:), ... 'HandleVisibility', 'off'); end % DVF plot(real(pole(G_md_mid('vn', 'f'))), imag(pole(G_md_mid('vn', 'f'))), 'x', 'color', colors(3,:), ... 'DisplayName', 'DVF'); plot(real(zero(G_md_mid('vn', 'f'))), imag(zero(G_md_mid('vn', 'f'))), 'o', 'color', colors(3,:), ... 'HandleVisibility', 'off'); for g = logspace(2,5,500) clpoles = pole(feedback(G_md_mid('vn', 'f'), -tf(g), +1)); plot(real(clpoles), imag(clpoles), '.', 'color', colors(3,:), ... 'HandleVisibility', 'off'); end hold off; xlim([-2100, 0]); ylim([0, 2100]); axis square; xlabel('Real Part'); ylabel('Imaginary Part'); ldg = legend('location', 'northwest', 'FontSize', 8, 'NumColumns', 1); ldg.ItemTokenSize = [10, 1]; #+end_src #+begin_src matlab :tangle no :exports results :results file replace exportFig('figs/uniaxial_root_locus_damping_techniques_micro_station_mode.pdf', 'width', 'wide', 'height', 'normal'); #+end_src #+name: fig:uniaxial_root_locus_damping_techniques_micro_station_mode #+caption: Root Locus for the three damping techniques. It is shown that the RDC active damping technique has some authority on one mode of the micro-station. This mode corresponds to the suspension mode of the micro-hexapod. #+RESULTS: [[file:figs/uniaxial_root_locus_damping_techniques_micro_station_mode.png]] ** Active Damping Controller Optimization and Damped plants :noexport: #+begin_src matlab :exports none %% Design of Active Damping controllers to have reasonable damping % IFF K_iff_vc = 20/(s + 2*pi*0.01); K_iff_vc.InputName = {'fm'}; K_iff_vc.OutputName = {'f'}; K_iff_md = 200/(s + 2*pi*0.01); K_iff_md.InputName = {'fm'}; K_iff_md.OutputName = {'f'}; K_iff_pz = 4000/(s + 2*pi*0.01); K_iff_pz.InputName = {'fm'}; K_iff_pz.OutputName = {'f'}; % RDC K_rdc_vc = -1e3*s; K_rdc_vc.InputName = {'dL'}; K_rdc_vc.OutputName = {'f'}; K_rdc_md = -1e4*s; K_rdc_md.InputName = {'dL'}; K_rdc_md.OutputName = {'f'}; K_rdc_pz = -1e5*s; K_rdc_pz.InputName = {'dL'}; K_rdc_pz.OutputName = {'f'}; % DVF K_dvf_vc = -tf(1e3); K_dvf_vc.InputName = {'vn'}; K_dvf_vc.OutputName = {'f'}; K_dvf_md = -tf(8e3); K_dvf_md.InputName = {'vn'}; K_dvf_md.OutputName = {'f'}; K_dvf_pz = -tf(2e5); K_dvf_pz.InputName = {'vn'}; K_dvf_pz.OutputName = {'f'}; #+end_src #+begin_src matlab :exports none :tangle no %% Save Active Damping Controllers save('./matlab/mat/uniaxial_active_damping_controllers.mat', 'K_iff_vc', 'K_iff_md', 'K_iff_pz', ... 'K_rdc_vc', 'K_rdc_md', 'K_rdc_pz', ... 'K_dvf_vc', 'K_dvf_md', 'K_dvf_pz'); #+end_src #+begin_src matlab :exports none :eval no %% Save Active Damping Controller save('./mat/uniaxial_active_damping_controllers.mat', 'K_iff_vc', 'K_iff_md', 'K_iff_pz', ... 'K_rdc_vc', 'K_rdc_md', 'K_rdc_pz', ... 'K_dvf_vc', 'K_dvf_md', 'K_dvf_pz'); #+end_src #+begin_src matlab :exports none %% Compute Damped Plants % IFF G_iff_vc_light = feedback(G_vc_light, K_iff_vc, 'name', +1); G_iff_vc_mid = feedback(G_vc_mid , K_iff_vc, 'name', +1); G_iff_vc_heavy = feedback(G_vc_heavy, K_iff_vc, 'name', +1); G_iff_md_light = feedback(G_md_light, K_iff_md, 'name', +1); G_iff_md_mid = feedback(G_md_mid , K_iff_md, 'name', +1); G_iff_md_heavy = feedback(G_md_heavy, K_iff_md, 'name', +1); G_iff_pz_light = feedback(G_pz_light, K_iff_pz, 'name', +1); G_iff_pz_mid = feedback(G_pz_mid , K_iff_pz, 'name', +1); G_iff_pz_heavy = feedback(G_pz_heavy, K_iff_pz, 'name', +1); % RDC G_rdc_vc_light = feedback(G_vc_light, K_rdc_vc, 'name', +1); G_rdc_vc_mid = feedback(G_vc_mid , K_rdc_vc, 'name', +1); G_rdc_vc_heavy = feedback(G_vc_heavy, K_rdc_vc, 'name', +1); G_rdc_md_light = feedback(G_md_light, K_rdc_md, 'name', +1); G_rdc_md_mid = feedback(G_md_mid , K_rdc_md, 'name', +1); G_rdc_md_heavy = feedback(G_md_heavy, K_rdc_md, 'name', +1); G_rdc_pz_light = feedback(G_pz_light, K_rdc_pz, 'name', +1); G_rdc_pz_mid = feedback(G_pz_mid , K_rdc_pz, 'name', +1); G_rdc_pz_heavy = feedback(G_pz_heavy, K_rdc_pz, 'name', +1); % DVF G_dvf_vc_light = feedback(G_vc_light, K_dvf_vc, 'name', +1); G_dvf_vc_mid = feedback(G_vc_mid , K_dvf_vc, 'name', +1); G_dvf_vc_heavy = feedback(G_vc_heavy, K_dvf_vc, 'name', +1); G_dvf_md_light = feedback(G_md_light, K_dvf_md, 'name', +1); G_dvf_md_mid = feedback(G_md_mid , K_dvf_md, 'name', +1); G_dvf_md_heavy = feedback(G_md_heavy, K_dvf_md, 'name', +1); G_dvf_pz_light = feedback(G_pz_light, K_dvf_pz, 'name', +1); G_dvf_pz_mid = feedback(G_pz_mid , K_dvf_pz, 'name', +1); G_dvf_pz_heavy = feedback(G_pz_heavy, K_dvf_pz, 'name', +1); #+end_src #+begin_src matlab %% Verify Stability % IFF isstable(G_iff_vc_light) && isstable(G_iff_vc_mid) && isstable(G_iff_vc_heavy) && ... isstable(G_iff_md_light) && isstable(G_iff_md_mid) && isstable(G_iff_md_heavy) && ... isstable(G_iff_pz_light) && isstable(G_iff_pz_mid) && isstable(G_iff_pz_heavy) % RDC isstable(G_rdc_vc_light) && isstable(G_rdc_vc_mid) && isstable(G_rdc_vc_heavy) && ... isstable(G_rdc_md_light) && isstable(G_rdc_md_mid) && isstable(G_rdc_md_heavy) && ... isstable(G_rdc_pz_light) && isstable(G_rdc_pz_mid) && isstable(G_rdc_pz_heavy) % DVF isstable(G_dvf_vc_light) && isstable(G_dvf_vc_mid) && isstable(G_dvf_vc_heavy) && ... isstable(G_dvf_md_light) && isstable(G_dvf_md_mid) && isstable(G_dvf_md_heavy) && ... isstable(G_dvf_pz_light) && isstable(G_dvf_pz_mid) && isstable(G_dvf_pz_heavy) #+end_src #+begin_src matlab :exports none :tangle no %% Save Active Damping Controllers save('./matlab/mat/uniaxial_damped_plants.mat', 'G_iff_vc_light', 'G_iff_md_light', 'G_iff_pz_light', ... 'G_rdc_vc_light', 'G_rdc_md_light', 'G_rdc_pz_light', ... 'G_dvf_vc_light', 'G_dvf_md_light', 'G_dvf_pz_light', ... 'G_iff_vc_mid', 'G_iff_md_mid', 'G_iff_pz_mid', ... 'G_rdc_vc_mid', 'G_rdc_md_mid', 'G_rdc_pz_mid', ... 'G_dvf_vc_mid', 'G_dvf_md_mid', 'G_dvf_pz_mid', ... 'G_iff_vc_heavy', 'G_iff_md_heavy', 'G_iff_pz_heavy', ... 'G_rdc_vc_heavy', 'G_rdc_md_heavy', 'G_rdc_pz_heavy', ... 'G_dvf_vc_heavy', 'G_dvf_md_heavy', 'G_dvf_pz_heavy'); #+end_src #+begin_src matlab :exports none :eval no %% Save Active Damping Controller save('./mat/uniaxial_damped_plants.mat', 'G_iff_vc_light', 'G_iff_md_light', 'G_iff_pz_light', ... 'G_rdc_vc_light', 'G_rdc_md_light', 'G_rdc_pz_light', ... 'G_dvf_vc_light', 'G_dvf_md_light', 'G_dvf_pz_light', ... 'G_iff_vc_mid', 'G_iff_md_mid', 'G_iff_pz_mid', ... 'G_rdc_vc_mid', 'G_rdc_md_mid', 'G_rdc_pz_mid', ... 'G_dvf_vc_mid', 'G_dvf_md_mid', 'G_dvf_pz_mid', ... 'G_iff_vc_heavy', 'G_iff_md_heavy', 'G_iff_pz_heavy', ... 'G_rdc_vc_heavy', 'G_rdc_md_heavy', 'G_rdc_pz_heavy', ... 'G_dvf_vc_heavy', 'G_dvf_md_heavy', 'G_dvf_pz_heavy'); #+end_src ** Change of sensitivity to disturbances The sensitivity to disturbances (direct forces $f_s$, stage vibrations $f_t$ and floor motion $x_f$) for all three active damping techniques are compared in Figure ref:fig:uniaxial_sensitivity_dist_active_damping. The comparison is done with the nano-hexapod having a stiffness $k_n = 1\,N/\mu m$. #+begin_important Conclusions from Figure ref:fig:uniaxial_sensitivity_dist_active_damping are: - IFF degrades the sensitivity to direct forces on the sample (i.e. the compliance) below the resonance of the nano-hexapod - RDC degrades the sensitivity to stage vibrations around the nano-hexapod's resonance as compared to the other two methods - both IFF and DVF degrades the sensitivity to floor motion below the resonance of the nano-hexapod #+end_important #+begin_src matlab :exports none :results none %% Change of sensitivity to disturbance with all three active damping strategies figure; tiledlayout(1, 3, 'TileSpacing', 'Compact', 'Padding', 'None'); ax1 = nexttile(); hold on; plot(freqs, abs(squeeze(freqresp(G_md_mid('d', 'fs'), freqs, 'Hz'))), 'k-'); plot(freqs, abs(squeeze(freqresp(G_iff_md_mid('d', 'fs'), freqs, 'Hz'))), 'color', colors(1,:)); plot(freqs, abs(squeeze(freqresp(G_rdc_md_mid('d', 'fs'), freqs, 'Hz'))), 'color', colors(2,:)); plot(freqs, abs(squeeze(freqresp(G_dvf_md_mid('d', 'fs'), freqs, 'Hz'))), 'color', colors(3,:)); hold off; set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log'); ylabel('Amplitude $d/f_{s}$ [m/N]'); xlabel('Frequency [Hz]'); xticks([1e0, 1e1, 1e2]); ax2 = nexttile(); hold on; plot(freqs, abs(squeeze(freqresp(G_md_mid('d', 'ft'), freqs, 'Hz'))), 'k-'); plot(freqs, abs(squeeze(freqresp(G_iff_md_mid('d', 'ft'), freqs, 'Hz'))), 'color', colors(1,:)); plot(freqs, abs(squeeze(freqresp(G_rdc_md_mid('d', 'ft'), freqs, 'Hz'))), 'color', colors(2,:)); plot(freqs, abs(squeeze(freqresp(G_dvf_md_mid('d', 'ft'), freqs, 'Hz'))), 'color', colors(3,:)); hold off; set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log'); ylabel('Amplitude $d/f_{t}$ [m/N]'); xlabel('Frequency [Hz]'); xticks([1e0, 1e1, 1e2]); ax3 = nexttile(); hold on; plot(freqs, abs(squeeze(freqresp(G_md_mid('d', 'xf'), freqs, 'Hz'))), 'k-', 'DisplayName', 'OL'); plot(freqs, abs(squeeze(freqresp(G_iff_md_mid('d', 'xf'), freqs, 'Hz'))), 'color', colors(1,:), 'DisplayName', 'IFF'); plot(freqs, abs(squeeze(freqresp(G_rdc_md_mid('d', 'xf'), freqs, 'Hz'))), 'color', colors(2,:), 'DisplayName', 'RDC'); plot(freqs, abs(squeeze(freqresp(G_dvf_md_mid('d', 'xf'), freqs, 'Hz'))), 'color', colors(3,:), 'DisplayName', 'DVF'); hold off; set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log'); ylabel('Amplitude $d/x_{f}$ [m/m]'); xlabel('Frequency [Hz]'); xticks([1e0, 1e1, 1e2]); legend('location', 'southeast', 'FontSize', 8, 'NumColumns', 1); linkaxes([ax1,ax2,ax3],'x'); xlim([1, 500]); #+end_src #+begin_src matlab :tangle no :exports results :results file replace exportFig('figs/uniaxial_sensitivity_dist_active_damping.pdf', 'width', 'full', 'height', 'normal'); #+end_src #+name: fig:uniaxial_sensitivity_dist_active_damping #+caption: Change of sensitivity to disturbance with all three active damping strategies #+RESULTS: [[file:figs/uniaxial_sensitivity_dist_active_damping.png]] ** Noise Budgeting after Active Damping Cumulative Amplitude Spectrum of the distance $d$ with all three active damping techniques are compared in Figure ref:fig:uniaxial_cas_active_damping. All three active damping methods are giving similar results (except the RDC which is a little bit worse for the stiff nano-hexapod). Compare to the open-loop case, the active damping helps to lower the vibrations induced by the nano-hexapod resonance. #+begin_src matlab :exports none :results none %% Cumulative Amplitude Spectrum of the distance d with all three active damping techniques figure; tiledlayout(1, 3, 'TileSpacing', 'Compact', 'Padding', 'None'); ax1 = nexttile(); hold on; plot(f, sqrt(flip(-cumtrapz(flip(f), flip(psd_ft.*abs(squeeze(freqresp(G_vc_mid('d', 'ft'), f, 'Hz'))).^2 + ... psd_xf.*abs(squeeze(freqresp(G_vc_mid('d', 'xf'), f, 'Hz'))).^2)))), '-', ... 'color', 'black', 'DisplayName', 'OL'); plot(f, sqrt(flip(-cumtrapz(flip(f), flip(psd_ft.*abs(squeeze(freqresp(G_iff_vc_mid('d', 'ft'), f, 'Hz'))).^2 + ... psd_xf.*abs(squeeze(freqresp(G_iff_vc_mid('d', 'xf'), f, 'Hz'))).^2)))), '-', ... 'color', colors(1,:), 'DisplayName', 'IFF'); plot(f, sqrt(flip(-cumtrapz(flip(f), flip(psd_ft.*abs(squeeze(freqresp(G_rdc_vc_mid('d', 'ft'), f, 'Hz'))).^2 + ... psd_xf.*abs(squeeze(freqresp(G_rdc_vc_mid('d', 'xf'), f, 'Hz'))).^2)))), '-', ... 'color', colors(2,:), 'DisplayName', 'RDC'); plot(f, sqrt(flip(-cumtrapz(flip(f), flip(psd_ft.*abs(squeeze(freqresp(G_dvf_vc_mid('d', 'ft'), f, 'Hz'))).^2 + ... psd_xf.*abs(squeeze(freqresp(G_dvf_vc_mid('d', 'xf'), f, 'Hz'))).^2)))), '-', ... 'color', colors(3,:), 'DisplayName', 'DVF'); hold off; set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log'); ylabel('CAS of $d$ [m]'); xlabel('Frequency [Hz]'); xticks([1e0, 1e1, 1e2]); title('$k_n = 0.01\,N/\mu m$') ax2 = nexttile(); hold on; plot(f, sqrt(flip(-cumtrapz(flip(f), flip(psd_ft.*abs(squeeze(freqresp(G_md_mid('d', 'ft'), f, 'Hz'))).^2 + ... psd_xf.*abs(squeeze(freqresp(G_md_mid('d', 'xf'), f, 'Hz'))).^2)))), '-', ... 'color', 'black', 'DisplayName', 'OL'); plot(f, sqrt(flip(-cumtrapz(flip(f), flip(psd_ft.*abs(squeeze(freqresp(G_iff_md_mid('d', 'ft'), f, 'Hz'))).^2 + ... psd_xf.*abs(squeeze(freqresp(G_iff_md_mid('d', 'xf'), f, 'Hz'))).^2)))), '-', ... 'color', colors(1,:), 'DisplayName', 'IFF'); plot(f, sqrt(flip(-cumtrapz(flip(f), flip(psd_ft.*abs(squeeze(freqresp(G_rdc_md_mid('d', 'ft'), f, 'Hz'))).^2 + ... psd_xf.*abs(squeeze(freqresp(G_rdc_md_mid('d', 'xf'), f, 'Hz'))).^2)))), '-', ... 'color', colors(2,:), 'DisplayName', 'RDC'); plot(f, sqrt(flip(-cumtrapz(flip(f), flip(psd_ft.*abs(squeeze(freqresp(G_dvf_md_mid('d', 'ft'), f, 'Hz'))).^2 + ... psd_xf.*abs(squeeze(freqresp(G_dvf_md_mid('d', 'xf'), f, 'Hz'))).^2)))), '-', ... 'color', colors(3,:), 'DisplayName', 'DVF'); hold off; set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log'); xlabel('Frequency [Hz]'); set(gca, 'YTickLabel',[]); xticks([1e0, 1e1, 1e2]); title('$k_n = 1\,N/\mu m$') ax3 = nexttile(); hold on; plot(f, sqrt(flip(-cumtrapz(flip(f), flip(psd_ft.*abs(squeeze(freqresp(G_pz_mid('d', 'ft'), f, 'Hz'))).^2 + ... psd_xf.*abs(squeeze(freqresp(G_pz_mid('d', 'xf'), f, 'Hz'))).^2)))), '-', ... 'color', 'black', 'DisplayName', 'OL'); plot(f, sqrt(flip(-cumtrapz(flip(f), flip(psd_ft.*abs(squeeze(freqresp(G_iff_pz_mid('d', 'ft'), f, 'Hz'))).^2 + ... psd_xf.*abs(squeeze(freqresp(G_iff_pz_mid('d', 'xf'), f, 'Hz'))).^2)))), '-', ... 'color', colors(1,:), 'DisplayName', 'IFF'); plot(f, sqrt(flip(-cumtrapz(flip(f), flip(psd_ft.*abs(squeeze(freqresp(G_rdc_pz_mid('d', 'ft'), f, 'Hz'))).^2 + ... psd_xf.*abs(squeeze(freqresp(G_rdc_pz_mid('d', 'xf'), f, 'Hz'))).^2)))), '-', ... 'color', colors(2,:), 'DisplayName', 'RDC'); plot(f, sqrt(flip(-cumtrapz(flip(f), flip(psd_ft.*abs(squeeze(freqresp(G_dvf_pz_mid('d', 'ft'), f, 'Hz'))).^2 + ... psd_xf.*abs(squeeze(freqresp(G_dvf_pz_mid('d', 'xf'), f, 'Hz'))).^2)))), '-', ... 'color', colors(3,:), 'DisplayName', 'DVF'); hold off; set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log'); xlabel('Frequency [Hz]'); set(gca, 'YTickLabel',[]); xticks([1e0, 1e1, 1e2]); title('$k_n = 100\,N/\mu m$') legend('location', 'southwest', 'FontSize', 8, 'NumColumns', 1); linkaxes([ax1,ax2,ax3], 'xy') xlim([1, 500]); ylim([2e-10, 3e-6]) #+end_src #+begin_src matlab :tangle no :exports results :results file replace exportFig('figs/uniaxial_cas_active_damping.pdf', 'width', 'full', 'height', 'normal'); #+end_src #+name: fig:uniaxial_cas_active_damping #+caption: Comparison of the cumulative amplitude spectrum (CAS) of the distance $d$ for all three active damping techniques (OL in black, IFF in blue, RDC in red and DVF in yellow). #+RESULTS: [[file:figs/uniaxial_cas_active_damping.png]] ** Obtained Damped Plant The transfer functions from the plant input $f$ to the relative displacement $d$ while the active damping is implemented are shown in Figure ref:fig:uniaxial_damped_plant_three_active_damping_techniques. All three active damping techniques yield similar damped plants. #+begin_src matlab :exports none :results none %% Obtained damped transfer function from f to d for the three damping techniques figure; tiledlayout(3, 1, 'TileSpacing', 'Compact', 'Padding', 'None'); ax1 = nexttile([2,1]); hold on; plot(freqs, abs(squeeze(freqresp(G_md_mid('d', 'f'), freqs, 'Hz'))), 'k-', 'DisplayName', 'OL'); plot(freqs, abs(squeeze(freqresp(G_iff_md_mid('d', 'f'), freqs, 'Hz'))), 'color', colors(1,:), 'DisplayName', 'IFF'); plot(freqs, abs(squeeze(freqresp(G_rdc_md_mid('d', 'f'), freqs, 'Hz'))), 'color', colors(2,:), 'DisplayName', 'RDC'); plot(freqs, abs(squeeze(freqresp(G_dvf_md_mid('d', 'f'), freqs, 'Hz'))), 'color', colors(3,:), 'DisplayName', 'DVF'); hold off; set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log'); ylabel('Amplitude $d/f$ [m/N]'); set(gca, 'XTickLabel',[]); legend('location', 'northwest', 'FontSize', 8, 'NumColumns', 1); ax2 = nexttile(); hold on; plot(freqs, 180/pi*unwrap(angle(squeeze(freqresp(G_md_mid('d', 'f'), freqs, 'Hz')))), 'k-'); plot(freqs, 180/pi*unwrap(angle(squeeze(freqresp(G_iff_md_mid('d', 'f'), freqs, 'Hz')))), 'color', colors(1,:)); plot(freqs, 180/pi*unwrap(angle(squeeze(freqresp(G_rdc_md_mid('d', 'f'), freqs, 'Hz')))), 'color', colors(2,:)); plot(freqs, 180/pi*unwrap(angle(squeeze(freqresp(G_dvf_md_mid('d', 'f'), freqs, 'Hz')))), 'color', colors(3,:)); hold off; set(gca, 'XScale', 'log'); set(gca, 'YScale', 'lin'); ylabel('Phase [deg]'); xlabel('Frequency [Hz]'); yticks(-360:90:360); ylim([-270, 90]); linkaxes([ax1,ax2],'x'); xlim([1, 500]); #+end_src #+begin_src matlab :tangle no :exports results :results file replace exportFig('figs/uniaxial_damped_plant_three_active_damping_techniques.pdf', 'width', 'wide', 'height', 'tall'); #+end_src #+name: fig:uniaxial_damped_plant_three_active_damping_techniques #+caption: Obtained damped transfer function from f to d for the three damping techniques #+RESULTS: [[file:figs/uniaxial_damped_plant_three_active_damping_techniques.png]] The damped plants are shown in Figure ref:fig:uniaxial_damped_plant_change_sample_mass for all three techniques, with the three considered nano-hexapod stiffnesses and sample's masses. #+begin_src matlab :exports none :results none %% Damped plant - Robustness to change of sample's mass figure; tiledlayout(3, 3, 'TileSpacing', 'Compact', 'Padding', 'None'); ax1 = nexttile([2,1]); hold on; plot(freqs, abs(squeeze(freqresp(G_vc_mid('d', 'f'), freqs, 'Hz'))), '-', 'color', [0, 0, 0, 0.5], 'HandleVisibility', 'off'); plot(freqs, abs(squeeze(freqresp(G_md_mid('d', 'f'), freqs, 'Hz'))), '-', 'color', [0, 0, 0, 0.5], 'HandleVisibility', 'off'); plot(freqs, abs(squeeze(freqresp(G_pz_mid('d', 'f'), freqs, 'Hz'))), '-', 'color', [0, 0, 0, 0.5], 'HandleVisibility', 'off'); plot(freqs, abs(squeeze(freqresp(G_iff_vc_light('d', 'f'), freqs, 'Hz'))), '-', 'color', colors(1,:), 'DisplayName', '$k_n = 0.01\,N/\mu m$'); plot(freqs, abs(squeeze(freqresp(G_iff_vc_mid( 'd', 'f'), freqs, 'Hz'))), '-.', 'color', colors(1,:), 'HandleVisibility', 'off'); plot(freqs, abs(squeeze(freqresp(G_iff_vc_heavy('d', 'f'), freqs, 'Hz'))), '--', 'color', colors(1,:), 'HandleVisibility', 'off'); plot(freqs, abs(squeeze(freqresp(G_iff_md_light('d', 'f'), freqs, 'Hz'))), '-', 'color', colors(2,:), 'DisplayName', '$k_n = 1\,N/\mu m$'); plot(freqs, abs(squeeze(freqresp(G_iff_md_mid( 'd', 'f'), freqs, 'Hz'))), '-.', 'color', colors(2,:), 'HandleVisibility', 'off'); plot(freqs, abs(squeeze(freqresp(G_iff_md_heavy('d', 'f'), freqs, 'Hz'))), '--', 'color', colors(2,:), 'HandleVisibility', 'off'); plot(freqs, abs(squeeze(freqresp(G_iff_pz_light('d', 'f'), freqs, 'Hz'))), '-', 'color', colors(3,:), 'DisplayName', '$k_n = 100\,N/\mu m$'); plot(freqs, abs(squeeze(freqresp(G_iff_pz_mid( 'd', 'f'), freqs, 'Hz'))), '-.', 'color', colors(3,:), 'HandleVisibility', 'off'); plot(freqs, abs(squeeze(freqresp(G_iff_pz_heavy('d', 'f'), freqs, 'Hz'))), '--', 'color', colors(3,:), 'HandleVisibility', 'off'); hold off; set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log'); ylabel('Amplitude [m/N]'); set(gca, 'XTickLabel',[]); title('IFF'); ylim([5e-10, 1e-3]); ldg = legend('location', 'northeast', 'FontSize', 8, 'NumColumns', 1); ldg.ItemTokenSize = [20, 1]; ax2 = nexttile([2,1]); hold on; plot(freqs, abs(squeeze(freqresp(G_vc_mid('d', 'f'), freqs, 'Hz'))), '-', 'color', [0, 0, 0, 0.5]); plot(freqs, abs(squeeze(freqresp(G_md_mid('d', 'f'), freqs, 'Hz'))), '-', 'color', [0, 0, 0, 0.5]); plot(freqs, abs(squeeze(freqresp(G_pz_mid('d', 'f'), freqs, 'Hz'))), '-', 'color', [0, 0, 0, 0.5]); plot(freqs, abs(squeeze(freqresp(G_rdc_vc_light('d', 'f'), freqs, 'Hz'))), '-', 'color', colors(1,:)); plot(freqs, abs(squeeze(freqresp(G_rdc_vc_mid( 'd', 'f'), freqs, 'Hz'))), '-.', 'color', colors(1,:)); plot(freqs, abs(squeeze(freqresp(G_rdc_vc_heavy('d', 'f'), freqs, 'Hz'))), '--', 'color', colors(1,:)); plot(freqs, abs(squeeze(freqresp(G_rdc_md_light('d', 'f'), freqs, 'Hz'))), '-', 'color', colors(2,:)); plot(freqs, abs(squeeze(freqresp(G_rdc_md_mid( 'd', 'f'), freqs, 'Hz'))), '-.', 'color', colors(2,:)); plot(freqs, abs(squeeze(freqresp(G_rdc_md_heavy('d', 'f'), freqs, 'Hz'))), '--', 'color', colors(2,:)); plot(freqs, abs(squeeze(freqresp(G_rdc_pz_light('d', 'f'), freqs, 'Hz'))), '-', 'color', colors(3,:)); plot(freqs, abs(squeeze(freqresp(G_rdc_pz_mid( 'd', 'f'), freqs, 'Hz'))), '-.', 'color', colors(3,:)); plot(freqs, abs(squeeze(freqresp(G_rdc_pz_heavy('d', 'f'), freqs, 'Hz'))), '--', 'color', colors(3,:)); hold off; set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log'); set(gca, 'XTickLabel',[]); set(gca, 'YTickLabel',[]); title('RDC'); ylim([5e-10, 1e-3]); ax3 = nexttile([2,1]); hold on; plot(freqs, abs(squeeze(freqresp(G_vc_mid('d', 'f'), freqs, 'Hz'))), '-', 'color', [0, 0, 0, 0.5], 'HandleVisibility', 'off'); plot(freqs, abs(squeeze(freqresp(G_md_mid('d', 'f'), freqs, 'Hz'))), '-', 'color', [0, 0, 0, 0.5], 'HandleVisibility', 'off'); plot(freqs, abs(squeeze(freqresp(G_pz_mid('d', 'f'), freqs, 'Hz'))), '-', 'color', [0, 0, 0, 0.5], 'HandleVisibility', 'off'); plot(freqs, abs(squeeze(freqresp(G_dvf_vc_light('d', 'f'), freqs, 'Hz'))), '-', 'color', colors(1,:), 'DisplayName', '$m_s = 1\,kg$'); plot(freqs, abs(squeeze(freqresp(G_dvf_vc_mid( 'd', 'f'), freqs, 'Hz'))), '-.', 'color', colors(1,:), 'DisplayName', '$m_s = 25\,kg$'); plot(freqs, abs(squeeze(freqresp(G_dvf_vc_heavy('d', 'f'), freqs, 'Hz'))), '--', 'color', colors(1,:), 'DisplayName', '$m_s = 50\,kg$'); plot(freqs, abs(squeeze(freqresp(G_dvf_md_light('d', 'f'), freqs, 'Hz'))), '-', 'color', colors(2,:), 'HandleVisibility', 'off'); plot(freqs, abs(squeeze(freqresp(G_dvf_md_mid( 'd', 'f'), freqs, 'Hz'))), '-.', 'color', colors(2,:), 'HandleVisibility', 'off'); plot(freqs, abs(squeeze(freqresp(G_dvf_md_heavy('d', 'f'), freqs, 'Hz'))), '--', 'color', colors(2,:), 'HandleVisibility', 'off'); plot(freqs, abs(squeeze(freqresp(G_dvf_pz_light('d', 'f'), freqs, 'Hz'))), '-', 'color', colors(3,:), 'HandleVisibility', 'off'); plot(freqs, abs(squeeze(freqresp(G_dvf_pz_mid( 'd', 'f'), freqs, 'Hz'))), '-.', 'color', colors(3,:), 'HandleVisibility', 'off'); plot(freqs, abs(squeeze(freqresp(G_dvf_pz_heavy('d', 'f'), freqs, 'Hz'))), '--', 'color', colors(3,:), 'HandleVisibility', 'off'); hold off; set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log'); set(gca, 'XTickLabel',[]); set(gca, 'YTickLabel',[]); title('DVF'); ylim([5e-10, 1e-3]); ldg = legend('location', 'northeast', 'FontSize', 8, 'NumColumns', 1); ldg.ItemTokenSize = [20, 1]; ax1b = nexttile(); hold on; plot(freqs, 180/pi*unwrap(angle(squeeze(freqresp(G_vc_mid('d', 'f'), freqs, 'Hz')))), '-', 'color', [0, 0, 0, 0.5]); plot(freqs, 180/pi*unwrap(angle(squeeze(freqresp(G_md_mid('d', 'f'), freqs, 'Hz')))), '-', 'color', [0, 0, 0, 0.5]); plot(freqs, 180/pi*unwrap(angle(squeeze(freqresp(G_pz_mid('d', 'f'), freqs, 'Hz')))), '-', 'color', [0, 0, 0, 0.5]); plot(freqs, 180/pi*unwrap(angle(squeeze(freqresp(G_iff_vc_light('d', 'f'), freqs, 'Hz')))), '-', 'color', colors(1,:)); plot(freqs, 180/pi*unwrap(angle(squeeze(freqresp(G_iff_vc_mid( 'd', 'f'), freqs, 'Hz')))), '-.', 'color', colors(1,:)); plot(freqs, 180/pi*unwrap(angle(squeeze(freqresp(G_iff_vc_heavy('d', 'f'), freqs, 'Hz')))), '--', 'color', colors(1,:)); plot(freqs, 180/pi*unwrap(angle(squeeze(freqresp(G_iff_md_light('d', 'f'), freqs, 'Hz')))), '-', 'color', colors(2,:)); plot(freqs, 180/pi*unwrap(angle(squeeze(freqresp(G_iff_md_mid( 'd', 'f'), freqs, 'Hz')))), '-.', 'color', colors(2,:)); plot(freqs, 180/pi*unwrap(angle(squeeze(freqresp(G_iff_md_heavy('d', 'f'), freqs, 'Hz')))), '--', 'color', colors(2,:)); plot(freqs, 180/pi*unwrap(angle(squeeze(freqresp(G_iff_pz_light('d', 'f'), freqs, 'Hz')))), '-', 'color', colors(3,:)); plot(freqs, 180/pi*unwrap(angle(squeeze(freqresp(G_iff_pz_mid( 'd', 'f'), freqs, 'Hz')))), '-.', 'color', colors(3,:)); plot(freqs, 180/pi*unwrap(angle(squeeze(freqresp(G_iff_pz_heavy('d', 'f'), freqs, 'Hz')))), '--', 'color', colors(3,:)); hold off; set(gca, 'XScale', 'log'); set(gca, 'YScale', 'lin'); ylabel('Phase [deg]'); xlabel('Frequency [Hz]'); xticks([1e0, 1e1, 1e2]); yticks(-360:90:360); ylim([-200, 20]); ax2b = nexttile(); hold on; plot(freqs, 180/pi*unwrap(angle(squeeze(freqresp(G_vc_mid('d', 'f'), freqs, 'Hz')))), '-', 'color', [0, 0, 0, 0.5]); plot(freqs, 180/pi*unwrap(angle(squeeze(freqresp(G_md_mid('d', 'f'), freqs, 'Hz')))), '-', 'color', [0, 0, 0, 0.5]); plot(freqs, 180/pi*unwrap(angle(squeeze(freqresp(G_pz_mid('d', 'f'), freqs, 'Hz')))), '-', 'color', [0, 0, 0, 0.5]); plot(freqs, 180/pi*unwrap(angle(squeeze(freqresp(G_rdc_vc_light('d', 'f'), freqs, 'Hz')))), '-', 'color', colors(1,:)); plot(freqs, 180/pi*unwrap(angle(squeeze(freqresp(G_rdc_vc_mid( 'd', 'f'), freqs, 'Hz')))), '-.', 'color', colors(1,:)); plot(freqs, 180/pi*unwrap(angle(squeeze(freqresp(G_rdc_vc_heavy('d', 'f'), freqs, 'Hz')))), '--', 'color', colors(1,:)); plot(freqs, 180/pi*unwrap(angle(squeeze(freqresp(G_rdc_md_light('d', 'f'), freqs, 'Hz')))), '-', 'color', colors(2,:)); plot(freqs, 180/pi*unwrap(angle(squeeze(freqresp(G_rdc_md_mid( 'd', 'f'), freqs, 'Hz')))), '-.', 'color', colors(2,:)); plot(freqs, 180/pi*unwrap(angle(squeeze(freqresp(G_rdc_md_heavy('d', 'f'), freqs, 'Hz')))), '--', 'color', colors(2,:)); plot(freqs, 180/pi*unwrap(angle(squeeze(freqresp(G_rdc_pz_light('d', 'f'), freqs, 'Hz')))), '-', 'color', colors(3,:)); plot(freqs, 180/pi*unwrap(angle(squeeze(freqresp(G_rdc_pz_mid( 'd', 'f'), freqs, 'Hz')))), '-.', 'color', colors(3,:)); plot(freqs, 180/pi*unwrap(angle(squeeze(freqresp(G_rdc_pz_heavy('d', 'f'), freqs, 'Hz')))), '--', 'color', colors(3,:)); hold off; set(gca, 'XScale', 'log'); set(gca, 'YScale', 'lin'); xlabel('Frequency [Hz]'); set(gca, 'YTickLabel',[]); xticks([1e0, 1e1, 1e2]); yticks(-360:90:360); ylim([-200, 20]); ax3b = nexttile(); hold on; plot(freqs, 180/pi*unwrap(angle(squeeze(freqresp(G_vc_mid('d', 'f'), freqs, 'Hz')))), '-', 'color', [0, 0, 0, 0.5]); plot(freqs, 180/pi*unwrap(angle(squeeze(freqresp(G_md_mid('d', 'f'), freqs, 'Hz')))), '-', 'color', [0, 0, 0, 0.5]); plot(freqs, 180/pi*unwrap(angle(squeeze(freqresp(G_pz_mid('d', 'f'), freqs, 'Hz')))), '-', 'color', [0, 0, 0, 0.5]); plot(freqs, 180/pi*unwrap(angle(squeeze(freqresp(G_dvf_vc_light('d', 'f'), freqs, 'Hz')))), '-', 'color', colors(1,:)); plot(freqs, 180/pi*unwrap(angle(squeeze(freqresp(G_dvf_vc_mid( 'd', 'f'), freqs, 'Hz')))), '-.', 'color', colors(1,:)); plot(freqs, 180/pi*unwrap(angle(squeeze(freqresp(G_dvf_vc_heavy('d', 'f'), freqs, 'Hz')))), '--', 'color', colors(1,:)); plot(freqs, 180/pi*unwrap(angle(squeeze(freqresp(G_dvf_md_light('d', 'f'), freqs, 'Hz')))), '-', 'color', colors(2,:)); plot(freqs, 180/pi*unwrap(angle(squeeze(freqresp(G_dvf_md_mid( 'd', 'f'), freqs, 'Hz')))), '-.', 'color', colors(2,:)); plot(freqs, 180/pi*unwrap(angle(squeeze(freqresp(G_dvf_md_heavy('d', 'f'), freqs, 'Hz')))), '--', 'color', colors(2,:)); plot(freqs, 180/pi*unwrap(angle(squeeze(freqresp(G_dvf_pz_light('d', 'f'), freqs, 'Hz')))), '-', 'color', colors(3,:)); plot(freqs, 180/pi*unwrap(angle(squeeze(freqresp(G_dvf_pz_mid( 'd', 'f'), freqs, 'Hz')))), '-.', 'color', colors(3,:)); plot(freqs, 180/pi*unwrap(angle(squeeze(freqresp(G_dvf_pz_heavy('d', 'f'), freqs, 'Hz')))), '--', 'color', colors(3,:)); hold off; set(gca, 'XScale', 'log'); set(gca, 'YScale', 'lin'); xlabel('Frequency [Hz]'); set(gca, 'YTickLabel',[]); xticks([1e0, 1e1, 1e2]); yticks(-360:90:360); ylim([-200, 20]); linkaxes([ax1,ax2,ax3,ax1b,ax2b,ax3b],'x'); xlim([1, 1e3]); #+end_src #+begin_src matlab :tangle no :exports results :results file replace exportFig('figs/uniaxial_damped_plant_change_sample_mass.pdf', 'width', 'full', 'height', 'tall'); #+end_src #+name: fig:uniaxial_damped_plant_change_sample_mass #+caption: Damped plant $d/f$ - Robustness to change of sample's mass for all three active damping techniques. Grey curves are the open-loop (i.e. undamped) plants. #+RESULTS: [[file:figs/uniaxial_damped_plant_change_sample_mass.png]] ** Robustness to change of payload's mass The Root Locus for the three damping techniques are shown in Figure ref:fig:uniaxial_active_damping_robustness_mass_root_locus for three sample's mass (1kg, 25kg and 50kg). The closed-loop poles are shown by the squares for a specific gain. We can see that having heavier samples yields larger damping for IFF and smaller damping for RDC and DVF. #+begin_src matlab :exports none %% Active Damping Robustness to change of sample's mass - Root Locus for all three damping techniques with 3 different sample's masses figure; tiledlayout(1, 3, 'TileSpacing', 'Compact', 'Padding', 'None'); %% Integral Force Feedback ax1 = nexttile(); hold on; % Light Sample plot(real(pole(G_md_light('fm', 'f'))), imag(pole(G_md_light('fm', 'f'))), 'x', 'color', colors(1,:), ... 'HandleVisibility', 'off'); plot(real(zero(G_md_light('fm', 'f'))), imag(zero(G_md_light('fm', 'f'))), 'o', 'color', colors(1,:), ... 'HandleVisibility', 'off'); for g = logspace(1,4,100) clpoles = pole(feedback(G_md_light('fm', 'f'), g/s, +1)); plot(real(clpoles), imag(clpoles), '.', 'color', colors(1,:), ... 'HandleVisibility', 'off'); end clpoles = pole(feedback(G_md_light('fm', 'f'), K_iff_md, +1)); plot(real(clpoles), imag(clpoles), 'square', 'color', colors(1,:), ... 'DisplayName', '$m_s = 1\,kg$'); % Mid Sample plot(real(pole(G_md_mid('fm', 'f'))), imag(pole(G_md_mid('fm', 'f'))), 'x', 'color', colors(2,:), ... 'HandleVisibility', 'off'); plot(real(zero(G_md_mid('fm', 'f'))), imag(zero(G_md_mid('fm', 'f'))), 'o', 'color', colors(2,:), ... 'HandleVisibility', 'off'); for g = logspace(1,4,100) clpoles = pole(feedback(G_md_mid('fm', 'f'), g/s, +1)); plot(real(clpoles), imag(clpoles), '.', 'color', colors(2,:), ... 'HandleVisibility', 'off'); end clpoles = pole(feedback(G_md_mid('fm', 'f'), K_iff_md, +1)); plot(real(clpoles), imag(clpoles), 'square', 'color', colors(2,:), ... 'DisplayName', '$m_s = 25\,kg$'); % Heavy Sample plot(real(pole(G_md_heavy('fm', 'f'))), imag(pole(G_md_heavy('fm', 'f'))), 'x', 'color', colors(3,:), ... 'HandleVisibility', 'off'); plot(real(zero(G_md_heavy('fm', 'f'))), imag(zero(G_md_heavy('fm', 'f'))), 'o', 'color', colors(3,:), ... 'HandleVisibility', 'off'); for g = logspace(1,4,100) clpoles = pole(feedback(G_md_heavy('fm', 'f'), g/s, +1)); plot(real(clpoles), imag(clpoles), '.', 'color', colors(3,:), ... 'HandleVisibility', 'off'); end clpoles = pole(feedback(G_md_heavy('fm', 'f'), K_iff_md, +1)); plot(real(clpoles), imag(clpoles), 'square', 'color', colors(3,:), ... 'DisplayName', '$m_s = 50\,kg$'); hold off; axis square; xlabel('Real Part'); ylabel('Imaginary Part'); title('IFF') ldg = legend('location', 'northwest', 'FontSize', 8, 'NumColumns', 1); ldg.ItemTokenSize = [10, 1]; %% Relative Damping Control ax2 = nexttile(); hold on; % Light Sample plot(real(pole(G_md_light('dL', 'f'))), imag(pole(G_md_light('dL', 'f'))), 'x', 'color', colors(1,:), ... 'DisplayName', '$m_s = 1\,kg$'); plot(real(zero(G_md_light('dL', 'f'))), imag(zero(G_md_light('dL', 'f'))), 'o', 'color', colors(1,:), ... 'HandleVisibility', 'off'); for g = logspace(2,5,100) clpoles = pole(feedback(G_md_light('dL', 'f'), -g*s, +1)); plot(real(clpoles), imag(clpoles), '.', 'color', colors(1,:), ... 'HandleVisibility', 'off'); end clpoles = pole(feedback(G_md_light('dL', 'f'), K_rdc_md, +1)); plot(real(clpoles), imag(clpoles), 'square', 'color', colors(1,:), ... 'HandleVisibility', 'off'); % Mid Sample plot(real(pole(G_md_mid('dL', 'f'))), imag(pole(G_md_mid('dL', 'f'))), 'x', 'color', colors(2,:), ... 'DisplayName', '$m_s = 25\,kg$'); plot(real(zero(G_md_mid('dL', 'f'))), imag(zero(G_md_mid('dL', 'f'))), 'o', 'color', colors(2,:), ... 'HandleVisibility', 'off'); for g = logspace(2,5,100) clpoles = pole(feedback(G_md_mid('dL', 'f'), -g*s, +1)); plot(real(clpoles), imag(clpoles), '.', 'color', colors(2,:), ... 'HandleVisibility', 'off'); end clpoles = pole(feedback(G_md_mid('dL', 'f'), K_rdc_md, +1)); plot(real(clpoles), imag(clpoles), 'square', 'color', colors(2,:), ... 'HandleVisibility', 'off'); % Heavy Sample plot(real(pole(G_md_heavy('dL', 'f'))), imag(pole(G_md_heavy('dL', 'f'))), 'x', 'color', colors(3,:), ... 'DisplayName', '$m_s = 50\,kg$'); plot(real(zero(G_md_heavy('dL', 'f'))), imag(zero(G_md_heavy('dL', 'f'))), 'o', 'color', colors(3,:), ... 'HandleVisibility', 'off'); for g = logspace(2,5,100) clpoles = pole(feedback(G_md_heavy('dL', 'f'), -g*s, +1)); plot(real(clpoles), imag(clpoles), '.', 'color', colors(3,:), ... 'HandleVisibility', 'off'); end clpoles = pole(feedback(G_md_heavy('dL', 'f'), K_rdc_md, +1)); plot(real(clpoles), imag(clpoles), 'square', 'color', colors(3,:), ... 'HandleVisibility', 'off'); hold off; axis square; xlabel('Real Part'); ylabel('Imaginary Part'); title('RDC'); %% Direct Velocity Feedback ax3 = nexttile(); hold on; % Light Sample plot(real(pole(G_md_light('vn', 'f'))), imag(pole(G_md_light('vn', 'f'))), 'x', 'color', colors(1,:), ... 'DisplayName', '$m_s = 1\,kg$'); plot(real(zero(G_md_light('vn', 'f'))), imag(zero(G_md_light('vn', 'f'))), 'o', 'color', colors(1,:), ... 'HandleVisibility', 'off'); for g = logspace(2,5,100) clpoles = pole(feedback(G_md_light('vn', 'f'), -g, +1)); plot(real(clpoles), imag(clpoles), '.', 'color', colors(1,:), ... 'HandleVisibility', 'off'); end clpoles = pole(feedback(G_md_light('vn', 'f'), K_dvf_md, +1)); plot(real(clpoles), imag(clpoles), 'square', 'color', colors(1,:), ... 'HandleVisibility', 'off'); % Mid Sample plot(real(pole(G_md_mid('vn', 'f'))), imag(pole(G_md_mid('vn', 'f'))), 'x', 'color', colors(2,:), ... 'DisplayName', '$m_s = 25\,kg$'); plot(real(zero(G_md_mid('vn', 'f'))), imag(zero(G_md_mid('vn', 'f'))), 'o', 'color', colors(2,:), ... 'HandleVisibility', 'off'); for g = logspace(2,5,100) clpoles = pole(feedback(G_md_mid('vn', 'f'), -g, +1)); plot(real(clpoles), imag(clpoles), '.', 'color', colors(2,:), ... 'HandleVisibility', 'off'); end clpoles = pole(feedback(G_md_mid('vn', 'f'), K_dvf_md, +1)); plot(real(clpoles), imag(clpoles), 'square', 'color', colors(2,:), ... 'HandleVisibility', 'off'); % Heavy Sample plot(real(pole(G_md_heavy('vn', 'f'))), imag(pole(G_md_heavy('vn', 'f'))), 'x', 'color', colors(3,:), ... 'DisplayName', '$m_s = 50\,kg$'); plot(real(zero(G_md_heavy('vn', 'f'))), imag(zero(G_md_heavy('vn', 'f'))), 'o', 'color', colors(3,:), ... 'HandleVisibility', 'off'); for g = logspace(2,5,100) clpoles = pole(feedback(G_md_heavy('vn', 'f'), -g, +1)); plot(real(clpoles), imag(clpoles), '.', 'color', colors(3,:), ... 'HandleVisibility', 'off'); end clpoles = pole(feedback(G_md_heavy('vn', 'f'), K_dvf_md, +1)); plot(real(clpoles), imag(clpoles), 'square', 'color', colors(3,:), ... 'HandleVisibility', 'off'); hold off; axis square; xlabel('Real Part'); ylabel('Imaginary Part'); title('DVF'); linkaxes([ax1,ax2,ax3],'xy'); xlim([-300, 0]); ylim([0, 300]); #+end_src #+begin_src matlab :tangle no :exports results :results file replace exportFig('figs/uniaxial_active_damping_robustness_mass_root_locus.pdf', 'width', 'full', 'height', 'normal'); #+end_src #+name: fig:uniaxial_active_damping_robustness_mass_root_locus #+caption: Active Damping Robustness to change of sample's mass - Root Locus for all three damping techniques with 3 different sample's masses #+RESULTS: [[file:figs/uniaxial_active_damping_robustness_mass_root_locus.png]] ** Conclusion #+begin_important Conclusions for Active Damping: - All three active damping techniques yields good damping (Figure ref:fig:uniaxial_root_locus_damping_techniques) and similar remaining vibrations (Figure ref:fig:uniaxial_cas_active_damping) - The obtained damped plants (Figure ref:fig:uniaxial_damped_plant_change_sample_mass) are equivalent for the three active damping techniques - Which one to be used will be determined with the use of more accurate models and will depend on which is the easiest to implement in practice #+end_important #+name: tab:comp_active_damping #+caption: Comparison of active damping strategies #+attr_latex: :environment tabularx :width \linewidth :align Xccc #+attr_latex: :center t :booktabs t :font \scriptsize | | *IFF* | *RDC* | *DVF* | |---------------------+-----------------------------+---------------------------+---------------------------------| | *Sensor* | Force sensor | Relative motion sensor | Inertial sensor | |---------------------+-----------------------------+---------------------------+---------------------------------| | *Damping* | Up to critical | Up to critical | Up to Critical | |---------------------+-----------------------------+---------------------------+---------------------------------| | *Robustness* | Requires collocation | Requires collocation | Impacted by geophone resonances | |---------------------+-----------------------------+---------------------------+---------------------------------| | $f_s$ *Disturbance* | $\nearrow$ at low frequency | $\searrow$ near resonance | $\searrow$ near resonance | | $f_t$ *Disturbance* | $\searrow$ near resonance | $\nearrow$ near resonance | $\searrow$ near resonance | | $x_f$ *Disturbance* | $\nearrow$ at low frequency | $\searrow$ near resonance | $\nearrow$ at low frequency | * Position Feedback Controller :PROPERTIES: :HEADER-ARGS:matlab+: :tangle matlab/uniaxial_6_hac_lac.m :END: <> ** Introduction :ignore: The High Authority Control - Low Authority Control (HAC-LAC) architecture is shown in Figure ref:fig:uniaxial_hac_lac_architecture. It corresponds to a /two step/ control strategy: - First, an active damping controller $\bm{K}_{\textsc{LAC}}$ is implemented (see Section ref:sec:uniaxial_active_damping). It allows to reduce the vibration level, and it also makes the damped plant (transfer function from $u^{\prime}$ to $y$) easier to control than the undamped plant (transfer function from $u$ to $y$). - Then, a position controller $\bm{K}_{\textsc{HAC}}$ is implemented. #+begin_src latex :file uniaxial_hac_lac_architecture.pdf :results none \begin{tikzpicture} % Blocs \node[block={3.0cm}{3.0cm}] (P) {Plant}; \coordinate[] (input) at ($(P.south west)!0.5!(P.north west)$); \coordinate[] (outputH) at ($(P.south east)!0.2!(P.north east)$); \coordinate[] (outputL) at ($(P.south east)!0.8!(P.north east)$); \node[block, above=0.4 of P] (Klac) {$\bm{K}_{\textsc{LAC}}$}; \node[addb, left=0.6 of input] (addF) {}; \node[block, left=1.0 of addF] (Khac) {$\bm{K}_{\textsc{HAC}}$}; \node[addb={+}{}{}{}{-}, left=0.6 of Khac] (subr) {}; % Connections and labels \draw[->] (outputL) -- ++(0.6, 0) coordinate(eastlac) |- (Klac.east); \node[above right] at (outputL){$y^{\prime}$}; \draw[->] (Klac.west) -| (addF.north); \draw[->] (addF.east) -- (input) node[above left]{$u$}; \draw[<-] (subr.west) --node[midway, above]{$r$} ++(-0.8, 0); \draw[->] (outputH) -- ++(1.6, 0); \draw[->] ($(outputH) + (1.2, 0)$)node[branch]{} node[above]{$y$} -- ++(0, -1.2) -| (subr.south); \draw[->] (subr.east) -- (Khac.west) node[above left]{$\epsilon$}; \draw[->] (Khac.east) -- (addF.west) node[above left=0 and 0.2]{$u^{\prime}$}; \begin{scope}[on background layer] \node[fit={(Klac.north-|eastlac) (addF.west|-P.south)}, fill=black!20!white, draw, dashed, inner sep=6pt] (Pi) {}; \node[anchor={north west}] at (Pi.north west){\small Damped Plant}; \end{scope} \end{tikzpicture} #+end_src Combined with the uniaxial model, it is shown in Figure ref:fig:uniaxial_hac_lac_model. #+begin_src latex :file uniaxial_hac_lac_model.pdf :results silent \begin{tikzpicture} % ==================== % Parameters % ==================== \def\massw{2.2} % Width of the masses \def\massh{0.8} % Height of the masses \def\spaceh{1.2} % Height of the springs/dampers \def\dispw{0.4} % Width of the dashed line for the displacement \def\disph{0.3} % Height of the arrow for the displacements \def\bracs{0.05} % Brace spacing vertically \def\brach{-12pt} % Brace shift horizontaly \def\fsensh{0.2} % Height of the force sensor \def\velsize{0.2} % Size of the velocity sensor % ==================== % IFF % ==================== % Ground % ==================== \draw (-0.5*\massw, 0) -- (0.5*\massw, 0); \draw[dashed] (0.5*\massw, 0) -- ++(\dispw, 0); \draw[->, color=colorpurple] (0.5*\massw+0.5*\dispw, 0) -- ++(0, 2*\disph) node[right, color=colorpurple]{$x_{f}$}; % ==================== % ==================== % Granite \begin{scope}[shift={(0, 0)}] % Mass \draw[fill=white] (-0.5*\massw, \spaceh) rectangle (0.5*\massw, \spaceh+\massh) node[pos=0.5]{$m_{g}$}; % Spring, Damper, and Actuator \draw[spring] (-0.4*\massw, 0) -- (-0.4*\massw, \spaceh) node[midway, left=0.1]{$k_{g}$}; \draw[damper] (0, 0) -- ( 0, \spaceh) node[midway, left=0.2]{$c_{g}$}; % Legend \draw[decorate, decoration={brace, amplitude=8pt}, xshift=\brach] % (-0.5*\massw, \bracs) -- (-0.5*\massw, \spaceh+\massh-\bracs) node[midway,rotate=90,anchor=south,yshift=10pt]{Granite}; % Displacements \draw[dashed] (0.5*\massw, \spaceh+\massh) -- ++(7.5*\dispw, 0) coordinate(xg); \end{scope} % ==================== % ==================== % Stages \begin{scope}[shift={(0, \spaceh+\massh)}] % Mass \draw[fill=white] (-0.5*\massw, \spaceh) rectangle (0.5*\massw, \spaceh+\massh) node[pos=0.5]{$m_{t}$}; % Spring, Damper, and Actuator \draw[spring] (-0.4*\massw, 0) -- (-0.4*\massw, \spaceh) node[midway, left=0.1]{$k_{t}$}; \draw[damper] (0, 0) -- ( 0, \spaceh) node[midway, left=0.2]{$c_{t}$}; \draw[actuator={0.45}{0.2}{colorpurple}] ( 0.3*\massw, 0) -- (0.3*\massw, \spaceh) node[midway, right=0.1, color=colorpurple](ft){$f_{t}$}; % Legend \draw[decorate, decoration={brace, amplitude=8pt}, xshift=\brach] % (-0.5*\massw, \bracs) -- (-0.5*\massw, \spaceh+\massh-\bracs) node[midway,rotate=90,anchor=south,yshift=10pt]{$T_y$/$R_y$/$R_z$}; \end{scope} % ==================== % ==================== % Hexapod \begin{scope}[shift={(0, 2*(\spaceh+\massh))}] % Mass \draw[fill=white] (-0.5*\massw, \spaceh) rectangle (0.5*\massw, \spaceh+\massh) node[pos=0.5]{$m_h$}; % Spring, Damper, and Actuator \draw[spring] (-0.4*\massw, 0) -- (-0.4*\massw, \spaceh) node[midway, left=0.1]{$k_h$}; \draw[damper] (0, 0) -- ( 0, \spaceh) node[midway, left=0.2]{$c_h$}; % Legend \draw[decorate, decoration={brace, amplitude=8pt}, xshift=\brach] % (-0.5*\massw, \bracs) -- (-0.5*\massw, \spaceh+\massh-\bracs) node[midway,rotate=90,anchor=south,yshift=10pt]{$\mu\text{-hexa}$}; \end{scope} % ==================== % ==================== % NASS \begin{scope}[shift={(0, 3*(\spaceh+\massh))}] % Mass \draw[fill=white] (-0.5*\massw, \spaceh) rectangle (0.5*\massw, \spaceh+\massh) node[pos=0.5]{$m_{n}$}; % Force Sensor \node[forcesensor={\massw}{\fsensh}{colorblue}] (fsensn) at (0, \spaceh-\fsensh){}; \node[right, color=colorblue] (fn) at (fsensn.east) {$f_n$}; % Spring, Damper, and Actuator \draw[spring] (-0.4*\massw, 0) -- (-0.4*\massw, \spaceh-\fsensh) node[midway, left=0.1]{$k_{n}$}; \draw[damper] (0, 0) -- ( 0, \spaceh-\fsensh) node[midway, left=0.2]{$c_{n}$}; \draw[actuator={0.4}{0.2}{black}] ( 0.3*\massw, 0) -- ( 0.3*\massw, \spaceh-\fsensh) node[midway, right=0.1](f){$f$}; % Legend \draw[decorate, decoration={brace, amplitude=8pt}, xshift=\brach] % (-0.5*\massw, \bracs) -- (-0.5*\massw, \spaceh+\massh-\bracs) node[midway,rotate=90,anchor=south,yshift=10pt]{$\nu\text{-hexa}$}; % Displacements \draw[dashed] (0.5*\massw, \spaceh+\massh) -- ++(7.5*\dispw, 0) coordinate(xnpos); \end{scope} % ==================== % ==================== % sample \begin{scope}[shift={(0, 4*(\spaceh+\massh))}] % Mass \draw[fill=white] (-0.3*\massw, 0) rectangle (0.3*\massw, \massh) node[pos=0.5]{$m_{s}$}; % External Force \draw[->, color=colorpurple] (0, \massh) node[]{$\bullet$} -- ++(0, 0.5*\massh) node[right, color=colorpurple]{$f_s$}; \end{scope} % ==================== % Measured displacement \draw[<->, dashed, draw=colorred] ($(xg)+(-0.1, 0)$) -- node[left, color=colorred](d){$d$} ($(xnpos)+(-0.1, 0)$); % ==================== % IFF Control \node[block={2em}{2em}, right=1.0 of fn, color=colorblue, fill=colorblue!10!white] (iff) {$K_{\textsc{IFF}}$}; \node[addb, right=0.5 of f.east] (ctrladd) {}; \node[block={2em}{2em}, color=colorred, fill=colorred!10!white] (Khac) at (ctrladd|-d) {$K_{\textsc{HAC}}$}; \draw[->, draw=colorblue] (fn.east) -- (iff.west); \draw[->, draw=colorblue] (iff.south) |- (ctrladd.east); \draw[->] (ctrladd.west) -- (f.east); \draw[->, draw=colorred] (d.west) -- (Khac.east); \draw[->, draw=colorred] (Khac.north) -- (ctrladd.south) node[below right, color=colorred]{$f^{\prime}$}; % ==================== \end{tikzpicture} #+end_src #+name: fig:uniaxial_hac_lac #+caption: High Authority Control - Low Authority Control (HAC-LAC) #+begin_figure #+attr_latex: :caption \subcaption{\label{fig:uniaxial_hac_lac_architecture}Typical HAC-LAC Architecture} #+attr_latex: :options {0.54\textwidth} #+begin_subfigure #+attr_latex: :width 1.0\linewidth [[file:figs/uniaxial_hac_lac_architecture.png]] #+end_subfigure #+attr_latex: :options {0.45\textwidth} #+attr_latex: :caption \subcaption{\label{fig:uniaxial_hac_lac_model}Uniaxial model with HAC-LAC strategy} #+begin_subfigure #+attr_latex: :scale 1 [[file:figs/uniaxial_hac_lac_model.png]] #+end_subfigure #+end_figure ** 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 :noweb yes <> #+end_src #+begin_src matlab :eval no :noweb yes <> #+end_src #+begin_src matlab :noweb yes <> #+end_src #+begin_src matlab %% Frequency Vector [Hz] freqs = logspace(0, 3, 1000); #+end_src #+begin_src matlab %% Load the PSD of disturbances load('uniaxial_disturbance_psd.mat', 'f', 'psd_ft', 'psd_xf'); #+end_src #+begin_src matlab %% Load Plants Dynamics load('uniaxial_plants.mat', 'G_vc_light', 'G_md_light', 'G_pz_light', ... 'G_vc_mid', 'G_md_mid', 'G_pz_mid', ... 'G_vc_heavy', 'G_md_heavy', 'G_pz_heavy'); #+end_src #+begin_src matlab %% Load Damped Plants load('uniaxial_damped_plants.mat', 'G_iff_vc_light', 'G_iff_md_light', 'G_iff_pz_light', ... 'G_rdc_vc_light', 'G_rdc_md_light', 'G_rdc_pz_light', ... 'G_dvf_vc_light', 'G_dvf_md_light', 'G_dvf_pz_light', ... 'G_iff_vc_mid', 'G_iff_md_mid', 'G_iff_pz_mid', ... 'G_rdc_vc_mid', 'G_rdc_md_mid', 'G_rdc_pz_mid', ... 'G_dvf_vc_mid', 'G_dvf_md_mid', 'G_dvf_pz_mid', ... 'G_iff_vc_heavy', 'G_iff_md_heavy', 'G_iff_pz_heavy', ... 'G_rdc_vc_heavy', 'G_rdc_md_heavy', 'G_rdc_pz_heavy', ... 'G_dvf_vc_heavy', 'G_dvf_md_heavy', 'G_dvf_pz_heavy'); #+end_src ** Damped Plant Dynamics As was shown in Section ref:sec:uniaxial_active_damping, all three proposed active damping techniques yield similar damping plants. Therefore, /Integral Force Feedback/ will be used in this section to study the HAC-LAC performances. The obtained damped plants for the three nano-hexapod stiffnesses are shown in Figure ref:fig:uniaxial_hac_iff_damped_plants_masses. #+begin_src matlab :exports none :results none %% Damped plant - Robustness to change of sample's mass figure; tiledlayout(3, 3, 'TileSpacing', 'Compact', 'Padding', 'None'); ax1 = nexttile([2,1]); hold on; plot(freqs, abs(squeeze(freqresp(G_iff_vc_light('d', 'f'), freqs, 'Hz'))), '-', 'DisplayName', '$m_s = 1\,kg$'); plot(freqs, abs(squeeze(freqresp(G_iff_vc_mid( 'd', 'f'), freqs, 'Hz'))), '-', 'DisplayName', '$m_s = 25\,kg$'); plot(freqs, abs(squeeze(freqresp(G_iff_vc_heavy('d', 'f'), freqs, 'Hz'))), '-', 'DisplayName', '$m_s = 50\,kg$'); hold off; set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log'); ylabel('Amplitude [m/N]'); set(gca, 'XTickLabel',[]); title('$k_n = 0.01\,N/\mu m$'); ylim([5e-10, 1e-3]); ldg = legend('location', 'northeast', 'FontSize', 8, 'NumColumns', 1); ldg.ItemTokenSize = [20, 1]; ax2 = nexttile([2,1]); hold on; plot(freqs, abs(squeeze(freqresp(G_iff_md_light('d', 'f'), freqs, 'Hz')))); plot(freqs, abs(squeeze(freqresp(G_iff_md_mid( 'd', 'f'), freqs, 'Hz')))); plot(freqs, abs(squeeze(freqresp(G_iff_md_heavy('d', 'f'), freqs, 'Hz')))); hold off; set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log'); set(gca, 'XTickLabel',[]); set(gca, 'YTickLabel',[]); title('$k_n = 1\,N/\mu m$'); ylim([5e-10, 1e-3]); ax3 = nexttile([2,1]); hold on; plot(freqs, abs(squeeze(freqresp(G_iff_pz_light('d', 'f'), freqs, 'Hz')))); plot(freqs, abs(squeeze(freqresp(G_iff_pz_mid( 'd', 'f'), freqs, 'Hz')))); plot(freqs, abs(squeeze(freqresp(G_iff_pz_heavy('d', 'f'), freqs, 'Hz')))); hold off; set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log'); set(gca, 'XTickLabel',[]); set(gca, 'YTickLabel',[]); title('$k_n = 100\,N/\mu m$'); ylim([5e-10, 1e-3]); ax1b = nexttile(); hold on; plot(freqs, unwrap(180/pi*angle(squeeze(freqresp(G_iff_vc_light('d', 'f'), freqs, 'Hz'))))); plot(freqs, unwrap(180/pi*angle(squeeze(freqresp(G_iff_vc_mid( 'd', 'f'), freqs, 'Hz'))))); plot(freqs, unwrap(180/pi*angle(squeeze(freqresp(G_iff_vc_heavy('d', 'f'), freqs, 'Hz'))))); hold off; set(gca, 'XScale', 'log'); set(gca, 'YScale', 'lin'); ylabel('Phase [deg]'); xlabel('Frequency [Hz]'); xticks([1e0, 1e1, 1e2]); yticks(-360:90:360); ylim([-200, 20]); ax2b = nexttile(); hold on; plot(freqs, unwrap(180/pi*angle(squeeze(freqresp(G_iff_md_light('d', 'f'), freqs, 'Hz'))))); plot(freqs, unwrap(180/pi*angle(squeeze(freqresp(G_iff_md_mid( 'd', 'f'), freqs, 'Hz'))))); plot(freqs, unwrap(180/pi*angle(squeeze(freqresp(G_iff_md_heavy('d', 'f'), freqs, 'Hz'))))); hold off; set(gca, 'XScale', 'log'); set(gca, 'YScale', 'lin'); xlabel('Frequency [Hz]'); set(gca, 'YTickLabel',[]); xticks([1e0, 1e1, 1e2]); yticks(-360:90:360); ylim([-200, 20]); ax3b = nexttile(); hold on; plot(freqs, unwrap(180/pi*angle(squeeze(freqresp(G_iff_pz_light('d', 'f'), freqs, 'Hz'))))); plot(freqs, unwrap(180/pi*angle(squeeze(freqresp(G_iff_pz_mid( 'd', 'f'), freqs, 'Hz'))))); plot(freqs, unwrap(180/pi*angle(squeeze(freqresp(G_iff_pz_heavy('d', 'f'), freqs, 'Hz'))))); hold off; set(gca, 'XScale', 'log'); set(gca, 'YScale', 'lin'); xlabel('Frequency [Hz]'); set(gca, 'YTickLabel',[]); xticks([1e0, 1e1, 1e2]); yticks(-360:90:360); ylim([-200, 20]); linkaxes([ax1,ax2,ax3,ax1b,ax2b,ax3b],'x'); xlim([1, 1e3]); #+end_src #+begin_src matlab :tangle no :exports results :results file replace exportFig('figs/uniaxial_hac_iff_damped_plants_masses.pdf', 'width', 'full', 'height', 'tall'); #+end_src #+name: fig:uniaxial_hac_iff_damped_plants_masses #+caption: Obtained damped plant using Integral Force Feedback for three sample's masses #+RESULTS: [[file:figs/uniaxial_hac_iff_damped_plants_masses.png]] ** Position Feedback Controller The objective now is to design a position feedback controller for each of the three nano-hexapods that are robust to the change of sample's mass. The required feedback bandwidth was approximately determined un Section ref:sec:uniaxial_noise_budgeting: - $\approx 10\,\text{Hz}$ for the soft nano-hexapod ($k_n = 0.01\,N/\mu m$). Near this frequency, the plants are equivalent to a mass line. The gain of the mass line can vary up to a fact $\approx 5$ (suspended mass from $16\,kg$ up to $65\,kg$). This mean that the designed controller will need to have large gain margins to be robust to the change of sample's mass. - $\approx 50\,\text{Hz}$ for the relatively stiff nano-hexapod ($k_n = 1\,N/\mu m$). Similarly to the soft nano-hexapod, the plants near the crossover frequency are equivalent to a mass line. It will be probably easier to have a little bit more bandwidth in this configuration to be further away from the nano-hexapod suspension mode. - $\approx 100\,\text{Hz}$ for the stiff nano-hexapod ($k_n = 100\,N/\mu m$). Contrary to the two first nano-hexapod stiffnesses, here the plants have more complex dynamics near the wanted crossover frequency. The micro-station is not stiff enough to have a clear stiffness line at this frequency. Therefore, there are both a change of phase and gain depending on the sample's mass. This makes the robust design of the controller a little bit more complicated. Position feedback controllers are designed for each nano-hexapod such that it is stable for all considered sample masses with similar stability margins (see Nyquist plots in Figure ref:fig:uniaxial_nyquist_hac). These high authority controllers are generally composed of a two integrators at low frequency for disturbance rejection, a lead to increase the phase margin near the crossover frequency and a low pass filter to increase the robustness to high frequency dynamics. The loop gains for the three nano-hexapod are shown in Figure ref:fig:uniaxial_loop_gain_hac. We can see that: - for the soft and moderately stiff nano-hexapod, the crossover frequency varies a lot with the sample mass. This is due to the fact that the crossover frequency corresponds to the mass line of the plant. - for the stiff nano-hexapod, the obtained crossover frequency is not at high as what was estimated necessary. The crossover frequency in that case is close to the stiffness line of the plant, which makes the robust design of the controller easier. Note that these controller were quickly tuned by hand and not designed using any optimization methods. The goal is just to have a first estimation of the attainable performances. #+begin_src matlab :exports none %% High Authority Controller - Soft Nano-Hexapod % Lead to increase phase margin a = 5; % Amount of phase lead / width of the phase lead / high frequency gain wc = 2*pi*20; % Frequency with the maximum phase lead [rad/s] H_lead = (1 + s/(wc/sqrt(a)))/(1 + s/(wc*sqrt(a))); % Low Pass filter to increase robustness H_lpf = 1/(1 + s/2/pi/200); % Added integrator at low frequency H_int = (s + 2*pi*5)/(s + 2*pi*0.01); % High Authority Controller K_hac_vc = 4e5 * ... % Gain H_lead * ... % Lead H_int * ... % Integrator H_lpf; % LPF K_hac_vc.InputName = {'d'}; K_hac_vc.OutputName = {'f'}; #+end_src #+begin_src matlab :exports none %% High Authority Controller - Mid Stiffness Nano-Hexapod % Integrator as low frequency H_int = (s + 2*pi*10)/(s + 2*pi*0.01) * (s + 2*pi*20)/(s + 2*pi*0.01); % Lead to increase phase margin a = 4; % Amount of phase lead / width of the phase lead / high frequency gain wc = 2*pi*70; % Frequency with the maximum phase lead [rad/s] H_lead = (1 + s/(wc/sqrt(a)))/(1 + s/(wc*sqrt(a))); % Low Pass filter to increase robustness H_lpf = 1/(1 + s/2/pi/300); % High Authority Controller K_hac_md = 3e6 * ... % Gain H_lead * ... % Lead H_lpf * ... % Low Pass Filter H_int; % Integrator K_hac_md.InputName = {'d'}; K_hac_md.OutputName = {'f'}; #+end_src #+begin_src matlab :exports none %% High Authority Controller - Stiff Nano-Hexapod % Integrator as low frequency H_int = 1/(s + 2*pi*0.01) * 1/(s + 2*pi*0.01); % Lead to increase phase margin a = 5; % Amount of phase lead / width of the phase lead / high frequency gain wc = 2*pi*100; % Frequency with the maximum phase lead [rad/s] H_lead = (1 + s/(wc/sqrt(a)))/(1 + s/(wc*sqrt(a))); % Low Pass filter to increase robustness H_lpf = 1/(1 + s/2/pi/500); % High Authority Controller K_hac_pz = 6e12 * ... % Gain H_lead^2 * ... % Lead H_lpf * ... % Low Pass Filter H_int; % Integrator K_hac_pz.InputName = {'d'}; K_hac_pz.OutputName = {'f'}; #+end_src #+begin_src matlab :exports none %% Compute Loop gain for Nyquist Plot L_vc_light = squeeze(freqresp(K_hac_vc*G_iff_vc_light('d', 'f'), freqs, 'Hz')); L_vc_mid = squeeze(freqresp(K_hac_vc*G_iff_vc_mid( 'd', 'f'), freqs, 'Hz')); L_vc_heavy = squeeze(freqresp(K_hac_vc*G_iff_vc_heavy('d', 'f'), freqs, 'Hz')); L_md_light = squeeze(freqresp(K_hac_md*G_iff_md_light('d', 'f'), freqs, 'Hz')); L_md_mid = squeeze(freqresp(K_hac_md*G_iff_md_mid( 'd', 'f'), freqs, 'Hz')); L_md_heavy = squeeze(freqresp(K_hac_md*G_iff_md_heavy('d', 'f'), freqs, 'Hz')); L_pz_light = squeeze(freqresp(K_hac_pz*G_iff_pz_light('d', 'f'), freqs, 'Hz')); L_pz_mid = squeeze(freqresp(K_hac_pz*G_iff_pz_mid( 'd', 'f'), freqs, 'Hz')); L_pz_heavy = squeeze(freqresp(K_hac_pz*G_iff_pz_heavy('d', 'f'), freqs, 'Hz')); #+end_src #+begin_src matlab :exports none :results none %% Nyquist Plot - Hight Authority Controller for all three nano-hexapod stiffnesses and all sample masses figure; hold on; plot(real(L_vc_light), +imag(L_vc_light), '-', 'color', [colors(1,:), 0.5], 'DisplayName', '$k_n = 0.01\,N/\mu m$') plot(real(L_vc_light), -imag(L_vc_light), '-', 'color', [colors(1,:), 0.5], 'HandleVisibility', 'off') plot(real(L_vc_mid ), +imag(L_vc_mid ), '-', 'color', [colors(1,:), 0.5], 'HandleVisibility', 'off') plot(real(L_vc_mid ), -imag(L_vc_mid ), '-', 'color', [colors(1,:), 0.5], 'HandleVisibility', 'off') plot(real(L_vc_heavy), +imag(L_vc_heavy), '-', 'color', [colors(1,:), 0.5], 'HandleVisibility', 'off') plot(real(L_vc_heavy), -imag(L_vc_heavy), '-', 'color', [colors(1,:), 0.5], 'HandleVisibility', 'off') plot(real(L_md_light), +imag(L_md_light), '-', 'color', [colors(2,:), 0.5], 'DisplayName', '$k_n = 1\,N/\mu m$') plot(real(L_md_light), -imag(L_md_light), '-', 'color', [colors(2,:), 0.5], 'HandleVisibility', 'off') plot(real(L_md_mid ), +imag(L_md_mid ), '-', 'color', [colors(2,:), 0.5], 'HandleVisibility', 'off') plot(real(L_md_mid ), -imag(L_md_mid ), '-', 'color', [colors(2,:), 0.5], 'HandleVisibility', 'off') plot(real(L_md_heavy), +imag(L_md_heavy), '-', 'color', [colors(2,:), 0.5], 'HandleVisibility', 'off') plot(real(L_md_heavy), -imag(L_md_heavy), '-', 'color', [colors(2,:), 0.5], 'HandleVisibility', 'off') plot(real(L_pz_light), +imag(L_pz_light), '-', 'color', [colors(3,:), 0.5], 'DisplayName', '$k_n = 100\,N/\mu m$') plot(real(L_pz_light), -imag(L_pz_light), '-', 'color', [colors(3,:), 0.5], 'HandleVisibility', 'off') plot(real(L_pz_mid ), +imag(L_pz_mid ), '-', 'color', [colors(3,:), 0.5], 'HandleVisibility', 'off') plot(real(L_pz_mid ), -imag(L_pz_mid ), '-', 'color', [colors(3,:), 0.5], 'HandleVisibility', 'off') plot(real(L_pz_heavy), +imag(L_pz_heavy), '-', 'color', [colors(3,:), 0.5], 'HandleVisibility', 'off') plot(real(L_pz_heavy), -imag(L_pz_heavy), '-', 'color', [colors(3,:), 0.5], 'HandleVisibility', 'off') plot(-1, 0, 'kx', 'HandleVisibility', 'off'); hold off; set(gca, 'XScale', 'lin'); set(gca, 'YScale', 'lin'); xlabel('Real'); ylabel('Imag'); legend('location', 'northeast', 'FontSize', 8, 'NumColumns', 1); xlim([-3.8, 0.2]); ylim([-2, 2]); axis square; #+end_src #+begin_src matlab :tangle no :exports results :results file replace exportFig('figs/uniaxial_nyquist_hac.pdf', 'width', 'wide', 'height', 'tall'); #+end_src #+name: fig:uniaxial_nyquist_hac #+caption: Nyquist Plot - Hight Authority Controller for all three nano-hexapod stiffnesses (soft one in blue, moderately stiff in red and very stiff in yellow) and all sample masses (corresponding to the three curves of each color) #+RESULTS: [[file:figs/uniaxial_nyquist_hac.png]] #+begin_src matlab :exports none :results none %% Loop Gain - High Authority Controller for all three nano-hexapod stiffnesses and all sample masses figure; tiledlayout(3, 1, 'TileSpacing', 'Compact', 'Padding', 'None'); ax1 = nexttile([2,1]); hold on; plot(freqs, abs(L_vc_light), 'color', [colors(1,:), 0.5], 'DisplayName', '$k_n = 0.01\,N/\mu m$'); plot(freqs, abs(L_vc_mid), 'color', [colors(1,:), 0.5], 'HandleVisibility', 'off'); plot(freqs, abs(L_vc_heavy), 'color', [colors(1,:), 0.5], 'HandleVisibility', 'off'); plot(freqs, abs(L_md_light), 'color', [colors(2,:), 0.5], 'DisplayName', '$k_n = 1\,N/\mu m$'); plot(freqs, abs(L_md_mid), 'color', [colors(2,:), 0.5], 'HandleVisibility', 'off'); plot(freqs, abs(L_md_heavy), 'color', [colors(2,:), 0.5], 'HandleVisibility', 'off'); plot(freqs, abs(L_pz_light), 'color', [colors(3,:), 0.5], 'DisplayName', '$k_n = 100\,N/\mu m$'); plot(freqs, abs(L_pz_mid), 'color', [colors(3,:), 0.5], 'HandleVisibility', 'off'); plot(freqs, abs(L_pz_heavy), 'color', [colors(3,:), 0.5], 'HandleVisibility', 'off'); hold off; set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log'); ylabel('Loop Gain'); set(gca, 'XTickLabel',[]); ylim([1e-3, 1e3]); legend('location', 'northeast', 'FontSize', 8, 'NumColumns', 1); ax2 = nexttile; hold on; plot(freqs, 180/pi*unwrap(angle(L_vc_light)), 'color', [colors(1,:), 0.5]); plot(freqs, 180/pi*unwrap(angle(L_vc_mid )), 'color', [colors(1,:), 0.5]); plot(freqs, 180/pi*unwrap(angle(L_vc_heavy)), 'color', [colors(1,:), 0.5]); plot(freqs, 180/pi*unwrap(angle(L_md_light)), 'color', [colors(2,:), 0.5]); plot(freqs, 180/pi*unwrap(angle(L_md_mid )), 'color', [colors(2,:), 0.5]); plot(freqs, 180/pi*unwrap(angle(L_md_heavy)), 'color', [colors(2,:), 0.5]); plot(freqs, 180/pi*unwrap(angle(L_pz_light)), 'color', [colors(3,:), 0.5]); plot(freqs, 180/pi*unwrap(angle(L_pz_mid )), 'color', [colors(3,:), 0.5]); plot(freqs, 180/pi*unwrap(angle(L_pz_heavy)), 'color', [colors(3,:), 0.5]); hold off; set(gca, 'XScale', 'log'); set(gca, 'YScale', 'lin'); xlabel('Frequency [Hz]'); ylabel('Phase [deg]'); hold off; yticks(-360:90:360); ylim([-270, 0]); linkaxes([ax1,ax2],'x'); xlim([1, 500]); #+end_src #+begin_src matlab :tangle no :exports results :results file replace exportFig('figs/uniaxial_loop_gain_hac.pdf', 'width', 'wide', 'height', 'tall'); #+end_src #+name: fig:uniaxial_loop_gain_hac #+caption: Loop Gain - High Authority Controller for all three nano-hexapod stiffnesses (soft one in blue, moderately stiff in red and very stiff in yellow) and all sample masses (corresponding to the three curves of each color) #+RESULTS: [[file:figs/uniaxial_loop_gain_hac.png]] ** Closed-Loop Noise Budgeting The high authority position feedback controllers are then implemented and the closed-loop sensitivity to disturbances are computed. These are compared with the open-loop and damped plants cases in Figure ref:fig:uniaxial_sensitivity_dist_hac_lac for just one configuration (moderately stiff nano-hexapod with 25kg sample's mass). As expected, the sensitivity to disturbances is decreased in the controller bandwidth and slightly increase outside this bandwidth. #+begin_src matlab :exports none %% Compute Closed Loop Systems G_hac_iff_vc_light = feedback(G_iff_vc_light, K_hac_vc, 'name', -1); G_hac_iff_vc_mid = feedback(G_iff_vc_mid , K_hac_vc, 'name', -1); G_hac_iff_vc_heavy = feedback(G_iff_vc_heavy, K_hac_vc, 'name', -1); G_hac_iff_md_light = feedback(G_iff_md_light, K_hac_md, 'name', -1); G_hac_iff_md_mid = feedback(G_iff_md_mid , K_hac_md, 'name', -1); G_hac_iff_md_heavy = feedback(G_iff_md_heavy, K_hac_md, 'name', -1); G_hac_iff_pz_light = feedback(G_iff_pz_light, K_hac_pz, 'name', -1); G_hac_iff_pz_mid = feedback(G_iff_pz_mid , K_hac_pz, 'name', -1); G_hac_iff_pz_heavy = feedback(G_iff_pz_heavy, K_hac_pz, 'name', -1); #+end_src #+begin_src matlab :exports none %% Verify Stability isstable(G_hac_iff_vc_light) && isstable(G_hac_iff_vc_mid) && isstable(G_hac_iff_vc_heavy) isstable(G_hac_iff_md_light) && isstable(G_hac_iff_md_mid) && isstable(G_hac_iff_md_heavy) isstable(G_hac_iff_pz_light) && isstable(G_hac_iff_pz_mid) && isstable(G_hac_iff_pz_heavy) #+end_src #+begin_src matlab :exports none :results none %% Change of sensitivity to disturbances with LAC and with HAC-LAC figure; tiledlayout(1, 3, 'TileSpacing', 'Compact', 'Padding', 'None'); ax1 = nexttile(); hold on; plot(freqs, abs(squeeze(freqresp(G_md_mid( 'd', 'fs'), freqs, 'Hz'))), 'k-'); plot(freqs, abs(squeeze(freqresp(G_iff_md_mid('d', 'fs'), freqs, 'Hz'))), 'color', colors(1,:)); plot(freqs, abs(squeeze(freqresp(G_hac_iff_md_mid('d', 'fs'), freqs, 'Hz'))), 'color', colors(2,:)); hold off; set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log'); xticks([1e0, 1e1, 1e2]); ylabel('Amplitude $d/f_{s}$ [m/N]'); xlabel('Frequency [Hz]'); ax2 = nexttile(); hold on; plot(freqs, abs(squeeze(freqresp(G_md_mid( 'd', 'ft'), freqs, 'Hz'))), 'k-'); plot(freqs, abs(squeeze(freqresp(G_iff_md_mid('d', 'ft'), freqs, 'Hz'))), 'color', colors(1,:)); plot(freqs, abs(squeeze(freqresp(G_hac_iff_md_mid('d', 'ft'), freqs, 'Hz'))), 'color', colors(2,:)); hold off; set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log'); xticks([1e0, 1e1, 1e2]); ylabel('Amplitude $d/f_{t}$ [m/N]'); xlabel('Frequency [Hz]'); ax3 = nexttile(); hold on; plot(freqs, abs(squeeze(freqresp(G_md_mid( 'd', 'xf'), freqs, 'Hz'))), 'k-', 'DisplayName', 'OL'); plot(freqs, abs(squeeze(freqresp(G_iff_md_mid('d', 'xf'), freqs, 'Hz'))), 'color', colors(1,:), 'DisplayName', 'IFF'); plot(freqs, abs(squeeze(freqresp(G_hac_iff_md_mid('d', 'xf'), freqs, 'Hz'))), 'color', colors(2,:), 'DisplayName', 'HAC-IFF'); hold off; set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log'); xticks([1e0, 1e1, 1e2]); ylabel('Amplitude $d/x_{f}$ [m/m]'); xlabel('Frequency [Hz]'); legend('location', 'southeast', 'FontSize', 8, 'NumColumns', 1); linkaxes([ax1,ax2,ax3],'x'); xlim([1, 500]); #+end_src #+begin_src matlab :tangle no :exports results :results file replace exportFig('figs/uniaxial_sensitivity_dist_hac_lac.pdf', 'width', 'full', 'height', 'normal'); #+end_src #+name: fig:uniaxial_sensitivity_dist_hac_lac #+caption: Change of sensitivity to disturbances with LAC and with HAC-LAC #+RESULTS: [[file:figs/uniaxial_sensitivity_dist_hac_lac.png]] The cumulative amplitude spectrum of the motion $d$ is computed for all nano-hexapod configurations, all sample masses and in the open-loop (OL), damped (IFF) and position controlled (HAC-IFF) cases. The results are shown in Figure ref:fig:uniaxial_cas_hac_lac. Obtained root mean square values of the distance $d$ are better for the soft nano-hexapod ($\approx 25\,nm$ to $\approx 35\,nm$ depending on the sample's mass) than for the stiffer nano-hexapod (from $\approx 30\,nm$ to $\approx 70\,nm$). #+begin_src matlab :exports none :results none %% Cumulative Amplitude Spectrum for all three nano-hexapod stiffnesses - Comparison of OL, IFF and HAC-LAC cases figure; tiledlayout(1, 3, 'TileSpacing', 'Compact', 'Padding', 'None'); ax1 = nexttile(); hold on; plot(f, sqrt(flip(-cumtrapz(flip(f), flip(psd_ft.*abs(squeeze(freqresp(G_vc_mid('d', 'ft'), f, 'Hz'))).^2 + ... psd_xf.*abs(squeeze(freqresp(G_vc_mid('d', 'xf'), f, 'Hz'))).^2)))), '-', ... 'color', [0,0,0,0.5], 'DisplayName', 'OL'); plot(f, sqrt(flip(-cumtrapz(flip(f), flip(psd_ft.*abs(squeeze(freqresp(G_vc_light('d', 'ft'), f, 'Hz'))).^2 + ... psd_xf.*abs(squeeze(freqresp(G_vc_light('d', 'xf'), f, 'Hz'))).^2)))), '-', ... 'color', [0,0,0,0.5], 'HandleVisibility', 'off'); plot(f, sqrt(flip(-cumtrapz(flip(f), flip(psd_ft.*abs(squeeze(freqresp(G_vc_heavy('d', 'ft'), f, 'Hz'))).^2 + ... psd_xf.*abs(squeeze(freqresp(G_vc_heavy('d', 'xf'), f, 'Hz'))).^2)))), '-', ... 'color', [0,0,0,0.5], 'HandleVisibility', 'off'); plot(f, sqrt(flip(-cumtrapz(flip(f), flip(psd_ft.*abs(squeeze(freqresp(G_iff_vc_mid('d', 'ft'), f, 'Hz'))).^2 + ... psd_xf.*abs(squeeze(freqresp(G_iff_vc_mid('d', 'xf'), f, 'Hz'))).^2)))), '-', ... 'color', [colors(1,:), 0.5], 'DisplayName', 'IFF'); plot(f, sqrt(flip(-cumtrapz(flip(f), flip(psd_ft.*abs(squeeze(freqresp(G_iff_vc_light('d', 'ft'), f, 'Hz'))).^2 + ... psd_xf.*abs(squeeze(freqresp(G_iff_vc_light('d', 'xf'), f, 'Hz'))).^2)))), '-', ... 'color', [colors(1,:), 0.5], 'HandleVisibility', 'off'); plot(f, sqrt(flip(-cumtrapz(flip(f), flip(psd_ft.*abs(squeeze(freqresp(G_iff_vc_heavy('d', 'ft'), f, 'Hz'))).^2 + ... psd_xf.*abs(squeeze(freqresp(G_iff_vc_heavy('d', 'xf'), f, 'Hz'))).^2)))), '-', ... 'color', [colors(1,:), 0.5], 'HandleVisibility', 'off'); plot(f, sqrt(flip(-cumtrapz(flip(f), flip(psd_ft.*abs(squeeze(freqresp(G_hac_iff_vc_mid('d', 'ft'), f, 'Hz'))).^2 + ... psd_xf.*abs(squeeze(freqresp(G_hac_iff_vc_mid('d', 'xf'), f, 'Hz'))).^2)))), '-', ... 'color', [colors(2,:), 0.5], 'DisplayName', 'HAC-IFF'); plot(f, sqrt(flip(-cumtrapz(flip(f), flip(psd_ft.*abs(squeeze(freqresp(G_hac_iff_vc_light('d', 'ft'), f, 'Hz'))).^2 + ... psd_xf.*abs(squeeze(freqresp(G_hac_iff_vc_light('d', 'xf'), f, 'Hz'))).^2)))), '-', ... 'color', [colors(2,:), 0.5], 'HandleVisibility', 'off'); plot(f, sqrt(flip(-cumtrapz(flip(f), flip(psd_ft.*abs(squeeze(freqresp(G_hac_iff_vc_heavy('d', 'ft'), f, 'Hz'))).^2 + ... psd_xf.*abs(squeeze(freqresp(G_hac_iff_vc_heavy('d', 'xf'), f, 'Hz'))).^2)))), '-', ... 'color', [colors(2,:), 0.5], 'HandleVisibility', 'off'); hold off; set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log'); xticks([1e0, 1e1, 1e2]); ylabel('CAS of $d$ [m]'); xlabel('Frequency [Hz]'); legend('location', 'southwest', 'FontSize', 8, 'NumColumns', 1); title('$k_n = 0.01\,N/\mu m$'); ax2 = nexttile(); hold on; plot(f, sqrt(flip(-cumtrapz(flip(f), flip(psd_ft.*abs(squeeze(freqresp(G_md_mid('d', 'ft'), f, 'Hz'))).^2 + ... psd_xf.*abs(squeeze(freqresp(G_md_mid('d', 'xf'), f, 'Hz'))).^2)))), '-', ... 'color', [0,0,0,0.5]); plot(f, sqrt(flip(-cumtrapz(flip(f), flip(psd_ft.*abs(squeeze(freqresp(G_md_light('d', 'ft'), f, 'Hz'))).^2 + ... psd_xf.*abs(squeeze(freqresp(G_md_light('d', 'xf'), f, 'Hz'))).^2)))), '-', ... 'color', [0,0,0,0.5]); plot(f, sqrt(flip(-cumtrapz(flip(f), flip(psd_ft.*abs(squeeze(freqresp(G_md_heavy('d', 'ft'), f, 'Hz'))).^2 + ... psd_xf.*abs(squeeze(freqresp(G_md_heavy('d', 'xf'), f, 'Hz'))).^2)))), '-', ... 'color', [0,0,0,0.5]); plot(f, sqrt(flip(-cumtrapz(flip(f), flip(psd_ft.*abs(squeeze(freqresp(G_iff_md_mid('d', 'ft'), f, 'Hz'))).^2 + ... psd_xf.*abs(squeeze(freqresp(G_iff_md_mid('d', 'xf'), f, 'Hz'))).^2)))), '-', ... 'color', [colors(1,:), 0.5]); plot(f, sqrt(flip(-cumtrapz(flip(f), flip(psd_ft.*abs(squeeze(freqresp(G_iff_md_light('d', 'ft'), f, 'Hz'))).^2 + ... psd_xf.*abs(squeeze(freqresp(G_iff_md_light('d', 'xf'), f, 'Hz'))).^2)))), '-', ... 'color', [colors(1,:), 0.5]); plot(f, sqrt(flip(-cumtrapz(flip(f), flip(psd_ft.*abs(squeeze(freqresp(G_iff_md_heavy('d', 'ft'), f, 'Hz'))).^2 + ... psd_xf.*abs(squeeze(freqresp(G_iff_md_heavy('d', 'xf'), f, 'Hz'))).^2)))), '-', ... 'color', [colors(1,:), 0.5]); plot(f, sqrt(flip(-cumtrapz(flip(f), flip(psd_ft.*abs(squeeze(freqresp(G_hac_iff_md_mid('d', 'ft'), f, 'Hz'))).^2 + ... psd_xf.*abs(squeeze(freqresp(G_hac_iff_md_mid('d', 'xf'), f, 'Hz'))).^2)))), '-', ... 'color', [colors(2,:), 0.5]); plot(f, sqrt(flip(-cumtrapz(flip(f), flip(psd_ft.*abs(squeeze(freqresp(G_hac_iff_md_light('d', 'ft'), f, 'Hz'))).^2 + ... psd_xf.*abs(squeeze(freqresp(G_hac_iff_md_light('d', 'xf'), f, 'Hz'))).^2)))), '-', ... 'color', [colors(2,:), 0.5]); plot(f, sqrt(flip(-cumtrapz(flip(f), flip(psd_ft.*abs(squeeze(freqresp(G_hac_iff_md_heavy('d', 'ft'), f, 'Hz'))).^2 + ... psd_xf.*abs(squeeze(freqresp(G_hac_iff_md_heavy('d', 'xf'), f, 'Hz'))).^2)))), '-', ... 'color', [colors(2,:), 0.5]); hold off; set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log'); xticks([1e0, 1e1, 1e2]); xlabel('Frequency [Hz]'); set(gca, 'YTickLabel',[]); title('$k_n = 1\,N/\mu m$'); ax3 = nexttile(); hold on; plot(f, sqrt(flip(-cumtrapz(flip(f), flip(psd_ft.*abs(squeeze(freqresp(G_pz_mid('d', 'ft'), f, 'Hz'))).^2 + ... psd_xf.*abs(squeeze(freqresp(G_pz_mid('d', 'xf'), f, 'Hz'))).^2)))), '-', ... 'color', [0,0,0,0.5]); plot(f, sqrt(flip(-cumtrapz(flip(f), flip(psd_ft.*abs(squeeze(freqresp(G_pz_light('d', 'ft'), f, 'Hz'))).^2 + ... psd_xf.*abs(squeeze(freqresp(G_pz_light('d', 'xf'), f, 'Hz'))).^2)))), '-', ... 'color', [0,0,0,0.5]); plot(f, sqrt(flip(-cumtrapz(flip(f), flip(psd_ft.*abs(squeeze(freqresp(G_pz_heavy('d', 'ft'), f, 'Hz'))).^2 + ... psd_xf.*abs(squeeze(freqresp(G_pz_heavy('d', 'xf'), f, 'Hz'))).^2)))), '-', ... 'color', [0,0,0,0.5]); plot(f, sqrt(flip(-cumtrapz(flip(f), flip(psd_ft.*abs(squeeze(freqresp(G_iff_pz_mid('d', 'ft'), f, 'Hz'))).^2 + ... psd_xf.*abs(squeeze(freqresp(G_iff_pz_mid('d', 'xf'), f, 'Hz'))).^2)))), '-', ... 'color', [colors(1,:), 0.5]); plot(f, sqrt(flip(-cumtrapz(flip(f), flip(psd_ft.*abs(squeeze(freqresp(G_iff_pz_light('d', 'ft'), f, 'Hz'))).^2 + ... psd_xf.*abs(squeeze(freqresp(G_iff_pz_light('d', 'xf'), f, 'Hz'))).^2)))), '-', ... 'color', [colors(1,:), 0.5]); plot(f, sqrt(flip(-cumtrapz(flip(f), flip(psd_ft.*abs(squeeze(freqresp(G_iff_pz_heavy('d', 'ft'), f, 'Hz'))).^2 + ... psd_xf.*abs(squeeze(freqresp(G_iff_pz_heavy('d', 'xf'), f, 'Hz'))).^2)))), '-', ... 'color', [colors(1,:), 0.5]); plot(f, sqrt(flip(-cumtrapz(flip(f), flip(psd_ft.*abs(squeeze(freqresp(G_hac_iff_pz_mid('d', 'ft'), f, 'Hz'))).^2 + ... psd_xf.*abs(squeeze(freqresp(G_hac_iff_pz_mid('d', 'xf'), f, 'Hz'))).^2)))), '-', ... 'color', [colors(2,:), 0.5]); plot(f, sqrt(flip(-cumtrapz(flip(f), flip(psd_ft.*abs(squeeze(freqresp(G_hac_iff_pz_light('d', 'ft'), f, 'Hz'))).^2 + ... psd_xf.*abs(squeeze(freqresp(G_hac_iff_pz_light('d', 'xf'), f, 'Hz'))).^2)))), '-', ... 'color', [colors(2,:), 0.5]); plot(f, sqrt(flip(-cumtrapz(flip(f), flip(psd_ft.*abs(squeeze(freqresp(G_hac_iff_pz_heavy('d', 'ft'), f, 'Hz'))).^2 + ... psd_xf.*abs(squeeze(freqresp(G_hac_iff_pz_heavy('d', 'xf'), f, 'Hz'))).^2)))), '-', ... 'color', [colors(2,:), 0.5]); hold off; set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log'); xticks([1e0, 1e1, 1e2]); xlabel('Frequency [Hz]'); set(gca, 'YTickLabel',[]); title('$k_n = 100\,N/\mu m$'); linkaxes([ax1,ax2,ax3],'xy'); xlim([1, 500]); ylim([2e-10, 3e-6]) #+end_src #+begin_src matlab :tangle no :exports results :results file replace exportFig('figs/uniaxial_cas_hac_lac.pdf', 'width', 'full', 'height', 'normal'); #+end_src #+name: fig:uniaxial_cas_hac_lac #+caption: Cumulative Amplitude Spectrum for all three nano-hexapod stiffnesses - Comparison of OL, IFF and HAC-LAC cases #+RESULTS: [[file:figs/uniaxial_cas_hac_lac.png]] * Conclusion <> In this study, a uniaxial model of the nano-active-stabilization-system has been tuned both from dynamical measurements (Section ref:sec:micro_station_model) and from disturbances measurements (Section ref:sec:uniaxial_disturbances). It has been shown that three active damping techniques can be used to critically damp the nano-hexapod resonances (Section ref:sec:uniaxial_active_damping). However, this model does not allows to determine which one is most suited to this application. Finally, position feedback controllers have been developed for three considered nano-hexapod stiffnesses. These controllers were shown to be robust to the change of sample's masses, and to provide good rejection of disturbances. It has been found that having a soft nano-hexapod makes the plant dynamics easier to control (because decoupled from the micro-station dynamics) and requires less position feedback bandwidth to fulfill the requirements. The moderately stiff nano-hexapod ($k_n = 1\,N/\mu m$) is requiring a bit more position feedback bandwidth, but it still seems to give acceptable results. However, the stiff nano-hexapod is the most complex to control and gives the worst positioning performances. * Helping Functions :noexport: ** Initialize Path #+NAME: m-init-path #+BEGIN_SRC matlab %% Path for functions, data and scripts addpath('./matlab/mat/'); % Path for data addpath('./matlab/'); % Path for scripts #+END_SRC #+NAME: m-init-path-tangle #+BEGIN_SRC matlab %% Path for functions, data and scripts addpath('./mat/'); % Path for data #+END_SRC ** Initialize other elements #+NAME: m-init-other #+BEGIN_SRC matlab %% Colors for the figures colors = colororder; #+END_SRC