diff --git a/docs/active_damping.html b/docs/active_damping.html index 0ea743f..89a5515 100644 --- a/docs/active_damping.html +++ b/docs/active_damping.html @@ -4,7 +4,7 @@ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> - + Active Damping applied on the Simscape Model @@ -202,50 +202,28 @@ @@ -258,7 +236,7 @@ for the JavaScript code in this tag.

Author: Dehaeze Thomas

-

Created: 2020-02-25 mar. 18:20

+

Created: 2020-03-06 ven. 15:09

diff --git a/docs/control_requirements.html b/docs/control_requirements.html new file mode 100644 index 0000000..6b0f946 --- /dev/null +++ b/docs/control_requirements.html @@ -0,0 +1,1251 @@ + + + + + + + + + +Control Requirements + + + + + + + + + + + + + + + +
+ UP + | + HOME +
+

Control Requirements

+
+

Table of Contents

+ +
+ +
+

1 Goal

+
+

+The goal here is to write clear specifications for the NASS. +

+ +

+This can then be used for the control synthesis and for the design of the nano-hexapod. +

+ +

+Ideal, specifications on the norm of closed loop transfer function should be written. +

+
+
+ +
+

2 Simplify Model for the Nano-Hexapod

+
+
+
+

2.1 Model of the nano-hexapod

+
+

+Let’s consider the simple mechanical system in Figure 1. +

+ + +
+

nass_simple_model.png +

+

Figure 1: Simplified mechanical system for the nano-hexapod

+
+ +

+The signals are described in table 1. +

+ + + + +++ ++ ++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Table 1: Signals definition for the generalized plant
 SymbolMeaning
Exogenous Inputs\(x_\mu\)Motion of the $ν$-hexapod’s base
 \(F_d\)External Forces applied to the Payload
 \(r\)Reference signal for tracking
Exogenous Outputs\(x\)Absolute Motion of the Payload
Sensed Outputs\(F_m\)Force Sensors in each leg
 \(d\)Measured displacement of each leg
 \(x\)Absolute Motion of the Payload
Control Signals\(F\)Actuator Inputs
+ +

+For the nano-hexapod alone, we have the following equations: +\[ \begin{align*} + x &= \frac{1}{ms^2 + k} F + \frac{1}{ms^2 + k} F_d + \frac{k}{ms^2 + k} x_\mu \\ + F_m &= \frac{ms^2}{ms^2 + k} F - \frac{k}{ms^2 + k} F_d + \frac{k m s^2}{ms^2 + k} x_\mu \\ + d &= \frac{1}{ms^2 + k} F + \frac{1}{ms^2 + k} F_d - \frac{ms^2}{ms^2 + k} x_\mu +\end{align*} \] +

+ +

+We can write the equations function of \(\omega_\nu = \sqrt{\frac{k}{m}}\): +\[ \begin{align*} + x &= \frac{1/k}{1 + \frac{s^2}{\omega_\nu^2}} F + \frac{1/k}{1 + \frac{s^2}{\omega_\nu^2}} F_d + \frac{1}{1 + \frac{s^2}{\omega_\nu^2}} x_\mu \\ + F_m &= \frac{\frac{s^2}{\omega_\nu^2}}{1 + \frac{s^2}{\omega_\nu^2}} F - \frac{1}{1 + \frac{s^2}{\omega_\nu^2}} F_d + \frac{k \frac{s^2}{\omega_\nu^2}}{1 + \frac{s^2}{\omega_\nu^2}} x_\mu \\ + d &= \frac{1/k}{1 + \frac{s^2}{\omega_\nu^2}} F + \frac{1/k}{1 + \frac{s^2}{\omega_\nu^2}} F_d - \frac{\frac{s^2}{\omega_\nu^2}}{1 + \frac{s^2}{\omega_\nu^2}} x_\mu +\end{align*} \] +

+ + +

+Assumptions: +

+
    +
  • the forces applied by the nano-hexapod have no influence on the micro-station, specifically on the displacement of the top platform of the micro-hexapod.
  • +
+ +

+This means that the nano-hexapod can be considered separately from the micro-station and that the motion \(x_\mu\) is imposed and considered as an external input. +

+ +

+The nano-hexapod can thus be represented as in Figure 2. +

+ + +
+

nano_station_inputs_outputs.png +

+

Figure 2: Block representation of the nano-hexapod

+
+
+
+ +
+

2.2 How to include Ground Motion in the model?

+
+

+What we measure is not the absolute motion \(x\), but the relative motion \(x - w\) where \(w\) is the motion of the granite. +

+ +

+Also, \(w\) induces some motion \(x_\mu\) through the transmissibility of the micro-station. +

+ + +
+

nano_station_inputs_outputs_ground_motion.png +

+
+
+
+
+ +
+

3 Motion of the micro-station

+
+

+As explained, we consider \(x_\mu\) as an external input (\(F\) has no influence on \(x_\mu\)). +

+ +

+\(x_\mu\) is the motion of the micro-station’s top platform due to the motion of each stage of the micro-station. +

+ +

+We consider that \(x_\mu\) has the following form: +\[ x_\mu = T_\mu r + d_\mu \] +where: +

+
    +
  • \(T_\mu r\) corresponds to the response of the stages due to the reference \(r\)
  • +
  • \(d_\mu\) is the motion of the hexapod due to all the vibrations of the stages
  • +
+ + +

+\(T_\mu\) can be considered to be a low pass filter with a bandwidth corresponding approximatively to the bandwidth of the micro-station’s stages. +To simplify, we can consider \(T_\mu\) to be a first order low pass filter: +\[ T_\mu = \frac{1}{1 + s/\omega_\mu} \] +where \(\omega_\mu\) corresponds to the tracking speed of the micro-station. +

+ + +

+What is important to note is that while \(x_\mu\) is viewed as a perturbation from the nano-hexapod point of view, \(x_\mu\) does depend on the reference signal \(r\). +

+ +

+Also, here, we suppose that the granite is not moving. +

+ +

+If we now include the motion of the granite \(w\), we obtain the block diagram shown in Figure 4. +

+ + +
+

nano_station_ground_motion.png +

+

Figure 4: Ground Motion \(w\) included

+
+ +

+\(T_w\) is the mechanical transmissibility of the micro-station. +We can approximate this transfer function by a second order low pass filter: +\[ T_w = \frac{1}{1 + 2 \xi s/\omega_0 + s^2/\omega_0^2} \] +

+
+
+ +
+

4 Values and Plant

+
+
+
+

4.1 Definition of the values

+
+

+Let’s define the mass and stiffness of the nano-hexapod. +

+
+
m = 50; % [kg]
+k = 1e7; % [N/m]
+
+
+ +

+Let’s define the Plant as shown in Figure 2: +

+
+
Gn = 1/(m*s^2 + k)*[-k, k*m*s^2, m*s^2; 1, -m*s^2, 1; 1, k, 1];
+Gn.InputName  = {'Fd', 'xmu', 'F'};
+Gn.OutputName = {'Fm', 'd', 'x'};
+
+
+ +

+Now, define the transmissibility transfer function \(T_\mu\) corresponding to the micro-station motion. +

+
+
wmu = 2*pi*50; % [rad/s]
+
+Tmu = 1/(1 + s/wmu);
+Tmu.InputName = {'r1'};
+Tmu.OutputName = {'ymu'};
+
+
+ +
+
w0 = 2*pi*40;
+xi = 0.5;
+Tw = 1/(1 + 2*xi*s/w0 + s^2/w0^2);
+Tw.InputName = {'w1'};
+Tw.OutputName = {'dw'};
+
+
+ +

+We add the fact that \(x_\mu = d_\mu + T_\mu r + T_w w\): +

+
+
Wsplit = [tf(1); tf(1)];
+Wsplit.InputName = {'w'};
+Wsplit.OutputName = {'w1', 'w2'};
+
+S = sumblk('xmu = ymu + dmu + dw');
+
+Sw = sumblk('y = x - w2');
+
+Gpz = connect(Gn, S, Wsplit, Tw, Tmu, Sw, {'Fd', 'dmu', 'r1', 'F', 'w'}, {'Fm', 'd', 'y'});
+
+
+
+
+
+ +
+

5 Control using \(d\)

+
+
+
+

5.1 Control Architecture

+
+

+Let’s consider a feedback loop using \(d\) as shown in Figure 5. +

+ + +
+

nano_station_control_d.png +

+

Figure 5: Feedback diagram using \(d\)

+
+
+
+ +
+

5.2 Analytical Analysis

+
+

+Let’s apply a direct velocity feedback by deriving \(d\): +\[ F = F^\prime - g s d \] +

+ +

+Thus: +\[ d = \frac{1}{ms^2 + gs + k} F^\prime + \frac{1}{ms^2 + gs + k} F_d - \frac{ms^2}{ms^2 + gs + k} x_\mu \] +

+ +

+\[ F = \frac{ms^2 + k}{ms^2 + gs + k} F^\prime - \frac{gs}{ms^2 + gs + k} F_d + \frac{mgs^3}{ms^2 + gs + k} x_\mu \] +

+ +

+and +\[ x = \frac{1}{ms^2 + k} (\frac{ms^2 + k}{ms^2 + gs + k} F^\prime - \frac{gs}{ms^2 + gs + k} F_d + \frac{mgs^3}{ms^2 + gs + k} x_\mu) + \frac{1}{ms^2 + k} F_d + \frac{k}{ms^2 + k} x_\mu \] +

+ + +

+\[ x = \frac{ms^2 + k}{(ms^2 + k) (ms^2 + gs + k)} F^\prime + \frac{ms^2 + k}{(ms^2 + k) (ms^2 + gs + k)} F_d + \frac{mgs^3 + k(ms^2 + gs + k)}{(ms^2 + k) (ms^2 + gs + k)} x_\mu \] +

+ +

+And we finally obtain: +\[ x = \frac{1}{ms^2 + gs + k} F^\prime + \frac{1}{ms^2 + gs + k} F_d + \frac{gs + k}{ms^2 + gs + k} x_\mu \] +

+ +
+
K_dvf = 2*sqrt(k*m)*s;
+K_dvf.InputName = {'d'};
+K_dvf.OutputName = {'F'};
+
+Gpz_dvf = feedback(Gpz, K_dvf, 'name');
+
+
+ +

+Now let’s consider that \(x_\mu = d_\mu + T_\mu r\) +

+ +

+\[ x = \frac{1}{ms^2 + gs + k} F^\prime + \frac{1}{ms^2 + gs + k} F_d + \frac{gs + k}{ms^2 + gs + k} d_\mu + T_\mu \frac{gs + k}{ms^2 + gs + k} r \] +

+ +

+And \(\epsilon = r - x\): +\[ \epsilon = \frac{1}{ms^2 + gs + k} F^\prime + \frac{1}{ms^2 + gs + k} F_d + \frac{gs + k}{ms^2 + gs + k} d_\mu + \frac{ms^2 + gs + k - T_\mu (gs + k)}{ms^2 + gs + k} r \] +

+ +
+

+\[ \epsilon = \frac{1}{ms^2 + gs + k} F^\prime + \frac{1}{ms^2 + gs + k} F_d + \frac{gs + k}{ms^2 + gs + k} d_\mu + \frac{ms^2 - S_\mu(gs + k)}{ms^2 + gs + k} r \] +

+ +
+
+
+
+ +
+

6 Control using \(F_m\)

+
+
+
+

6.1 Control Architecture

+
+

+Let’s consider a feedback loop using \(d\) as shown in Figure 5. +

+ + +
+

nano_station_control_Fm.png +

+

Figure 6: Feedback diagram using \(F_m\)

+
+
+
+ +
+

6.2 Pure Integrator

+
+

+Let’s apply integral force feedback by integration \(F_m\): +\[ F = F^\prime - \frac{g}{s} F_m \] +

+ +

+And we finally obtain: +\[ x = \frac{1}{ms^2 + mgs + k} F^\prime + \frac{1 + \frac{g}{s}}{ms^2 + mgs + k} F_d + \frac{k}{ms^2 + mgs + k} x_\mu \] +

+ +
+
K_iff = 2*sqrt(k/m)/s;
+K_iff.InputName = {'Fm'};
+K_iff.OutputName = {'F'};
+
+Gpz_iff = feedback(Gpz, K_iff, 'name');
+
+
+ +

+Now let’s consider that \(x_\mu = d_\mu + T_\mu r\) +

+ +

+\[ x = \frac{1}{ms^2 + mgs + k} F^\prime + \frac{1 + \frac{g}{s}}{ms^2 + mgs + k} F_d + \frac{k}{ms^2 + mgs + k} d_\mu + \frac{T_\mu k}{ms^2 + mgs + k} r \] +

+ +

+And \(\epsilon = r - x\): +\[ \epsilon = \frac{1}{ms^2 + mgs + k} F^\prime + \frac{1 + \frac{g}{s}}{ms^2 + mgs + k} F_d + \frac{k}{ms^2 + mgs + k} d_\mu + \frac{ms^2 + mgs + k - T_\mu k}{ms^2 + mgs + k} r \] +

+ +
+

+\[ \epsilon = \frac{1}{ms^2 + mgs + k} F^\prime + \frac{1 + \frac{g}{s}}{ms^2 + mgs + k} F_d + \frac{k}{ms^2 + mgs + k} d_\mu + \frac{ms^2 + mgs + S_\mu k}{ms^2 + mgs + k} r \] +

+ +
+
+
+ +
+

6.3 Low pass filter

+
+

+Instead of a pure integrator, let’s use a low pass filter with a cut-off frequency above the bandwidth of the micro-station \(\omega_mu\) +

+
+
% K_iff = (2*sqrt(k/m)/(2*wmu))*(1/(1 + s/(2*wmu)));
+% K_iff.InputName = {'Fm'};
+% K_iff.OutputName = {'F'};
+
+% Gpz_iff = feedback(Gpz, K_iff, 'name');
+
+
+
+
+
+ +
+

7 Comparison

+
+ +
+

comp_iff_dvf_simplified.png +

+

Figure 7: Obtained transfer functions for DVF and IFF (png, pdf)

+
+ + + + +++ ++ ++ ++ + + + + + + + + + + + + + + + + + + + + + + + +
 \(d_\mu\)\(F_d\)\(w\)
IFFBetter filtering of the vibrationsMore sensitive to External forces 
DVFinverseinverseLittle bit better at low frequencies
+
+
+ +
+

8 Control using \(x\)

+
+
+
+

8.1 Analytical analysis

+
+

+Let’s first consider that only the output \(x\) is used for feedback (Figure 8) +

+ + +
+

nano_station_control_x.png +

+

Figure 8: Feedback diagram using \(x\)

+
+ +

+We then have: +\[ \epsilon &= r - G_{\frac{x}{F}} K \epsilon - G_{\frac{x}{F_d}} F_d - G_{\frac{x}{x_\mu}} d_\mu - G_{\frac{x}{x_\mu}} T_\mu r \] +

+ +

+And then: +

+
+

+\[ \epsilon = \frac{-G_{\frac{x}{F_d}}}{1 + G_{\frac{x}{F}}K} F_d + \frac{-G_{\frac{x}{x_\mu}}}{1 + G_{\frac{x}{F}}K} d_\mu + \frac{1 - G_{\frac{x}{x_\mu}} T_\mu}{1 + G_{\frac{x}{F}}K} r \] +

+ +
+ +

+With \(S = \frac{1}{1 + G_{\frac{x}{F}} K}\), we have: +\[ \epsilon = - S G_{\frac{x}{F_d}} F_d - S G_{\frac{x}{x_\mu}} d_\mu + S (1 - G_{\frac{x}{x_\mu}} T_\mu) r \] +

+ +

+We have 3 terms that we would like to have small by design: +

+
    +
  • \(G_{\frac{x}{F_d}} = \frac{1}{ms^2 + k}\): thus \(k\) and \(m\) should be high to lower the effect of direct forces \(F_d\)
  • +
  • \(G_{\frac{x}{x_\mu}} = \frac{k}{ms^2 + k} = \frac{1}{1 + \frac{s^2}{\omega_\nu^2}}\): \(\omega_\nu\) should be small enough such that it filters out the vibrations of the micro-station
  • +
  • \(1 - G_{\frac{x}{x_\mu}} T_\mu\)
  • +
+ +

+\[ 1 - G_{\frac{x}{x_\mu}} T_\mu = 1 - \frac{1}{1 + \frac{s^2}{\omega_\nu^2}} T_\mu \] +

+ +

+We can approximate \(T_\mu \approx \frac{1}{1 + \frac{s}{\omega_\mu}}\) to have: +

+\begin{align*} + 1 - G_{\frac{x}{x_\mu}} T_\mu &= 1 - \frac{1}{1 + \frac{s^2}{\omega_\nu^2}} \frac{1}{1 + \frac{s}{\omega_\mu}} \\ + &\approx \frac{\frac{s}{\omega_\mu}}{1 + \frac{s}{\omega_\mu}} = S_\mu \text{ if } \omega_\nu > \omega_\mu \\ + &\approx \frac{\frac{s^2}{\omega_\nu^2}}{1 + \frac{s^2}{\omega_\nu^2}} = \text{ if } \omega_\nu < \omega_\mu +\end{align*} + +

+In our case, we have \(\omega_\nu > \omega_\mu\) and thus we cannot lower this term. +

+ +

+Some implications on the design are summarized on table 2. +

+ + + + +++ ++ + + + + + + + + + + + + + + + + + + + + + + +
Table 2: Design recommendation
Exogenous OutputsDesign recommendation
\(F_d\)high \(k\), high \(m\)
\(d_\mu\)low \(k\), high \(m\)
\(r\)no influence if \(\omega_\nu > \omega_\mu\)
+
+
+ +
+

8.2 Control implementation

+
+

+Controller for the damped plant using DVF. +

+
+
wb = 2*pi*50; % control bandwidth [rad/s]
+
+% Lead
+h = 2.0;
+wz = wb/h; % [rad/s]
+wp = wb*h; % [rad/s]
+
+H = 1/h*(1 + s/wz)/(1 + s/wp);
+
+% Integrator until 10Hz
+Hi = (1 + s/2/pi/10)/(s/2/pi/10);
+
+K = Hi*H*(1/s);
+
+Kpz_dvf = K/abs(freqresp(K*Gpz_dvf('y', 'F'), wb));
+Kpz_dvf.InputName = {'e'};
+Kpz_dvf.OutputName = {'F'};
+
+
+
+ +

+Controller for the damped plant using IFF. +

+
+
wb = 2*pi*50; % control bandwidth [rad/s]
+
+% Lead
+h = 2.0;
+wz = wb/h; % [rad/s]
+wp = wb*h; % [rad/s]
+
+H = 1/h*(1 + s/wz)/(1 + s/wp);
+
+% Integrator until 10Hz
+Hi = (1 + s/2/pi/10)/(s/2/pi/10);
+
+K = Hi*H*(1/s);
+
+Kpz_iff = K/abs(freqresp(K*Gpz_iff('y', 'F'), wb));
+Kpz_iff.InputName = {'e'};
+Kpz_iff.OutputName = {'F'};
+
+
+ +

+Loop gain +

+ +
+

simple_loop_gain_pz.png +

+

Figure 9: Loop Gain (png, pdf)

+
+ + +

+Let’s connect all the systems as shown in Figure 8. +

+
+
Sfb = sumblk('e = r2 - y');
+
+R = [tf(1); tf(1)];
+R.InputName = {'r'};
+R.OutputName = {'r1', 'r2'};
+
+Gpz_fb_dvf = connect(Gpz_dvf, Kpz_dvf, R, Sfb, {'r', 'dmu', 'Fd', 'w'}, {'y', 'e', 'Fm', 'd'});
+Gpz_fb_iff = connect(Gpz_iff, Kpz_iff, R, Sfb, {'r', 'dmu', 'Fd', 'w'}, {'y', 'e', 'Fm', 'd'});
+
+
+
+
+ +
+

8.3 Results

+
+ +
+

simple_hac_lac_results.png +

+

Figure 10: Obtained closed-loop transfer functions (png, pdf)

+
+
+
+
+ +
+

9 Two degree of freedom control

+
+

+Let’s try to implement the control architecture shown in Figure 11. +

+ +

+The pre-filter \(K_r\) is added in order to improve the reference tracking performances. +

+ + +
+

nano_station_control_2dof_x.png +

+

Figure 11: Two degrees of freedom feedback control

+
+ +

+In order to design the pre-filter \(K_r\), the dynamics of the system should be known quite precisely (Dynamics of the nano-hexapod + \(T_\mu\)). +

+
+
Krpz = inv(Gpz_fb('y', 'r'));
+
+Krpz.InputName = {'r2'};
+Krpz.OutputName = {'r3'};
+
+
+ +
+
Sfb = sumblk('e = r3 - y');
+
+R = [tf(1); tf(1)];
+R.InputName = {'r'};
+R.OutputName = {'r1', 'r2'};
+
+Gpz_2dof = connect(Gpz_dvf, Krpz, Kpz, R, Sfb, {'r', 'dmu', 'Fd', 'w'}, {'y', 'e', 'Fm', 'd'});
+
+
+
+
+ +
+

10 Soft nano-hexapod

+
+
+
m = 50; % [kg]
+k = 1e3; % [N/m]
+
+Gn = 1/(m*s^2 + k)*[-k, k*m*s^2, m*s^2; 1, -m*s^2, 1; 1, k, 1];
+Gn.InputName  = {'Fd', 'xmu', 'F'};
+Gn.OutputName = {'Fm', 'd', 'x'};
+
+
+ +
+
wmu = 2*pi*50; % [rad/s]
+
+Tmu = 1/(1 + s/wmu);
+Tmu.InputName = {'r1'};
+Tmu.OutputName = {'ymu'};
+
+
+ +
+
w0 = 2*pi*40;
+xi = 0.5;
+Tw = 1/(1 + 2*xi*s/w0 + s^2/w0^2);
+Tw.InputName = {'w1'};
+Tw.OutputName = {'dw'};
+
+
+ +
+
Wsplit = [tf(1); tf(1)];
+Wsplit.InputName = {'w'};
+Wsplit.OutputName = {'w1', 'w2'};
+
+S = sumblk('xmu = ymu + dmu + dw');
+
+Sw = sumblk('y = x - w2');
+
+Gvc = connect(Gn, S, Wsplit, Tw, Tmu, Sw, {'Fd', 'dmu', 'r1', 'F', 'w'}, {'Fm', 'd', 'y'});
+
+
+ +
+
Kvc_dvf = 2*sqrt(k*m)*s;
+Kvc_dvf.InputName = {'d'};
+Kvc_dvf.OutputName = {'F'};
+
+Gvc_dvf = feedback(Gvc, Kvc_dvf, 'name');
+
+Kvc_iff = 2*sqrt(k/m)/s;
+Kvc_iff.InputName = {'Fm'};
+Kvc_iff.OutputName = {'F'};
+
+Gvc_iff = feedback(Gvc, Kvc_iff, 'name');
+
+
+ +
+
wb = 2*pi*100; % control bandwidth [rad/s]
+
+% Lead
+h = 2.0;
+wz = wb/h; % [rad/s]
+wp = wb*h; % [rad/s]
+
+H = 1/h*(1 + s/wz)/(1 + s/wp);
+
+Kvc_dvf = H/abs(freqresp(H*Gvc_dvf('y', 'F'), wb));
+Kvc_dvf.InputName = {'e'};
+Kvc_dvf.OutputName = {'F'};
+
+Kvc_iff = H/abs(freqresp(H*Gvc_iff('y', 'F'), wb));
+Kvc_iff.InputName = {'e'};
+Kvc_iff.OutputName = {'F'};
+
+
+ +
+
Sfb = sumblk('e = r2 - y');
+
+R = [tf(1); tf(1)];
+R.InputName = {'r'};
+R.OutputName = {'r1', 'r2'};
+
+Gvc_fb_dvf = connect(Gvc_dvf, Kvc_dvf, R, Sfb, {'r', 'dmu', 'Fd', 'w'}, {'y', 'e', 'Fm', 'd'});
+Gvc_fb_iff = connect(Gvc_iff, Kvc_iff, R, Sfb, {'r', 'dmu', 'Fd', 'w'}, {'y', 'e', 'Fm', 'd'});
+
+
+ + +
+

simple_hac_lac_results_soft.png +

+

Figure 12: Obtained closed-loop transfer functions (png, pdf)

+
+
+
+ +
+

11 Compare Soft and Stiff nano-hexapods

+
+ +
+

simple_comp_vc_pz.png +

+

Figure 13: Comparison of the closed-loop transfer functions for Soft and Stiff nano-hexapod (png, pdf)

+
+ + + + +++ ++ ++ + + + + + + + + + + + + + + + + + + + + + + + + + + +
 SoftStiff
Reference Tracking==
Vibration Isolation+-
Compliance-+
+
+
+ +
+

12 Estimate the level of vibration

+
+
+
gm  = load('./mat/psd_gm.mat', 'f', 'psd_gm');
+rz  = load('./mat/pxsp_r.mat', 'f', 'pxsp_r');
+tyz = load('./mat/pxz_ty_r.mat', 'f', 'pxz_ty_r');
+
+
+ +
+
x_pz = sqrt(abs(squeeze(freqresp(Gpz_fb_iff('y', 'dmu'), f, 'Hz'))).^2.*(psd_rz + psd_ty) + abs(squeeze(freqresp(Gpz_fb_iff('y', 'w'), f, 'Hz'))).^2.*(psd_gm));
+x_vc = sqrt(abs(squeeze(freqresp(Gvc_fb_iff('y', 'dmu'), f, 'Hz'))).^2.*(psd_rz + psd_ty) + abs(squeeze(freqresp(Gvc_fb_iff('y', 'w'), f, 'Hz'))).^2.*(psd_gm));
+
+
+
+
+ +
+

13 Requirements on the norm of closed-loop transfer functions

+
+ + + +++ ++ ++ + + + + + + + + + + + + + + + + + + + +
reference tracking\(\epsilon/r\)-120dB at 1Hz
vibration isolation\(x/x_\mu\)-60dB above 10Hz
compliance\(x/F_d\) 
+
+
+
+
+

Author: Dehaeze Thomas

+

Created: 2020-03-06 ven. 15:10

