4451 lines
199 KiB
Org Mode
4451 lines
199 KiB
Org Mode
#+TITLE: Nano Active Stabilization System - Effect of rotation
|
|
:DRAWER:
|
|
#+LANGUAGE: en
|
|
#+EMAIL: dehaeze.thomas@gmail.com
|
|
#+AUTHOR: Dehaeze Thomas
|
|
|
|
#+HTML_LINK_HOME: ../index.html
|
|
#+HTML_LINK_UP: ../index.html
|
|
|
|
#+HTML_HEAD: <link rel="stylesheet" type="text/css" href="https://research.tdehaeze.xyz/css/style.css"/>
|
|
#+HTML_HEAD: <script type="text/javascript" src="https://research.tdehaeze.xyz/js/script.js"></script>
|
|
|
|
#+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, bibliography=totoc]
|
|
#+LATEX_HEADER: \input{preamble.tex}
|
|
#+LATEX_HEADER_EXTRA: \input{preamble_extra.tex}
|
|
#+LATEX_HEADER_EXTRA: \bibliography{nass-rotating-3dof-model.bib}
|
|
|
|
#+BIND: org-latex-bib-compiler "biber"
|
|
|
|
#+PROPERTY: header-args:matlab :session *MATLAB*
|
|
#+PROPERTY: header-args:matlab+ :comments org
|
|
#+PROPERTY: header-args:matlab+ :exports none
|
|
#+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
|
|
<hr>
|
|
<p>This report is also available as a <a href="./nass-rotating-3dof-model.pdf">pdf</a>.</p>
|
|
<hr>
|
|
#+end_export
|
|
|
|
#+latex: \clearpage
|
|
|
|
* Build :noexport:
|
|
#+NAME: startblock
|
|
#+BEGIN_SRC emacs-lisp :results none :tangle no
|
|
(add-to-list 'org-latex-classes
|
|
'("scrreprt"
|
|
"\\documentclass{scrreprt}"
|
|
("\\chapter{%s}" . "\\chapter*{%s}")
|
|
("\\section{%s}" . "\\section*{%s}")
|
|
("\\subsection{%s}" . "\\subsection*{%s}")
|
|
("\\paragraph{%s}" . "\\paragraph*{%s}")
|
|
))
|
|
|
|
|
|
;; Remove automatic org heading labels
|
|
(defun my-latex-filter-removeOrgAutoLabels (text backend info)
|
|
"Org-mode automatically generates labels for headings despite explicit use of `#+LABEL`. This filter forcibly removes all automatically generated org-labels in headings."
|
|
(when (org-export-derived-backend-p backend 'latex)
|
|
(replace-regexp-in-string "\\\\label{sec:org[a-f0-9]+}\n" "" text)))
|
|
(add-to-list 'org-export-filter-headline-functions
|
|
'my-latex-filter-removeOrgAutoLabels)
|
|
|
|
;; Use no package by default
|
|
(setq org-latex-packages-alist nil)
|
|
(setq org-latex-default-packages-alist nil)
|
|
|
|
;; Do not include the subtitle inside the title
|
|
(setq org-latex-subtitle-separate t)
|
|
(setq org-latex-subtitle-format "\\subtitle{%s}")
|
|
|
|
(setq org-export-before-parsing-hook '(org-ref-glossary-before-parsing
|
|
org-ref-acronyms-before-parsing))
|
|
#+END_SRC
|
|
|
|
* Notes :noexport:
|
|
Prefix is =rotating=
|
|
|
|
* Glossary and Acronyms - Tables :ignore:
|
|
|
|
#+name: glossary
|
|
| label | name | description |
|
|
|-------+-------------------------+---------------------------------------------|
|
|
| psdx | \ensuremath{\Phi_{x}} | Power spectral density of signal $x$ |
|
|
| asdx | \ensuremath{\Gamma_{x}} | Amplitude spectral density of signal $x$ |
|
|
| cpsx | \ensuremath{\Phi_{x}} | Cumulative Power Spectrum of signal $x$ |
|
|
| casx | \ensuremath{\Gamma_{x}} | Cumulative Amplitude Spectrum of signal $x$ |
|
|
|
|
#+name: acronyms
|
|
| key | abbreviation | full form |
|
|
|--------+--------------+------------------------------------------------|
|
|
| haclac | HAC-LAC | High Authority Control - Low Authority Control |
|
|
| hac | HAC | High Authority Control |
|
|
| lac | LAC | Low Authority Control |
|
|
| nass | NASS | Nano Active Stabilization System |
|
|
| asd | ASD | Amplitude Spectral Density |
|
|
| psd | PSD | Power Spectral Density |
|
|
| cps | CPS | Cumulative Power Spectrum |
|
|
| cas | CAS | Cumulative Amplitude Spectrum |
|
|
| frf | FRF | Frequency Response Function |
|
|
| iff | IFF | Integral Force Feedback |
|
|
| rdc | RDC | Relative Damping Control |
|
|
| drga | DRGA | Dynamical Relative Gain Array |
|
|
| hpf | HPF | high-pass filter |
|
|
| lpf | LPF | low-pass filter |
|
|
|
|
* Introduction :ignore:
|
|
|
|
An important aspect of the acrfull:nass is that the nano-hexapod continuously rotates around a vertical axis, whereas the external metrology is not.
|
|
Such rotation induces gyroscopic effects that may impact the system dynamics and obtained performance.
|
|
To study these effects, a model of a rotating suspended platform is first presented (Section ref:sec:rotating_system_description)
|
|
This model is simple enough to be able to derive its dynamics analytically and to understand its behavior, while still allowing the capture of important physical effects in play.
|
|
|
|
acrfull:iff is then applied to the rotating platform, and it is shown that the unconditional stability of acrshort:iff is lost due to the gyroscopic effects induced by the rotation (Section ref:sec:rotating_iff_pure_int).
|
|
Two modifications of the Integral Force Feedback are then proposed.
|
|
The first modification involves adding a high-pass filter to the acrshort:iff controller (Section ref:sec:rotating_iff_pseudo_int).
|
|
It is shown that the acrshort:iff controller is stable for some gain values, and that damping can be added to the suspension modes.
|
|
The optimal high-pass filter cut-off frequency is computed.
|
|
The second modification consists of adding a stiffness in parallel to the force sensors (Section ref:sec:rotating_iff_parallel_stiffness).
|
|
Under certain conditions, the unconditional stability of the IFF controller is regained.
|
|
The optimal parallel stiffness is then computed.
|
|
This study of adapting acrshort:iff for the damping of rotating platforms has been the subject of two published papers [[cite:&dehaeze20_activ_dampin_rotat_platf_integ_force_feedb;&dehaeze21_activ_dampin_rotat_platf_using]].
|
|
|
|
It is then shown that acrfull:rdc is less affected by gyroscopic effects (Section ref:sec:rotating_relative_damp_control).
|
|
Once the optimal control parameters for the three tested active damping techniques are obtained, they are compared in terms of achievable damping, damped plant and closed-loop compliance and transmissibility (Section ref:sec:rotating_comp_act_damp).
|
|
|
|
The previous analysis was applied to three considered nano-hexapod stiffnesses ($k_n = 0.01\,N/\mu m$, $k_n = 1\,N/\mu m$ and $k_n = 100\,N/\mu m$) and the optimal active damping controller was obtained in each case (Section ref:sec:rotating_nano_hexapod).
|
|
Up until this section, the study was performed on a very simplistic model that only captures the rotation aspect, and the model parameters were not tuned to correspond to the NASS.
|
|
In the last section (Section ref:sec:rotating_nass), a model of the micro-station is added below the suspended platform (i.e. the nano-hexapod) with a rotating spindle and parameters tuned to match the NASS dynamics.
|
|
The goal is to determine whether the rotation imposes performance limitation on the NASS.
|
|
|
|
#+name: fig:rotating_overview
|
|
#+caption: Overview of this chapter's organization. Sections are indicated by the red circles.
|
|
#+attr_latex: :width \linewidth
|
|
[[file:figs/rotating_overview.png]]
|
|
|
|
* System Description and Analysis
|
|
:PROPERTIES:
|
|
:header-args:matlab+: :tangle matlab/rotating_1_system_description.m
|
|
:END:
|
|
<<sec:rotating_system_description>>
|
|
|
|
** Introduction :ignore:
|
|
The system used to study gyroscopic effects consists of a 2 degree of freedom translation stage on top of a rotating stage (Figure ref:fig:rotating_3dof_model_schematic).
|
|
The rotating stage is supposed to be ideal, meaning it induces a perfect rotation $\theta(t) = \Omega t$ where $\Omega$ is the rotational speed in $\si{\radian\per\s}$.
|
|
The suspended platform consists of two orthogonal actuators, each represented by three elements in parallel: a spring with a stiffness $k$ in $\si{\newton\per\meter}$, a dashpot with a damping coefficient $c$ in $\si{\newton\per(\meter\per\second)}$ and an ideal force source $F_u, F_v$.
|
|
A payload with a mass $m$ in $\si{\kilo\gram}$, is mounted on the (rotating) suspended platform.
|
|
Two reference frames are used: an /inertial/ frame $(\vec{i}_x, \vec{i}_y, \vec{i}_z)$ and a /uniform rotating/ frame $(\vec{i}_u, \vec{i}_v, \vec{i}_w)$ rigidly fixed on top of the rotating stage with $\vec{i}_w$ aligned with the rotation axis.
|
|
The position of the payload is represented by $(d_u, d_v, 0)$ expressed in the rotating frame.
|
|
After the dynamics of this system is studied, the objective will be to dampen the two suspension modes of the payload while the rotating stage performs a constant rotation.
|
|
|
|
#+begin_src latex :file rotating_3dof_model_schematic.pdf
|
|
\begin{tikzpicture}
|
|
% Angle
|
|
\def\thetau{25}
|
|
|
|
% Rotational Stage
|
|
\draw[fill=black!60!white] (0, 0) circle (4.3);
|
|
\draw[fill=black!40!white] (0, 0) circle (3.8);
|
|
|
|
% Label
|
|
\node[anchor=north west, rotate=\thetau] at (-2.5, 2.5) {\small Rotating Stage};
|
|
|
|
% Rotating Scope
|
|
\begin{scope}[rotate=\thetau]
|
|
% Rotating Frame
|
|
\draw[fill=black!20!white] (-2.6, -2.6) rectangle (2.6, 2.6);
|
|
% Label
|
|
\node[anchor=north west, rotate=\thetau] at (-2.6, 2.6) {\small Suspended Platform};
|
|
|
|
% Mass
|
|
\draw[fill=white] (-1, -1) rectangle (1, 1);
|
|
% Label
|
|
\node[anchor=south west, rotate=\thetau] at (-1, -1) {\small Payload};
|
|
|
|
% Attached Points
|
|
\node[] at (-1, 0){$\bullet$};
|
|
\draw[] (-1, 0) -- ++(-0.2, 0) coordinate(cu);
|
|
\draw[] ($(cu) + (0, -0.8)$) coordinate(actu) -- ($(cu) + (0, 0.8)$) coordinate(ku);
|
|
\node[] at (0, -1){$\bullet$};
|
|
\draw[] (0, -1) -- ++(0, -0.2) coordinate(cv);
|
|
\draw[] ($(cv) + (-0.8, 0)$)coordinate(kv) -- ($(cv) + (0.8, 0)$) coordinate(actv);
|
|
|
|
% Spring and Actuator for U
|
|
\draw[actuator={0.6}{0.2}{black}] (actu) -- node[above=0.1, rotate=\thetau]{$F_u$} (actu-|-2.6,0);
|
|
\draw[spring=0.2] (ku) -- node[above=0.1, rotate=\thetau]{$k$} (ku-|-2.6,0);
|
|
\draw[damper={black}{8}{8}] (cu) -- node[above left=0.2 and -0.1, rotate=\thetau]{$c$} (cu-|-2.6,0);
|
|
|
|
\draw[actuator={0.6}{0.2}{black}] (actv) -- node[left, rotate=\thetau]{$F_v$} (actv|-0,-2.6);
|
|
\draw[spring=0.2] (kv) -- node[left, rotate=\thetau]{$k$} (kv|-0,-2.6);
|
|
\draw[damper={black}{8}{8}] (cv) -- node[left=0.1, rotate=\thetau]{$c$} (cv|-0,-2.6);
|
|
\end{scope}
|
|
|
|
% Inertial Frame
|
|
\draw[->] (-4, -4) -- ++(2, 0) node[below]{$\vec{i}_x$};
|
|
\draw[->] (-4, -4) -- ++(0, 2) node[left]{$\vec{i}_y$};
|
|
\draw[fill, color=black] (-4, -4) circle (0.06);
|
|
\node[draw, circle, inner sep=0pt, minimum size=0.3cm, label=left:$\vec{i}_z$] at (-4, -4){};
|
|
|
|
\draw[->] (0, 0) node[above left, rotate=\thetau]{$\vec{i}_w$} -- ++(\thetau:2) node[above, rotate=\thetau]{$\vec{i}_u$};
|
|
\draw[->] (0, 0) -- ++(\thetau+90:2) node[left, rotate=\thetau]{$\vec{i}_v$};
|
|
\draw[fill, color=black] (0,0) circle (0.06);
|
|
\node[draw, circle, inner sep=0pt, minimum size=0.3cm] at (0, 0){};
|
|
\draw[dashed] (0, 0) -- ++(2, 0);
|
|
\draw[] (1.5, 0) arc (0:\thetau:1.5) node[midway, right]{$\theta$};
|
|
|
|
\draw[->] (3.5, 0) arc (0:40:3.5) node[midway, left]{$\Omega$};
|
|
\end{tikzpicture}
|
|
#+end_src
|
|
|
|
#+name: fig:rotating_3dof_model_schematic
|
|
#+caption: Schematic of the studied system
|
|
#+attr_latex: :scale 0.8
|
|
#+RESULTS:
|
|
[[file:figs/rotating_3dof_model_schematic.png]]
|
|
|
|
** Matlab Init :noexport:ignore:
|
|
#+begin_src matlab :tangle no :results silent :noweb yes :var current_dir=(file-name-directory buffer-file-name)
|
|
<<matlab-dir>>
|
|
#+end_src
|
|
|
|
#+begin_src matlab :results silent :noweb yes
|
|
<<matlab-init>>
|
|
#+end_src
|
|
|
|
#+begin_src matlab :tangle no :noweb yes
|
|
<<m-init-path>>
|
|
#+end_src
|
|
|
|
#+begin_src matlab :eval no :noweb yes
|
|
<<m-init-path-tangle>>
|
|
#+end_src
|
|
|
|
#+begin_src matlab :noweb yes
|
|
<<m-init-other>>
|
|
#+end_src
|
|
|
|
#+begin_src matlab
|
|
%% Simscape model name
|
|
mdl = 'rotating_model';
|
|
#+end_src
|
|
|
|
** Equations of motion and transfer functions
|
|
To obtain the equations of motion for the system represented in Figure ref:fig:rotating_3dof_model_schematic, the Lagrangian equation eqref:eq:rotating_lagrangian_equations is used.
|
|
$L = T - V$ is the Lagrangian, $T$ the kinetic coenergy, $V$ the potential energy, $D$ the dissipation function, and $Q_i$ the generalized force associated with the generalized variable $\begin{bmatrix}q_1 & q_2\end{bmatrix} = \begin{bmatrix}d_u & d_v\end{bmatrix}$.
|
|
These terms are derived in eqref:eq:rotating_energy_functions_lagrange.
|
|
Note that the equation of motion corresponding to constant rotation along $\vec{i}_w$ is disregarded because this motion is imposed by the rotation stage.
|
|
|
|
\begin{equation}\label{eq:rotating_lagrangian_equations}
|
|
\frac{d}{dt} \left( \frac{\partial L}{\partial \dot{q}_i} \right) + \frac{\partial D}{\partial \dot{q}_i} - \frac{\partial L}{\partial q_i} = Q_i
|
|
\end{equation}
|
|
|
|
\begin{equation} \label{eq:rotating_energy_functions_lagrange}
|
|
\begin{aligned}
|
|
T &= \frac{1}{2} m \left( ( \dot{d}_u - \Omega d_v )^2 + ( \dot{d}_v + \Omega d_u )^2 \right), \quad Q_1 = F_u, \quad Q_2 = F_v, \\
|
|
V &= \frac{1}{2} k \big( {d_u}^2 + {d_v}^2 \big), \quad D = \frac{1}{2} c \big( \dot{d}_u{}^2 + \dot{d}_v{}^2 \big)
|
|
\end{aligned}
|
|
\end{equation}
|
|
|
|
Substituting equations eqref:eq:rotating_energy_functions_lagrange into equation eqref:eq:rotating_lagrangian_equations for both generalized coordinates gives two coupled differential equations eqref:eq:rotating_eom_coupled_1 and eqref:eq:rotating_eom_coupled_2.
|
|
|
|
\begin{subequations} \label{eq:rotating_eom_coupled}
|
|
\begin{align}
|
|
m \ddot{d}_u + c \dot{d}_u + ( k - m \Omega^2 ) d_u &= F_u + 2 m \Omega \dot{d}_v \label{eq:rotating_eom_coupled_1} \\
|
|
m \ddot{d}_v + c \dot{d}_v + ( k \underbrace{-\,m \Omega^2}_{\text{Centrif.}} ) d_v &= F_v \underbrace{-\,2 m \Omega \dot{d}_u}_{\text{Coriolis}} \label{eq:rotating_eom_coupled_2}
|
|
\end{align}
|
|
\end{subequations}
|
|
|
|
The uniform rotation of the system induces two /gyroscopic effects/ as shown in equation eqref:eq:rotating_eom_coupled:
|
|
- /Centrifugal forces/: that can be seen as an added /negative stiffness/ $- m \Omega^2$ along $\vec{i}_u$ and $\vec{i}_v$
|
|
- /Coriolis forces/: that adds /coupling/ between the two orthogonal directions.
|
|
One can verify that without rotation ($\Omega = 0$), the system becomes equivalent to two /uncoupled/ one degree of freedom mass-spring-damper systems.
|
|
|
|
To study the dynamics of the system, the two differential equations of motions eqref:eq:rotating_eom_coupled are converted into the Laplace domain and the $2 \times 2$ transfer function matrix $\mathbf{G}_d$ from $\begin{bmatrix}F_u & F_v\end{bmatrix}$ to $\begin{bmatrix}d_u & d_v\end{bmatrix}$ in equation eqref:eq:rotating_Gd_mimo_tf is obtained.
|
|
The four transfer functions in $\mathbf{G}_d$ are shown in equation eqref:eq:rotating_Gd_indiv_el.
|
|
|
|
\begin{equation}\label{eq:rotating_Gd_mimo_tf}
|
|
\begin{bmatrix} d_u \\ d_v \end{bmatrix} = \mathbf{G}_d \begin{bmatrix} F_u \\ F_v \end{bmatrix}
|
|
\end{equation}
|
|
|
|
\begin{subequations}\label{eq:rotating_Gd_indiv_el}
|
|
\begin{align}
|
|
\mathbf{G}_{d}(1,1) &= \mathbf{G}_{d}(2,2) = \frac{ms^2 + cs + k - m \Omega^2}{\left( m s^2 + cs + k - m \Omega^2 \right)^2 + \left( 2 m \Omega s \right)^2} \\
|
|
\mathbf{G}_{d}(1,2) &= -\mathbf{G}_{d}(2,1) = \frac{2 m \Omega s}{\left( m s^2 + cs + k - m \Omega^2 \right)^2 + \left( 2 m \Omega s \right)^2}
|
|
\end{align}
|
|
\end{subequations}
|
|
|
|
To simplify the analysis, the undamped natural frequency $\omega_0$ and the damping ratio $\xi$ defined in eqref:eq:rotating_xi_and_omega are used instead.
|
|
The elements of the transfer function matrix $\mathbf{G}_d$ are described by equation eqref:eq:rotating_Gd_w0_xi_k.
|
|
\begin{equation} \label{eq:rotating_xi_and_omega}
|
|
\omega_0 = \sqrt{\frac{k}{m}} \text{ in } \si{\radian\per\second}, \quad \xi = \frac{c}{2 \sqrt{k m}}
|
|
\end{equation}
|
|
|
|
\begin{subequations} \label{eq:rotating_Gd_w0_xi_k}
|
|
\begin{align}
|
|
\mathbf{G}_{d}(1,1) &= \frac{\frac{1}{k} \left( \frac{s^2}{{\omega_0}^2} + 2 \xi \frac{s}{\omega_0} + 1 - \frac{{\Omega}^2}{{\omega_0}^2} \right)}{\left( \frac{s^2}{{\omega_0}^2} + 2 \xi \frac{s}{\omega_0} + 1 - \frac{{\Omega}^2}{{\omega_0}^2} \right)^2 + \left( 2 \frac{\Omega}{\omega_0} \frac{s}{\omega_0} \right)^2} \\
|
|
\mathbf{G}_{d}(1,2) &= \frac{\frac{1}{k} \left( 2 \frac{\Omega}{\omega_0} \frac{s}{\omega_0} \right)}{\left( \frac{s^2}{{\omega_0}^2} + 2 \xi \frac{s}{\omega_0} + 1 - \frac{{\Omega}^2}{{\omega_0}^2} \right)^2 + \left( 2 \frac{\Omega}{\omega_0} \frac{s}{\omega_0} \right)^2}
|
|
\end{align}
|
|
\end{subequations}
|
|
|
|
** System Poles: Campbell Diagram
|
|
The poles of $\mathbf{G}_d$ are the complex solutions $p$ of equation eqref:eq:rotating_poles (i.e. the roots of its denominator).
|
|
|
|
\begin{equation}\label{eq:rotating_poles}
|
|
\left( \frac{p^2}{{\omega_0}^2} + 2 \xi \frac{p}{\omega_0} + 1 - \frac{{\Omega}^2}{{\omega_0}^2} \right)^2 + \left( 2 \frac{\Omega}{\omega_0} \frac{p}{\omega_0} \right)^2 = 0
|
|
\end{equation}
|
|
|
|
Supposing small damping ($\xi \ll 1$), two pairs of complex conjugate poles $[p_{+}, p_{-}]$ are obtained as shown in equation eqref:eq:rotating_pole_values.
|
|
|
|
\begin{subequations} \label{eq:rotating_pole_values}
|
|
\begin{align}
|
|
p_{+} &= - \xi \omega_0 \left( 1 + \frac{\Omega}{\omega_0} \right) \pm j \omega_0 \left( 1 + \frac{\Omega}{\omega_0} \right) \\
|
|
p_{-} &= - \xi \omega_0 \left( 1 - \frac{\Omega}{\omega_0} \right) \pm j \omega_0 \left( 1 - \frac{\Omega}{\omega_0} \right)
|
|
\end{align}
|
|
\end{subequations}
|
|
|
|
#+begin_src matlab
|
|
%% Model parameters for first analysis
|
|
kn = 1; % Actuator Stiffness [N/m]
|
|
mn = 1; % Payload Mass [kg]
|
|
cn = 0.05; % Actuator Damping [N/(m/s)]
|
|
|
|
xin = cn/(2*sqrt(kn*mn)); % Modal Damping [-]
|
|
w0n = sqrt(kn/mn); % Natural Frequency [rad/s]
|
|
|
|
%% Computation of the poles as a function of the rotating velocity
|
|
Wzs = linspace(0, 2, 51); % Vector of rotation speeds [rad/s]
|
|
|
|
p_ws = zeros(4, length(Wzs));
|
|
|
|
for i = 1:length(Wzs)
|
|
Wz = Wzs(i);
|
|
|
|
pole_G = pole(1/(((s^2)/(w0n^2) + 2*xin*s/w0n + 1 - (Wz^2)/(w0n^2))^2 + (2*Wz*s/(w0n^2))^2));
|
|
[~, i_sort] = sort(imag(pole_G));
|
|
p_ws(:, i) = pole_G(i_sort);
|
|
end
|
|
|
|
clear pole_G;
|
|
#+end_src
|
|
|
|
The real and complex parts of these two pairs of complex conjugate poles are represented in Figure ref:fig:rotating_campbell_diagram as a function of the rotational speed $\Omega$.
|
|
As the rotational speed increases, $p_{+}$ goes to higher frequencies and $p_{-}$ goes to lower frequencies (Figure ref:fig:rotating_campbell_diagram_imag).
|
|
The system becomes unstable for $\Omega > \omega_0$ as the real part of $p_{-}$ is positive (Figure ref:fig:rotating_campbell_diagram_real).
|
|
Physically, the negative stiffness term $-m\Omega^2$ induced by centrifugal forces exceeds the spring stiffness $k$.
|
|
|
|
#+begin_src matlab :results none
|
|
%% Campbell diagram - Real and Imaginary parts of the poles as a function of the rotating velocity
|
|
figure;
|
|
hold on;
|
|
plot(Wzs, real(p_ws(1, :)), '-', 'color', colors(1,:), 'DisplayName', '$p_{+}$')
|
|
plot(Wzs, real(p_ws(4, :)), '-', 'color', colors(1,:), 'HandleVisibility', 'off')
|
|
plot(Wzs, real(p_ws(2, :)), '-', 'color', colors(2,:), 'DisplayName', '$p_{-}$')
|
|
plot(Wzs, real(p_ws(3, :)), '-', 'color', colors(2,:), 'HandleVisibility', 'off')
|
|
plot(Wzs, zeros(size(Wzs)), 'k--', 'HandleVisibility', 'off')
|
|
hold off;
|
|
xlabel('Rotational Speed $\Omega$'); ylabel('Real Part');
|
|
leg = legend('location', 'northwest', 'FontSize', 8);
|
|
leg.ItemTokenSize(1) = 8;
|
|
xlim([0, 2*w0n]);
|
|
xticks([0,w0n/2,w0n,3/2*w0n,2*w0n])
|
|
xticklabels({'$0$', '', '$\omega_0$', '', '$2 \omega_0$'})
|
|
ylim([-3*xin, 3*xin]);
|
|
yticks([-3*xin, -2*xin, -xin, 0, xin, 2*xin, 3*xin])
|
|
yticklabels({'', '', '$-\xi\omega_0$', '$0$', ''})
|
|
#+end_src
|
|
|
|
#+begin_src matlab :tangle no :exports results :results file none
|
|
exportFig('figs/rotating_campbell_diagram_real.pdf', 'width', 450, 'height', 400);
|
|
#+end_src
|
|
|
|
#+begin_src matlab :results none
|
|
figure
|
|
hold on;
|
|
plot(Wzs, imag(p_ws(1, :)), '-', 'color', colors(1,:))
|
|
plot(Wzs, imag(p_ws(4, :)), '-', 'color', colors(1,:))
|
|
plot(Wzs, imag(p_ws(2, :)), '-', 'color', colors(2,:))
|
|
plot(Wzs, imag(p_ws(3, :)), '-', 'color', colors(2,:))
|
|
plot(Wzs, zeros(size(Wzs)), 'k--')
|
|
hold off;
|
|
xlabel('Rotational Speed $\Omega$'); ylabel('Imaginary Part');
|
|
xlim([0, 2*w0n]);
|
|
xticks([0,w0n/2,w0n,3/2*w0n,2*w0n])
|
|
xticklabels({'$0$', '', '$\omega_0$', '', '$2 \omega_0$'})
|
|
ylim([-3*w0n, 3*w0n]);
|
|
yticks([-3*w0n, -2*w0n, -w0n, 0, w0n, 2*w0n, 3*w0n])
|
|
yticklabels({'', '', '$-\omega_0$', '$0$', '$\omega_0$', '', ''})
|
|
#+end_src
|
|
|
|
#+begin_src matlab :tangle no :exports results :results file none
|
|
exportFig('figs/rotating_campbell_diagram_imag.pdf', 'width', 450, 'height', 400);
|
|
#+end_src
|
|
|
|
#+name: fig:rotating_campbell_diagram
|
|
#+caption: Campbell diagram - Real (\subref{fig:rotating_campbell_diagram_real}) and Imaginary (\subref{fig:rotating_campbell_diagram_imag}) parts of the poles as a function of the rotating velocity $\Omega$.
|
|
#+attr_latex: :options [htbp]
|
|
#+begin_figure
|
|
#+attr_latex: :caption \subcaption{\label{fig:rotating_campbell_diagram_real}Real part}
|
|
#+attr_latex: :options {0.49\textwidth}
|
|
#+begin_subfigure
|
|
#+attr_latex: :scale 1
|
|
[[file:figs/rotating_campbell_diagram_real.png]]
|
|
#+end_subfigure
|
|
#+attr_latex: :caption \subcaption{\label{fig:rotating_campbell_diagram_imag}Imaginary part}
|
|
#+attr_latex: :options {0.49\textwidth}
|
|
#+begin_subfigure
|
|
#+attr_latex: :scale 1
|
|
[[file:figs/rotating_campbell_diagram_imag.png]]
|
|
#+end_subfigure
|
|
#+end_figure
|
|
|
|
** Identify Generic Dynamics :noexport:
|
|
#+begin_src matlab
|
|
%% Identify the dynamics for several rotating velocities
|
|
% Sample
|
|
ms = 0.5; % Sample mass [kg]
|
|
|
|
% Tuv Stage
|
|
kn = 1; % Stiffness [N/m]
|
|
mn = 0.5; % Tuv mass [kg]
|
|
cn = 0.01*2*sqrt(kn*(mn+ms)); % Damping [N/(m/s)]
|
|
|
|
% General Configuration
|
|
model_config = struct();
|
|
model_config.controller = "open_loop"; % Default: Open-Loop
|
|
model_config.Tuv_type = "normal"; % Default: 2DoF stage
|
|
|
|
% Input/Output definition
|
|
clear io; io_i = 1;
|
|
io(io_i) = linio([mdl, '/controller'], 1, 'openinput'); io_i = io_i + 1; % [Fu, Fv]
|
|
io(io_i) = linio([mdl, '/fd'], 1, 'openinput'); io_i = io_i + 1; % [Fdu, Fdv]
|
|
io(io_i) = linio([mdl, '/xf'], 1, 'openinput'); io_i = io_i + 1; % [Dfx, Dfy]
|
|
io(io_i) = linio([mdl, '/translation_stage'], 1, 'openoutput'); io_i = io_i + 1; % [Fmu, Fmv]
|
|
io(io_i) = linio([mdl, '/translation_stage'], 2, 'openoutput'); io_i = io_i + 1; % [Du, Dv]
|
|
io(io_i) = linio([mdl, '/ext_metrology'], 1, 'openoutput'); io_i = io_i + 1; % [Dx, Dy]
|
|
|
|
% Tested rotating velocities [rad/s]
|
|
Wzs = [0, 0.1, 0.2, 0.7, 1.2]; % Vector of rotation speeds [rad/s]
|
|
|
|
Gs = {zeros(2, 2, length(Wzs))}; % Direct terms
|
|
|
|
for i = 1:length(Wzs)
|
|
Wz = Wzs(i);
|
|
|
|
%% Linearize the model
|
|
G = linearize(mdl, io, 0);
|
|
|
|
%% Input/Output definition
|
|
G.InputName = {'Fu', 'Fv', 'Fdx', 'Fdy', 'Dfx', 'Dfy'};
|
|
G.OutputName = {'fu', 'fv', 'Du', 'Dv', 'Dx', 'Dy'};
|
|
|
|
Gs{:,:,i} = G;
|
|
end
|
|
#+end_src
|
|
|
|
#+begin_src matlab :tangle no
|
|
% Save All Identified Plants
|
|
save('./matlab/mat/rotating_generic_plants.mat', 'Gs', 'Wzs');
|
|
#+end_src
|
|
|
|
#+begin_src matlab :eval no
|
|
% Save All Identified Plants
|
|
save('./mat/rotating_generic_plants.mat', 'Gs', 'Wzs');
|
|
#+end_src
|
|
|
|
** System Dynamics: Effect of rotation
|
|
The system dynamics from actuator forces $[F_u, F_v]$ to the relative motion $[d_u, d_v]$ is identified for several rotating velocities.
|
|
Looking at the transfer function matrix $\mathbf{G}_d$ in equation eqref:eq:rotating_Gd_w0_xi_k, one can see that the two diagonal (direct) terms are equal and that the two off-diagonal (coupling) terms are opposite.
|
|
The bode plots of these two terms are shown in Figure ref:fig:rotating_bode_plot for several rotational speeds $\Omega$.
|
|
These plots confirm the expected behavior: the frequencies of the two pairs of complex conjugate poles are further separated as $\Omega$ increases.
|
|
For $\Omega > \omega_0$, the low-frequency pair of complex conjugate poles $p_{-}$ becomes unstable (shown be the 180 degrees phase lead instead of phase lag).
|
|
|
|
#+begin_src matlab :results none
|
|
%% Bode plot of the direct and coupling terms for several rotating velocities
|
|
freqs = logspace(-1, 1, 1000);
|
|
|
|
figure;
|
|
tiledlayout(3, 1, 'TileSpacing', 'Compact', 'Padding', 'None');
|
|
|
|
% Magnitude
|
|
ax1 = nexttile([2, 1]);
|
|
hold on;
|
|
for i = 1:length(Wzs)
|
|
plot(freqs, abs(squeeze(freqresp(Gs{i}('du', 'Fu'), freqs, 'rad/s'))), '-', 'color', colors(i,:))
|
|
end
|
|
hold off;
|
|
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
|
|
set(gca, 'XTickLabel',[]); ylabel('Magnitude [m/N]');
|
|
ylim([1e-2, 1e2]);
|
|
yticks([1e-2,1e-1,1,1e1,1e2])
|
|
yticklabels({'$0.01/k$', '$0.1/k$', '$1/k$', '$10/k$', '$100/k$'})
|
|
|
|
ax2 = nexttile;
|
|
hold on;
|
|
for i = 1:length(Wzs)
|
|
plot(freqs, 180/pi*angle(squeeze(freqresp(Gs{i}('du', 'Fu'), freqs, 'rad/s'))), '-', 'color', colors(i,:))
|
|
end
|
|
hold off;
|
|
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'lin');
|
|
xlabel('Frequency [rad/s]'); ylabel('Phase [deg]');
|
|
yticks(-180:90:180);
|
|
ylim([-180 180]);
|
|
xticks([1e-1,1,1e1])
|
|
xticklabels({'$0.1 \omega_0$', '$\omega_0$', '$10 \omega_0$'})
|
|
|
|
linkaxes([ax1,ax2],'x');
|
|
xlim([freqs(1), freqs(end)]);
|
|
#+end_src
|
|
|
|
#+begin_src matlab :tangle no :exports results :results file replace
|
|
exportFig('figs/rotating_bode_plot_direct.pdf', 'width', 'half', 'height', 600);
|
|
#+end_src
|
|
|
|
#+begin_src matlab :results none
|
|
figure;
|
|
tiledlayout(3, 1, 'TileSpacing', 'Compact', 'Padding', 'None');
|
|
|
|
ax1 = nexttile([2, 1]);
|
|
hold on;
|
|
for i = 1:length(Wzs)
|
|
plot(freqs, abs(squeeze(freqresp(Gs{i}('dv', 'Fu'), freqs, 'rad/s'))), '-', 'color', colors(i,:), ...
|
|
'DisplayName', sprintf('$\\Omega = %.1f \\omega_0$', Wzs(i)))
|
|
end
|
|
hold off;
|
|
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
|
|
set(gca, 'XTickLabel',[]); ylabel('Magnitude [m/N]');
|
|
ldg = legend('location', 'northeast', 'FontSize', 8, 'NumColumns', 1);
|
|
ldg.ItemTokenSize = [10, 1];
|
|
ylim([1e-2, 1e2]);
|
|
yticks([1e-2,1e-1,1,1e1,1e2])
|
|
yticklabels({'$0.01/k$', '$0.1/k$', '$1/k$', '$10/k$', '$100/k$'})
|
|
|
|
|
|
ax2 = nexttile;
|
|
hold on;
|
|
for i = 1:length(Wzs)
|
|
plot(freqs, 180/pi*angle(squeeze(freqresp(Gs{i}('dv', 'Fu'), freqs, 'rad/s'))), '-', 'color', colors(i,:));
|
|
end
|
|
hold off;
|
|
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'lin');
|
|
xlabel('Frequency [rad/s]'); ylabel('Phase [deg]');
|
|
yticks(-180:90:180);
|
|
ylim([-180 180]);
|
|
xticks([1e-1,1,1e1])
|
|
xticklabels({'$0.1 \omega_0$', '$\omega_0$', '$10 \omega_0$'})
|
|
|
|
linkaxes([ax1,ax2],'x');
|
|
xlim([freqs(1), freqs(end)]);
|
|
#+end_src
|
|
|
|
#+begin_src matlab :tangle no :exports results :results file replace
|
|
exportFig('figs/rotating_bode_plot_coupling.pdf', 'width', 'half', 'height', 600);
|
|
#+end_src
|
|
|
|
#+name: fig:rotating_bode_plot
|
|
#+caption: Bode plot of the direct (\subref{fig:rotating_bode_plot_direct}) and coupling (\subref{fig:rotating_bode_plot_direct}) terms for several rotating velocities
|
|
#+attr_latex: :options [htbp]
|
|
#+begin_figure
|
|
#+attr_latex: :caption \subcaption{\label{fig:rotating_bode_plot_direct}Direct terms: $d_u/F_u$, $d_v/F_v$}
|
|
#+attr_latex: :options {0.49\textwidth}
|
|
#+begin_subfigure
|
|
#+attr_latex: :width 0.95\linewidth
|
|
[[file:figs/rotating_bode_plot_direct.png]]
|
|
#+end_subfigure
|
|
#+attr_latex: :caption \subcaption{\label{fig:rotating_bode_plot_coupling}Coupling terms: $d_u/F_v$, $d_v/F_u$}
|
|
#+attr_latex: :options {0.49\textwidth}
|
|
#+begin_subfigure
|
|
#+attr_latex: :width 0.95\linewidth
|
|
[[file:figs/rotating_bode_plot_coupling.png]]
|
|
#+end_subfigure
|
|
#+end_figure
|
|
|
|
* Integral Force Feedback
|
|
:PROPERTIES:
|
|
:header-args:matlab+: :tangle matlab/rotating_2_iff_pure_int.m
|
|
:END:
|
|
<<sec:rotating_iff_pure_int>>
|
|
|
|
** Introduction :ignore:
|
|
The goal is now to damp the two suspension modes of the payload using an active damping strategy while the rotating stage performs a constant rotation.
|
|
As was explained with the uniaxial model, such an active damping strategy is key to both reducing the magnification of the response in the vicinity of the resonances cite:collette11_review_activ_vibrat_isolat_strat and to make the plant easier to control for the high authority controller.
|
|
|
|
Many active damping techniques have been developed over the years, such as Positive Position Feedback (PPF) cite:lin06_distur_atten_precis_hexap_point,fanson90_posit_posit_feedb_contr_large_space_struc, Integral Force Feedback (IFF) cite:preumont91_activ and Direct Velocity Feedback (DVF) cite:karnopp74_vibrat_contr_using_semi_activ_force_gener,serrand00_multic_feedb_contr_isolat_base_excit_vibrat,preumont02_force_feedb_versus_accel_feedb.
|
|
In [[cite:&preumont91_activ]], the IFF control scheme has been proposed, where a force sensor, a force actuator, and an integral controller are used to increase the damping of a mechanical system.
|
|
When the force sensor is collocated with the actuator, the open-loop transfer function has alternating poles and zeros, which guarantees the stability of the closed-loop system cite:preumont02_force_feedb_versus_accel_feedb.
|
|
It was later shown that this property holds for multiple collated actuator/sensor pairs cite:preumont08_trans_zeros_struc_contr_with.
|
|
|
|
The main advantages of IFF over other active damping techniques are the guaranteed stability even in the presence of flexible dynamics, good performance, and robustness properties cite:preumont02_force_feedb_versus_accel_feedb.
|
|
|
|
Several improvements to the classical IFF have been proposed, such as adding a feed-through term to increase the achievable damping cite:teo15_optim_integ_force_feedb_activ_vibrat_contr or adding a high-pass filter to recover the loss of compliance at low-frequency cite:chesne16_enhan_dampin_flexib_struc_using_force_feedb.
|
|
Recently, an $\mathcal{H}_\infty$ optimization criterion has been used to derive optimal gains for the IFF controller cite:zhao19_optim_integ_force_feedb_contr. \par
|
|
|
|
However, none of these studies have been applied to rotating systems.
|
|
In this section, the acrshort:iff strategy is applied on the rotating suspended platform, and it is shown that gyroscopic effects alter the system dynamics and that IFF cannot be applied as is.
|
|
|
|
** Matlab Init :noexport:ignore:
|
|
#+begin_src matlab :tangle no :results silent :noweb yes :var current_dir=(file-name-directory buffer-file-name)
|
|
<<matlab-dir>>
|
|
#+end_src
|
|
|
|
#+begin_src matlab :results silent :noweb yes
|
|
<<matlab-init>>
|
|
#+end_src
|
|
|
|
#+begin_src matlab :tangle no :noweb yes
|
|
<<m-init-path>>
|
|
#+end_src
|
|
|
|
#+begin_src matlab :eval no :noweb yes
|
|
<<m-init-path-tangle>>
|
|
#+end_src
|
|
|
|
#+begin_src matlab :noweb yes
|
|
<<m-init-other>>
|
|
#+end_src
|
|
|
|
#+begin_src matlab
|
|
%% Simscape model name
|
|
mdl = 'rotating_model';
|
|
#+end_src
|
|
|
|
#+begin_src matlab
|
|
%% Load "Generic" system dynamics
|
|
load('rotating_generic_plants.mat', 'Gs', 'Wzs');
|
|
#+end_src
|
|
|
|
** System and Equations of motion
|
|
To apply Integral Force Feedback, two force sensors are added in series with the actuators (Figure ref:fig:rotating_3dof_model_schematic_iff).
|
|
Two identical controllers $K_F$ described by eqref:eq:rotating_iff_controller are then used to feedback each of the sensed force to its associated actuator.
|
|
|
|
\begin{equation}\label{eq:rotating_iff_controller}
|
|
K_{F}(s) = g \cdot \frac{1}{s}
|
|
\end{equation}
|
|
|
|
#+begin_src latex :file rotating_3dof_model_schematic_iff.pdf
|
|
\begin{tikzpicture}
|
|
% Angle
|
|
\def\thetau{25}
|
|
|
|
% Rotational Stage
|
|
\draw[fill=black!60!white] (0, 0) circle (4.3);
|
|
\draw[fill=black!40!white] (0, 0) circle (3.8);
|
|
|
|
% Label
|
|
\node[anchor=north west, rotate=\thetau] at (-2.5, 2.5) {\small Rotating Stage};
|
|
|
|
% Rotating Scope
|
|
\begin{scope}[rotate=\thetau]
|
|
% Rotating Frame
|
|
\draw[fill=black!20!white] (-2.6, -2.6) rectangle (2.6, 2.6);
|
|
% Label
|
|
\node[anchor=north west, rotate=\thetau] at (-2.6, 2.6) {\small Suspended Platform};
|
|
|
|
% Mass
|
|
\draw[fill=white] (-1, -1) rectangle (1, 1);
|
|
% Label
|
|
\node[anchor=south west, rotate=\thetau] at (-1, -1) {\small Payload};
|
|
|
|
% Attached Points
|
|
\node[] at (-1, 0){$\bullet$};
|
|
\draw[] (-1, 0) -- ++(-0.2, 0) coordinate(au);
|
|
\node[] at (0, -1){$\bullet$};
|
|
\draw[] (0, -1) -- ++(0, -0.2) coordinate(av);
|
|
|
|
% Force Sensors
|
|
\draw[draw=colorblue, fill=colorblue!10!white] ($(au) + (-0.2, -0.5)$) rectangle ($(au) + (0, 0.5)$);
|
|
\draw[draw=colorblue] ($(au) + (-0.2, -0.5)$)coordinate(actu) -- ($(au) + (0, 0.5)$);
|
|
\draw[draw=colorblue] ($(au) + (-0.2, 0.5)$)coordinate(ku) -- ($(au) + (0, -0.5)$);
|
|
|
|
\draw[draw=colorblue, fill=colorblue!10!white] ($(av) + (-0.5, -0.2)$) rectangle ($(av) + (0.5, 0)$);
|
|
\draw[draw=colorblue] ($(av) + ( 0.5, -0.2)$)coordinate(actv) -- ($(av) + (-0.5, 0)$);
|
|
\draw[draw=colorblue] ($(av) + (-0.5, -0.2)$)coordinate(kv) -- ($(av) + ( 0.5, 0)$);
|
|
|
|
% Spring and Actuator for U
|
|
\draw[actuator={0.6}{0.2}{black}] (actu) -- coordinate[midway](actumid) (actu-|-2.6,0);
|
|
\draw[spring=0.2] (ku) -- node[above=0.1, rotate=\thetau]{$k$} (ku-|-2.6,0);
|
|
|
|
% \draw[actuator={0.6}{0.2}] (actv) -- node[right, rotate=\thetau]{$F_v$} (actv|-0,-2.6);
|
|
\draw[actuator={0.6}{0.2}{black}] (actv) -- coordinate[midway](actvmid) (actv|-0,-2.6);
|
|
\draw[spring=0.2] (kv) -- node[left, rotate=\thetau]{$k$} (kv|-0,-2.6);
|
|
|
|
\node[color=colorblue, block={0.8cm}{0.6cm}, fill=colorblue!10!white, rotate=\thetau] (Ku) at ($(actumid) + (0, -1.2)$) {$K_{F}$};
|
|
\draw[->, draw=colorblue] ($(au) + (-0.1, -0.5)$) |- (Ku.east) node[below right, rotate=\thetau]{$f_{u}$};
|
|
\draw[->, draw=colorblue] (Ku.north) -- ($(actumid) + (0, -0.1)$) node[below left, rotate=\thetau]{$F_u$};
|
|
|
|
\node[color=colorblue, block={0.8cm}{0.6cm}, fill=colorblue!10!white, rotate=\thetau] (Kv) at ($(actvmid) + (1.2, 0)$) {$K_{F}$};
|
|
\draw[->, draw=colorblue] ($(av) + (0.5, -0.1)$) -| (Kv.north) node[above right, rotate=\thetau]{$f_{v}$};
|
|
\draw[->, draw=colorblue] (Kv.west) -- ($(actvmid) + (0.1, 0)$) node[below right, rotate=\thetau]{$F_v$};
|
|
\end{scope}
|
|
|
|
% Inertial Frame
|
|
\draw[->] (-4, -4) -- ++(2, 0) node[below]{$\vec{i}_x$};
|
|
\draw[->] (-4, -4) -- ++(0, 2) node[left]{$\vec{i}_y$};
|
|
\draw[fill, color=black] (-4, -4) circle (0.06);
|
|
\node[draw, circle, inner sep=0pt, minimum size=0.3cm, label=left:$\vec{i}_z$] at (-4, -4){};
|
|
|
|
\node[draw, circle, inner sep=0pt, minimum size=0.3cm] at (0, 0){};
|
|
\draw[->] (0, 0) node[above left, rotate=\thetau]{$\vec{i}_w$} -- ++(\thetau:2) node[above, rotate=\thetau]{$\vec{i}_u$};
|
|
\draw[->] (0, 0) -- ++(\thetau+90:2) node[left, rotate=\thetau]{$\vec{i}_v$};
|
|
\draw[dashed] (0, 0) -- ++(2, 0);
|
|
\draw[] (1.5, 0) arc (0:\thetau:1.5) node[midway, right]{$\theta$};
|
|
\node[] at (0,0) {$\bullet$};
|
|
|
|
\draw[->] (3.5, 0) arc (0:40:3.5) node[midway, left]{$\Omega$};
|
|
\end{tikzpicture}
|
|
#+end_src
|
|
|
|
#+begin_src latex :file rotating_iff_diagram.pdf
|
|
\tikzset{block/.default={0.8cm}{0.8cm}}
|
|
\tikzset{addb/.append style={scale=0.7}}
|
|
\tikzset{node distance=0.6}
|
|
|
|
\begin{tikzpicture}
|
|
\node[block={1.8cm}{2.2cm}] (G) {$\bm{G}_f$};
|
|
|
|
% Inputs of the controllers
|
|
\coordinate[] (output1) at ($(G.south east)!0.75!(G.north east)$);
|
|
\coordinate[] (output2) at ($(G.south east)!0.25!(G.north east)$);
|
|
\coordinate[] (input1) at ($(G.south west)!0.75!(G.north west)$);
|
|
\coordinate[] (input2) at ($(G.south west)!0.25!(G.north west)$);
|
|
|
|
\node[block, left=1.8 of input1] (K1) {$g/s$};
|
|
\node[block] (K2) at ($(K1.east|-input2)+(0.6, 0)$) {$g/s$};
|
|
|
|
% Connections and labels
|
|
\draw[->] (K1.east) -- (input1)node[above left]{$F_u$};
|
|
\draw[->] (K2.east) -- (input2)node[above left]{$F_v$};
|
|
|
|
\draw[->] (output1) -- ++(0.8, 0) node[above left]{$f_u$};
|
|
\draw[->] (output2) -- ++(0.8, 0) node[above left]{$f_v$};
|
|
|
|
\draw[->] ($(output1)+(0.2, 0)$)node[branch]{} -- ++(0, 1.2) -| ($(K1.west) + (-0.8, 0)$)coordinate(start) -- (K1.west);
|
|
\draw[->] ($(output2)+(0.2, 0)$)node[branch]{} -- ++(0, -1.2) -| (start|-K2) -- (K2.west);
|
|
|
|
\begin{scope}[on background layer]
|
|
\node[fit={(K1.north west) (K2.south east)}, inner sep=6pt, draw, dashed, fill=black!20!white] (K) {};
|
|
\node[below left] at (K.north east) {$\bm{K}_F$};
|
|
\end{scope}
|
|
\end{tikzpicture}
|
|
#+end_src
|
|
|
|
#+name: fig:rotating_iff_pure_int
|
|
#+caption: Integral Force Feedback applied to the suspended rotating platform. The damper $c$ in (\subref{fig:rotating_3dof_model_schematic_iff}) is omitted for readability.
|
|
#+attr_latex: :options [htbp]
|
|
#+begin_figure
|
|
#+attr_latex: :caption \subcaption{\label{fig:rotating_3dof_model_schematic_iff}System with added Force Sensor in series with the actuators}
|
|
#+attr_latex: :options {0.49\textwidth}
|
|
#+begin_subfigure
|
|
#+attr_latex: :width 0.95\linewidth
|
|
[[file:figs/rotating_3dof_model_schematic_iff.png]]
|
|
#+end_subfigure
|
|
#+attr_latex: :caption \subcaption{\label{fig:rotating_iff_diagram}Control diagram}
|
|
#+attr_latex: :options {0.49\textwidth}
|
|
#+begin_subfigure
|
|
#+attr_latex: :scale 1
|
|
[[file:figs/rotating_iff_diagram.png]]
|
|
#+end_subfigure
|
|
#+end_figure
|
|
|
|
The forces $\begin{bmatrix}f_u & f_v\end{bmatrix}$ measured by the two force sensors represented in Figure ref:fig:rotating_3dof_model_schematic_iff are described by equation eqref:eq:rotating_measured_force.
|
|
|
|
\begin{equation}\label{eq:rotating_measured_force}
|
|
\begin{bmatrix} f_{u} \\ f_{v} \end{bmatrix} =
|
|
\begin{bmatrix} F_u \\ F_v \end{bmatrix} - (c s + k)
|
|
\begin{bmatrix} d_u \\ d_v \end{bmatrix}
|
|
\end{equation}
|
|
|
|
The transfer function matrix $\mathbf{G}_{f}$ from actuator forces to measured forces in equation eqref:eq:rotating_Gf_mimo_tf can be obtained by inserting equation eqref:eq:rotating_Gd_w0_xi_k into equation eqref:eq:rotating_measured_force.
|
|
Its elements are shown in equation eqref:eq:rotating_Gf.
|
|
|
|
\begin{equation}\label{eq:rotating_Gf_mimo_tf}
|
|
\begin{bmatrix} f_{u} \\ f_{v} \end{bmatrix} = \mathbf{G}_{f} \begin{bmatrix} F_u \\ F_v \end{bmatrix}
|
|
\end{equation}
|
|
|
|
\begin{subequations}\label{eq:rotating_Gf}
|
|
\begin{align}
|
|
\mathbf{G}_{f}(1,1) &= \mathbf{G}_{f}(2,2) = \frac{\left( \frac{s^2}{{\omega_0}^2} - \frac{\Omega^2}{{\omega_0}^2} \right) \left( \frac{s^2}{{\omega_0}^2} + 2 \xi \frac{s}{\omega_0} + 1 - \frac{{\Omega}^2}{{\omega_0}^2} \right) + \left( 2 \frac{\Omega}{\omega_0} \frac{s}{\omega_0} \right)^2}{\left( \frac{s^2}{{\omega_0}^2} + 2 \xi \frac{s}{\omega_0} + 1 - \frac{{\Omega}^2}{{\omega_0}^2} \right)^2 + \left( 2 \frac{\Omega}{\omega_0} \frac{s}{\omega_0} \right)^2} \label{eq:rotating_Gf_diag_tf} \\
|
|
\mathbf{G}_{f}(1,2) &= -\mathbf{G}_{f}(2,1) = \frac{- \left( 2 \xi \frac{s}{\omega_0} + 1 \right) \left( 2 \frac{\Omega}{\omega_0} \frac{s}{\omega_0} \right)}{\left( \frac{s^2}{{\omega_0}^2} + 2 \xi \frac{s}{\omega_0} + 1 - \frac{{\Omega}^2}{{\omega_0}^2} \right)^2 + \left( 2 \frac{\Omega}{\omega_0} \frac{s}{\omega_0} \right)^2} \label{eq:rotating_Gf_off_diag_tf}
|
|
\end{align}
|
|
\end{subequations}
|
|
|
|
The zeros of the diagonal terms of $\mathbf{G}_f$ in equation eqref:eq:rotating_Gf_diag_tf are computed, and neglecting the damping for simplicity, two complex conjugated zeros $z_{c}$ eqref:eq:rotating_iff_zero_cc, and two real zeros $z_{r}$ eqref:eq:rotating_iff_zero_real are obtained.
|
|
|
|
\begin{subequations}
|
|
\begin{align}
|
|
z_c &= \pm j \omega_0 \sqrt{\frac{1}{2} \sqrt{8 \frac{\Omega^2}{{\omega_0}^2} + 1} + \frac{\Omega^2}{{\omega_0}^2} + \frac{1}{2} } \label{eq:rotating_iff_zero_cc} \\
|
|
z_r &= \pm \omega_0 \sqrt{\frac{1}{2} \sqrt{8 \frac{\Omega^2}{{\omega_0}^2} + 1} - \frac{\Omega^2}{{\omega_0}^2} - \frac{1}{2} } \label{eq:rotating_iff_zero_real}
|
|
\end{align}
|
|
\end{subequations}
|
|
|
|
It is interesting to see that the frequency of the pair of complex conjugate zeros $z_c$ in equation eqref:eq:rotating_iff_zero_cc always lies between the frequency of the two pairs of complex conjugate poles $p_{-}$ and $p_{+}$ in equation eqref:eq:rotating_pole_values.
|
|
This is what usually gives the unconditional stability of IFF when collocated force sensors are used.
|
|
|
|
However, for non-null rotational speeds, the two real zeros $z_r$ in equation eqref:eq:rotating_iff_zero_real are inducing a /non-minimum phase behavior/.
|
|
This can be seen in the Bode plot of the diagonal terms (Figure ref:fig:rotating_iff_bode_plot_effect_rot) where the low-frequency gain is no longer zero while the phase stays at $\SI{180}{\degree}$.
|
|
|
|
The low-frequency gain of $\mathbf{G}_f$ increases with the rotational speed $\Omega$ as shown in equation eqref:eq:rotating_low_freq_gain_iff_plan.
|
|
This can be explained as follows: a constant actuator force $F_u$ induces a small displacement of the mass $d_u = \frac{F_u}{k - m\Omega^2}$ (Hooke's law considering the negative stiffness induced by the rotation).
|
|
This small displacement then increases the centrifugal force $m\Omega^2d_u = \frac{\Omega^2}{{\omega_0}^2 - \Omega^2} F_u$ which is then measured by the force sensors.
|
|
|
|
\begin{equation}\label{eq:rotating_low_freq_gain_iff_plan}
|
|
\lim_{\omega \to 0} \left| \mathbf{G}_f (j\omega) \right| = \begin{bmatrix}
|
|
\frac{\Omega^2}{{\omega_0}^2 - \Omega^2} & 0 \\
|
|
0 & \frac{\Omega^2}{{\omega_0}^2 - \Omega^2}
|
|
\end{bmatrix}
|
|
\end{equation}
|
|
|
|
** Effect of rotation speed on IFF plant dynamics
|
|
The transfer functions from actuator forces $[F_u,\ F_v]$ to the measured force sensors $[f_u,\ f_v]$ are identified for several rotating velocities and are shown in Figure ref:fig:rotating_iff_bode_plot_effect_rot.
|
|
As expected from the derived equations of motion:
|
|
- when $\Omega < \omega_0$: the low-frequency gain is no longer zero and two (non-minimum phase) real zeros appear at low-frequencies.
|
|
The low-frequency gain increases with $\Omega$.
|
|
A pair of (minimum phase) complex conjugate zeros appears between the two complex conjugate poles, which are split further apart as $\Omega$ increases.
|
|
- when $\omega_0 < \Omega$: the low-frequency pole becomes unstable.
|
|
|
|
#+begin_src matlab :results none
|
|
%% Bode plot of the direct and coupling term for Integral Force Feedback - Effect of rotation
|
|
freqs = logspace(-2, 1, 1000);
|
|
|
|
Wz_i = [1,3,4];
|
|
|
|
figure;
|
|
tiledlayout(3, 1, 'TileSpacing', 'Compact', 'Padding', 'None');
|
|
|
|
% Magnitude
|
|
ax1 = nexttile([2, 1]);
|
|
hold on;
|
|
for i = 1:length(Wz_i)
|
|
plot(freqs, abs(squeeze(freqresp(Gs{Wz_i(i)}('fu', 'Fu'), freqs, 'rad/s'))), '-', 'color', colors(i,:), ...
|
|
'DisplayName', sprintf('$\\Omega = %.1f \\omega_0 $', Wzs(Wz_i(i))),'MarkerSize',8);
|
|
end
|
|
hold off;
|
|
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
|
|
set(gca, 'XTickLabel',[]); ylabel('Magnitude [N/N]');
|
|
ylim([1e-3, 1e2]);
|
|
leg = legend('location', 'northwest', 'FontSize', 8);
|
|
|
|
ax2 = nexttile;
|
|
hold on;
|
|
for i = 1:length(Wz_i)
|
|
plot(freqs, 180/pi*angle(squeeze(freqresp(Gs{Wz_i(i)}('fu', 'Fu'), freqs, 'rad/s'))), '-', 'color', colors(i,:))
|
|
end
|
|
hold off;
|
|
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'lin');
|
|
xlabel('Frequency [rad/s]'); ylabel('Phase [deg]');
|
|
yticks(-180:90:180);
|
|
ylim([0 180]);
|
|
xticks([1e-2,1e-1,1,1e1])
|
|
xticklabels({'$0.01 \omega_0$', '$0.1 \omega_0$', '$\omega_0$', '$10 \omega_0$'})
|
|
|
|
linkaxes([ax1,ax2],'x');
|
|
xlim([freqs(1), freqs(end)]);
|
|
#+end_src
|
|
|
|
#+begin_src matlab :tangle no :exports results :results file none
|
|
exportFig('figs/rotating_iff_bode_plot_effect_rot_direct.pdf', 'width', 'half', 'height', 600);
|
|
#+end_src
|
|
|
|
#+name: fig:rotating_iff_bode_plot_effect_rot
|
|
#+caption: Effect of the rotation velocity on the bode plot of the direct terms (\subref{fig:rotating_iff_bode_plot_effect_rot_direct}) and on the IFF root locus (\subref{fig:rotating_root_locus_iff_pure_int})
|
|
#+attr_latex: :options [htbp]
|
|
#+begin_figure
|
|
#+attr_latex: :caption \subcaption{\label{fig:rotating_iff_bode_plot_effect_rot_direct}Direct terms: $d_u/F_u$, $d_v/F_v$}
|
|
#+attr_latex: :options {0.49\textwidth}
|
|
#+begin_subfigure
|
|
#+attr_latex: :width 0.95\linewidth
|
|
[[file:figs/rotating_iff_bode_plot_effect_rot_direct.png]]
|
|
#+end_subfigure
|
|
#+attr_latex: :caption \subcaption{\label{fig:rotating_root_locus_iff_pure_int}Root Locus}
|
|
#+attr_latex: :options {0.49\textwidth}
|
|
#+begin_subfigure
|
|
#+attr_latex: :scale 1
|
|
[[file:figs/rotating_root_locus_iff_pure_int.png]]
|
|
#+end_subfigure
|
|
#+end_figure
|
|
|
|
** Decentralized Integral Force Feedback
|
|
The control diagram for decentralized acrshort:iff is shown in Figure ref:fig:rotating_iff_diagram.
|
|
The decentralized acrshort:iff controller $\bm{K}_F$ corresponds to a diagonal controller with integrators eqref:eq:rotating_Kf_pure_int.
|
|
|
|
\begin{equation} \label{eq:rotating_Kf_pure_int}
|
|
\begin{aligned}
|
|
\mathbf{K}_{F}(s) &= \begin{bmatrix} K_{F}(s) & 0 \\ 0 & K_{F}(s) \end{bmatrix} \\
|
|
K_{F}(s) &= g \cdot \frac{1}{s}
|
|
\end{aligned}
|
|
\end{equation}
|
|
|
|
To determine how the acrshort:iff controller affects the poles of the closed-loop system, a Root Locus plot (Figure ref:fig:rotating_root_locus_iff_pure_int) is constructed as follows: the poles of the closed-loop system are drawn in the complex plane as the controller gain $g$ varies from $0$ to $\infty$ for the two controllers $K_{F}$ simultaneously.
|
|
As explained in cite:preumont08_trans_zeros_struc_contr_with,skogestad07_multiv_feedb_contr, the closed-loop poles start at the open-loop poles (shown by $\tikz[baseline=-0.6ex] \node[cross out, draw=black, minimum size=1ex, line width=2pt, inner sep=0pt, outer sep=0pt] at (0, 0){};$) for $g = 0$ and coincide with the transmission zeros (shown by $\tikz[baseline=-0.6ex] \draw[line width=2pt, inner sep=0pt, outer sep=0pt] (0,0) circle[radius=3pt];$) as $g \to \infty$.
|
|
|
|
Whereas collocated IFF is usually associated with unconditional stability cite:preumont91_activ, this property is lost due to gyroscopic effects as soon as the rotation velocity becomes non-null.
|
|
This can be seen in the Root Locus plot (Figure ref:fig:rotating_root_locus_iff_pure_int) where poles corresponding to the controller are bound to the right half plane implying closed-loop system instability.
|
|
Physically, this can be explained as follows: at low frequencies, the loop gain is huge due to the pure integrator in $K_{F}$ and the finite gain of the plant (Figure ref:fig:rotating_iff_bode_plot_effect_rot).
|
|
The control system is thus cancels the spring forces, which makes the suspended platform not capable to hold the payload against centrifugal forces, hence the instability.
|
|
|
|
#+begin_src matlab
|
|
%% Root Locus for the Decentralized Integral Force Feedback controller
|
|
Kiff = 1/s*eye(2);
|
|
|
|
gains = logspace(-2, 4, 300);
|
|
Wz_i = [1,3,4];
|
|
|
|
figure;
|
|
hold on;
|
|
for i = 1:length(Wz_i)
|
|
plot(real(pole(Gs{Wz_i(i)}({'fu', 'fv'}, {'Fu', 'Fv'})*Kiff)), imag(pole(Gs{Wz_i(i)}({'fu', 'fv'}, {'Fu', 'Fv'})*Kiff)), 'x', 'color', colors(i,:), ...
|
|
'DisplayName', sprintf('$\\Omega = %.1f \\omega_0 $', Wzs(Wz_i(i))),'MarkerSize',8);
|
|
plot(real(tzero(Gs{Wz_i(i)}({'fu', 'fv'}, {'Fu', 'Fv'})*Kiff)), imag(tzero(Gs{Wz_i(i)}({'fu', 'fv'}, {'Fu', 'Fv'})*Kiff)), 'o', 'color', colors(i,:), ...
|
|
'HandleVisibility', 'off','MarkerSize',8);
|
|
for g = gains
|
|
cl_poles = pole(feedback(Gs{Wz_i(i)}({'fu', 'fv'}, {'Fu', 'Fv'}), g*Kiff, -1));
|
|
plot(real(cl_poles), imag(cl_poles), '.', 'color', colors(i,:), ...
|
|
'HandleVisibility', 'off','MarkerSize',4);
|
|
end
|
|
end
|
|
hold off;
|
|
axis square;
|
|
xlim([-1.8, 0.2]); ylim([0, 2]);
|
|
xticks([-1, 0])
|
|
xticklabels({'-$\omega_0$', '$0$'})
|
|
yticks([0, 1, 2])
|
|
yticklabels({'$0$', '$\omega_0$', '$2 \omega_0$'})
|
|
|
|
xlabel('Real Part'); ylabel('Imaginary Part');
|
|
leg = legend('location', 'northwest', 'FontSize', 8);
|
|
leg.ItemTokenSize(1) = 8;
|
|
#+end_src
|
|
|
|
#+begin_src matlab :tangle no :exports results :results file none
|
|
exportFig('figs/rotating_root_locus_iff_pure_int.pdf', 'width', 600, 'height', 600);
|
|
#+end_src
|
|
|
|
* Integral Force Feedback with a High-Pass Filter
|
|
:PROPERTIES:
|
|
:header-args:matlab+: :tangle matlab/rotating_3_iff_hpf.m
|
|
:END:
|
|
<<sec:rotating_iff_pseudo_int>>
|
|
|
|
** Introduction :ignore:
|
|
As explained in the previous section, the instability of the IFF controller applied to the rotating system is due to the high gain of the integrator at low-frequency.
|
|
To limit the low-frequency controller gain, a acrfull:hpf can be added to the controller, as shown in equation eqref:eq:rotating_iff_lhf.
|
|
This is equivalent to slightly shifting the controller pole to the left along the real axis.
|
|
This modification of the IFF controller is typically performed to avoid saturation associated with the pure integrator cite:preumont91_activ,marneffe07_activ_passiv_vibrat_isolat_dampin_shunt_trans.
|
|
This is however not the reason why this high-pass filter is added here.
|
|
|
|
\begin{equation}\label{eq:rotating_iff_lhf}
|
|
\boxed{K_{F}(s) = g \cdot \frac{1}{s} \cdot \underbrace{\frac{s/\omega_i}{1 + s/\omega_i}}_{\text{HPF}} = g \cdot \frac{1}{s + \omega_i}}
|
|
\end{equation}
|
|
|
|
** Matlab Init :noexport:ignore:
|
|
#+begin_src matlab :tangle no :results silent :noweb yes :var current_dir=(file-name-directory buffer-file-name)
|
|
<<matlab-dir>>
|
|
#+end_src
|
|
|
|
#+begin_src matlab :results silent :noweb yes
|
|
<<matlab-init>>
|
|
#+end_src
|
|
|
|
#+begin_src matlab :tangle no :noweb yes
|
|
<<m-init-path>>
|
|
#+end_src
|
|
|
|
#+begin_src matlab :eval no :noweb yes
|
|
<<m-init-path-tangle>>
|
|
#+end_src
|
|
|
|
#+begin_src matlab :noweb yes
|
|
<<m-init-other>>
|
|
#+end_src
|
|
|
|
#+begin_src matlab
|
|
%% Simscape model name
|
|
mdl = 'rotating_model';
|
|
#+end_src
|
|
|
|
#+begin_src matlab
|
|
%% Load "Generic" system dynamics
|
|
load('rotating_generic_plants.mat', 'Gs', 'Wzs');
|
|
#+end_src
|
|
|
|
** Modified Integral Force Feedback Controller
|
|
The Integral Force Feedback Controller is modified such that instead of using pure integrators, pseudo integrators (i.e. low pass filters) are used eqref:eq:rotating_iff_lhf where $\omega_i$ characterize the frequency down to which the signal is integrated.
|
|
The loop gains ($K_F(s)$ times the direct dynamics $f_u/F_u$) with and without the added HPF are shown in Figure ref:fig:rotating_iff_modified_loop_gain.
|
|
The effect of the added HPF limits the low-frequency gain to finite values as expected.
|
|
|
|
The Root Locus plots for the decentralized acrshort:iff with and without the acrshort:hpf are displayed in Figure ref:fig:rotating_iff_root_locus_hpf_large.
|
|
With the added acrshort:hpf, the poles of the closed-loop system are shown to be stable up to some value of the gain $g_\text{max}$ given by equation eqref:eq:rotating_gmax_iff_hpf.
|
|
It is interesting to note that $g_{\text{max}}$ also corresponds to the controller gain at which the low-frequency loop gain reaches one (for instance the gain $g$ can be increased by a factor $5$ in Figure ref:fig:rotating_iff_modified_loop_gain before the system becomes unstable).
|
|
|
|
\begin{equation}\label{eq:rotating_gmax_iff_hpf}
|
|
\boxed{g_{\text{max}} = \omega_i \left( \frac{{\omega_0}^2}{\Omega^2} - 1 \right)}
|
|
\end{equation}
|
|
|
|
#+begin_src matlab
|
|
%% Modified IFF - parameters
|
|
g = 2; % Controller gain
|
|
wi = 0.1; % HPF Cut-Off frequency [rad/s]
|
|
|
|
Kiff = (g/s)*eye(2); % Pure IFF
|
|
Kiff_hpf = (g/(wi+s))*eye(2); % IFF with added HPF
|
|
#+end_src
|
|
|
|
#+begin_src matlab :results none
|
|
%% Loop gain for the IFF with pure integrator and modified IFF with added high-pass filter
|
|
freqs = logspace(-2, 1, 1000);
|
|
Wz_i = 2;
|
|
|
|
figure;
|
|
tiledlayout(3, 1, 'TileSpacing', 'Compact', 'Padding', 'None');
|
|
|
|
% Magnitude
|
|
ax1 = nexttile([2, 1]);
|
|
hold on;
|
|
plot(freqs, abs(squeeze(freqresp(Gs{Wz_i}('fu', 'Fu')*Kiff(1,1), freqs, 'rad/s'))))
|
|
plot(freqs, abs(squeeze(freqresp(Gs{Wz_i}('fu', 'Fu')*Kiff_hpf(1,1), freqs, 'rad/s'))))
|
|
hold off;
|
|
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
|
|
set(gca, 'XTickLabel',[]); ylabel('Loop Gain');
|
|
|
|
% Phase
|
|
ax2 = nexttile;
|
|
hold on;
|
|
plot(freqs, 180/pi*angle(squeeze(freqresp(Gs{Wz_i}('fu', 'Fu')*Kiff(1,1), freqs, 'rad/s'))), 'DisplayName', 'IFF')
|
|
plot(freqs, 180/pi*angle(squeeze(freqresp(Gs{Wz_i}('fu', 'Fu')*Kiff_hpf(1,1), freqs, 'rad/s'))), 'DisplayName', 'IFF,HPF')
|
|
hold off;
|
|
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'lin');
|
|
xlabel('Frequency [rad/s]'); ylabel('Phase [deg]');
|
|
yticks(-180:90:180);
|
|
ylim([-90 180]);
|
|
xticks([1e-2,1e-1,1,1e1])
|
|
xticklabels({'', '$0.1 \omega_0$', '$\omega_0$', '$10 \omega_0$'})
|
|
leg = legend('location', 'southwest', 'FontSize', 8);
|
|
leg.ItemTokenSize(1) = 15;
|
|
|
|
linkaxes([ax1,ax2],'x');
|
|
xlim([freqs(1), freqs(end)]);
|
|
#+end_src
|
|
|
|
#+name: fig:rotating_iff_modified_loop_gain_root_locus
|
|
#+caption: Comparison of the IFF with pure integrator and modified IFF with added high-pass filter ($\Omega = 0.1\omega_0$). The loop gain is shown in (\subref{fig:rotating_iff_modified_loop_gain}) with $\omega_i = 0.1 \omega_0$ and $g = 2$. The root locus is shown in (\subref{fig:rotating_iff_root_locus_hpf_large})
|
|
#+attr_latex: :options [htbp]
|
|
#+begin_figure
|
|
#+attr_latex: :caption \subcaption{\label{fig:rotating_iff_modified_loop_gain}Loop gain}
|
|
#+attr_latex: :options {0.49\textwidth}
|
|
#+begin_subfigure
|
|
#+attr_latex: :scale 0.8
|
|
[[file:figs/rotating_iff_modified_loop_gain.png]]
|
|
#+end_subfigure
|
|
#+attr_latex: :caption \subcaption{\label{fig:rotating_iff_root_locus_hpf_large}Root Locus}
|
|
#+attr_latex: :options {0.49\textwidth}
|
|
#+begin_subfigure
|
|
#+attr_latex: :scale 0.8
|
|
[[file:figs/rotating_iff_root_locus_hpf_large.png]]
|
|
#+end_subfigure
|
|
#+end_figure
|
|
|
|
** Optimal IFF with HPF parameters $\omega_i$ and $g$
|
|
Two parameters can be tuned for the modified controller in equation eqref:eq:rotating_iff_lhf: the gain $g$ and the pole's location $\omega_i$.
|
|
The optimal values of $\omega_i$ and $g$ are considered here as the values for which the damping of all the closed-loop poles is simultaneously maximized.
|
|
|
|
To visualize how $\omega_i$ does affect the attainable damping, the Root Locus plots for several $\omega_i$ are displayed in Figure ref:fig:rotating_root_locus_iff_modified_effect_wi.
|
|
It is shown that even though small $\omega_i$ seem to allow more damping to be added to the suspension modes (see Root locus in Figure ref:fig:rotating_root_locus_iff_modified_effect_wi), the control gain $g$ may be limited to small values due to equation eqref:eq:rotating_gmax_iff_hpf.
|
|
To study this trade-off, the attainable closed-loop damping ratio $\xi_{\text{cl}}$ is computed as a function of $\omega_i/\omega_0$.
|
|
The gain $g_{\text{opt}}$ at which this maximum damping is obtained is also displayed and compared with the gain $g_{\text{max}}$ at which the system becomes unstable (Figure ref:fig:rotating_iff_hpf_optimal_gain).
|
|
|
|
For small values of $\omega_i$, the added damping is limited by the maximum allowed control gain $g_{\text{max}}$ (red curve and dashed red curve superimposed in Figure ref:fig:rotating_iff_hpf_optimal_gain) at which point the pole corresponding to the controller becomes unstable.
|
|
For larger values of $\omega_i$, the attainable damping ratio decreases as a function of $\omega_i$ as was predicted from the root locus plot of Figure ref:fig:rotating_iff_root_locus_hpf_large.
|
|
|
|
#+begin_src matlab
|
|
%% High-Pass Filter Cut-Off Frequency
|
|
wis = [0.01, 0.05, 0.1]; % [rad/s]
|
|
#+end_src
|
|
|
|
#+begin_src matlab :results none
|
|
%% Root Locus for the initial IFF and the modified IFF
|
|
gains = logspace(-2, 4, 200);
|
|
|
|
figure;
|
|
hold on;
|
|
for wi_i = 1:length(wis)
|
|
wi = wis(wi_i);
|
|
Kiff = (1/(wi+s))*eye(2);
|
|
L(wi_i) = plot(nan, nan, '.', 'color', colors(wi_i,:), 'DisplayName', sprintf('$\\omega_i = %.2f \\omega_0$', wi));
|
|
for g = gains
|
|
clpoles = pole(feedback(Gs{2}({'fu', 'fv'}, {'Fu', 'Fv'}), g*Kiff));
|
|
plot(real(clpoles), imag(clpoles), '.', 'color', colors(wi_i,:),'MarkerSize',4);
|
|
end
|
|
plot(real(pole(Gs{2}({'fu', 'fv'}, {'Fu', 'Fv'})*Kiff)), ...
|
|
imag(pole(Gs{2}({'fu', 'fv'}, {'Fu', 'Fv'})*Kiff)), ...
|
|
'x', 'color', colors(wi_i,:),'MarkerSize',8);
|
|
plot(real(tzero(Gs{2}({'fu', 'fv'}, {'Fu', 'Fv'})*Kiff)), ...
|
|
imag(tzero(Gs{2}({'fu', 'fv'}, {'Fu', 'Fv'})*Kiff)), ...
|
|
'o', 'color', colors(wi_i,:),'MarkerSize',8);
|
|
end
|
|
hold off;
|
|
axis equal;
|
|
xlim([-2.3, 0.1]); ylim([-1.2, 1.2]);
|
|
xticks([-2:1:2]); yticks([-2:1:2]);
|
|
leg = legend(L, 'location', 'southwest', 'FontSize', 8);
|
|
leg.ItemTokenSize(1) = 8;
|
|
xlabel('Real Part'); ylabel('Imaginary Part');
|
|
clear L
|
|
|
|
xlim([-1.25, 0.25]); ylim([-1.25, 1.25]);
|
|
xticks([-1, 0])
|
|
xticklabels({'$-\omega_0$', '$0$'})
|
|
yticks([-1, 0, 1])
|
|
yticklabels({'$-\omega_0$', '$0$', '$\omega_0$'})
|
|
ytickangle(90)
|
|
#+end_src
|
|
|
|
#+begin_src matlab
|
|
%% Compute the optimal control gain
|
|
wis = logspace(-2, 1, 100); % [rad/s]
|
|
|
|
opt_xi = zeros(1, length(wis)); % Optimal simultaneous damping
|
|
opt_gain = zeros(1, length(wis)); % Corresponding optimal gain
|
|
|
|
for wi_i = 1:length(wis)
|
|
wi = wis(wi_i);
|
|
Kiff = 1/(s + wi)*eye(2);
|
|
|
|
fun = @(g)computeSimultaneousDamping(g, Gs{2}({'fu', 'fv'}, {'Fu', 'Fv'}), Kiff);
|
|
|
|
[g_opt, xi_opt] = fminsearch(fun, 0.5*wi*((1/Wzs(2))^2 - 1));
|
|
opt_xi(wi_i) = 1/xi_opt;
|
|
opt_gain(wi_i) = g_opt;
|
|
end
|
|
#+end_src
|
|
|
|
#+begin_src matlab :results none
|
|
%% Attainable damping ratio as a function of wi/w0. Corresponding control gain g_opt and g_max are also shown
|
|
figure;
|
|
yyaxis left
|
|
plot(wis, opt_xi, '-', 'DisplayName', '$\xi_{cl}$');
|
|
set(gca, 'YScale', 'lin');
|
|
ylim([0,1]);
|
|
ylabel('Damping Ratio $\xi$');
|
|
|
|
yyaxis right
|
|
hold on;
|
|
plot(wis, opt_gain, '-', 'DisplayName', '$g_{opt}$');
|
|
plot(wis, wis*((1/Wzs(2))^2 - 1), '--', 'DisplayName', '$g_{max}$');
|
|
hold off;
|
|
set(gca, 'YScale', 'lin');
|
|
ylim([0,10]);
|
|
ylabel('Controller gain $g$');
|
|
|
|
xlabel('$\omega_i/\omega_0$');
|
|
set(gca, 'XScale', 'log');
|
|
legend('location', 'northeast', 'FontSize', 8);
|
|
#+end_src
|
|
|
|
#+begin_src matlab :tangle no :exports results :results file none
|
|
exportFig('figs/rotating_iff_hpf_optimal_gain.pdf', 'width', 'half', 'height', 450);
|
|
#+end_src
|
|
|
|
#+name: fig:rotating_iff_modified_effect_wi
|
|
#+caption: Root Locus for several high-pass filter cut-off frequency (\subref{fig:rotating_root_locus_iff_modified_effect_wi}). The achievable damping ratio decreases as $\omega_i$ increases, as confirmed in (\subref{fig:rotating_iff_hpf_optimal_gain})
|
|
#+attr_latex: :options [htbp]
|
|
#+begin_figure
|
|
#+attr_latex: :caption \subcaption{\label{fig:rotating_root_locus_iff_modified_effect_wi}Root Locus}
|
|
#+attr_latex: :options {0.49\textwidth}
|
|
#+begin_subfigure
|
|
#+attr_latex: :width 0.95\linewidth
|
|
[[file:figs/rotating_root_locus_iff_modified_effect_wi.png]]
|
|
#+end_subfigure
|
|
#+attr_latex: :caption \subcaption{\label{fig:rotating_iff_hpf_optimal_gain}Attainable damping ratio $\xi_\text{cl}$ as a function of $\omega_i/\omega_0$. Corresponding control gain $g_\text{opt}$ and $g_\text{max}$ are also shown}
|
|
#+attr_latex: :options {0.49\textwidth}
|
|
#+begin_subfigure
|
|
#+attr_latex: :width 0.95\linewidth
|
|
[[file:figs/rotating_iff_hpf_optimal_gain.png]]
|
|
#+end_subfigure
|
|
#+end_figure
|
|
|
|
** Obtained Damped Plant
|
|
To study how the parameter $\omega_i$ affects the damped plant, the obtained damped plants for several $\omega_i$ are compared in Figure ref:fig:rotating_iff_hpf_damped_plant_effect_wi_plant.
|
|
It can be seen that the low-frequency coupling increases as $\omega_i$ increases.
|
|
Therefore, there is a trade-off between achievable damping and added coupling when tuning $\omega_i$.
|
|
The same trade-off can be seen between achievable damping and loss of compliance at low-frequency (see Figure ref:fig:rotating_iff_hpf_effect_wi_compliance).
|
|
|
|
#+begin_src matlab
|
|
%% Compute damped plant
|
|
wis = [0.03, 0.1, 0.5]; % [rad/s]
|
|
g = 2; % Gain
|
|
|
|
Gs_iff_hpf = {};
|
|
|
|
for i = 1:length(wis)
|
|
Kiff_hpf = (g/(wis(i)+s))*eye(2); % IFF with added HPF
|
|
Kiff_hpf.InputName = {'fu', 'fv'};
|
|
Kiff_hpf.OutputName = {'Fu', 'Fv'};
|
|
|
|
Gs_iff_hpf(i) = {feedback(Gs{2}, Kiff_hpf, 'name')};
|
|
end
|
|
#+end_src
|
|
|
|
#+begin_src matlab :exports none :results none
|
|
%% Effect of $\omega_i$ on the damped plant coupling
|
|
freqs = logspace(-2, 1, 1000);
|
|
|
|
figure;
|
|
tiledlayout(3, 1, 'TileSpacing', 'Compact', 'Padding', 'None');
|
|
|
|
% Magnitude
|
|
ax1 = nexttile([2, 1]);
|
|
hold on;
|
|
for i = 1:length(wis)
|
|
plot(freqs, abs(squeeze(freqresp(Gs_iff_hpf{i}('Du', 'Fu'), freqs, 'rad/s'))), '-', 'color', [colors(i,:)], ...
|
|
'DisplayName', sprintf('$d_u/F_u$, $\\omega_i = %.2f \\omega_0$', wis(i)))
|
|
plot(freqs, abs(squeeze(freqresp(Gs_iff_hpf{i}('Dv', 'Fu'), freqs, 'rad/s'))), '-', 'color', [colors(i,:), 0.5], ...
|
|
'DisplayName', sprintf('$d_v/F_u$, $\\omega_i = %.2f \\omega_0$', wis(i)))
|
|
end
|
|
hold off;
|
|
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
|
|
set(gca, 'XTickLabel',[]); ylabel('Magnitude [m/N]');
|
|
leg = legend('location', 'southwest', 'FontSize', 8, 'NumColumns', 1);
|
|
leg.ItemTokenSize(1) = 20;
|
|
|
|
ax2 = nexttile;
|
|
hold on;
|
|
for i = 1:length(wis)
|
|
plot(freqs, 180/pi*angle(squeeze(freqresp(Gs_iff_hpf{i}('Du', 'Fu'), freqs, 'rad/s'))), '-')
|
|
end
|
|
hold off;
|
|
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'lin');
|
|
xlabel('Frequency [rad/s]'); ylabel('Phase [deg]');
|
|
yticks(-180:90:180);
|
|
ylim([-180 0]);
|
|
xticks([1e-2,1e-1,1,1e1])
|
|
xticklabels({'$0.01 \omega_0$', '$0.1 \omega_0$', '$\omega_0$', '$10 \omega_0$'})
|
|
|
|
linkaxes([ax1,ax2],'x');
|
|
xlim([freqs(1), freqs(end)]);
|
|
#+end_src
|
|
|
|
#+begin_src matlab :tangle no :exports results :results file none
|
|
exportFig('figs/rotating_iff_hpf_damped_plant_effect_wi_plant.pdf', 'width', 'half', 'height', 600);
|
|
#+end_src
|
|
|
|
#+begin_src matlab :exports none :results none
|
|
%% Effect of $\omega_i$ on the obtained compliance
|
|
freqs = logspace(-2, 1, 1000);
|
|
|
|
figure;
|
|
tiledlayout(1, 1, 'TileSpacing', 'Compact', 'Padding', 'None');
|
|
|
|
% Magnitude
|
|
ax1 = nexttile();
|
|
hold on;
|
|
for i = 1:length(wis)
|
|
plot(freqs, abs(squeeze(freqresp(Gs_iff_hpf{i}('Du', 'Fdx'), freqs, 'rad/s'))), '-', 'color', [colors(i,:)], ...
|
|
'DisplayName', sprintf('$d_{x}/F_{dx}$, $\\omega_i = %.2f \\omega_0$', wis(i)))
|
|
end
|
|
plot(freqs, abs(squeeze(freqresp(Gs{2}('Du', 'Fdx'), freqs, 'rad/s'))), 'k--', ...
|
|
'DisplayName', '$d_{x}/F_{dx}$, OL')
|
|
hold off;
|
|
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
|
|
xlabel('Frequency [rad/s]'); ylabel('Compliance [m/N]');
|
|
leg = legend('location', 'southwest', 'FontSize', 8, 'NumColumns', 1);
|
|
leg.ItemTokenSize(1) = 20;
|
|
xticks([1e-2,1e-1,1,1e1])
|
|
xticklabels({'$0.01 \omega_0$', '$0.1 \omega_0$', '$\omega_0$', '$10 \omega_0$'})
|
|
#+end_src
|
|
|
|
#+begin_src matlab :tangle no :exports results :results file replace
|
|
exportFig('figs/rotating_iff_hpf_effect_wi_compliance.pdf', 'width', 'half', 'height', 600);
|
|
#+end_src
|
|
|
|
#+name: fig:rotating_iff_hpf_damped_plant_effect_wi
|
|
#+caption: Effect of $\omega_i$ on the damped plant coupling
|
|
#+attr_latex: :options [htbp]
|
|
#+begin_figure
|
|
#+attr_latex: :caption \subcaption{\label{fig:rotating_iff_hpf_damped_plant_effect_wi_plant}Obtained plants}
|
|
#+attr_latex: :options {0.49\textwidth}
|
|
#+begin_subfigure
|
|
#+attr_latex: :width 0.95\linewidth
|
|
[[file:figs/rotating_iff_hpf_damped_plant_effect_wi_plant.png]]
|
|
#+end_subfigure
|
|
#+attr_latex: :caption \subcaption{\label{fig:rotating_iff_hpf_effect_wi_compliance}Effect of $\omega_i$ on the compliance}
|
|
#+attr_latex: :options {0.49\textwidth}
|
|
#+begin_subfigure
|
|
#+attr_latex: :width 0.95\linewidth
|
|
[[file:figs/rotating_iff_hpf_effect_wi_compliance.png]]
|
|
#+end_subfigure
|
|
#+end_figure
|
|
|
|
* IFF with a stiffness in parallel with the force sensor
|
|
:PROPERTIES:
|
|
:header-args:matlab+: :tangle matlab/rotating_4_iff_kp.m
|
|
:END:
|
|
<<sec:rotating_iff_parallel_stiffness>>
|
|
|
|
** Introduction :ignore:
|
|
In this section it is proposed to add springs in parallel with the force sensors to counteract the negative stiffness induced by the gyroscopic effects.
|
|
Such springs are schematically shown in Figure ref:fig:rotating_3dof_model_schematic_iff_parallel_springs where $k_a$ is the stiffness of the actuator and $k_p$ the added stiffness in parallel with the actuator and force sensor.
|
|
|
|
#+begin_src latex :file rotating_3dof_model_schematic_iff_parallel_springs.pdf
|
|
\begin{tikzpicture}
|
|
% Angle
|
|
\def\thetau{25}
|
|
|
|
% Rotational Stage
|
|
\draw[fill=black!60!white] (0, 0) circle (4.3);
|
|
\draw[fill=black!40!white] (0, 0) circle (3.8);
|
|
|
|
% Label
|
|
\node[anchor=north west, rotate=\thetau] at (-2.5, 2.5) {\small Rotating Stage};
|
|
|
|
% Rotating Scope
|
|
\begin{scope}[rotate=\thetau]
|
|
% Rotating Frame
|
|
\draw[fill=black!20!white] (-2.6, -2.6) rectangle (2.6, 2.6);
|
|
% Label
|
|
\node[anchor=north west, rotate=\thetau] at (-2.6, 2.6) {\small Suspended Platform};
|
|
|
|
% Mass
|
|
\draw[fill=white] (-1, -1) rectangle (1, 1);
|
|
% Label
|
|
\node[anchor=south west, rotate=\thetau] at (-1, -1) {\small Payload};
|
|
|
|
% Attached Points
|
|
\draw[] (-1, 0) -- ++(-0.2, 0) coordinate(au);
|
|
\draw[] (0, -1) -- ++(0, -0.2) coordinate(av);
|
|
|
|
% Force Sensors
|
|
\draw[fill=white] ($(au) + (-0.2, -0.5)$) rectangle ($(au) + (0, 0.5)$);
|
|
\draw[] ($(au) + (-0.2, -0.5)$)coordinate(actu) -- ($(au) + (0, 0.5)$);
|
|
\draw[] ($(au) + (-0.2, 0.5)$)coordinate(ku) -- ($(au) + (0, -0.5)$);
|
|
\node[below=0.1, rotate=\thetau] at ($(au) + (-0.1, -0.5)$) {$f_{u}$};
|
|
|
|
\draw[fill=white] ($(av) + (-0.5, -0.2)$) rectangle ($(av) + (0.5, 0)$);
|
|
\draw[] ($(av) + ( 0.5, -0.2)$)coordinate(actv) -- ($(av) + (-0.5, 0)$);
|
|
\draw[] ($(av) + (-0.5, -0.2)$)coordinate(kv) -- ($(av) + ( 0.5, 0)$);
|
|
\node[right=0.1, rotate=\thetau] at ($(av) + (0.5, -0.1)$) {$f_{v}$};
|
|
|
|
% Spring and Actuator for U
|
|
\draw[actuator={0.6}{0.2}{black}] (actu) -- node[below=0.1, rotate=\thetau]{$F_u$} (actu-|-2.6,0);
|
|
\draw[spring=0.2] (ku) -- node[below=0.1, rotate=\thetau]{$k_a$} (ku-|-2.6,0);
|
|
\draw[spring=0.2,draw=colorred] (-1, 0.8) -- node[above=0.1, rotate=\thetau, color=colorred]{$k_p$} (-1, 0.8-|-2.6,0);
|
|
|
|
\draw[actuator={0.6}{0.2}{black}] (actv) -- node[right=0.1, rotate=\thetau]{$F_v$} (actv|-0,-2.6);
|
|
\draw[spring=0.2] (kv) -- node[right=0.1, rotate=\thetau]{$k_a$} (kv|-0,-2.6);
|
|
\draw[spring=0.2, draw=colorred] (-0.8, -1) -- node[left=0.1, rotate=\thetau, color=colorred]{$k_p$} (-0.8, -1|-0,-2.6);
|
|
\end{scope}
|
|
|
|
% Inertial Frame
|
|
\draw[->] (-4, -4) -- ++(2, 0) node[below]{$\vec{i}_x$};
|
|
\draw[->] (-4, -4) -- ++(0, 2) node[left]{$\vec{i}_y$};
|
|
\draw[fill, color=black] (-4, -4) circle (0.06);
|
|
\node[draw, circle, inner sep=0pt, minimum size=0.3cm, label=left:$\vec{i}_z$] at (-4, -4){};
|
|
|
|
\node[draw, circle, inner sep=0pt, minimum size=0.3cm] at (0, 0){};
|
|
\draw[->] (0, 0) node[above left, rotate=\thetau]{$\vec{i}_w$} -- ++(\thetau:2) node[above, rotate=\thetau]{$\vec{i}_u$};
|
|
\draw[->] (0, 0) -- ++(\thetau+90:2) node[left, rotate=\thetau]{$\vec{i}_v$};
|
|
\draw[dashed] (0, 0) -- ++(2, 0);
|
|
\draw[] (1.5, 0) arc (0:\thetau:1.5) node[midway, right]{$\theta$};
|
|
\node[] at (0,0) {$\bullet$};
|
|
|
|
\draw[->] (3.5, 0) arc (0:40:3.5) node[midway, left]{$\Omega$};
|
|
\end{tikzpicture}
|
|
#+end_src
|
|
|
|
#+name: fig:rotating_3dof_model_schematic_iff_parallel_springs
|
|
#+caption: Studied system with additional springs in parallel with the actuators and force sensors (shown in red)
|
|
#+attr_latex: :scale 0.8
|
|
#+RESULTS:
|
|
[[file:figs/rotating_3dof_model_schematic_iff_parallel_springs.png]]
|
|
|
|
** Matlab Init :noexport:ignore:
|
|
#+begin_src matlab :tangle no :results silent :noweb yes :var current_dir=(file-name-directory buffer-file-name)
|
|
<<matlab-dir>>
|
|
#+end_src
|
|
|
|
#+begin_src matlab :results silent :noweb yes
|
|
<<matlab-init>>
|
|
#+end_src
|
|
|
|
#+begin_src matlab :tangle no :noweb yes
|
|
<<m-init-path>>
|
|
#+end_src
|
|
|
|
#+begin_src matlab :eval no :noweb yes
|
|
<<m-init-path-tangle>>
|
|
#+end_src
|
|
|
|
#+begin_src matlab :noweb yes
|
|
<<m-init-other>>
|
|
#+end_src
|
|
|
|
#+begin_src matlab
|
|
%% Simscape model name
|
|
mdl = 'rotating_model';
|
|
#+end_src
|
|
|
|
#+begin_src matlab
|
|
%% Load "Generic" system dynamics
|
|
load('rotating_generic_plants.mat', 'Gs', 'Wzs');
|
|
#+end_src
|
|
|
|
** Equations
|
|
The forces measured by the two force sensors represented in Figure ref:fig:rotating_3dof_model_schematic_iff_parallel_springs are described by eqref:eq:rotating_measured_force_kp.
|
|
|
|
\begin{equation}\label{eq:rotating_measured_force_kp}
|
|
\begin{bmatrix} f_{u} \\ f_{v} \end{bmatrix} =
|
|
\begin{bmatrix} F_u \\ F_v \end{bmatrix} - (c s + k_a)
|
|
\begin{bmatrix} d_u \\ d_v \end{bmatrix}
|
|
\end{equation}
|
|
|
|
To keep the overall stiffness $k = k_a + k_p$ constant, thus not modifying the open-loop poles as $k_p$ is changed, a scalar parameter $\alpha$ ($0 \le \alpha < 1$) is defined to describe the fraction of the total stiffness in parallel with the actuator and force sensor as in eqref:eq:rotating_kp_alpha.
|
|
|
|
\begin{equation}\label{eq:rotating_kp_alpha}
|
|
k_p = \alpha k, \quad k_a = (1 - \alpha) k
|
|
\end{equation}
|
|
|
|
After the equations of motion are derived and transformed in the Laplace domain, the transfer function matrix $\mathbf{G}_k$ in Eq. eqref:eq:rotating_Gk_mimo_tf is computed.
|
|
Its elements are shown in Eqs. eqref:eq:rotating_Gk_diag and eqref:eq:rotating_Gk_off_diag.
|
|
|
|
\begin{equation}\label{eq:rotating_Gk_mimo_tf}
|
|
\begin{bmatrix} f_u \\ f_v \end{bmatrix} =
|
|
\mathbf{G}_k
|
|
\begin{bmatrix} F_u \\ F_v \end{bmatrix}
|
|
\end{equation}
|
|
|
|
\begin{subequations}\label{eq:rotating_Gk}
|
|
\begin{align}
|
|
\mathbf{G}_{k}(1,1) &= \mathbf{G}_{k}(2,2) = \frac{\big( \frac{s^2}{{\omega_0}^2} - \frac{\Omega^2}{{\omega_0}^2} + \alpha \big) \big( \frac{s^2}{{\omega_0}^2} + 2 \xi \frac{s}{\omega_0} + 1 - \frac{{\Omega}^2}{{\omega_0}^2} \big) + \big( 2 \frac{\Omega}{\omega_0} \frac{s}{\omega_0} \big)^2}{\big( \frac{s^2}{{\omega_0}^2} + 2 \xi \frac{s}{\omega_0} + 1 - \frac{{\Omega}^2}{{\omega_0}^2} \big)^2 + \big( 2 \frac{\Omega}{\omega_0} \frac{s}{\omega_0} \big)^2} \label{eq:rotating_Gk_diag} \\
|
|
\mathbf{G}_{k}(1,2) &= -\mathbf{G}_{k}(2,1) = \frac{- \left( 2 \xi \frac{s}{\omega_0} + 1 - \alpha \right) \left( 2 \frac{\Omega}{\omega_0} \frac{s}{\omega_0} \right)}{\left( \frac{s^2}{{\omega_0}^2} + 2 \xi \frac{s}{\omega_0} + 1 - \frac{{\Omega}^2}{{\omega_0}^2} \right)^2 + \left( 2 \frac{\Omega}{\omega_0} \frac{s}{\omega_0} \right)^2} \label{eq:rotating_Gk_off_diag}
|
|
\end{align}
|
|
\end{subequations}
|
|
|
|
Comparing $\mathbf{G}_k$ in eqref:eq:rotating_Gk with $\mathbf{G}_f$ in eqref:eq:rotating_Gf shows that while the poles of the system remain the same, the zeros of the diagonal terms change.
|
|
The two real zeros $z_r$ in eqref:eq:rotating_iff_zero_real that were inducing a non-minimum phase behavior are transformed into two complex conjugate zeros if the condition in eqref:eq:rotating_kp_cond_cc_zeros holds.
|
|
Thus, if the added /parallel stiffness/ $k_p$ is higher than the /negative stiffness/ induced by centrifugal forces $m \Omega^2$, the dynamics from the actuator to its collocated force sensor will show /minimum phase behavior/.
|
|
|
|
\begin{equation}\label{eq:rotating_kp_cond_cc_zeros}
|
|
\boxed{\alpha > \frac{\Omega^2}{{\omega_0}^2} \quad \Leftrightarrow \quad k_p > m \Omega^2}
|
|
\end{equation}
|
|
|
|
** Identify plant with parallel stiffnesses :noexport:
|
|
#+begin_src matlab
|
|
%% Tuv Stage
|
|
mn = 0.5; % Tuv mass [kg]
|
|
|
|
%% Sample
|
|
ms = 0.5; % Sample mass [kg]
|
|
|
|
%% General Configuration
|
|
model_config = struct();
|
|
model_config.controller = "open_loop"; % Default: Open-Loop
|
|
model_config.Tuv_type = "parallel_k"; % Default: 2DoF stage
|
|
#+end_src
|
|
|
|
#+begin_src matlab
|
|
%% Input/Output definition
|
|
clear io; io_i = 1;
|
|
io(io_i) = linio([mdl, '/controller'], 1, 'openinput'); io_i = io_i + 1; % [Fu, Fv]
|
|
io(io_i) = linio([mdl, '/fd'], 1, 'openinput'); io_i = io_i + 1; % [Fdu, Fdv]
|
|
io(io_i) = linio([mdl, '/translation_stage'], 1, 'openoutput'); io_i = io_i + 1; % [Fmu, Fmv]
|
|
io(io_i) = linio([mdl, '/translation_stage'], 2, 'openoutput'); io_i = io_i + 1; % [Du, Dv]
|
|
io(io_i) = linio([mdl, '/ext_metrology'], 1, 'openoutput'); io_i = io_i + 1; % [Dx, Dy]
|
|
#+end_src
|
|
|
|
** Effect of parallel stiffness on the IFF plant
|
|
The IFF plant (transfer function from $[F_u, F_v]$ to $[f_u, f_v]$) is identified without parallel stiffness $k_p = 0$, with a small parallel stiffness $k_p < m \Omega^2$ and with a large parallel stiffness $k_p > m \Omega^2$.
|
|
Bode plots of the obtained dynamics are shown in Figure ref:fig:rotating_iff_effect_kp.
|
|
The two real zeros for $k_p < m \Omega^2$ are transformed into two complex conjugate zeros for $k_p > m \Omega^2$.
|
|
In that case, the system shows alternating complex conjugate poles and zeros as what is the case in the non-rotating case.
|
|
|
|
Figure ref:fig:rotating_iff_kp_root_locus shows the Root Locus plots for $k_p = 0$, $k_p < m \Omega^2$ and $k_p > m \Omega^2$ when $K_F$ is a pure integrator, as shown in Eq. eqref:eq:rotating_Kf_pure_int.
|
|
It is shown that if the added stiffness is higher than the maximum negative stiffness, the poles of the closed-loop system are bounded on the (stable) left half-plane, and hence the unconditional stability of acrshort:iff is recovered.
|
|
|
|
#+begin_src matlab
|
|
Wz = 0.1; % The rotation speed [rad/s]
|
|
|
|
%% No parallel Stiffness
|
|
kp = 0; % Parallel Stiffness [N/m]
|
|
cp = 0.001*2*sqrt(kp*(mn+ms)); % Small parallel damping [N/(m/s)]
|
|
kn = 1 - kp; % Stiffness [N/m]
|
|
cn = 0.01*2*sqrt(kn*(mn+ms)); % Damping [N/(m/s)]
|
|
|
|
G_no_kp = linearize(mdl, io, 0);
|
|
G_no_kp.InputName = {'Fu', 'Fv', 'Fdx', 'Fdy'};
|
|
G_no_kp.OutputName = {'fu', 'fv', 'Du', 'Dv', 'Dx', 'Dy'};
|
|
|
|
%% Small parallel Stiffness
|
|
kp = 0.5*(mn+ms)*Wz^2; % Parallel Stiffness [N/m]
|
|
cp = 0.001*2*sqrt(kp*(mn+ms)); % Small parallel damping [N/(m/s)]
|
|
kn = 1 - kp; % Stiffness [N/m]
|
|
cn = 0.01*2*sqrt(kn*(mn+ms)); % Damping [N/(m/s)]
|
|
|
|
G_low_kp = linearize(mdl, io, 0);
|
|
G_low_kp.InputName = {'Fu', 'Fv', 'Fdx', 'Fdy'};
|
|
G_low_kp.OutputName = {'fu', 'fv', 'Du', 'Dv', 'Dx', 'Dy'};
|
|
|
|
%% Large parallel Stiffness
|
|
kp = 1.5*(mn+ms)*Wz^2; % Parallel Stiffness [N/m]
|
|
cp = 0.001*2*sqrt(kp*(mn+ms)); % Small parallel damping [N/(m/s)]
|
|
kn = 1 - kp; % Stiffness [N/m]
|
|
cn = 0.01*2*sqrt(kn*(mn+ms)); % Damping [N/(m/s)]
|
|
|
|
G_high_kp = linearize(mdl, io, 0);
|
|
G_high_kp.InputName = {'Fu', 'Fv', 'Fdx', 'Fdy'};
|
|
G_high_kp.OutputName = {'fu', 'fv', 'Du', 'Dv', 'Dx', 'Dy'};
|
|
#+end_src
|
|
|
|
#+begin_src matlab :results none
|
|
%% Effect of the parallel stiffness on the IFF plant
|
|
freqs = logspace(-2, 1, 1000);
|
|
|
|
figure;
|
|
tiledlayout(3, 1, 'TileSpacing', 'Compact', 'Padding', 'None');
|
|
|
|
% Magnitude
|
|
ax1 = nexttile([2, 1]);
|
|
hold on;
|
|
plot(freqs, abs(squeeze(freqresp(G_no_kp( 'fu', 'Fu'), freqs, 'rad/s'))), '-', ...
|
|
'DisplayName', '$k_p = 0$')
|
|
plot(freqs, abs(squeeze(freqresp(G_low_kp( 'fu', 'Fu'), freqs, 'rad/s'))), '-', ...
|
|
'DisplayName', '$k_p < m\Omega^2$')
|
|
plot(freqs, abs(squeeze(freqresp(G_high_kp('fu', 'Fu'), freqs, 'rad/s'))), '-', ...
|
|
'DisplayName', '$k_p > m\Omega^2$')
|
|
hold off;
|
|
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
|
|
set(gca, 'XTickLabel',[]); ylabel('Magnitude [N/N]');
|
|
ylim([1e-4, 5e1]);
|
|
legend('location', 'southeast', 'FontSize', 8);
|
|
|
|
% Phase
|
|
ax2 = nexttile;
|
|
hold on;
|
|
plot(freqs, 180/pi*angle(squeeze(freqresp(G_no_kp( 'fu', 'Fu'), freqs, 'rad/s'))), '-')
|
|
plot(freqs, 180/pi*angle(squeeze(freqresp(G_low_kp( 'fu', 'Fu'), freqs, 'rad/s'))), '-')
|
|
plot(freqs, 180/pi*angle(squeeze(freqresp(G_high_kp('fu', 'Fu'), freqs, 'rad/s'))), '-')
|
|
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'lin');
|
|
xlabel('Frequency [rad/s]'); ylabel('Phase [deg]');
|
|
yticks(-180:90:180);
|
|
ylim([0 180]);
|
|
hold off;
|
|
xticks([1e-2,1e-1,1,1e1])
|
|
xticklabels({'$0.01 \omega_0$', '$0.1 \omega_0$', '$\omega_0$', '$10 \omega_0$'})
|
|
|
|
linkaxes([ax1,ax2],'x');
|
|
xlim([freqs(1), freqs(end)]);
|
|
#+end_src
|
|
|
|
#+begin_src matlab :tangle no :exports results :results file replace
|
|
exportFig('figs/rotating_iff_effect_kp.pdf', 'width', 'half', 'height', 500);
|
|
#+end_src
|
|
|
|
#+begin_src matlab :results none
|
|
%% Root Locus for IFF without parallel spring, with small parallel spring and with large parallel spring
|
|
gains = logspace(-2, 2, 200);
|
|
|
|
figure;
|
|
hold on;
|
|
plot(real(pole(G_no_kp({'fu','fv'},{'Fu','Fv'})*(1/s))), imag(pole(G_no_kp({'fu','fv'},{'Fu','Fv'})*(1/s))), 'x', 'color', colors(1,:), ...
|
|
'DisplayName', '$k_p = 0$','MarkerSize',8);
|
|
plot(real(tzero(G_no_kp({'fu','fv'},{'Fu','Fv'})*(1/s))), imag(tzero(G_no_kp({'fu','fv'},{'Fu','Fv'})*(1/s))), 'o', 'color', colors(1,:), ...
|
|
'HandleVisibility', 'off','MarkerSize',8);
|
|
for g = gains
|
|
cl_poles = pole(feedback(G_no_kp({'fu','fv'},{'Fu','Fv'}), (g/s)*eye(2)));
|
|
plot(real(cl_poles), imag(cl_poles), '.', 'color', colors(1,:), ...
|
|
'HandleVisibility', 'off','MarkerSize',4);
|
|
end
|
|
|
|
plot(real(pole(G_low_kp({'fu','fv'},{'Fu','Fv'})*(1/s))), imag(pole(G_low_kp({'fu','fv'},{'Fu','Fv'})*(1/s))), 'x', 'color', colors(2,:), ...
|
|
'DisplayName', '$k_p < m\Omega^2$','MarkerSize',8);
|
|
plot(real(tzero(G_low_kp({'fu','fv'},{'Fu','Fv'})*(1/s))), imag(tzero(G_low_kp({'fu','fv'},{'Fu','Fv'})*(1/s))), 'o', 'color', colors(2,:), ...
|
|
'HandleVisibility', 'off','MarkerSize',8);
|
|
for g = gains
|
|
cl_poles = pole(feedback(G_low_kp({'fu','fv'},{'Fu','Fv'}), (g/s)*eye(2)));
|
|
plot(real(cl_poles), imag(cl_poles), '.', 'color', colors(2,:), ...
|
|
'HandleVisibility', 'off','MarkerSize',4);
|
|
end
|
|
|
|
plot(real(pole(G_high_kp({'fu','fv'},{'Fu','Fv'})*(1/s))), imag(pole(G_high_kp({'fu','fv'},{'Fu','Fv'})*(1/s))), 'x', 'color', colors(3,:), ...
|
|
'DisplayName', '$k_p > m\Omega^2$','MarkerSize',8);
|
|
plot(real(tzero(G_high_kp({'fu','fv'},{'Fu','Fv'})*(1/s))), imag(tzero(G_high_kp({'fu','fv'},{'Fu','Fv'})*(1/s))), 'o', 'color', colors(3,:), ...
|
|
'HandleVisibility', 'off','MarkerSize',8);
|
|
for g = gains
|
|
cl_poles = pole(feedback(G_high_kp({'fu','fv'},{'Fu','Fv'}), (g/s)*eye(2)));
|
|
plot(real(cl_poles), imag(cl_poles), '.', 'color', colors(3,:), ...
|
|
'HandleVisibility', 'off','MarkerSize',4);
|
|
end
|
|
hold off;
|
|
axis square;
|
|
xlim([-2.25, 0.25]); ylim([-1.25, 1.25]);
|
|
xticks([-2, -1, 0])
|
|
xticklabels({'$-2\omega_0$', '$-\omega_0$', '$0$'})
|
|
yticks([-1, 0, 1])
|
|
yticklabels({'$-\omega_0$', '$0$', '$\omega_0$'})
|
|
|
|
xlabel('Real Part'); ylabel('Imaginary Part');
|
|
leg = legend('location', 'northwest', 'FontSize', 8);
|
|
leg.ItemTokenSize(1) = 8;
|
|
#+end_src
|
|
|
|
#+name: fig:rotating_iff_plant_effect_kp
|
|
#+caption: Effect of parallel stiffness on the IFF plant
|
|
#+attr_latex: :options [htbp]
|
|
#+begin_figure
|
|
#+attr_latex: :caption \subcaption{\label{fig:rotating_iff_effect_kp}Bode plot of $G_{k}(1,1) = f_u/F_u$ without parallel spring, with parallel spring stiffness $k_p < m \Omega^2$ and $k_p > m \Omega^2$, $\Omega = 0.1 \omega_0$}
|
|
#+attr_latex: :options {0.55\linewidth}
|
|
#+begin_subfigure
|
|
#+attr_latex: :width 0.95\linewidth
|
|
[[file:figs/rotating_iff_effect_kp.png]]
|
|
#+end_subfigure
|
|
#+attr_latex: :caption \subcaption{\label{fig:rotating_iff_kp_root_locus}Root Locus for IFF without parallel spring, with small parallel spring and with large parallel spring}
|
|
#+attr_latex: :options {0.44\linewidth}
|
|
#+begin_subfigure
|
|
#+attr_latex: :width 0.95\linewidth
|
|
[[file:figs/rotating_iff_kp_root_locus.png]]
|
|
#+end_subfigure
|
|
#+end_figure
|
|
|
|
** Effect of $k_p$ on the attainable damping
|
|
Even though the parallel stiffness $k_p$ has no impact on the open-loop poles (as the overall stiffness $k$ is kept constant), it has a large impact on the transmission zeros.
|
|
Moreover, as the attainable damping is generally proportional to the distance between poles and zeros cite:preumont18_vibrat_contr_activ_struc_fourt_edition, the parallel stiffness $k_p$ is expected to have some impact on the attainable damping.
|
|
To study this effect, Root Locus plots for several parallel stiffnesses $k_p > m \Omega^2$ are shown in Figure ref:fig:rotating_iff_kp_root_locus_effect_kp.
|
|
The frequencies of the transmission zeros of the system increase with an increase in the parallel stiffness $k_p$ (thus getting closer to the poles), and the associated attainable damping is reduced.
|
|
Therefore, even though the parallel stiffness $k_p$ should be larger than $m \Omega^2$ for stability reasons, it should not be taken too large as this would limit the attainable damping.
|
|
This is confirmed by the Figure ref:fig:rotating_iff_kp_optimal_gain where the attainable closed-loop damping ratio $\xi_{\text{cl}}$ and the associated optimal control gain $g_\text{opt}$ are computed as a function of the parallel stiffness.
|
|
|
|
#+begin_src matlab
|
|
%% Tested parallel stiffnesses
|
|
kps = [2, 20, 40]*(mn + ms)*Wz^2;
|
|
#+end_src
|
|
|
|
#+begin_src matlab :results none
|
|
%% Root Locus: Effect of the parallel stiffness on the attainable damping
|
|
gains = logspace(-2, 4, 500);
|
|
|
|
figure;
|
|
hold on;
|
|
for kp_i = 1:length(kps)
|
|
kp = kps(kp_i); % Parallel Stiffness [N/m]
|
|
cp = 0.001*2*sqrt(kp*(mn+ms)); % Small parallel damping [N/(m/s)]
|
|
kn = 1 - kp; % Stiffness [N/m]
|
|
cn = 0.01*2*sqrt(kn*(mn+ms)); % Damping [N/(m/s)]
|
|
|
|
% Identify dynamics
|
|
G = linearize(mdl, io, 0);
|
|
G.InputName = {'Fu', 'Fv', 'Fdx', 'Fdy'};
|
|
G.OutputName = {'fu', 'fv', 'Du', 'Dv', 'Dx', 'Dy'};
|
|
|
|
plot(real(pole(G({'fu', 'fv'}, {'Fu', 'Fv'})*(1/s*eye(2)))), imag(pole(G({'fu', 'fv'}, {'Fu', 'Fv'})*(1/s*eye(2)))), 'x', 'color', colors(kp_i,:), ...
|
|
'DisplayName', sprintf('$k_p = %.1f m \\Omega^2$', kp/((mn+ms)*Wz^2)),'MarkerSize',8);
|
|
plot(real(tzero(G({'fu', 'fv'}, {'Fu', 'Fv'})*(1/s*eye(2)))), imag(tzero(G({'fu', 'fv'}, {'Fu', 'Fv'})*(1/s*eye(2)))), 'o', 'color', colors(kp_i,:), ...
|
|
'HandleVisibility', 'off','MarkerSize',8);
|
|
for g = gains
|
|
cl_poles = pole(feedback(G({'fu', 'fv'}, {'Fu', 'Fv'}), (g/s)*eye(2)));
|
|
plot(real(cl_poles), imag(cl_poles), '.', 'color', colors(kp_i,:),'MarkerSize',4, ...
|
|
'HandleVisibility', 'off');
|
|
end
|
|
end
|
|
hold off;
|
|
axis square;
|
|
% xlim([-1.15, 0.05]); ylim([0, 1.2]);
|
|
xlim([-2.25, 0.25]); ylim([-1.25, 1.25]);
|
|
xticks([-2, -1, 0])
|
|
xticklabels({'$-2\omega_0$', '$-\omega_0$', '$0$'})
|
|
yticks([-1, 0, 1])
|
|
yticklabels({'$-\omega_0$', '$0$', '$\omega_0$'})
|
|
|
|
xlabel('Real Part'); ylabel('Imaginary Part');
|
|
leg = legend('location', 'northwest', 'FontSize', 8);
|
|
leg.ItemTokenSize(1) = 12;
|
|
#+end_src
|
|
|
|
#+begin_src matlab
|
|
%% Computes the optimal parameters and attainable simultaneous damping
|
|
alphas = logspace(-2, 0, 100);
|
|
alphas(end) = []; % Remove last point
|
|
|
|
opt_xi = zeros(1, length(alphas)); % Optimal simultaneous damping
|
|
opt_gain = zeros(1, length(alphas)); % Corresponding optimal gain
|
|
|
|
Kiff = 1/s*eye(2);
|
|
|
|
for alpha_i = 1:length(alphas)
|
|
kp = alphas(alpha_i);
|
|
cp = 0.001*2*sqrt(kp*(mn+ms)); % Small parallel damping [N/(m/s)]
|
|
kn = 1 - kp; % Stiffness [N/m]
|
|
cn = 0.01*2*sqrt(kn*(mn+ms)); % Damping [N/(m/s)]
|
|
|
|
% Identify dynamics
|
|
G = linearize(mdl, io, 0);
|
|
G.InputName = {'Fu', 'Fv', 'Fdx', 'Fdy'};
|
|
G.OutputName = {'fu', 'fv', 'Du', 'Dv', 'Dx', 'Dy'};
|
|
|
|
fun = @(g)computeSimultaneousDamping(g, G({'fu', 'fv'}, {'Fu', 'Fv'}), Kiff);
|
|
|
|
[g_opt, xi_opt] = fminsearch(fun, 2);
|
|
opt_xi(alpha_i) = 1/xi_opt;
|
|
opt_gain(alpha_i) = g_opt;
|
|
end
|
|
#+end_src
|
|
|
|
#+begin_src matlab
|
|
%% Attainable damping as a function of the stiffness ratio
|
|
figure;
|
|
yyaxis left
|
|
plot(alphas, opt_xi, '-', 'DisplayName', '$\xi_{cl}$');
|
|
set(gca, 'YScale', 'lin');
|
|
ylim([0,1]);
|
|
ylabel('Damping Ratio $\xi$');
|
|
|
|
yyaxis right
|
|
hold on;
|
|
plot(alphas, opt_gain, '-', 'DisplayName', '$g_{opt}$');
|
|
set(gca, 'YScale', 'lin');
|
|
ylim([0,2.5]);
|
|
ylabel('Controller gain $g$');
|
|
|
|
set(gca, 'XScale', 'log');
|
|
legend('location', 'northeast', 'FontSize', 8);
|
|
|
|
xlabel('$k_p$');
|
|
xlim([0.01, 1]);
|
|
xticks([0.01, 0.1, 1])
|
|
xticklabels({'$m\Omega^2$', '$10m\Omega^2$', '$100m\Omega^2$'})
|
|
#+end_src
|
|
|
|
#+begin_src matlab :tangle no :exports results :results file none
|
|
exportFig('figs/rotating_iff_kp_optimal_gain.pdf', 'width', 'half', 'height', 450);
|
|
#+end_src
|
|
|
|
#+name: fig:rotating_iff_optimal_kp
|
|
#+caption: Effect of parallel stiffness on the IFF plant
|
|
#+attr_latex: :options [htbp]
|
|
#+begin_figure
|
|
#+attr_latex: :caption \subcaption{\label{fig:rotating_iff_kp_root_locus_effect_kp}Root Locus: Effect of parallel stiffness on the attainable damping, $\Omega = 0.1 \omega_0$}
|
|
#+attr_latex: :options {0.49\linewidth}
|
|
#+begin_subfigure
|
|
#+attr_latex: :scale 1
|
|
[[file:figs/rotating_iff_kp_root_locus_effect_kp.png]]
|
|
#+end_subfigure
|
|
#+attr_latex: :caption \subcaption{\label{fig:rotating_iff_kp_optimal_gain}Attainable damping ratio $\xi_\text{cl}$ as a function of the parallel stiffness $k_p$. The corresponding control gain $g_\text{opt}$ is also shown. Values for $k_p < m\Omega^2$ are not shown because the system is unstable.}
|
|
#+attr_latex: :options {0.49\linewidth}
|
|
#+begin_subfigure
|
|
#+attr_latex: :scale 0.9
|
|
[[file:figs/rotating_iff_kp_optimal_gain.png]]
|
|
#+end_subfigure
|
|
#+end_figure
|
|
|
|
** Damped plant
|
|
The parallel stiffness are chosen to be $k_p = 2 m \Omega^2$ and the damped plant is computed.
|
|
The damped and undamped transfer functions from $F_u$ to $d_u$ are compared in Figure ref:fig:rotating_iff_kp_added_hpf_damped_plant.
|
|
Even though the two resonances are well damped, the IFF changes the low-frequency behavior of the plant, which is usually not desired.
|
|
This is because "pure" integrators are used which are inducing large low-frequency loop gains.
|
|
|
|
To lower the low-frequency gain, a high-pass filter is added to the IFF controller (which is equivalent as shifting the controller pole to the left in the complex plane):
|
|
\begin{equation}
|
|
K_{\text{IFF}}(s) = g\frac{1}{\omega_i + s} \begin{bmatrix}
|
|
1 & 0 \\
|
|
0 & 1
|
|
\end{bmatrix}
|
|
\end{equation}
|
|
|
|
To determine how the high-pass filter impacts the attainable damping, the controller gain $g$ is kept constant while $\omega_i$ is changed, and the minimum damping ratio of the damped plant is computed.
|
|
The obtained damping ratio as a function of $\omega_i/\omega_0$ (where $\omega_0$ is the resonance of the system without rotation) is shown in Figure ref:fig:rotating_iff_kp_added_hpf_effect_damping.
|
|
It is shown that the attainable damping ratio reduces as $\omega_i$ is increased (same conclusion than in Section ref:sec:rotating_iff_pseudo_int).
|
|
Let's choose $\omega_i = 0.1 \cdot \omega_0$ and compare the obtained damped plant again with the undamped and with the "pure" IFF in Figure ref:fig:rotating_iff_kp_added_hpf_damped_plant.
|
|
The added high-pass filter gives almost the same damping properties to the suspension while exhibiting good low-frequency behavior.
|
|
|
|
#+begin_src matlab
|
|
%% Identify dynamics with parallel stiffness = 2mW^2
|
|
Wz = 0.1; % [rad/s]
|
|
kp = 2*(mn + ms)*Wz^2; % Parallel Stiffness [N/m]
|
|
cp = 0.001*2*sqrt(kp*(mn+ms)); % Small parallel damping [N/(m/s)]
|
|
kn = 1 - kp; % Stiffness [N/m]
|
|
cn = 0.01*2*sqrt(kn*(mn+ms)); % Damping [N/(m/s)]
|
|
|
|
% Identify dynamics
|
|
G = linearize(mdl, io, 0);
|
|
G.InputName = {'Fu', 'Fv', 'Fdx', 'Fdy'};
|
|
G.OutputName = {'fu', 'fv', 'Du', 'Dv', 'Dx', 'Dy'};
|
|
|
|
%% IFF controller with pure integrator
|
|
Kiff_kp = (2.2/s)*eye(2);
|
|
Kiff_kp.InputName = {'fu', 'fv'};
|
|
Kiff_kp.OutputName = {'Fu', 'Fv'};
|
|
|
|
%% Compute the damped plant
|
|
G_cl_iff_kp = feedback(G, Kiff_kp, 'name');
|
|
#+end_src
|
|
|
|
#+begin_src matlab
|
|
w0 = sqrt((kn+kp)/(mn+ms)); % Resonance frequency [rad/s]
|
|
wis = w0*logspace(-2, 0, 100); % LPF cut-off [rad/s]
|
|
#+end_src
|
|
|
|
#+begin_src matlab
|
|
%% Computes the obtained damping as a function of the HPF cut-off frequency
|
|
opt_xi = zeros(1, length(wis)); % Optimal simultaneous damping
|
|
|
|
for wi_i = 1:length(wis)
|
|
Kiff_kp_hpf = (2.2/(s + wis(wi_i)))*eye(2);
|
|
Kiff_kp_hpf.InputName = {'fu', 'fv'};
|
|
Kiff_kp_hpf.OutputName = {'Fu', 'Fv'};
|
|
|
|
[~, xi] = damp(feedback(G, Kiff_kp_hpf, 'name'));
|
|
opt_xi(wi_i) = min(xi);
|
|
end
|
|
#+end_src
|
|
|
|
#+begin_src matlab :results none
|
|
%% Effect of the high-pass filter cut-off frequency on the obtained damping
|
|
figure;
|
|
plot(wis, opt_xi, '-');
|
|
set(gca, 'XScale', 'log');
|
|
set(gca, 'YScale', 'lin');
|
|
ylim([0,1]);
|
|
ylabel('Damping Ratio $\xi$');
|
|
xlabel('$\omega_i/\omega_0$');
|
|
#+end_src
|
|
|
|
#+begin_src matlab :tangle no :exports results :results file none
|
|
exportFig('figs/rotating_iff_kp_added_hpf_effect_damping.pdf', 'width', 'third', 'height', 600);
|
|
#+end_src
|
|
|
|
#+begin_src matlab
|
|
%% Compute the damped plant with added High-Pass Filter
|
|
Kiff_kp_hpf = (2.2/(s + 0.1*w0))*eye(2);
|
|
Kiff_kp_hpf.InputName = {'fu', 'fv'};
|
|
Kiff_kp_hpf.OutputName = {'Fu', 'Fv'};
|
|
|
|
G_cl_iff_hpf_kp = feedback(G, Kiff_kp_hpf, 'name');
|
|
#+end_src
|
|
|
|
#+begin_src matlab :results none
|
|
%% Bode plot of the direct and coupling terms for several rotating velocities
|
|
freqs = logspace(-3, 1, 1000);
|
|
|
|
figure;
|
|
tiledlayout(3, 1, 'TileSpacing', 'Compact', 'Padding', 'None');
|
|
|
|
% Magnitude
|
|
ax1 = nexttile([2, 1]);
|
|
hold on;
|
|
plot(freqs, abs(squeeze(freqresp(G( 'Du', 'Fu'), freqs, 'rad/s'))), '-', 'color', zeros( 1,3), ...
|
|
'DisplayName', '$d_u/F_u$ - OL')
|
|
plot(freqs, abs(squeeze(freqresp(G_cl_iff_kp( 'Du', 'Fu'), freqs, 'rad/s'))), '-', 'color', colors(1,:), ...
|
|
'DisplayName', '$d_u/F_u$ - IFF + $k_p$')
|
|
plot(freqs, abs(squeeze(freqresp(G_cl_iff_hpf_kp('Du', 'Fu'), freqs, 'rad/s'))), '-', 'color', colors(2,:), ...
|
|
'DisplayName', '$d_u/F_u$ - IFF + $k_p$ + HPF')
|
|
plot(freqs, abs(squeeze(freqresp(G( 'Dv', 'Fu'), freqs, 'rad/s'))), '-', 'color', [zeros( 1,3), 0.5], ...
|
|
'HandleVisibility', 'off')
|
|
plot(freqs, abs(squeeze(freqresp(G_cl_iff_kp( 'Dv', 'Fu'), freqs, 'rad/s'))), '-', 'color', [colors(1,:), 0.5], ...
|
|
'HandleVisibility', 'off')
|
|
plot(freqs, abs(squeeze(freqresp(G_cl_iff_hpf_kp('Dv', 'Fu'), freqs, 'rad/s'))), '-', 'color', [colors(2,:), 0.5], ...
|
|
'HandleVisibility', 'off')
|
|
hold off;
|
|
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
|
|
set(gca, 'XTickLabel',[]); ylabel('Magnitude [m/N]');
|
|
ldg = legend('location', 'southwest', 'FontSize', 8, 'NumColumns', 1);
|
|
ldg.ItemTokenSize(1) = 10;
|
|
|
|
ax2 = nexttile;
|
|
hold on;
|
|
plot(freqs, 180/pi*angle(squeeze(freqresp(G( 'Du', 'Fu'), freqs, 'rad/s'))), '-', 'color', zeros( 1,3))
|
|
plot(freqs, 180/pi*angle(squeeze(freqresp(G_cl_iff_kp( 'Du', 'Fu'), freqs, 'rad/s'))), '-', 'color', colors(1,:))
|
|
plot(freqs, 180/pi*angle(squeeze(freqresp(G_cl_iff_hpf_kp('Du', 'Fu'), freqs, 'rad/s'))), '-', 'color', colors(2,:))
|
|
hold off;
|
|
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'lin');
|
|
xlabel('Frequency [rad/s]'); ylabel('Phase [deg]');
|
|
yticks(-180:90:180);
|
|
ylim([-180 90]);
|
|
xticks([1e-3,1e-2,1e-1,1,1e1])
|
|
xticklabels({'$0.001 \omega_0$', '$0.01 \omega_0$', '$0.1 \omega_0$', '$\omega_0$', '$10 \omega_0$'})
|
|
|
|
linkaxes([ax1,ax2],'x');
|
|
xlim([freqs(1), freqs(end)]);
|
|
#+end_src
|
|
|
|
#+begin_src matlab :tangle no :exports results :results file none
|
|
exportFig('figs/rotating_iff_kp_added_hpf_damped_plant.pdf', 'width', 700, 'height', 600);
|
|
#+end_src
|
|
|
|
#+name: fig:rotating_iff_optimal_hpf
|
|
#+caption:Effect of high-pass filter cut-off frequency on the obtained damping
|
|
#+attr_latex: :options [htbp]
|
|
#+begin_figure
|
|
#+attr_latex: :caption \subcaption{\label{fig:rotating_iff_kp_added_hpf_effect_damping}Reduced damping ratio with increased cut-off frequency $\omega_i$}
|
|
#+attr_latex: :options {0.34\linewidth}
|
|
#+begin_subfigure
|
|
#+attr_latex: :scale 0.95
|
|
[[file:figs/rotating_iff_kp_added_hpf_effect_damping.png]]
|
|
#+end_subfigure
|
|
#+attr_latex: :caption \subcaption{\label{fig:rotating_iff_kp_added_hpf_damped_plant}Damped plant with the parallel stiffness, effect of the added HPF}
|
|
#+attr_latex: :options {0.65\linewidth}
|
|
#+begin_subfigure
|
|
#+attr_latex: :scale 0.95
|
|
[[file:figs/rotating_iff_kp_added_hpf_damped_plant.png]]
|
|
#+end_subfigure
|
|
#+end_figure
|
|
|
|
* Relative Damping Control
|
|
:PROPERTIES:
|
|
:header-args:matlab+: :tangle matlab/rotating_5_rdc.m
|
|
:END:
|
|
<<sec:rotating_relative_damp_control>>
|
|
|
|
** Introduction :ignore:
|
|
To apply a "Relative Damping Control" strategy, relative motion sensors are added in parallel with the actuators as shown in Figure ref:fig:rotating_3dof_model_schematic_rdc.
|
|
Two controllers $K_d$ are used to feed back the relative motion to the actuator.
|
|
These controllers are in principle pure derivators ($K_d = s$), but to be implemented in practice they are usually replaced by a high-pass filter eqref:eq:rotating_rdc_controller.
|
|
|
|
\begin{equation}\label{eq:rotating_rdc_controller}
|
|
K_d(s) = g \cdot \frac{s}{s + \omega_d}
|
|
\end{equation}
|
|
|
|
#+begin_src latex :file rotating_3dof_model_schematic_rdc.pdf
|
|
\begin{tikzpicture}
|
|
% Angle
|
|
\def\thetau{25}
|
|
|
|
% Rotational Stage
|
|
\draw[fill=black!60!white] (0, 0) circle (4.3);
|
|
\draw[fill=black!40!white] (0, 0) circle (3.8);
|
|
|
|
% Label
|
|
\node[anchor=north west, rotate=\thetau] at (-2.5, 2.5) {\small Rotating Stage};
|
|
|
|
% Rotating Scope
|
|
\begin{scope}[rotate=\thetau]
|
|
% Rotating Frame
|
|
\draw[fill=black!20!white] (-2.6, -2.6) rectangle (2.6, 2.6);
|
|
% Label
|
|
\node[anchor=north west, rotate=\thetau] at (-2.6, 2.6) {\small Suspended Platform};
|
|
|
|
% Mass
|
|
\draw[fill=white] (-1, -1) rectangle (1, 1);
|
|
% Label
|
|
\node[anchor=south west, rotate=\thetau] at (-1, -1) {\small Payload};
|
|
|
|
% Attached Points
|
|
\node[] at (-1, 0){$\bullet$};
|
|
\draw[] (-1, 0) -- ++(-0.2, 0) coordinate(cu);
|
|
\draw[] ($(cu) + (0, -0.8)$) coordinate(actu) -- ($(cu) + (0, 0.8)$) coordinate(ku);
|
|
\node[] at (0, -1){$\bullet$};
|
|
\draw[] (0, -1) -- ++(0, -0.2) coordinate(cv);
|
|
\draw[] ($(cv) + (-0.8, 0)$)coordinate(kv) -- ($(cv) + (0.8, 0)$) coordinate(actv);
|
|
|
|
% Spring and Actuator for U
|
|
\draw[actuator={0.6}{0.2}{black}] (cu) -- coordinate[midway, below=0.1](actumid) node[above=0.1, rotate=\thetau]{$F_u$} (cu-|-2.6,0);
|
|
\draw[spring=0.2] (ku) -- node[above=0.1, rotate=\thetau]{$k$} (ku-|-2.6,0);
|
|
\draw[<->, dashed, draw=colorgreen] (actu) node[below=0.1, rotate=\thetau, color=colorgreen](du){$d_u$} -- (actu-|-2.6,0);
|
|
|
|
\node[color=colorgreen, block={0.6cm}{0.6cm}, fill=colorgreen!10!white, rotate=\thetau] (Ku) at ($(actumid) + (0, -1.4)$) {$K_{d}$};
|
|
\draw[->, draw=colorgreen] (du.south) -- ++(0, -0.8) -| (Ku.south);
|
|
\draw[->, draw=colorgreen] (Ku.north) -- (actumid);
|
|
|
|
\draw[actuator={0.6}{0.2}{black}] (cv) -- coordinate[midway, right=0.1](actvmid) node[left, rotate=\thetau]{$F_v$} (cv|-0,-2.6);
|
|
\draw[spring=0.2] (kv) -- node[left, rotate=\thetau]{$k$} (kv|-0,-2.6);
|
|
\draw[<->, dashed, draw=colorgreen] (actv)node[right=0.1, rotate=\thetau, color=colorgreen](dv){$d_v$} -- (actv|-0,-2.6);
|
|
|
|
\node[color=colorgreen, block={0.6cm}{0.6cm}, fill=colorgreen!10!white, rotate=\thetau] (Kv) at ($(actvmid) + (1.4, 0)$) {$K_{d}$};
|
|
\draw[->, draw=colorgreen] (dv.east) -- ++(0.8, 0) |- (Kv.east);
|
|
\draw[->, draw=colorgreen] (Kv.west) -- (actvmid);
|
|
\end{scope}
|
|
|
|
% Inertial Frame
|
|
\draw[->] (-4, -4) -- ++(2, 0) node[below]{$\vec{i}_x$};
|
|
\draw[->] (-4, -4) -- ++(0, 2) node[left]{$\vec{i}_y$};
|
|
\draw[fill, color=black] (-4, -4) circle (0.06);
|
|
\node[draw, circle, inner sep=0pt, minimum size=0.3cm, label=left:$\vec{i}_z$] at (-4, -4){};
|
|
|
|
\draw[->] (0, 0) node[above left, rotate=\thetau]{$\vec{i}_w$} -- ++(\thetau:2) node[above, rotate=\thetau]{$\vec{i}_u$};
|
|
\draw[->] (0, 0) -- ++(\thetau+90:2) node[left, rotate=\thetau]{$\vec{i}_v$};
|
|
\draw[fill, color=black] (0,0) circle (0.06);
|
|
\node[draw, circle, inner sep=0pt, minimum size=0.3cm] at (0, 0){};
|
|
\draw[dashed] (0, 0) -- ++(2, 0);
|
|
\draw[] (1.5, 0) arc (0:\thetau:1.5) node[midway, right]{$\theta$};
|
|
|
|
\draw[->] (3.5, 0) arc (0:40:3.5) node[midway, left]{$\Omega$};
|
|
\end{tikzpicture}
|
|
#+end_src
|
|
|
|
#+name: fig:rotating_3dof_model_schematic_rdc
|
|
#+caption: System with relative motion sensor and decentralized "relative damping control" applied.
|
|
#+attr_latex: :scale 0.8
|
|
#+RESULTS:
|
|
[[file:figs/rotating_3dof_model_schematic_rdc.png]]
|
|
|
|
** Matlab Init :noexport:ignore:
|
|
#+begin_src matlab :tangle no :results silent :noweb yes :var current_dir=(file-name-directory buffer-file-name)
|
|
<<matlab-dir>>
|
|
#+end_src
|
|
|
|
#+begin_src matlab :results silent :noweb yes
|
|
<<matlab-init>>
|
|
#+end_src
|
|
|
|
#+begin_src matlab :tangle no :noweb yes
|
|
<<m-init-path>>
|
|
#+end_src
|
|
|
|
#+begin_src matlab :eval no :noweb yes
|
|
<<m-init-path-tangle>>
|
|
#+end_src
|
|
|
|
#+begin_src matlab :noweb yes
|
|
<<m-init-other>>
|
|
#+end_src
|
|
|
|
#+begin_src matlab
|
|
%% Simscape model name
|
|
mdl = 'rotating_model';
|
|
#+end_src
|
|
|
|
#+begin_src matlab
|
|
%% Load "Generic" system dynamics
|
|
load('rotating_generic_plants.mat', 'Gs', 'Wzs');
|
|
#+end_src
|
|
|
|
** Equations of motion
|
|
Let's note $\bm{G}_d$ the transfer function between actuator forces and measured relative motion in parallel with the actuators eqref:eq:rotating_rdc_plant_matrix.
|
|
The elements of $\bm{G}_d$ were derived in Section ref:sec:rotating_system_description are shown in eqref:eq:rotating_rdc_plant_elements.
|
|
|
|
\begin{equation}\label{eq:rotating_rdc_plant_matrix}
|
|
\begin{bmatrix} d_u \\ d_v \end{bmatrix} = \mathbf{G}_d \begin{bmatrix} F_u \\ F_v \end{bmatrix}
|
|
\end{equation}
|
|
|
|
\begin{subequations}\label{eq:rotating_rdc_plant_elements}
|
|
\begin{align}
|
|
\mathbf{G}_{d}(1,1) &= \mathbf{G}_{d}(2,2) = \frac{\frac{1}{k} \left( \frac{s^2}{{\omega_0}^2} + 2 \xi \frac{s}{\omega_0} + 1 - \frac{{\Omega}^2}{{\omega_0}^2} \right)}{\left( \frac{s^2}{{\omega_0}^2} + 2 \xi \frac{s}{\omega_0} + 1 - \frac{{\Omega}^2}{{\omega_0}^2} \right)^2 + \left( 2 \frac{\Omega}{\omega_0} \frac{s}{\omega_0} \right)^2} \\
|
|
\mathbf{G}_{d}(1,2) &= -\mathbf{G}_{d}(2,1) = \frac{\frac{1}{k} \left( 2 \frac{\Omega}{\omega_0} \frac{s}{\omega_0} \right)}{\left( \frac{s^2}{{\omega_0}^2} + 2 \xi \frac{s}{\omega_0} + 1 - \frac{{\Omega}^2}{{\omega_0}^2} \right)^2 + \left( 2 \frac{\Omega}{\omega_0} \frac{s}{\omega_0} \right)^2}
|
|
\end{align}
|
|
\end{subequations}
|
|
|
|
Neglecting the damping for simplicity ($\xi \ll 1$), the direct terms have two complex conjugate zeros between the two pairs of complex conjugate poles eqref:eq:rotating_rdc_zeros_poles.
|
|
Therefore, for $\Omega < \sqrt{k/m}$ (i.e. stable system), the transfer functions for Relative Damping Control have alternating complex conjugate poles and zeros.
|
|
|
|
\begin{equation}\label{eq:rotating_rdc_zeros_poles}
|
|
z = \pm j \sqrt{\omega_0^2 - \omega^2}, \quad p_1 = \pm j (\omega_0 - \omega), \quad p_2 = \pm j (\omega_0 + \omega)
|
|
\end{equation}
|
|
|
|
** Decentralized Relative Damping Control
|
|
The transfer functions from $[F_u,\ F_v]$ to $[d_u,\ d_v]$ were identified for several rotating velocities in Section ref:sec:rotating_system_description and are shown in Figure ref:fig:rotating_bode_plot (page pageref:fig:rotating_bode_plot).
|
|
|
|
To see if large damping can be added with Relative Damping Control, the root locus is computed (Figure ref:fig:rotating_rdc_root_locus).
|
|
The closed-loop system is unconditionally stable as expected and the poles can be damped as much as desired.
|
|
|
|
Let us select a reasonable "Relative Damping Control" gain, and compute the closed-loop damped system.
|
|
The open-loop and damped plants are compared in Figure ref:fig:rotating_rdc_damped_plant.
|
|
The rotating aspect does not add any complexity to the use of Relative Damping Control.
|
|
It does not increase the low-frequency coupling as compared to the Integral Force Feedback.
|
|
|
|
#+begin_src matlab :results none
|
|
%% Root Locus for Relative Damping Control
|
|
Krdc = s*eye(2); % Relative damping controller
|
|
|
|
gains = logspace(-2, 2, 300); % Tested gains
|
|
Wz_i = [1,3,4];
|
|
|
|
figure;
|
|
hold on;
|
|
for i = 1:length(Wz_i)
|
|
plot(real(pole(Gs{Wz_i(i)}({'du', 'dv'}, {'Fu', 'Fv'})*Krdc)), imag(pole(Gs{Wz_i(i)}({'du', 'dv'}, {'Fu', 'Fv'})*Krdc)), 'x', 'color', colors(i,:), ...
|
|
'DisplayName', sprintf('$\\Omega = %.1f \\omega_0 $', Wzs(Wz_i(i))),'MarkerSize',8);
|
|
plot(real(tzero(Gs{Wz_i(i)}({'du', 'dv'}, {'Fu', 'Fv'})*Krdc)), imag(tzero(Gs{Wz_i(i)}({'du', 'dv'}, {'Fu', 'Fv'})*Krdc)), 'o', 'color', colors(i,:), ...
|
|
'HandleVisibility', 'off','MarkerSize',8);
|
|
for g = gains
|
|
cl_poles = pole(feedback(Gs{Wz_i(i)}({'du', 'dv'}, {'Fu', 'Fv'}), g*Krdc, -1));
|
|
plot(real(cl_poles), imag(cl_poles), '.', 'color', colors(i,:), ...
|
|
'HandleVisibility', 'off','MarkerSize',4);
|
|
end
|
|
end
|
|
hold off;
|
|
axis square;
|
|
xlim([-1.8, 0.2]); ylim([0, 2]);
|
|
xticks([-1, 0])
|
|
xticklabels({'-$\omega_0$', '$0$'})
|
|
yticks([0, 1, 2])
|
|
yticklabels({'$0$', '$\omega_0$', '$2 \omega_0$'})
|
|
|
|
xlabel('Real Part'); ylabel('Imaginary Part');
|
|
leg = legend('location', 'northwest', 'FontSize', 8);
|
|
leg.ItemTokenSize(1) = 8;
|
|
#+end_src
|
|
|
|
#+begin_src matlab :tangle no :results none
|
|
%% Root Locus for Relative Damping Control
|
|
Krdc = s*eye(2); % Relative damping controller
|
|
|
|
gains = logspace(-2, 2, 300); % Tested gains
|
|
Wz_i = [1,3,4];
|
|
|
|
figure;
|
|
hold on;
|
|
for i = 1:length(Wz_i)
|
|
plot(real(pole(Gs{Wz_i(i)}({'du', 'dv'}, {'Fu', 'Fv'})*Krdc)), imag(pole(Gs{Wz_i(i)}({'du', 'dv'}, {'Fu', 'Fv'})*Krdc)), 'x', 'color', colors(i,:), ...
|
|
'DisplayName', sprintf('$\\Omega = %.1f \\omega_0 $', Wzs(Wz_i(i))),'MarkerSize',8);
|
|
plot(real(tzero(Gs{Wz_i(i)}({'du', 'dv'}, {'Fu', 'Fv'})*Krdc)), imag(tzero(Gs{Wz_i(i)}({'du', 'dv'}, {'Fu', 'Fv'})*Krdc)), 'o', 'color', colors(i,:), ...
|
|
'HandleVisibility', 'off','MarkerSize',8);
|
|
|
|
poles_rdc = rootLocusPolesSorted(Gs{Wz_i(i)}({'du', 'dv'}, {'Fu', 'Fv'}), Krdc, gains, 'd_max', 1e-4);
|
|
for p_i = 1:size(poles_rdc, 2)
|
|
plot(real(poles_rdc(:, p_i)), imag(poles_rdc(:, p_i)), '-', 'color', colors(i,:), ...
|
|
'HandleVisibility', 'off');
|
|
end
|
|
end
|
|
hold off;
|
|
axis equal;
|
|
xlim([-1.8, 0.2]); ylim([0, 2]);
|
|
xticks([-1, 0])
|
|
xticklabels({'-$\omega_0$', '$0$'})
|
|
yticks([0, 1, 2])
|
|
yticklabels({'$0$', '$\omega_0$', '$2 \omega_0$'})
|
|
|
|
xlabel('Real Part'); ylabel('Imaginary Part');
|
|
leg = legend('location', 'northwest', 'FontSize', 8);
|
|
leg.ItemTokenSize(1) = 8;
|
|
#+end_src
|
|
|
|
#+begin_src matlab :tangle no :exports results :results file none
|
|
exportFig('figs/rotating_rdc_root_locus_inkscape.pdf', 'width', 'half', 'height', 500, 'png', false, 'pdf', false, 'svg', true);
|
|
#+end_src
|
|
|
|
#+begin_src matlab
|
|
i = 2;
|
|
|
|
%% Relative Damping Controller
|
|
Krdc = 2*s*eye(2);
|
|
Krdc.InputName = {'Du', 'Dv'};
|
|
Krdc.OutputName = {'Fu', 'Fv'};
|
|
|
|
%% Compute the damped plant
|
|
G_cl_rdc = feedback(Gs{i}, Krdc, 'name');
|
|
#+end_src
|
|
|
|
#+begin_src matlab :results none
|
|
%% Damped plant using Relative Damping Control
|
|
freqs = logspace(-3, 2, 1000);
|
|
|
|
figure;
|
|
tiledlayout(3, 1, 'TileSpacing', 'Compact', 'Padding', 'None');
|
|
|
|
% Magnitude
|
|
ax1 = nexttile([2, 1]);
|
|
hold on;
|
|
plot(freqs, abs(squeeze(freqresp(Gs{i}( 'Du', 'Fu'), freqs, 'rad/s'))), '-', 'color', zeros(1,3), ...
|
|
'DisplayName', 'OL - $G_d(1,1)$')
|
|
plot(freqs, abs(squeeze(freqresp(G_cl_rdc('Du', 'Fu'), freqs, 'rad/s'))), '-', 'color', colors(1,:), ...
|
|
'DisplayName', 'RDC - $G_d(1,1)$')
|
|
plot(freqs, abs(squeeze(freqresp(Gs{i}( 'Dv', 'Fu'), freqs, 'rad/s'))), '-', 'color', [zeros(1,3), 0.5], ...
|
|
'DisplayName', 'OL - $G_d(2,1)$')
|
|
plot(freqs, abs(squeeze(freqresp(G_cl_rdc('Dv', 'Fu'), freqs, 'rad/s'))), '-', 'color', [colors(1,:), 0.5], ...
|
|
'DisplayName', 'RDC - $G_d(2,1)$')
|
|
hold off;
|
|
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
|
|
set(gca, 'XTickLabel',[]); ylabel('Magnitude [m/N]');
|
|
ldg = legend('location', 'southwest', 'FontSize', 8, 'NumColumns', 2);
|
|
ldg.ItemTokenSize(1) = 20;
|
|
ylim([1e-4, 1e2]);
|
|
|
|
ax2 = nexttile;
|
|
hold on;
|
|
plot(freqs, 180/pi*angle(squeeze(freqresp(Gs{i}('Du', 'Fu'), freqs, 'rad/s'))), '-', 'color', zeros(1,3))
|
|
plot(freqs, 180/pi*angle(squeeze(freqresp(G_cl_rdc('Du', 'Fu'), freqs, 'rad/s'))), '-', 'color', colors(1,:))
|
|
hold off;
|
|
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'lin');
|
|
xlabel('Frequency [rad/s]'); ylabel('Phase [deg]');
|
|
yticks(-180:90:180);
|
|
ylim([-180 0]);
|
|
|
|
linkaxes([ax1,ax2],'x');
|
|
xlim([freqs(1), freqs(end)]);
|
|
#+end_src
|
|
|
|
#+begin_src matlab :tangle no :exports results :results file none
|
|
exportFig('figs/rotating_rdc_damped_plant.pdf', 'width', 'half', 'height', 500);
|
|
#+end_src
|
|
|
|
#+name: fig:rotating_rdc_result
|
|
#+caption: Relative Damping Control. Root Locus (\subref{fig:rotating_rdc_root_locus}) and obtained damped plant (\subref{fig:rotating_rdc_damped_plant})
|
|
#+attr_latex: :options [htbp]
|
|
#+begin_figure
|
|
#+attr_latex: :caption \subcaption{\label{fig:rotating_rdc_root_locus}Root Locus for Relative Damping Control}
|
|
#+attr_latex: :options {0.49\linewidth}
|
|
#+begin_subfigure
|
|
#+attr_latex: :scale 1
|
|
[[file:figs/rotating_rdc_root_locus.png]]
|
|
#+end_subfigure
|
|
#+attr_latex: :caption \subcaption{\label{fig:rotating_rdc_damped_plant}Damped plant using Relative Damping Control}
|
|
#+attr_latex: :options {0.49\linewidth}
|
|
#+begin_subfigure
|
|
#+attr_latex: :scale 0.8
|
|
[[file:figs/rotating_rdc_damped_plant.png]]
|
|
#+end_subfigure
|
|
#+end_figure
|
|
|
|
* Comparison of Active Damping Techniques
|
|
:PROPERTIES:
|
|
:header-args:matlab+: :tangle matlab/rotating_6_act_damp_comparison.m
|
|
:END:
|
|
<<sec:rotating_comp_act_damp>>
|
|
|
|
** Introduction :ignore:
|
|
These two proposed IFF modifications and relative damping control are compared in terms of added damping and closed-loop behavior.
|
|
For the following comparisons, the cut-off frequency for the added HPF is set to $\omega_i = 0.1 \omega_0$ and the stiffness of the parallel springs is set to $k_p = 5 m \Omega^2$ (corresponding to $\alpha = 0.05$).
|
|
These values are chosen one the basis of previous discussions about optimal parameters.
|
|
|
|
** Matlab Init :noexport:ignore:
|
|
#+begin_src matlab :tangle no :results silent :noweb yes :var current_dir=(file-name-directory buffer-file-name)
|
|
<<matlab-dir>>
|
|
#+end_src
|
|
|
|
#+begin_src matlab :results silent :noweb yes
|
|
<<matlab-init>>
|
|
#+end_src
|
|
|
|
#+begin_src matlab :tangle no :noweb yes
|
|
<<m-init-path>>
|
|
#+end_src
|
|
|
|
#+begin_src matlab :eval no :noweb yes
|
|
<<m-init-path-tangle>>
|
|
#+end_src
|
|
|
|
#+begin_src matlab :noweb yes
|
|
<<m-init-other>>
|
|
#+end_src
|
|
|
|
#+begin_src matlab
|
|
%% Simscape model name
|
|
mdl = 'rotating_model';
|
|
#+end_src
|
|
|
|
** Identify plants :noexport:
|
|
#+begin_src matlab
|
|
%% The rotating speed is set to $\Omega = 0.1 \omega_0$.
|
|
Wz = 0.1; % [rad/s]
|
|
|
|
%% Masses
|
|
ms = 0.5; % Sample mass [kg]
|
|
mn = 0.5; % Tuv mass [kg]
|
|
#+end_src
|
|
|
|
#+begin_src matlab
|
|
%% General Configuration
|
|
model_config = struct();
|
|
model_config.controller = "open_loop"; % Default: Open-Loop
|
|
|
|
%% Input/Output definition
|
|
clear io; io_i = 1;
|
|
io(io_i) = linio([mdl, '/controller'], 1, 'openinput'); io_i = io_i + 1; % [Fu, Fv]
|
|
io(io_i) = linio([mdl, '/fd'], 1, 'openinput'); io_i = io_i + 1; % [Fdu, Fdv]
|
|
io(io_i) = linio([mdl, '/xf'], 1, 'openinput'); io_i = io_i + 1; % [Dfx, Dfy]
|
|
io(io_i) = linio([mdl, '/translation_stage'], 1, 'openoutput'); io_i = io_i + 1; % [Fmu, Fmv]
|
|
io(io_i) = linio([mdl, '/translation_stage'], 2, 'openoutput'); io_i = io_i + 1; % [Du, Dv]
|
|
io(io_i) = linio([mdl, '/ext_metrology'], 1, 'openoutput'); io_i = io_i + 1; % [Dx, Dy]
|
|
#+end_src
|
|
|
|
#+begin_src matlab
|
|
%% Identifying plant with parallel stiffness
|
|
model_config.Tuv_type = "parallel_k";
|
|
|
|
% Parallel stiffness
|
|
kp = 2*(mn+ms)*Wz^2; % Parallel Stiffness [N/m]
|
|
cp = 0.001*2*sqrt(kp*(mn+ms)); % Small parallel damping [N/(m/s)]
|
|
|
|
% Tuv Stage
|
|
kn = 1 - kp; % Stiffness [N/m]
|
|
cn = 0.01*2*sqrt(kn*(mn+ms)); % Damping [N/(m/s)]
|
|
|
|
% Linearize
|
|
G_kp = linearize(mdl, io, 0);
|
|
G_kp.InputName = {'Fu', 'Fv', 'Fdx', 'Fdy', 'Dfx', 'Dfy'};
|
|
G_kp.OutputName = {'fu', 'fv', 'Du', 'Dv', 'Dx', 'Dy'};
|
|
#+end_src
|
|
|
|
#+begin_src matlab
|
|
%% Identifying plant with no parallel stiffness
|
|
model_config.Tuv_type = "normal";
|
|
|
|
% Tuv Stage
|
|
kn = 1; % Stiffness [N/m]
|
|
cn = 0.01*2*sqrt(kn*(mn+ms)); % Damping [N/(m/s)]
|
|
|
|
% Linearize
|
|
G = linearize(mdl, io, 0);
|
|
G.InputName = {'Fu', 'Fv', 'Fdx', 'Fdy', 'Dfx', 'Dfy'};
|
|
G.OutputName = {'fu', 'fv', 'Du', 'Dv', 'Dx', 'Dy'};
|
|
#+end_src
|
|
|
|
#+begin_src matlab
|
|
%% IFF Controller
|
|
Kiff = (2.2/(s + 0.1))*eye(2);
|
|
Kiff.InputName = {'fu', 'fv'};
|
|
Kiff.OutputName = {'Fu', 'Fv'};
|
|
#+end_src
|
|
|
|
#+begin_src matlab
|
|
%% IFF Controller with added stiffness
|
|
Kiff_kp = (2.2/(s + 0.1))*eye(2);
|
|
Kiff_kp.InputName = {'fu', 'fv'};
|
|
Kiff_kp.OutputName = {'Fu', 'Fv'};
|
|
#+end_src
|
|
|
|
#+begin_src matlab
|
|
%% Relative Damping Controller
|
|
Krdc = 2*s*eye(2);
|
|
Krdc.InputName = {'Du', 'Dv'};
|
|
Krdc.OutputName = {'Fu', 'Fv'};
|
|
#+end_src
|
|
|
|
** Root Locus
|
|
Figure ref:fig:rotating_comp_techniques_root_locus shows the Root Locus plots for the two proposed IFF modifications and the relative damping control.
|
|
While the two pairs of complex conjugate open-loop poles are identical for both IFF modifications, the transmission zeros are not.
|
|
This means that the closed-loop behavior of both systems will differ when large control gains are used.
|
|
|
|
The closed-loop poles corresponding to the system with added springs (in red) are bounded to the left half plane implying unconditional stability.
|
|
This is not the case for the system in which the controller is augmented with an HPF (in blue).
|
|
It is interesting to note that the maximum added damping is very similar for both modified IFF techniques.
|
|
|
|
#+begin_src matlab :exports none :results none
|
|
%% Comparison of active damping techniques for rotating platform - Root Locus
|
|
gains = logspace(-2, 2, 500);
|
|
|
|
figure;
|
|
hold on;
|
|
% IFF
|
|
plot(real(pole(G({'fu', 'fv'}, {'Fu', 'Fv'})*Kiff)), imag(pole(G({'fu', 'fv'}, {'Fu', 'Fv'})*Kiff)), 'x', 'color', colors(1,:), ...
|
|
'DisplayName', 'IFF with HPF', 'MarkerSize', 8);
|
|
plot(real(tzero(G({'fu', 'fv'}, {'Fu', 'Fv'})*Kiff)), imag(tzero(G({'fu', 'fv'}, {'Fu', 'Fv'})*Kiff)), 'o', 'color', colors(1,:), ...
|
|
'HandleVisibility', 'off', 'MarkerSize', 8);
|
|
for g = gains
|
|
cl_poles = pole(feedback(G({'fu', 'fv'}, {'Fu', 'Fv'}), g*Kiff));
|
|
plot(real(cl_poles), imag(cl_poles), '.', 'color', colors(1,:),'MarkerSize',4, ...
|
|
'HandleVisibility', 'off');
|
|
end
|
|
% IFF with parallel stiffness
|
|
plot(real(pole(G_kp({'fu', 'fv'}, {'Fu', 'Fv'})*Kiff_kp)), imag(pole(G_kp({'fu', 'fv'}, {'Fu', 'Fv'})*Kiff_kp)), 'x', 'color', colors(2,:), ...
|
|
'DisplayName', 'IFF with $k_p$', 'MarkerSize', 8);
|
|
plot(real(tzero(G_kp({'fu', 'fv'}, {'Fu', 'Fv'})*Kiff_kp)), imag(tzero(G_kp({'fu', 'fv'}, {'Fu', 'Fv'})*Kiff_kp)), 'o', 'color', colors(2,:), ...
|
|
'HandleVisibility', 'off', 'MarkerSize', 8);
|
|
for g = gains
|
|
cl_poles = pole(feedback(G_kp({'fu', 'fv'}, {'Fu', 'Fv'}), g*Kiff_kp));
|
|
plot(real(cl_poles), imag(cl_poles), '.', 'color', colors(2,:),'MarkerSize',4, ...
|
|
'HandleVisibility', 'off');
|
|
end
|
|
% RDC
|
|
plot(real(pole(G({'Du', 'Dv'}, {'Fu', 'Fv'})*Krdc)), imag(pole(G({'Du', 'Dv'}, {'Fu', 'Fv'})*Krdc)), 'x', 'color', colors(3,:), ...
|
|
'DisplayName', 'RDC', 'MarkerSize', 8);
|
|
plot(real(tzero(G({'Du', 'Dv'}, {'Fu', 'Fv'})*Krdc)), imag(tzero(G({'Du', 'Dv'}, {'Fu', 'Fv'})*Krdc)), 'o', 'color', colors(3,:), ...
|
|
'HandleVisibility', 'off', 'MarkerSize', 8);
|
|
for g = gains
|
|
cl_poles = pole(feedback(G({'Du', 'Dv'}, {'Fu', 'Fv'}), g*Krdc));
|
|
plot(real(cl_poles), imag(cl_poles), '.', 'color', colors(3,:),'MarkerSize',4, ...
|
|
'HandleVisibility', 'off');
|
|
end
|
|
hold off;
|
|
axis square;
|
|
xlim([-1.15, 0.05]); ylim([0, 1.2]);
|
|
|
|
xlabel('Real Part'); ylabel('Imaginary Part');
|
|
leg = legend('location', 'northwest', 'FontSize', 8);
|
|
leg.ItemTokenSize(1) = 12;
|
|
#+end_src
|
|
|
|
#+begin_src matlab :tangle no
|
|
gains = logspace(-2, 2, 500);
|
|
|
|
poles_iff_hpf = rootLocusPolesSorted(G({'fu', 'fv'}, {'Fu', 'Fv'}), Kiff, gains, 'd_max', 1e-4);
|
|
poles_iff_kp = rootLocusPolesSorted(G_kp({'fu', 'fv'}, {'Fu', 'Fv'}), Kiff_kp, gains, 'd_max', 1e-4);
|
|
poles_rdc = rootLocusPolesSorted(G({'Du', 'Dv'}, {'Fu', 'Fv'}), Krdc, gains, 'd_max', 1e-4);
|
|
|
|
figure;
|
|
hold on;
|
|
% IFF
|
|
plot(real(pole(G({'fu', 'fv'}, {'Fu', 'Fv'})*Kiff)), imag(pole(G({'fu', 'fv'}, {'Fu', 'Fv'})*Kiff)), 'x', 'color', colors(1,:), ...
|
|
'DisplayName', 'IFF with HPF', 'MarkerSize', 8);
|
|
plot(real(tzero(G({'fu', 'fv'}, {'Fu', 'Fv'})*Kiff)), imag(tzero(G({'fu', 'fv'}, {'Fu', 'Fv'})*Kiff)), 'o', 'color', colors(1,:), ...
|
|
'HandleVisibility', 'off', 'MarkerSize', 8);
|
|
for p_i = 1:size(poles_iff_hpf, 2)
|
|
plot(real(poles_iff_hpf(:, p_i)), imag(poles_iff_hpf(:, p_i)), '-', 'color', colors(1,:), ...
|
|
'HandleVisibility', 'off');
|
|
end
|
|
|
|
% IFF with parallel stiffness
|
|
plot(real(pole(G_kp({'fu', 'fv'}, {'Fu', 'Fv'})*Kiff_kp)), imag(pole(G_kp({'fu', 'fv'}, {'Fu', 'Fv'})*Kiff_kp)), 'x', 'color', colors(2,:), ...
|
|
'DisplayName', 'IFF with $k_p$', 'MarkerSize', 8);
|
|
plot(real(tzero(G_kp({'fu', 'fv'}, {'Fu', 'Fv'})*Kiff_kp)), imag(tzero(G_kp({'fu', 'fv'}, {'Fu', 'Fv'})*Kiff_kp)), 'o', 'color', colors(2,:), ...
|
|
'HandleVisibility', 'off', 'MarkerSize', 8);
|
|
for p_i = 1:size(poles_iff_kp, 2)
|
|
plot(real(poles_iff_kp(:, p_i)), imag(poles_iff_kp(:, p_i)), '-', 'color', colors(2,:), ...
|
|
'HandleVisibility', 'off');
|
|
end
|
|
% RDC
|
|
plot(real(pole(G({'Du', 'Dv'}, {'Fu', 'Fv'})*Krdc)), imag(pole(G({'Du', 'Dv'}, {'Fu', 'Fv'})*Krdc)), 'x', 'color', colors(3,:), ...
|
|
'DisplayName', 'RDC', 'MarkerSize', 8);
|
|
plot(real(tzero(G({'Du', 'Dv'}, {'Fu', 'Fv'})*Krdc)), imag(tzero(G({'Du', 'Dv'}, {'Fu', 'Fv'})*Krdc)), 'o', 'color', colors(3,:), ...
|
|
'HandleVisibility', 'off', 'MarkerSize', 8);
|
|
for p_i = 1:size(poles_rdc, 2)
|
|
plot(real(poles_rdc(:, p_i)), imag(poles_rdc(:, p_i)), '-', 'color', colors(3,:), ...
|
|
'HandleVisibility', 'off');
|
|
end
|
|
hold off;
|
|
axis equal;
|
|
xlim([-1.15, 0.05]); ylim([0, 1.2]);
|
|
xticks([-1, -0.8, -0.6, -0.4, -0.2 , 0]);
|
|
xticklabels({'-$\omega_0$', '', '', '', '', '$0$'});
|
|
yticks([0, 0.2, 0.4, 0.6, 0.8, 1]);
|
|
yticklabels({'$0$', '', '', '', '', '$\omega_0$'});
|
|
|
|
xlabel('Real Part'); ylabel('Imaginary Part');
|
|
leg = legend('location', 'northwest', 'FontSize', 8);
|
|
leg.ItemTokenSize(1) = 12;
|
|
|
|
exportFig('figs/rotating_comp_techniques_root_locus_inkscape.pdf', 'width', 600, 'height', 600, 'png', false, 'pdf', false, 'svg', true);
|
|
|
|
xlim([-0.14, 0.02]); ylim([0, 0.2]);
|
|
|
|
exportFig('figs/rotating_comp_techniques_root_locus_zoom.pdf', 'width', 600, 'height', 600, 'png', false, 'pdf', false, 'svg', true);
|
|
#+end_src
|
|
|
|
#+name: fig:rotating_comp_techniques
|
|
#+caption: Comparison of active damping techniques for rotating platform
|
|
#+attr_latex: :options [htbp]
|
|
#+begin_figure
|
|
#+attr_latex: :caption \subcaption{\label{fig:rotating_comp_techniques_root_locus}Root Locus}
|
|
#+attr_latex: :options {0.49\textwidth}
|
|
#+begin_subfigure
|
|
#+attr_latex: :width 0.95\linewidth
|
|
[[file:figs/rotating_comp_techniques_root_locus.png]]
|
|
#+end_subfigure
|
|
#+attr_latex: :caption \subcaption{\label{fig:rotating_comp_techniques_dampled_plants}Damped plants}
|
|
#+attr_latex: :options {0.49\textwidth}
|
|
#+begin_subfigure
|
|
#+attr_latex: :width 0.95\linewidth
|
|
[[file:figs/rotating_comp_techniques_dampled_plants.png]]
|
|
#+end_subfigure
|
|
#+end_figure
|
|
|
|
** Obtained Damped Plant
|
|
The actively damped plants are computed for the three techniques and compared in Figure ref:fig:rotating_comp_techniques_dampled_plants.
|
|
It is shown that while the diagonal (direct) terms of the damped plants are similar for the three active damping techniques, the off-diagonal (coupling) terms are not.
|
|
The acrshort:iff strategy is adding some coupling at low-frequency, which may negatively impact the positioning performance.
|
|
|
|
#+begin_src matlab
|
|
%% Compute Damped plants
|
|
G_cl_iff = feedback(G, Kiff, 'name');
|
|
G_cl_iff_kp = feedback(G_kp, Kiff_kp, 'name');
|
|
G_cl_rdc = feedback(G, Krdc, 'name');
|
|
#+end_src
|
|
|
|
#+begin_src matlab :exports none :results none
|
|
%% Comparison of the damped plants obtained with the three active damping techniques
|
|
freqs = logspace(-2, 2, 1000);
|
|
|
|
figure;
|
|
tiledlayout(3, 1, 'TileSpacing', 'Compact', 'Padding', 'None');
|
|
|
|
% Magnitude
|
|
ax1 = nexttile([2, 1]);
|
|
hold on;
|
|
plot(freqs, abs(squeeze(freqresp(G( 'Du', 'Fu'), freqs, 'rad/s'))), '-', 'color', zeros(1,3), ...
|
|
'DisplayName', 'OL')
|
|
plot(freqs, abs(squeeze(freqresp(G_cl_iff( 'Du', 'Fu'), freqs, 'rad/s'))), '-', 'color', colors(1,:), ...
|
|
'DisplayName', 'IFF + HPF')
|
|
plot(freqs, abs(squeeze(freqresp(G_cl_iff_kp('Du', 'Fu'), freqs, 'rad/s'))), '-', 'color', colors(2,:), ...
|
|
'DisplayName', 'IFF + $k_p$')
|
|
plot(freqs, abs(squeeze(freqresp(G_cl_rdc( 'Du', 'Fu'), freqs, 'rad/s'))), '-', 'color', colors(3,:), ...
|
|
'DisplayName', 'RDC')
|
|
plot(freqs, abs(squeeze(freqresp(G( 'Dv', 'Fu'), freqs, 'rad/s'))), '-', 'color', [zeros(1,3), 0.5], ...
|
|
'DisplayName', 'Coupling')
|
|
plot(freqs, abs(squeeze(freqresp(G_cl_iff( 'Dv', 'Fu'), freqs, 'rad/s'))), '-', 'color', [colors(1,:), 0.5], ...
|
|
'DisplayName', 'Coupling')
|
|
plot(freqs, abs(squeeze(freqresp(G_cl_iff_kp('Dv', 'Fu'), freqs, 'rad/s'))), '-', 'color', [colors(2,:), 0.5], ...
|
|
'DisplayName', 'Coupling')
|
|
plot(freqs, abs(squeeze(freqresp(G_cl_rdc( 'Dv', 'Fu'), freqs, 'rad/s'))), '-', 'color', [colors(3,:), 0.5], ...
|
|
'DisplayName', 'Coupling')
|
|
hold off;
|
|
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
|
|
set(gca, 'XTickLabel',[]); ylabel('Magnitude [m/N]');
|
|
ldg = legend('location', 'southwest', 'FontSize', 8, 'NumColumns', 2);
|
|
ldg.ItemTokenSize = [10, 1];
|
|
ylim([1e-6, 1e2])
|
|
|
|
ax2 = nexttile;
|
|
hold on;
|
|
plot(freqs, 180/pi*angle(squeeze(freqresp(G( 'Du', 'Fu'), freqs, 'rad/s'))), '-', 'color', zeros(1,3))
|
|
plot(freqs, 180/pi*angle(squeeze(freqresp(G_cl_iff( 'Du', 'Fu'), freqs, 'rad/s'))), '-', 'color', colors(1,:))
|
|
plot(freqs, 180/pi*angle(squeeze(freqresp(G_cl_iff_kp('Du', 'Fu'), freqs, 'rad/s'))), '-', 'color', colors(2,:))
|
|
plot(freqs, 180/pi*angle(squeeze(freqresp(G_cl_rdc( 'Du', 'Fu'), freqs, 'rad/s'))), '-', 'color', colors(3,:))
|
|
hold off;
|
|
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'lin');
|
|
xlabel('Frequency [rad/s]'); ylabel('Phase [deg]');
|
|
yticks(-180:90:180);
|
|
ylim([-180 15]);
|
|
|
|
linkaxes([ax1,ax2],'x');
|
|
xlim([freqs(1), freqs(end)]);
|
|
xticks([1e-2,1e-1,1,1e1,1e2])
|
|
xticklabels({'$0.01 \omega_0$', '$0.1 \omega_0$', '$\omega_0$', '$10 \omega_0$', '$100 \omega_0$'})
|
|
#+end_src
|
|
|
|
#+begin_src matlab :tangle no :exports results :results file none
|
|
exportFig('figs/rotating_comp_techniques_dampled_plants.pdf', 'width', 'half', 'height', 600);
|
|
#+end_src
|
|
|
|
** Transmissibility And Compliance
|
|
The proposed active damping techniques are now compared in terms of closed-loop transmissibility and compliance.
|
|
The transmissibility is defined as the transfer function from the displacement of the rotating stage along $\vec{i}_x$ to the displacement of the payload along the same direction.
|
|
It is used to characterize the amount of vibration is transmitted through the suspended platform to the payload.
|
|
The compliance describes the displacement response of the payload to the external forces applied to it.
|
|
This is a useful metric when disturbances are directly applied to the payload.
|
|
Here, it is defined as the transfer function from external forces applied on the payload along $\vec{i}_x$ to the displacement of the payload along the same direction.
|
|
|
|
Very similar results were obtained for the two proposed IFF modifications in terms of transmissibility and compliance (Figure ref:fig:rotating_comp_techniques_trans_compliance).
|
|
Using IFF degrades the compliance at low frequencies, whereas using relative damping control degrades the transmissibility at high frequencies.
|
|
This is very well known characteristics of these common active damping techniques that hold when applied to rotating platforms.
|
|
|
|
#+begin_src matlab :exports none :results none
|
|
%% Comparison of the obtained transmissibility and compliance for the three tested active damping techniques
|
|
freqs = logspace(-2, 2, 1000);
|
|
|
|
% transmissibility
|
|
figure;
|
|
hold on;
|
|
plot(freqs, abs(squeeze(freqresp(G( 'Dx', 'Dfx'), freqs, 'rad/s'))), '-', 'color', zeros(1,3), ...
|
|
'DisplayName', 'OL')
|
|
plot(freqs, abs(squeeze(freqresp(G_cl_iff( 'Dx', 'Dfx'), freqs, 'rad/s'))), '-', 'color', colors(1,:), ...
|
|
'DisplayName', 'IFF + HPF')
|
|
plot(freqs, abs(squeeze(freqresp(G_cl_iff_kp('Dx', 'Dfx'), freqs, 'rad/s'))), '-', 'color', colors(2,:), ...
|
|
'DisplayName', 'IFF + $k_p$')
|
|
plot(freqs, abs(squeeze(freqresp(G_cl_rdc( 'Dx', 'Dfx'), freqs, 'rad/s'))), '-', 'color', colors(3,:), ...
|
|
'DisplayName', 'RDC')
|
|
hold off;
|
|
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
|
|
xlabel('Frequency [rad/s]'); ylabel('Transmissibility [m/m]');
|
|
xlim([freqs(1), freqs(end)]);
|
|
#+end_src
|
|
|
|
#+begin_src matlab :tangle no :exports results :results file none
|
|
exportFig('figs/rotating_comp_techniques_transmissibility.pdf', 'width', 'half', 'height', 450);
|
|
#+end_src
|
|
|
|
#+begin_src matlab :exports none :results none
|
|
% Compliance
|
|
figure;
|
|
ax1 = nexttile();
|
|
hold on;
|
|
plot(freqs, abs(squeeze(freqresp(G( 'Dx', 'Fdx'), freqs, 'rad/s'))), '-', 'color', zeros(1,3), ...
|
|
'DisplayName', 'OL')
|
|
plot(freqs, abs(squeeze(freqresp(G_cl_iff( 'Dx', 'Fdx'), freqs, 'rad/s'))), '-', 'color', colors(1,:), ...
|
|
'DisplayName', 'IFF + HPF')
|
|
plot(freqs, abs(squeeze(freqresp(G_cl_iff_kp('Dx', 'Fdx'), freqs, 'rad/s'))), '-', 'color', colors(2,:), ...
|
|
'DisplayName', 'IFF + $k_p$')
|
|
plot(freqs, abs(squeeze(freqresp(G_cl_rdc( 'Dx', 'Fdx'), freqs, 'rad/s'))), '-', 'color', colors(3,:), ...
|
|
'DisplayName', 'RDC')
|
|
hold off;
|
|
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
|
|
xlabel('Frequency [rad/s]'); ylabel('Compliance [m/N]');
|
|
ldg = legend('location', 'southwest', 'FontSize', 8, 'NumColumns', 2);
|
|
ldg.ItemTokenSize = [10, 1];
|
|
xlim([freqs(1), freqs(end)]);
|
|
#+end_src
|
|
|
|
#+begin_src matlab :tangle no :exports results :results file none
|
|
exportFig('figs/rotating_comp_techniques_compliance.pdf', 'width', 'half', 'height', 450);
|
|
#+end_src
|
|
|
|
#+name: fig:rotating_comp_techniques_trans_compliance
|
|
#+caption: Comparison of the obtained transmissibility (\subref{fig:rotating_comp_techniques_transmissibility}) and compliance (\subref{fig:rotating_comp_techniques_compliance}) for the three tested active damping techniques
|
|
#+attr_latex: :options [htbp]
|
|
#+begin_figure
|
|
#+attr_latex: :caption \subcaption{\label{fig:rotating_comp_techniques_transmissibility}Transmissibility}
|
|
#+attr_latex: :options {0.49\textwidth}
|
|
#+begin_subfigure
|
|
#+attr_latex: :width 0.95\linewidth
|
|
[[file:figs/rotating_comp_techniques_transmissibility.png]]
|
|
#+end_subfigure
|
|
#+attr_latex: :caption \subcaption{\label{fig:rotating_comp_techniques_compliance}Compliance}
|
|
#+attr_latex: :options {0.49\textwidth}
|
|
#+begin_subfigure
|
|
#+attr_latex: :width 0.95\linewidth
|
|
[[file:figs/rotating_comp_techniques_compliance.png]]
|
|
#+end_subfigure
|
|
#+end_figure
|
|
|
|
* Rotating Nano-Hexapod
|
|
:PROPERTIES:
|
|
:header-args:matlab+: :tangle matlab/rotating_7_nano_hexapod.m
|
|
:END:
|
|
<<sec:rotating_nano_hexapod>>
|
|
** Introduction :ignore:
|
|
The previous analysis is now applied to a model representing a rotating nano-hexapod.
|
|
Three nano-hexapod stiffnesses are tested as for the uniaxial model: $k_n = \SI{0.01}{\N\per\mu\m}$, $k_n = \SI{1}{\N\per\mu\m}$ and $k_n = \SI{100}{\N\per\mu\m}$.
|
|
Only the maximum rotating velocity is here considered ($\Omega = \SI{60}{rpm}$) with the light sample ($m_s = \SI{1}{kg}$) because this is the worst identified case scenario in terms of gyroscopic effects.
|
|
|
|
** Matlab Init :noexport:ignore:
|
|
#+begin_src matlab :tangle no :results silent :noweb yes :var current_dir=(file-name-directory buffer-file-name)
|
|
<<matlab-dir>>
|
|
#+end_src
|
|
|
|
#+begin_src matlab :results silent :noweb yes
|
|
<<matlab-init>>
|
|
#+end_src
|
|
|
|
#+begin_src matlab :tangle no :noweb yes
|
|
<<m-init-path>>
|
|
#+end_src
|
|
|
|
#+begin_src matlab :eval no :noweb yes
|
|
<<m-init-path-tangle>>
|
|
#+end_src
|
|
|
|
#+begin_src matlab :noweb yes
|
|
<<m-init-other>>
|
|
#+end_src
|
|
|
|
#+begin_src matlab
|
|
%% Simscape model name
|
|
mdl = 'rotating_model';
|
|
#+end_src
|
|
|
|
** Identify NASS dynamics :noexport:
|
|
#+begin_src matlab
|
|
%% Nano-Hexapod
|
|
mn = 15; % Nano-Hexapod mass [kg]
|
|
|
|
%% Light Sample
|
|
ms = 1; % Sample Mass [kg]
|
|
|
|
%% General Configuration
|
|
model_config = struct();
|
|
model_config.controller = "open_loop"; % Default: Open-Loop
|
|
model_config.Tuv_type = "normal"; % Default: 2DoF stage
|
|
#+end_src
|
|
|
|
#+begin_src matlab
|
|
%% Input/Output definition
|
|
clear io; io_i = 1;
|
|
io(io_i) = linio([mdl, '/controller'], 1, 'openinput'); io_i = io_i + 1; % [Fu, Fv]
|
|
io(io_i) = linio([mdl, '/fd'], 1, 'openinput'); io_i = io_i + 1; % [Fdx, Fdy]
|
|
io(io_i) = linio([mdl, '/xf'], 1, 'openinput'); io_i = io_i + 1; % [Dfx, Dfy]
|
|
io(io_i) = linio([mdl, '/translation_stage'], 1, 'openoutput'); io_i = io_i + 1; % [Fmu, Fmv]
|
|
io(io_i) = linio([mdl, '/translation_stage'], 2, 'openoutput'); io_i = io_i + 1; % [Du, Dv]
|
|
io(io_i) = linio([mdl, '/ext_metrology'], 1, 'openoutput'); io_i = io_i + 1; % [Dx, Dy]
|
|
#+end_src
|
|
|
|
#+begin_src matlab
|
|
%% Voice Coil (i.e. soft) Nano-Hexapod
|
|
kn = 1e4; % Nano-Hexapod Stiffness [N/m]
|
|
cn = 2*0.005*sqrt((ms + mn)*kn); % Nano-Hexapod Damping [N/(m/s)]
|
|
|
|
Wz = 0; % Rotating Velocity [rad/s]
|
|
G_vc_norot = linearize(mdl, io, 0.0);
|
|
G_vc_norot.InputName = {'Fu', 'Fv', 'Fdx', 'Fdy', 'Dfx', 'Dfy'};
|
|
G_vc_norot.OutputName = {'fu', 'fv', 'Du', 'Dv', 'Dx', 'Dy'};
|
|
|
|
Wz = 2*pi; % Rotating Velocity [rad/s]
|
|
G_vc_fast = linearize(mdl, io, 0.0);
|
|
G_vc_fast.InputName = {'Fu', 'Fv', 'Fdx', 'Fdy', 'Dfx', 'Dfy'};
|
|
G_vc_fast.OutputName = {'fu', 'fv', 'Du', 'Dv', 'Dx', 'Dy'};
|
|
|
|
%% APA (i.e. relatively stiff) Nano-Hexapod
|
|
kn = 1e6; % Nano-Hexapod Stiffness [N/m]
|
|
cn = 2*0.005*sqrt((ms + mn)*kn); % Nano-Hexapod Damping [N/(m/s)]
|
|
|
|
Wz = 0; % Rotating Velocity [rad/s]
|
|
G_md_norot = linearize(mdl, io, 0.0);
|
|
G_md_norot.InputName = {'Fu', 'Fv', 'Fdx', 'Fdy', 'Dfx', 'Dfy'};
|
|
G_md_norot.OutputName = {'fu', 'fv', 'Du', 'Dv', 'Dx', 'Dy'};
|
|
|
|
Wz = 2*pi; % Rotating Velocity [rad/s]
|
|
G_md_fast = linearize(mdl, io, 0.0);
|
|
G_md_fast.InputName = {'Fu', 'Fv', 'Fdx', 'Fdy', 'Dfx', 'Dfy'};
|
|
G_md_fast.OutputName = {'fu', 'fv', 'Du', 'Dv', 'Dx', 'Dy'};
|
|
|
|
%% Piezoelectric (i.e. stiff) Nano-Hexapod
|
|
kn = 1e8; % Nano-Hexapod Stiffness [N/m]
|
|
cn = 2*0.005*sqrt((ms + mn)*kn); % Nano-Hexapod Damping [N/(m/s)]
|
|
|
|
Wz = 0; % Rotating Velocity [rad/s]
|
|
G_pz_norot = linearize(mdl, io, 0.0);
|
|
G_pz_norot.InputName = {'Fu', 'Fv', 'Fdx', 'Fdy', 'Dfx', 'Dfy'};
|
|
G_pz_norot.OutputName = {'fu', 'fv', 'Du', 'Dv', 'Dx', 'Dy'};
|
|
|
|
Wz = 2*pi; % Rotating Velocity [rad/s]
|
|
G_pz_fast = linearize(mdl, io, 0.0);
|
|
G_pz_fast.InputName = {'Fu', 'Fv', 'Fdx', 'Fdy', 'Dfx', 'Dfy'};
|
|
G_pz_fast.OutputName = {'fu', 'fv', 'Du', 'Dv', 'Dx', 'Dy'};
|
|
#+end_src
|
|
|
|
** Nano-Active-Stabilization-System - Plant Dynamics
|
|
For the NASS, the maximum rotating velocity is $\Omega = \SI[parse-numbers=false]{2\pi}{\radian\per\s}$ for a suspended mass on top of the nano-hexapod's actuators equal to $m_n + m_s = \SI{16}{\kilo\gram}$.
|
|
The parallel stiffness corresponding to the centrifugal forces is $m \Omega^2 \approx \SI{0.6}{\newton\per\mm}$.
|
|
|
|
#+begin_src matlab
|
|
%% Compute negative spring in [N/m]
|
|
Kneg_light = (15+1)*(2*pi)^2;
|
|
#+end_src
|
|
|
|
The transfer functions from the nano-hexapod actuator force $F_u$ to the displacement of the nano-hexapod in the same direction $d_u$ as well as in the orthogonal direction $d_v$ (coupling) are shown in Figure ref:fig:rotating_nano_hexapod_dynamics for all three considered nano-hexapod stiffnesses.
|
|
The soft nano-hexapod is the most affected by rotation.
|
|
This can be seen by the large shift of the resonance frequencies, and by the induced coupling, which is larger than that for the stiffer nano-hexapods.
|
|
The coupling (or interaction) in a MIMO $2 \times 2$ system can be visually estimated as the ratio between the diagonal term and the off-diagonal terms (see corresponding Appendix).
|
|
|
|
#+begin_src matlab :results none
|
|
%% Effect of rotation on the nano-hexapod dynamics
|
|
freqs = logspace(0, 1, 1000);
|
|
|
|
figure;
|
|
tiledlayout(3, 1, 'TileSpacing', 'Compact', 'Padding', 'None');
|
|
|
|
ax1 = nexttile([2,1]);
|
|
hold on;
|
|
plot(freqs, abs(squeeze(freqresp(G_vc_norot('Du', 'Fu'), freqs, 'Hz'))), '--', 'color', colors(1,:), ...
|
|
'DisplayName', '$\Omega = 0\,$rpm, $D_u/F_u$');
|
|
plot(freqs, abs(squeeze(freqresp(G_vc_fast( 'Du', 'Fu'), freqs, 'Hz'))), '-' , 'color', colors(1,:), ...
|
|
'DisplayName', '$\Omega = 60\,$rpm, $D_u/F_u$');
|
|
plot(freqs, abs(squeeze(freqresp(G_vc_fast( 'Dv', 'Fu'), freqs, 'Hz'))), '-' , 'color', [colors(1,:), 0.5], ...
|
|
'DisplayName', '$\Omega = 60\,$rpm, $D_v/F_u$');
|
|
hold off;
|
|
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
|
|
ylabel('Magnitude [m/N]'); set(gca, 'XTickLabel',[]);
|
|
ylim([1e-6, 1e-2])
|
|
|
|
ax2 = nexttile;
|
|
hold on;
|
|
plot(freqs, 180/pi*angle(squeeze(freqresp(G_vc_norot('Du', 'Fu'), freqs, 'Hz'))), '--', 'color', colors(1,:));
|
|
plot(freqs, 180/pi*angle(squeeze(freqresp(G_vc_fast( 'Du', 'Fu'), freqs, 'Hz'))), '-' , 'color', colors(1,:));
|
|
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, 1e3]);
|
|
#+end_src
|
|
|
|
#+begin_src matlab :tangle no :exports results :results file none
|
|
exportFig('figs/rotating_nano_hexapod_dynamics_vc.pdf', 'width', 'third', 'height', 500);
|
|
#+end_src
|
|
|
|
#+begin_src matlab :results none
|
|
%% Effect of rotation on the nano-hexapod dynamics
|
|
freqs = logspace(1, 2, 1000);
|
|
|
|
figure;
|
|
tiledlayout(3, 1, 'TileSpacing', 'Compact', 'Padding', 'None');
|
|
|
|
ax1 = nexttile([2,1]);
|
|
hold on;
|
|
plot(freqs, abs(squeeze(freqresp(G_md_norot('Du', 'Fu'), freqs, 'Hz'))), '--', 'color', colors(2,:), ...
|
|
'DisplayName', '$\Omega = 0\,$rpm, $D_u/F_u$');
|
|
plot(freqs, abs(squeeze(freqresp(G_md_fast( 'Du', 'Fu'), freqs, 'Hz'))), '-' , 'color', colors(2,:), ...
|
|
'DisplayName', '$\Omega = 60\,$rpm, $D_u/F_u$');
|
|
plot(freqs, abs(squeeze(freqresp(G_md_fast( 'Dv', 'Fu'), freqs, 'Hz'))), '-' , 'color', [colors(2,:), 0.5], ...
|
|
'DisplayName', '$\Omega = 60\,$rpm, $D_v/F_u$');
|
|
hold off;
|
|
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
|
|
ylabel('Magnitude [m/N]'); set(gca, 'XTickLabel',[]);
|
|
ylim([1e-8, 1e-4])
|
|
|
|
ax2 = nexttile;
|
|
hold on;
|
|
plot(freqs, 180/pi*angle(squeeze(freqresp(G_md_norot('Du', 'Fu'), freqs, 'Hz'))), '--', 'color', colors(2,:));
|
|
plot(freqs, 180/pi*angle(squeeze(freqresp(G_md_fast( 'Du', 'Fu'), freqs, 'Hz'))), '-' , 'color', colors(2,:));
|
|
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');
|
|
#+end_src
|
|
|
|
#+begin_src matlab :tangle no :exports results :results file none
|
|
exportFig('figs/rotating_nano_hexapod_dynamics_md.pdf', 'width', 'third', 'height', 500);
|
|
#+end_src
|
|
|
|
#+begin_src matlab :results none
|
|
%% Effect of rotation on the nano-hexapod dynamics
|
|
freqs = logspace(2, 3, 1000);
|
|
|
|
figure;
|
|
tiledlayout(3, 1, 'TileSpacing', 'Compact', 'Padding', 'None');
|
|
|
|
ax1 = nexttile([2,1]);
|
|
hold on;
|
|
plot(freqs, abs(squeeze(freqresp(G_pz_norot('Du', 'Fu'), freqs, 'Hz'))), '--', 'color', colors(3,:), ...
|
|
'DisplayName', '$\Omega = 0\,$rpm, $D_u/F_u$');
|
|
plot(freqs, abs(squeeze(freqresp(G_pz_fast( 'Du', 'Fu'), freqs, 'Hz'))), '-' , 'color', colors(3,:), ...
|
|
'DisplayName', '$\Omega = 60\,$rpm, $D_u/F_u$');
|
|
plot(freqs, abs(squeeze(freqresp(G_pz_fast( 'Dv', 'Fu'), freqs, 'Hz'))), '-' , 'color', [colors(3,:), 0.5], ...
|
|
'DisplayName', '$\Omega = 60\,$rpm, $D_v/F_u$');
|
|
hold off;
|
|
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
|
|
ylabel('Magnitude [m/N]'); set(gca, 'XTickLabel',[]);
|
|
ylim([1e-10, 1e-6])
|
|
|
|
ax2 = nexttile;
|
|
hold on;
|
|
plot(freqs, 180/pi*angle(squeeze(freqresp(G_pz_norot('Du', 'Fu'), freqs, 'Hz'))), '--', 'color', colors(3,:));
|
|
plot(freqs, 180/pi*angle(squeeze(freqresp(G_pz_fast( 'Du', 'Fu'), freqs, 'Hz'))), '-' , '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([-180, 0]);
|
|
|
|
linkaxes([ax1,ax2],'x');
|
|
#+end_src
|
|
|
|
#+begin_src matlab :tangle no :exports results :results file none
|
|
exportFig('figs/rotating_nano_hexapod_dynamics_pz.pdf', 'width', 'third', 'height', 500);
|
|
#+end_src
|
|
|
|
#+name: fig:rotating_nano_hexapod_dynamics
|
|
#+caption: Effect of rotation on the nano-hexapod dynamics. Dashed lines represent plants without rotation, solid lines represent plants at maximum rotating velocity ($\Omega = 60\,\text{rpm}$), and shaded lines are coupling terms at maximum rotating velocity
|
|
#+attr_latex: :options [htbp]
|
|
#+begin_figure
|
|
#+attr_latex: :caption \subcaption{\label{fig:uniaxial_damped_plant_three_active_damping_techniques_vc}$k_n = 0.01\,N/\mu m$}
|
|
#+attr_latex: :options {0.33\textwidth}
|
|
#+begin_subfigure
|
|
#+attr_latex: :width 0.95\linewidth
|
|
[[file:figs/rotating_nano_hexapod_dynamics_vc.png]]
|
|
#+end_subfigure
|
|
#+attr_latex: :caption \subcaption{\label{fig:rotating_nano_hexapod_dynamics_md}$k_n = 1\,N/\mu m$}
|
|
#+attr_latex: :options {0.33\textwidth}
|
|
#+begin_subfigure
|
|
#+attr_latex: :width 0.95\linewidth
|
|
[[file:figs/rotating_nano_hexapod_dynamics_md.png]]
|
|
#+end_subfigure
|
|
#+attr_latex: :caption \subcaption{\label{fig:rotating_nano_hexapod_dynamics_pz}$k_n = 100\,N/\mu m$}
|
|
#+attr_latex: :options {0.33\textwidth}
|
|
#+begin_subfigure
|
|
#+attr_latex: :width 0.95\linewidth
|
|
[[file:figs/rotating_nano_hexapod_dynamics_pz.png]]
|
|
#+end_subfigure
|
|
#+end_figure
|
|
|
|
** Optimal IFF with a High-Pass Filter
|
|
Integral Force Feedback with an added high-pass filter is applied to the three nano-hexapods.
|
|
First, the parameters ($\omega_i$ and $g$) of the IFF controller that yield the best simultaneous damping are determined from Figure ref:fig:rotating_iff_hpf_nass_optimal_gain.
|
|
The IFF parameters are chosen as follows:
|
|
- for $k_n = \SI{0.01}{\N\per\mu\m}$ (Figure ref:fig:rotating_iff_hpf_nass_optimal_gain): $\omega_i$ is chosen such that maximum damping is achieved while the gain is less than half of the maximum gain at which the system is unstable.
|
|
This is done to have some control robustness.
|
|
- for $k_n = \SI{1}{\N\per\mu\m}$ and $k_n = \SI{100}{\N\per\mu\m}$ (Figure ref:fig:rotating_iff_hpf_nass_optimal_gain_md and ref:fig:rotating_iff_hpf_nass_optimal_gain_pz): the largest $\omega_i$ is chosen such that the obtained damping is $\SI{95}{\percent}$ of the maximum achievable damping.
|
|
Large $\omega_i$ is chosen here to limit the loss of compliance and the increase of coupling at low-frequency as shown in Section ref:sec:rotating_iff_pseudo_int.
|
|
The obtained IFF parameters and the achievable damping are visually shown by large dots in Figure ref:fig:rotating_iff_hpf_nass_optimal_gain and are summarized in Table ref:tab:rotating_iff_hpf_opt_iff_hpf_params_nass.
|
|
|
|
#+begin_src matlab
|
|
%% Compute the optimal control gain
|
|
wis = logspace(-2, 3, 200); % [rad/s]
|
|
|
|
opt_iff_hpf_xi_vc = zeros(1, length(wis)); % Optimal simultaneous damping
|
|
opt_iff_hpf_gain_vc = zeros(1, length(wis)); % Corresponding optimal gain
|
|
|
|
opt_iff_hpf_xi_md = zeros(1, length(wis)); % Optimal simultaneous damping
|
|
opt_iff_hpf_gain_md = zeros(1, length(wis)); % Corresponding optimal gain
|
|
|
|
opt_iff_hpf_xi_pz = zeros(1, length(wis)); % Optimal simultaneous damping
|
|
opt_iff_hpf_gain_pz = zeros(1, length(wis)); % Corresponding optimal gain
|
|
|
|
for wi_i = 1:length(wis)
|
|
wi = wis(wi_i);
|
|
Kiff = 1/(s + wi)*eye(2);
|
|
|
|
fun = @(g)computeSimultaneousDamping(g, G_vc_fast({'fu', 'fv'}, {'Fu', 'Fv'}), Kiff);
|
|
|
|
[g_opt, xi_opt] = fminsearch(fun, 0.1);
|
|
opt_iff_hpf_xi_vc(wi_i) = 1/xi_opt;
|
|
opt_iff_hpf_gain_vc(wi_i) = g_opt;
|
|
|
|
fun = @(g)computeSimultaneousDamping(g, G_md_fast({'fu', 'fv'}, {'Fu', 'Fv'}), Kiff);
|
|
|
|
[g_opt, xi_opt] = fminsearch(fun, 0.1);
|
|
opt_iff_hpf_xi_md(wi_i) = 1/xi_opt;
|
|
opt_iff_hpf_gain_md(wi_i) = g_opt;
|
|
|
|
fun = @(g)computeSimultaneousDamping(g, G_pz_fast({'fu', 'fv'}, {'Fu', 'Fv'}), Kiff);
|
|
|
|
[g_opt, xi_opt] = fminsearch(fun, 0.1);
|
|
opt_iff_hpf_xi_pz(wi_i) = 1/xi_opt;
|
|
opt_iff_hpf_gain_pz(wi_i) = g_opt;
|
|
end
|
|
#+end_src
|
|
|
|
#+begin_src matlab
|
|
%% Find optimal parameters with at least a gain margin of 2
|
|
i_iff_hpf_vc = find(opt_iff_hpf_gain_vc < 0.5*(wis*((sqrt(1e4/16)/(2*pi))^2 - 1)));
|
|
i_iff_hpf_vc = i_iff_hpf_vc(1);
|
|
|
|
i_iff_hpf_md = find(opt_iff_hpf_xi_md > 0.95*max(opt_iff_hpf_xi_md));
|
|
i_iff_hpf_md = i_iff_hpf_md(end)+1;
|
|
|
|
i_iff_hpf_pz = find(opt_iff_hpf_xi_pz > 0.95*max(opt_iff_hpf_xi_pz));
|
|
i_iff_hpf_pz = i_iff_hpf_pz(end)+1;
|
|
#+end_src
|
|
|
|
#+begin_src matlab :results none
|
|
%% Optimal modified IFF parameters that yields maximum simultaneous damping
|
|
figure;
|
|
yyaxis left
|
|
hold on;
|
|
plot(wis, opt_iff_hpf_xi_vc, '-', 'DisplayName', '$\xi_{cl}$');
|
|
plot(wis(i_iff_hpf_vc), opt_iff_hpf_xi_vc(i_iff_hpf_vc), '.', 'MarkerSize', 15, 'HandleVisibility', 'off');
|
|
hold off;
|
|
set(gca, 'YScale', 'lin');
|
|
ylim([0,1]);
|
|
ylabel('Damping Ratio $\xi$');
|
|
|
|
yyaxis right
|
|
hold on;
|
|
plot(wis, opt_iff_hpf_gain_vc, '-', 'DisplayName', '$g_{opt}$');
|
|
plot(wis, wis*((sqrt(1e4/16)/(2*pi))^2 - 1), '--', 'DisplayName', '$g_{max}$');
|
|
plot(wis(i_iff_hpf_vc), opt_iff_hpf_gain_vc(i_iff_hpf_vc), '.', 'MarkerSize', 15, 'HandleVisibility', 'off');
|
|
set(gca, 'YScale', 'lin');
|
|
ylim([0,200]);
|
|
xlabel('$\omega_i$ [rad/s]');
|
|
set(gca, 'YTickLabel',[]);
|
|
ylabel('Controller gain $g$');
|
|
set(gca, 'XScale', 'log');
|
|
xticks([1e-2,1,1e2])
|
|
legend('location', 'northwest', 'FontSize', 8);
|
|
#+end_src
|
|
|
|
#+begin_src matlab :tangle no :exports results :results file replace
|
|
exportFig('figs/rotating_iff_hpf_nass_optimal_gain_vc.pdf', 'width', 'third', 'height', 450);
|
|
#+end_src
|
|
|
|
#+begin_src matlab :results none
|
|
figure;
|
|
yyaxis left
|
|
hold on;
|
|
plot(wis, opt_iff_hpf_xi_md, '-');
|
|
plot(wis(i_iff_hpf_md), opt_iff_hpf_xi_md(i_iff_hpf_md), '.', 'MarkerSize', 15, 'HandleVisibility', 'off');
|
|
hold off;
|
|
set(gca, 'YScale', 'lin');
|
|
ylim([0,1]);
|
|
ylabel('Damping Ratio $\xi$');
|
|
|
|
yyaxis right
|
|
hold on;
|
|
plot(wis, opt_iff_hpf_gain_md, '-');
|
|
plot(wis(i_iff_hpf_md), opt_iff_hpf_gain_md(i_iff_hpf_md), '.', 'MarkerSize', 15, 'HandleVisibility', 'off');
|
|
plot(wis, wis*((sqrt(1e6/16)/(2*pi))^2 - 1), '--');
|
|
set(gca, 'YScale', 'lin');
|
|
ylim([0,1000]);
|
|
xlabel('$\omega_i$ [rad/s]');
|
|
ylabel('Controller gain $g$');
|
|
set(gca, 'YTickLabel',[]);
|
|
set(gca, 'XScale', 'log');
|
|
xticks([1e-2,1,1e2])
|
|
#+end_src
|
|
|
|
#+begin_src matlab :tangle no :exports results :results file replace
|
|
exportFig('figs/rotating_iff_hpf_nass_optimal_gain_md.pdf', 'width', 'third', 'height', 450);
|
|
#+end_src
|
|
|
|
#+begin_src matlab :results none
|
|
figure;
|
|
yyaxis left
|
|
hold on;
|
|
plot(wis, opt_iff_hpf_xi_pz, '-');
|
|
plot(wis(i_iff_hpf_pz), opt_iff_hpf_xi_pz(i_iff_hpf_pz), '.', 'MarkerSize', 15, 'HandleVisibility', 'off');
|
|
hold off;
|
|
set(gca, 'YScale', 'lin');
|
|
ylim([0,1]);
|
|
ylabel('Damping Ratio $\xi$');
|
|
|
|
yyaxis right
|
|
hold on;
|
|
plot(wis, opt_iff_hpf_gain_pz, '-');
|
|
plot(wis(i_iff_hpf_pz), opt_iff_hpf_gain_pz(i_iff_hpf_pz), '.', 'MarkerSize', 15, 'HandleVisibility', 'off');
|
|
plot(wis, wis*((sqrt(1e8/16)/(2*pi))^2 - 1), '--');
|
|
set(gca, 'YScale', 'lin');
|
|
ylim([0,10000]);
|
|
xlabel('$\omega_i$ [rad/s]');
|
|
set(gca, 'YTickLabel',[]);
|
|
ylabel('Controller gain $g$');
|
|
set(gca, 'XScale', 'log');
|
|
xticks([1e-2,1,1e2])
|
|
#+end_src
|
|
|
|
#+begin_src matlab :tangle no :exports results :results file replace
|
|
exportFig('figs/rotating_iff_hpf_nass_optimal_gain_pz.pdf', 'width', 'third', 'height', 450);
|
|
#+end_src
|
|
|
|
#+name: fig:rotating_iff_hpf_nass_optimal_gain
|
|
#+caption: For each value of $\omega_i$, the maximum damping ratio $\xi$ is computed (blue), and the corresponding controller gain is shown (in red). The chosen controller parameters used for further analysis are indicated by the large dots.
|
|
#+attr_latex: :options [htbp]
|
|
#+begin_figure
|
|
#+attr_latex: :caption \subcaption{\label{fig:rotating_iff_hpf_nass_optimal_gain_vc}$k_n = 0.01\,N/\mu m$}
|
|
#+attr_latex: :options {0.33\textwidth}
|
|
#+begin_subfigure
|
|
#+attr_latex: :width 0.95\linewidth
|
|
[[file:figs/rotating_iff_hpf_nass_optimal_gain_vc.png]]
|
|
#+end_subfigure
|
|
#+attr_latex: :caption \subcaption{\label{fig:rotating_iff_hpf_nass_optimal_gain_md}$k_n = 1\,N/\mu m$}
|
|
#+attr_latex: :options {0.33\textwidth}
|
|
#+begin_subfigure
|
|
#+attr_latex: :width 0.95\linewidth
|
|
[[file:figs/rotating_iff_hpf_nass_optimal_gain_md.png]]
|
|
#+end_subfigure
|
|
#+attr_latex: :caption \subcaption{\label{fig:rotating_iff_hpf_nass_optimal_gain_pz}$k_n = 100\,N/\mu m$}
|
|
#+attr_latex: :options {0.33\textwidth}
|
|
#+begin_subfigure
|
|
#+attr_latex: :width 0.95\linewidth
|
|
[[file:figs/rotating_iff_hpf_nass_optimal_gain_pz.png]]
|
|
#+end_subfigure
|
|
#+end_figure
|
|
|
|
#+begin_src matlab :exports results :results value table replace :tangle no :post addhdr(*this*)
|
|
data2orgtable([wis(i_iff_hpf_vc), opt_iff_hpf_gain_vc(i_iff_hpf_vc), opt_iff_hpf_xi_vc(i_iff_hpf_vc); wis(i_iff_hpf_md), opt_iff_hpf_gain_md(i_iff_hpf_md), opt_iff_hpf_xi_md(i_iff_hpf_md); wis(i_iff_hpf_pz), opt_iff_hpf_gain_pz(i_iff_hpf_pz), opt_iff_hpf_xi_pz(i_iff_hpf_pz)], {'$k_n = 0.01\,N/\mu m$', '$k_n = 1\,N/\mu m$', '$k_n = 100\,N/\mu m$'}, {'$\omega_i$', '$g$', '$\xi$'}, ' %.2f ');
|
|
#+end_src
|
|
|
|
#+name: tab:rotating_iff_hpf_opt_iff_hpf_params_nass
|
|
#+caption: Obtained optimal parameters ($\omega_i$ and $g$) for the modified IFF controller including a high-pass filter. The corresponding achievable simultaneous damping of the two modes $\xi$ is also shown.
|
|
#+attr_latex: :environment tabularx :width 0.4\linewidth :align Xccc
|
|
#+attr_latex: :center t :booktabs t
|
|
#+RESULTS:
|
|
| $k_n$ | $\omega_i$ | $g$ | $\xi_\text{opt}$ |
|
|
|-----------------+------------+------+------------------|
|
|
| $0.01\,N/\mu m$ | 7.3 | 51 | 0.45 |
|
|
| $1\,N/\mu m$ | 39 | 427 | 0.93 |
|
|
| $100\,N/\mu m$ | 500 | 3775 | 0.94 |
|
|
|
|
** Optimal IFF with Parallel Stiffness
|
|
For each considered nano-hexapod stiffness, the parallel stiffness $k_p$ is varied from $k_{p,\text{min}} = m\Omega^2$ (the minimum stiffness that yields unconditional stability) to $k_{p,\text{max}} = k_n$ (the total nano-hexapod stiffness).
|
|
To keep the overall stiffness constant, the actuator stiffness $k_a$ is decreased when $k_p$ is increased ($k_a = k_n - k_p$, with $k_n$ the total nano-hexapod stiffness).
|
|
A high-pass filter is also added to limit the low-frequency gain with a cut-off frequency $\omega_i$ equal to one tenth of the system resonance ($\omega_i = \omega_0/10$).
|
|
|
|
The achievable maximum simultaneous damping of all the modes is computed as a function of the parallel stiffnesses (Figure ref:fig:rotating_iff_kp_nass_optimal_gain).
|
|
It is shown that the soft nano-hexapod cannot yield good damping because the parallel stiffness cannot be sufficiently large compared to the negative stiffness induced by the rotation.
|
|
For the two stiff options, the achievable damping decreases when the parallel stiffness is too high, as explained in Section ref:sec:rotating_iff_parallel_stiffness.
|
|
Such behavior can be explained by the fact that the achievable damping can be approximated by the distance between the open-loop pole and the open-loop zero [[cite:&preumont18_vibrat_contr_activ_struc_fourt_edition chapt 7.2]].
|
|
This distance is larger for stiff nano-hexapod because the open-loop pole will be at higher frequencies while the open-loop zero, whereas depends on the value of the parallel stiffness, can only be made large for stiff nano-hexapods.
|
|
|
|
Let's choose $k_p = 1\,N/mm$, $k_p = 0.01\,N/\mu m$ and $k_p = 1\,N/\mu m$ for the three considered nano-hexapods.
|
|
The corresponding optimal controller gains and achievable damping are summarized in Table ref:tab:rotating_iff_kp_opt_iff_kp_params_nass.
|
|
|
|
#+begin_src matlab
|
|
%% Maximum rotating velocity
|
|
Wz = 2*pi; % [rad/s]
|
|
|
|
%% Minimum parallel stiffness
|
|
kp_min = (mn + ms) * Wz^2; % [N/m]
|
|
|
|
%% Parameters for simulation
|
|
mn = 15; % Nano-Hexapod mass [kg]
|
|
ms = 1; % Sample Mass [kg]
|
|
|
|
%% IFF Controller
|
|
Kiff_vc = 1/(s + 0.1*sqrt(1e4/(mn+ms)))*eye(2); % IFF
|
|
Kiff_md = 1/(s + 0.1*sqrt(1e6/(mn+ms)))*eye(2); % IFF
|
|
Kiff_pz = 1/(s + 0.1*sqrt(1e8/(mn+ms)))*eye(2); % IFF
|
|
|
|
%% General Configuration
|
|
model_config = struct();
|
|
model_config.controller = "open_loop"; % Default: Open-Loop
|
|
model_config.Tuv_type = "parallel_k"; % Default: 2DoF stage
|
|
|
|
%% Computes the optimal parameters and attainable simultaneous damping - Voice Coil nano-hexapod
|
|
kps_vc = logspace(log10(kp_min), log10(1e4), 100); % Tested parallel stiffnesses [N/m]
|
|
kps_vc(end) = [];
|
|
|
|
opt_iff_kp_xi_vc = zeros(1, length(kps_vc)); % Optimal simultaneous damping
|
|
opt_iff_kp_gain_vc = zeros(1, length(kps_vc)); % Corresponding optimal gain
|
|
|
|
for kp_i = 1:length(kps_vc)
|
|
% Voice Coil Nano-Hexapod
|
|
kp = kps_vc(kp_i);
|
|
cp = 2*0.001*sqrt((ms + mn)*kp);
|
|
kn = 1e4 - kp; % Nano-Hexapod Stiffness [N/m]
|
|
cn = 2*0.01*sqrt((ms + mn)*kn); % Nano-Hexapod Damping [N/(m/s)]
|
|
|
|
% Identify dynamics
|
|
Giff_vc = linearize(mdl, io, 0);
|
|
Giff_vc.InputName = {'Fu', 'Fv', 'Fdx', 'Fdy', 'Dfx', 'Dfy'};
|
|
Giff_vc.OutputName = {'fu', 'fv', 'Du', 'Dv', 'Dx', 'Dy'};
|
|
|
|
fun = @(g)computeSimultaneousDamping(g, Giff_vc({'fu', 'fv'}, {'Fu', 'Fv'}), Kiff_vc);
|
|
|
|
[g_opt, xi_opt] = fminsearch(fun, 0.1);
|
|
opt_iff_kp_xi_vc(kp_i) = 1/xi_opt;
|
|
opt_iff_kp_gain_vc(kp_i) = g_opt;
|
|
end
|
|
|
|
%% Computes the optimal parameters and attainable simultaneous damping - APA nano-hexapod
|
|
kps_md = logspace(log10(kp_min), log10(1e6), 100); % Tested parallel stiffnesses [N/m]
|
|
kps_md(end) = [];
|
|
|
|
opt_iff_kp_xi_md = zeros(1, length(kps_md)); % Optimal simultaneous damping
|
|
opt_iff_kp_gain_md = zeros(1, length(kps_md)); % Corresponding optimal gain
|
|
|
|
|
|
for kp_i = 1:length(kps_md)
|
|
% Voice Coil Nano-Hexapod
|
|
kp = kps_md(kp_i);
|
|
cp = 2*0.001*sqrt((ms + mn)*kp);
|
|
kn = 1e6 - kp; % Nano-Hexapod Stiffness [N/m]
|
|
cn = 2*0.01*sqrt((ms + mn)*kn); % Nano-Hexapod Damping [N/(m/s)]
|
|
|
|
% Identify dynamics
|
|
Giff_md = linearize(mdl, io, 0);
|
|
Giff_md.InputName = {'Fu', 'Fv', 'Fdx', 'Fdy', 'Dfx', 'Dfy'};
|
|
Giff_md.OutputName = {'fu', 'fv', 'Du', 'Dv', 'Dx', 'Dy'};
|
|
|
|
fun = @(g)computeSimultaneousDamping(g, Giff_md({'fu', 'fv'}, {'Fu', 'Fv'}), Kiff_md);
|
|
|
|
[g_opt, xi_opt] = fminsearch(fun, 0.1);
|
|
opt_iff_kp_xi_md(kp_i) = 1/xi_opt;
|
|
opt_iff_kp_gain_md(kp_i) = g_opt;
|
|
end
|
|
|
|
%% Computes the optimal parameters and attainable simultaneous damping - Piezo nano-hexapod
|
|
kps_pz = logspace(log10(kp_min), log10(1e8), 100); % Tested parallel stiffnesses [N/m]
|
|
kps_pz(end) = [];
|
|
|
|
opt_iff_kp_xi_pz = zeros(1, length(kps_pz)); % Optimal simultaneous damping
|
|
opt_iff_kp_gain_pz = zeros(1, length(kps_pz)); % Corresponding optimal gain
|
|
|
|
|
|
for kp_i = 1:length(kps_pz)
|
|
% Voice Coil Nano-Hexapod
|
|
kp = kps_pz(kp_i);
|
|
cp = 2*0.001*sqrt((ms + mn)*kp);
|
|
kn = 1e8 - kp; % Nano-Hexapod Stiffness [N/m]
|
|
cn = 2*0.01*sqrt((ms + mn)*kn); % Nano-Hexapod Damping [N/(m/s)]
|
|
|
|
% Identify dynamics
|
|
Giff_pz = linearize(mdl, io, 0);
|
|
Giff_pz.InputName = {'Fu', 'Fv', 'Fdx', 'Fdy', 'Dfx', 'Dfy'};
|
|
Giff_pz.OutputName = {'fu', 'fv', 'Du', 'Dv', 'Dx', 'Dy'};
|
|
|
|
fun = @(g)computeSimultaneousDamping(g, Giff_pz({'fu', 'fv'}, {'Fu', 'Fv'}), Kiff_pz);
|
|
|
|
[g_opt, xi_opt] = fminsearch(fun, 0.1);
|
|
opt_iff_kp_xi_pz(kp_i) = 1/xi_opt;
|
|
opt_iff_kp_gain_pz(kp_i) = g_opt;
|
|
end
|
|
#+end_src
|
|
|
|
#+begin_src matlab
|
|
%% Find result with wanted parallel stiffness
|
|
[~, i_kp_vc] = min(abs(kps_vc - 1e3));
|
|
[~, i_kp_md] = min(abs(kps_md - 1e4));
|
|
[~, i_kp_pz] = min(abs(kps_pz - 1e6));
|
|
|
|
%% Identify plants with choosen Parallel stiffnesses
|
|
model_config.Tuv_type = "parallel_k"; % Default: 2DoF stage
|
|
|
|
% Voice Coil
|
|
kp = 1e3;
|
|
cp = 2*0.001*sqrt((ms + mn)*kp);
|
|
kn = 1e4-kp; % Nano-Hexapod Stiffness [N/m]
|
|
cn = 2*0.01*sqrt((ms + mn)*kn); % Nano-Hexapod Damping [N/(m/s)]
|
|
|
|
% Identify dynamics
|
|
Wz = 2*pi; % [rad/s]
|
|
G_vc_kp_fast = linearize(mdl, io, 0);
|
|
G_vc_kp_fast.InputName = {'Fu', 'Fv', 'Fdx', 'Fdy', 'Dfx', 'Dfy'};
|
|
G_vc_kp_fast.OutputName = {'fu', 'fv', 'Du', 'Dv', 'Dx', 'Dy'};
|
|
|
|
Wz = 0; % [rad/s]
|
|
G_vc_kp_norot = linearize(mdl, io, 0);
|
|
G_vc_kp_norot.InputName = {'Fu', 'Fv', 'Fdx', 'Fdy', 'Dfx', 'Dfy'};
|
|
G_vc_kp_norot.OutputName = {'fu', 'fv', 'Du', 'Dv', 'Dx', 'Dy'};
|
|
|
|
% APA
|
|
kp = 1e4;
|
|
cp = 2*0.001*sqrt((ms + mn)*kp);
|
|
kn = 1e6 - kp; % Nano-Hexapod Stiffness [N/m]
|
|
cn = 2*0.01*sqrt((ms + mn)*kn); % Nano-Hexapod Damping [N/(m/s)]
|
|
|
|
% Identify dynamics
|
|
Wz = 2*pi; % [rad/s]
|
|
G_md_kp_fast = linearize(mdl, io, 0);
|
|
G_md_kp_fast.InputName = {'Fu', 'Fv', 'Fdx', 'Fdy', 'Dfx', 'Dfy'};
|
|
G_md_kp_fast.OutputName = {'fu', 'fv', 'Du', 'Dv', 'Dx', 'Dy'};
|
|
|
|
Wz = 0; % [rad/s]
|
|
G_md_kp_norot = linearize(mdl, io, 0);
|
|
G_md_kp_norot.InputName = {'Fu', 'Fv', 'Fdx', 'Fdy', 'Dfx', 'Dfy'};
|
|
G_md_kp_norot.OutputName = {'fu', 'fv', 'Du', 'Dv', 'Dx', 'Dy'};
|
|
|
|
% Piezo
|
|
kp = 1e6;
|
|
cp = 2*0.001*sqrt((ms + mn)*kp);
|
|
kn = 1e8 - kp; % Nano-Hexapod Stiffness [N/m]
|
|
cn = 2*0.01*sqrt((ms + mn)*kn); % Nano-Hexapod Damping [N/(m/s)]
|
|
|
|
% Identify dynamics
|
|
Wz = 2*pi; % [rad/s]
|
|
G_pz_kp_fast = linearize(mdl, io, 0);
|
|
G_pz_kp_fast.InputName = {'Fu', 'Fv', 'Fdx', 'Fdy', 'Dfx', 'Dfy'};
|
|
G_pz_kp_fast.OutputName = {'fu', 'fv', 'Du', 'Dv', 'Dx', 'Dy'};
|
|
|
|
Wz = 0; % [rad/s]
|
|
G_pz_kp_norot = linearize(mdl, io, 0);
|
|
G_pz_kp_norot.InputName = {'Fu', 'Fv', 'Fdx', 'Fdy', 'Dfx', 'Dfy'};
|
|
G_pz_kp_norot.OutputName = {'fu', 'fv', 'Du', 'Dv', 'Dx', 'Dy'};
|
|
#+end_src
|
|
|
|
#+begin_src matlab :results none
|
|
%% Optimal IFF gain and associated simultaneous damping as a function of the parallel stiffness
|
|
figure;
|
|
hold on;
|
|
plot(kps_vc, opt_iff_kp_xi_vc, '-', ...
|
|
'color', colors(1,:), 'DisplayName', '$k_n = 0.01\,N/\mu m$');
|
|
plot(kps_vc(i_kp_vc), opt_iff_kp_xi_vc(i_kp_vc), '.', ...
|
|
'color', colors(1,:), 'MarkerSize', 15, 'HandleVisibility', 'off');
|
|
plot(kps_md, opt_iff_kp_xi_md, '-', ...
|
|
'color', colors(2,:), 'DisplayName', '$k_n = 1\,N/\mu m$');
|
|
plot(kps_md(i_kp_md), opt_iff_kp_xi_md(i_kp_md), '.', ...
|
|
'color', colors(2,:), 'MarkerSize', 15, 'HandleVisibility', 'off');
|
|
plot(kps_pz, opt_iff_kp_xi_pz, '-', ...
|
|
'color', colors(3,:), 'DisplayName', '$k_n = 100\,N/\mu m$');
|
|
plot(kps_pz(i_kp_pz), opt_iff_kp_xi_pz(i_kp_pz), '.', ...
|
|
'color', colors(3,:), 'MarkerSize', 15, 'HandleVisibility', 'off');
|
|
hold off;
|
|
xlabel('$k_p [N/m]$');
|
|
ylabel('Damping Ratio $\xi$');
|
|
set(gca, 'XScale', 'log');
|
|
set(gca, 'YScale', 'lin');
|
|
ylim([0,1]);
|
|
yticks([0:0.2:1])
|
|
legend('location', 'southeast', 'FontSize', 8);
|
|
xlim([kps_pz(1), kps_pz(end)])
|
|
#+end_src
|
|
|
|
#+begin_src matlab :tangle no :exports results :results file none
|
|
exportFig('figs/rotating_iff_kp_nass_optimal_gain.pdf', 'width', 'half', 'height', 350);
|
|
#+end_src
|
|
|
|
#+attr_latex: :options [t]{0.49\linewidth}
|
|
#+begin_minipage
|
|
#+name: fig:rotating_iff_kp_nass_optimal_gain
|
|
#+attr_latex: :width \linewidth :float nil
|
|
#+caption: Maximum damping $\xi$ as a function of the parallel stiffness $k_p$
|
|
[[file:figs/rotating_iff_kp_nass_optimal_gain.png]]
|
|
#+end_minipage
|
|
\hfill
|
|
#+attr_latex: :options [b]{0.45\linewidth}
|
|
#+begin_minipage
|
|
#+caption: Obtained optimal parameters for the IFF controller when using parallel stiffnesses
|
|
#+name: tab:rotating_iff_kp_opt_iff_kp_params_nass
|
|
#+attr_latex: :environment tabularx :width \linewidth :placement [b] :align Xccc
|
|
#+attr_latex: :booktabs t :float nil
|
|
#+RESULTS:
|
|
| $k_n$ | $k_p$ | $g$ | $\xi_{\text{opt}}$ |
|
|
|-----------------+-----------------+---------+--------------------|
|
|
| $0.01\,N/\mu m$ | $1\,N/mm$ | 47.9 | 0.44 |
|
|
| $1\,N/\mu m$ | $0.01\,N/\mu m$ | 465.57 | 0.97 |
|
|
| $100\,N/\mu m$ | $1\,N/\mu m$ | 4624.25 | 0.99 |
|
|
#+end_minipage
|
|
|
|
#+begin_src matlab :exports results :results value table replace :tangle no :post addhdr(*this*)
|
|
data2orgtable([opt_iff_kp_gain_vc(i_kp_vc), opt_iff_kp_xi_vc(i_kp_vc); opt_iff_kp_gain_md(i_kp_md), opt_iff_kp_xi_md(i_kp_md); opt_iff_kp_gain_pz(i_kp_pz), opt_iff_kp_xi_pz(i_kp_pz)], {'$k_n = 0.01\,N/\mu m$', '$k_n = 1\,N/\mu m$', '$k_n = 100\,N/\mu m$'}, {'$g$', '$\xi_{\text{opt}}$'}, ' %.2f ');
|
|
#+end_src
|
|
|
|
** Optimal Relative Motion Control
|
|
For each considered nano-hexapod stiffness, relative damping control is applied and the achievable damping ratio as a function of the controller gain is computed (Figure ref:fig:rotating_rdc_optimal_gain).
|
|
The gain is chosen such that 99% of modal damping is obtained (obtained gains are summarized in Table ref:tab:rotating_rdc_opt_params_nass).
|
|
|
|
#+begin_src matlab
|
|
%% Computes the optimal parameters and attainable simultaneous damping - Piezo nano-hexapod
|
|
rdc_gains = 2*logspace(1, 5, 200);
|
|
% Obtained simultaneous damping
|
|
rdc_xi_vc = zeros(1, length(rdc_gains));
|
|
rdc_xi_md = zeros(1, length(rdc_gains));
|
|
rdc_xi_pz = zeros(1, length(rdc_gains));
|
|
|
|
Krdc = s*eye(2);
|
|
Krdc.InputName = {'Du', 'Dv'};
|
|
Krdc.OutputName = {'Fu', 'Fv'};
|
|
|
|
for g_i = 1:length(rdc_gains)
|
|
[~, xi] = damp(feedback(G_vc_fast({'Du', 'Dv'}, {'Fu', 'Fv'}), rdc_gains(g_i)*Krdc));
|
|
rdc_xi_vc(g_i) = min(xi);
|
|
|
|
[~, xi] = damp(feedback(G_md_fast({'Du', 'Dv'}, {'Fu', 'Fv'}), rdc_gains(g_i)*Krdc));
|
|
rdc_xi_md(g_i) = min(xi);
|
|
|
|
[~, xi] = damp(feedback(G_pz_fast({'Du', 'Dv'}, {'Fu', 'Fv'}), rdc_gains(g_i)*Krdc));
|
|
rdc_xi_pz(g_i) = min(xi);
|
|
end
|
|
#+end_src
|
|
|
|
#+begin_src matlab
|
|
%% Optimal RDC
|
|
[~, i_rdc_vc] = min(abs(rdc_xi_vc - 0.99));
|
|
[~, i_rdc_md] = min(abs(rdc_xi_md - 0.99));
|
|
[~, i_rdc_pz] = min(abs(rdc_xi_pz - 0.99));
|
|
|
|
Krdc_vc = rdc_gains(i_rdc_vc)*Krdc;
|
|
Krdc_md = rdc_gains(i_rdc_md)*Krdc;
|
|
Krdc_pz = rdc_gains(i_rdc_pz)*Krdc;
|
|
#+end_src
|
|
|
|
#+begin_src matlab :results none
|
|
%% Optimal IFF gain and associated simultaneous damping as a function of the parallel stiffness
|
|
figure;
|
|
hold on;
|
|
plot(rdc_gains, rdc_xi_vc, '-', ...
|
|
'color', colors(1,:), 'DisplayName', '$k_n = 0.01\,N/\mu m$');
|
|
plot(rdc_gains(i_rdc_vc), rdc_xi_vc(i_rdc_vc), '.', ...
|
|
'color', colors(1,:), 'MarkerSize', 15, 'HandleVisibility', 'off');
|
|
plot(rdc_gains, rdc_xi_md, '-', ...
|
|
'color', colors(2,:), 'DisplayName', '$k_n = 1\,N/\mu m$');
|
|
plot(rdc_gains(i_rdc_md), rdc_xi_md(i_rdc_md), '.', ...
|
|
'color', colors(2,:), 'MarkerSize', 15, 'HandleVisibility', 'off');
|
|
plot(rdc_gains, rdc_xi_pz, '-', ...
|
|
'color', colors(3,:), 'DisplayName', '$k_n = 100\,N/\mu m$');
|
|
plot(rdc_gains(i_rdc_pz), rdc_xi_pz(i_rdc_pz), '.', ...
|
|
'color', colors(3,:), 'MarkerSize', 15, 'HandleVisibility', 'off');
|
|
hold off;
|
|
xlabel('Relative Damping Controller gain $g$');
|
|
ylabel('Damping Ratio $\xi$');
|
|
set(gca, 'XScale', 'log');
|
|
set(gca, 'YScale', 'lin');
|
|
ylim([0,1]);
|
|
yticks([0:0.2:1])
|
|
xlim([rdc_gains(1), rdc_gains(end)])
|
|
legend('location', 'southeast', 'FontSize', 8);
|
|
#+end_src
|
|
|
|
#+begin_src matlab :tangle no :exports results :results file replace
|
|
exportFig('figs/rotating_rdc_optimal_gain.pdf', 'width', 'half', 'height', 350);
|
|
#+end_src
|
|
|
|
#+attr_latex: :options [t]{0.49\linewidth}
|
|
#+begin_minipage
|
|
#+name: fig:rotating_rdc_optimal_gain
|
|
#+attr_latex: :width \linewidth :float nil
|
|
#+caption: Maximum damping $\xi$ as a function of the RDC gain $g$
|
|
[[file:figs/rotating_rdc_optimal_gain.png]]
|
|
#+end_minipage
|
|
\hfill
|
|
#+attr_latex: :options [b]{0.45\linewidth}
|
|
#+begin_minipage
|
|
#+caption: Obtained optimal parameters for the RDC
|
|
#+name: tab:rotating_rdc_opt_params_nass
|
|
#+attr_latex: :environment tabularx :width 0.8\linewidth :placement [b] :align Xcc
|
|
#+attr_latex: :booktabs t :float nil
|
|
#+RESULTS:
|
|
| $k_n$ | $g$ | $\xi_{\text{opt}}$ |
|
|
|-----------------+-------+--------------------|
|
|
| $0.01\,N/\mu m$ | 1600 | 0.99 |
|
|
| $1\,N/\mu m$ | 8200 | 0.99 |
|
|
| $100\,N/\mu m$ | 80000 | 0.99 |
|
|
#+end_minipage
|
|
|
|
** Comparison of the obtained damped plants
|
|
Now that the optimal parameters for the three considered active damping techniques have been determined, the obtained damped plants are computed and compared in Figure ref:fig:rotating_nass_damped_plant_comp.
|
|
|
|
Similar to what was concluded in the previous analysis:
|
|
- acrshort:iff adds more coupling below the resonance frequency as compared to the open-loop and acrshort:rdc cases
|
|
- All three methods yield good damping, except for acrshort:iff applied on the soft nano-hexapod
|
|
- Coupling is smaller for stiff nano-hexapods
|
|
|
|
#+begin_src matlab :tangle no
|
|
%% Saved controllers
|
|
save('./matlab/mat/nass_controllers.mat', ...
|
|
'Kiff_hpf_vc', 'Kiff_hpf_md', 'Kiff_hpf_pz', ...
|
|
'Kiff_kp_vc', 'Kiff_kp_md', 'Kiff_kp_pz', ...
|
|
'Krdc_vc', 'Krdc_md', 'Krdc_pz');
|
|
#+end_src
|
|
|
|
#+begin_src matlab :tangle no
|
|
%% Load controllers
|
|
load('nass_controllers.mat');
|
|
#+end_src
|
|
|
|
#+begin_src matlab
|
|
%% Closed-Loop Plants - IFF with HPF
|
|
G_vc_norot_iff_hpf = feedback(G_vc_norot, Kiff_hpf_vc, 'name');
|
|
G_vc_fast_iff_hpf = feedback(G_vc_fast, Kiff_hpf_vc, 'name');
|
|
|
|
G_md_norot_iff_hpf = feedback(G_md_norot, Kiff_hpf_md, 'name');
|
|
G_md_fast_iff_hpf = feedback(G_md_fast, Kiff_hpf_md, 'name');
|
|
|
|
G_pz_norot_iff_hpf = feedback(G_pz_norot, Kiff_hpf_pz, 'name');
|
|
G_pz_fast_iff_hpf = feedback(G_pz_fast, Kiff_hpf_pz, 'name');
|
|
|
|
%% Closed-Loop Plants - IFF with Parallel Stiffness
|
|
G_vc_norot_iff_kp = feedback(G_vc_kp_norot, Kiff_kp_vc, 'name');
|
|
G_vc_fast_iff_kp = feedback(G_vc_kp_fast, Kiff_kp_vc, 'name');
|
|
|
|
G_md_norot_iff_kp = feedback(G_md_kp_norot, Kiff_kp_md, 'name');
|
|
G_md_fast_iff_kp = feedback(G_md_kp_fast, Kiff_kp_md, 'name');
|
|
|
|
G_pz_norot_iff_kp = feedback(G_pz_kp_norot, Kiff_kp_pz, 'name');
|
|
G_pz_fast_iff_kp = feedback(G_pz_kp_fast, Kiff_kp_pz, 'name');
|
|
|
|
%% Closed-Loop Plants - RDC
|
|
G_vc_norot_rdc = feedback(G_vc_norot, Krdc_vc, 'name');
|
|
G_vc_fast_rdc = feedback(G_vc_fast, Krdc_vc, 'name');
|
|
|
|
G_md_norot_rdc = feedback(G_md_norot, Krdc_md, 'name');
|
|
G_md_fast_rdc = feedback(G_md_fast, Krdc_md, 'name');
|
|
|
|
G_pz_norot_rdc = feedback(G_pz_norot, Krdc_pz, 'name');
|
|
G_pz_fast_rdc = feedback(G_pz_fast, Krdc_pz, 'name');
|
|
#+end_src
|
|
|
|
#+begin_src matlab :exports none :results none
|
|
%% Comparison of the damped plants (direct and coupling terms) for the three proposed active damping techniques (IFF with HPF, IFF with $k_p$ and RDC) applied on the three nano-hexapod stiffnesses
|
|
freqs_vc = logspace(-1, 2, 1000);
|
|
|
|
figure;
|
|
tiledlayout(3, 1, 'TileSpacing', 'Compact', 'Padding', 'None');
|
|
|
|
ax1 = nexttile([2,1]);
|
|
hold on;
|
|
plot(freqs_vc, abs(squeeze(freqresp(G_vc_fast( 'Du', 'Fu'), freqs_vc, 'Hz'))), '-' , 'color', [zeros(1,3)]);
|
|
plot(freqs_vc, abs(squeeze(freqresp(G_vc_fast( 'Dv', 'Fu'), freqs_vc, 'Hz'))), '-' , 'color', [zeros(1,3), 0.5]);
|
|
plot(freqs_vc, abs(squeeze(freqresp(G_vc_fast_iff_hpf( 'Du', 'Fu'), freqs_vc, 'Hz'))), '-' , 'color', [colors(1,:)]);
|
|
plot(freqs_vc, abs(squeeze(freqresp(G_vc_fast_iff_hpf( 'Dv', 'Fu'), freqs_vc, 'Hz'))), '-' , 'color', [colors(1,:), 0.5]);
|
|
plot(freqs_vc, abs(squeeze(freqresp(G_vc_fast_iff_kp( 'Du', 'Fu'), freqs_vc, 'Hz'))), '-' , 'color', [colors(2,:)]);
|
|
plot(freqs_vc, abs(squeeze(freqresp(G_vc_fast_iff_kp( 'Dv', 'Fu'), freqs_vc, 'Hz'))), '-' , 'color', [colors(2,:), 0.5]);
|
|
plot(freqs_vc, abs(squeeze(freqresp(G_vc_fast_rdc( 'Du', 'Fu'), freqs_vc, 'Hz'))), '-' , 'color', [colors(3,:)]);
|
|
plot(freqs_vc, abs(squeeze(freqresp(G_vc_fast_rdc( 'Dv', 'Fu'), freqs_vc, 'Hz'))), '-' , 'color', [colors(3,:), 0.5]);
|
|
hold off;
|
|
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
|
|
ylabel('Magnitude [m/N]'); set(gca, 'XTickLabel',[]);
|
|
ylim([1e-8, 1e-2])
|
|
|
|
ax2 = nexttile;
|
|
hold on;
|
|
plot(freqs_vc, 180/pi*angle(squeeze(freqresp(G_vc_fast( 'Du', 'Fu'), freqs_vc, 'Hz'))), '-' , 'color', [zeros(1,3)]);
|
|
plot(freqs_vc, 180/pi*angle(squeeze(freqresp(G_vc_fast_iff_hpf( 'Du', 'Fu'), freqs_vc, 'Hz'))), '-' , 'color', [colors(1,:)]);
|
|
plot(freqs_vc, 180/pi*angle(squeeze(freqresp(G_vc_fast_iff_kp( 'Du', 'Fu'), freqs_vc, 'Hz'))), '-' , 'color', [colors(2,:)]);
|
|
plot(freqs_vc, 180/pi*angle(squeeze(freqresp(G_vc_fast_rdc( 'Du', 'Fu'), freqs_vc, 'Hz'))), '-' , '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([-180, 0]);
|
|
|
|
linkaxes([ax1,ax2],'x');
|
|
xlim([freqs_vc(1), freqs_vc(end)]);
|
|
#+end_src
|
|
|
|
#+begin_src matlab :tangle no :exports results :results file replace
|
|
exportFig('figs/rotating_nass_damped_plant_comp_vc.pdf', 'width', 'third', 'height', 500);
|
|
#+end_src
|
|
|
|
#+begin_src matlab :exports none :results none
|
|
freqs_md = logspace(0, 3, 1000);
|
|
|
|
figure;
|
|
tiledlayout(3, 1, 'TileSpacing', 'Compact', 'Padding', 'None');
|
|
|
|
ax1 = nexttile([2,1]);
|
|
hold on;
|
|
plot(freqs_md, abs(squeeze(freqresp(G_md_fast( 'Du', 'Fu'), freqs_md, 'Hz'))), '-' , 'color', [zeros(1,3)]);
|
|
plot(freqs_md, abs(squeeze(freqresp(G_md_fast( 'Dv', 'Fu'), freqs_md, 'Hz'))), '-' , 'color', [zeros(1,3), 0.5]);
|
|
plot(freqs_md, abs(squeeze(freqresp(G_md_fast_iff_hpf( 'Du', 'Fu'), freqs_md, 'Hz'))), '-' , 'color', [colors(1,:)]);
|
|
plot(freqs_md, abs(squeeze(freqresp(G_md_fast_iff_hpf( 'Dv', 'Fu'), freqs_md, 'Hz'))), '-' , 'color', [colors(1,:), 0.5]);
|
|
plot(freqs_md, abs(squeeze(freqresp(G_md_fast_iff_kp( 'Du', 'Fu'), freqs_md, 'Hz'))), '-' , 'color', [colors(2,:)]);
|
|
plot(freqs_md, abs(squeeze(freqresp(G_md_fast_iff_kp( 'Dv', 'Fu'), freqs_md, 'Hz'))), '-' , 'color', [colors(2,:), 0.5]);
|
|
plot(freqs_md, abs(squeeze(freqresp(G_md_fast_rdc( 'Du', 'Fu'), freqs_md, 'Hz'))), '-' , 'color', [colors(3,:)]);
|
|
plot(freqs_md, abs(squeeze(freqresp(G_md_fast_rdc( 'Dv', 'Fu'), freqs_md, 'Hz'))), '-' , 'color', [colors(3,:), 0.5]);
|
|
hold off;
|
|
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
|
|
ylabel('Magnitude [m/N]'); set(gca, 'XTickLabel',[]);
|
|
ylim([1e-10, 1e-4])
|
|
|
|
ax2 = nexttile;
|
|
hold on;
|
|
plot(freqs_md, 180/pi*angle(squeeze(freqresp(G_md_fast( 'Du', 'Fu'), freqs_md, 'Hz'))), '-' , 'color', [zeros(1,3)]);
|
|
plot(freqs_md, 180/pi*angle(squeeze(freqresp(G_md_fast_iff_hpf( 'Du', 'Fu'), freqs_md, 'Hz'))), '-' , 'color', [colors(1,:)]);
|
|
plot(freqs_md, 180/pi*angle(squeeze(freqresp(G_md_fast_iff_kp( 'Du', 'Fu'), freqs_md, 'Hz'))), '-' , 'color', [colors(2,:)]);
|
|
plot(freqs_md, 180/pi*angle(squeeze(freqresp(G_md_fast_rdc( 'Du', 'Fu'), freqs_md, 'Hz'))), '-' , '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([-180, 0]);
|
|
|
|
linkaxes([ax1,ax2],'x');
|
|
xlim([freqs_md(1), freqs_md(end)]);
|
|
#+end_src
|
|
|
|
#+begin_src matlab :tangle no :exports results :results file replace
|
|
exportFig('figs/rotating_nass_damped_plant_comp_md.pdf', 'width', 'third', 'height', 500);
|
|
#+end_src
|
|
|
|
#+begin_src matlab :exports none :results none
|
|
freqs_pz = logspace(0, 3, 1000);
|
|
|
|
figure;
|
|
tiledlayout(3, 1, 'TileSpacing', 'Compact', 'Padding', 'None');
|
|
|
|
ax1 = nexttile([2,1]);
|
|
hold on;
|
|
plot(freqs_pz, abs(squeeze(freqresp(G_pz_fast( 'Du', 'Fu'), freqs_pz, 'Hz'))), '-' , 'color', [zeros(1,3)], ...
|
|
'DisplayName', 'OL');
|
|
plot(freqs_pz, abs(squeeze(freqresp(G_pz_fast( 'Dv', 'Fu'), freqs_pz, 'Hz'))), '-' , 'color', [zeros(1,3), 0.5], ...
|
|
'DisplayName', 'Coupling');
|
|
plot(freqs_pz, abs(squeeze(freqresp(G_pz_fast_iff_hpf( 'Du', 'Fu'), freqs_pz, 'Hz'))), '-' , 'color', [colors(1,:)], ...
|
|
'DisplayName', 'IFF + HPF');
|
|
plot(freqs_pz, abs(squeeze(freqresp(G_pz_fast_iff_hpf( 'Dv', 'Fu'), freqs_pz, 'Hz'))), '-' , 'color', [colors(1,:), 0.5], ...
|
|
'HandleVisibility', 'off');
|
|
plot(freqs_pz, abs(squeeze(freqresp(G_pz_fast_iff_kp( 'Du', 'Fu'), freqs_pz, 'Hz'))), '-' , 'color', [colors(2,:)], ...
|
|
'DisplayName', 'IFF + $k_p$');
|
|
plot(freqs_pz, abs(squeeze(freqresp(G_pz_fast_iff_kp( 'Dv', 'Fu'), freqs_pz, 'Hz'))), '-' , 'color', [colors(2,:), 0.5], ...
|
|
'HandleVisibility', 'off');
|
|
plot(freqs_pz, abs(squeeze(freqresp(G_pz_fast_rdc( 'Du', 'Fu'), freqs_pz, 'Hz'))), '-' , 'color', [colors(3,:)], ...
|
|
'DisplayName', 'RDC');
|
|
plot(freqs_pz, abs(squeeze(freqresp(G_pz_fast_rdc( 'Dv', 'Fu'), freqs_pz, 'Hz'))), '-' , 'color', [colors(3,:), 0.5], ...
|
|
'HandleVisibility', 'off');
|
|
hold off;
|
|
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
|
|
ylabel('Magnitude [m/N]'); set(gca, 'XTickLabel',[]);
|
|
ylim([1e-12, 1e-6])
|
|
ldg = legend('location', 'northwest', 'FontSize', 8, 'NumColumns', 1);
|
|
ldg.ItemTokenSize = [20, 1];
|
|
|
|
ax2 = nexttile;
|
|
hold on;
|
|
plot(freqs_pz, 180/pi*angle(squeeze(freqresp(G_pz_fast( 'Du', 'Fu'), freqs_pz, 'Hz'))), '-' , 'color', [zeros(1,3)]);
|
|
plot(freqs_pz, 180/pi*angle(squeeze(freqresp(G_pz_fast_iff_hpf( 'Du', 'Fu'), freqs_pz, 'Hz'))), '-' , 'color', [colors(1,:)]);
|
|
plot(freqs_pz, 180/pi*angle(squeeze(freqresp(G_pz_fast_iff_kp( 'Du', 'Fu'), freqs_pz, 'Hz'))), '-' , 'color', [colors(2,:)]);
|
|
plot(freqs_pz, 180/pi*angle(squeeze(freqresp(G_pz_fast_rdc( 'Du', 'Fu'), freqs_pz, 'Hz'))), '-' , '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([-180, 0]);
|
|
|
|
linkaxes([ax1,ax2],'x');
|
|
xlim([freqs_pz(1), freqs_pz(end)]);
|
|
#+end_src
|
|
|
|
#+begin_src matlab :tangle no :exports results :results file replace
|
|
exportFig('figs/rotating_nass_damped_plant_comp_pz.pdf', 'width', 'third', 'height', 500);
|
|
#+end_src
|
|
|
|
#+name: fig:rotating_nass_damped_plant_comp
|
|
#+caption: Comparison of the damped plants for the three proposed active damping techniques (IFF with HPF in blue, IFF with $k_p$ in red and RDC in yellow). The direct terms are shown by solid lines, and the coupling terms are shown by the shaded lines. Three nano-hexapod stiffnesses are considered. For this analysis the rotating velocity is $\Omega = 60\,\text{rpm}$ and the suspended mass is $m_n + m_s = \SI{16}{\kg}$.
|
|
#+attr_latex: :options [htbp]
|
|
#+begin_figure
|
|
#+attr_latex: :caption \subcaption{\label{fig:rotating_nass_damped_plant_comp_vc}$k_n = 0.01\,N/\mu m$}
|
|
#+attr_latex: :options {0.33\textwidth}
|
|
#+begin_subfigure
|
|
#+attr_latex: :width 0.95\linewidth
|
|
[[file:figs/rotating_nass_damped_plant_comp_vc.png]]
|
|
#+end_subfigure
|
|
#+attr_latex: :caption \subcaption{\label{fig:rotating_nass_damped_plant_comp_md}$k_n = 1\,N/\mu m$}
|
|
#+attr_latex: :options {0.33\textwidth}
|
|
#+begin_subfigure
|
|
#+attr_latex: :width 0.95\linewidth
|
|
[[file:figs/rotating_nass_damped_plant_comp_md.png]]
|
|
#+end_subfigure
|
|
#+attr_latex: :caption \subcaption{\label{fig:rotating_nass_damped_plant_comp_pz}$k_n = 100\,N/\mu m$}
|
|
#+attr_latex: :options {0.33\textwidth}
|
|
#+begin_subfigure
|
|
#+attr_latex: :width 0.95\linewidth
|
|
[[file:figs/rotating_nass_damped_plant_comp_pz.png]]
|
|
#+end_subfigure
|
|
#+end_figure
|
|
|
|
* Nano-Active-Stabilization-System with rotation
|
|
:PROPERTIES:
|
|
:header-args:matlab+: :tangle matlab/rotating_8_nass.m
|
|
:END:
|
|
<<sec:rotating_nass>>
|
|
** Introduction :ignore:
|
|
Until now, the model used to study gyroscopic effects consisted of an infinitely stiff rotating stage with a X-Y suspended stage on top.
|
|
While quite simplistic, this allowed us to study the effects of rotation and the associated limitations when active damping is to be applied.
|
|
In this section, the limited compliance of the micro-station is considered as well as the rotation of the spindle.
|
|
|
|
** Matlab Init :noexport:ignore:
|
|
#+begin_src matlab :tangle no :results silent :noweb yes :var current_dir=(file-name-directory buffer-file-name)
|
|
<<matlab-dir>>
|
|
#+end_src
|
|
|
|
#+begin_src matlab :results silent :noweb yes
|
|
<<matlab-init>>
|
|
#+end_src
|
|
|
|
#+begin_src matlab :tangle no :noweb yes
|
|
<<m-init-path>>
|
|
#+end_src
|
|
|
|
#+begin_src matlab :eval no :noweb yes
|
|
<<m-init-path-tangle>>
|
|
#+end_src
|
|
|
|
#+begin_src matlab :noweb yes
|
|
<<m-init-other>>
|
|
#+end_src
|
|
|
|
#+begin_src matlab
|
|
%% Nano-Hexapod on top of Micro-Station model
|
|
mdl = 'nass_rotating_model';
|
|
|
|
%% Load micro-station parameters
|
|
load('uniaxial_micro_station_parameters.mat')
|
|
|
|
%% Load controllers
|
|
load('nass_controllers.mat');
|
|
#+end_src
|
|
|
|
** Nano Active Stabilization System model
|
|
To have a more realistic dynamics model of the NASS, the 2-DoF nano-hexapod (modeled as shown in Figure ref:fig:rotating_3dof_model_schematic) is now located on top of a model of the micro-station including (see Figure ref:fig:rotating_nass_model for a 3D view):
|
|
- the floor whose motion is imposed
|
|
- a 2-DoF granite ($k_{g,x} = k_{g,y} = \SI{950}{\N\per\mu\m}$, $m_g = \SI{2500}{\kg}$)
|
|
- a 2-DoF $T_y$ stage ($k_{t,x} = k_{t,y} = \SI{520}{\N\per\mu\m}$, $m_t = \SI{600}{\kg}$)
|
|
- a spindle (vertical rotation) stage whose rotation is imposed ($m_s = \SI{600}{\kg}$)
|
|
- a 2-DoF micro-hexapod ($k_{h,x} = k_{h,y} = \SI{61}{\N\per\mu\m}$, $m_h = \SI{15}{\kg}$)
|
|
|
|
A payload is rigidly fixed to the nano-hexapod and the $x,y$ motion of the payload is measured with respect to the granite.
|
|
|
|
#+name: fig:rotating_nass_model
|
|
#+caption: 3D view of the Nano-Active-Stabilization-System model.
|
|
#+attr_latex: :scale 0.7
|
|
[[file:figs/rotating_nass_model.png]]
|
|
|
|
** System dynamics
|
|
|
|
The dynamics of the undamped and damped plants are identified using the optimal parameters found in Section ref:sec:rotating_nano_hexapod.
|
|
The obtained dynamics are compared in Figure ref:fig:rotating_nass_plant_comp_stiffness in which the direct terms are shown by the solid curves and the coupling terms are shown by the shaded ones.
|
|
It can be observed that:
|
|
- The coupling (quantified by the ratio between the off-diagonal and direct terms) is higher for the soft nano-hexapod
|
|
- Damping added using the three proposed techniques is quite high, and the obtained plant is rather easy to control
|
|
- There is some coupling between nano-hexapod and micro-station dynamics for the stiff nano-hexapod (mode at 200Hz)
|
|
- The two proposed IFF modifications yield similar results
|
|
|
|
#+begin_src matlab
|
|
%% System parameters
|
|
mn = 15; % Nano-Hexapod mass [kg]
|
|
ms = 1; % Sample Mass [kg]
|
|
|
|
% General Configuration
|
|
model_config = struct();
|
|
model_config.controller = "open_loop"; % Default: Open-Loop
|
|
model_config.Tuv_type = "normal"; % Default: 2DoF stage
|
|
|
|
% Input/Output definition
|
|
clear io; io_i = 1;
|
|
io(io_i) = linio([mdl, '/controller'], 1, 'openinput'); io_i = io_i + 1; % Actuator Forces [Fu, Fv]
|
|
io(io_i) = linio([mdl, '/fd'], 1, 'openinput'); io_i = io_i + 1; % Direct Forces on Sample [Fdx, Fdy]
|
|
io(io_i) = linio([mdl, '/xf'], 1, 'openinput'); io_i = io_i + 1; % Floor Motion [Dfx, Dfy]
|
|
io(io_i) = linio([mdl, '/ft'], 1, 'openinput'); io_i = io_i + 1; % Micro-Station Disturbances [Ftx, Fty]
|
|
io(io_i) = linio([mdl, '/nano_hexapod'], 1, 'openoutput'); io_i = io_i + 1; % [Fmu, Fmv]
|
|
io(io_i) = linio([mdl, '/nano_hexapod'], 2, 'openoutput'); io_i = io_i + 1; % [Du, Dv]
|
|
io(io_i) = linio([mdl, '/ext_metrology'],1, 'openoutput'); io_i = io_i + 1; % [Dx, Dy]
|
|
|
|
%% Identify plant without parallel stiffness
|
|
% Voice Coil (i.e. soft) Nano-Hexapod
|
|
kn = 1e4; % Nano-Hexapod Stiffness [N/m]
|
|
cn = 2*0.005*sqrt((ms + mn)*kn); % Nano-Hexapod Damping [N/(m/s)]
|
|
|
|
Wz = 0; % Rotating Velocity [rad/s]
|
|
G_vc_norot = linearize(mdl, io, 0.0);
|
|
G_vc_norot.InputName = {'Fu', 'Fv', 'Fdx', 'Fdy', 'Dfx', 'Dfy', 'Ftx', 'Fty'};
|
|
G_vc_norot.OutputName = {'fu', 'fv', 'Du', 'Dv', 'Dx', 'Dy'};
|
|
|
|
Wz = 2*pi; % Rotating Velocity [rad/s]
|
|
G_vc_fast = linearize(mdl, io, 0.0);
|
|
G_vc_fast.InputName = {'Fu', 'Fv', 'Fdx', 'Fdy', 'Dfx', 'Dfy', 'Ftx', 'Fty'};
|
|
G_vc_fast.OutputName = {'fu', 'fv', 'Du', 'Dv', 'Dx', 'Dy'};
|
|
|
|
% APA (i.e. relatively stiff) Nano-Hexapod
|
|
kn = 1e6; % Nano-Hexapod Stiffness [N/m]
|
|
cn = 2*0.005*sqrt((ms + mn)*kn); % Nano-Hexapod Damping [N/(m/s)]
|
|
|
|
Wz = 0; % Rotating Velocity [rad/s]
|
|
G_md_norot = linearize(mdl, io, 0.0);
|
|
G_md_norot.InputName = {'Fu', 'Fv', 'Fdx', 'Fdy', 'Dfx', 'Dfy', 'Ftx', 'Fty'};
|
|
G_md_norot.OutputName = {'fu', 'fv', 'Du', 'Dv', 'Dx', 'Dy'};
|
|
|
|
Wz = 2*pi; % Rotating Velocity [rad/s]
|
|
G_md_fast = linearize(mdl, io, 0.0);
|
|
G_md_fast.InputName = {'Fu', 'Fv', 'Fdx', 'Fdy', 'Dfx', 'Dfy', 'Ftx', 'Fty'};
|
|
G_md_fast.OutputName = {'fu', 'fv', 'Du', 'Dv', 'Dx', 'Dy'};
|
|
|
|
% Piezoelectric (i.e. stiff) Nano-Hexapod
|
|
kn = 1e8; % Nano-Hexapod Stiffness [N/m]
|
|
cn = 2*0.005*sqrt((ms + mn)*kn); % Nano-Hexapod Damping [N/(m/s)]
|
|
|
|
Wz = 0; % Rotating Velocity [rad/s]
|
|
G_pz_norot = linearize(mdl, io, 0.0);
|
|
G_pz_norot.InputName = {'Fu', 'Fv', 'Fdx', 'Fdy', 'Dfx', 'Dfy', 'Ftx', 'Fty'};
|
|
G_pz_norot.OutputName = {'fu', 'fv', 'Du', 'Dv', 'Dx', 'Dy'};
|
|
|
|
Wz = 2*pi; % Rotating Velocity [rad/s]
|
|
G_pz_fast = linearize(mdl, io, 0.0);
|
|
G_pz_fast.InputName = {'Fu', 'Fv', 'Fdx', 'Fdy', 'Dfx', 'Dfy', 'Ftx', 'Fty'};
|
|
G_pz_fast.OutputName = {'fu', 'fv', 'Du', 'Dv', 'Dx', 'Dy'};
|
|
|
|
%% Identify plants with Parallel stiffnesses
|
|
model_config.Tuv_type = "parallel_k"; % Default: 2DoF stage
|
|
|
|
% Voice Coil
|
|
kp = 1e3;
|
|
cp = 2*0.001*sqrt((ms + mn)*kp);
|
|
kn = 1e4-kp; % Nano-Hexapod Stiffness [N/m]
|
|
cn = 2*0.01*sqrt((ms + mn)*kn); % Nano-Hexapod Damping [N/(m/s)]
|
|
|
|
% Identify dynamics
|
|
Wz = 2*pi; % [rad/s]
|
|
G_vc_kp_fast = linearize(mdl, io, 0);
|
|
G_vc_kp_fast.InputName = {'Fu', 'Fv', 'Fdx', 'Fdy', 'Dfx', 'Dfy', 'Ftx', 'Fty'};
|
|
G_vc_kp_fast.OutputName = {'fu', 'fv', 'Du', 'Dv', 'Dx', 'Dy'};
|
|
|
|
Wz = 0; % [rad/s]
|
|
G_vc_kp_norot = linearize(mdl, io, 0);
|
|
G_vc_kp_norot.InputName = {'Fu', 'Fv', 'Fdx', 'Fdy', 'Dfx', 'Dfy', 'Ftx', 'Fty'};
|
|
G_vc_kp_norot.OutputName = {'fu', 'fv', 'Du', 'Dv', 'Dx', 'Dy'};
|
|
|
|
% APA
|
|
kp = 1e4;
|
|
cp = 2*0.001*sqrt((ms + mn)*kp);
|
|
kn = 1e6 - kp; % Nano-Hexapod Stiffness [N/m]
|
|
cn = 2*0.01*sqrt((ms + mn)*kn); % Nano-Hexapod Damping [N/(m/s)]
|
|
|
|
% Identify dynamics
|
|
Wz = 2*pi; % [rad/s]
|
|
G_md_kp_fast = linearize(mdl, io, 0);
|
|
G_md_kp_fast.InputName = {'Fu', 'Fv', 'Fdx', 'Fdy', 'Dfx', 'Dfy', 'Ftx', 'Fty'};
|
|
G_md_kp_fast.OutputName = {'fu', 'fv', 'Du', 'Dv', 'Dx', 'Dy'};
|
|
|
|
Wz = 0; % [rad/s]
|
|
G_md_kp_norot = linearize(mdl, io, 0);
|
|
G_md_kp_norot.InputName = {'Fu', 'Fv', 'Fdx', 'Fdy', 'Dfx', 'Dfy', 'Ftx', 'Fty'};
|
|
G_md_kp_norot.OutputName = {'fu', 'fv', 'Du', 'Dv', 'Dx', 'Dy'};
|
|
|
|
% Piezo
|
|
kp = 1e5;
|
|
cp = 2*0.001*sqrt((ms + mn)*kp);
|
|
kn = 1e8 - kp; % Nano-Hexapod Stiffness [N/m]
|
|
cn = 2*0.01*sqrt((ms + mn)*kn); % Nano-Hexapod Damping [N/(m/s)]
|
|
|
|
% Identify dynamics
|
|
Wz = 2*pi; % [rad/s]
|
|
G_pz_kp_fast = linearize(mdl, io, 0);
|
|
G_pz_kp_fast.InputName = {'Fu', 'Fv', 'Fdx', 'Fdy', 'Dfx', 'Dfy', 'Ftx', 'Fty'};
|
|
G_pz_kp_fast.OutputName = {'fu', 'fv', 'Du', 'Dv', 'Dx', 'Dy'};
|
|
|
|
Wz = 0; % [rad/s]
|
|
G_pz_kp_norot = linearize(mdl, io, 0);
|
|
G_pz_kp_norot.InputName = {'Fu', 'Fv', 'Fdx', 'Fdy', 'Dfx', 'Dfy', 'Ftx', 'Fty'};
|
|
G_pz_kp_norot.OutputName = {'fu', 'fv', 'Du', 'Dv', 'Dx', 'Dy'};
|
|
|
|
%% Compute dampepd plants
|
|
% Closed-Loop Plants - IFF with HPF
|
|
G_vc_norot_iff_hpf = feedback(G_vc_norot, Kiff_hpf_vc, 'name');
|
|
G_vc_fast_iff_hpf = feedback(G_vc_fast, Kiff_hpf_vc, 'name');
|
|
|
|
G_md_norot_iff_hpf = feedback(G_md_norot, Kiff_hpf_md, 'name');
|
|
G_md_fast_iff_hpf = feedback(G_md_fast, Kiff_hpf_md, 'name');
|
|
|
|
G_pz_norot_iff_hpf = feedback(G_pz_norot, Kiff_hpf_pz, 'name');
|
|
G_pz_fast_iff_hpf = feedback(G_pz_fast, Kiff_hpf_pz, 'name');
|
|
|
|
% Closed-Loop Plants - IFF with Parallel Stiffness
|
|
G_vc_norot_iff_kp = feedback(G_vc_kp_norot, Kiff_kp_vc, 'name');
|
|
G_vc_fast_iff_kp = feedback(G_vc_kp_fast, Kiff_kp_vc, 'name');
|
|
|
|
G_md_norot_iff_kp = feedback(G_md_kp_norot, Kiff_kp_md, 'name');
|
|
G_md_fast_iff_kp = feedback(G_md_kp_fast, Kiff_kp_md, 'name');
|
|
|
|
G_pz_norot_iff_kp = feedback(G_pz_kp_norot, Kiff_kp_pz, 'name');
|
|
G_pz_fast_iff_kp = feedback(G_pz_kp_fast, Kiff_kp_pz, 'name');
|
|
|
|
% Closed-Loop Plants - RDC
|
|
G_vc_norot_rdc = feedback(G_vc_norot, Krdc_vc, 'name');
|
|
G_vc_fast_rdc = feedback(G_vc_fast, Krdc_vc, 'name');
|
|
|
|
G_md_norot_rdc = feedback(G_md_norot, Krdc_md, 'name');
|
|
G_md_fast_rdc = feedback(G_md_fast, Krdc_md, 'name');
|
|
|
|
G_pz_norot_rdc = feedback(G_pz_norot, Krdc_pz, 'name');
|
|
G_pz_fast_rdc = feedback(G_pz_fast, Krdc_pz, 'name');
|
|
#+end_src
|
|
|
|
#+begin_src matlab :exports none :results none
|
|
%% Bode plot of the transfer function from nano-hexapod actuator to measured motion by the external metrology
|
|
freqs_vc = logspace(-1, 2, 1000);
|
|
|
|
figure;
|
|
tiledlayout(3, 1, 'TileSpacing', 'Compact', 'Padding', 'None');
|
|
|
|
ax1 = nexttile([2,1]);
|
|
hold on;
|
|
plot(freqs_vc, abs(squeeze(freqresp(G_vc_fast('Dx', 'Fu'), freqs_vc, 'Hz'))), 'color', zeros(1,3), ...
|
|
'DisplayName', 'OL');
|
|
plot(freqs_vc, abs(squeeze(freqresp(G_vc_fast('Dy', 'Fu'), freqs_vc, 'Hz'))), 'color', [zeros(1,3), 0.5], ...
|
|
'DisplayName', 'Coupling');
|
|
plot(freqs_vc, abs(squeeze(freqresp(G_vc_fast_iff_hpf('Dx', 'Fu'), freqs_vc, 'Hz'))), 'color', colors(1,:), ...
|
|
'DisplayName', 'IFF + $k_p$');
|
|
plot(freqs_vc, abs(squeeze(freqresp(G_vc_fast_iff_hpf('Dy', 'Fu'), freqs_vc, 'Hz'))), 'color', [colors(1,:), 0.5], ...
|
|
'HandleVisibility', 'off');
|
|
plot(freqs_vc, abs(squeeze(freqresp(G_vc_fast_iff_kp('Dx', 'Fu'), freqs_vc, 'Hz'))), 'color', colors(2,:), ...
|
|
'DisplayName', 'IFF + HPF');
|
|
plot(freqs_vc, abs(squeeze(freqresp(G_vc_fast_iff_kp('Dy', 'Fu'), freqs_vc, 'Hz'))), 'color', [colors(2,:), 0.5], ...
|
|
'HandleVisibility', 'off');
|
|
plot(freqs_vc, abs(squeeze(freqresp(G_vc_fast_rdc('Dx', 'Fu'), freqs_vc, 'Hz'))), 'color', colors(3,:), ...
|
|
'DisplayName', 'RDC');
|
|
plot(freqs_vc, abs(squeeze(freqresp(G_vc_fast_rdc('Dy', 'Fu'), freqs_vc, 'Hz'))), 'color', [colors(3,:), 0.5], ...
|
|
'HandleVisibility', 'off');
|
|
hold off;
|
|
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
|
|
ylabel('Magnitude [m/N]'); set(gca, 'XTickLabel',[]);
|
|
ylim([1e-8, 1e-2])
|
|
|
|
ax2 = nexttile;
|
|
hold on;
|
|
plot(freqs_vc, 180/pi*unwrap(angle(squeeze(freqresp(G_vc_fast('Dx', 'Fu'), freqs_vc, 'Hz')))), 'color', zeros(1,3));
|
|
plot(freqs_vc, 180/pi*unwrap(angle(squeeze(freqresp(G_vc_fast_iff_hpf('Dx', 'Fu'), freqs_vc, 'Hz')))), 'color', colors(1,:));
|
|
plot(freqs_vc, 180/pi*unwrap(angle(squeeze(freqresp(G_vc_fast_iff_kp('Dx', 'Fu'), freqs_vc, 'Hz')))), 'color', colors(2,:));
|
|
plot(freqs_vc, 180/pi*unwrap(angle(squeeze(freqresp(G_vc_fast_rdc('Dx', 'Fu'), freqs_vc, 'Hz')))), '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([ -200, 20]);
|
|
|
|
linkaxes([ax,ax2],'x');
|
|
xlim([freqs_vc(1), freqs_vc(end)]);
|
|
xticks([1e-1, 1e0, 1e1]);
|
|
#+end_src
|
|
|
|
#+begin_src matlab :tangle no :exports results :results file none
|
|
exportFig('figs/rotating_nass_plant_comp_stiffness_vc.pdf', 'width', 'third', 'height', 600);
|
|
#+end_src
|
|
|
|
#+begin_src matlab :exports none :results none
|
|
freqs_md = logspace(0, 3, 1000);
|
|
figure;
|
|
tiledlayout(3, 1, 'TileSpacing', 'Compact', 'Padding', 'None');
|
|
|
|
ax1 = nexttile([2,1]);
|
|
hold on;
|
|
plot(freqs_md, abs(squeeze(freqresp(G_md_fast('Dx', 'Fu'), freqs_md, 'Hz'))), 'color', zeros(1,3), ...
|
|
'DisplayName', 'OL');
|
|
plot(freqs_md, abs(squeeze(freqresp(G_md_fast('Dy', 'Fu'), freqs_md, 'Hz'))), 'color', [zeros(1,3), 0.5], ...
|
|
'DisplayName', 'Coupling');
|
|
plot(freqs_md, abs(squeeze(freqresp(G_md_fast_iff_hpf('Dx', 'Fu'), freqs_md, 'Hz'))), 'color', colors(1,:), ...
|
|
'DisplayName', 'IFF + $k_p$');
|
|
plot(freqs_md, abs(squeeze(freqresp(G_md_fast_iff_hpf('Dy', 'Fu'), freqs_md, 'Hz'))), 'color', [colors(1,:), 0.5], ...
|
|
'HandleVisibility', 'off');
|
|
plot(freqs_md, abs(squeeze(freqresp(G_md_fast_iff_kp('Dx', 'Fu'), freqs_md, 'Hz'))), 'color', colors(2,:), ...
|
|
'DisplayName', 'IFF + HPF');
|
|
plot(freqs_md, abs(squeeze(freqresp(G_md_fast_iff_kp('Dy', 'Fu'), freqs_md, 'Hz'))), 'color', [colors(2,:), 0.5], ...
|
|
'HandleVisibility', 'off');
|
|
plot(freqs_md, abs(squeeze(freqresp(G_md_fast_rdc('Dx', 'Fu'), freqs_md, 'Hz'))), 'color', colors(3,:), ...
|
|
'DisplayName', 'RDC');
|
|
plot(freqs_md, abs(squeeze(freqresp(G_md_fast_rdc('Dy', 'Fu'), freqs_md, 'Hz'))), 'color', [colors(3,:), 0.5], ...
|
|
'HandleVisibility', 'off');
|
|
hold off;
|
|
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
|
|
ylabel('Magnitude [m/N]'); set(gca, 'XTickLabel',[]);
|
|
ylim([1e-10, 1e-4])
|
|
|
|
ax2 = nexttile;
|
|
hold on;
|
|
plot(freqs_md, 180/pi*unwrap(angle(squeeze(freqresp(G_md_fast('Dx', 'Fu'), freqs_md, 'Hz')))), 'color', zeros(1,3));
|
|
plot(freqs_md, 180/pi*unwrap(angle(squeeze(freqresp(G_md_fast_iff_hpf('Dx', 'Fu'), freqs_md, 'Hz')))), 'color', colors(1,:));
|
|
plot(freqs_md, 180/pi*unwrap(angle(squeeze(freqresp(G_md_fast_iff_kp('Dx', 'Fu'), freqs_md, 'Hz')))), 'color', colors(2,:));
|
|
plot(freqs_md, 180/pi*unwrap(angle(squeeze(freqresp(G_md_fast_rdc('Dx', 'Fu'), freqs_md, 'Hz')))), '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([ -200, 20]);
|
|
|
|
linkaxes([ax1,ax2],'x');
|
|
xlim([freqs_md(1), freqs_md(end)]);
|
|
xticks([1e0, 1e1, 1e2]);
|
|
#+end_src
|
|
|
|
#+begin_src matlab :tangle no :exports results :results file none
|
|
exportFig('figs/rotating_nass_plant_comp_stiffness_md.pdf', 'width', 'third', 'height', 600);
|
|
#+end_src
|
|
|
|
#+begin_src matlab :exports none :results none
|
|
freqs_pz = logspace(0, 3, 1000);
|
|
figure;
|
|
tiledlayout(3, 1, 'TileSpacing', 'Compact', 'Padding', 'None');
|
|
|
|
ax1 = nexttile([2,1]);
|
|
hold on;
|
|
plot(freqs_pz, abs(squeeze(freqresp(G_pz_fast('Dx', 'Fu'), freqs_pz, 'Hz'))), 'color', zeros(1,3), ...
|
|
'DisplayName', 'OL');
|
|
plot(freqs_pz, abs(squeeze(freqresp(G_pz_fast('Dy', 'Fu'), freqs_pz, 'Hz'))), 'color', [zeros(1,3), 0.5], ...
|
|
'DisplayName', 'Coupling');
|
|
plot(freqs_pz, abs(squeeze(freqresp(G_pz_fast_iff_hpf('Dx', 'Fu'), freqs_pz, 'Hz'))), 'color', colors(1,:), ...
|
|
'DisplayName', 'IFF + $k_p$');
|
|
plot(freqs_pz, abs(squeeze(freqresp(G_pz_fast_iff_hpf('Dy', 'Fu'), freqs_pz, 'Hz'))), 'color', [colors(1,:), 0.5], ...
|
|
'HandleVisibility', 'off');
|
|
plot(freqs_pz, abs(squeeze(freqresp(G_pz_fast_iff_kp('Dx', 'Fu'), freqs_pz, 'Hz'))), 'color', colors(2,:), ...
|
|
'DisplayName', 'IFF + HPF');
|
|
plot(freqs_pz, abs(squeeze(freqresp(G_pz_fast_iff_kp('Dy', 'Fu'), freqs_pz, 'Hz'))), 'color', [colors(2,:), 0.5], ...
|
|
'HandleVisibility', 'off');
|
|
plot(freqs_pz, abs(squeeze(freqresp(G_pz_fast_rdc('Dx', 'Fu'), freqs_pz, 'Hz'))), 'color', colors(3,:), ...
|
|
'DisplayName', 'RDC');
|
|
plot(freqs_pz, abs(squeeze(freqresp(G_pz_fast_rdc('Dy', 'Fu'), freqs_pz, 'Hz'))), 'color', [colors(3,:), 0.5], ...
|
|
'HandleVisibility', 'off');
|
|
hold off;
|
|
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
|
|
ylabel('Magnitude [m/N]'); set(gca, 'XTickLabel',[]);
|
|
ylim([1e-12, 1e-6])
|
|
ldg = legend('location', 'northwest', 'FontSize', 8, 'NumColumns', 1);
|
|
ldg.ItemTokenSize = [20, 1];
|
|
|
|
ax2 = nexttile;
|
|
hold on;
|
|
plot(freqs_pz, 180/pi*unwrap(angle(squeeze(freqresp(G_pz_fast('Dx', 'Fu'), freqs_pz, 'Hz')))), 'color', zeros(1,3));
|
|
plot(freqs_pz, 180/pi*unwrap(angle(squeeze(freqresp(G_pz_fast_iff_hpf('Dx', 'Fu'), freqs_pz, 'Hz')))), 'color', colors(1,:));
|
|
plot(freqs_pz, 180/pi*unwrap(angle(squeeze(freqresp(G_pz_fast_iff_kp('Dx', 'Fu'), freqs_pz, 'Hz')))), 'color', colors(2,:));
|
|
plot(freqs_pz, 180/pi*unwrap(angle(squeeze(freqresp(G_pz_fast_rdc('Dx', 'Fu'), freqs_pz, 'Hz')))), '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([ -200, 20]);
|
|
|
|
linkaxes([ax1,ax2],'x');
|
|
xlim([freqs_pz(1), freqs_pz(end)]);
|
|
xticks([1e0, 1e1, 1e2]);
|
|
#+end_src
|
|
|
|
#+begin_src matlab :tangle no :exports results :results file none
|
|
exportFig('figs/rotating_nass_plant_comp_stiffness_pz.pdf', 'width', 'third', 'height', 600);
|
|
#+end_src
|
|
|
|
#+name: fig:rotating_nass_plant_comp_stiffness
|
|
#+caption: Bode plot of the transfer function from nano-hexapod actuator to measured motion by the external metrology
|
|
#+attr_latex: :options [htbp]
|
|
#+begin_figure
|
|
#+attr_latex: :caption \subcaption{\label{fig:rotating_nass_plant_comp_stiffness_vc}$k_n = 0.01\,N/\mu m$}
|
|
#+attr_latex: :options {0.33\textwidth}
|
|
#+begin_subfigure
|
|
#+attr_latex: :width 0.95\linewidth
|
|
[[file:figs/rotating_nass_plant_comp_stiffness_vc.png]]
|
|
#+end_subfigure
|
|
#+attr_latex: :caption \subcaption{\label{fig:rotating_nass_plant_comp_stiffness_md}$k_n = 1\,N/\mu m$}
|
|
#+attr_latex: :options {0.33\textwidth}
|
|
#+begin_subfigure
|
|
#+attr_latex: :width 0.95\linewidth
|
|
[[file:figs/rotating_nass_plant_comp_stiffness_md.png]]
|
|
#+end_subfigure
|
|
#+attr_latex: :caption \subcaption{\label{fig:rotating_nass_plant_comp_stiffness_pz}$k_n = 100\,N/\mu m$}
|
|
#+attr_latex: :options {0.33\textwidth}
|
|
#+begin_subfigure
|
|
#+attr_latex: :width 0.95\linewidth
|
|
[[file:figs/rotating_nass_plant_comp_stiffness_pz.png]]
|
|
#+end_subfigure
|
|
#+end_figure
|
|
|
|
** Effect of disturbances
|
|
|
|
The effect of three disturbances are considered (as for the uniaxial model), floor motion $[x_{f,x},\ x_{f,y}]$ (Figure ref:fig:rotating_nass_effect_floor_motion), micro-Station vibrations $[f_{t,x},\ f_{t,y}]$ (Figure ref:fig:rotating_nass_effect_stage_vibration) and direct forces applied on the sample $[f_{s,x},\ f_{s,y}]$ (Figure ref:fig:rotating_nass_effect_direct_forces).
|
|
Note that only the transfer functions from the disturbances in the $x$ direction to the relative position $d_x$ between the sample and the granite in the $x$ direction are displayed because the transfer functions in the $y$ direction are the same due to the system symmetry.
|
|
|
|
Conclusions are similar than those of the uniaxial (non-rotating) model:
|
|
- Regarding the effect of floor motion and forces applied on the payload:
|
|
- The stiffer, the better. This can be seen in Figures ref:fig:rotating_nass_effect_floor_motion and ref:fig:rotating_nass_effect_direct_forces where the magnitudes for the stiff hexapod are lower than those for the soft one
|
|
- acrshort:iff degrades the performance at low-frequency compared to acrshort:rdc
|
|
- Regarding the effect of micro-station vibrations:
|
|
- Having a soft nano-hexapod allows filtering of these vibrations between the suspension modes of the nano-hexapod and some flexible modes of the micro-station. Using relative damping control reduces this filtering (Figure ref:fig:rotating_nass_effect_stage_vibration_vc).
|
|
|
|
#+begin_src matlab :exports none :results none
|
|
%% Effect of Floor motion on the position error - Comparison of active damping techniques for the three nano-hexapod stiffnesses
|
|
freqs = logspace(-1, 3, 1000);
|
|
|
|
figure;
|
|
hold on;
|
|
plot(freqs, abs(squeeze(freqresp(G_vc_fast('Dx', 'Dfx'), freqs, 'Hz'))), 'color', zeros(1,3), ...
|
|
'DisplayName', 'OL');
|
|
plot(freqs, abs(squeeze(freqresp(G_vc_fast_iff_hpf('Dx', 'Dfx'), freqs, 'Hz'))), 'color', colors(1,:), ...
|
|
'DisplayName', 'IFF + $k_p$');
|
|
plot(freqs, abs(squeeze(freqresp(G_vc_fast_iff_kp('Dx', 'Dfx'), freqs, 'Hz'))), 'color', colors(2,:), ...
|
|
'DisplayName', 'IFF + HPF');
|
|
plot(freqs, abs(squeeze(freqresp(G_vc_fast_rdc('Dx', 'Dfx'), freqs, 'Hz'))), 'color', colors(3,:), ...
|
|
'DisplayName', 'RDC');
|
|
hold off;
|
|
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
|
|
xlabel('Frequency [Hz]'); ylabel('Magnitude $d_x/x_{f,x}$ [m/N]');
|
|
xticks([1e-1, 1e0, 1e1, 1e2, 1e3]);
|
|
xtickangle(0)
|
|
ylim([1e-4, 1e2]);
|
|
#+end_src
|
|
|
|
#+begin_src matlab :tangle no :exports results :results file none
|
|
exportFig('figs/rotating_nass_effect_floor_motion_vc.pdf', 'width', 'third', 'height', 450);
|
|
#+end_src
|
|
|
|
#+begin_src matlab :exports none :results none
|
|
figure;
|
|
hold on;
|
|
plot(freqs, abs(squeeze(freqresp(G_md_fast('Dx', 'Dfx'), freqs, 'Hz'))), 'color', zeros(1,3), ...
|
|
'DisplayName', 'OL');
|
|
plot(freqs, abs(squeeze(freqresp(G_md_fast_iff_hpf('Dx', 'Dfx'), freqs, 'Hz'))), 'color', colors(1,:), ...
|
|
'DisplayName', 'IFF + $k_p$');
|
|
plot(freqs, abs(squeeze(freqresp(G_md_fast_iff_kp('Dx', 'Dfx'), freqs, 'Hz'))), 'color', colors(2,:), ...
|
|
'DisplayName', 'IFF + HPF');
|
|
plot(freqs, abs(squeeze(freqresp(G_md_fast_rdc('Dx', 'Dfx'), freqs, 'Hz'))), 'color', colors(3,:), ...
|
|
'DisplayName', 'RDC');
|
|
hold off;
|
|
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
|
|
xlabel('Frequency [Hz]'); ylabel('Magnitude $d_x/x_{f,x}$ [m/N]');
|
|
xticks([1e-1, 1e0, 1e1, 1e2, 1e3]);
|
|
xtickangle(0)
|
|
ylim([1e-4, 1e2]);
|
|
#+end_src
|
|
|
|
#+begin_src matlab :tangle no :exports results :results file none
|
|
exportFig('figs/rotating_nass_effect_floor_motion_md.pdf', 'width', 'third', 'height', 450);
|
|
#+end_src
|
|
|
|
#+begin_src matlab :exports none :results none
|
|
figure;
|
|
hold on;
|
|
plot(freqs, abs(squeeze(freqresp(G_pz_fast('Dx', 'Dfx'), freqs, 'Hz'))), 'color', zeros(1,3), ...
|
|
'DisplayName', 'OL');
|
|
plot(freqs, abs(squeeze(freqresp(G_pz_fast_iff_hpf('Dx', 'Dfx'), freqs, 'Hz'))), 'color', colors(1,:), ...
|
|
'DisplayName', 'IFF + $k_p$');
|
|
plot(freqs, abs(squeeze(freqresp(G_pz_fast_iff_kp('Dx', 'Dfx'), freqs, 'Hz'))), 'color', colors(2,:), ...
|
|
'DisplayName', 'IFF + HPF');
|
|
plot(freqs, abs(squeeze(freqresp(G_pz_fast_rdc('Dx', 'Dfx'), freqs, 'Hz'))), 'color', colors(3,:), ...
|
|
'DisplayName', 'RDC');
|
|
hold off;
|
|
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
|
|
xlabel('Frequency [Hz]'); ylabel('Magnitude $d_x/x_{f,x}$ [m/N]');
|
|
xticks([1e-1, 1e0, 1e1, 1e2, 1e3]);
|
|
xtickangle(0)
|
|
ldg = legend('location', 'southeast', 'FontSize', 8, 'NumColumns', 1);
|
|
ldg.ItemTokenSize = [15, 1];
|
|
ylim([1e-4, 1e2]);
|
|
#+end_src
|
|
|
|
#+begin_src matlab :tangle no :exports results :results file none
|
|
exportFig('figs/rotating_nass_effect_floor_motion_pz.pdf', 'width', 'third', 'height', 450);
|
|
#+end_src
|
|
|
|
#+name: fig:rotating_nass_effect_floor_motion
|
|
#+caption: Effect of floor motion $x_{f,x}$ on the position error $d_x$ - Comparison of active damping techniques for the three nano-hexapod stiffnesses. IFF is shown to increase the sensitivity to floor motion at low-frequency.
|
|
#+attr_latex: :options [htbp]
|
|
#+begin_figure
|
|
#+attr_latex: :caption \subcaption{\label{fig:rotating_nass_effect_floor_motion_vc}$k_n = 0.01\,N/\mu m$}
|
|
#+attr_latex: :options {0.33\textwidth}
|
|
#+begin_subfigure
|
|
#+attr_latex: :width 0.95\linewidth
|
|
[[file:figs/rotating_nass_effect_floor_motion_vc.png]]
|
|
#+end_subfigure
|
|
#+attr_latex: :caption \subcaption{\label{fig:rotating_nass_effect_floor_motion_md}$k_n = 1\,N/\mu m$}
|
|
#+attr_latex: :options {0.33\textwidth}
|
|
#+begin_subfigure
|
|
#+attr_latex: :width 0.95\linewidth
|
|
[[file:figs/rotating_nass_effect_floor_motion_md.png]]
|
|
#+end_subfigure
|
|
#+attr_latex: :caption \subcaption{\label{fig:rotating_nass_effect_floor_motion_pz}$k_n = 100\,N/\mu m$}
|
|
#+attr_latex: :options {0.33\textwidth}
|
|
#+begin_subfigure
|
|
#+attr_latex: :width 0.95\linewidth
|
|
[[file:figs/rotating_nass_effect_floor_motion_pz.png]]
|
|
#+end_subfigure
|
|
#+end_figure
|
|
|
|
#+begin_src matlab :exports none :results none
|
|
%% Effect of micro-station vibrations on the position error - Comparison of active damping techniques for the three nano-hexapod stiffnesses
|
|
figure;
|
|
hold on;
|
|
plot(freqs, abs(squeeze(freqresp(G_vc_fast('Dx', 'Ftx'), freqs, 'Hz'))), 'color', zeros(1,3), ...
|
|
'DisplayName', 'OL');
|
|
plot(freqs, abs(squeeze(freqresp(G_vc_fast_iff_hpf('Dx', 'Ftx'), freqs, 'Hz'))), 'color', colors(1,:), ...
|
|
'DisplayName', 'IFF + $k_p$');
|
|
plot(freqs, abs(squeeze(freqresp(G_vc_fast_iff_kp('Dx', 'Ftx'), freqs, 'Hz'))), 'color', colors(2,:), ...
|
|
'DisplayName', 'IFF + HPF');
|
|
plot(freqs, abs(squeeze(freqresp(G_vc_fast_rdc('Dx', 'Ftx'), freqs, 'Hz'))), 'color', colors(3,:), ...
|
|
'DisplayName', 'RDC');
|
|
hold off;
|
|
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
|
|
xlabel('Frequency [Hz]'); ylabel('Magnitude $d_x/f_{t,x}$ [m/N]');
|
|
xticks([1e-1, 1e0, 1e1, 1e2, 1e3]);
|
|
xtickangle(0)
|
|
ylim([1e-12, 2e-7]);
|
|
#+end_src
|
|
|
|
#+begin_src matlab :tangle no :exports results :results file none
|
|
exportFig('figs/rotating_nass_effect_stage_vibration_vc.pdf', 'width', 'third', 'height', 450);
|
|
#+end_src
|
|
|
|
#+begin_src matlab :exports none :results none
|
|
figure;
|
|
hold on;
|
|
plot(freqs, abs(squeeze(freqresp(G_md_fast('Dx', 'Ftx'), freqs, 'Hz'))), 'color', zeros(1,3), ...
|
|
'DisplayName', 'OL');
|
|
plot(freqs, abs(squeeze(freqresp(G_md_fast_iff_hpf('Dx', 'Ftx'), freqs, 'Hz'))), 'color', colors(1,:), ...
|
|
'DisplayName', 'IFF + $k_p$');
|
|
plot(freqs, abs(squeeze(freqresp(G_md_fast_iff_kp('Dx', 'Ftx'), freqs, 'Hz'))), 'color', colors(2,:), ...
|
|
'DisplayName', 'IFF + HPF');
|
|
plot(freqs, abs(squeeze(freqresp(G_md_fast_rdc('Dx', 'Ftx'), freqs, 'Hz'))), 'color', colors(3,:), ...
|
|
'DisplayName', 'RDC');
|
|
hold off;
|
|
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
|
|
xlabel('Frequency [Hz]'); ylabel('Magnitude $d_x/f_{t,x}$ [m/N]');
|
|
xticks([1e-1, 1e0, 1e1, 1e2, 1e3]);
|
|
xtickangle(0)
|
|
ylim([1e-12, 2e-7]);
|
|
#+end_src
|
|
|
|
#+begin_src matlab :tangle no :exports results :results file none
|
|
exportFig('figs/rotating_nass_effect_stage_vibration_md.pdf', 'width', 'third', 'height', 450);
|
|
#+end_src
|
|
|
|
#+begin_src matlab :exports none :results none
|
|
figure;
|
|
hold on;
|
|
plot(freqs, abs(squeeze(freqresp(G_pz_fast('Dx', 'Ftx'), freqs, 'Hz'))), 'color', zeros(1,3), ...
|
|
'DisplayName', 'OL');
|
|
plot(freqs, abs(squeeze(freqresp(G_pz_fast_iff_hpf('Dx', 'Ftx'), freqs, 'Hz'))), 'color', colors(1,:), ...
|
|
'DisplayName', 'IFF + $k_p$');
|
|
plot(freqs, abs(squeeze(freqresp(G_pz_fast_iff_kp('Dx', 'Ftx'), freqs, 'Hz'))), 'color', colors(2,:), ...
|
|
'DisplayName', 'IFF + HPF');
|
|
plot(freqs, abs(squeeze(freqresp(G_pz_fast_rdc('Dx', 'Ftx'), freqs, 'Hz'))), 'color', colors(3,:), ...
|
|
'DisplayName', 'RDC');
|
|
hold off;
|
|
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
|
|
xlabel('Frequency [Hz]'); ylabel('Magnitude $d_x/f_{t,x}$ [m/N]');
|
|
xticks([1e-1, 1e0, 1e1, 1e2, 1e3]);
|
|
xtickangle(0)
|
|
ldg = legend('location', 'southwest', 'FontSize', 8, 'NumColumns', 1);
|
|
ldg.ItemTokenSize = [20, 1];
|
|
ylim([1e-12, 2e-7]);
|
|
#+end_src
|
|
|
|
#+begin_src matlab :tangle no :exports results :results file none
|
|
exportFig('figs/rotating_nass_effect_stage_vibration_pz.pdf', 'width', 'third', 'height', 450);
|
|
#+end_src
|
|
|
|
#+name: fig:rotating_nass_effect_stage_vibration
|
|
#+caption: Effect of micro-station vibrations $f_{t,x}$ on the position error $d_x$ - Comparison of active damping techniques for the three nano-hexapod stiffnesses. Relative Damping Control increases the sensitivity to micro-station vibrations between the soft nano-hexapod suspension modes and the micro-station modes (\subref{fig:rotating_nass_effect_stage_vibration_vc})
|
|
#+attr_latex: :options [htbp]
|
|
#+begin_figure
|
|
#+attr_latex: :caption \subcaption{\label{fig:rotating_nass_effect_stage_vibration_vc}$k_n = 0.01\,N/\mu m$}
|
|
#+attr_latex: :options {0.33\textwidth}
|
|
#+begin_subfigure
|
|
#+attr_latex: :width 0.95\linewidth
|
|
[[file:figs/rotating_nass_effect_stage_vibration_vc.png]]
|
|
#+end_subfigure
|
|
#+attr_latex: :caption \subcaption{\label{fig:rotating_nass_effect_stage_vibration_md}$k_n = 1\,N/\mu m$}
|
|
#+attr_latex: :options {0.33\textwidth}
|
|
#+begin_subfigure
|
|
#+attr_latex: :width 0.95\linewidth
|
|
[[file:figs/rotating_nass_effect_stage_vibration_md.png]]
|
|
#+end_subfigure
|
|
#+attr_latex: :caption \subcaption{\label{fig:rotating_nass_effect_stage_vibration_pz}$k_n = 100\,N/\mu m$}
|
|
#+attr_latex: :options {0.33\textwidth}
|
|
#+begin_subfigure
|
|
#+attr_latex: :width 0.95\linewidth
|
|
[[file:figs/rotating_nass_effect_stage_vibration_pz.png]]
|
|
#+end_subfigure
|
|
#+end_figure
|
|
|
|
|
|
#+begin_src matlab :exports none :results none
|
|
%% Effect of sample forces on the position error - Comparison of active damping techniques for the three nano-hexapod stiffnesses
|
|
figure;
|
|
hold on;
|
|
plot(freqs, abs(squeeze(freqresp(G_vc_fast('Dx', 'Fdx'), freqs, 'Hz'))), 'color', zeros(1,3), ...
|
|
'DisplayName', 'OL');
|
|
plot(freqs, abs(squeeze(freqresp(G_vc_fast_iff_hpf('Dx', 'Fdx'), freqs, 'Hz'))), 'color', colors(1,:), ...
|
|
'DisplayName', 'IFF + $k_p$');
|
|
plot(freqs, abs(squeeze(freqresp(G_vc_fast_iff_kp('Dx', 'Fdx'), freqs, 'Hz'))), 'color', colors(2,:), ...
|
|
'DisplayName', 'IFF + HPF');
|
|
plot(freqs, abs(squeeze(freqresp(G_vc_fast_rdc('Dx', 'Fdx'), freqs, 'Hz'))), 'color', colors(3,:), ...
|
|
'DisplayName', 'RDC');
|
|
hold off;
|
|
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
|
|
xlabel('Frequency [Hz]'); ylabel('Magnitude $d_x/f_{s,x}$ [m/N]');
|
|
xticks([1e-1, 1e0, 1e1, 1e2, 1e3]);
|
|
xtickangle(0)
|
|
ylim([1e-8, 1e-2])
|
|
#+end_src
|
|
|
|
#+begin_src matlab :tangle no :exports results :results file none
|
|
exportFig('figs/rotating_nass_effect_direct_forces_vc.pdf', 'width', 'third', 'height', 450);
|
|
#+end_src
|
|
|
|
#+begin_src matlab :exports none :results none
|
|
figure;
|
|
hold on;
|
|
plot(freqs, abs(squeeze(freqresp(G_md_fast('Dx', 'Fdx'), freqs, 'Hz'))), 'color', zeros(1,3), ...
|
|
'DisplayName', 'OL');
|
|
plot(freqs, abs(squeeze(freqresp(G_md_fast_iff_hpf('Dx', 'Fdx'), freqs, 'Hz'))), 'color', colors(1,:), ...
|
|
'DisplayName', 'IFF + $k_p$');
|
|
plot(freqs, abs(squeeze(freqresp(G_md_fast_iff_kp('Dx', 'Fdx'), freqs, 'Hz'))), 'color', colors(2,:), ...
|
|
'DisplayName', 'IFF + HPF');
|
|
plot(freqs, abs(squeeze(freqresp(G_md_fast_rdc('Dx', 'Fdx'), freqs, 'Hz'))), 'color', colors(3,:), ...
|
|
'DisplayName', 'RDC');
|
|
hold off;
|
|
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
|
|
xlabel('Frequency [Hz]'); ylabel('Magnitude $d_x/f_{s,x}$ [m/N]');
|
|
xticks([1e-1, 1e0, 1e1, 1e2, 1e3]);
|
|
xtickangle(0)
|
|
ylim([1e-8, 1e-2])
|
|
#+end_src
|
|
|
|
#+begin_src matlab :tangle no :exports results :results file none
|
|
exportFig('figs/rotating_nass_effect_direct_forces_md.pdf', 'width', 'third', 'height', 450);
|
|
#+end_src
|
|
|
|
#+begin_src matlab :exports none :results none
|
|
figure;
|
|
hold on;
|
|
plot(freqs, abs(squeeze(freqresp(G_pz_fast('Dx', 'Fdx'), freqs, 'Hz'))), 'color', zeros(1,3), ...
|
|
'DisplayName', 'OL');
|
|
plot(freqs, abs(squeeze(freqresp(G_pz_fast_iff_hpf('Dx', 'Fdx'), freqs, 'Hz'))), 'color', colors(1,:), ...
|
|
'DisplayName', 'IFF + $k_p$');
|
|
plot(freqs, abs(squeeze(freqresp(G_pz_fast_iff_kp('Dx', 'Fdx'), freqs, 'Hz'))), 'color', colors(2,:), ...
|
|
'DisplayName', 'IFF + HPF');
|
|
plot(freqs, abs(squeeze(freqresp(G_pz_fast_rdc('Dx', 'Fdx'), freqs, 'Hz'))), 'color', colors(3,:), ...
|
|
'DisplayName', 'RDC');
|
|
hold off;
|
|
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
|
|
xlabel('Frequency [Hz]'); ylabel('Magnitude $d_x/f_{s,x}$ [m/N]');
|
|
xticks([1e-1, 1e0, 1e1, 1e2, 1e3]);
|
|
xtickangle(0)
|
|
ldg = legend('location', 'northwest', 'FontSize', 8, 'NumColumns', 1);
|
|
ldg.ItemTokenSize = [20, 1];
|
|
|
|
linkaxes([ax1,ax2,ax3], 'y')
|
|
ylim([1e-8, 1e-2])
|
|
#+end_src
|
|
|
|
#+begin_src matlab :tangle no :exports results :results file none
|
|
exportFig('figs/rotating_nass_effect_direct_forces_pz.pdf', 'width', 'third', 'height', 450);
|
|
#+end_src
|
|
|
|
#+name: fig:rotating_nass_effect_direct_forces
|
|
#+caption: Effect of sample forces $f_{s,x}$ on the position error $d_x$ - Comparison of active damping techniques for the three nano-hexapod stiffnesses. Integral Force Feedback degrades this compliance at low-frequency.
|
|
#+attr_latex: :options [htbp]
|
|
#+begin_figure
|
|
#+attr_latex: :caption \subcaption{\label{fig:rotating_nass_effect_direct_forces_vc}$k_n = 0.01\,N/\mu m$}
|
|
#+attr_latex: :options {0.33\textwidth}
|
|
#+begin_subfigure
|
|
#+attr_latex: :width 0.95\linewidth
|
|
[[file:figs/rotating_nass_effect_direct_forces_vc.png]]
|
|
#+end_subfigure
|
|
#+attr_latex: :caption \subcaption{\label{fig:rotating_nass_effect_direct_forces_md}$k_n = 1\,N/\mu m$}
|
|
#+attr_latex: :options {0.33\textwidth}
|
|
#+begin_subfigure
|
|
#+attr_latex: :width 0.95\linewidth
|
|
[[file:figs/rotating_nass_effect_direct_forces_md.png]]
|
|
#+end_subfigure
|
|
#+attr_latex: :caption \subcaption{\label{fig:rotating_nass_effect_direct_forces_pz}$k_n = 100\,N/\mu m$}
|
|
#+attr_latex: :options {0.33\textwidth}
|
|
#+begin_subfigure
|
|
#+attr_latex: :width 0.95\linewidth
|
|
[[file:figs/rotating_nass_effect_direct_forces_pz.png]]
|
|
#+end_subfigure
|
|
#+end_figure
|
|
|
|
* Conclusion
|
|
:PROPERTIES:
|
|
:UNNUMBERED: t
|
|
:END:
|
|
|
|
In this study, the gyroscopic effects induced by the spindle's rotation have been studied using a simplified model (Section ref:sec:rotating_system_description).
|
|
Decentralized acrlong:iff with pure integrators was shown to be unstable when applied to rotating platforms (Section ref:sec:rotating_iff_pure_int).
|
|
Two modifications of the classical acrshort:iff control have been proposed to overcome this issue.
|
|
|
|
The first modification concerns the controller and consists of adding a high-pass filter to the pure integrators.
|
|
This is equivalent to moving the controller pole to the left along the real axis.
|
|
This allows the closed-loop system to be stable up to some value of the controller gain (Section ref:sec:rotating_iff_pseudo_int).
|
|
|
|
The second proposed modification concerns the mechanical system.
|
|
Additional springs are added in parallel with the actuators and force sensors.
|
|
It was shown that if the stiffness $k_p$ of the additional springs is larger than the negative stiffness $m \Omega^2$ induced by centrifugal forces, the classical decentralized acrshort:iff regains its unconditional stability property (Section ref:sec:rotating_iff_parallel_stiffness).
|
|
|
|
These two modifications were compared with acrlong:rdc in Section ref:sec:rotating_comp_act_damp.
|
|
While having very different implementations, both proposed modifications were found to be very similar with respect to the attainable damping and the obtained closed-loop system behavior.
|
|
|
|
This study has been applied to a rotating platform that corresponds to the nano-hexapod parameters (Section ref:sec:rotating_nano_hexapod).
|
|
As for the uniaxial model, three nano-hexapod stiffnesses values were considered.
|
|
The dynamics of the soft nano-hexapod ($k_n = 0.01\,N/\mu m$) was shown to be more depend more on the rotation velocity (higher coupling and change of dynamics due to gyroscopic effects).
|
|
In addition, the attainable damping ratio of the soft nano-hexapod when using acrshort:iff is limited by gyroscopic effects.
|
|
|
|
To be closer to the acrlong:nass dynamics, the limited compliance of the micro-station has been considered (Section ref:sec:rotating_nass).
|
|
Results are similar to those of the uniaxial model except that come complexity is added for the soft nano-hexapod due to the spindle's rotation.
|
|
For the moderately stiff nano-hexapod ($k_n = 1\,N/\mu m$), the gyroscopic effects only slightly affect the system dynamics, and therefore could represent a good alternative to the soft nano-hexapod that showed better results with the uniaxial model.
|
|
|
|
* Bibliography :ignore:
|
|
#+latex: \printbibliography[heading=bibintoc,title={Bibliography}]
|
|
|
|
* Glossary :ignore:
|
|
[[printglossaries:]]
|
|
|
|
* 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/src/'); % Path for Functions
|
|
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
|
|
addpath('./src/'); % Path for Functions
|
|
#+END_SRC
|
|
|
|
** Initialize other elements
|
|
#+NAME: m-init-other
|
|
#+BEGIN_SRC matlab
|
|
%% Colors for the figures
|
|
colors = colororder;
|
|
#+END_SRC
|
|
|
|
** =rootLocusPolesSorted=
|
|
#+begin_src matlab :tangle matlab/src/rootLocusPolesSorted.m
|
|
function [poles] = rootLocusPolesSorted(G, K, gains, args)
|
|
% rootLocusPolesSorted -
|
|
%
|
|
% Syntax: [poles] = rootLocusPolesSorted(G, K, gains, args)
|
|
%
|
|
% Inputs:
|
|
% - G, K, gains, args -
|
|
%
|
|
% Outputs:
|
|
% - poles -
|
|
|
|
arguments
|
|
G
|
|
K
|
|
gains
|
|
args.minreal double {mustBeNumericOrLogical} = false
|
|
args.p_half double {mustBeNumericOrLogical} = false
|
|
args.d_max double {mustBeNumeric} = -1
|
|
end
|
|
|
|
if args.minreal
|
|
p1 = pole(minreal(feedback(G, gains(1)*K)));
|
|
[~, i_uniq] = uniquetol([real(p1), imag(p1)], 1e-10, 'ByRows', true);
|
|
p1 = p1(i_uniq);
|
|
|
|
poles = zeros(length(p1), length(gains));
|
|
poles(:, 1) = p1;
|
|
else
|
|
p1 = pole(feedback(G, gains(1)*K));
|
|
[~, i_uniq] = uniquetol([real(p1), imag(p1)], 1e-10, 'ByRows', true);
|
|
p1 = p1(i_uniq);
|
|
|
|
poles = zeros(length(p1), length(gains));
|
|
poles(:, 1) = p1;
|
|
end
|
|
|
|
if args.minreal
|
|
p2 = pole(minreal(feedback(G, gains(2)*K)));
|
|
[~, i_uniq] = uniquetol([real(p2), imag(p2)], 1e-10, 'ByRows', true);
|
|
p2 = p2(i_uniq);
|
|
poles(:, 2) = p2;
|
|
else
|
|
p2 = pole(feedback(G, gains(2)*K));
|
|
[~, i_uniq] = uniquetol([real(p2), imag(p2)], 1e-10, 'ByRows', true);
|
|
p2 = p2(i_uniq);
|
|
poles(:, 2) = p2;
|
|
end
|
|
|
|
for g_i = 3:length(gains)
|
|
% Estimated value of the poles
|
|
poles_est = poles(:, g_i-1) + (poles(:, g_i-1) - poles(:, g_i-2))*(gains(g_i) - gains(g_i-1))/(gains(g_i-1) - gains(g_i - 2));
|
|
|
|
% New values for the poles
|
|
poles_gi = pole(feedback(G, gains(g_i)*K));
|
|
[~, i_uniq] = uniquetol([real(poles_gi), imag(poles_gi)], 1e-10, 'ByRows', true);
|
|
poles_gi = poles_gi(i_uniq);
|
|
|
|
% Array of distances between all the poles
|
|
poles_dist = sqrt((poles_est-poles_gi.').*conj(poles_est-poles_gi.'));
|
|
|
|
% Get indices corresponding to distances from lowest to highest
|
|
[~, c] = sort(min(poles_dist));
|
|
|
|
as = 1:length(poles_gi);
|
|
|
|
% for each column of poles_dist corresponding to the i'th pole
|
|
% with closest previous poles
|
|
for p_i = c
|
|
% Get the indice a_i of the previous pole that is the closest
|
|
% to pole c(p_i)
|
|
[~, a_i] = min(poles_dist(:, p_i));
|
|
|
|
poles(as(a_i), g_i) = poles_gi(p_i);
|
|
|
|
% Remove old poles that are already matched
|
|
% poles_gi(as(a_i), :) = [];
|
|
poles_dist(a_i, :) = [];
|
|
as(a_i) = [];
|
|
end
|
|
end
|
|
|
|
|
|
if args.d_max > 0
|
|
poles = poles(max(abs(poles(:, 2:end) - poles(:, 1:end-1))') > args.d_max, :);
|
|
end
|
|
|
|
if args.p_half
|
|
poles = poles(1:round(end/2), :);
|
|
end
|
|
|
|
[~, s_p] = sort(imag(poles(:,1)), 'descend');
|
|
poles = poles(s_p, :);
|
|
|
|
poles = poles.';
|
|
#+end_src
|
|
|
|
** =computeSimultaneousDamping=
|
|
#+begin_src matlab :tangle matlab/src/computeSimultaneousDamping.m
|
|
function [xi_min] = computeSimultaneousDamping(g, G, K)
|
|
[~, xi] = damp(minreal(feedback(G, g*K), [], false));
|
|
xi_min = 1/min(xi);
|
|
|
|
if xi_min < 0
|
|
xi_min = 1e8;
|
|
end
|
|
end
|
|
#+end_src
|
|
|