diff --git a/experiment_tomography/index.html b/experiment_tomography/index.html index 89cb126..029e490 100644 --- a/experiment_tomography/index.html +++ b/experiment_tomography/index.html @@ -3,7 +3,7 @@ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> - + Tomography Experiment @@ -193,6 +193,13 @@ .org-svg { width: 90%; } /*]]>*/--> + + + + + + + - -
@@ -273,378 +258,162 @@ for the JavaScript code in this tag.

Table of Contents

-
-

1 Initialize Experiment

+
+

1 Simscape Model

+

+The simulink file to do tomography experiments is sim_nano_station_tomo.slx. +

+
+
open('experiment_tomography/matlab/sim_nano_station_tomo.slx')
+
+
+ +

+We load the shared simulink configuration and we set a small StopTime. +

+
+
load('mat/conf_simscape.mat');
+set_param(conf_simscape, 'StopTime', '10');
+
+
+

We first initialize all the stages.

-
initializeGround();
-initializeGranite();
-initializeTy();
-initializeRy();
-initializeRz();
-initializeMicroHexapod();
-initializeAxisc();
-initializeMirror();
-initializeNanoHexapod(struct('actuator', 'piezo'));
-initializeSample(struct('mass', 1));
+
initializeGround();
+initializeGranite();
+initializeTy();
+initializeRy();
+initializeRz();
+initializeMicroHexapod();
+initializeAxisc();
+initializeMirror();
+initializeNanoHexapod(struct('actuator', 'piezo'));
+initializeSample(struct('mass', 1));
 

We initialize the reference path for all the stages. +All stage is set to its zero position except the Spindle which is rotating at 60rpm.

-
initializeReferences(struct('Rz_type', 'rotating', 'Rz_period', 1));
-
-
- -

-And we initialize the disturbances. -

-
-
initDisturbances();
+
initializeReferences(struct('Rz_type', 'rotating', 'Rz_period', 1));
 
-
-

2 Run the Tomography Experiment

+
+

2 Tomography Experiment with no disturbances

-We first load the simulation configuration +And we initialize the disturbances to zero.

-
load('simscape/conf_simscape.mat');
+
opts = struct(...
+    'Dwx', false, ... % Ground Motion - X direction
+    'Dwy', false, ... % Ground Motion - Y direction
+    'Dwz', false, ... % Ground Motion - Z direction
+    'Fty_x', false, ... % Translation Stage - X direction
+    'Fty_z', false, ... % Translation Stage - Z direction
+    'Frz_z', false  ... % Spindle - Z direction
+);
+initDisturbances(opts);
 
-
set_param(conf_simscape, 'StopTime', '1');
+
sim('sim_nano_station_tomo')
 
-
set_param('sim_nano_station_tomo', 'SimulationCommand', 'start');
+
Dsm_without_dist = Dsm;
 
+ +
+
figure;
+hold on;
+plot(Dsm_without_dist.x.Time, Dsm_without_dist.x.Data, 'DisplayName', 'x')
+plot(Dsm_without_dist.y.Time, Dsm_without_dist.y.Data, 'DisplayName', 'y')
+plot(Dsm_without_dist.z.Time, Dsm_without_dist.z.Data, 'DisplayName', 'z')
+hold off;
+xlim([2, inf]);
+legend('location', 'northeast');
+
+
+ + +
+

exp_tomo_without_dist_trans.png +

+

Figure 1: X-Y-Z translation of the sample w.r.t. granite when performing tomography experiment with no disturbances (png, pdf)

+
+ + +

+Rotations. +Think of the good way to plot these rotations with respect to time. +

-
-

3 TODO Tests on the transformation from reference to wanted position

+
+

3 With Perturbations