+
+ + diff --git a/docs/disturbances.html b/docs/disturbances.html index f1fe192..45028c1 100644 --- a/docs/disturbances.html +++ b/docs/disturbances.html @@ -4,7 +4,7 @@ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> - + Identification of the disturbances @@ -202,50 +202,28 @@ @@ -262,30 +240,30 @@ for the JavaScript code in this tag.
  • 1. Simscape Model
  • 2. Tomography Experiment with no disturbances
  • 3. Tomography Experiment with included perturbations
  • 4. Tomography when the micro-hexapod is not centered
  • 5. Raster Scans with the translation stage
  • @@ -372,8 +350,8 @@ All stage is set to its zero position except the Spindle which is rotating at 60

    -
    -

    2.1 Simulation Setup

    +
    +

    2.1 Simulation Setup

    And we initialize the disturbances to be equal to zero. @@ -403,17 +381,17 @@ And we save the obtained data.

    tomo_align_no_dist = struct('t', t, 'MTr', MTr);
    -save('experiment_tomography/mat/experiment.mat', 'tomo_align_no_dist', '-append');
    +save('./mat/experiment_tomography.mat', 'tomo_align_no_dist', '-append');
     
    -
    -

    2.2 Analysis

    +
    +

    2.2 Analysis

    -
    load('experiment_tomography/mat/experiment.mat', 'tomo_align_no_dist');
    +
    load('./mat/experiment_tomography.mat', 'tomo_align_no_dist');
     t = tomo_align_no_dist.t;
     MTr = tomo_align_no_dist.MTr;
     
    @@ -446,8 +424,8 @@ Erz = atan2(-squeeze(MTr(1, 2, -

    2.3 Conclusion

    +
    +

    2.3 Conclusion

    @@ -467,8 +445,8 @@ This residual error motion probably comes from a small misalignment somewhere.

    -
    -

    3.1 Simulation Setup

    +
    +

    3.1 Simulation Setup

    We now activate the disturbances. @@ -498,17 +476,17 @@ And we save the obtained data.

    tomo_align_dist = struct('t', t, 'MTr', MTr);
    -save('experiment_tomography/mat/experiment.mat', 'tomo_align_dist', '-append');
    +save('./mat/experiment_tomography.mat', 'tomo_align_dist', '-append');
     
    -
    -

    3.2 Analysis

    +
    +

    3.2 Analysis

    -
    load('experiment_tomography/mat/experiment.mat', 'tomo_align_dist');
    +
    load('./mat/experiment_tomography.mat', 'tomo_align_dist');
     t = tomo_align_dist.t;
     MTr = tomo_align_dist.MTr;
     
    @@ -541,8 +519,8 @@ Erz = atan2(-squeeze(MTr(1, 2, -

    3.3 Conclusion

    +
    +

    3.3 Conclusion

    @@ -561,8 +539,8 @@ Error motion is what expected from the disturbance measurements.

    -
    -

    4.1 Simulation Setup

    +
    +

    4.1 Simulation Setup

    We first set the wanted translation of the Micro Hexapod. @@ -616,17 +594,17 @@ And we save the obtained data.

    tomo_not_align = struct('t', t, 'MTr', MTr);
    -save('experiment_tomography/mat/experiment.mat', 'tomo_not_align', '-append');
    +save('./mat/experiment_tomography.mat', 'tomo_not_align', '-append');
     
    -
    -

    4.2 Analysis

    +
    +

    4.2 Analysis

    -
    load('experiment_tomography/mat/experiment.mat', 'tomo_not_align');
    +
    load('./mat/experiment_tomography.mat', 'tomo_not_align');
     t = tomo_not_align.t;
     MTr = tomo_not_align.MTr;
     
    @@ -659,8 +637,8 @@ Erz = atan2(-squeeze(MTr(1, 2, -

    4.3 Conclusion

    +
    +

    4.3 Conclusion

    @@ -679,8 +657,8 @@ The main motions are translations in the X direction of the mobile platform (cor

    -
    -

    5.1 Simulation Setup

    +
    +

    5.1 Simulation Setup

    We set the reference path. @@ -735,17 +713,17 @@ And we save the obtained data.

    ty_scan = struct('t', t, 'MTr', MTr);
    -save('experiment_tomography/mat/experiment.mat', 'ty_scan', '-append');
    +save('./mat/experiment_tomography.mat', 'ty_scan', '-append');
     
    -
    -

    5.2 Analysis

    +
    +

    5.2 Analysis

    -
    load('experiment_tomography/mat/experiment.mat', 'ty_scan');
    +
    load('./mat/experiment_tomography.mat', 'ty_scan');
     t = ty_scan.t;
     MTr = ty_scan.MTr;
     
    @@ -778,8 +756,8 @@ Erz = atan2(-squeeze(MTr(1, 2, -

    5.3 Conclusion

    +
    +

    5.3 Conclusion

    @@ -794,7 +772,7 @@ In order to reduce the errors, we can make a smoother reference path for the tra

    Author: Dehaeze Thomas

    -

    Created: 2020-02-25 mar. 18:21

    +

    Created: 2020-03-13 ven. 17:39

    diff --git a/docs/figs/comp_iff_dvf_simplified.pdf b/docs/figs/comp_iff_dvf_simplified.pdf new file mode 100644 index 0000000..9d5b5c1 Binary files /dev/null and b/docs/figs/comp_iff_dvf_simplified.pdf differ diff --git a/docs/figs/comp_iff_dvf_simplified.png b/docs/figs/comp_iff_dvf_simplified.png new file mode 100644 index 0000000..cbd8e89 Binary files /dev/null and b/docs/figs/comp_iff_dvf_simplified.png differ diff --git a/docs/figs/hac_lac_control_schematic.pdf b/docs/figs/hac_lac_control_schematic.pdf new file mode 100644 index 0000000..c047068 Binary files /dev/null and b/docs/figs/hac_lac_control_schematic.pdf differ diff --git a/docs/figs/hac_lac_control_schematic.png b/docs/figs/hac_lac_control_schematic.png new file mode 100644 index 0000000..08eb497 Binary files /dev/null and b/docs/figs/hac_lac_control_schematic.png differ diff --git a/docs/figs/nano_station_control_2dof_x.pdf b/docs/figs/nano_station_control_2dof_x.pdf new file mode 100644 index 0000000..9873058 Binary files /dev/null and b/docs/figs/nano_station_control_2dof_x.pdf differ diff --git a/docs/figs/nano_station_control_2dof_x.png b/docs/figs/nano_station_control_2dof_x.png new file mode 100644 index 0000000..95d46cc Binary files /dev/null and b/docs/figs/nano_station_control_2dof_x.png differ diff --git a/docs/figs/nano_station_control_Fm.pdf b/docs/figs/nano_station_control_Fm.pdf new file mode 100644 index 0000000..a471b93 Binary files /dev/null and b/docs/figs/nano_station_control_Fm.pdf differ diff --git a/docs/figs/nano_station_control_Fm.png b/docs/figs/nano_station_control_Fm.png new file mode 100644 index 0000000..b25a810 Binary files /dev/null and b/docs/figs/nano_station_control_Fm.png differ diff --git a/docs/figs/nano_station_control_d.pdf b/docs/figs/nano_station_control_d.pdf new file mode 100644 index 0000000..9c05e02 Binary files /dev/null and b/docs/figs/nano_station_control_d.pdf differ diff --git a/docs/figs/nano_station_control_d.png b/docs/figs/nano_station_control_d.png new file mode 100644 index 0000000..e5af89a Binary files /dev/null and b/docs/figs/nano_station_control_d.png differ diff --git a/docs/figs/nano_station_control_x.pdf b/docs/figs/nano_station_control_x.pdf new file mode 100644 index 0000000..c5d82b4 Binary files /dev/null and b/docs/figs/nano_station_control_x.pdf differ diff --git a/docs/figs/nano_station_control_x.png b/docs/figs/nano_station_control_x.png new file mode 100644 index 0000000..6b5b4c5 Binary files /dev/null and b/docs/figs/nano_station_control_x.png differ diff --git a/docs/figs/nano_station_ground_motion.pdf b/docs/figs/nano_station_ground_motion.pdf new file mode 100644 index 0000000..e3fb4a0 Binary files /dev/null and b/docs/figs/nano_station_ground_motion.pdf differ diff --git a/docs/figs/nano_station_ground_motion.png b/docs/figs/nano_station_ground_motion.png new file mode 100644 index 0000000..ca4b605 Binary files /dev/null and b/docs/figs/nano_station_ground_motion.png differ diff --git a/docs/figs/nano_station_inputs_outputs.pdf b/docs/figs/nano_station_inputs_outputs.pdf new file mode 100644 index 0000000..9bd69d6 Binary files /dev/null and b/docs/figs/nano_station_inputs_outputs.pdf differ diff --git a/docs/figs/nano_station_inputs_outputs.png b/docs/figs/nano_station_inputs_outputs.png new file mode 100644 index 0000000..0fefc92 Binary files /dev/null and b/docs/figs/nano_station_inputs_outputs.png differ diff --git a/docs/figs/nano_station_inputs_outputs_ground_motion.pdf b/docs/figs/nano_station_inputs_outputs_ground_motion.pdf new file mode 100644 index 0000000..31ecff5 Binary files /dev/null and b/docs/figs/nano_station_inputs_outputs_ground_motion.pdf differ diff --git a/docs/figs/nano_station_inputs_outputs_ground_motion.png b/docs/figs/nano_station_inputs_outputs_ground_motion.png new file mode 100644 index 0000000..ab23b5b Binary files /dev/null and b/docs/figs/nano_station_inputs_outputs_ground_motion.png differ diff --git a/docs/figs/nass_simple_model.pdf b/docs/figs/nass_simple_model.pdf new file mode 100644 index 0000000..d6e98da Binary files /dev/null and b/docs/figs/nass_simple_model.pdf differ diff --git a/docs/figs/nass_simple_model.png b/docs/figs/nass_simple_model.png new file mode 100644 index 0000000..f76b2f6 Binary files /dev/null and b/docs/figs/nass_simple_model.png differ diff --git a/docs/figs/simple_comp_vc_pz.pdf b/docs/figs/simple_comp_vc_pz.pdf new file mode 100644 index 0000000..6cbc447 Binary files /dev/null and b/docs/figs/simple_comp_vc_pz.pdf differ diff --git a/docs/figs/simple_comp_vc_pz.png b/docs/figs/simple_comp_vc_pz.png new file mode 100644 index 0000000..09b80b1 Binary files /dev/null and b/docs/figs/simple_comp_vc_pz.png differ diff --git a/docs/figs/simple_hac_lac_results.pdf b/docs/figs/simple_hac_lac_results.pdf new file mode 100644 index 0000000..e745123 Binary files /dev/null and b/docs/figs/simple_hac_lac_results.pdf differ diff --git a/docs/figs/simple_hac_lac_results.png b/docs/figs/simple_hac_lac_results.png new file mode 100644 index 0000000..4ee2b66 Binary files /dev/null and b/docs/figs/simple_hac_lac_results.png differ diff --git a/docs/figs/simple_hac_lac_results_soft.pdf b/docs/figs/simple_hac_lac_results_soft.pdf new file mode 100644 index 0000000..a0806f1 Binary files /dev/null and b/docs/figs/simple_hac_lac_results_soft.pdf differ diff --git a/docs/figs/simple_hac_lac_results_soft.png b/docs/figs/simple_hac_lac_results_soft.png new file mode 100644 index 0000000..586a30b Binary files /dev/null and b/docs/figs/simple_hac_lac_results_soft.png differ diff --git a/docs/figs/simple_loop_gain_pz.pdf b/docs/figs/simple_loop_gain_pz.pdf new file mode 100644 index 0000000..44228d8 Binary files /dev/null and b/docs/figs/simple_loop_gain_pz.pdf differ diff --git a/docs/figs/simple_loop_gain_pz.png b/docs/figs/simple_loop_gain_pz.png new file mode 100644 index 0000000..cc104db Binary files /dev/null and b/docs/figs/simple_loop_gain_pz.png differ diff --git a/docs/functions.html b/docs/functions.html index cb5021f..ab576ca 100644 --- a/docs/functions.html +++ b/docs/functions.html @@ -4,7 +4,7 @@ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> - + Matlab Functions used for the NASS Project @@ -202,50 +202,28 @@ @@ -259,276 +237,15 @@ for the JavaScript code in this tag.

    Table of Contents

    -
    -

    1 computePsdDispl

    -
    -

    - -

    - -

    -This Matlab function is accessible here. -

    - -
    -
    function [psd_object] = computePsdDispl(sys_data, t_init, n_av)
    -    i_init = find(sys_data.time > t_init, 1);
    -
    -    han_win = hanning(ceil(length(sys_data.Dx(i_init:end, :))/n_av));
    -    Fs = 1/sys_data.time(2);
    -
    -    [pdx, f] = pwelch(sys_data.Dx(i_init:end, :), han_win, [], [], Fs);
    -    [pdy, ~] = pwelch(sys_data.Dy(i_init:end, :), han_win, [], [], Fs);
    -    [pdz, ~] = pwelch(sys_data.Dz(i_init:end, :), han_win, [], [], Fs);
    -
    -    [prx, ~] = pwelch(sys_data.Rx(i_init:end, :), han_win, [], [], Fs);
    -    [pry, ~] = pwelch(sys_data.Ry(i_init:end, :), han_win, [], [], Fs);
    -    [prz, ~] = pwelch(sys_data.Rz(i_init:end, :), han_win, [], [], Fs);
    -
    -    psd_object = struct(...
    -        'f',  f,   ...
    -        'dx', pdx, ...
    -        'dy', pdy, ...
    -        'dz', pdz, ...
    -        'rx', prx, ...
    -        'ry', pry, ...
    -        'rz', prz);
    -end
    -
    -
    -
    -
    - -
    -

    2 computeSetpoint

    -
    -

    - -

    - -

    -This Matlab function is accessible here. -

    - -
    -
    function setpoint = computeSetpoint(ty, ry, rz)
    -%%
    -setpoint = zeros(6, 1);
    -
    -%% Ty
    -Ty = [1 0 0 0  ;
    -      0 1 0 ty ;
    -      0 0 1 0  ;
    -      0 0 0 1 ];
    -
    -% Tyinv = [1 0 0  0  ;
    -%          0 1 0 -ty ;
    -%          0 0 1  0  ;
    -%          0 0 0  1 ];
    -
    -%% Ry
    -Ry = [ cos(ry) 0 sin(ry) 0 ;
    -      0       1 0       0 ;
    -      -sin(ry) 0 cos(ry) 0 ;
    -      0        0 0       1 ];
    -
    -% TMry = Ty*Ry*Tyinv;
    -
    -%% Rz
    -Rz = [cos(rz) -sin(rz) 0 0 ;
    -      sin(rz)  cos(rz) 0 0 ;
    -      0        0       1 0 ;
    -      0        0       0 1 ];
    -
    -% TMrz = Ty*TMry*Rz*TMry'*Tyinv;
    -
    -%% All stages
    -% TM = TMrz*TMry*Ty;
    -
    -TM = Ty*Ry*Rz;
    -
    -[thetax, thetay, thetaz] = RM2angle(TM(1:3, 1:3));
    -
    -setpoint(1:3) = TM(1:3, 4);
    -setpoint(4:6) = [thetax, thetay, thetaz];
    -
    -%% Custom Functions
    -function [thetax, thetay, thetaz] = RM2angle(R)
    -    if abs(abs(R(3, 1)) - 1) > 1e-6 % R31 != 1 and R31 != -1
    -        thetay = -asin(R(3, 1));
    -        thetax = atan2(R(3, 2)/cos(thetay), R(3, 3)/cos(thetay));
    -        thetaz = atan2(R(2, 1)/cos(thetay), R(1, 1)/cos(thetay));
    -    else
    -        thetaz = 0;
    -        if abs(R(3, 1)+1) < 1e-6 % R31 = -1
    -            thetay = pi/2;
    -            thetax = thetaz + atan2(R(1, 2), R(1, 3));
    -        else
    -            thetay = -pi/2;
    -            thetax = -thetaz + atan2(-R(1, 2), -R(1, 3));
    -        end
    -    end
    -end
    -end
    -
    -
    -
    -
    - -
    -

    3 converErrorBasis

    -
    -

    - -

    - -

    -This Matlab function is accessible here. -

    - -
    -
    function error_nass = convertErrorBasis(pos, setpoint, ty, ry, rz)
    -% convertErrorBasis -
    -%
    -% Syntax: convertErrorBasis(p_error, ty, ry, rz)
    -%
    -% Inputs:
    -%    - p_error - Position error of the sample w.r.t. the granite [m, rad]
    -%    - ty - Measured translation of the Ty stage [m]
    -%    - ry - Measured rotation of the Ry stage [rad]
    -%    - rz - Measured rotation of the Rz stage [rad]
    -%
    -% Outputs:
    -%    - P_nass - Position error of the sample w.r.t. the NASS base [m]
    -%    - R_nass - Rotation error of the sample w.r.t. the NASS base [rad]
    -%
    -% Example:
    -%
    -
    -%% If line vector => column vector
    -if size(pos, 2) == 6
    -    pos = pos';
    -end
    -
    -if size(setpoint, 2) == 6
    -    setpoint = setpoint';
    -end
    -
    -%% Position of the sample in the frame fixed to the Granite
    -P_granite = [pos(1:3); 1]; % Position [m]
    -R_granite = [setpoint(1:3); 1]; % Reference [m]
    -
    -%% Transformation matrices of the stages
    -% T-y
    -TMty = [1 0 0 0  ;
    -        0 1 0 ty ;
    -        0 0 1 0  ;
    -        0 0 0 1 ];
    -
    -% R-y
    -TMry = [ cos(ry) 0 sin(ry) 0 ;
    -        0       1 0       0 ;
    -        -sin(ry) 0 cos(ry) 0 ;
    -        0        0 0       1 ];
    -
    -% R-z
    -TMrz = [cos(rz) -sin(rz) 0 0 ;
    -        sin(rz)  cos(rz) 0 0 ;
    -        0        0       1 0 ;
    -        0        0       0 1 ];
    -
    -%% Compute Point coordinates in the new reference fixed to the NASS base
    -% P_nass = TMrz*TMry*TMty*P_granite;
    -P_nass = TMrz\TMry\TMty\P_granite;
    -R_nass = TMrz\TMry\TMty\R_granite;
    -
    -dx = R_nass(1)-P_nass(1);
    -dy = R_nass(2)-P_nass(2);
    -dz = R_nass(3)-P_nass(3);
    -
    -%% Compute new basis vectors linked to the NASS base
    -% ux_nass = TMrz*TMry*TMty*[1; 0; 0; 0];
    -% ux_nass = ux_nass(1:3);
    -% uy_nass = TMrz*TMry*TMty*[0; 1; 0; 0];
    -% uy_nass = uy_nass(1:3);
    -% uz_nass = TMrz*TMry*TMty*[0; 0; 1; 0];
    -% uz_nass = uz_nass(1:3);
    -
    -ux_nass = TMrz\TMry\TMty\[1; 0; 0; 0];
    -ux_nass = ux_nass(1:3);
    -uy_nass = TMrz\TMry\TMty\[0; 1; 0; 0];
    -uy_nass = uy_nass(1:3);
    -uz_nass = TMrz\TMry\TMty\[0; 0; 1; 0];
    -uz_nass = uz_nass(1:3);
    -
    -%% Rotations error w.r.t. granite Frame
    -% Rotations error w.r.t. granite Frame
    -rx_nass = pos(4);
    -ry_nass = pos(5);
    -rz_nass = pos(6);
    -
    -% Rotation matrices of the Sample w.r.t. the Granite
    -Mrx_error = [1 0              0 ;
    -            0 cos(-rx_nass) -sin(-rx_nass) ;
    -            0 sin(-rx_nass)  cos(-rx_nass)];
    -
    -Mry_error = [ cos(-ry_nass) 0 sin(-ry_nass) ;
    -              0             1 0 ;
    -            -sin(-ry_nass) 0 cos(-ry_nass)];
    -
    -Mrz_error = [cos(-rz_nass) -sin(-rz_nass) 0 ;
    -            sin(-rz_nass)  cos(-rz_nass) 0 ;
    -            0              0             1];
    -
    -% Rotation matrix of the Sample w.r.t. the Granite
    -Mr_error = Mrz_error*Mry_error*Mrx_error;
    -
    -%% Use matrix to solve
    -R = Mr_error/[ux_nass, uy_nass, uz_nass]; % Rotation matrix from NASS base to Sample
    -
    -[thetax, thetay, thetaz] = RM2angle(R);
    -
    -error_nass = [dx; dy; dz; thetax; thetay; thetaz];
    -
    -%% Custom Functions
    -function [thetax, thetay, thetaz] = RM2angle(R)
    -    if abs(abs(R(3, 1)) - 1) > 1e-6 % R31 != 1 and R31 != -1
    -        thetay = -asin(R(3, 1));
    -        % thetaybis = pi-thetay;
    -        thetax = atan2(R(3, 2)/cos(thetay), R(3, 3)/cos(thetay));
    -        % thetaxbis = atan2(R(3, 2)/cos(thetaybis), R(3, 3)/cos(thetaybis));
    -        thetaz = atan2(R(2, 1)/cos(thetay), R(1, 1)/cos(thetay));
    -        % thetazbis = atan2(R(2, 1)/cos(thetaybis), R(1, 1)/cos(thetaybis));
    -    else
    -        thetaz = 0;
    -        if abs(R(3, 1)+1) < 1e-6 % R31 = -1
    -            thetay = pi/2;
    -            thetax = thetaz + atan2(R(1, 2), R(1, 3));
    -        else
    -            thetay = -pi/2;
    -            thetax = -thetaz + atan2(-R(1, 2), -R(1, 3));
    -        end
    -    end
    -end
    -
    -end
    -
    -
    -
    -
    -
    -

    4 computeReferencePose

    -
    +

    1 computeReferencePose

    +

    @@ -620,8 +337,8 @@ This Matlab function is accessible here
    -

    5 Compute the Sample Position Error w.r.t. the NASS

    -
    +

    2 Compute the Sample Position Error w.r.t. the NASS

    +

    @@ -658,7 +375,7 @@ MTr = [WTm(1:3,1:3)<

    Author: Dehaeze Thomas

    -

    Created: 2020-02-25 mar. 18:20

    +

    Created: 2020-03-06 ven. 15:09

    diff --git a/docs/hac_lac.html b/docs/hac_lac.html index 55fe05c..4b3c363 100644 --- a/docs/hac_lac.html +++ b/docs/hac_lac.html @@ -4,7 +4,7 @@ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> - + HAC-LAC applied on the Simscape Model @@ -202,51 +202,39 @@ + + -
    -

    1 Undamped System

    -

    - +The position \(\bm{\mathcal{X}}\) of the Sample with respect to the granite is measured. +

    + +

    +It is then compare to the wanted position of the Sample \(\bm{r}_\mathcal{X}\) in order to obtain the position error \(\bm{\epsilon}_\mathcal{X}\) of the Sample with respect to a frame attached to the Stewart top platform. +

    + + +
    +

    hac_lac_control_schematic.png

    -
    -

    1.1 Identification of the plant

    -
    -
    -
    -

    1.1.1 Initialize the Simulation

    -
    +
    +

    1 Initialization

    +

    We initialize all the stages with the default parameters.

    @@ -324,137 +305,199 @@ The nano-hexapod is a piezoelectric hexapod and the sample has a mass of 50kg.

    initializeNanoHexapod('actuator', 'piezo');
    -initializeSample('mass', 50);
    +initializeSample('mass', 1);
     

    -No disturbances. +We set the references that corresponds to a tomography experiment.

    -
    initializeDisturbances('enable', false);
    +
    initializeReferences('Rz_type', 'rotating', 'Rz_period', 1);
     
    -

    -We set the references to zero. -

    -
    initializeReferences();
    +
    initializeDisturbances();
     

    -And all the controllers are set to 0. +Open Loop.

    initializeController('type', 'open-loop');
     
    -
    -
    -
    -

    1.1.2 Identification

    -

    -First, we identify the dynamics of the system using the linearize function. +And we put some gravity.

    -
    %% Options for Linearized
    -options = linearizeOptions;
    -options.SampleTime = 0;
    +
    initializeSimscapeConfiguration('gravity', true);
    +
    +
    -%% Name of the Simulink File +

    +We log the signals. +

    +
    +
    initializeLoggingConfiguration('log', 'all');
    +
    +
    +
    +
    + +
    +

    2 Low Authority Control - Direct Velocity Feedback \(\bm{K}_\mathcal{L}\)

    +
    +

    +The first loop closed corresponds to a direct velocity feedback loop. +

    + +

    +The design of the associated decentralized controller is explained in this file. +

    +
    + +
    +

    2.1 Identification

    +
    +
    +
    %% Name of the Simulink File
     mdl = 'nass_model';
     
     %% Input/Output definition
     clear io; io_i = 1;
    -io(io_i) = linio([mdl, '/Controller'],     1, 'openinput');            io_i = io_i + 1; % Actuator Inputs
    -io(io_i) = linio([mdl, '/Tracking Error'], 1, 'openoutput', [], 'En'); io_i = io_i + 1; % Metrology Outputs
    +io(io_i) = linio([mdl, '/Controller'],    1, 'openinput');               io_i = io_i + 1; % Actuator Inputs
    +io(io_i) = linio([mdl, '/Micro-Station'], 3, 'openoutput', [], 'Dnlm');  io_i = io_i + 1; % Relative Motion Outputs
     
     %% Run the linearization
    -G = linearize(mdl, io, options);
    -G.InputName  = {'Fnl1', 'Fnl2', 'Fnl3', 'Fnl4', 'Fnl5', 'Fnl6'};
    -G.OutputName = {'Edx', 'Edy', 'Edz', 'Erx', 'Ery', 'Erz'};
    +G_dvf = linearize(mdl, io, 0);
    +G_dvf.InputName  = {'Fnl1', 'Fnl2', 'Fnl3', 'Fnl4', 'Fnl5', 'Fnl6'};
    +G_dvf.OutputName = {'Dnlm1', 'Dnlm2', 'Dnlm3', 'Dnlm4', 'Dnlm5', 'Dnlm6'};
    +
    +
    +
    +
    + +
    +

    2.2 Plant

    +
    +
    +

    2.3 Root Locus

    +
    +
    +

    2.4 Controller and Loop Gain

    +
    +
    +
    K_dvf = s*15000/(1 + s/2/pi/10000);
     
    +
    +
    K_dvf = -K_dvf*eye(6);
    +
    +
    +
    +
    +
    + +
    +

    3 High Authority Control - \(\bm{K}_\mathcal{X}\)

    +
    +
    +
    +

    3.1 Identification of the damped plant

    +
    +
    +
    Kx = tf(zeros(6));
    +
    +
    + +
    +
    initializeController('type', 'hac-dvf');
    +
    +
    + +
    +
    %% Name of the Simulink File
    +mdl = 'nass_model';
    +
    +%% Input/Output definition
    +clear io; io_i = 1;
    +io(io_i) = linio([mdl, '/Controller'],     1, 'input');            io_i = io_i + 1; % Actuator Inputs
    +io(io_i) = linio([mdl, '/Tracking Error'], 1, 'output', [], 'En'); io_i = io_i + 1; % Position Errror
    +
    +%% Run the linearization
    +G = linearize(mdl, io, 0);
    +G.InputName  = {'Fnl1', 'Fnl2', 'Fnl3', 'Fnl4', 'Fnl5', 'Fnl6'};
    +G.OutputName = {'Ex', 'Ey', 'Ez', 'Erx', 'Ery', 'Erz'};
    +
    +
    + +

    +The minus sine is put here because there is already a minus sign included due to the computation of the position error. +

    load('mat/stages.mat', 'nano_hexapod');
    -G_cart = minreal(G*inv(nano_hexapod.J'));
    -G_cart.InputName = {'Fnx', 'Fny', 'Fnz', 'Mnx', 'Mny', 'Mnz'};
    +
    +Gx = -G*inv(nano_hexapod.J');
    +Gx.InputName  = {'Fx', 'Fy', 'Fz', 'Mx', 'My', 'Mz'};
    +
    +
    +
    +
    + +
    +

    3.2 Controller Design

    +
    +

    +The controller consists of: +

    +
      +
    • A pure integrator
    • +
    • A Second integrator up to half the wanted bandwidth
    • +
    • A Lead around the cross-over frequency
    • +
    • A low pass filter with a cut-off equal to two times the wanted bandwidth
    • +
    + +
    +
    wc = 2*pi*15; % Bandwidth Bandwidth [rad/s]
    +
    +h = 1.5; % Lead parameter
    +
    +Kx = (1/h) * (1 + s/wc*h)/(1 + s/wc/h) * wc/s * ((s/wc*2 + 1)/(s/wc*2)) * (1/(1 + s/wc/2));
    +
    +% Normalization of the gain of have a loop gain of 1 at frequency wc
    +Kx = Kx.*diag(1./diag(abs(freqresp(Gx*Kx, wc))));
     
    -
    G_legs = minreal(inv(nano_hexapod.J)*G);
    -G_legs.OutputName = {'e1', 'e2', 'e3', 'e4', 'e5', 'e6'};
    +
    isstable(feedback(Gx*Kx, eye(6), -1))
     
    -
    -
    -
    -

    1.1.3 Display TF

    -
    - -
    -

    plant_G_cart.png -

    -

    Figure 1: Transfer Function from forces applied by the nano-hexapod to position error (png, pdf)

    -
    -
    -
    - -
    -

    1.1.4 Obtained Plants for Active Damping

    -
    - -
    -

    nass_active_damping_iff_plant.png -

    -

    Figure 2: G_iff: IFF Plant (png, pdf)

    -
    - - -
    -

    nass_active_damping_ine_plant.png -

    -

    Figure 3: G_dvf: Plant for Direct Velocity Feedback (png, pdf)

    -
    - - -
    -

    nass_active_damping_inertial_plant.png -

    -

    Figure 4: Inertial Feedback Plant (png, pdf)

    -
    -
    -
    -
    - -
    -

    1.2 Tomography Experiment

    -
    -
    -
    -

    1.2.1 Simulation

    -
    -

    -We initialize elements for the tomography experiment. -

    -
    prepareTomographyExperiment();
    +
    Kx = inv(nano_hexapod.J')*Kx;
     
    -

    -We change the simulation stop time. -

    +
    +
    isstable(feedback(G*Kx, eye(6), 1))
    +
    +
    +
    +
    +
    + +
    +

    4 Simulation

    +
    load('mat/conf_simulink.mat');
    -set_param(conf_simulink, 'StopTime', '3');
    +set_param(conf_simulink, 'StopTime', '1.5');
     
    @@ -466,186 +509,26 @@ And we simulate the system.
    -

    -Finally, we save the simulation results for further analysis -

    -
    save('./active_damping/mat/tomo_exp.mat', 'En', 'Eg', '-append');
    +
    save('./mat/tomo_exp_hac_lac.mat', 'simout');
     
    -
    -

    1.2.2 Results

    -
    -

    -We load the results of tomography experiments. -

    +
    +

    5 Results

    +
    -
    load('./active_damping/mat/tomo_exp.mat', 'En');
    -t = linspace(0, 3, length(En(:,1)));
    +
    load('./mat/tomo_exp_hac_lac.mat', 'simout');
     
    - - -
    -

    nass_act_damp_undamped_sim_tomo_trans.png -

    -

    Figure 5: Position Error during tomography experiment - Translations (png, pdf)

    -
    - - -
    -

    nass_act_damp_undamped_sim_tomo_rot.png -

    -

    Figure 6: Position Error during tomography experiment - Rotations (png, pdf)

    -
    -
    -
    -
    - -
    -

    1.3 Verification of the transfer function from nano hexapod to metrology

    -
    -
    -
    -

    1.3.1 Initialize the Simulation

    -
    -

    -We initialize all the stages with the default parameters. -

    -
    -
    initializeGround();
    -initializeGranite();
    -initializeTy();
    -initializeRy();
    -initializeRz();
    -initializeMicroHexapod();
    -initializeAxisc();
    -initializeMirror();
    -
    -
    - -

    -The nano-hexapod is a piezoelectric hexapod and the sample has a mass of 50kg. -

    -
    -
    initializeNanoHexapod('actuator', 'piezo');
    -initializeSample('mass', 50);
    -
    -
    - -

    -No disturbances. -

    -
    -
    initializeDisturbances('enable', false);
    -
    -
    - -

    -We set the references to zero. -

    -
    -
    initializeReferences();
    -
    -
    - -

    -And all the controllers are set to 0. -

    -
    -
    initializeController('type', 'open-loop');
    -
    -
    -
    -
    - -
    -

    1.3.2 Identification

    -
    -

    -First, we identify the dynamics of the system using the linearize function. -

    -
    -
    %% Options for Linearized
    -options = linearizeOptions;
    -options.SampleTime = 0;
    -
    -%% Name of the Simulink File
    -mdl = 'nass_model';
    -
    -%% Input/Output definition
    -clear io; io_i = 1;
    -io(io_i) = linio([mdl, '/Controller'],     1, 'openinput');            io_i = io_i + 1; % Actuator Inputs
    -io(io_i) = linio([mdl, '/Tracking Error'], 1, 'openoutput', [], 'En'); io_i = io_i + 1; % Metrology Outputs
    -
    -%% Run the linearization
    -G = linearize(mdl, io, options);
    -G.InputName  = {'Fnl1', 'Fnl2', 'Fnl3', 'Fnl4', 'Fnl5', 'Fnl6'};
    -G.OutputName = {'Edx', 'Edy', 'Edz', 'Erx', 'Ery', 'Erz'};
    -
    -
    - -
    -
    load('mat/stages.mat', 'nano_hexapod');
    -G_cart = minreal(G*inv(nano_hexapod.J'));
    -G_cart.InputName = {'Fnx', 'Fny', 'Fnz', 'Mnx', 'Mny', 'Mnz'};
    -
    -
    - -
    -
    G_legs = minreal(inv(nano_hexapod.J)*G);
    -G_legs.OutputName = {'e1', 'e2', 'e3', 'e4', 'e5', 'e6'};
    -
    -
    -
    -
    - -
    -

    1.3.3 Display TF

    -
    - -
    -

    plant_G_cart.png -

    -

    Figure 7: Transfer Function from forces applied by the nano-hexapod to position error (png, pdf)

    -
    -
    -
    - -
    -

    1.3.4 Obtained Plants for Active Damping

    -
    - -
    -

    nass_active_damping_iff_plant.png -

    -

    Figure 8: G_iff: IFF Plant (png, pdf)

    -
    - - -
    -

    nass_active_damping_ine_plant.png -

    -

    Figure 9: G_dvf: Plant for Direct Velocity Feedback (png, pdf)

    -
    - - -
    -

    nass_active_damping_inertial_plant.png -

    -

    Figure 10: Inertial Feedback Plant (png, pdf)

    -
    -
    -

    Author: Dehaeze Thomas

    -

    Created: 2020-02-25 mar. 18:20

    +

    Created: 2020-03-13 ven. 17:39

    diff --git a/docs/identification.html b/docs/identification.html index b05bdd3..78b13f6 100644 --- a/docs/identification.html +++ b/docs/identification.html @@ -4,7 +4,7 @@ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> - + Identification @@ -202,50 +202,28 @@ @@ -411,7 +389,7 @@ These functions are all defined here.

    Author: Dehaeze Thomas

    -

    Created: 2020-02-25 mar. 18:18

    +

    Created: 2020-03-06 ven. 15:09

    diff --git a/docs/kinematics.html b/docs/kinematics.html index dca11c0..7282706 100644 --- a/docs/kinematics.html +++ b/docs/kinematics.html @@ -4,7 +4,7 @@ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> - + Kinematics of the station @@ -202,50 +202,28 @@ + + + + +
    + UP + | + HOME +
    +

    Motion and Force Requirements for the Nano-Hexapod

    +
    +

    Table of Contents

    + +
    + + +
    +

    1 Soft Hexapod

    +
    +

    +As the nano-hexapod is in series with the other stages, it must apply all the force required to move the sample. +

    + +

    +If the nano-hexapod is soft (voice coil), its actuator must apply all the force such that the sample has the wanted motion. +

    + +

    +In some sense, it does not use the fact that the other stage are participating to the displacement of the sample. +

    + +

    +Let’s take two examples: +

    +
      +
    • Sinus Ty translation at 1Hz with an amplitude of 5mm
    • +
    • Long stroke hexapod has an offset of 10mm in X and the spindle is rotating +Thus the wanted motion is a circle with a radius of 10mm +If the sample if light (30Kg) => 60rpm +If the sample if heavy (100Kg) => 1rpm
    • +
    + +

    +From the motion, we compute the required acceleration by derive the displacement two times. +Then from the Newton’s second law: \(m \vec{a} = \sum \vec{F}\) we can compute the required force. +

    +
    + +
    +

    1.1 Example

    +
    +

    +The wanted motion is: +

    +\begin{align*} + x &= d \cos(\omega t) \\ + y &= d \sin(\omega t) +\end{align*} + +

    +The corresponding acceleration is thus: +

    +\begin{align*} + \ddot{x} &= - d \omega^2 \cos(\omega t) \\ + \ddot{y} &= - d \omega^2 \sin(\omega t) +\end{align*} + +

    +From the Newton’s second law: +

    +\begin{align*} + m \ddot{x} &= F_x \\ + m \ddot{y} &= F_y +\end{align*} + +

    +Thus the applied forces should be: +

    +\begin{align*} + F_x &= - m d \omega^2 \cos(\omega t) \\ + F_y &= - m d \omega^2 \sin(\omega t) +\end{align*} + +

    +And the norm of the force is: +\[ |F| = \sqrt{F_x^2 + F_y^2} = m d \omega^2 \ [N] \] +

    + + +

    +For a Light sample: +

    +
    +
    m = 30;
    +d = 10e-3;
    +w = 2*pi;
    +F = m*d*w^2;
    +ans = F
    +
    +
    + +
    +11.844
    +
    + + +

    +For the Heavy sample: +

    +
    +
    m = 80;
    +d = 10e-3;
    +w = 2*pi/60;
    +F = m*d*w^2
    +ans = F
    +
    +
    + +
    +0.008773
    +
    +
    +
    +
    +
    +
    +

    Author: Dehaeze Thomas

    +

    Created: 2020-03-13 ven. 17:39

    +
    + + diff --git a/docs/positioning_error.html b/docs/positioning_error.html index 60a2ac2..608ab94 100644 --- a/docs/positioning_error.html +++ b/docs/positioning_error.html @@ -4,7 +4,7 @@ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> - + Computation of the Positioning Error with respect to the nano-hexapod @@ -202,50 +202,28 @@ @@ -775,7 +753,7 @@ Internal force, acting reciprocally between base and following origins is implem

    Author: Dehaeze Thomas

    -

    Created: 2020-02-25 mar. 18:20

    +

    Created: 2020-03-06 ven. 15:09

    diff --git a/docs/simscape_subsystems.html b/docs/simscape_subsystems.html index 31032df..b259b53 100644 --- a/docs/simscape_subsystems.html +++ b/docs/simscape_subsystems.html @@ -4,7 +4,7 @@ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> - + Subsystems used for the Simscape Models @@ -202,50 +202,28 @@ @@ -261,169 +239,170 @@ for the JavaScript code in this tag.
    -
    -

    Function description

    -
    +
    +

    Function description

    +
    function [] = initializeSimscapeConfiguration(args)
     
    @@ -493,9 +472,9 @@ These functions are defined below.
    -
    -

    Optional Parameters

    -
    +
    +

    Optional Parameters

    +
    arguments
       args.gravity logical {mustBeNumericOrLogical} = true
    @@ -505,9 +484,9 @@ These functions are defined below.
     
    -
    -

    Structure initialization

    -
    +
    +

    Structure initialization

    +
    conf_simscape = struct();
     
    @@ -515,9 +494,9 @@ These functions are defined below.
    -
    -

    Add Type

    -
    +
    +

    Add Type

    +
    if args.gravity
       conf_simscape.type = 1;
    @@ -529,9 +508,9 @@ These functions are defined below.
     
    -
    -

    Save the Structure

    -
    +
    +

    Save the Structure

    +
    save('./mat/conf_simscape.mat', 'conf_simscape');
     
    @@ -548,9 +527,9 @@ These functions are defined below.

    -
    -

    Function description

    -
    +
    +

    Function description

    +
    function [] = initializeLoggingConfiguration(args)
     
    @@ -558,9 +537,9 @@ These functions are defined below.
    -
    -

    Optional Parameters

    -
    +
    +

    Optional Parameters

    +
    arguments
       args.log      char   {mustBeMember(args.log,{'none', 'all', 'forces'})} = 'none'
    @@ -571,9 +550,9 @@ These functions are defined below.
     
    -
    -

    Structure initialization

    -
    +
    +

    Structure initialization

    +
    conf_log = struct();
     
    @@ -581,9 +560,9 @@ These functions are defined below.
    -
    -

    Add Type

    -
    +
    +

    Add Type

    +
    switch args.log
       case 'none'
    @@ -608,9 +587,9 @@ These functions are defined below.
     
    -
    -

    Save the Structure

    -
    +
    +

    Save the Structure

    +
    save('./mat/conf_log.mat', 'conf_log');
     
    @@ -627,9 +606,9 @@ These functions are defined below.

    -
    -

    Simscape Model

    -
    +
    +

    Simscape Model

    +

    The model of the Ground is composed of:

    @@ -654,9 +633,9 @@ The model of the Ground is composed of:
    -
    -

    Function description

    -
    +
    +

    Function description

    +
    function [ground] = initializeGround(args)
     
    @@ -664,21 +643,22 @@ The model of the Ground is composed of:
    -
    -

    Optional Parameters

    -
    +
    +

    Optional Parameters

    +
    arguments
    -    args.type char {mustBeMember(args.type,{'none', 'rigid'})} = 'rigid'
    +  args.type char {mustBeMember(args.type,{'none', 'rigid'})} = 'rigid'
    +  args.rot_point (3,1) double {mustBeNumeric} = zeros(3,1) % Rotation point for the ground motion [m]
     end
     
    -
    -

    Structure initialization

    -
    +
    +

    Structure initialization

    +

    First, we initialize the granite structure.

    @@ -689,9 +669,9 @@ First, we initialize the granite structure.
    -
    -

    Add Type

    -
    +
    +

    Add Type

    +
    switch args.type
       case 'none'
    @@ -718,9 +698,19 @@ ground.density = 2800;        % [kg/m3]
     
    -
    -

    Save the Structure

    -
    +
    +

    Rotation Point

    +
    +
    +
    ground.rot_point = args.rot_point;
    +
    +
    +
    +
    + +
    +

    Save the Structure

    +

    The ground structure is saved.

    @@ -740,9 +730,9 @@ The ground structure is saved.

    -
    -

    Simscape Model

    -
    +
    +

    Simscape Model

    +

    The Simscape model of the granite is composed of:

    @@ -771,9 +761,9 @@ The output sample_pos corresponds to the impact point of the X-ray.
    -
    -

    Function description

    -
    +
    +

    Function description

    +
    function [granite] = initializeGranite(args)
     
    @@ -781,9 +771,9 @@ The output sample_pos corresponds to the impact point of the X-ray.
    -
    -

    Optional Parameters

    -
    +
    +

    Optional Parameters

    +
    arguments
       args.type          char    {mustBeMember(args.type,{'rigid', 'flexible', 'none', 'modal-analysis', 'init'})} = 'flexible'
    @@ -799,9 +789,9 @@ The output sample_pos corresponds to the impact point of the X-ray.
     
    -
    -

    Structure initialization

    -
    +
    +

    Structure initialization

    +

    First, we initialize the granite structure.

    @@ -833,9 +823,9 @@ First, we initialize the granite structure.
    -
    -

    Material and Geometry

    -
    +
    +

    Material and Geometry

    +

    Properties of the Material and link to the geometry of the granite.

    @@ -855,9 +845,9 @@ Z-offset for the initial position of the sample with respect to the granite top
    -
    -

    Stiffness and Damping properties

    -
    +
    +

    Stiffness and Damping properties

    +
    granite.K = [4e9; 3e8; 8e8]; % [N/m]
     granite.C = [4.0e5; 1.1e5; 9.0e5]; % [N/(m/s)]
    @@ -866,9 +856,9 @@ granite.C = [4.0e5; 1.1e5; 9.0e5]; % [N/(m/s)]
     
    -
    -

    Equilibrium position of the each joint.

    -
    +
    +

    Equilibrium position of the each joint.

    +
    if args.Foffset && ~strcmp(args.type, 'none') && ~strcmp(args.type, 'rigid') && ~strcmp(args.type, 'init')
       load('mat/Foffset.mat', 'Fgm');
    @@ -881,9 +871,9 @@ granite.C = [4.0e5; 1.1e5; 9.0e5]; % [N/(m/s)]
     
    -
    -

    Save the Structure

    -
    +
    +

    Save the Structure

    +

    The granite structure is saved.

    @@ -895,17 +885,17 @@ The granite structure is saved.
    -
    -

    5 Translation Stage

    +
    +

    5 Translation Stage

    -
    -

    Simscape Model

    -
    +
    +

    Simscape Model

    +

    The Simscape model of the Translation stage consist of:

    @@ -935,9 +925,9 @@ It is used to impose the motion in the Y direction
    -
    -

    Function description

    -
    +
    +

    Function description

    +
    function [ty] = initializeTy(args)
     
    @@ -945,9 +935,9 @@ It is used to impose the motion in the Y direction
    -
    -

    Optional Parameters

    -
    +
    +

    Optional Parameters

    +
    arguments
       args.type      char   {mustBeMember(args.type,{'none', 'rigid', 'flexible', 'modal-analysis', 'init'})} = 'flexible'
    @@ -958,9 +948,9 @@ It is used to impose the motion in the Y direction
     
    -
    -

    Structure initialization

    -
    +
    +

    Structure initialization

    +

    First, we initialize the ty structure.

    @@ -992,9 +982,9 @@ First, we initialize the ty structure.
    -
    -

    Material and Geometry

    -
    +
    +

    Material and Geometry

    +

    Define the density of the materials as well as the geometry (STEP files).

    @@ -1039,9 +1029,9 @@ ty.rotor.STEP = './STEPS/ty/Ty_Motor_Rotor.S
    -
    -

    Stiffness and Damping properties

    -
    +
    +

    Stiffness and Damping properties

    +
    ty.K = [2e8; 1e8; 2e8; 6e7; 9e7; 6e7]; % [N/m, N*m/rad]
     ty.C = [8e4; 5e4; 8e4; 2e4; 3e4; 2e4]; % [N/(m/s), N*m/(rad/s)]
    @@ -1050,9 +1040,9 @@ ty.C = [8e4; 5e4; 8e4; 2e4; 3e4; 2e4]; % [N/(m/s), N*m
     
    -
    -

    Equilibrium position of the each joint.

    -
    +
    +

    Equilibrium position of the each joint.

    +
    if args.Foffset && ~strcmp(args.type, 'none') && ~strcmp(args.type, 'rigid') && ~strcmp(args.type, 'init')
       load('mat/Foffset.mat', 'Ftym');
    @@ -1065,9 +1055,9 @@ ty.C = [8e4; 5e4; 8e4; 2e4; 3e4; 2e4]; % [N/(m/s), N*m
     
    -
    -

    Save the Structure

    -
    +
    +

    Save the Structure

    +

    The ty structure is saved.

    @@ -1079,17 +1069,17 @@ The ty structure is saved.
    -
    -

    6 Tilt Stage

    +
    +

    6 Tilt Stage

    -
    -

    Simscape Model

    -
    +
    +

    Simscape Model

    +

    The Simscape model of the Tilt stage is composed of:

    @@ -1119,9 +1109,9 @@ The Ry motion is imposed by the input.
    -
    -

    Function description

    -
    +
    +

    Function description

    +
    function [ry] = initializeRy(args)
     
    @@ -1129,9 +1119,9 @@ The Ry motion is imposed by the input.
    -
    -

    Optional Parameters

    -
    +
    +

    Optional Parameters

    +
    arguments
       args.type          char    {mustBeMember(args.type,{'none', 'rigid', 'flexible', 'modal-analysis', 'init'})} = 'flexible'
    @@ -1143,9 +1133,9 @@ The Ry motion is imposed by the input.
     
    -
    -

    Structure initialization

    -
    +
    +

    Structure initialization

    +

    First, we initialize the ry structure.

    @@ -1178,9 +1168,9 @@ First, we initialize the ry structure.
    -
    -

    Material and Geometry

    -
    +
    +

    Material and Geometry

    +

    Properties of the Material and link to the geometry of the Tilt stage.

    @@ -1218,9 +1208,9 @@ Z-Offset so that the center of rotation matches the sample center;
    -
    -

    Stiffness and Damping properties

    -
    +
    +

    Stiffness and Damping properties

    +
    ry.K = [3.8e8; 4e8; 3.8e8; 1.2e8; 6e4; 1.2e8];
     ry.C = [1e5;   1e5; 1e5;   3e4;   1e3; 3e4];
    @@ -1229,9 +1219,9 @@ ry.C = [1e5;   1e5; 1e5;   3e4;   1e3; 3e4];
     
    -
    -

    Equilibrium position of the each joint.

    -
    +
    +

    Equilibrium position of the each joint.

    +
    if args.Foffset && ~strcmp(args.type, 'none') && ~strcmp(args.type, 'rigid') && ~strcmp(args.type, 'init')
       load('mat/Foffset.mat', 'Fym');
    @@ -1244,9 +1234,9 @@ ry.C = [1e5;   1e5; 1e5;   3e4;   1e3; 3e4];
     
    -
    -

    Save the Structure

    -
    +
    +

    Save the Structure

    +

    The ry structure is saved.

    @@ -1258,17 +1248,17 @@ The ry structure is saved.
    -
    -

    7 Spindle

    +
    +

    7 Spindle

    -
    -

    Simscape Model

    -
    +
    +

    Simscape Model

    +

    The Simscape model of the Spindle is composed of:

    @@ -1294,9 +1284,9 @@ The Simscape model of the Spindle is composed of:
    -
    -

    Function description

    -
    +
    +

    Function description

    +
    function [rz] = initializeRz(args)
     
    @@ -1304,9 +1294,9 @@ The Simscape model of the Spindle is composed of:
    -
    -

    Optional Parameters

    -
    +
    +

    Optional Parameters

    +
    arguments
       args.type    char    {mustBeMember(args.type,{'none', 'rigid', 'flexible', 'modal-analysis', 'init'})} = 'flexible'
    @@ -1317,9 +1307,9 @@ The Simscape model of the Spindle is composed of:
     
    -
    -

    Structure initialization

    -
    +
    +

    Structure initialization

    +

    First, we initialize the rz structure.

    @@ -1351,9 +1341,9 @@ First, we initialize the rz structure.
    -
    -

    Material and Geometry

    -
    +
    +

    Material and Geometry

    +

    Properties of the Material and link to the geometry of the spindle.

    @@ -1374,9 +1364,9 @@ rz.stator.STEP = './STEPS/rz/Spindle_Stator.STEP'<
    -
    -

    Stiffness and Damping properties

    -
    +
    +

    Stiffness and Damping properties

    +
    rz.K = [7e8; 7e8; 2e9; 1e7; 1e7; 1e7];
     rz.C = [4e4; 4e4; 7e4; 1e4; 1e4; 1e4];
    @@ -1385,9 +1375,9 @@ rz.C = [4e4; 4e4; 7e4; 1e4; 1e4; 1e4];
     
    -
    -

    Equilibrium position of the each joint.

    -
    +
    +

    Equilibrium position of the each joint.

    +
    if args.Foffset && ~strcmp(args.type, 'none') && ~strcmp(args.type, 'rigid') && ~strcmp(args.type, 'init')
       load('mat/Foffset.mat', 'Fzm');
    @@ -1400,9 +1390,9 @@ rz.C = [4e4; 4e4; 7e4; 1e4; 1e4; 1e4];
     
    -
    -

    Save the Structure

    -
    +
    +

    Save the Structure

    +

    The rz structure is saved.

    @@ -1414,17 +1404,17 @@ The rz structure is saved.
    -
    -

    8 Micro Hexapod

    +
    +

    8 Micro Hexapod

    -
    -

    Simscape Model

    -
    +
    +

    Simscape Model

    +

    simscape_model_micro_hexapod.png @@ -1441,9 +1431,9 @@ The rz structure is saved.

    -
    -

    Function description

    -
    +
    +

    Function description

    +
    function [micro_hexapod] = initializeMicroHexapod(args)
     
    @@ -1451,9 +1441,9 @@ The rz structure is saved.
    -
    -

    Optional Parameters

    -
    +
    +

    Optional Parameters

    +
    arguments
         args.type      char   {mustBeMember(args.type,{'none', 'rigid', 'flexible', 'modal-analysis', 'init'})} = 'flexible'
    @@ -1495,9 +1485,9 @@ The rz structure is saved.
     
    -
    -

    Function content

    -
    +
    +

    Function content

    +
    micro_hexapod = initializeFramesPositions('H', args.H, 'MO_B', args.MO_B);
     micro_hexapod = generateGeneralConfiguration(micro_hexapod, 'FH', args.FH, 'FR', args.FR, 'FTh', args.FTh, 'MH', args.MH, 'MR', args.MR, 'MTh', args.MTh);
    @@ -1527,9 +1517,9 @@ Equilibrium position of the each joint.
     
    -
    -

    Add Type

    -
    +
    +

    Add Type

    +
    switch args.type
       case 'none'
    @@ -1548,9 +1538,9 @@ Equilibrium position of the each joint.
     
    -
    -

    Save the Structure

    -
    +
    +

    Save the Structure

    +

    The micro_hexapod structure is saved.

    @@ -1570,9 +1560,9 @@ The micro_hexapod structure is saved.

    -
    -

    Simscape Model

    -
    +
    +

    Simscape Model

    +

    The Simscape model of the Center of gravity compensator is composed of:

    @@ -1597,9 +1587,9 @@ The Simscape model of the Center of gravity compensator is composed of:
    -
    -

    Function description

    -
    +
    +

    Function description

    +
    function [axisc] = initializeAxisc(args)
     
    @@ -1607,9 +1597,9 @@ The Simscape model of the Center of gravity compensator is composed of:
    -
    -

    Optional Parameters

    -
    +
    +

    Optional Parameters

    +
    arguments
       args.type char {mustBeMember(args.type,{'none', 'rigid', 'flexible'})} = 'flexible'
    @@ -1619,9 +1609,9 @@ The Simscape model of the Center of gravity compensator is composed of:
     
    -
    -

    Structure initialization

    -
    +
    +

    Structure initialization

    +

    First, we initialize the axisc structure.

    @@ -1632,9 +1622,9 @@ First, we initialize the axisc structure.
    -
    -

    Add Type

    -
    +
    +

    Add Type

    +
    switch args.type
       case 'none'
    @@ -1649,9 +1639,9 @@ First, we initialize the axisc structure.
     
    -
    -

    Material and Geometry

    -
    +
    +

    Material and Geometry

    +

    Properties of the Material and link to the geometry files.

    @@ -1676,9 +1666,9 @@ axisc.gear.STEP = './STEPS/axisc/axisc_gear.STE
    -
    -

    Save the Structure

    -
    +
    +

    Save the Structure

    +

    The axisc structure is saved.

    @@ -1698,9 +1688,9 @@ The axisc structure is saved.

    -
    -

    Simscape Model

    -
    +
    +

    Simscape Model

    +

    The Simscape Model of the mirror is just a solid body. The output mirror_center corresponds to the center of the Sphere and is the point of measurement for the metrology @@ -1722,9 +1712,9 @@ The output mirror_center corresponds to the center of the Sphere an

    -
    -

    Function description

    -
    +
    +

    Function description

    +
    function [] = initializeMirror(args)
     
    @@ -1732,9 +1722,9 @@ The output mirror_center corresponds to the center of the Sphere an
    -
    -

    Optional Parameters

    -
    +
    +

    Optional Parameters

    +
    arguments
       args.type        char   {mustBeMember(args.type,{'none', 'rigid'})} = 'rigid'
    @@ -1746,9 +1736,9 @@ The output mirror_center corresponds to the center of the Sphere an
     
    -
    -

    Structure initialization

    -
    +
    +

    Structure initialization

    +

    First, we initialize the mirror structure.

    @@ -1774,9 +1764,9 @@ First, we initialize the mirror structure.
    -
    -

    Material and Geometry

    -
    +
    +

    Material and Geometry

    +

    We define the geometrical values.

    @@ -1853,9 +1843,9 @@ Finally, we close the shape.
    -
    -

    Save the Structure

    -
    +
    +

    Save the Structure

    +

    The mirror structure is saved.

    @@ -1867,17 +1857,17 @@ The mirror structure is saved.
    -
    -

    11 Nano Hexapod

    +
    +

    11 Nano Hexapod

    -
    -

    Simscape Model

    -
    +
    +

    Simscape Model

    +

    simscape_model_nano_hexapod.png @@ -1894,9 +1884,9 @@ The mirror structure is saved.

    -
    -

    Function description

    -
    +
    +

    Function description

    +
    function [nano_hexapod] = initializeNanoHexapod(args)
     
    @@ -1904,9 +1894,9 @@ The mirror structure is saved.
    -
    -

    Optional Parameters

    -
    +
    +

    Optional Parameters

    +
    arguments
         args.type      char   {mustBeMember(args.type,{'none', 'rigid', 'flexible'})} = 'flexible'
    @@ -1947,9 +1937,9 @@ The mirror structure is saved.
     
    -
    -

    Function content

    -
    +
    +

    Function content

    +
    nano_hexapod = initializeFramesPositions('H', args.H, 'MO_B', args.MO_B);
     nano_hexapod = generateGeneralConfiguration(nano_hexapod, 'FH', args.FH, 'FR', args.FR, 'FTh', args.FTh, 'MH', args.MH, 'MR', args.MR, 'MTh', args.MTh);
    @@ -1977,9 +1967,9 @@ nano_hexapod.dLi = dLi;
     
    -
    -

    Add Type

    -
    +
    +

    Add Type

    +
    switch args.type
       case 'none'
    @@ -1994,9 +1984,9 @@ nano_hexapod.dLi = dLi;
     
    -
    -

    Save the Structure

    -
    +
    +

    Save the Structure

    +
    save('./mat/stages.mat', 'nano_hexapod', '-append');
     
    @@ -2013,9 +2003,9 @@ nano_hexapod.dLi = dLi;

    -
    -

    Simscape Model

    -
    +
    +

    Simscape Model

    +

    The Simscape model of the sample environment is composed of:

    @@ -2043,9 +2033,9 @@ This could be the case for cable forces for instance.
    -
    -

    Function description

    -
    +
    +

    Function description

    +
    function [sample] = initializeSample(args)
     
    @@ -2053,9 +2043,9 @@ This could be the case for cable forces for instance.
    -
    -

    Optional Parameters

    -
    +
    +

    Optional Parameters

    +
    arguments
       args.type         char    {mustBeMember(args.type,{'rigid', 'flexible', 'none', 'init'})} = 'flexible'
    @@ -2071,9 +2061,9 @@ This could be the case for cable forces for instance.
     
    -
    -

    Structure initialization

    -
    +
    +

    Structure initialization

    +

    First, we initialize the sample structure.

    @@ -2103,9 +2093,9 @@ First, we initialize the sample structure.
    -
    -

    Material and Geometry

    -
    +
    +

    Material and Geometry

    +

    We define the geometrical parameters of the sample as well as its mass and position.

    @@ -2119,9 +2109,9 @@ sample.offset = args.offset; % [m]
    -
    -

    Stiffness and Damping properties

    -
    +
    +

    Stiffness and Damping properties

    +
    sample.K = ones(3,1) * sample.mass * (2*pi * args.freq)^2; % [N/m]
     sample.C = 0.1 * sqrt(sample.K*sample.mass); % [N/(m/s)]
    @@ -2130,9 +2120,9 @@ sample.C = 0.1 * sqrt(sample.K
    -

    Equilibrium position of the each joint.

    -
    +
    +

    Equilibrium position of the each joint.

    +
    if args.Foffset && ~strcmp(args.type, 'none') && ~strcmp(args.type, 'rigid') && ~strcmp(args.type, 'init')
       load('mat/Foffset.mat', 'Fsm');
    @@ -2145,9 +2135,9 @@ sample.C = 0.1 * sqrt(sample.K
    -

    Save the Structure

    -
    +
    +

    Save the Structure

    +

    The sample structure is saved.

    @@ -2167,9 +2157,9 @@ The sample structure is saved.

    -
    -

    Function Declaration and Documentation

    -
    +
    +

    Function Declaration and Documentation

    +
    function [] = initializeController(args)
     
    @@ -2177,22 +2167,22 @@ The sample structure is saved.
    -
    -

    Optional Parameters

    -
    +
    +

    Optional Parameters

    +
    arguments
    -  args.type         char   {mustBeMember(args.type,{'open-loop', 'iff', 'dvf'})} = 'open-loop'
    -  args.K (6,6)                                                                   = ss(zeros(6, 6))
    +  args.type char {mustBeMember(args.type,{'open-loop', 'iff', 'dvf', 'hac-dvf'})} = 'open-loop'
    +  args.K (6,6) = ss(zeros(6, 6))
     end
     
    -
    -

    Structure initialization

    -
    +
    +

    Structure initialization

    +

    First, we initialize the controller structure.

    @@ -2214,6 +2204,8 @@ First, we initialize the controller structure. controller.type = 2; case 'iff' controller.type = 3; + case 'hac-dvf' + controller.type = 4; end
    @@ -2230,9 +2222,9 @@ First, we initialize the controller structure.
    -
    -

    Save the Structure

    -
    +
    +

    Save the Structure

    +

    The controller structure is saved.

    @@ -2252,9 +2244,9 @@ The controller structure is saved.

    -
    -

    Function Declaration and Documentation

    -
    +
    +

    Function Declaration and Documentation

    +
    function [ref] = initializeReferences(args)
     
    @@ -2262,9 +2254,9 @@ The controller structure is saved.
    -
    -

    Optional Parameters

    -
    +
    +

    Optional Parameters

    +
    arguments
         % Sampling Frequency [s]
    @@ -2326,9 +2318,9 @@ H_lpf = 1/(1 + 2
     
    -
    -

    Translation Stage

    -
    +
    +

    Translation Stage

    +
    %% Translation stage - Dy
     t = 0:Ts:Tmax; % Time Vector [s]
    @@ -2365,9 +2357,9 @@ Dy = struct('time', t, 
     
    -
    -

    Tilt Stage

    -
    +
    +

    Tilt Stage

    +
    %% Tilt Stage - Ry
     t = 0:Ts:Tmax; % Time Vector [s]
    @@ -2405,9 +2397,9 @@ Ry = struct('time', t, 
     
    -
    -

    Spindle

    -
    +
    +

    Spindle

    +
    %% Spindle - Rz
     t = 0:Ts:Tmax; % Time Vector [s]
    @@ -2440,9 +2432,9 @@ Rz = struct('time', t, 
     
    -
    -

    Micro Hexapod

    -
    +
    +

    Micro Hexapod

    +
    %% Micro-Hexapod
     t = [0, Ts];
    @@ -2498,9 +2490,9 @@ Rm = struct('time', t, 
     
    -
    -

    Nano Hexapod

    -
    +
    +

    Nano Hexapod

    +
    %% Nano-Hexapod
     t = [0, Ts];
    @@ -2541,12 +2533,12 @@ Dnl = struct('time', t, 
     
    -
    -

    Save

    -
    +
    +

    Save

    +
        %% Save
    -    save('mat/nass_references.mat', 'Dy', 'Ry', 'Rz', 'Dh', 'Dhl', 'Rm', 'Dn', 'Dnl', 'Ts');
    +    save('./mat/nass_references.mat', 'Dy', 'Ry', 'Rz', 'Dh', 'Dhl', 'Rm', 'Dn', 'Dnl', 'Ts');
     end
     
    @@ -2562,9 +2554,9 @@ Dnl = struct('time', t,
    -
    -

    Function Declaration and Documentation

    -
    +
    +

    Function Declaration and Documentation

    +
    function [] = initializeDisturbances(args)
     % initializeDisturbances - Initialize the disturbances
    @@ -2579,9 +2571,9 @@ Dnl = struct('time', t, 
     
    -
    -

    Optional Parameters

    -
    +
    +

    Optional Parameters

    +
    arguments
         % Global parameter to enable or disable the disturbances
    @@ -2609,7 +2601,7 @@ Dnl = struct('time', t, Load Data
     
    -
    load('./disturbances/mat/dist_psd.mat', 'dist_f');
    +
    load('./mat/dist_psd.mat', 'dist_f');
     
    @@ -2788,11 +2780,11 @@ Frz_z = Frz_z - Frz_z(1);
    -
    -

    Save

    -
    +
    +

    Save

    +
    -
    save('mat/nass_disturbances.mat', 'Dwx', 'Dwy', 'Dwz', 'Fty_x', 'Fty_z', 'Frz_z', 'Fd', 'Ts', 't');
    +
    save('./mat/nass_disturbances.mat', 'Dwx', 'Dwy', 'Dwz', 'Fty_x', 'Fty_z', 'Frz_z', 'Fd', 'Ts', 't');
     
    @@ -2807,9 +2799,9 @@ Frz_z = Frz_z - Frz_z(1);

    -
    -

    Function Declaration and Documentation

    -
    +
    +

    Function Declaration and Documentation

    +
    function [] = initializePosError(args)
     % initializePosError - Initialize the position errors
    @@ -2824,9 +2816,9 @@ Frz_z  = Frz_z - Frz_z(1);
     
    -
    -

    Optional Parameters

    -
    +
    +

    Optional Parameters

    +
    arguments
         args.error    logical {mustBeNumericOrLogical} = false
    @@ -2839,9 +2831,9 @@ Frz_z  = Frz_z - Frz_z(1);
     
    -
    -

    Structure initialization

    -
    +
    +

    Structure initialization

    +

    First, we initialize the pos_error structure.

    @@ -2878,11 +2870,11 @@ pos_error.Rz = args.Rz;
    -
    -

    Save

    -
    +
    +

    Save

    +
    -
    save('mat/pos_error.mat', 'pos_error');
    +
    save('./mat/pos_error.mat', 'pos_error');
     
    @@ -2956,7 +2948,7 @@ pos_error.Rz = args.Rz;

    Author: Dehaeze Thomas

    -

    Created: 2020-02-25 mar. 18:20

    +

    Created: 2020-03-13 ven. 17:39

    diff --git a/docs/simulink_project.html b/docs/simulink_project.html index c73b0f0..88ed97b 100644 --- a/docs/simulink_project.html +++ b/docs/simulink_project.html @@ -4,7 +4,7 @@ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> - + Simulink Project for the NASS @@ -202,50 +202,28 @@ @@ -322,7 +300,7 @@ The project also permits to automatically add defined folder to the path when th

    Author: Dehaeze Thomas

    -

    Created: 2020-02-25 mar. 18:21

    +

    Created: 2020-03-06 ven. 15:10

    diff --git a/docs/uniaxial.html b/docs/uniaxial.html index d23de45..6559920 100644 --- a/docs/uniaxial.html +++ b/docs/uniaxial.html @@ -4,7 +4,7 @@ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> - + Simscape Uniaxial Model @@ -202,50 +202,28 @@ +#+HTML_HEAD: +#+HTML_HEAD: +#+HTML_HEAD: + +#+HTML_MATHJAX: align: center tagside: right font: TeX + +#+PROPERTY: header-args:matlab :session *MATLAB* +#+PROPERTY: header-args:matlab+ :comments org +#+PROPERTY: header-args:matlab+ :results none +#+PROPERTY: header-args:matlab+ :exports both +#+PROPERTY: header-args:matlab+ :eval no-export +#+PROPERTY: header-args:matlab+ :output-dir figs +#+PROPERTY: header-args:matlab+ :tangle no +#+PROPERTY: header-args:matlab+ :mkdirp yes + +#+PROPERTY: header-args:shell :eval no-export + +#+PROPERTY: header-args:latex :headers '("\\usepackage{tikz}" "\\usepackage{import}" "\\import{$HOME/Cloud/thesis/latex/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+ :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: + +* Introduction :ignore: +The goal here is to write clear specifications for the NASS. + +This can then be used for the control synthesis and for the design of the nano-hexapod. + +Ideal, specifications on the norm of closed loop transfer function should be written. + +* Simplify Model for the Nano-Hexapod +** Model of the nano-hexapod +Let's consider the simple mechanical system in Figure [[fig:nass_simple_model]]. + +#+begin_src latex :file nass_simple_model.pdf + \begin{tikzpicture} + % Parameters + \def\massw{3} + \def\massh{1} + \def\spaceh{2} + + % Ground + \draw[] (-0.5*\massw, 0) -- (0.5*\massw, 0); + % Mass + \draw[fill=white] (-0.5*\massw, \spaceh) rectangle (0.5*\massw, \spaceh+\massh) node[pos=0.5](m){$m$}; + + % Spring, Damper, and Actuator + \draw[spring] (-0.3*\massw, 0) -- (-0.3*\massw, \spaceh) node[midway, left=0.1]{$k$}; + \draw[actuator] ( 0.3*\massw, 0) -- ( 0.3*\massw, \spaceh) node[midway, right=0.1](F){$F$}; + + % Force Sensor + \node[forcesensor={\massw}{0.2}] (fsens) at (0, \spaceh){}; + \node[right] at (fsens.east) {$F_m$}; + + % Displacements + \draw[dashed] (0.5*\massw, 0) -- ++(0.2*\massw, 0); + \draw[->] (0.6*\massw, 0) -- ++(0, 0.2*\spaceh) node[below right]{$x_\mu$}; + + % Displacements + \draw[dashed] (0.5*\massw, \spaceh+\massh) -- ++(0.2*\massw, 0); + \draw[->] (0.6*\massw, \spaceh+\massh) -- ++(0, 0.2*\spaceh) node[below right]{$x$}; + + \draw[<->] (-0.5*\massw+-1.5*\dispw, 0) -- node[midway, left]{$d$} ++(0, \spaceh); + + % Direct forces + \draw[->] (0, \spaceh+\massh) node[branch]{} -- ++(0, 0.4*\spaceh) node[below right]{$F_d$}; + \end{tikzpicture} +#+end_src + +#+name: fig:nass_simple_model +#+caption: Simplified mechanical system for the nano-hexapod +#+RESULTS: +[[file:figs/nass_simple_model.png]] + +The signals are described in table [[tab:general_plant_signals]]. + +#+name: tab:general_plant_signals +#+caption: Signals definition for the generalized plant +| | *Symbol* | *Meaning* | +|---------------------+----------+----------------------------------------| +| *Exogenous Inputs* | $x_\mu$ | Motion of the $\nu$-hexapod's base | +| | $F_d$ | External Forces applied to the Payload | +| | $r$ | Reference signal for tracking | +|---------------------+----------+----------------------------------------| +| *Exogenous Outputs* | $x$ | Absolute Motion of the Payload | +|---------------------+----------+----------------------------------------| +| *Sensed Outputs* | $F_m$ | Force Sensors in each leg | +| | $d$ | Measured displacement of each leg | +| | $x$ | Absolute Motion of the Payload | +|---------------------+----------+----------------------------------------| +| *Control Signals* | $F$ | Actuator Inputs | + +For the nano-hexapod alone, we have the following equations: +\[ \begin{align*} + x &= \frac{1}{ms^2 + k} F + \frac{1}{ms^2 + k} F_d + \frac{k}{ms^2 + k} x_\mu \\ + F_m &= \frac{ms^2}{ms^2 + k} F - \frac{k}{ms^2 + k} F_d + \frac{k m s^2}{ms^2 + k} x_\mu \\ + d &= \frac{1}{ms^2 + k} F + \frac{1}{ms^2 + k} F_d - \frac{ms^2}{ms^2 + k} x_\mu +\end{align*} \] + +We can write the equations function of $\omega_\nu = \sqrt{\frac{k}{m}}$: +\[ \begin{align*} + x &= \frac{1/k}{1 + \frac{s^2}{\omega_\nu^2}} F + \frac{1/k}{1 + \frac{s^2}{\omega_\nu^2}} F_d + \frac{1}{1 + \frac{s^2}{\omega_\nu^2}} x_\mu \\ + F_m &= \frac{\frac{s^2}{\omega_\nu^2}}{1 + \frac{s^2}{\omega_\nu^2}} F - \frac{1}{1 + \frac{s^2}{\omega_\nu^2}} F_d + \frac{k \frac{s^2}{\omega_\nu^2}}{1 + \frac{s^2}{\omega_\nu^2}} x_\mu \\ + d &= \frac{1/k}{1 + \frac{s^2}{\omega_\nu^2}} F + \frac{1/k}{1 + \frac{s^2}{\omega_\nu^2}} F_d - \frac{\frac{s^2}{\omega_\nu^2}}{1 + \frac{s^2}{\omega_\nu^2}} x_\mu +\end{align*} \] + + +*Assumptions*: +- the forces applied by the nano-hexapod have no influence on the micro-station, specifically on the displacement of the top platform of the micro-hexapod. + +This means that the nano-hexapod can be considered separately from the micro-station and that the motion $x_\mu$ is imposed and considered as an external input. + +The nano-hexapod can thus be represented as in Figure [[fig:nano_station_inputs_outputs]]. + +#+begin_src latex :file nano_station_inputs_outputs.pdf + \begin{tikzpicture} + \node[block={2.0cm}{2.0cm}] (P) {}; + \node[above] at (P.north) {$\nu$-hexapod}; + + % Input and outputs coordinates + \coordinate[] (inputFd) at ($(P.south west)!0.8!(P.north west)$); + \coordinate[] (inputw) at ($(P.south west)!0.5!(P.north west)$); + \coordinate[] (inputF) at ($(P.south west)!0.2!(P.north west)$); + \coordinate[] (outputF) at ($(P.south east)!0.8!(P.north east)$); + \coordinate[] (outputd) at ($(P.south east)!0.5!(P.north east)$); + \coordinate[] (outputx) at ($(P.south east)!0.2!(P.north east)$); + + % Connections and labels + \draw[<-] (inputFd) -- ++(-0.8, 0) node[above right]{$F_d$}; + \draw[<-] (inputw) -- ++(-0.8, 0) node[above right]{$x_\mu$}; + \draw[<-] (inputF) -- ++(-0.8, 0) node[above right]{$F$}; + + \draw[->] (outputF) -- ++(0.8, 0) node[above left]{$F_m$}; + \draw[->] (outputd) -- ++(0.8, 0) node[above left]{$d$}; + \draw[->] (outputx) -- ++(0.8, 0) node[above left]{$x$}; + \end{tikzpicture} +#+end_src + +#+name: fig:nano_station_inputs_outputs +#+caption: Block representation of the nano-hexapod + +** How to include Ground Motion in the model? +What we measure is not the absolute motion $x$, but the relative motion $x - w$ where $w$ is the motion of the granite. + +Also, $w$ induces some motion $x_\mu$ through the transmissibility of the micro-station. + +#+begin_src latex :file nano_station_inputs_outputs_ground_motion.pdf + \begin{tikzpicture} + \node[block={3.0cm}{3.0cm}] (P) {}; + \node[above] at (P.north) {$\nu$-hexapod}; + + % Input and outputs coordinates + \coordinate[] (inputFd) at ($(P.south west)!0.95!(P.north west)$); + \coordinate[] (inputw) at ($(P.south west)!0.65!(P.north west)$); + \coordinate[] (inputxm) at ($(P.south west)!0.35!(P.north west)$); + \coordinate[] (inputF) at ($(P.south west)!0.05!(P.north west)$); + \coordinate[] (outputF) at ($(P.south east)!0.8!(P.north east)$); + \coordinate[] (outputd) at ($(P.south east)!0.5!(P.north east)$); + \coordinate[] (outputx) at ($(P.south east)!0.2!(P.north east)$); + + % Connections and labels + \draw[<-] (inputFd) -- ++(-1.4, 0) node[above right]{$F_d$}; + \draw[<-] (inputw) -- ++(-1.4, 0) node[above right]{$w$}; + \draw[<-] (inputxm) -- ++(-1.4, 0) node[above right]{$x_\mu$}; + \draw[<-] (inputF) -- ++(-1.4, 0) node[above right]{$F$}; + + \draw[->] (outputF) -- ++(1.4, 0) node[above left]{$F_m$}; + \draw[->] (outputd) -- ++(1.4, 0) node[above left]{$d$}; + \draw[->] (outputx) -- ++(1.4, 0) node[above]{$y = x-w$}; + \end{tikzpicture} +#+end_src + +** Motion of the micro-station +As explained, we consider $x_\mu$ as an external input ($F$ has no influence on $x_\mu$). + +$x_\mu$ is the motion of the micro-station's top platform due to the motion of each stage of the micro-station. + +We consider that $x_\mu$ has the following form: +\[ x_\mu = T_\mu r + d_\mu \] +where: +- $T_\mu r$ corresponds to the response of the stages due to the reference $r$ +- $d_\mu$ is the motion of the hexapod due to all the vibrations of the stages + + +$T_\mu$ can be considered to be a low pass filter with a bandwidth corresponding approximatively to the bandwidth of the micro-station's stages. +To simplify, we can consider $T_\mu$ to be a first order low pass filter: +\[ T_\mu = \frac{1}{1 + s/\omega_\mu} \] +where $\omega_\mu$ corresponds to the tracking speed of the micro-station. + + +What is important to note is that while $x_\mu$ is viewed as a perturbation from the nano-hexapod point of view, $x_\mu$ *does* depend on the reference signal $r$. + +Also, here, we suppose that the granite is not moving. + +If we now include the motion of the granite $w$, we obtain the block diagram shown in Figure [[fig:nano_station_ground_motion]]. + +#+begin_src latex :file nano_station_ground_motion.pdf + \begin{tikzpicture} + \node[block={4.0cm}{4.0cm}] (P) {}; + \node[above] at (P.north) {$\nu$-hexapod}; + + % Input and outputs coordinates + \coordinate[] (inputFd) at ($(P.south west)!0.8!(P.north west)$); + \coordinate[] (inputw) at ($(P.south west)!0.5!(P.north west)$); + \coordinate[] (inputF) at ($(P.south west)!0.2!(P.north west)$); + \coordinate[] (outputF) at ($(P.south east)!0.8!(P.north east)$); + \coordinate[] (outputd) at ($(P.south east)!0.5!(P.north east)$); + \coordinate[] (outputx) at ($(P.south east)!0.2!(P.north east)$); + + % Connections and labels + \draw[<-] (inputFd) -- ++(-0.8, 0) node[above right]{$F_d$}; + \draw[<-] (inputF) -- ++(-0.8, 0) node[above right]{$F$}; + + \draw[->] (outputF) -- ++(0.8, 0) node[above left]{$F_m$}; + \draw[->] (outputd) -- ++(0.8, 0) node[above left]{$d$}; + + \node[addb, left= of inputw] (add) {}; + \node[block, left= of add] (Tmu) {$T_\mu$}; + \node[addb, above= of add] (addw) {}; + \node[block, left= of addw] (Tw) {$T_w$}; + + \node[addb={+}{}{-}{}{}, right= of outputx] (addx) {}; + \draw[->] (outputx) -- (addx.west) node[above left]{$x$}; + \draw[->] (addx.east) -- ++(0.8, 0) node[above left]{$y$}; + + \draw[<-] (Tmu.west) -- ++(-0.8, 0)node[above right]{$r$}; + + \draw[->] (Tmu.east) -- (add.west); + \draw[->] (add.east) -- (inputw) node[above left]{$x_\mu$}; + \draw[->] ($(addw.north) + (0, 0.8)$) node[below right]{$d_\mu$} -- (addw.north); + \draw[->] (addw.south) -- (add.north); + + \draw[->] ($(Tw.west) + (-1, 0)$) node[above right]{$w$} -- (Tw.west); + \draw[->] ($(Tw.west) + (-0.4, 0)$) node[branch]{} -- ++(0, 1.4) -| (addx.north); + \draw[->] (Tw.east) -- (addw.west); + \end{tikzpicture} +#+end_src + +#+name: fig:nano_station_ground_motion +#+caption: Ground Motion $w$ included +#+RESULTS: +[[file:figs/nano_station_ground_motion.png]] + +$T_w$ is the mechanical transmissibility of the micro-station. +We can approximate this transfer function by a second order low pass filter: +\[ T_w = \frac{1}{1 + 2 \xi s/\omega_0 + s^2/\omega_0^2} \] + +** Notes on the signals :noexport: +Let's consider the reference tracking problem: + +The reference $r$ is a sinusoidal signal at 1Hz with an amplitude up to 10mm. +We want to position error $\epsilon = x - r$ to be less than 10nm. + +Thus, if we don't take into account the fact that the perturbation $x_\mu$ does depend on the reference $r$, we would conclude that we need the sensitivity function of the nano-hexapod $S$: +\[ |S| < - 60dB\quad\text{at 1 Hz} \] +And thus we would need a bandwidth of approximatively 1kHz which is not realistic. + +* Control with the Stiff Nano-Hexapod +** Matlab Init :noexport:ignore: +#+begin_src matlab :tangle no :exports none :results silent :noweb yes :var current_dir=(file-name-directory buffer-file-name) + <> +#+end_src + +#+begin_src matlab :exports none :results silent :noweb yes + <> +#+end_src + +#+begin_src matlab + freqs = logspace(-1, 3, 1000); +#+end_src + +** Definition of the values +Let's define the mass and stiffness of the nano-hexapod. +#+begin_src matlab + m = 50; % [kg] + k = 1e7; % [N/m] +#+end_src + +Let's define the Plant as shown in Figure [[fig:nano_station_inputs_outputs]]: +#+begin_src matlab + Gn = 1/(m*s^2 + k)*[-k, k*m*s^2, m*s^2; 1, -m*s^2, 1; 1, k, 1]; + Gn.InputName = {'Fd', 'xmu', 'F'}; + Gn.OutputName = {'Fm', 'd', 'x'}; +#+end_src + +Now, define the transmissibility transfer function $T_\mu$ corresponding to the micro-station motion. +#+begin_src matlab + wmu = 2*pi*50; % [rad/s] + + Tmu = 1/(1 + s/wmu); + Tmu.InputName = {'r1'}; + Tmu.OutputName = {'ymu'}; +#+end_src + +#+begin_src matlab + w0 = 2*pi*40; + xi = 0.5; + Tw = 1/(1 + 2*xi*s/w0 + s^2/w0^2); + Tw.InputName = {'w1'}; + Tw.OutputName = {'dw'}; +#+end_src + +We add the fact that $x_\mu = d_\mu + T_\mu r + T_w w$: +#+begin_src matlab + Wsplit = [tf(1); tf(1)]; + Wsplit.InputName = {'w'}; + Wsplit.OutputName = {'w1', 'w2'}; + + S = sumblk('xmu = ymu + dmu + dw'); + + Sw = sumblk('y = x - w2'); + + Gpz = connect(Gn, S, Wsplit, Tw, Tmu, Sw, {'Fd', 'dmu', 'r1', 'F', 'w'}, {'Fm', 'd', 'y'}); +#+end_src + +** Control using $d$ +*** Control Architecture +Let's consider a feedback loop using $d$ as shown in Figure [[fig:nano_station_control_d]]. + +#+begin_src latex :file nano_station_control_d.pdf + \begin{tikzpicture} + \node[block={4.0cm}{4.0cm}] (P) {}; + \node[above] at (P.north) {$\nu$-hexapod}; + + % Input and outputs coordinates + \coordinate[] (inputFd) at ($(P.south west)!0.8!(P.north west)$); + \coordinate[] (inputw) at ($(P.south west)!0.5!(P.north west)$); + \coordinate[] (inputF) at ($(P.south west)!0.2!(P.north west)$); + \coordinate[] (outputF) at ($(P.south east)!0.8!(P.north east)$); + \coordinate[] (outputd) at ($(P.south east)!0.5!(P.north east)$); + \coordinate[] (outputx) at ($(P.south east)!0.2!(P.north east)$); + + % Connections and labels + \draw[<-] (inputFd) -- ++(-0.8, 0) node[above right]{$F_d$}; + \draw[<-] (inputw) -- ++(-0.8, 0) node[above right]{$x_\mu$}; + + \draw[->] (outputF) -- ++(0.8, 0) node[above left]{$F_m$}; + \draw[->] (outputd) -- ++(1.6, 0) node[above left]{$d$}; + \draw[->] (outputx) -- ++(0.8, 0) node[above left]{$x$}; + + \node[block, below=0.3 of P] (K) {$K_d$}; + + \node[addb={+}{}{}{}{-}, left= of inputF] (addF) {}; + + \draw[->] ($(outputd) + (1.1, 0)$) node[branch]{} |- (K.east); + \draw[->] (K.west) -| (addF.south); + \draw[->] (addF.east) -- (inputF) node[above left]{$F$}; + \draw[<-] (addF.west) -- ++(-0.8, 0)node[above right]{$F^\prime$}; + \end{tikzpicture} +#+end_src + +#+name: fig:nano_station_control_d +#+caption: Feedback diagram using $d$ +#+RESULTS: +[[file:figs/nano_station_control_d.png]] + +*** Analytical Analysis +Let's apply a direct velocity feedback by deriving $d$: +\[ F = F^\prime - g s d \] + +Thus: +\[ d = \frac{1}{ms^2 + gs + k} F^\prime + \frac{1}{ms^2 + gs + k} F_d - \frac{ms^2}{ms^2 + gs + k} x_\mu \] + +\[ F = \frac{ms^2 + k}{ms^2 + gs + k} F^\prime - \frac{gs}{ms^2 + gs + k} F_d + \frac{mgs^3}{ms^2 + gs + k} x_\mu \] + +and +\[ x = \frac{1}{ms^2 + k} (\frac{ms^2 + k}{ms^2 + gs + k} F^\prime - \frac{gs}{ms^2 + gs + k} F_d + \frac{mgs^3}{ms^2 + gs + k} x_\mu) + \frac{1}{ms^2 + k} F_d + \frac{k}{ms^2 + k} x_\mu \] + + +\[ x = \frac{ms^2 + k}{(ms^2 + k) (ms^2 + gs + k)} F^\prime + \frac{ms^2 + k}{(ms^2 + k) (ms^2 + gs + k)} F_d + \frac{mgs^3 + k(ms^2 + gs + k)}{(ms^2 + k) (ms^2 + gs + k)} x_\mu \] + +And we finally obtain: +\[ x = \frac{1}{ms^2 + gs + k} F^\prime + \frac{1}{ms^2 + gs + k} F_d + \frac{gs + k}{ms^2 + gs + k} x_\mu \] + +#+begin_src matlab + K_dvf = 2*sqrt(k*m)*s; + K_dvf.InputName = {'d'}; + K_dvf.OutputName = {'F'}; + + Gpz_dvf = feedback(Gpz, K_dvf, 'name'); +#+end_src + +Now let's consider that $x_\mu = d_\mu + T_\mu r$ + +\[ x = \frac{1}{ms^2 + gs + k} F^\prime + \frac{1}{ms^2 + gs + k} F_d + \frac{gs + k}{ms^2 + gs + k} d_\mu + T_\mu \frac{gs + k}{ms^2 + gs + k} r \] + +And $\epsilon = r - x$: +\[ \epsilon = \frac{1}{ms^2 + gs + k} F^\prime + \frac{1}{ms^2 + gs + k} F_d + \frac{gs + k}{ms^2 + gs + k} d_\mu + \frac{ms^2 + gs + k - T_\mu (gs + k)}{ms^2 + gs + k} r \] + +#+begin_important +\[ \epsilon = \frac{1}{ms^2 + gs + k} F^\prime + \frac{1}{ms^2 + gs + k} F_d + \frac{gs + k}{ms^2 + gs + k} d_\mu + \frac{ms^2 - S_\mu(gs + k)}{ms^2 + gs + k} r \] +#+end_important + +** Control using $F_m$ +*** Control Architecture +Let's consider a feedback loop using $Fm$ as shown in Figure [[fig:nano_station_control_Fm]]. + +#+begin_src latex :file nano_station_control_Fm.pdf + \begin{tikzpicture} + \node[block={4.0cm}{4.0cm}] (P) {}; + \node[above] at (P.north) {$\nu$-hexapod}; + + % Input and outputs coordinates + \coordinate[] (inputFd) at ($(P.south west)!0.8!(P.north west)$); + \coordinate[] (inputw) at ($(P.south west)!0.5!(P.north west)$); + \coordinate[] (inputF) at ($(P.south west)!0.2!(P.north west)$); + \coordinate[] (outputF) at ($(P.south east)!0.8!(P.north east)$); + \coordinate[] (outputd) at ($(P.south east)!0.5!(P.north east)$); + \coordinate[] (outputx) at ($(P.south east)!0.2!(P.north east)$); + + % Connections and labels + \draw[<-] (inputFd) -- ++(-0.8, 0) node[above right]{$F_d$}; + \draw[<-] (inputw) -- ++(-0.8, 0) node[above right]{$x_\mu$}; + + \draw[->] (outputF) -- ++(1.6, 0) node[above left]{$F_m$}; + \draw[->] (outputd) -- ++(0.8, 0) node[above left]{$d$}; + \draw[->] (outputx) -- ++(0.8, 0) node[above left]{$x$}; + + \node[block, below=0.3 of P] (K) {$K_{F_m}$}; + + \node[addb={+}{}{}{}{-}, left= of inputF] (addF) {}; + + \draw[->] ($(outputF) + (1.1, 0)$) node[branch]{} |- (K.east); + \draw[->] (K.west) -| (addF.south); + \draw[->] (addF.east) -- (inputF) node[above left]{$F$}; + \draw[<-] (addF.west) -- ++(-0.8, 0)node[above right]{$F^\prime$}; + \end{tikzpicture} +#+end_src + +#+name: fig:nano_station_control_Fm +#+caption: Feedback diagram using $F_m$ +#+RESULTS: +[[file:figs/nano_station_control_Fm.png]] + +*** Pure Integrator +Let's apply integral force feedback by integration $F_m$: +\[ F = F^\prime - \frac{g}{s} F_m \] + +And we finally obtain: +\[ x = \frac{1}{ms^2 + mgs + k} F^\prime + \frac{1 + \frac{g}{s}}{ms^2 + mgs + k} F_d + \frac{k}{ms^2 + mgs + k} x_\mu \] + +#+begin_src matlab + K_iff = 2*sqrt(k/m)/s; + K_iff.InputName = {'Fm'}; + K_iff.OutputName = {'F'}; + + Gpz_iff = feedback(Gpz, K_iff, 'name'); +#+end_src + +Now let's consider that $x_\mu = d_\mu + T_\mu r$ + +\[ x = \frac{1}{ms^2 + mgs + k} F^\prime + \frac{1 + \frac{g}{s}}{ms^2 + mgs + k} F_d + \frac{k}{ms^2 + mgs + k} d_\mu + \frac{T_\mu k}{ms^2 + mgs + k} r \] + +And $\epsilon = r - x$: +\[ \epsilon = \frac{1}{ms^2 + mgs + k} F^\prime + \frac{1 + \frac{g}{s}}{ms^2 + mgs + k} F_d + \frac{k}{ms^2 + mgs + k} d_\mu + \frac{ms^2 + mgs + k - T_\mu k}{ms^2 + mgs + k} r \] + +#+begin_important +\[ \epsilon = \frac{1}{ms^2 + mgs + k} F^\prime + \frac{1 + \frac{g}{s}}{ms^2 + mgs + k} F_d + \frac{k}{ms^2 + mgs + k} d_\mu + \frac{ms^2 + mgs + S_\mu k}{ms^2 + mgs + k} r \] +#+end_important + +*** Low pass filter +Instead of a pure integrator, let's use a low pass filter with a cut-off frequency above the bandwidth of the micro-station $\omega_mu$ +#+begin_src matlab + % K_iff = (2*sqrt(k/m)/(2*wmu))*(1/(1 + s/(2*wmu))); + % K_iff.InputName = {'Fm'}; + % K_iff.OutputName = {'F'}; + + % Gpz_iff = feedback(Gpz, K_iff, 'name'); +#+end_src + +** Comparison +#+begin_src matlab :exports none + figure; + subplot(2, 2, 1); + title('Effect of Ground motion ($\epsilon/w$)'); + hold on; + plot(freqs, abs(squeeze(freqresp(Gpz('y', 'w'), freqs, 'Hz')))); + plot(freqs, abs(squeeze(freqresp(Gpz_iff('y', 'w'), freqs, 'Hz')))); + plot(freqs, abs(squeeze(freqresp(Gpz_dvf('y', 'w'), freqs, 'Hz')))); + hold off; + set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log'); + ylabel('Amplitude [m/N]'); xlabel('Frequency [Hz]'); + xlim([freqs(1), freqs(end)]); + + subplot(2, 2, 2); + title('Compliance ($\epsilon/F_d$)'); + hold on; + plot(freqs, abs(squeeze(freqresp(Gpz('y', 'Fd'), freqs, 'Hz')))); + plot(freqs, abs(squeeze(freqresp(Gpz_iff('y', 'Fd'), freqs, 'Hz')))); + plot(freqs, abs(squeeze(freqresp(Gpz_dvf('y', 'Fd'), freqs, 'Hz')))); + hold off; + set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log'); + ylabel('Amplitude [m/N]'); xlabel('Frequency [Hz]'); + xlim([freqs(1), freqs(end)]); + + subplot(2, 2, 3); + title('Vibration Filtering ($\epsilon/d_\mu$)'); + hold on; + plot(freqs, abs(squeeze(freqresp(Gpz('y', 'dmu'), freqs, 'Hz')))); + plot(freqs, abs(squeeze(freqresp(Gpz_iff('y', 'dmu'), freqs, 'Hz')))); + plot(freqs, abs(squeeze(freqresp(Gpz_dvf('y', 'dmu'), freqs, 'Hz')))); + hold off; + set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log'); + ylabel('Amplitude [m/m]'); xlabel('Frequency [Hz]'); + xlim([freqs(1), freqs(end)]); + + subplot(2, 2, 4); + title('Reference Tracking ($\epsilon/r$)'); + hold on; + plot(freqs, abs(squeeze(freqresp(1 - Gpz('y', 'r'), freqs, 'Hz'))), 'DisplayName', 'OL' ); + plot(freqs, abs(squeeze(freqresp(1 - Gpz_iff('y', 'r'), freqs, 'Hz'))), 'DisplayName', 'IFF'); + plot(freqs, abs(squeeze(freqresp(1 - Gpz_dvf('y', 'r'), freqs, 'Hz'))), 'DisplayName', 'DVF'); + plot(freqs, abs(squeeze(freqresp(1 - Tmu, freqs, 'Hz'))), 'k--', 'DisplayName', '$S_\mu$'); + hold off; + set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log'); + ylabel('Amplitude [m/m]'); xlabel('Frequency [Hz]'); + legend('location', 'northwest'); + xlim([freqs(1), freqs(end)]); +#+end_src + +#+header: :tangle no :exports results :results none :noweb yes +#+begin_src matlab :var filepath="figs/comp_iff_dvf_simplified.pdf" :var figsize="full-tall" :post pdf2svg(file=*this*, ext="png") +<> +#+end_src + +#+name: fig:comp_iff_dvf_simplified +#+caption: Obtained transfer functions for DVF and IFF ([[./figs/comp_iff_dvf_simplified.png][png]], [[./figs/comp_iff_dvf_simplified.pdf][pdf]]) +[[file:figs/comp_iff_dvf_simplified.png]] + +| | $d_\mu$ | $F_d$ | $w$ | +|-----+------------------------------------+-----------------------------------+--------------------------------------| +| IFF | Better filtering of the vibrations | More sensitive to External forces | | +| DVF | inverse | inverse | Little bit better at low frequencies | + +** Control using $x$ +*** Analytical analysis +Let's first consider that only the output $x$ is used for feedback (Figure [[fig:nano_station_control_x]]) + +#+begin_src latex :file nano_station_control_x.pdf + \begin{tikzpicture} + \node[block={4.0cm}{4.0cm}] (P) {}; + \node[above] at (P.north) {$\nu$-hexapod}; + + % Input and outputs coordinates + \coordinate[] (inputFd) at ($(P.south west)!0.8!(P.north west)$); + \coordinate[] (inputw) at ($(P.south west)!0.5!(P.north west)$); + \coordinate[] (inputF) at ($(P.south west)!0.2!(P.north west)$); + \coordinate[] (outputF) at ($(P.south east)!0.8!(P.north east)$); + \coordinate[] (outputd) at ($(P.south east)!0.5!(P.north east)$); + \coordinate[] (outputx) at ($(P.south east)!0.2!(P.north east)$); + + % Connections and labels + \draw[<-] (inputFd) -- ++(-0.8, 0) node[above right]{$F_d$}; + + \draw[->] (outputF) -- ++(0.8, 0) node[above left]{$F_m$}; + \draw[->] (outputd) -- ++(0.8, 0) node[above left]{$d$}; + \draw[->] (outputx) -- ++(0.8, 0) node[above left]{$x$}; + + \node[block, left= of inputF] (K) {$K$}; + \node[addb={+}{}{}{}{-}, left= of K] (addfb) {}; + \node[addb, left= of inputw] (add) {}; + \node[block, left= of add] (Tmu) {$T_\mu$}; + + \draw[->] ($(outputx) + (0.3, 0)$) node[branch]{} -- ++(0, -1) -| (addfb.south); + \draw[->] (addfb.east) -- (K.west) node[above left]{$\epsilon$}; + \draw[->] (K.east) -- (inputF) node[above left]{$F$}; + + \draw[->] ($(addfb.west) + (-1.6, 0)$)node[above right]{$r$} -- (addfb.west); + + \draw[->] ($(addfb.west) + (-0.8, 0)$)node[branch]{} |- (Tmu.west); + \draw[->] (Tmu.east) -- (add.west); + \draw[->] (add.east) -- (inputw) node[above left]{$x_\mu$}; + \draw[->] ($(add.north) + (0, 0.8)$) node[below right]{$d_\mu$} -- (add.north); + \end{tikzpicture} +#+end_src + +#+name: fig:nano_station_control_x +#+caption: Feedback diagram using $x$ +#+RESULTS: +[[file:figs/nano_station_control_x.png]] + +We then have: +\[ \epsilon &= r - G_{\frac{x}{F}} K \epsilon - G_{\frac{x}{F_d}} F_d - G_{\frac{x}{x_\mu}} d_\mu - G_{\frac{x}{x_\mu}} T_\mu r \] + +And then: +#+begin_important +\[ \epsilon = \frac{-G_{\frac{x}{F_d}}}{1 + G_{\frac{x}{F}}K} F_d + \frac{-G_{\frac{x}{x_\mu}}}{1 + G_{\frac{x}{F}}K} d_\mu + \frac{1 - G_{\frac{x}{x_\mu}} T_\mu}{1 + G_{\frac{x}{F}}K} r \] +#+end_important + +With $S = \frac{1}{1 + G_{\frac{x}{F}} K}$, we have: +\[ \epsilon = - S G_{\frac{x}{F_d}} F_d - S G_{\frac{x}{x_\mu}} d_\mu + S (1 - G_{\frac{x}{x_\mu}} T_\mu) r \] + +We have 3 terms that we would like to have small by design: +- $G_{\frac{x}{F_d}} = \frac{1}{ms^2 + k}$: thus $k$ and $m$ should be high to lower the effect of direct forces $F_d$ +- $G_{\frac{x}{x_\mu}} = \frac{k}{ms^2 + k} = \frac{1}{1 + \frac{s^2}{\omega_\nu^2}}$: $\omega_\nu$ should be small enough such that it filters out the vibrations of the micro-station +- $1 - G_{\frac{x}{x_\mu}} T_\mu$ + +\[ 1 - G_{\frac{x}{x_\mu}} T_\mu = 1 - \frac{1}{1 + \frac{s^2}{\omega_\nu^2}} T_\mu \] + +We can approximate $T_\mu \approx \frac{1}{1 + \frac{s}{\omega_\mu}}$ to have: +\begin{align*} + 1 - G_{\frac{x}{x_\mu}} T_\mu &= 1 - \frac{1}{1 + \frac{s^2}{\omega_\nu^2}} \frac{1}{1 + \frac{s}{\omega_\mu}} \\ + &\approx \frac{\frac{s}{\omega_\mu}}{1 + \frac{s}{\omega_\mu}} = S_\mu \text{ if } \omega_\nu > \omega_\mu \\ + &\approx \frac{\frac{s^2}{\omega_\nu^2}}{1 + \frac{s^2}{\omega_\nu^2}} = \text{ if } \omega_\nu < \omega_\mu +\end{align*} + +In our case, we have $\omega_\nu > \omega_\mu$ and thus we cannot lower this term. + +Some implications on the design are summarized on table [[tab:design_decommentation]]. + +#+name: tab:design_decommentation +#+caption: Design recommendation +| Exogenous Outputs | Design recommendation | +|-------------------+-------------------------------------------| +| $F_d$ | high $k$, high $m$ | +| $d_\mu$ | low $k$, high $m$ | +| $r$ | no influence if $\omega_\nu > \omega_\mu$ | + +*** Control implementation +Controller for the damped plant using DVF. +#+begin_src matlab + wb = 2*pi*50; % control bandwidth [rad/s] + + % Lead + h = 2.0; + wz = wb/h; % [rad/s] + wp = wb*h; % [rad/s] + + H = 1/h*(1 + s/wz)/(1 + s/wp); + + % Integrator until 10Hz + Hi = (1 + s/2/pi/10)/(s/2/pi/10); + + K = Hi*H*(1/s); + + Kpz_dvf = K/abs(freqresp(K*Gpz_dvf('y', 'F'), wb)); + Kpz_dvf.InputName = {'e'}; + Kpz_dvf.OutputName = {'Fi'}; +#+end_src + +Controller for the damped plant using IFF. +#+begin_src matlab + wb = 2*pi*50; % control bandwidth [rad/s] + + % Lead + h = 2.0; + wz = wb/h; % [rad/s] + wp = wb*h; % [rad/s] + + H = 1/h*(1 + s/wz)/(1 + s/wp); + + % Integrator until 10Hz + Hi = (1 + s/2/pi/10)/(s/2/pi/10); + + K = Hi*H*(1/s); + + Kpz_iff = K/abs(freqresp(K*Gpz_iff('y', 'F'), wb)); + Kpz_iff.InputName = {'e'}; + Kpz_iff.OutputName = {'Fi'}; +#+end_src + +Loop gain +#+begin_src matlab :exports none + figure; + title('Transfer function from $F^\prime$ to $\epsilon$'); + subplot(2, 1, 1); + hold on; + plot(freqs, abs(squeeze(freqresp(Kpz_dvf*Gpz_dvf('y', 'F'), freqs, 'Hz')))); + plot(freqs, abs(squeeze(freqresp(Kpz_iff*Gpz_iff('y', 'F'), freqs, 'Hz'))), '--'); + hold off; + set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log'); + ylabel('Loop Gain'); xlabel('Frequency [Hz]'); + + subplot(2, 1, 2); + hold on; + plot(freqs, 180/pi*angle(squeeze(freqresp(Kpz_dvf*Gpz_dvf('y', 'F'), freqs, 'Hz'))), 'DisplayName', '$L_{DVF}$'); + plot(freqs, 180/pi*angle(squeeze(freqresp(Kpz_iff*Gpz_iff('y', 'F'), freqs, 'Hz'))), '--', 'DisplayName', '$L_{IFF}$'); + hold off; + set(gca, 'XScale', 'log'); set(gca, 'YScale', 'lin'); + ylabel('Phase [deg]'); xlabel('Frequency [Hz]'); + ylim([-180, 180]); + yticks([-180, -90, 0, 90, 180]); + legend('location', 'northwest'); +#+end_src + +#+header: :tangle no :exports results :results none :noweb yes +#+begin_src matlab :var filepath="figs/simple_loop_gain_pz.pdf" :var figsize="full-tall" :post pdf2svg(file=*this*, ext="png") +<> +#+end_src + +#+name: fig:simple_loop_gain_pz +#+caption: Loop Gain ([[./figs/simple_loop_gain_pz.png][png]], [[./figs/simple_loop_gain_pz.pdf][pdf]]) +[[file:figs/simple_loop_gain_pz.png]] + + +Let's connect all the systems as shown in Figure [[fig:nano_station_control_x]]. +#+begin_src matlab + Sfb = sumblk('e = r2 - y'); + + R = [tf(1); tf(1)]; + R.InputName = {'r'}; + R.OutputName = {'r1', 'r2'}; + + F = [tf(1); tf(1)]; + F.InputName = {'Fi'}; + F.OutputName = {'F', 'Fu'}; + + Gpz_fb_dvf = connect(Gpz_dvf, Kpz_dvf, R, Sfb, F, {'r', 'dmu', 'Fd', 'w'}, {'y', 'e', 'Fm', 'd', 'Fu'}); + Gpz_fb_iff = connect(Gpz_iff, Kpz_iff, R, Sfb, F, {'r', 'dmu', 'Fd', 'w'}, {'y', 'e', 'Fm', 'd', 'Fu'}); +#+end_src + +*** Results +#+begin_src matlab :exports none + figure; + subplot(2, 2, 1); + title('Effect of Ground Motion ($\epsilon/w$)'); + hold on; + plot(freqs, abs(squeeze(freqresp(Gpz('y', 'w'), freqs, 'Hz')))); + plot(freqs, abs(squeeze(freqresp(Gpz_iff('y', 'w'), freqs, 'Hz')))); + plot(freqs, abs(squeeze(freqresp(Gpz_dvf('y', 'w'), freqs, 'Hz')))); + plot(freqs, abs(squeeze(freqresp(Gpz_fb_iff('y', 'w'), freqs, 'Hz')))); + plot(freqs, abs(squeeze(freqresp(Gpz_fb_dvf('y', 'w'), freqs, 'Hz')))); + hold off; + set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log'); + ylabel('Amplitude [m/N]'); xlabel('Frequency [Hz]'); + xlim([freqs(1), freqs(end)]); + + subplot(2, 2, 2); + title('Compliance ($\epsilon/F_d$)'); + hold on; + plot(freqs, abs(squeeze(freqresp(Gpz('y', 'Fd'), freqs, 'Hz')))); + plot(freqs, abs(squeeze(freqresp(Gpz_iff('y', 'Fd'), freqs, 'Hz')))); + plot(freqs, abs(squeeze(freqresp(Gpz_dvf('y', 'Fd'), freqs, 'Hz')))); + plot(freqs, abs(squeeze(freqresp(Gpz_fb_iff('y', 'Fd'), freqs, 'Hz')))); + plot(freqs, abs(squeeze(freqresp(Gpz_fb_dvf('y', 'Fd'), freqs, 'Hz')))); + hold off; + set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log'); + ylabel('Amplitude [m/N]'); xlabel('Frequency [Hz]'); + xlim([freqs(1), freqs(end)]); + + subplot(2, 2, 3); + title('Vibration Filtering ($\epsilon/d_\mu$)'); + hold on; + plot(freqs, abs(squeeze(freqresp(Gpz('y', 'dmu'), freqs, 'Hz')))); + plot(freqs, abs(squeeze(freqresp(Gpz_iff('y', 'dmu'), freqs, 'Hz')))); + plot(freqs, abs(squeeze(freqresp(Gpz_dvf('y', 'dmu'), freqs, 'Hz')))); + plot(freqs, abs(squeeze(freqresp(Gpz_fb_iff('y', 'dmu'), freqs, 'Hz')))); + plot(freqs, abs(squeeze(freqresp(Gpz_fb_dvf('y', 'dmu'), freqs, 'Hz')))); + hold off; + set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log'); + ylabel('Amplitude [m/m]'); xlabel('Frequency [Hz]'); + xlim([freqs(1), freqs(end)]); + + subplot(2, 2, 4); + title('Reference Tracking ($\epsilon/r$)'); + hold on; + plot(freqs, abs(squeeze(freqresp(1 - Gpz('y', 'r'), freqs, 'Hz'))), 'DisplayName', 'OL' ); + plot(freqs, abs(squeeze(freqresp(1 - Gpz_iff('y', 'r'), freqs, 'Hz'))), 'DisplayName', 'IFF'); + plot(freqs, abs(squeeze(freqresp(1 - Gpz_dvf('y', 'r'), freqs, 'Hz'))), 'DisplayName', 'DVF'); + plot(freqs, abs(squeeze(freqresp(1 - Gpz_fb_iff('y', 'r'), freqs, 'Hz'))), 'DisplayName', 'HAC-IFF'); + plot(freqs, abs(squeeze(freqresp(1 - Gpz_fb_dvf('y', 'r'), freqs, 'Hz'))), 'DisplayName', 'HAC-DVF'); + hold off; + set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log'); + ylabel('Amplitude [m/m]'); xlabel('Frequency [Hz]'); + xlim([freqs(1), freqs(end)]); + legend('location', 'southeast'); +#+end_src + +#+header: :tangle no :exports results :results none :noweb yes +#+begin_src matlab :var filepath="figs/simple_hac_lac_results.pdf" :var figsize="full-tall" :post pdf2svg(file=*this*, ext="png") +<> +#+end_src + +#+name: fig:simple_hac_lac_results +#+caption: Obtained closed-loop transfer functions ([[./figs/simple_hac_lac_results.png][png]], [[./figs/simple_hac_lac_results.pdf][pdf]]) +[[file:figs/simple_hac_lac_results.png]] + +| | Reference Tracking | Vibration Filtering | Compliance | +|-----+--------------------+----------------------------------+----------------------------------| +| DVF | Similar behavior | | Better for $\omega < \omega_\nu$ | +| IFF | Similar behavior | Better for $\omega > \omega_\nu$ | | + +** Two degree of freedom control :noexport: +Let's try to implement the control architecture shown in Figure [[fig:nano_station_control_2dof_x]]. + +The pre-filter $K_r$ is added in order to improve the reference tracking performances. + +#+begin_src latex :file nano_station_control_2dof_x.pdf + \begin{tikzpicture} + \node[block={4.0cm}{4.0cm}] (P) {}; + \node[above] at (P.north) {$\nu$-hexapod}; + + % Input and outputs coordinates + \coordinate[] (inputFd) at ($(P.south west)!0.8!(P.north west)$); + \coordinate[] (inputw) at ($(P.south west)!0.5!(P.north west)$); + \coordinate[] (inputF) at ($(P.south west)!0.2!(P.north west)$); + \coordinate[] (outputF) at ($(P.south east)!0.8!(P.north east)$); + \coordinate[] (outputd) at ($(P.south east)!0.5!(P.north east)$); + \coordinate[] (outputx) at ($(P.south east)!0.2!(P.north east)$); + + % Connections and labels + \draw[<-] (inputFd) -- ++(-0.8, 0) node[above right]{$F_d$}; + + \draw[->] (outputF) -- ++(0.8, 0) node[above left]{$F_m$}; + \draw[->] (outputd) -- ++(0.8, 0) node[above left]{$d$}; + \draw[->] (outputx) -- ++(0.8, 0) node[above left]{$x$}; + + \node[block, left= of inputF] (K) {$K$}; + \node[addb={+}{}{}{}{-}, left= of K] (addfb) {}; + \node[block, left= of addfb] (Kr) {$K_r$}; + \node[addb, left= of inputw] (add) {}; + \node[block, left= of add] (Tmu) {$T_\mu$}; + + \draw[->] ($(outputx) + (0.3, 0)$) node[branch]{} -- ++(0, -1) -| (addfb.south); + \draw[->] (addfb.east) -- (K.west) node[above left]{$\epsilon$}; + \draw[->] (K.east) -- (inputF) node[above left]{$F$}; + + \draw[->] ($(Kr.west) + (-1.6, 0)$)node[above right]{$r$} -- (Kr.west); + \draw[->] (Kr.east) -- (addfb.west); + + \draw[->] ($(Kr.west) + (-0.8, 0)$)node[branch]{} |- (Tmu.west); + \draw[->] (Tmu.east) -- (add.west); + \draw[->] (add.east) -- (inputw) node[above left]{$x_\mu$}; + \draw[->] ($(add.north) + (0, 0.8)$) node[below right]{$d_\mu$} -- (add.north); + \end{tikzpicture} +#+end_src + +#+name: fig:nano_station_control_2dof_x +#+caption: Two degrees of freedom feedback control +#+RESULTS: +[[file:figs/nano_station_control_2dof_x.png]] + +In order to design the pre-filter $K_r$, the dynamics of the system should be known quite precisely (Dynamics of the nano-hexapod + $T_\mu$). +#+begin_src matlab + Krpz = inv(Gpz_fb('y', 'r')); + + Krpz.InputName = {'r2'}; + Krpz.OutputName = {'r3'}; +#+end_src + +#+begin_src matlab + Sfb = sumblk('e = r3 - y'); + + R = [tf(1); tf(1)]; + R.InputName = {'r'}; + R.OutputName = {'r1', 'r2'}; + + Gpz_2dof = connect(Gpz_dvf, Krpz, Kpz, R, Sfb, {'r', 'dmu', 'Fd', 'w'}, {'y', 'e', 'Fm', 'd'}); +#+end_src + +#+begin_src matlab :exports none + figure; + subplot(2, 2, 1); + title('Effect of Ground Motion ($\epsilon/w$)'); + hold on; + plot(freqs, abs(squeeze(freqresp(Gpz('y', 'w'), freqs, 'Hz')))); + plot(freqs, abs(squeeze(freqresp(Gpz_iff('y', 'w'), freqs, 'Hz')))); + plot(freqs, abs(squeeze(freqresp(Gpz_dvf('y', 'w'), freqs, 'Hz')))); + plot(freqs, abs(squeeze(freqresp(Gpz_fb('y', 'w'), freqs, 'Hz')))); + plot(freqs, abs(squeeze(freqresp(Gpz_2dof('y', 'w'), freqs, 'Hz')))); + hold off; + set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log'); + ylabel('Amplitude [m/N]'); xlabel('Frequency [Hz]'); + + subplot(2, 2, 2); + title('Compliance ($\epsilon/F_d$)'); + hold on; + plot(freqs, abs(squeeze(freqresp(Gpz('y', 'Fd'), freqs, 'Hz')))); + plot(freqs, abs(squeeze(freqresp(Gpz_iff('y', 'Fd'), freqs, 'Hz')))); + plot(freqs, abs(squeeze(freqresp(Gpz_dvf('y', 'Fd'), freqs, 'Hz')))); + plot(freqs, abs(squeeze(freqresp(Gpz_fb('y', 'Fd'), freqs, 'Hz')))); + plot(freqs, abs(squeeze(freqresp(Gpz_2dof('y', 'Fd'), freqs, 'Hz')))); + hold off; + set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log'); + ylabel('Amplitude [m/N]'); xlabel('Frequency [Hz]'); + + subplot(2, 2, 3); + title('Vibration Filtering ($\epsilon/d_\mu$)'); + hold on; + plot(freqs, abs(squeeze(freqresp(Gpz('y', 'dmu'), freqs, 'Hz')))); + plot(freqs, abs(squeeze(freqresp(Gpz_iff('y', 'dmu'), freqs, 'Hz')))); + plot(freqs, abs(squeeze(freqresp(Gpz_dvf('y', 'dmu'), freqs, 'Hz')))); + plot(freqs, abs(squeeze(freqresp(Gpz_fb('y', 'dmu'), freqs, 'Hz')))); + plot(freqs, abs(squeeze(freqresp(Gpz_2dof('y', 'dmu'), freqs, 'Hz')))); + hold off; + set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log'); + ylabel('Amplitude [m/m]'); xlabel('Frequency [Hz]'); + + subplot(2, 2, 4); + title('Reference Tracking ($\epsilon/r$)'); + hold on; + plot(freqs, abs(squeeze(freqresp(1 - Gpz('y', 'r'), freqs, 'Hz'))), 'DisplayName', 'OL' ); + plot(freqs, abs(squeeze(freqresp(1 - Gpz_iff('y', 'r'), freqs, 'Hz'))), 'DisplayName', 'IFF'); + plot(freqs, abs(squeeze(freqresp(1 - Gpz_dvf('y', 'r'), freqs, 'Hz'))), 'DisplayName', 'DVF'); + plot(freqs, abs(squeeze(freqresp(1 - Gpz_fb('y', 'r'), freqs, 'Hz'))), 'DisplayName', 'FB'); + plot(freqs, abs(squeeze(freqresp(1 - Gpz_2dof('y', 'r'), freqs, 'Hz'))), 'DisplayName', '2-DOF'); + hold off; + set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log'); + ylabel('Amplitude [m/m]'); xlabel('Frequency [Hz]'); + legend('location', 'northwest'); +#+end_src + +* Comparison with the use of a Soft nano-hexapod +#+begin_src matlab + m = 50; % [kg] + k = 1e3; % [N/m] + + Gn = 1/(m*s^2 + k)*[-k, k*m*s^2, m*s^2; 1, -m*s^2, 1; 1, k, 1]; + Gn.InputName = {'Fd', 'xmu', 'F'}; + Gn.OutputName = {'Fm', 'd', 'x'}; +#+end_src + +#+begin_src matlab + wmu = 2*pi*50; % [rad/s] + + Tmu = 1/(1 + s/wmu); + Tmu.InputName = {'r1'}; + Tmu.OutputName = {'ymu'}; +#+end_src + +#+begin_src matlab + w0 = 2*pi*40; + xi = 0.5; + Tw = 1/(1 + 2*xi*s/w0 + s^2/w0^2); + Tw.InputName = {'w1'}; + Tw.OutputName = {'dw'}; +#+end_src + +#+begin_src matlab + Wsplit = [tf(1); tf(1)]; + Wsplit.InputName = {'w'}; + Wsplit.OutputName = {'w1', 'w2'}; + + S = sumblk('xmu = ymu + dmu + dw'); + + Sw = sumblk('y = x - w2'); + + Gvc = connect(Gn, S, Wsplit, Tw, Tmu, Sw, {'Fd', 'dmu', 'r1', 'F', 'w'}, {'Fm', 'd', 'y'}); +#+end_src + +#+begin_src matlab + Kvc_dvf = 2*sqrt(k*m)*s; + Kvc_dvf.InputName = {'d'}; + Kvc_dvf.OutputName = {'F'}; + + Gvc_dvf = feedback(Gvc, Kvc_dvf, 'name'); + + Kvc_iff = 2*sqrt(k/m)/s; + Kvc_iff.InputName = {'Fm'}; + Kvc_iff.OutputName = {'F'}; + + Gvc_iff = feedback(Gvc, Kvc_iff, 'name'); +#+end_src + +#+begin_src matlab + wb = 2*pi*100; % control bandwidth [rad/s] + + % Lead + h = 2.0; + wz = wb/h; % [rad/s] + wp = wb*h; % [rad/s] + + H = 1/h*(1 + s/wz)/(1 + s/wp); + + Kvc_dvf = H/abs(freqresp(H*Gvc_dvf('y', 'F'), wb)); + Kvc_dvf.InputName = {'e'}; + Kvc_dvf.OutputName = {'Fi'}; + + Kvc_iff = H/abs(freqresp(H*Gvc_iff('y', 'F'), wb)); + Kvc_iff.InputName = {'e'}; + Kvc_iff.OutputName = {'Fi'}; +#+end_src + +#+begin_src matlab + Sfb = sumblk('e = r2 - y'); + + R = [tf(1); tf(1)]; + R.InputName = {'r'}; + R.OutputName = {'r1', 'r2'}; + + F = [tf(1); tf(1)]; + F.InputName = {'Fi'}; + F.OutputName = {'F', 'Fu'}; + + + Gvc_fb_dvf = connect(Gvc_dvf, Kvc_dvf, R, Sfb, F, {'r', 'dmu', 'Fd', 'w'}, {'y', 'e', 'Fm', 'd', 'Fu'}); + Gvc_fb_iff = connect(Gvc_iff, Kvc_iff, R, Sfb, F, {'r', 'dmu', 'Fd', 'w'}, {'y', 'e', 'Fm', 'd', 'Fu'}); +#+end_src + +#+begin_src matlab :exports none + figure; + subplot(2, 2, 1); + title('Effect of Ground Motion ($\epsilon/w$)'); + hold on; + plot(freqs, abs(squeeze(freqresp(Gvc('y', 'w'), freqs, 'Hz')))); + plot(freqs, abs(squeeze(freqresp(Gvc_iff('y', 'w'), freqs, 'Hz')))); + plot(freqs, abs(squeeze(freqresp(Gvc_dvf('y', 'w'), freqs, 'Hz')))); + plot(freqs, abs(squeeze(freqresp(Gvc_fb_iff('y', 'w'), freqs, 'Hz')))); + plot(freqs, abs(squeeze(freqresp(Gvc_fb_dvf('y', 'w'), freqs, 'Hz')))); + hold off; + set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log'); + ylabel('Amplitude [m/N]'); xlabel('Frequency [Hz]'); + xlim([freqs(1), freqs(end)]); + + subplot(2, 2, 2); + title('Compliance ($\epsilon/F_d$)'); + hold on; + plot(freqs, abs(squeeze(freqresp(Gvc('y', 'Fd'), freqs, 'Hz')))); + plot(freqs, abs(squeeze(freqresp(Gvc_iff('y', 'Fd'), freqs, 'Hz')))); + plot(freqs, abs(squeeze(freqresp(Gvc_dvf('y', 'Fd'), freqs, 'Hz')))); + plot(freqs, abs(squeeze(freqresp(Gvc_fb_iff('y', 'Fd'), freqs, 'Hz')))); + plot(freqs, abs(squeeze(freqresp(Gvc_fb_dvf('y', 'Fd'), freqs, 'Hz')))); + hold off; + set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log'); + ylabel('Amplitude [m/N]'); xlabel('Frequency [Hz]'); + xlim([freqs(1), freqs(end)]); + + subplot(2, 2, 3); + title('Vibration Filtering ($\epsilon/d_\mu$)'); + hold on; + plot(freqs, abs(squeeze(freqresp(Gvc('y', 'dmu'), freqs, 'Hz')))); + plot(freqs, abs(squeeze(freqresp(Gvc_iff('y', 'dmu'), freqs, 'Hz')))); + plot(freqs, abs(squeeze(freqresp(Gvc_dvf('y', 'dmu'), freqs, 'Hz')))); + plot(freqs, abs(squeeze(freqresp(Gvc_fb_iff('y', 'dmu'), freqs, 'Hz')))); + plot(freqs, abs(squeeze(freqresp(Gvc_fb_dvf('y', 'dmu'), freqs, 'Hz')))); + hold off; + set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log'); + ylabel('Amplitude [m/m]'); xlabel('Frequency [Hz]'); + xlim([freqs(1), freqs(end)]); + + subplot(2, 2, 4); + title('Reference Tracking ($\epsilon/r$)'); + hold on; + plot(freqs, abs(squeeze(freqresp(1 - Gvc('y', 'r'), freqs, 'Hz'))), 'DisplayName', 'OL' ); + plot(freqs, abs(squeeze(freqresp(1 - Gvc_iff('y', 'r'), freqs, 'Hz'))), 'DisplayName', 'IFF'); + plot(freqs, abs(squeeze(freqresp(1 - Gvc_dvf('y', 'r'), freqs, 'Hz'))), 'DisplayName', 'DVF'); + plot(freqs, abs(squeeze(freqresp(1 - Gvc_fb_iff('y', 'r'), freqs, 'Hz'))), 'DisplayName', 'HAC-IFF'); + plot(freqs, abs(squeeze(freqresp(1 - Gvc_fb_dvf('y', 'r'), freqs, 'Hz'))), 'DisplayName', 'HAC-DVF'); + hold off; + set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log'); + ylabel('Amplitude [m/m]'); xlabel('Frequency [Hz]'); + xlim([freqs(1), freqs(end)]); + legend('location', 'southeast'); +#+end_src + +#+header: :tangle no :exports results :results none :noweb yes +#+begin_src matlab :var filepath="figs/simple_hac_lac_results_soft.pdf" :var figsize="full-tall" :post pdf2svg(file=*this*, ext="png") +<> +#+end_src + +#+name: fig:simple_hac_lac_results_soft +#+caption: Obtained closed-loop transfer functions ([[./figs/simple_hac_lac_results_soft.png][png]], [[./figs/simple_hac_lac_results_soft.pdf][pdf]]) +[[file:figs/simple_hac_lac_results_soft.png]] + +| | Reference Tracking | Vibration Filtering | Compliance | +|-----+--------------------+----------------------------------+----------------------------------| +| DVF | Similar behavior | | Better for $\omega < \omega_\nu$ | +| IFF | Similar behavior | Better for $\omega > \omega_\nu$ | | + +#+begin_src matlab :exports none + figure; + subplot(2, 2, 1); + title('Effect of Ground Motion ($\epsilon/w$)'); + hold on; + plot(freqs, abs(squeeze(freqresp(Gpz_fb_dvf('y', 'w'), freqs, 'Hz')))); + plot(freqs, abs(squeeze(freqresp(Gvc_fb_dvf('y', 'w'), freqs, 'Hz')))); + set(gca,'ColorOrderIndex',1); + plot(freqs, abs(squeeze(freqresp(Gpz_fb_iff('y', 'w'), freqs, 'Hz'))), '--'); + plot(freqs, abs(squeeze(freqresp(Gvc_fb_iff('y', 'w'), freqs, 'Hz'))), '--'); + hold off; + set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log'); + ylabel('Amplitude [m/N]'); xlabel('Frequency [Hz]'); + xlim([freqs(1), freqs(end)]); + + subplot(2, 2, 2); + title('Compliance ($\epsilon/F_d$)'); + hold on; + plot(freqs, abs(squeeze(freqresp(Gpz_fb_dvf('y', 'Fd'), freqs, 'Hz')))); + plot(freqs, abs(squeeze(freqresp(Gvc_fb_dvf('y', 'Fd'), freqs, 'Hz')))); + set(gca,'ColorOrderIndex',1); + plot(freqs, abs(squeeze(freqresp(Gpz_fb_iff('y', 'Fd'), freqs, 'Hz'))), '--'); + plot(freqs, abs(squeeze(freqresp(Gvc_fb_iff('y', 'Fd'), freqs, 'Hz'))), '--'); + hold off; + set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log'); + ylabel('Amplitude [m/N]'); xlabel('Frequency [Hz]'); + xlim([freqs(1), freqs(end)]); + + subplot(2, 2, 3); + title('Vibration Filtering ($\epsilon/d_\mu$)'); + hold on; + plot(freqs, abs(squeeze(freqresp(Gpz_fb_dvf('y', 'dmu'), freqs, 'Hz')))); + plot(freqs, abs(squeeze(freqresp(Gvc_fb_dvf('y', 'dmu'), freqs, 'Hz')))); + set(gca,'ColorOrderIndex',1); + plot(freqs, abs(squeeze(freqresp(Gpz_fb_iff('y', 'dmu'), freqs, 'Hz'))), '--'); + plot(freqs, abs(squeeze(freqresp(Gvc_fb_iff('y', 'dmu'), freqs, 'Hz'))), '--'); + hold off; + set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log'); + ylabel('Amplitude [m/m]'); xlabel('Frequency [Hz]'); + xlim([freqs(1), freqs(end)]); + + subplot(2, 2, 4); + title('Reference Tracking ($\epsilon/r$)'); + hold on; + plot(freqs, abs(squeeze(freqresp(1 - Gpz_fb_dvf('y', 'r'), freqs, 'Hz'))), 'DisplayName', 'HAC-DVF PZ'); + plot(freqs, abs(squeeze(freqresp(1 - Gvc_fb_dvf('y', 'r'), freqs, 'Hz'))), 'DisplayName', 'HAC-DVF VC'); + set(gca,'ColorOrderIndex',1); + plot(freqs, abs(squeeze(freqresp(1 - Gpz_fb_iff('y', 'r'), freqs, 'Hz'))), '--', 'DisplayName', 'HAC-IFF PZ'); + plot(freqs, abs(squeeze(freqresp(1 - Gvc_fb_iff('y', 'r'), freqs, 'Hz'))), '--', 'DisplayName', 'HAC-IFF VC'); + hold off; + set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log'); + ylabel('Amplitude [m/m]'); xlabel('Frequency [Hz]'); + xlim([freqs(1), freqs(end)]); + legend('location', 'southeast'); +#+end_src + +#+header: :tangle no :exports results :results none :noweb yes +#+begin_src matlab :var filepath="figs/simple_comp_vc_pz.pdf" :var figsize="full-tall" :post pdf2svg(file=*this*, ext="png") +<> +#+end_src + +#+name: fig:simple_comp_vc_pz +#+caption: Comparison of the closed-loop transfer functions for Soft and Stiff nano-hexapod ([[./figs/simple_comp_vc_pz.png][png]], [[./figs/simple_comp_vc_pz.pdf][pdf]]) +[[file:figs/simple_comp_vc_pz.png]] + +| | | | +| | *Soft* | *Stiff* | +|-----------------------+--------+---------| +| *Reference Tracking* | = | = | +| *Ground Motion* | = | = | +| *Vibration Isolation* | + | - | +| *Compliance* | - | + | + +* Estimate the level of vibration +#+begin_src matlab + gm = load('./mat/psd_gm.mat', 'f', 'psd_gm'); + rz = load('./mat/pxsp_r.mat', 'f', 'pxsp_r'); + tyz = load('./mat/pxz_ty_r.mat', 'f', 'pxz_ty_r'); +#+end_src + +#+begin_src matlab :exports none + f = gm.f(2:end); + + psd_gm = gm.psd_gm(2:end); % PSD of ground motion [m^2/Hz] + psd_rz = rz.pxsp_r(2:end)./(2*pi*f.^2); % PSD of hexapod's motion due to Rz [m^2/Hz] + psd_ty = tyz.pxz_ty_r(2:end)./(2*pi*f.^2); % PSD of hexapod's motion due to Ty [m^2/Hz] +#+end_src + +#+begin_src matlab :exports none + figure; + hold on; + plot(f, sqrt(psd_rz), 'DisplayName', 'Rz'); + plot(f, sqrt(psd_ty), 'DisplayName', 'Ty'); + plot(f, sqrt(psd_gm), 'DisplayName', 'Gm'); + hold off; + set(gca, 'xscale', 'log'); set(gca, 'yscale', 'log'); + xlabel('Frequency [Hz]'); ylabel('ASD of the displacement $\left[\frac{m}{\sqrt{Hz}}\right]$') + legend('Location', 'southwest'); +#+end_src + +#+begin_src matlab :exports none + figure; + hold on; + plot(f, flip(sqrt(-cumtrapz(flip(f), flip(psd_rz)))), 'DisplayName', 'Rz'); + plot(f, flip(sqrt(-cumtrapz(flip(f), flip(psd_ty)))), 'DisplayName', 'Ty'); + plot(f, flip(sqrt(-cumtrapz(flip(f), flip(psd_ty + psd_rz)))), 'k-', 'DisplayName', 'tot'); + hold off; + set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log'); + xlabel('Frequency [Hz]'); ylabel('CAS of $x_\mu$ [m]') + xlim([freqs(1), freqs(end)]); + legend('Location', 'southwest'); +#+end_src + +If we note the PSD $\Gamma$: +\[ \Gamma_y = |G_{\frac{y}{w}}|^2 \Gamma_w + |G_{\frac{y}{x_\mu}}|^2 \Gamma_{x_\mu} \] + +#+begin_src matlab + x_pz = abs(squeeze(freqresp(Gpz_fb_iff('y', 'dmu'), f, 'Hz'))).^2.*(psd_rz + psd_ty) + abs(squeeze(freqresp(Gpz_fb_iff('y', 'w'), f, 'Hz'))).^2.*(psd_gm); + x_vc = abs(squeeze(freqresp(Gvc_fb_iff('y', 'dmu'), f, 'Hz'))).^2.*(psd_rz + psd_ty) + abs(squeeze(freqresp(Gvc_fb_iff('y', 'w'), f, 'Hz'))).^2.*(psd_gm); +#+end_src + +#+begin_src matlab :exports none + figure; + hold on; + plot(f, sqrt(x_pz)); + plot(f, sqrt(x_vc)); + hold off; + set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log'); + xlabel('Frequency [Hz]'); ylabel('ASD of the displacement $\left[\frac{m}{\sqrt{Hz}}\right]$') + xlim([freqs(1), freqs(end)]); +#+end_src + +#+begin_src matlab :exports none + figure; + hold on; + plot(f, flip(sqrt(-cumtrapz(flip(f), flip(x_pz)))), 'DisplayName', 'PZ'); + plot(f, flip(sqrt(-cumtrapz(flip(f), flip(x_vc)))), 'DisplayName', 'VC'); + plot(f, flip(sqrt(-cumtrapz(flip(f), flip(psd_rz + psd_ty + psd_gm.*abs(squeeze(freqresp(Tw, f, 'Hz')).^2))))), 'DisplayName', 'OL'); + hold off; + set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log'); + xlabel('Frequency [Hz]'); ylabel('CAS of the relative displacement $[m]$') + xlim([freqs(1), freqs(end)]); + legend(); +#+end_src + +#+header: :tangle no :exports results :results none :noweb yes +#+begin_src matlab :var filepath="figs/simple_asd_motion_error.pdf" :var figsize="full-tall" :post pdf2svg(file=*this*, ext="png") +<> +#+end_src + +#+name: fig:simple_asd_motion_error +#+caption: ASD of the position error due to Ground Motion and Vibration ([[./figs/simple_asd_motion_error.png][png]], [[./figs/simple_asd_motion_error.pdf][pdf]]) +[[file:figs/simple_asd_motion_error.png]] + +Actuator usage +#+begin_src matlab + F_pz = abs(squeeze(freqresp(Gpz_fb_iff('Fu', 'dmu'), f, 'Hz'))).^2.*(psd_rz + psd_ty) + abs(squeeze(freqresp(Gpz_fb_iff('Fu', 'w'), f, 'Hz'))).^2.*(psd_gm); + F_vc = abs(squeeze(freqresp(Gvc_fb_iff('Fu', 'dmu'), f, 'Hz'))).^2.*(psd_rz + psd_ty) + abs(squeeze(freqresp(Gvc_fb_iff('Fu', 'w'), f, 'Hz'))).^2.*(psd_gm); +#+end_src + +#+begin_src matlab :results output replace + sqrt(trapz(f, F_pz)) + sqrt(trapz(f, F_vc)) +#+end_src + +#+RESULTS: +: sqrt(trapz(f, F_pz)) +: ans = +: 84.8961762069446 +: sqrt(trapz(f, F_vc)) +: ans = +: 0.0387785981815527 + +* Requirements on the norm of closed-loop transfer functions +** Approximation of the ASD of perturbations +#+begin_src matlab + G_rz = 1e-9*1/(1 + s/2/pi/0.5)^2*(s + 2*pi*1)*(s + 2*pi*10)*(1/((1 + s/2/pi/100)^2)); +#+end_src + +#+begin_src matlab :exports none + figure; + hold on; + plot(f, sqrt(psd_rz), 'DisplayName', 'Rz'); + plot(freqs, abs(squeeze(freqresp(G_rz, freqs, 'Hz')))); + hold off; + set(gca, 'xscale', 'log'); set(gca, 'yscale', 'log'); + xlabel('Frequency [Hz]'); ylabel('ASD of the displacement $\left[\frac{m}{\sqrt{Hz}}\right]$') + legend('Location', 'southwest'); +#+end_src + +#+begin_src matlab + G_gm = 1e-8*1/s^2*(s + 2*pi*1)^2*(1/((1 + s/2/pi/10)^3)); +#+end_src + +#+begin_src matlab :exports none + figure; + hold on; + plot(f, sqrt(psd_gm), 'DisplayName', 'Rz'); + plot(freqs, abs(squeeze(freqresp(G_gm, freqs, 'Hz')))); + hold off; + set(gca, 'xscale', 'log'); set(gca, 'yscale', 'log'); + xlabel('Frequency [Hz]'); ylabel('ASD of the displacement $\left[\frac{m}{\sqrt{Hz}}\right]$') + legend('Location', 'southwest'); +#+end_src + +** Wanted ASD of outputs +Wanted ASD of motion error +#+begin_src matlab + y_wanted = 100e-9; % 10nm rms wanted + y_bw = 2*pi*100; % bandwidth [rad/s] + + G_y = 2*y_wanted/sqrt(y_bw) * (1 + s/y_bw/10) / (1 + s/y_bw); +#+end_src + +#+begin_src matlab :exports none + figure; + hold on; + plot(freqs, abs(squeeze(freqresp(G_y, freqs, 'Hz')))); + hold off; + set(gca, 'xscale', 'log'); set(gca, 'yscale', 'log'); + xlabel('Frequency [Hz]'); ylabel('ASD of the displacement $\left[\frac{m}{\sqrt{Hz}}\right]$') + legend('Location', 'southwest'); +#+end_src + +#+begin_src matlab :results output replace + sqrt(trapz(f, abs(squeeze(freqresp(G_y, f, 'Hz'))).^2)) +#+end_src + +#+RESULTS: +: sqrt(trapz(f, abs(squeeze(freqresp(G_y, f, 'Hz'))).^2)) +: ans = +: 9.47118350214793e-08 + +** Limiting the bandwidth +#+begin_src matlab + wF = 2*pi*10; + G_F = 100000*(wF + s)^2; +#+end_src + +** Generalized Weighted plant +Let's create a generalized weighted plant for controller synthesis. + +Let's start simple: +| | *Symbol* | *Meaning* | +|---------------------+----------+------------------------------------| +| *Exogenous Inputs* | $x_\mu$ | Motion of the $\nu$-hexapod's base | +|---------------------+----------+------------------------------------| +| *Exogenous Outputs* | $y$ | Motion error of the Payload | +|---------------------+----------+------------------------------------| +| *Sensed Outputs* | $y$ | Motion error of the Payload | +|---------------------+----------+------------------------------------| +| *Control Signals* | $F$ | Actuator Inputs | + +Add $F$ as output. +#+begin_src matlab + F = [tf(1); tf(1)]; + F.InputName = {'Fi'}; + F.OutputName = {'F', 'Fu'}; + + P_pz = connect(F, Gpz_dvf, {'dmu', 'Fi'}, {'y', 'Fu', 'y'}) + P_vc = connect(F, Gvc_dvf, {'dmu', 'Fi'}, {'y', 'Fu', 'y'}) +#+end_src + +Normalization. + +We multiply the plant input by $G_{rz}$ and the plant output by $G_y^{-1}$: +#+begin_src matlab + P_pz_norm = blkdiag(inv(G_y), inv(G_F), 1)*P_pz*blkdiag(G_rz, 1); + P_pz_norm.OutputName = {'z', 'F', 'y'}; + P_pz_norm.InputName = {'w', 'u'}; + + P_vc_norm = blkdiag(inv(G_y), inv(G_F), 1)*P_vc*blkdiag(G_rz, 1); + P_vc_norm.OutputName = {'z', 'F', 'y'}; + P_vc_norm.InputName = {'w', 'u'}; +#+end_src + +** Synthesis +#+begin_src matlab + [Kpz_dvf,CL_vc,~] = hinfsyn(minreal(P_pz_norm), 1, 1, 'TOLGAM', 0.001, 'METHOD', 'LMI', 'DISPLAY', 'on'); + Kpz_dvf.InputName = {'e'}; + Kpz_dvf.OutputName = {'Fi'}; + + [Kvc_dvf,CL_pz,~] = hinfsyn(minreal(P_vc_norm), 1, 1, 'TOLGAM', 0.001, 'METHOD', 'LMI', 'DISPLAY', 'on'); + Kvc_dvf.InputName = {'e'}; + Kvc_dvf.OutputName = {'Fi'}; +#+end_src + +** Loop Gain +#+begin_src matlab :exports none + figure; + title('Transfer function from $F^\prime$ to $\epsilon$'); + subplot(2, 1, 1); + hold on; + plot(freqs, abs(squeeze(freqresp(Kpz_dvf*Gpz_dvf('y', 'F'), freqs, 'Hz')))); + plot(freqs, abs(squeeze(freqresp(Kvc_dvf*Gvc_dvf('y', 'F'), freqs, 'Hz')))); + hold off; + set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log'); + ylabel('Loop Gain'); xlabel('Frequency [Hz]'); + + subplot(2, 1, 2); + hold on; + plot(freqs, 180/pi*angle(squeeze(freqresp(-Kpz_dvf*Gpz_dvf('y', 'F'), freqs, 'Hz'))), 'DisplayName', '$PZ$'); + plot(freqs, 180/pi*angle(squeeze(freqresp(-Kvc_dvf*Gvc_dvf('y', 'F'), freqs, 'Hz'))), 'DisplayName', '$VC$'); + hold off; + set(gca, 'XScale', 'log'); set(gca, 'YScale', 'lin'); + ylabel('Phase [deg]'); xlabel('Frequency [Hz]'); + ylim([-180, 180]); + yticks([-180, -90, 0, 90, 180]); + legend('location', 'northwest'); +#+end_src + +#+begin_src matlab + Sfb = sumblk('e = r2 - y'); + + R = [tf(1); tf(1)]; + R.InputName = {'r'}; + R.OutputName = {'r1', 'r2'}; + + F = [tf(1); tf(1)]; + F.InputName = {'Fi'}; + F.OutputName = {'F', 'Fu'}; + + Gpz_fb_dvf = connect(Gpz_dvf, -Kpz_dvf, R, Sfb, F, {'r', 'dmu', 'Fd', 'w'}, {'y', 'e', 'Fm', 'd', 'Fu'}); + Gvc_fb_dvf = connect(Gvc_dvf, -Kvc_dvf, R, Sfb, F, {'r', 'dmu', 'Fd', 'w'}, {'y', 'e', 'Fm', 'd', 'Fu'}); +#+end_src + +** Results +#+begin_src matlab :exports none + freqs = logspace(-6, 8, 1000); + + figure; + subplot(2, 2, 1); + title('Effect of Ground Motion ($\epsilon/w$)'); + hold on; + plot(freqs, abs(squeeze(freqresp(Gpz_fb_dvf('y', 'w'), freqs, 'Hz')))); + plot(freqs, abs(squeeze(freqresp(Gvc_fb_dvf('y', 'w'), freqs, 'Hz')))); + hold off; + set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log'); + ylabel('Amplitude [m/N]'); xlabel('Frequency [Hz]'); + xlim([freqs(1), freqs(end)]); + + subplot(2, 2, 2); + title('Compliance ($\epsilon/F_d$)'); + hold on; + plot(freqs, abs(squeeze(freqresp(Gpz_fb_dvf('y', 'Fd'), freqs, 'Hz')))); + plot(freqs, abs(squeeze(freqresp(Gvc_fb_dvf('y', 'Fd'), freqs, 'Hz')))); + hold off; + set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log'); + ylabel('Amplitude [m/N]'); xlabel('Frequency [Hz]'); + xlim([freqs(1), freqs(end)]); + + subplot(2, 2, 3); + title('Vibration Filtering ($\epsilon/d_\mu$)'); + hold on; + plot(freqs, abs(squeeze(freqresp(Gpz_fb_dvf('y', 'dmu'), freqs, 'Hz')))); + plot(freqs, abs(squeeze(freqresp(Gvc_fb_dvf('y', 'dmu'), freqs, 'Hz')))); + plot(freqs, abs(squeeze(freqresp(G_y*inv(G_rz), freqs, 'Hz'))), 'k--'); + hold off; + set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log'); + ylabel('Amplitude [m/m]'); xlabel('Frequency [Hz]'); + xlim([freqs(1), freqs(end)]); + + subplot(2, 2, 4); + title('Reference Tracking ($\epsilon/r$)'); + hold on; + plot(freqs, abs(squeeze(freqresp(1 - Gpz_fb_dvf('y', 'r'), freqs, 'Hz'))), 'DisplayName', 'HAC-DVF PZ'); + plot(freqs, abs(squeeze(freqresp(1 - Gvc_fb_dvf('y', 'r'), freqs, 'Hz'))), 'DisplayName', 'HAC-DVF VC'); + hold off; + set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log'); + ylabel('Amplitude [m/m]'); xlabel('Frequency [Hz]'); + xlim([freqs(1), freqs(end)]); + legend('location', 'southeast'); +#+end_src + +** Requirements +| reference tracking | $\epsilon/r$ | -120dB at 1Hz | +| vibration isolation | $x/x_\mu$ | -60dB above 10Hz | +| compliance | $x/F_d$ | | diff --git a/org/disturbances.org b/org/disturbances.org index a989165..d509667 100644 --- a/org/disturbances.org +++ b/org/disturbances.org @@ -30,7 +30,7 @@ #+PROPERTY: header-args:shell :eval no-export -#+PROPERTY: header-args:latex :headers '("\\usepackage{tikz}" "\\usepackage{import}" "\\import{$HOME/Cloud/thesis/latex/}{config.tex}") +#+PROPERTY: header-args:latex :headers '("\\usepackage{tikz}" "\\usepackage{import}" "\\import{$HOME/Cloud/thesis/latex/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 @@ -356,10 +356,10 @@ The PSD of the relative velocity between the hexapod and the marble in $[(m/s)^2 Also, the Ground Motion is measured. #+begin_src matlab - gm = load('./disturbances/mat/psd_gm.mat', 'f', 'psd_gm', 'psd_gv'); - rz = load('./disturbances/mat/pxsp_r.mat', 'f', 'pxsp_r'); - tyz = load('./disturbances/mat/pxz_ty_r.mat', 'f', 'pxz_ty_r'); - tyx = load('./disturbances/mat/pxe_ty_r.mat', 'f', 'pxe_ty_r'); + gm = load('./mat/psd_gm.mat', 'f', 'psd_gm'); + rz = load('./mat/pxsp_r.mat', 'f', 'pxsp_r'); + tyz = load('./mat/pxz_ty_r.mat', 'f', 'pxz_ty_r'); + tyx = load('./mat/pxe_ty_r.mat', 'f', 'pxe_ty_r'); #+end_src #+begin_src matlab :exports none @@ -553,7 +553,7 @@ We should verify that this is coherent with the measurements. :PROPERTIES: :CUSTOM_ID: Save :END: -The PSD of the disturbance force are now saved for further analysis (the mat file is accessible [[file:mat/dist_psd.mat][here]]). +The PSD of the disturbance force are now saved for further analysis. #+begin_src matlab dist_f = struct(); @@ -564,5 +564,85 @@ The PSD of the disturbance force are now saved for further analysis (the mat fil dist_f.psd_ty = tyz.psd_f; % Power Spectral Density of the force induced by the Ty stage in the Z direction [N^2/Hz] dist_f.psd_rz = rz.psd_f; % Power Spectral Density of the force induced by the Rz stage in the Z direction [N^2/Hz] - save('./disturbances/mat/dist_psd.mat', 'dist_f'); + save('./mat/dist_psd.mat', 'dist_f'); +#+end_src + +* Error motion of the Sample without Control +#+begin_src matlab + initializeGround(); + initializeGranite('Foffset', false); + initializeTy('Foffset', false); + initializeRy('Foffset', false); + initializeRz('Foffset', false); + initializeMicroHexapod('Foffset', false); + initializeAxisc('type', 'rigid'); + initializeMirror('type', 'rigid'); +#+end_src + +The nano-hexapod is a piezoelectric hexapod and the sample has a mass of 50kg. +#+begin_src matlab + initializeNanoHexapod('type', 'rigid'); + initializeSample('type', 'rigid', 'mass', 50); +#+end_src + +We set the references and disturbances to zero. +#+begin_src matlab + initializeReferences(); + initializeDisturbances(); +#+end_src + +We set the controller type to Open-Loop. +#+begin_src matlab + initializeController('type', 'open-loop'); +#+end_src + +And we put some gravity. +#+begin_src matlab + initializeSimscapeConfiguration('gravity', false); +#+end_src + +We do not need to log any signal. +#+begin_src matlab + initializeLoggingConfiguration('log', 'all'); +#+end_src + +#+begin_src matlab + initializePosError('error', false); +#+end_src + +#+begin_src matlab + load('mat/conf_simulink.mat'); + set_param(conf_simulink, 'StopTime', '1'); +#+end_src + +We simulate the model. +#+begin_src matlab + sim('nass_model'); +#+end_src + +#+begin_src matlab + figure; + subplot(1, 2, 1); + hold on; + plot(simout.Em.Eg.Time, simout.Em.Eg.Data(:, 1), 'DisplayName', 'X'); + plot(simout.Em.Eg.Time, simout.Em.Eg.Data(:, 2), 'DisplayName', 'Y'); + plot(simout.Em.Eg.Time, simout.Em.Eg.Data(:, 3), 'DisplayName', 'Z'); + hold off; + xlabel('Time [s]'); + ylabel('Position error [m]'); + legend(); + + subplot(1, 2, 2); + hold on; + plot(simout.Em.Eg.Time, simout.Em.Eg.Data(:, 4)); + plot(simout.Em.Eg.Time, simout.Em.Eg.Data(:, 5)); + plot(simout.Em.Eg.Time, simout.Em.Eg.Data(:, 6)); + hold off; + xlabel('Time [s]'); + ylabel('Orientation error [rad]'); +#+end_src + +#+begin_src matlab + Eg = simout.Em.Eg; + save('./mat/motion_error_ol.mat', 'Eg'); #+end_src diff --git a/org/experiments.org b/org/experiments.org index 4c24ca3..d5a3e2b 100644 --- a/org/experiments.org +++ b/org/experiments.org @@ -30,7 +30,7 @@ #+PROPERTY: header-args:shell :eval no-export -#+PROPERTY: header-args:latex :headers '("\\usepackage{tikz}" "\\usepackage{import}" "\\import{$HOME/Cloud/thesis/latex/}{config.tex}") +#+PROPERTY: header-args:latex :headers '("\\usepackage{tikz}" "\\usepackage{import}" "\\import{$HOME/Cloud/thesis/latex/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 @@ -127,12 +127,12 @@ We simulate the model. And we save the obtained data. #+begin_src matlab tomo_align_no_dist = struct('t', t, 'MTr', MTr); - save('experiment_tomography/mat/experiment.mat', 'tomo_align_no_dist', '-append'); + save('./mat/experiment_tomography.mat', 'tomo_align_no_dist', '-append'); #+end_src ** Analysis #+begin_src matlab - load('experiment_tomography/mat/experiment.mat', 'tomo_align_no_dist'); + load('./mat/experiment_tomography.mat', 'tomo_align_no_dist'); t = tomo_align_no_dist.t; MTr = tomo_align_no_dist.MTr; #+end_src @@ -206,7 +206,6 @@ And we save the obtained data. [[file:figs/exp_tomo_without_dist_rot.png]] ** Conclusion - #+begin_important When everything is aligned, the resulting error motion is very small (nm range) and is quite negligible with respect to the error when disturbances are included. This residual error motion probably comes from a small misalignment somewhere. @@ -237,12 +236,12 @@ We simulate the model. And we save the obtained data. #+begin_src matlab tomo_align_dist = struct('t', t, 'MTr', MTr); - save('experiment_tomography/mat/experiment.mat', 'tomo_align_dist', '-append'); + save('./mat/experiment_tomography.mat', 'tomo_align_dist', '-append'); #+end_src ** Analysis #+begin_src matlab - load('experiment_tomography/mat/experiment.mat', 'tomo_align_dist'); + load('./mat/experiment_tomography.mat', 'tomo_align_dist'); t = tomo_align_dist.t; MTr = tomo_align_dist.MTr; #+end_src @@ -361,12 +360,12 @@ We simulate the model. And we save the obtained data. #+begin_src matlab tomo_not_align = struct('t', t, 'MTr', MTr); - save('experiment_tomography/mat/experiment.mat', 'tomo_not_align', '-append'); + save('./mat/experiment_tomography.mat', 'tomo_not_align', '-append'); #+end_src ** Analysis #+begin_src matlab - load('experiment_tomography/mat/experiment.mat', 'tomo_not_align'); + load('./mat/experiment_tomography.mat', 'tomo_not_align'); t = tomo_not_align.t; MTr = tomo_not_align.MTr; #+end_src @@ -489,12 +488,12 @@ We simulate the model. And we save the obtained data. #+begin_src matlab ty_scan = struct('t', t, 'MTr', MTr); - save('experiment_tomography/mat/experiment.mat', 'ty_scan', '-append'); + save('./mat/experiment_tomography.mat', 'ty_scan', '-append'); #+end_src ** Analysis #+begin_src matlab - load('experiment_tomography/mat/experiment.mat', 'ty_scan'); + load('./mat/experiment_tomography.mat', 'ty_scan'); t = ty_scan.t; MTr = ty_scan.MTr; #+end_src diff --git a/org/functions.org b/org/functions.org index c17a84e..459328d 100644 --- a/org/functions.org +++ b/org/functions.org @@ -30,7 +30,7 @@ #+PROPERTY: header-args:shell :eval no-export -#+PROPERTY: header-args:latex :headers '("\\usepackage{tikz}" "\\usepackage{import}" "\\import{$HOME/Cloud/thesis/latex/}{config.tex}") +#+PROPERTY: header-args:latex :headers '("\\usepackage{tikz}" "\\usepackage{import}" "\\import{$HOME/Cloud/thesis/latex/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 diff --git a/org/hac_lac.org b/org/hac_lac.org index 4a0c1f9..4589a74 100644 --- a/org/hac_lac.org +++ b/org/hac_lac.org @@ -30,18 +30,471 @@ #+PROPERTY: header-args:shell :eval no-export -#+PROPERTY: header-args:latex :headers '("\\usepackage{tikz}" "\\usepackage{import}" "\\import{$HOME/Cloud/thesis/latex/}{config.tex}") +#+PROPERTY: header-args:latex :headers '("\\usepackage{tikz}" "\\usepackage{import}" "\\import{$HOME/Cloud/thesis/latex/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 raw replace :buffer no +#+PROPERTY: header-args:latex+ :results file raw replace +#+PROPERTY: header-args:latex+ :buffer no #+PROPERTY: header-args:latex+ :eval no-export -#+PROPERTY: header-args:latex+ :exports both +#+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: -* Undamped System +* Introduction :ignore: +The position $\bm{\mathcal{X}}$ of the Sample with respect to the granite is measured. + +It is then compare to the wanted position of the Sample $\bm{r}_\mathcal{X}$ in order to obtain the position error $\bm{\epsilon}_\mathcal{X}$ of the Sample with respect to a frame attached to the Stewart top platform. + +#+begin_src latex :file hac_lac_control_schematic.pdf + \begin{tikzpicture} + \node[block={3.0cm}{3.0cm}] (G) {$G$}; + + % Input and outputs coordinates + \coordinate[] (outputX) at ($(G.south east)!0.25!(G.north east)$); + \coordinate[] (outputL) at ($(G.south east)!0.75!(G.north east)$); + + \draw[->] (outputX) -- ++(1.8, 0) node[above left]{$\bm{\mathcal{X}}$}; + \draw[->] (outputL) -- ++(1.8, 0) node[above left]{$\bm{\mathcal{L}}$}; + + % Blocs + \node[addb, left= of G] (addF) {}; + \node[block, left=1.2 of addF] (Kx) {$\bm{K}_\mathcal{X}$}; + \node[block={2cm}{2cm}, align=center, left=1.2 of Kx] (subx) {Computes\\Position\\Error}; + + \node[block, above= of addF] (Kl) {$\bm{K}_\mathcal{L}$}; + \node[addb={+}{}{}{-}{}, above= of Kl] (subl) {}; + + \node[block, align=center, left=0.8 of subl] (invK) {Inverse\\Kinematics}; + + % Connections and labels + \draw[<-] (subx.west)node[above left]{$\bm{r}_{\mathcal{X}}$} -- ++(-0.8, 0); + \draw[->] ($(subx.east) + (0.2, 0)$)node[branch]{} |- (invK.west); + \draw[->] (invK.east) -- (subl.west) node[above left]{$\bm{r}_\mathcal{L}$}; + \draw[->] (subl.south) -- (Kl.north) node[above right]{$\bm{\epsilon}_\mathcal{L}$}; + \draw[->] (Kl.south) -- (addF.north); + + \draw[->] (subx.east) -- (Kx.west) node[above left]{$\bm{\epsilon}_\mathcal{X}$}; + \draw[->] (Kx.east) node[above right]{$\bm{\tau}_\mathcal{X}$} -- (addF.west); + \draw[->] (addF.east) -- (G.west) node[above left]{$\bm{\tau}$}; + + \draw[->] ($(outputL.east) + (0.4, 0)$)node[branch](L){} |- (subl.east); + \draw[->] ($(outputX.east) + (1.2, 0)$)node[branch]{} -- ++(0, -1.6) -| (subx.south); + + \begin{scope}[on background layer] + \node[fit={(G.south-|Kl.west) (L|-subl.north)}, fill=black!20!white, draw, dashed, inner sep=8pt] (Ktot) {}; + \end{scope} + \end{tikzpicture} +#+end_src + +#+RESULTS: +[[file:figs/hac_lac_control_schematic.png]] + +* Initialization +We initialize all the stages with the default parameters. +#+begin_src matlab + initializeGround(); + initializeGranite(); + initializeTy(); + initializeRy(); + initializeRz(); + initializeMicroHexapod(); + initializeAxisc(); + initializeMirror(); +#+end_src + +The nano-hexapod is a piezoelectric hexapod and the sample has a mass of 50kg. +#+begin_src matlab + initializeNanoHexapod('actuator', 'piezo'); + initializeSample('mass', 1); +#+end_src + +We set the references that corresponds to a tomography experiment. +#+begin_src matlab + initializeReferences('Rz_type', 'rotating', 'Rz_period', 1); +#+end_src + +#+begin_src matlab + initializeDisturbances(); +#+end_src + +Open Loop. +#+begin_src matlab + initializeController('type', 'open-loop'); +#+end_src + +And we put some gravity. +#+begin_src matlab + initializeSimscapeConfiguration('gravity', true); +#+end_src + +We log the signals. +#+begin_src matlab + initializeLoggingConfiguration('log', 'all'); +#+end_src + +* Low Authority Control - Direct Velocity Feedback $\bm{K}_\mathcal{L}$ +** Introduction :ignore: +The first loop closed corresponds to a direct velocity feedback loop. + +The design of the associated decentralized controller is explained in [[file:active_damping.org][this]] file. + +** Identification +#+begin_src matlab + %% Name of the Simulink File + mdl = 'nass_model'; + + %% Input/Output definition + clear io; io_i = 1; + io(io_i) = linio([mdl, '/Controller'], 1, 'openinput'); io_i = io_i + 1; % Actuator Inputs + io(io_i) = linio([mdl, '/Micro-Station'], 3, 'openoutput', [], 'Dnlm'); io_i = io_i + 1; % Relative Motion Outputs + + %% Run the linearization + G_dvf = linearize(mdl, io, 0); + G_dvf.InputName = {'Fnl1', 'Fnl2', 'Fnl3', 'Fnl4', 'Fnl5', 'Fnl6'}; + G_dvf.OutputName = {'Dnlm1', 'Dnlm2', 'Dnlm3', 'Dnlm4', 'Dnlm5', 'Dnlm6'}; +#+end_src + +** Plant +#+begin_src matlab :exports none + freqs = logspace(0, 3, 1000); + + figure; + + ax1 = subplot(2, 1, 1); + hold on; + for i = 1:6 + plot(freqs, abs(squeeze(freqresp(G_dvf(i,i), freqs, 'Hz')))); + end + hold off; + set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log'); + ylabel('Amplitude [m/N]'); set(gca, 'XTickLabel',[]); + + ax2 = subplot(2, 1, 2); + hold on; + for i = 1:6 + plot(freqs, 180/pi*angle(squeeze(freqresp(G_dvf(i,i), freqs, 'Hz')))); + end + hold off; + set(gca, 'XScale', 'log'); set(gca, 'YScale', 'lin'); + ylabel('Phase [deg]'); xlabel('Frequency [Hz]'); + ylim([-180, 180]); + yticks([-180, -90, 0, 90, 180]); + + linkaxes([ax1,ax2],'x'); +#+end_src + +** Root Locus +#+begin_src matlab :exports none + gains = logspace(0, 5, 500); + + figure; + hold on; + plot(real(pole(G_dvf)), imag(pole(G_dvf)), 'x'); + set(gca,'ColorOrderIndex',1); + plot(real(tzero(G_dvf)), imag(tzero(G_dvf)), 'o'); + for i = 1:length(gains) + set(gca,'ColorOrderIndex',1); + cl_poles = pole(feedback(G_dvf, (gains(i)*s)*eye(6))); + plot(real(cl_poles), imag(cl_poles), '.'); + end + % ylim([0, 1.1*max(imag(pole(G_dvf)))]); + % xlim([-1.1*max(imag(pole(G_dvf))),0]); + xlabel('Real Part') + ylabel('Imaginary Part') + axis square +#+end_src + +** Controller and Loop Gain +#+begin_src matlab + K_dvf = s*15000/(1 + s/2/pi/10000); +#+end_src + +#+begin_src matlab :exports none + freqs = logspace(0, 3, 1000); + + figure; + + ax1 = subplot(2, 1, 1); + hold on; + for i = 1:6 + plot(freqs, abs(squeeze(freqresp(K_dvf*G_dvf(i,i), freqs, 'Hz')))); + end + hold off; + set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log'); + ylabel('Amplitude [m/N]'); set(gca, 'XTickLabel',[]); + + ax2 = subplot(2, 1, 2); + hold on; + for i = 1:6 + plot(freqs, 180/pi*angle(squeeze(freqresp(K_dvf*G_dvf(i,i), freqs, 'Hz')))); + end + hold off; + set(gca, 'XScale', 'log'); set(gca, 'YScale', 'lin'); + ylabel('Phase [deg]'); xlabel('Frequency [Hz]'); + ylim([-180, 180]); + yticks([-180, -90, 0, 90, 180]); + + linkaxes([ax1,ax2],'x'); +#+end_src + +#+begin_src matlab + K_dvf = -K_dvf*eye(6); +#+end_src + +* High Authority Control - $\bm{K}_\mathcal{X}$ +** Identification of the damped plant +#+begin_src matlab + Kx = tf(zeros(6)); +#+end_src + +#+begin_src matlab + initializeController('type', 'hac-dvf'); +#+end_src + +#+begin_src matlab + %% Name of the Simulink File + mdl = 'nass_model'; + + %% Input/Output definition + clear io; io_i = 1; + io(io_i) = linio([mdl, '/Controller'], 1, 'input'); io_i = io_i + 1; % Actuator Inputs + io(io_i) = linio([mdl, '/Tracking Error'], 1, 'output', [], 'En'); io_i = io_i + 1; % Position Errror + + %% Run the linearization + G = linearize(mdl, io, 0); + G.InputName = {'Fnl1', 'Fnl2', 'Fnl3', 'Fnl4', 'Fnl5', 'Fnl6'}; + G.OutputName = {'Ex', 'Ey', 'Ez', 'Erx', 'Ery', 'Erz'}; +#+end_src + +The minus sine is put here because there is already a minus sign included due to the computation of the position error. +#+begin_src matlab + load('mat/stages.mat', 'nano_hexapod'); + + Gx = -G*inv(nano_hexapod.J'); + Gx.InputName = {'Fx', 'Fy', 'Fz', 'Mx', 'My', 'Mz'}; +#+end_src + +#+begin_src matlab :exports none + freqs = logspace(0, 3, 1000); + + labels = {'$D_x/\mathcal{F}_x$', '$D_y/\mathcal{F}_y$', '$D_z/\mathcal{F}_z$', '$R_x/\mathcal{M}_x$', '$R_y/\mathcal{M}_y$', '$R_z/\mathcal{M}_z$'}; + + figure; + + ax1 = subplot(2, 2, 1); + hold on; + for i = 1:6 + plot(freqs, abs(squeeze(freqresp(Gx(i, i), freqs, 'Hz')))); + end + hold off; + set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log'); + ylabel('Amplitude [m/N]'); set(gca, 'XTickLabel',[]); + title('Diagonal elements of the Plant'); + + ax2 = subplot(2, 2, 3); + hold on; + for i = 1:6 + plot(freqs, 180/pi*angle(squeeze(freqresp(Gx(i, i), freqs, 'Hz'))), 'DisplayName', labels{i}); + end + hold off; + set(gca, 'XScale', 'log'); set(gca, 'YScale', 'lin'); + ylabel('Phase [deg]'); xlabel('Frequency [Hz]'); + ylim([-180, 180]); + yticks([-180, -90, 0, 90, 180]); + legend(); + + ax3 = subplot(2, 2, 2); + hold on; + for i = 1:5 + for j = i+1:6 + plot(freqs, abs(squeeze(freqresp(Gx(i, j), freqs, 'Hz'))), 'color', [0, 0, 0, 0.2]); + end + end + set(gca,'ColorOrderIndex',1); + plot(freqs, abs(squeeze(freqresp(Gx(1, 1), freqs, 'Hz')))); + hold off; + set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log'); + ylabel('Amplitude [m/N]'); set(gca, 'XTickLabel',[]); + title('Off-Diagonal elements of the Plant'); + + ax4 = subplot(2, 2, 4); + hold on; + for i = 1:5 + for j = i+1:6 + plot(freqs, 180/pi*angle(squeeze(freqresp(Gx(i, j), freqs, 'Hz'))), 'color', [0, 0, 0, 0.2]); + end + end + set(gca,'ColorOrderIndex',1); + plot(freqs, 180/pi*angle(squeeze(freqresp(Gx(1, 1), freqs, 'Hz')))); + hold off; + set(gca, 'XScale', 'log'); set(gca, 'YScale', 'lin'); + ylabel('Phase [deg]'); xlabel('Frequency [Hz]'); + ylim([-180, 180]); + yticks([-180, -90, 0, 90, 180]); + + linkaxes([ax1,ax2,ax3,ax4],'x'); +#+end_src + +** Controller Design +The controller consists of: +- A pure integrator +- A Second integrator up to half the wanted bandwidth +- A Lead around the cross-over frequency +- A low pass filter with a cut-off equal to two times the wanted bandwidth + +#+begin_src matlab + wc = 2*pi*15; % Bandwidth Bandwidth [rad/s] + + h = 1.5; % Lead parameter + + Kx = (1/h) * (1 + s/wc*h)/(1 + s/wc/h) * wc/s * ((s/wc*2 + 1)/(s/wc*2)) * (1/(1 + s/wc/2)); + + % Normalization of the gain of have a loop gain of 1 at frequency wc + Kx = Kx.*diag(1./diag(abs(freqresp(Gx*Kx, wc)))); +#+end_src + +#+begin_src matlab :exports none + freqs = logspace(0, 3, 1000); + + labels = {'$D_x/\mathcal{F}_x$', '$D_y/\mathcal{F}_y$', '$D_z/\mathcal{F}_z$', '$R_x/\mathcal{M}_x$', '$R_y/\mathcal{M}_y$', '$R_z/\mathcal{M}_z$'}; + + figure; + + ax1 = subplot(2, 2, 1); + hold on; + for i = 1:6 + plot(freqs, abs(squeeze(freqresp(Gx(i, i)*Kx(i,i), freqs, 'Hz')))); + end + hold off; + set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log'); + ylabel('Amplitude [m/N]'); set(gca, 'XTickLabel',[]); + title('Diagonal elements of the Plant'); + + ax2 = subplot(2, 2, 3); + hold on; + for i = 1:6 + plot(freqs, 180/pi*angle(squeeze(freqresp(Gx(i, i)*Kx(i,i), freqs, 'Hz'))), 'DisplayName', labels{i}); + end + hold off; + set(gca, 'XScale', 'log'); set(gca, 'YScale', 'lin'); + ylabel('Phase [deg]'); xlabel('Frequency [Hz]'); + ylim([-180, 180]); + yticks([-180, -90, 0, 90, 180]); + legend(); + + ax3 = subplot(2, 2, 2); + hold on; + for i = 1:5 + for j = i+1:6 + plot(freqs, abs(squeeze(freqresp(Gx(i, j)*Kx(i,j), freqs, 'Hz'))), 'color', [0, 0, 0, 0.2]); + end + end + set(gca,'ColorOrderIndex',1); + plot(freqs, abs(squeeze(freqresp(Gx(1, 1), freqs, 'Hz')))); + hold off; + set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log'); + ylabel('Amplitude [m/N]'); set(gca, 'XTickLabel',[]); + title('Off-Diagonal elements of the Plant'); + + ax4 = subplot(2, 2, 4); + hold on; + for i = 1:5 + for j = i+1:6 + plot(freqs, 180/pi*angle(squeeze(freqresp(Gx(i, j), freqs, 'Hz'))), 'color', [0, 0, 0, 0.2]); + end + end + set(gca,'ColorOrderIndex',1); + plot(freqs, 180/pi*angle(squeeze(freqresp(Gx(1, 1), freqs, 'Hz')))); + hold off; + set(gca, 'XScale', 'log'); set(gca, 'YScale', 'lin'); + ylabel('Phase [deg]'); xlabel('Frequency [Hz]'); + ylim([-180, 180]); + yticks([-180, -90, 0, 90, 180]); + + linkaxes([ax1,ax2,ax3,ax4],'x'); +#+end_src + +#+begin_src matlab + isstable(feedback(Gx*Kx, eye(6), -1)) +#+end_src + +#+begin_src matlab + Kx = inv(nano_hexapod.J')*Kx; +#+end_src + +#+begin_src matlab + isstable(feedback(G*Kx, eye(6), 1)) +#+end_src + +* Simulation +#+begin_src matlab + load('mat/conf_simulink.mat'); + set_param(conf_simulink, 'StopTime', '1.5'); +#+end_src + +And we simulate the system. +#+begin_src matlab + sim('nass_model'); +#+end_src + +#+begin_src matlab + save('./mat/tomo_exp_hac_lac.mat', 'simout'); +#+end_src + +* Results +#+begin_src matlab + load('./mat/tomo_exp_hac_lac.mat', 'simout'); +#+end_src + +#+begin_src matlab :exports none + figure; + hold on; + plot(simout.Em.En.Data(:,1), simout.Em.En.Data(:,2), 'DisplayName', '$\epsilon_{x,y}$ - OL') + xlabel('X Motion [m]'); ylabel('Y Motion [m]'); + legend(); +#+end_src + + +#+begin_src matlab :exports none + figure; + hold on; + plot3(simout.Em.En.Data(:,1), simout.Em.En.Data(:,2), simout.Em.En.Data(:,3)) + xlabel('X Motion [m]'); ylabel('Y Motion [m]'); +#+end_src + +#+begin_src matlab :exports none + figure; + hold on; + plot3(simout.Em.En.Data(:,4), simout.Em.En.Data(:,5), simout.Em.En.Data(:,3)) + xlabel('X Motion [m]'); ylabel('Y Motion [m]'); +#+end_src + +#+begin_src matlab :exports none + figure; + hold on; + plot(simout.Em.En.Time, simout.Em.En.Data(:,1), 'DisplayName', '$\epsilon_{x}$') + plot(simout.Em.En.Time, simout.Em.En.Data(:,2), 'DisplayName', '$\epsilon_{y}$') + plot(simout.Em.En.Time, simout.Em.En.Data(:,3), 'DisplayName', '$\epsilon_{z}$') + hold off; + legend(); + xlabel('Time [s]'); ylabel('Position Error [m]'); +#+end_src + +#+begin_src matlab :exports none + figure; + hold on; + plot(simout.Em.En.Time, simout.Em.En.Data(:,4), 'DisplayName', '$\epsilon_{R_x}$') + plot(simout.Em.En.Time, simout.Em.En.Data(:,5), 'DisplayName', '$\epsilon_{R_y}$') + plot(simout.Em.En.Time, simout.Em.En.Data(:,6), 'DisplayName', '$\epsilon_{R_z}$') + hold off; + legend(); + xlabel('Time [s]'); ylabel('Orientation Error [rad]'); +#+end_src + +* Undamped System :noexport: <> ** Introduction :ignore: @@ -85,7 +538,7 @@ The nano-hexapod is a piezoelectric hexapod and the sample has a mass of 50kg. No disturbances. #+begin_src matlab - initializeDisturbances('enable', false); + initializeDisturbances(); #+end_src We set the references to zero. @@ -329,13 +782,13 @@ And we simulate the system. Finally, we save the simulation results for further analysis #+begin_src matlab - save('./active_damping/mat/tomo_exp.mat', 'En', 'Eg', '-append'); + save('./mat/active_damping_tomo_exp.mat', 'En', 'Eg', '-append'); #+end_src *** Results We load the results of tomography experiments. #+begin_src matlab - load('./active_damping/mat/tomo_exp.mat', 'En'); + load('./mat/active_damping_tomo_exp.mat', 'En'); t = linspace(0, 3, length(En(:,1))); #+end_src @@ -447,11 +900,6 @@ First, we identify the dynamics of the system using the =linearize= function. G_legs.OutputName = {'e1', 'e2', 'e3', 'e4', 'e5', 'e6'}; #+end_src -# And we save them for further analysis. -# #+begin_src matlab -# save('./hac_lac/mat/undamped_plant.mat', 'G'); -# #+end_src - *** Display TF #+begin_src matlab :exports none freqs = logspace(0, 3, 1000); diff --git a/org/identification.org b/org/identification.org index e86afd7..76162ca 100644 --- a/org/identification.org +++ b/org/identification.org @@ -30,7 +30,7 @@ #+PROPERTY: header-args:shell :eval no-export -#+PROPERTY: header-args:latex :headers '("\\usepackage{tikz}" "\\usepackage{import}" "\\import{$HOME/Cloud/thesis/latex/}{config.tex}") +#+PROPERTY: header-args:latex :headers '("\\usepackage{tikz}" "\\usepackage{import}" "\\import{$HOME/Cloud/thesis/latex/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 @@ -50,195 +50,6 @@ We can then compare the measured Frequency Response Functions with the identifie Finally, this should help to tune the parameters of the model such that the dynamics is closer to the measured FRF. -* Identification of the Micro-Station :noexport: -** Introduction :ignore: - -** Matlab Init :noexport:ignore: -#+begin_src matlab :tangle no :exports none :results silent :noweb yes :var current_dir=(file-name-directory buffer-file-name) - <> -#+end_src - -#+begin_src matlab :exports none :results silent :noweb yes - <> -#+end_src - -#+begin_src matlab :tangle no - simulinkproject('../'); -#+end_src - -** Simscape Model -The simulink file for the identification is =sim_micro_station_id.slx=. -#+begin_src matlab - open('identification/matlab/sim_micro_station_id.slx') -#+end_src - -We load the configuration and we set a small =StopTime=. -#+begin_src matlab - load('mat/conf_simulink.mat'); - set_param(conf_simulink, 'StopTime', '0.5'); -#+end_src - -We initialize all the stages. -#+begin_src matlab - initializeGround(); - initializeGranite(); - initializeTy(); - initializeRy(); - initializeRz(); - initializeMicroHexapod(); - initializeAxisc(); - initializeMirror(); - initializeNanoHexapod('actuator', 'piezo'); - initializeSample('mass', 50); -#+end_src - -** Compute the transfer functions -We first define some parameters for the identification. -#+begin_src matlab -%% Options for Linearized -options = linearizeOptions; -options.SampleTime = 0; - -%% Name of the Simulink File -mdl = 'sim_micro_station_id'; -#+end_src - -#+begin_src matlab -%% Micro-Hexapod -% Input/Output definition -io(1) = linio([mdl, '/Micro-Station/Fm_ext'],1,'openinput'); -io(2) = linio([mdl, '/Micro-Station/Fg_ext'],1,'openinput'); -io(3) = linio([mdl, '/Micro-Station/Dm_inertial'],1,'output'); -io(4) = linio([mdl, '/Micro-Station/Ty_inertial'],1,'output'); -io(5) = linio([mdl, '/Micro-Station/Ry_inertial'],1,'output'); -io(6) = linio([mdl, '/Micro-Station/Dg_inertial'],1,'output'); -#+end_src - -#+begin_src matlab -% Run the linearization -G_ms = linearize(mdl, io, 0); - -% Input/Output names -G_ms.InputName = {'Fmx', 'Fmy', 'Fmz',... - 'Fgx', 'Fgy', 'Fgz'}; -G_ms.OutputName = {'Dmx', 'Dmy', 'Dmz', ... - 'Tyx', 'Tyy', 'Tyz', ... - 'Ryx', 'Ryy', 'Ryz', ... - 'Dgx', 'Dgy', 'Dgz'}; -#+end_src - -#+begin_src matlab -%% Save the obtained transfer functions -save('./mat/id_micro_station.mat', 'G_ms'); -#+end_src - -** Plots the transfer functions - -** Compare with the measurements - -* Modal Analysis of the Micro-Station :noexport: -** Matlab Init :noexport:ignore: -#+begin_src matlab :tangle no :exports none :results silent :noweb yes :var current_dir=(file-name-directory buffer-file-name) - <> -#+end_src - -#+begin_src matlab :exports none :results silent :noweb yes - <> -#+end_src - -#+begin_src matlab :tangle no - simulinkproject('../'); -#+end_src - -** Simscape Model -The simulink file for the analysis is =sim_micro_station_modal_analysis.slx=. -#+begin_src matlab - open('identification/matlab/sim_micro_station_modal_analysis.slx') -#+end_src - -We load the configuration and we set a small =StopTime=. -#+begin_src matlab - load('mat/conf_simulink.mat'); - set_param(conf_simulink, 'StopTime', '0.5'); -#+end_src - -We initialize all the stages. -#+begin_src matlab - initializeGround(); - initializeGranite(); - initializeTy(); - initializeRy(); - initializeRz(); - initializeMicroHexapod(); - initializeAxisc(); - initializeMirror(); - initializeNanoHexapod('actuator', 'piezo'); - initializeSample('mass', 50); -#+end_src - -** Identification -#+begin_src matlab -%% Options for Linearized -options = linearizeOptions; -options.SampleTime = 0; - -%% Name of the Simulink File -mdl = 'sim_micro_station_modal_analysis'; -#+end_src - -#+begin_src matlab -%% Micro-Hexapod -% Input/Output definition -io(1) = linio([mdl, '/Micro-Station/F_hammer'],1,'openinput'); -io(2) = linio([mdl, '/Micro-Station/acc9'],1,'output'); -io(3) = linio([mdl, '/Micro-Station/acc10'],1,'output'); -io(4) = linio([mdl, '/Micro-Station/acc11'],1,'output'); -io(5) = linio([mdl, '/Micro-Station/acc12'],1,'output'); -#+end_src - -#+begin_src matlab - % Run the linearization - G_ms = linearize(mdl, io, 0); - - % Input/Output names - G_ms.InputName = {'Fx', 'Fy', 'Fz'}; - G_ms.OutputName = {'x9', 'y9', 'z9', ... - 'x10', 'y10', 'z10', ... - 'x11', 'y11', 'z11', ... - 'x12', 'y12', 'z12'}; -#+end_src - -** Plot Results -#+begin_src matlab - figure; - hold on; - plot(freqs, abs(squeeze(freqresp(G_ms('x9', 'Fx'), freqs, 'Hz')))); - set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log'); - ylabel('Amplitude [m/N]'); - hold off; -#+end_src - -** Compare with measurements -#+begin_src matlab - load('../meas/modal-analysis/mat/frf_coh_matrices.mat', 'FRFs', 'COHs', 'freqs'); -#+end_src - -#+begin_src matlab - dirs = {'x', 'y', 'z'}; - - n_acc = 9; - n_dir = 1; % x, y, z - n_exc = 1; % x, y, z - - figure; - hold on; - plot(freqs, abs(squeeze(FRFs(3*(n_acc-1) + n_dir, n_exc, :)))./((2*pi*freqs).^2)'); - plot(freqs, abs(squeeze(freqresp(G_ms([dirs{n_dir}, num2str(n_acc)], ['F', dirs{n_dir}]), freqs, 'Hz')))); - set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log'); - ylabel('Amplitude [m/N]'); - hold off; -#+end_src - * Some notes about the Simscape Model The Simscape Model of the micro-station consists of several solid bodies: - Bottom Granite @@ -255,9 +66,6 @@ Then, the solid bodies are connected with springs and dampers. Some of the springs and dampers values can be estimated from the joints/stages specifications, however, we here prefer to tune these values based on the measurements. * Compare with measurements at the CoM of each element -** Introduction :ignore: -[[file:../../meas/modal-analysis/index.org][here]] - ** Matlab Init :noexport:ignore: #+begin_src matlab :tangle no :exports none :results silent :noweb yes :var current_dir=(file-name-directory buffer-file-name) <> @@ -393,7 +201,7 @@ We now same this for further use: rz_com = rz_com.Data(end, :)'; hexa_com = hexa_com.Data(end, :)'; - save('mat/solids_com.mat', 'granite_bot_com', 'granite_top_com', 'ty_com', 'ry_com', 'rz_com', 'hexa_com'); + save('./mat/solids_com.mat', 'granite_bot_com', 'granite_top_com', 'ty_com', 'ry_com', 'rz_com', 'hexa_com'); #+end_src Then, we use the obtained results to add a =rigidTransform= block in order to create a new frame at the center of mass of each solid body. @@ -433,7 +241,6 @@ We use the =linearize= function in order to estimate the dynamics from forces ap G_ms = linearize(mdl, io, 0); %% Input/Output definition - clear io; io_i = 1; G_ms.InputName = {'Fx', 'Fy', 'Fz'}; G_ms.OutputName = {'gtop_x', 'gtop_y', 'gtop_z', 'gtop_rx', 'gtop_ry', 'gtop_rz', ... 'ty_x', 'ty_y', 'ty_z', 'ty_rx', 'ty_ry', 'ty_rz', ... diff --git a/org/index.org b/org/index.org index 5579e10..4ec9add 100644 --- a/org/index.org +++ b/org/index.org @@ -27,7 +27,7 @@ #+PROPERTY: header-args:shell :eval no-export -#+PROPERTY: header-args:latex :headers '("\\usepackage{tikz}" "\\usepackage{import}" "\\import{$HOME/Cloud/thesis/latex/}{config.tex}") +#+PROPERTY: header-args:latex :headers '("\\usepackage{tikz}" "\\usepackage{import}" "\\import{$HOME/Cloud/thesis/latex/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 diff --git a/org/kinematics.org b/org/kinematics.org index 91aac4c..b8de000 100644 --- a/org/kinematics.org +++ b/org/kinematics.org @@ -30,7 +30,7 @@ #+PROPERTY: header-args:shell :eval no-export -#+PROPERTY: header-args:latex :headers '("\\usepackage{tikz}" "\\usepackage{import}" "\\import{$HOME/Cloud/thesis/latex/}{config.tex}") +#+PROPERTY: header-args:latex :headers '("\\usepackage{tikz}" "\\usepackage{import}" "\\import{$HOME/Cloud/thesis/latex/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 diff --git a/org/motion_force_requirements.org b/org/motion_force_requirements.org new file mode 100644 index 0000000..9c290f3 --- /dev/null +++ b/org/motion_force_requirements.org @@ -0,0 +1,81 @@ +#+TITLE: Motion and Force Requirements for the Nano-Hexapod + + +* Soft Hexapod +As the nano-hexapod is in series with the other stages, it must apply all the force required to move the sample. + +If the nano-hexapod is soft (voice coil), its actuator must apply all the force such that the sample has the wanted motion. + +In some sense, it does not use the fact that the other stage are participating to the displacement of the sample. + +Let's take two examples: +- Sinus Ty translation at 1Hz with an amplitude of 5mm +- Long stroke hexapod has an offset of 10mm in X and the spindle is rotating + Thus the wanted motion is a circle with a radius of 10mm + If the sample if light (30Kg) => 60rpm + If the sample if heavy (100Kg) => 1rpm + +From the motion, we compute the required acceleration by derive the displacement two times. +Then from the Newton's second law: $m \vec{a} = \sum \vec{F}$ we can compute the required force. + +** Matlab Init :noexport:ignore: +#+begin_src matlab :tangle no :exports none :results silent :noweb yes :var current_dir=(file-name-directory buffer-file-name) +<> +#+end_src + +#+begin_src matlab :exports none :results silent :noweb yes +<> +#+end_src + +** Example +The wanted motion is: +\begin{align*} + x &= d \cos(\omega t) \\ + y &= d \sin(\omega t) +\end{align*} + +The corresponding acceleration is thus: +\begin{align*} + \ddot{x} &= - d \omega^2 \cos(\omega t) \\ + \ddot{y} &= - d \omega^2 \sin(\omega t) +\end{align*} + +From the Newton's second law: +\begin{align*} + m \ddot{x} &= F_x \\ + m \ddot{y} &= F_y +\end{align*} + +Thus the applied forces should be: +\begin{align*} + F_x &= - m d \omega^2 \cos(\omega t) \\ + F_y &= - m d \omega^2 \sin(\omega t) +\end{align*} + +And the norm of the force is: +\[ |F| = \sqrt{F_x^2 + F_y^2} = m d \omega^2 \ [N] \] + + +For a Light sample: +#+begin_src matlab :results value replace + m = 30; + d = 10e-3; + w = 2*pi; + F = m*d*w^2; + ans = F +#+end_src + +#+RESULTS: +: 11.844 + +For the Heavy sample: +#+begin_src matlab :results value replace + m = 80; + d = 10e-3; + w = 2*pi/60; + F = m*d*w^2 + ans = F +#+end_src + +#+RESULTS: +: 0.008773 diff --git a/org/positioning_error.org b/org/positioning_error.org index 3676aec..5ffa1dc 100644 --- a/org/positioning_error.org +++ b/org/positioning_error.org @@ -30,7 +30,7 @@ #+PROPERTY: header-args:shell :eval no-export -#+PROPERTY: header-args:latex :headers '("\\usepackage{tikz}" "\\usepackage{import}" "\\import{$HOME/Cloud/thesis/latex/}{config.tex}") +#+PROPERTY: header-args:latex :headers '("\\usepackage{tikz}" "\\usepackage{import}" "\\import{$HOME/Cloud/thesis/latex/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 diff --git a/org/simscape.org b/org/simscape.org index be8ff65..d6a50b0 100644 --- a/org/simscape.org +++ b/org/simscape.org @@ -30,7 +30,7 @@ #+PROPERTY: header-args:shell :eval no-export -#+PROPERTY: header-args:latex :headers '("\\usepackage{tikz}" "\\usepackage{import}" "\\import{$HOME/Cloud/thesis/latex/}{config.tex}") +#+PROPERTY: header-args:latex :headers '("\\usepackage{tikz}" "\\usepackage{import}" "\\import{$HOME/Cloud/thesis/latex/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 diff --git a/org/simscape_subsystems.org b/org/simscape_subsystems.org index 68d03b7..51aec70 100644 --- a/org/simscape_subsystems.org +++ b/org/simscape_subsystems.org @@ -30,7 +30,7 @@ #+PROPERTY: header-args:shell :eval no-export -#+PROPERTY: header-args:latex :headers '("\\usepackage{tikz}" "\\usepackage{import}" "\\import{$HOME/Cloud/thesis/latex/}{config.tex}") +#+PROPERTY: header-args:latex :headers '("\\usepackage{tikz}" "\\usepackage{import}" "\\import{$HOME/Cloud/thesis/latex/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 @@ -213,7 +213,8 @@ The model of the Ground is composed of: :END: #+begin_src matlab arguments - args.type char {mustBeMember(args.type,{'none', 'rigid'})} = 'rigid' + args.type char {mustBeMember(args.type,{'none', 'rigid'})} = 'rigid' + args.rot_point (3,1) double {mustBeNumeric} = zeros(3,1) % Rotation point for the ground motion [m] end #+end_src @@ -249,6 +250,15 @@ We set the shape and density of the ground solid element. ground.density = 2800; % [kg/m3] #+end_src +** Rotation Point +:PROPERTIES: +:UNNUMBERED: t +:END: + +#+begin_src matlab + ground.rot_point = args.rot_point; +#+end_src + ** Save the Structure :PROPERTIES: :UNNUMBERED: t @@ -1448,8 +1458,8 @@ The =sample= structure is saved. :END: #+begin_src matlab arguments - args.type char {mustBeMember(args.type,{'open-loop', 'iff', 'dvf'})} = 'open-loop' - args.K (6,6) = ss(zeros(6, 6)) + args.type char {mustBeMember(args.type,{'open-loop', 'iff', 'dvf', 'hac-dvf'})} = 'open-loop' + args.K (6,6) = ss(zeros(6, 6)) end #+end_src @@ -1474,6 +1484,8 @@ First, we initialize the =controller= structure. controller.type = 2; case 'iff' controller.type = 3; + case 'hac-dvf' + controller.type = 4; end #+end_src @@ -1778,7 +1790,7 @@ The =controller= structure is saved. :END: #+begin_src matlab %% Save - save('mat/nass_references.mat', 'Dy', 'Ry', 'Rz', 'Dh', 'Dhl', 'Rm', 'Dn', 'Dnl', 'Ts'); + save('./mat/nass_references.mat', 'Dy', 'Ry', 'Rz', 'Dh', 'Dhl', 'Rm', 'Dn', 'Dnl', 'Ts'); end #+end_src @@ -1834,7 +1846,7 @@ The =controller= structure is saved. :UNNUMBERED: t :END: #+begin_src matlab - load('./disturbances/mat/dist_psd.mat', 'dist_f'); + load('./mat/dist_psd.mat', 'dist_f'); #+end_src We remove the first frequency point that usually is very large. @@ -2001,7 +2013,7 @@ We define some parameters that will be used in the algorithm. :UNNUMBERED: t :END: #+begin_src matlab - save('mat/nass_disturbances.mat', 'Dwx', 'Dwy', 'Dwz', 'Fty_x', 'Fty_z', 'Frz_z', 'Fd', 'Ts', 't'); + save('./mat/nass_disturbances.mat', 'Dwx', 'Dwy', 'Dwz', 'Fty_x', 'Fty_z', 'Frz_z', 'Fd', 'Ts', 't'); #+end_src * Initialize Position Errors @@ -2076,7 +2088,7 @@ First, we initialize the =pos_error= structure. :UNNUMBERED: t :END: #+begin_src matlab - save('mat/pos_error.mat', 'pos_error'); + save('./mat/pos_error.mat', 'pos_error'); #+end_src * Z-Axis Geophone diff --git a/org/simulink_project.org b/org/simulink_project.org index a929e58..7b718a4 100644 --- a/org/simulink_project.org +++ b/org/simulink_project.org @@ -30,7 +30,7 @@ #+PROPERTY: header-args:shell :eval no-export -#+PROPERTY: header-args:latex :headers '("\\usepackage{tikz}" "\\usepackage{import}" "\\import{$HOME/Cloud/thesis/latex/}{config.tex}") +#+PROPERTY: header-args:latex :headers '("\\usepackage{tikz}" "\\usepackage{import}" "\\import{$HOME/Cloud/thesis/latex/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 diff --git a/org/uniaxial.org b/org/uniaxial.org index b1703a5..a6a16d2 100644 --- a/org/uniaxial.org +++ b/org/uniaxial.org @@ -30,7 +30,7 @@ #+PROPERTY: header-args:shell :eval no-export -#+PROPERTY: header-args:latex :headers '("\\usepackage{tikz}" "\\usepackage{import}" "\\import{$HOME/Cloud/thesis/latex/}{config.tex}") +#+PROPERTY: header-args:latex :headers '("\\usepackage{tikz}" "\\usepackage{import}" "\\import{$HOME/Cloud/thesis/latex/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 @@ -666,13 +666,13 @@ The nano-hexapod is a piezoelectric hexapod and the sample has a mass of 50kg. All the controllers are set to 0 (Open Loop). #+begin_src matlab :exports none K = tf(0); - save('./mat/controllers.mat', 'K', '-append'); + save('./mat/controllers_uniaxial.mat', 'K', '-append'); K_iff = tf(0); - save('./mat/controllers.mat', 'K_iff', '-append'); + save('./mat/controllers_uniaxial.mat', 'K_iff', '-append'); K_rmc = tf(0); - save('./mat/controllers.mat', 'K_rmc', '-append'); + save('./mat/controllers_uniaxial.mat', 'K_rmc', '-append'); K_dvf = tf(0); - save('./mat/controllers.mat', 'K_dvf', '-append'); + save('./mat/controllers_uniaxial.mat', 'K_dvf', '-append'); #+end_src ** Identification @@ -720,7 +720,7 @@ Finally, we use the =linearize= Matlab function to extract a state space model f Finally, we save the identified system dynamics for further analysis. #+begin_src matlab - save('./uniaxial/mat/plants.mat', 'G'); + save('./mat/uniaxial_plants.mat', 'G'); #+end_src ** Sensitivity to Disturbances @@ -793,7 +793,7 @@ We show several plots representing the sensitivity to disturbances: ** Noise Budget We first load the measured PSD of the disturbance. #+begin_src matlab - load('./disturbances/mat/dist_psd.mat', 'dist_f'); + load('./mat/disturbances_dist_psd.mat', 'dist_f'); #+end_src The effect of these disturbances on the distance $D$ is computed below. @@ -1080,7 +1080,7 @@ It corresponds to the plant to control. ** Control Design #+begin_src matlab - load('./uniaxial/mat/plants.mat', 'G'); + load('./mat/uniaxial_plants.mat', 'G'); #+end_src Let's look at the transfer function from actuator forces in the nano-hexapod to the force sensor in the nano-hexapod legs for all 6 pairs of actuator/sensor. @@ -1166,13 +1166,13 @@ Let's initialize the system prior to identification. All the controllers are set to 0. #+begin_src matlab K = tf(0); - save('./mat/controllers.mat', 'K', '-append'); + save('./mat/controllers_uniaxial.mat', 'K', '-append'); K_iff = -K_iff; - save('./mat/controllers.mat', 'K_iff', '-append'); + save('./mat/controllers_uniaxial.mat', 'K_iff', '-append'); K_rmc = tf(0); - save('./mat/controllers.mat', 'K_rmc', '-append'); + save('./mat/controllers_uniaxial.mat', 'K_rmc', '-append'); K_dvf = tf(0); - save('./mat/controllers.mat', 'K_dvf', '-append'); + save('./mat/controllers_uniaxial.mat', 'K_dvf', '-append'); #+end_src #+begin_src matlab @@ -1215,7 +1215,7 @@ All the controllers are set to 0. #+end_src #+begin_src matlab - save('./uniaxial/mat/plants.mat', 'G_iff', '-append'); + save('./mat/uniaxial_plants.mat', 'G_iff', '-append'); #+end_src ** Sensitivity to Disturbance @@ -1506,7 +1506,7 @@ In the Relative Motion Control (RMC), a derivative feedback is applied between t ** Control Design #+begin_src matlab - load('./uniaxial/mat/plants.mat', 'G'); + load('./mat/uniaxial_plants.mat', 'G'); #+end_src Let's look at the transfer function from actuator forces in the nano-hexapod to the measured displacement of the actuator for all 6 pairs of actuator/sensor. @@ -1593,13 +1593,13 @@ Let's initialize the system prior to identification. And initialize the controllers. #+begin_src matlab K = tf(0); - save('./mat/controllers.mat', 'K', '-append'); + save('./mat/controllers_uniaxial.mat', 'K', '-append'); K_iff = tf(0); - save('./mat/controllers.mat', 'K_iff', '-append'); + save('./mat/controllers_uniaxial.mat', 'K_iff', '-append'); K_rmc = -K_rmc; - save('./mat/controllers.mat', 'K_rmc', '-append'); + save('./mat/controllers_uniaxial.mat', 'K_rmc', '-append'); K_dvf = tf(0); - save('./mat/controllers.mat', 'K_dvf', '-append'); + save('./mat/controllers_uniaxial.mat', 'K_dvf', '-append'); #+end_src #+begin_src matlab @@ -1642,7 +1642,7 @@ And initialize the controllers. #+end_src #+begin_src matlab - save('./uniaxial/mat/plants.mat', 'G_rmc', '-append'); + save('./mat/uniaxial_plants.mat', 'G_rmc', '-append'); #+end_src @@ -1941,7 +1941,7 @@ In the Relative Motion Control (RMC), a feedback is applied between the measured ** Control Design #+begin_src matlab - load('./uniaxial/mat/plants.mat', 'G'); + load('./mat/uniaxial_plants.mat', 'G'); #+end_src #+begin_src matlab :exports none @@ -2024,13 +2024,13 @@ Let's initialize the system prior to identification. And initialize the controllers. #+begin_src matlab K = tf(0); - save('./mat/controllers.mat', 'K', '-append'); + save('./mat/controllers_uniaxial.mat', 'K', '-append'); K_iff = tf(0); - save('./mat/controllers.mat', 'K_iff', '-append'); + save('./mat/controllers_uniaxial.mat', 'K_iff', '-append'); K_rmc = tf(0); - save('./mat/controllers.mat', 'K_rmc', '-append'); + save('./mat/controllers_uniaxial.mat', 'K_rmc', '-append'); K_dvf = -K_dvf; - save('./mat/controllers.mat', 'K_dvf', '-append'); + save('./mat/controllers_uniaxial.mat', 'K_dvf', '-append'); #+end_src #+begin_src matlab @@ -2073,7 +2073,7 @@ And initialize the controllers. #+end_src #+begin_src matlab - save('./uniaxial/mat/plants.mat', 'G_dvf', '-append'); + save('./mat/uniaxial_plants.mat', 'G_dvf', '-append'); #+end_src ** Sensitivity to Disturbance @@ -2258,13 +2258,13 @@ Let's initialize the system prior to identification. And initialize the controllers. #+begin_src matlab K = tf(0); - save('./mat/controllers.mat', 'K', '-append'); + save('./mat/controllers_uniaxial.mat', 'K', '-append'); K_iff = tf(0); - save('./mat/controllers.mat', 'K_iff', '-append'); + save('./mat/controllers_uniaxial.mat', 'K_iff', '-append'); K_rmc = tf(0); - save('./mat/controllers.mat', 'K_rmc', '-append'); + save('./mat/controllers_uniaxial.mat', 'K_rmc', '-append'); K_dvf = tf(0); - save('./mat/controllers.mat', 'K_dvf', '-append'); + save('./mat/controllers_uniaxial.mat', 'K_dvf', '-append'); #+end_src We identify the dynamics of the system. @@ -2394,13 +2394,13 @@ Let's initialize the system prior to identification. All the controllers are set to 0. #+begin_src matlab K = tf(0); - save('./mat/controllers.mat', 'K', '-append'); + save('./mat/controllers_uniaxial.mat', 'K', '-append'); K_iff = -K_cedrat; - save('./mat/controllers.mat', 'K_iff', '-append'); + save('./mat/controllers_uniaxial.mat', 'K_iff', '-append'); K_rmc = tf(0); - save('./mat/controllers.mat', 'K_rmc', '-append'); + save('./mat/controllers_uniaxial.mat', 'K_rmc', '-append'); K_dvf = tf(0); - save('./mat/controllers.mat', 'K_dvf', '-append'); + save('./mat/controllers_uniaxial.mat', 'K_dvf', '-append'); #+end_src #+begin_src matlab @@ -2443,7 +2443,7 @@ All the controllers are set to 0. #+end_src #+begin_src matlab - % save('./uniaxial/mat/plants.mat', 'G_cedrat', '-append'); + % save('./mat/uniaxial_plants.mat', 'G_cedrat', '-append'); #+end_src ** Sensitivity to Disturbance @@ -2578,7 +2578,7 @@ All the controllers are set to 0. ** Load the plants #+begin_src matlab - load('./uniaxial/mat/plants.mat', 'G', 'G_iff', 'G_rmc', 'G_dvf'); + load('./mat/uniaxial_plants.mat', 'G', 'G_iff', 'G_rmc', 'G_dvf'); #+end_src ** Sensitivity to Disturbance @@ -2689,7 +2689,7 @@ All the controllers are set to 0. ** Noise Budget We first load the measured PSD of the disturbance. #+begin_src matlab - load('./disturbances/mat/dist_psd.mat', 'dist_f'); + load('./mat/disturbances_dist_psd.mat', 'dist_f'); #+end_src The effect of these disturbances on the distance $D$ is computed for all active damping techniques. @@ -2854,13 +2854,13 @@ The nano-hexapod is an hexapod with voice coils and the sample has a mass of 50k All the controllers are set to 0 (Open Loop). #+begin_src matlab :exports none K = tf(0); - save('./mat/controllers.mat', 'K', '-append'); + save('./mat/controllers_uniaxial.mat', 'K', '-append'); K_iff = tf(0); - save('./mat/controllers.mat', 'K_iff', '-append'); + save('./mat/controllers_uniaxial.mat', 'K_iff', '-append'); K_rmc = tf(0); - save('./mat/controllers.mat', 'K_rmc', '-append'); + save('./mat/controllers_uniaxial.mat', 'K_rmc', '-append'); K_dvf = tf(0); - save('./mat/controllers.mat', 'K_dvf', '-append'); + save('./mat/controllers_uniaxial.mat', 'K_dvf', '-append'); #+end_src ** Identification @@ -2908,13 +2908,13 @@ Finally, we use the =linearize= Matlab function to extract a state space model f Finally, we save the identified system dynamics for further analysis. #+begin_src matlab - save('./uniaxial/mat/plants.mat', 'G_vc', '-append'); + save('./mat/uniaxial_plants.mat', 'G_vc', '-append'); #+end_src ** Sensitivity to Disturbances We load the dynamics when using a piezo-electric nano hexapod to compare the results. #+begin_src matlab - load('./uniaxial/mat/plants.mat', 'G'); + load('./mat/uniaxial_plants.mat', 'G'); #+end_src We show several plots representing the sensitivity to disturbances: @@ -2990,7 +2990,7 @@ We show several plots representing the sensitivity to disturbances: ** Noise Budget We first load the measured PSD of the disturbance. #+begin_src matlab - load('./disturbances/mat/dist_psd.mat', 'dist_f'); + load('./mat/disturbances_dist_psd.mat', 'dist_f'); #+end_src The effect of these disturbances on the distance $D$ is computed below. @@ -3125,13 +3125,13 @@ Let's initialize the system prior to identification. All the controllers are set to 0. #+begin_src matlab K = tf(0); - save('./mat/controllers.mat', 'K', '-append'); + save('./mat/controllers_uniaxial.mat', 'K', '-append'); K_iff = -K_iff; - save('./mat/controllers.mat', 'K_iff', '-append'); + save('./mat/controllers_uniaxial.mat', 'K_iff', '-append'); K_rmc = tf(0); - save('./mat/controllers.mat', 'K_rmc', '-append'); + save('./mat/controllers_uniaxial.mat', 'K_rmc', '-append'); K_dvf = tf(0); - save('./mat/controllers.mat', 'K_dvf', '-append'); + save('./mat/controllers_uniaxial.mat', 'K_dvf', '-append'); #+end_src #+begin_src matlab diff --git a/readme.org b/readme.org index cbb5521..2eefd7d 100644 --- a/readme.org +++ b/readme.org @@ -2,26 +2,5 @@ #+AUTHOR: Dehaeze Thomas #+EMAIL: dehaeze.thomas@gmail.com #+OPTIONS: num:nil toc:nil todo:nil -#+EXPORT_EXCLUDE_TAGS: exclude noexport The goal of this project is to study the Nano-Active-Stabilization-System concept using Matlab/Simscape. - -* Org Publish Configuration :noexport: -#+begin_src emacs-lisp :results none - (setq org-publish-project-alist - '(("nass-simscape" - :base-directory "~/Cloud/thesis/matlab/nass-simscape/org/" - :base-extension "org" - :publishing-directory "~/Cloud/thesis/matlab/nass-simscape/docs/" - :author "Dehaeze Thomas" - :email "dehaeze.thomas@gmail.com/" - :recursive nil - :publishing-function org-html-publish-to-html - :auto-preamble t - :auto-sitemap nil - :html-link-up "index.html" - :html-link-home "index.html" - :with-todo-keywords nil - :html-wrap-src-lines nil - :table-of-contents nil))) -#+end_src diff --git a/src/initializeController.m b/src/initializeController.m index b5f39d2..34a229e 100644 --- a/src/initializeController.m +++ b/src/initializeController.m @@ -1,8 +1,8 @@ function [] = initializeController(args) arguments - args.type char {mustBeMember(args.type,{'open-loop', 'iff', 'dvf'})} = 'open-loop' - args.K (6,6) = ss(zeros(6, 6)) + args.type char {mustBeMember(args.type,{'open-loop', 'iff', 'dvf', 'hac-dvf'})} = 'open-loop' + args.K (6,6) = ss(zeros(6, 6)) end controller = struct(); @@ -14,6 +14,8 @@ switch args.type controller.type = 2; case 'iff' controller.type = 3; + case 'hac-dvf' + controller.type = 4; end controller.K = args.K; diff --git a/src/initializeDisturbances.m b/src/initializeDisturbances.m index 9f5b6c1..5075a1d 100644 --- a/src/initializeDisturbances.m +++ b/src/initializeDisturbances.m @@ -23,7 +23,7 @@ arguments args.Frz_z logical {mustBeNumericOrLogical} = true end -load('./disturbances/mat/dist_psd.mat', 'dist_f'); +load('./mat/dist_psd.mat', 'dist_f'); dist_f.f = dist_f.f(2:end); dist_f.psd_gm = dist_f.psd_gm(2:end); diff --git a/src/initializeGround.m b/src/initializeGround.m index 3e0d3d4..d9c4f2a 100644 --- a/src/initializeGround.m +++ b/src/initializeGround.m @@ -1,7 +1,8 @@ function [ground] = initializeGround(args) arguments - args.type char {mustBeMember(args.type,{'none', 'rigid'})} = 'rigid' + args.type char {mustBeMember(args.type,{'none', 'rigid'})} = 'rigid' + args.rot_point (3,1) double {mustBeNumeric} = zeros(3,1) % Rotation point for the ground motion [m] end ground = struct(); @@ -16,4 +17,6 @@ end ground.shape = [2, 2, 0.5]; % [m] ground.density = 2800; % [kg/m3] +ground.rot_point = args.rot_point; + save('./mat/stages.mat', 'ground', '-append');