-
    -
  • [X] Are the rotation matrix commutable? => no
  • -
  • [X] How to express the measured rotation errors? => screw axis coordinate seems nice (used in Taghirad's book)
  • -
  • [ ] Should ask Veijo how he specifies the position of the Symetrie Hexapod
  • -
  • [ ] Create functions for all distinct part and then include that in Simulink
  • -
  • [ ] How the express the orientation error?
  • -
  • [ ] If we use screw coordinate, can we add/subtract them?
  • -
  • [ ] Do some simple tests to verify that the algorithm is working fine
  • -
- -
-

-Rx = [1 0 0; - 0 cos(t) -sin(t); - 0 sin(t) cos(t)]; -

- -

-Ry = [ cos(t) 0 sin(t); - 0 1 0; - -sin(t) 0 cos(t)]; -

- -

-Rz = [cos(t) -sin(t) 0; - sin(t) cos(t) 0; - 0 0 1]; -

-
- -

-Let's define the following frames: -

-
    -
  • \(\{W\}\) the frame that is fixed to the granite and its origin at the theoretical meeting point between the X-ray and the spindle axis.
  • -
  • \(\{S\}\) the frame attached to the sample (in reality attached to the top platform of the nano-hexapod) with its origin at 175mm above the top platform of the nano-hexapod. -Its origin is \(O_S\).
  • -
  • \(\{T\}\) the theoretical wanted frame that correspond to the wanted pose of the frame \(\{S\}\). -\(\{T\}\) is computed from the wanted position of each stage. It is thus theoretical and does not correspond to a real position. -The origin of \(T\) is \(O_T\) and is the wanted position of the sample.
  • -
- -

-Thus: -

-
    -
  • the measurement of the position of the sample corresponds to \({}^W O_S = \begin{bmatrix} {}^WP_{x,m} & {}^WP_{y,m} & {}^WP_{z,m} \end{bmatrix}^T\) in translation and to \(\theta_m {}^W\bm{s}_m = \theta_m \cdot \begin{bmatrix} {}^Ws_{x,m} & {}^Ws_{y,m} & {}^Ws_{z,m} \end{bmatrix}^T\) in rotations
  • -
  • the wanted position of the sample expressed w.r.t. the granite is \({}^W O_T = \begin{bmatrix} {}^WP_{x,r} & {}^WP_{y,r} & {}^WP_{z,r} \end{bmatrix}^T\) in translation and to \(\theta_r {}^W\bm{s}_r = \theta_r \cdot \begin{bmatrix} {}^Ws_{x,r} & {}^Ws_{y,r} & {}^Ws_{z,r} \end{bmatrix}^T\) in rotations
  • -
-
- -
-

3.1 Wanted Position of the Sample with respect to the Granite

-
-

-Let's define the wanted position of each stage. -

-
Ty = 1; % [m]
-Ry = 3*pi/180; % [rad]
-Rz = 180*pi/180; % [rad]
-
-% Hexapod (first consider only translations)
-Thx = 0; % [m]
-Thy = 0; % [m]
-Thz = 0; % [m]
-
-
- -

-Now, we compute the corresponding wanted translation and rotation of the sample with respect to the granite frame \(\{W\}\). -This corresponds to \({}^WO_T\) and \(\theta_m {}^Ws_m\). -

- -

-To do so, we have to define the homogeneous transformation for each stage. -

-
-
% Translation Stage
-Rty = [1 0 0 0;
-       0 1 0 Ty;
-       0 0 1 0;
-       0 0 0 1];
-
-% Tilt Stage - Pure rotating aligned with Ob
-Rry = [ cos(Ry) 0 sin(Ry) 0;
-        0       1 0       0;
-       -sin(Ry) 0 cos(Ry) 0;
-        0       0 0       1];
-
-% Spindle - Rotation along the Z axis
-Rrz = [cos(Rz) -sin(Rz) 0 0 ;
-       sin(Rz)  cos(Rz) 0 0 ;
-       0        0       1 0 ;
-       0        0       0 1 ];
-
-% Micro-Hexapod (only rotations first)
-Rh = [1 0 0 Thx ;
-      0 1 0 Thy ;
-      0 0 1 Thz ;
-      0 0 0 1 ];
-
-
- -

-We combine the individual homogeneous transformations into one homogeneous transformation for all the station. -

-
-
Ttot = Rty*Rry*Rrz*Rh;
-
-
- -

-Using this homogeneous transformation, we can compute the wanted position and orientation of the sample with respect to the granite. -

-
-
WOr = Ttot*[0;0;0;1];
-WOr = WOr(1:3);
+
opts = struct(...
+    'Dwx', true, ... % Ground Motion - X direction
+    'Dwy', true, ... % Ground Motion - Y direction
+    'Dwz', true, ... % Ground Motion - Z direction
+    'Fty_x', true, ... % Translation Stage - X direction
+    'Fty_z', true, ... % Translation Stage - Z direction
+    'Frz_z', true  ... % Spindle - Z direction
+);
+initDisturbances(opts);
 
-
thetar = acos((trace(Ttot(1:3, 1:3))-1)/2)
-if thetar == 0
-  WSr = [0; 0; 0];
-else
-  [V, D] = eig(Ttot(1:3, 1:3));
-  WSr = thetar*V(:, abs(diag(D) - 1) < eps(1));
-end
+
sim('sim_nano_station_tomo')
 
-
WPr = [WOr ; WSr];
-
-
-
-
- -
-

3.2 Measured Position of the Sample with respect to the Granite

-
-

-The measurement of the position of the sample using the metrology system gives the position and orientation of the sample with respect to the granite. -

-
-
% Measurements: Xm, Ym, Zm, Rx, Ry, Rz
-Dxm = 0; % [m]
-Dym = 1; % [m]
-Dzm = 0; % [m]
-
-Rxm = 0*pi/180; % [rad]
-Rym = 3*pi/180; % [rad]
-Rzm = 0*pi/180; % [rad]
+
figure;
+hold on;
+plot(Dsm.x.Time, Dsm.x.Data, 'DisplayName', 'x')
+plot(Dsm.y.Time, Dsm.y.Data, 'DisplayName', 'y')
+plot(Dsm.z.Time, Dsm.z.Data, 'DisplayName', 'z')
+hold off;
+xlim([2, inf]);
+legend('location', 'northeast');
 
-

-Let's compute the corresponding orientation using screw axis. + +

+

exp_tomo_dist_trans.png

-
-
Trxm = [1 0         0;
-        0 cos(Rxm) -sin(Rxm);
-        0 sin(Rxm)  cos(Rxm)];
-Trym = [ cos(Rym) 0 sin(Rym);
-         0        1 0;
-        -sin(Rym) 0 cos(Rym)];
-Trzm = [cos(Rzm) -sin(Rzm) 0;
-        sin(Rzm)  cos(Rzm) 0;
-        0         0        1];
-
-STw = [[ Trym*Trxm*Trzm , [Dxm; Dym; Dzm]]; 0 0 0 1];
-
-
- -

-We then obtain the orientation measurement in the form of screw coordinate \(\theta_m ({}^Ws_{x,m},\ {}^Ws_{y,m},\ {}^Ws_{z,m})^T\) where: -

-
    -
  • \(\theta_m = \cos^{-1} \frac{\text{Tr}(R) - 1}{2}\)
  • -
  • \({}^W\bm{s}_m\) is the eigen vector of the rotation matrix \(R\) corresponding to the eigen value \(\lambda = 1\)
  • -
- -
-
thetam = acos((trace(STw(1:3, 1:3))-1)/2); % [rad]
-if thetam == 0
-  WSm = [0; 0; 0];
-else
-  [V, D] = eig(STw(1:3, 1:3));
-  WSm = thetam*V(:, abs(diag(D) - 1) < eps(1));
-end
-
-
- -
-
WPm = [Dxm ; Dym ; Dzm ; WSm];
-
-
-
-
- -
-

3.3 Positioning Error with respect to the Granite

-
-

-The wanted position expressed with respect to the granite is \({}^WO_T\) and the measured position with respect to the granite is \({}^WO_S\), thus the position error expressed in \(\{W\}\) is -\[ {}^W E = {}^W O_T - {}^W O_S \] -The same is true for rotations: -\[ \theta_\epsilon {}^W\bm{s}_\epsilon = \theta_r {}^W\bm{s}_r - \theta_m {}^W\bm{s}_m \] -

- -
-
WPe = WPr - WPm;
-
-
- -
-

-Now we want to express this error in a frame attached to the base of the nano-hexapod with its origin at the same point where the Jacobian of the nano-hexapod is computed (175mm above the top platform + 90mm of total height of the nano-hexapod). -

- -

-Or maybe should we want to express this error with respect to the top platform of the nano-hexapod? -We are measuring the position of the top-platform, and we don't know exactly the position of the bottom platform. -We could compute the position of the bottom platform in two ways: -

-
    -
  • from the encoders of each stage
  • -
  • from the measurement of the nano-hexapod top platform + the internal metrology in the nano-hexapod (capacitive sensors e.g)
  • -
- -

-A third option is to say that the maximum stroke of the nano-hexapod is so small that the error should no change to much by the change of base. -

-
-
-
- -
-

3.4 Position Error Expressed in the Nano-Hexapod Frame

-
-

-We now want the position error to be expressed in \(\{S\}\) (the frame attach to the sample): -\[ {}^S E = {}^S T_W \cdot {}^W E \] -

- -

-Thus we need to compute the homogeneous transformation \({}^ST_W\). -Fortunately, this homogeneous transformation can be computed from the measurement of the sample position and orientation with respect to the granite. -

-
-
Trxm = [1 0         0;
-        0 cos(Rxm) -sin(Rxm);
-        0 sin(Rxm)  cos(Rxm)];
-Trym = [ cos(Rym) 0 sin(Rym);
-         0        1 0;
-        -sin(Rym) 0 cos(Rym)];
-Trzm = [cos(Rzm) -sin(Rzm) 0;
-        sin(Rzm)  cos(Rzm) 0;
-        0         0        1];
-
-STw = [[ Trym*Trxm*Trzm , [Dxm; Dym; Dzm]]; 0 0 0 1];
-
-
- -

-Translation Error. -

-
-
SEm = STw * [WPe(1:3); 1];
-SEm = SEm(1:3);
-
-
- -

-Rotation Error. -

-
-
SEr = STw * [WPe(4:6); 0];
-SEr = SEr(1:3);
-
-
- -
-
Etot = [SEm ; SEr]
-
-
+

Figure 2: X-Y-Z translation of the sample w.r.t. the granite when performing tomography experiment with disturbances (png, pdf)

Author: Dehaeze Thomas

-

Created: 2019-12-04 mer. 21:55

+

Created: 2019-12-13 ven. 19:06

Validate

diff --git a/experiment_tomography/index.org b/experiment_tomography/index.org index da072a1..29ed521 100644 --- a/experiment_tomography/index.org +++ b/experiment_tomography/index.org @@ -9,13 +9,13 @@ #+HTML_LINK_HOME: ../index.html #+HTML_LINK_UP: ../index.html -# #+HTML_HEAD: -# #+HTML_HEAD: -# #+HTML_HEAD: -# #+HTML_HEAD: -# #+HTML_HEAD: -# #+HTML_HEAD: -# #+HTML_HEAD: +#+HTML_HEAD: +#+HTML_HEAD: +#+HTML_HEAD: +#+HTML_HEAD: +#+HTML_HEAD: +#+HTML_HEAD: +#+HTML_HEAD: #+HTML_MATHJAX: align: center tagside: right font: TeX @@ -41,6 +41,7 @@ #+PROPERTY: header-args:latex+ :output-dir figs :END: +* 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) <> @@ -54,11 +55,18 @@ simulinkproject('../'); #+end_src +* Simscape Model +The simulink file to do tomography experiments is =sim_nano_station_tomo.slx=. #+begin_src matlab open('experiment_tomography/matlab/sim_nano_station_tomo.slx') #+end_src -* Initialize Experiment +We load the shared simulink configuration and we set a small =StopTime=. +#+begin_src matlab + load('mat/conf_simscape.mat'); + set_param(conf_simscape, 'StopTime', '10'); +#+end_src + We first initialize all the stages. #+begin_src matlab initializeGround(); @@ -74,38 +82,98 @@ We first initialize all the stages. #+end_src We initialize the reference path for all the stages. +All stage is set to its zero position except the Spindle which is rotating at 60rpm. #+begin_src matlab initializeReferences(struct('Rz_type', 'rotating', 'Rz_period', 1)); #+end_src -And we initialize the disturbances. +* Tomography Experiment with no disturbances +And we initialize the disturbances to zero. #+begin_src matlab - initDisturbances(); -#+end_src - -* Run the Tomography Experiment -We first load the simulation configuration -#+begin_src matlab - load('mat/conf_simscape.mat'); + opts = struct(... + 'Dwx', false, ... % Ground Motion - X direction + 'Dwy', false, ... % Ground Motion - Y direction + 'Dwz', false, ... % Ground Motion - Z direction + 'Fty_x', false, ... % Translation Stage - X direction + 'Fty_z', false, ... % Translation Stage - Z direction + 'Frz_z', false ... % Spindle - Z direction + ); + initDisturbances(opts); #+end_src #+begin_src matlab - set_param(conf_simscape, 'StopTime', '1'); + sim('sim_nano_station_tomo') #+end_src #+begin_src matlab - set_param('sim_nano_station_tomo', 'SimulationCommand', 'start'); + Dsm_without_dist = Dsm; #+end_src -* TODO Tests on the transformation from reference to wanted position -- [X] Are the rotation matrix commutable? => no -- [X] How to express the measured rotation errors? => screw axis coordinate seems nice (used in Taghirad's book) -- [ ] Should ask Veijo how he specifies the position of the Symetrie Hexapod -- [ ] Create functions for all distinct part and then include that in Simulink -- [ ] How the express the orientation error? -- [ ] If we use screw coordinate, can we add/subtract them? -- [ ] Do some simple tests to verify that the algorithm is working fine +#+begin_src matlab + figure; + hold on; + plot(Dsm_without_dist.x.Time, Dsm_without_dist.x.Data, 'DisplayName', 'x') + plot(Dsm_without_dist.y.Time, Dsm_without_dist.y.Data, 'DisplayName', 'y') + plot(Dsm_without_dist.z.Time, Dsm_without_dist.z.Data, 'DisplayName', 'z') + hold off; + xlim([2, inf]); + legend('location', 'northeast'); +#+end_src +#+HEADER: :tangle no :exports results :results none :noweb yes +#+begin_src matlab :var filepath="figs/exp_tomo_without_dist_trans.pdf" :var figsize="wide-normal" :post pdf2svg(file=*this*, ext="png") + <> +#+end_src + +#+NAME: fig:exp_tomo_without_dist_trans +#+CAPTION: X-Y-Z translation of the sample w.r.t. granite when performing tomography experiment with no disturbances ([[./figs/exp_tomo_without_dist_trans.png][png]], [[./figs/exp_tomo_without_dist_trans.pdf][pdf]]) +[[file:figs/exp_tomo_without_dist_trans.png]] + + +Rotations. +Think of the good way to plot these rotations with respect to time. + +* With Perturbations +#+begin_src matlab + opts = struct(... + 'Dwx', true, ... % Ground Motion - X direction + 'Dwy', true, ... % Ground Motion - Y direction + 'Dwz', true, ... % Ground Motion - Z direction + 'Fty_x', true, ... % Translation Stage - X direction + 'Fty_z', true, ... % Translation Stage - Z direction + 'Frz_z', true ... % Spindle - Z direction + ); + initDisturbances(opts); +#+end_src + +#+begin_src matlab + sim('sim_nano_station_tomo') +#+end_src + +#+begin_src matlab + figure; + hold on; + plot(Dsm.x.Time, Dsm.x.Data, 'DisplayName', 'x') + plot(Dsm.y.Time, Dsm.y.Data, 'DisplayName', 'y') + plot(Dsm.z.Time, Dsm.z.Data, 'DisplayName', 'z') + hold off; + xlim([2, inf]); + legend('location', 'northeast'); +#+end_src + +#+HEADER: :tangle no :exports results :results none :noweb yes +#+begin_src matlab :var filepath="figs/exp_tomo_dist_trans.pdf" :var figsize="wide-tall" :post pdf2svg(file=*this*, ext="png") + <> +#+end_src + +#+NAME: fig:exp_tomo_dist_trans +#+CAPTION: X-Y-Z translation of the sample w.r.t. the granite when performing tomography experiment with disturbances ([[./figs/exp_tomo_dist_trans.png][png]], [[./figs/exp_tomo_dist_trans.pdf][pdf]]) +[[file:figs/exp_tomo_dist_trans.png]] + +* TODO Tests on the transformation from reference to wanted position :noexport: +:PROPERTIES: +:header-args:matlab+: :eval no +:END: ** Introduction :ignore: #+begin_quote Rx = [1 0 0; diff --git a/experiment_tomography/matlab/sim_nano_station_tomo.slx b/experiment_tomography/matlab/sim_nano_station_tomo.slx index 24cd82a..e8b64d0 100644 Binary files a/experiment_tomography/matlab/sim_nano_station_tomo.slx and b/experiment_tomography/matlab/sim_nano_station_tomo.slx differ diff --git a/figs/exp_tomo_dist_trans.png b/figs/exp_tomo_dist_trans.png new file mode 100644 index 0000000..50a8950 Binary files /dev/null and b/figs/exp_tomo_dist_trans.png differ diff --git a/figs/exp_tomo_without_dist_trans.png b/figs/exp_tomo_without_dist_trans.png new file mode 100644 index 0000000..87dbbc5 Binary files /dev/null and b/figs/exp_tomo_without_dist_trans.png differ diff --git a/functions/index.org b/functions/index.org index 07299a0..5e9ebeb 100644 --- a/functions/index.org +++ b/functions/index.org @@ -43,7 +43,7 @@ * Functions <> -** computePsdDispl +** TODO computePsdDispl :PROPERTIES: :header-args:matlab+: :tangle ../src/computePsdDispl.m :header-args:matlab+: :comments none :mkdirp yes :eval no @@ -78,7 +78,7 @@ This Matlab function is accessible [[file:../src/computePsdDispl.m][here]]. end #+end_src -** computeSetpoint +** TODO computeSetpoint :PROPERTIES: :header-args:matlab+: :tangle ../src/computeSetpoint.m :header-args:matlab+: :comments none :mkdirp yes :eval no @@ -149,7 +149,7 @@ This Matlab function is accessible [[file:../src/computeSetpoint.m][here]]. end #+end_src -** converErrorBasis +** TODO converErrorBasis :PROPERTIES: :header-args:matlab+: :tangle ../src/converErrorBasis.m :header-args:matlab+: :comments none :mkdirp yes :eval no @@ -286,127 +286,6 @@ This Matlab function is accessible [[file:../src/converErrorBasis.m][here]]. end #+end_src -** generateDiagPidControl -:PROPERTIES: -:header-args:matlab+: :tangle ../src/generateDiagPidControl.m -:header-args:matlab+: :comments none :mkdirp yes :eval no -:END: -<> - -This Matlab function is accessible [[file:../src/generateDiagPidControl.m][here]]. - -#+begin_src matlab - function [K] = generateDiagPidControl(G, fs) - %% - pid_opts = pidtuneOptions(... - 'PhaseMargin', 50, ... - 'DesignFocus', 'disturbance-rejection'); - - %% - K = tf(zeros(6)); - - for i = 1:6 - input_name = G.InputName(i); - output_name = G.OutputName(i); - K(i, i) = tf(pidtune(minreal(G(output_name, input_name)), 'PIDF', 2*pi*fs, pid_opts)); - end - - K.InputName = G.OutputName; - K.OutputName = G.InputName; - end -#+end_src - -** identifyPlant -:PROPERTIES: -:header-args:matlab+: :tangle ../src/identifyPlant.m -:header-args:matlab+: :comments none :mkdirp yes :eval no -:END: -<> - -This Matlab function is accessible [[file:../src/identifyPlant.m][here]]. - -#+begin_src matlab - function [sys] = identifyPlant(opts_param) - %% Default values for opts - opts = struct(); - - %% Populate opts with input parameters - if exist('opts_param','var') - for opt = fieldnames(opts_param)' - opts.(opt{1}) = opts_param.(opt{1}); - end - end - - %% Options for Linearized - options = linearizeOptions; - options.SampleTime = 0; - - %% Name of the Simulink File - mdl = 'sim_nano_station_id'; - - %% Input/Output definition - io(1) = linio([mdl, '/Fn'], 1, 'input'); % Cartesian forces applied by NASS - io(2) = linio([mdl, '/Dw'], 1, 'input'); % Ground Motion - io(3) = linio([mdl, '/Fs'], 1, 'input'); % External forces on the sample - io(4) = linio([mdl, '/Fnl'], 1, 'input'); % Forces applied on the NASS's legs - io(5) = linio([mdl, '/Fd'], 1, 'input'); % Disturbance Forces - io(6) = linio([mdl, '/Dsm'], 1, 'output'); % Displacement of the sample - io(7) = linio([mdl, '/Fnlm'], 1, 'output'); % Force sensor in NASS's legs - io(8) = linio([mdl, '/Dnlm'], 1, 'output'); % Displacement of NASS's legs - io(9) = linio([mdl, '/Es'], 1, 'output'); % Position Error w.r.t. NASS base - io(10) = linio([mdl, '/Vlm'], 1, 'output'); % Measured absolute velocity of the legs - - %% Run the linearization - G = linearize(mdl, io, options); - G.InputName = {'Fnx', 'Fny', 'Fnz', 'Mnx', 'Mny', 'Mnz', ... - 'Dgx', 'Dgy', 'Dgz', ... - 'Fsx', 'Fsy', 'Fsz', 'Msx', 'Msy', 'Msz', ... - 'F1', 'F2', 'F3', 'F4', 'F5', 'F6', ... - 'Frzz', 'Ftyx', 'Ftyz'}; - G.OutputName = {'Dx', 'Dy', 'Dz', 'Rx', 'Ry', 'Rz', ... - 'Fm1', 'Fm2', 'Fm3', 'Fm4', 'Fm5', 'Fm6', ... - 'Dm1', 'Dm2', 'Dm3', 'Dm4', 'Dm5', 'Dm6', ... - 'Edx', 'Edy', 'Edz', 'Erx', 'Ery', 'Erz', ... - 'Vm1', 'Vm2', 'Vm3', 'Vm4', 'Vm5', 'Vm6'}; - - %% Create the sub transfer functions - minreal_tol = sqrt(eps); - % From forces applied in the cartesian frame to displacement of the sample in the cartesian frame - sys.G_cart = minreal(G({'Dx', 'Dy', 'Dz', 'Rx', 'Ry', 'Rz'}, {'Fnx', 'Fny', 'Fnz', 'Mnx', 'Mny', 'Mnz'}), minreal_tol, false); - % From ground motion to Sample displacement - sys.G_gm = minreal(G({'Dx', 'Dy', 'Dz', 'Rx', 'Ry', 'Rz'}, {'Dgx', 'Dgy', 'Dgz'}), minreal_tol, false); - % From direct forces applied on the sample to displacement of the sample - sys.G_fs = minreal(G({'Dx', 'Dy', 'Dz', 'Rx', 'Ry', 'Rz'}, {'Fsx', 'Fsy', 'Fsz', 'Msx', 'Msy', 'Msz'}), minreal_tol, false); - % From forces applied on NASS's legs to force sensor in each leg - sys.G_iff = minreal(G({'Fm1', 'Fm2', 'Fm3', 'Fm4', 'Fm5', 'Fm6'}, {'F1', 'F2', 'F3', 'F4', 'F5', 'F6'}), minreal_tol, false); - % From forces applied on NASS's legs to displacement of each leg - sys.G_dleg = minreal(G({'Dm1', 'Dm2', 'Dm3', 'Dm4', 'Dm5', 'Dm6'}, {'F1', 'F2', 'F3', 'F4', 'F5', 'F6'}), minreal_tol, false); - % From forces/torques applied by the NASS to position error - sys.G_plant = minreal(G({'Edx', 'Edy', 'Edz', 'Erx', 'Ery', 'Erz'}, {'Fnx', 'Fny', 'Fnz', 'Mnx', 'Mny', 'Mnz'}), minreal_tol, false); - % From forces/torques applied by the NASS to velocity of the actuator - sys.G_geoph = minreal(G({'Vm1', 'Vm2', 'Vm3', 'Vm4', 'Vm5', 'Vm6'}, {'F1', 'F2', 'F3', 'F4', 'F5', 'F6'}), minreal_tol, false); - % From various disturbance forces to position error - sys.G_dist = minreal(G({'Dx', 'Dy', 'Dz', 'Rx', 'Ry', 'Rz'}, {'Frzz', 'Ftyx', 'Ftyz'}), minreal_tol, false); - - %% We remove low frequency and high frequency dynamics that are usually unstable - % using =freqsep= is risky as it may change the shape of the transfer functions - % f_min = 0.1; % [Hz] - % f_max = 1e4; % [Hz] - - % [~, sys.G_cart] = freqsep(freqsep(sys.G_cart, 2*pi*f_max), 2*pi*f_min); - % [~, sys.G_gm] = freqsep(freqsep(sys.G_gm, 2*pi*f_max), 2*pi*f_min); - % [~, sys.G_fs] = freqsep(freqsep(sys.G_fs, 2*pi*f_max), 2*pi*f_min); - % [~, sys.G_iff] = freqsep(freqsep(sys.G_iff, 2*pi*f_max), 2*pi*f_min); - % [~, sys.G_dleg] = freqsep(freqsep(sys.G_dleg, 2*pi*f_max), 2*pi*f_min); - % [~, sys.G_plant] = freqsep(freqsep(sys.G_plant, 2*pi*f_max), 2*pi*f_min); - - %% We finally verify that the system is stable - if ~isstable(sys.G_cart) || ~isstable(sys.G_gm) || ~isstable(sys.G_fs) || ~isstable(sys.G_iff) || ~isstable(sys.G_dleg) || ~isstable(sys.G_plant) - warning('One of the identified system is unstable'); - end - end -#+end_src - ** Inverse Kinematics of the Hexapod :PROPERTIES: :header-args:matlab+: :tangle ../src/inverseKinematicsHexapod.m diff --git a/index.html b/index.html index 7be9ac2..cb88a3d 100644 --- a/index.html +++ b/index.html @@ -3,7 +3,7 @@ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> - + Simscape Model of the Nano-Active-Stabilization-System @@ -258,16 +258,17 @@ for the JavaScript code in this tag.

Table of Contents

@@ -276,8 +277,8 @@ for the JavaScript code in this tag. Here are links to the documents related to the Simscape model of the Nano-Active-Stabilization-System.

-
-

1 Simulink Project (link)

+
+

1 Simulink Project (link)

The project is managed with a Simulink Project. @@ -286,8 +287,8 @@ Such project is briefly presented here

-
-

2 Simscape Model (link)

+
+

2 Simscape Model (link)

The model of the NASS is based on Simulink and Simscape Multi-Body. @@ -296,8 +297,8 @@ Such toolbox is presented here.

-
-

3 Simscape Subsystems (link)

+
+

3 Simscape Subsystems (link)

The model is decomposed of multiple subsystems. @@ -311,8 +312,8 @@ All these subsystems are described he

-
-

4 Kinematics of the Station (link)

+
+

4 Kinematics of the Station (link)

First, we consider perfectly rigid elements and joints and we just study the kinematic of the station. @@ -322,8 +323,8 @@ This is detailed here.

-
-

5 Metrology (link)

+
+

5 Metrology (link)

In this document (accessible here), we discuss the measurement of the sample with respect to the granite. @@ -331,8 +332,8 @@ In this document (accessible here), we disc

-
-

6 Computation of the positioning error of the Sample (link)

+
+

6 Computation of the positioning error of the Sample (link)

From the measurement of the position of the sample with respect to the granite and from the wanted position of each stage, we can compute the positioning error of the sample with respect to the nano-hexapod. @@ -341,8 +342,8 @@ This is done here.

-
-

7 Tuning of the Dynamics of the Simscape model (link)

+
+

7 Tuning of the Dynamics of the Simscape model (link)

From dynamical measurements perform on the real positioning station, we tune the parameters of the simscape model to have similar dynamics. @@ -354,8 +355,8 @@ This is explained here.

-
-

8 Disturbances (link)

+
+

8 Disturbances (link)

The effect of disturbances on the position of the micro-station have been measured. @@ -372,8 +373,8 @@ We also discuss how the disturbances are implemented in the model.

-
-

9 Tomography Experiment (link)

+
+

9 Tomography Experiment (link)

Now that the dynamics of the Model have been tuned and the Disturbances have included, we can simulate experiments. @@ -385,10 +386,19 @@ Tomography experiments are simulated and the results are presented -

10 Useful Matlab Functions (link)

+
+

10 Active Damping Techniques (link)

+Active damping techniques are applied to the Simscape model. +

+
+
+ +
+

11 Useful Matlab Functions (link)

+
+

Many matlab functions are shared among all the files of the projects.

@@ -400,7 +410,7 @@ These functions are all defined here.

Author: Dehaeze Thomas

-

Created: 2019-12-12 jeu. 11:35

+

Created: 2019-12-13 ven. 17:55

Validate

diff --git a/index.org b/index.org index 8a2ac1c..b68e6b0 100644 --- a/index.org +++ b/index.org @@ -88,6 +88,9 @@ Now that the dynamics of the Model have been tuned and the Disturbances have inc Tomography experiments are simulated and the results are presented [[./experiment_tomography/index.org][here]]. +* Active Damping Techniques ([[./active_damping/index.org][link]]) +Active damping techniques are applied to the Simscape model. + * Useful Matlab Functions ([[./functions/index.org][link]]) Many matlab functions are shared among all the files of the projects. diff --git a/mat/nass_disturbances.mat b/mat/nass_disturbances.mat index 19fa786..dd9205c 100644 Binary files a/mat/nass_disturbances.mat and b/mat/nass_disturbances.mat differ diff --git a/mat/nass_references.mat b/mat/nass_references.mat index 7bd4d15..abd3fe4 100644 Binary files a/mat/nass_references.mat and b/mat/nass_references.mat differ diff --git a/mat/stages.mat b/mat/stages.mat index aba72d8..3a798fa 100644 Binary files a/mat/stages.mat and b/mat/stages.mat differ diff --git a/simscape_subsystems/index.org b/simscape_subsystems/index.org index e2c432a..f956a96 100644 --- a/simscape_subsystems/index.org +++ b/simscape_subsystems/index.org @@ -122,7 +122,7 @@ This Matlab function is accessible [[file:../src/initializeInputs.m][here]]. Ry = struct('time', t, 'signals', struct('values', Ry)); %% Spindle - Rz - t = 0:Ts:opts.Rz_period-Ts; + t = 0:Ts:100*opts.Rz_period-Ts; Rz = zeros(length(t), 1); switch opts.Rz_type @@ -192,7 +192,7 @@ This Matlab function is accessible [[file:../src/initializeInputs.m][here]]. end #+end_src -** Function that initialize the disturbances +** Initialize Disturbances :PROPERTIES: :header-args:matlab+: :tangle ../src/initDisturbances.m :header-args:matlab+: :comments none :mkdirp yes @@ -202,6 +202,7 @@ This Matlab function is accessible [[file:../src/initializeInputs.m][here]]. This Matlab function is accessible [[file:src/initDisturbances.m][here]]. +*** Function Declaration and Documentation #+begin_src matlab function [] = initDisturbances(opts_param) % initDisturbances - Initialize the disturbances @@ -216,7 +217,14 @@ This Matlab function is accessible [[file:src/initDisturbances.m][here]]. *** Default values for the Options #+begin_src matlab %% Default values for opts - opts = struct(); + opts = struct(... + 'Dwx', true, ... % Ground Motion - X direction + 'Dwy', true, ... % Ground Motion - Y direction + 'Dwz', true, ... % Ground Motion - Z direction + 'Fty_x', true, ... % Translation Stage - X direction + 'Fty_z', true, ... % Translation Stage - Z direction + 'Frz_z', true ... % Spindle - Z direction + ); %% Populate opts with input parameters if exist('opts_param','var') @@ -258,64 +266,93 @@ We define some parameters that will be used in the algorithm. for i = 1:N/2 C(i) = sqrt(phi(i)*df); end - theta = 2*pi*rand(N/2,1); % Generate random phase [rad] - Cx = [0 ; C.*complex(cos(theta),sin(theta))]; - Cx = [Cx; flipud(conj(Cx(2:end)))];; - u = N/sqrt(2)*ifft(Cx); % Ground Motion - x direction [m] - % Dwx = struct('time', t, 'signals', struct('values', u)); - Dwx = u; - theta = 2*pi*rand(N/2,1); % Generate random phase [rad] - Cx = [0 ; C.*complex(cos(theta),sin(theta))]; - Cx = [Cx; flipud(conj(Cx(2:end)))];; - u = N/sqrt(2)*ifft(Cx); % Ground Motion - y direction [m] - Dwy = u; - theta = 2*pi*rand(N/2,1); % Generate random phase [rad] - Cx = [0 ; C.*complex(cos(theta),sin(theta))]; - Cx = [Cx; flipud(conj(Cx(2:end)))];; - u = N/sqrt(2)*ifft(Cx); % Ground Motion - z direction [m] - Dwz = u; +#+end_src + +#+begin_src matlab + if opts.Dwx + theta = 2*pi*rand(N/2,1); % Generate random phase [rad] + Cx = [0 ; C.*complex(cos(theta),sin(theta))]; + Cx = [Cx; flipud(conj(Cx(2:end)))];; + Dwx = N/sqrt(2)*ifft(Cx); % Ground Motion - x direction [m] + else + Dwx = zeros(length(t), 1); + end +#+end_src + +#+begin_src matlab + if opts.Dwy + theta = 2*pi*rand(N/2,1); % Generate random phase [rad] + Cx = [0 ; C.*complex(cos(theta),sin(theta))]; + Cx = [Cx; flipud(conj(Cx(2:end)))];; + Dwy = N/sqrt(2)*ifft(Cx); % Ground Motion - y direction [m] + else + Dwy = zeros(length(t), 1); + end +#+end_src + +#+begin_src matlab + if opts.Dwy + theta = 2*pi*rand(N/2,1); % Generate random phase [rad] + Cx = [0 ; C.*complex(cos(theta),sin(theta))]; + Cx = [Cx; flipud(conj(Cx(2:end)))];; + Dwz = N/sqrt(2)*ifft(Cx); % Ground Motion - z direction [m] + else + Dwz = zeros(length(t), 1); + end #+end_src *** Translation Stage - X direction #+begin_src matlab - phi = dist_f.psd_ty; % TODO - we take here the vertical direction which is wrong but approximate - C = zeros(N/2,1); - for i = 1:N/2 - C(i) = sqrt(phi(i)*df); + if opts.Fty_x + phi = dist_f.psd_ty; % TODO - we take here the vertical direction which is wrong but approximate + C = zeros(N/2,1); + for i = 1:N/2 + C(i) = sqrt(phi(i)*df); + end + theta = 2*pi*rand(N/2,1); % Generate random phase [rad] + Cx = [0 ; C.*complex(cos(theta),sin(theta))]; + Cx = [Cx; flipud(conj(Cx(2:end)))];; + u = N/sqrt(2)*ifft(Cx); % Disturbance Force Ty x [N] + Fty_x = u; + else + Fty_x = zeros(length(t), 1); end - theta = 2*pi*rand(N/2,1); % Generate random phase [rad] - Cx = [0 ; C.*complex(cos(theta),sin(theta))]; - Cx = [Cx; flipud(conj(Cx(2:end)))];; - u = N/sqrt(2)*ifft(Cx); % Disturbance Force Ty x [N] - Fty_x = u; #+end_src *** Translation Stage - Z direction #+begin_src matlab - phi = dist_f.psd_ty; - C = zeros(N/2,1); - for i = 1:N/2 - C(i) = sqrt(phi(i)*df); + if opts.Fty_z + phi = dist_f.psd_ty; + C = zeros(N/2,1); + for i = 1:N/2 + C(i) = sqrt(phi(i)*df); + end + theta = 2*pi*rand(N/2,1); % Generate random phase [rad] + Cx = [0 ; C.*complex(cos(theta),sin(theta))]; + Cx = [Cx; flipud(conj(Cx(2:end)))];; + u = N/sqrt(2)*ifft(Cx); % Disturbance Force Ty z [N] + Fty_z = u; + else + Fty_z = zeros(length(t), 1); end - theta = 2*pi*rand(N/2,1); % Generate random phase [rad] - Cx = [0 ; C.*complex(cos(theta),sin(theta))]; - Cx = [Cx; flipud(conj(Cx(2:end)))];; - u = N/sqrt(2)*ifft(Cx); % Disturbance Force Ty z [N] - Fty_z = u; #+end_src *** Spindle - Z direction #+begin_src matlab - phi = dist_f.psd_rz; - C = zeros(N/2,1); - for i = 1:N/2 - C(i) = sqrt(phi(i)*df); + if opts.Frz_z + phi = dist_f.psd_rz; + C = zeros(N/2,1); + for i = 1:N/2 + C(i) = sqrt(phi(i)*df); + end + theta = 2*pi*rand(N/2,1); % Generate random phase [rad] + Cx = [0 ; C.*complex(cos(theta),sin(theta))]; + Cx = [Cx; flipud(conj(Cx(2:end)))];; + u = N/sqrt(2)*ifft(Cx); % Disturbance Force Rz z [N] + Frz_z = u; + else + Frz_z = zeros(length(t), 1); end - theta = 2*pi*rand(N/2,1); % Generate random phase [rad] - Cx = [0 ; C.*complex(cos(theta),sin(theta))]; - Cx = [Cx; flipud(conj(Cx(2:end)))];; - u = N/sqrt(2)*ifft(Cx); % Disturbance Force Rz z [N] - Frz_z = u; #+end_src *** Direct Forces diff --git a/simscape_subsystems/nass_disturbances.slx b/simscape_subsystems/nass_disturbances.slx index dcfb411..4ac6586 100644 Binary files a/simscape_subsystems/nass_disturbances.slx and b/simscape_subsystems/nass_disturbances.slx differ diff --git a/simscape_subsystems/tilt_stage_D.slx b/simscape_subsystems/tilt_stage_D.slx index fe8040a..1a4d481 100644 Binary files a/simscape_subsystems/tilt_stage_D.slx and b/simscape_subsystems/tilt_stage_D.slx differ diff --git a/src/initDisturbances.m b/src/initDisturbances.m index 6483080..9116d12 100644 --- a/src/initDisturbances.m +++ b/src/initDisturbances.m @@ -7,7 +7,14 @@ function [] = initDisturbances(opts_param) % - opts_param - %% Default values for opts -opts = struct(); +opts = struct(... + 'Dwx', true, ... % Ground Motion - X direction + 'Dwy', true, ... % Ground Motion - Y direction + 'Dwz', true, ... % Ground Motion - Z direction + 'Fty_x', true, ... % Translation Stage - X direction + 'Fty_z', true, ... % Translation Stage - Z direction + 'Frz_z', true ... % Spindle - Z direction +); %% Populate opts with input parameters if exist('opts_param','var') @@ -36,55 +43,78 @@ C = zeros(N/2,1); for i = 1:N/2 C(i) = sqrt(phi(i)*df); end -theta = 2*pi*rand(N/2,1); % Generate random phase [rad] -Cx = [0 ; C.*complex(cos(theta),sin(theta))]; -Cx = [Cx; flipud(conj(Cx(2:end)))];; -u = N/sqrt(2)*ifft(Cx); % Ground Motion - x direction [m] -% Dwx = struct('time', t, 'signals', struct('values', u)); -Dwx = u; -theta = 2*pi*rand(N/2,1); % Generate random phase [rad] -Cx = [0 ; C.*complex(cos(theta),sin(theta))]; -Cx = [Cx; flipud(conj(Cx(2:end)))];; -u = N/sqrt(2)*ifft(Cx); % Ground Motion - y direction [m] -Dwy = u; -theta = 2*pi*rand(N/2,1); % Generate random phase [rad] -Cx = [0 ; C.*complex(cos(theta),sin(theta))]; -Cx = [Cx; flipud(conj(Cx(2:end)))];; -u = N/sqrt(2)*ifft(Cx); % Ground Motion - z direction [m] -Dwz = u; -phi = dist_f.psd_ty; % TODO - we take here the vertical direction which is wrong but approximate -C = zeros(N/2,1); -for i = 1:N/2 - C(i) = sqrt(phi(i)*df); +if opts.Dwx + theta = 2*pi*rand(N/2,1); % Generate random phase [rad] + Cx = [0 ; C.*complex(cos(theta),sin(theta))]; + Cx = [Cx; flipud(conj(Cx(2:end)))];; + Dwx = N/sqrt(2)*ifft(Cx); % Ground Motion - x direction [m] +else + Dwx = zeros(length(t), 1); end -theta = 2*pi*rand(N/2,1); % Generate random phase [rad] -Cx = [0 ; C.*complex(cos(theta),sin(theta))]; -Cx = [Cx; flipud(conj(Cx(2:end)))];; -u = N/sqrt(2)*ifft(Cx); % Disturbance Force Ty x [N] -Fty_x = u; -phi = dist_f.psd_ty; -C = zeros(N/2,1); -for i = 1:N/2 - C(i) = sqrt(phi(i)*df); +if opts.Dwy + theta = 2*pi*rand(N/2,1); % Generate random phase [rad] + Cx = [0 ; C.*complex(cos(theta),sin(theta))]; + Cx = [Cx; flipud(conj(Cx(2:end)))];; + Dwy = N/sqrt(2)*ifft(Cx); % Ground Motion - y direction [m] +else + Dwy = zeros(length(t), 1); end -theta = 2*pi*rand(N/2,1); % Generate random phase [rad] -Cx = [0 ; C.*complex(cos(theta),sin(theta))]; -Cx = [Cx; flipud(conj(Cx(2:end)))];; -u = N/sqrt(2)*ifft(Cx); % Disturbance Force Ty z [N] -Fty_z = u; -phi = dist_f.psd_rz; -C = zeros(N/2,1); -for i = 1:N/2 - C(i) = sqrt(phi(i)*df); +if opts.Dwy + theta = 2*pi*rand(N/2,1); % Generate random phase [rad] + Cx = [0 ; C.*complex(cos(theta),sin(theta))]; + Cx = [Cx; flipud(conj(Cx(2:end)))];; + Dwz = N/sqrt(2)*ifft(Cx); % Ground Motion - z direction [m] +else + Dwz = zeros(length(t), 1); +end + +if opts.Fty_x + phi = dist_f.psd_ty; % TODO - we take here the vertical direction which is wrong but approximate + C = zeros(N/2,1); + for i = 1:N/2 + C(i) = sqrt(phi(i)*df); + end + theta = 2*pi*rand(N/2,1); % Generate random phase [rad] + Cx = [0 ; C.*complex(cos(theta),sin(theta))]; + Cx = [Cx; flipud(conj(Cx(2:end)))];; + u = N/sqrt(2)*ifft(Cx); % Disturbance Force Ty x [N] + Fty_x = u; +else + Fty_x = zeros(length(t), 1); +end + +if opts.Fty_z + phi = dist_f.psd_ty; + C = zeros(N/2,1); + for i = 1:N/2 + C(i) = sqrt(phi(i)*df); + end + theta = 2*pi*rand(N/2,1); % Generate random phase [rad] + Cx = [0 ; C.*complex(cos(theta),sin(theta))]; + Cx = [Cx; flipud(conj(Cx(2:end)))];; + u = N/sqrt(2)*ifft(Cx); % Disturbance Force Ty z [N] + Fty_z = u; +else + Fty_z = zeros(length(t), 1); +end + +if opts.Frz_z + phi = dist_f.psd_rz; + C = zeros(N/2,1); + for i = 1:N/2 + C(i) = sqrt(phi(i)*df); + end + theta = 2*pi*rand(N/2,1); % Generate random phase [rad] + Cx = [0 ; C.*complex(cos(theta),sin(theta))]; + Cx = [Cx; flipud(conj(Cx(2:end)))];; + u = N/sqrt(2)*ifft(Cx); % Disturbance Force Rz z [N] + Frz_z = u; +else + Frz_z = zeros(length(t), 1); end -theta = 2*pi*rand(N/2,1); % Generate random phase [rad] -Cx = [0 ; C.*complex(cos(theta),sin(theta))]; -Cx = [Cx; flipud(conj(Cx(2:end)))];; -u = N/sqrt(2)*ifft(Cx); % Disturbance Force Rz z [N] -Frz_z = u; u = zeros(length(t), 6); Fd = u; diff --git a/src/initializeReferences.m b/src/initializeReferences.m index 4d9bf7b..1d21c98 100644 --- a/src/initializeReferences.m +++ b/src/initializeReferences.m @@ -66,7 +66,7 @@ function [ref] = initializeReferences(opts_param) Ry = struct('time', t, 'signals', struct('values', Ry)); %% Spindle - Rz - t = 0:Ts:opts.Rz_period-Ts; + t = 0:Ts:100*opts.Rz_period-Ts; Rz = zeros(length(t), 1); switch opts.Rz_type