diff --git a/docs/control_cascade.html b/docs/control_cascade.html index b125f52..ef4f462 100644 --- a/docs/control_cascade.html +++ b/docs/control_cascade.html @@ -1,11 +1,10 @@ - - + Cascade Control applied on the Simscape Model @@ -282,14 +281,14 @@ for the JavaScript code in this tag.
  • 3. High Authority Control in the joint space - \(\bm{K}_\mathcal{L}\)
  • 4. Primary Controller in the task space - \(\bm{K}_\mathcal{X}\)
  • @@ -518,8 +517,8 @@ isstable(Gl) -
    -

    3.2 Obtained Plant

    +
    +

    3.2 Obtained Plant

    The obtain plant is shown in Figure 5. @@ -616,8 +615,8 @@ isstable(Gx)

    -
    -

    4.2 Obtained Plant

    +
    +

    4.2 Obtained Plant

    @@ -687,18 +686,47 @@ load('./mat/cascade_hac_lac.mat', +
    n_av = 4;
    +han_win = hanning(ceil(length(cascade_hac_lac.Em.En.Data(:,1))/n_av));
    +
    +
    + +
    +
    t = cascade_hac_lac.Em.En.Time;
    +Ts = t(2)-t(1);
    +
    +[pxx_ol, f] = pwelch(tomo_align_dist.Em.En.Data, han_win, [], [], 1/Ts);
    +[pxx_ca, ~] = pwelch(cascade_hac_lac.Em.En.Data, han_win, [], [], 1/Ts);
    +
    +
    + + +
    +

    cascade_hac_lac_tomography_psd.png +

    +

    Figure 9: ASD of the position error (png, pdf)

    +
    + + +
    +

    cascade_hac_lac_tomography_cas.png +

    +

    Figure 10: Cumulative Amplitude Spectrum of the position error (png, pdf)

    +
    +

    cascade_hac_lac_tomography.png

    -

    Figure 9: Results of the Tomography Experiment (png, pdf)

    +

    Figure 11: Results of the Tomography Experiment (png, pdf)

    Author: Dehaeze Thomas

    -

    Created: 2020-03-23 lun. 10:05

    +

    Created: 2020-03-25 mer. 19:23

    diff --git a/docs/control_hac_lac.html b/docs/control_hac_lac.html index 9775190..ea8e2c3 100644 --- a/docs/control_hac_lac.html +++ b/docs/control_hac_lac.html @@ -4,7 +4,7 @@ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> - + HAC-LAC applied on the Simscape Model @@ -278,14 +278,15 @@ for the JavaScript code in this tag.
  • 2.4. Controller and Loop Gain
  • -
  • 3. High Authority Control - \(\bm{K}_\mathcal{X}\) +
  • 3. Uncertainty Improvements thanks to the LAC control
  • +
  • 4. High Authority Control - \(\bm{K}_\mathcal{X}\)
  • -
  • 4. Simulation
  • -
  • 5. Results
  • +
  • 5. Simulation
  • +
  • 6. Results
  • @@ -426,13 +427,40 @@ G_dvf.OutputName = {'Dnlm1', -

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

    +
    +

    3 Uncertainty Improvements thanks to the LAC control

    +
    +
    K_dvf_backup = K_dvf;
    +initializeController('type', 'hac-dvf');
    +
    +
    + +
    +
    masses = [1, 10, 50]; % [kg]
    +
    +
    + +
    +
    %% 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
    +
    +
    +
    +
    + +
    +

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

    +
    -

    3.1 Identification of the damped plant

    -
    +

    4.1 Identification of the damped plant

    +
    Kx = tf(zeros(6));
     
    @@ -473,8 +501,8 @@ Gx.InputName = {'Fx',
    -

    3.2 Controller Design

    -
    +

    4.2 Controller Design

    +

    The controller consists of:

    @@ -516,8 +544,8 @@ Kx = Kx.*diag(1./dia
    -

    4 Simulation

    -
    +

    5 Simulation

    +
    load('mat/conf_simulink.mat');
     set_param(conf_simulink, 'StopTime', '2');
    @@ -541,8 +569,8 @@ save('./mat/tomo_exp_hac_lac.mat', 
    -

    5 Results

    -
    +

    6 Results

    +

    Let’s load the simulation when no control is applied.

    @@ -556,7 +584,7 @@ load('./mat/tomo_exp_hac_lac.mat',

    Author: Dehaeze Thomas

    -

    Created: 2020-03-23 lun. 10:05

    +

    Created: 2020-03-25 mer. 19:23

    diff --git a/docs/control_voice_coil.html b/docs/control_voice_coil.html index 6b98e2e..d838fb7 100644 --- a/docs/control_voice_coil.html +++ b/docs/control_voice_coil.html @@ -1,11 +1,10 @@ - - + Control of the NASS with Voice coil actuators @@ -248,6 +247,16 @@ for the JavaScript code in this tag. } /*]]>*///--> + +
    @@ -256,10 +265,537 @@ for the JavaScript code in this tag. HOME

    Control of the NASS with Voice coil actuators

    + + +

    +The goal here is to study the use of a voice coil based nano-hexapod. +That is to say a nano-hexapod with a very small stiffness. +

    + + +
    +

    cascade_control_architecture.png +

    +

    Figure 1: Cascaded Control consisting of (from inner to outer loop): IFF, Linearization Loop, Tracking Control in the frame of the Legs

    +
    + +
    +

    1 Initialization

    +
    +

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

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

    +The nano-hexapod is a voice coil based hexapod and the sample has a mass of 1kg. +

    +
    +
    initializeNanoHexapod('actuator', 'lorentz');
    +initializeSample('mass', 1);
    +
    +
    + +

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

    +
    +
    initializeReferences('Rz_type', 'rotating', 'Rz_period', 1);
    +
    +
    + +
    +
    initializeDisturbances();
    +
    +
    + +
    +
    initializeController('type', 'cascade-hac-lac');
    +
    +
    + +
    +
    initializeSimscapeConfiguration('gravity', true);
    +
    +
    + +

    +We log the signals. +

    +
    +
    initializeLoggingConfiguration('log', 'all');
    +
    +
    + +
    +
    Kx = tf(zeros(6));
    +Kl = tf(zeros(6));
    +Kiff = tf(zeros(6));
    +
    +
    +
    +
    + +
    +

    2 Low Authority Control - Integral Force Feedback \(\bm{K}_\text{IFF}\)

    +
    +

    + +

    +
    +
    +

    2.1 Identification

    +
    +

    +Let’s first identify the plant for the IFF controller. +

    +
    +
    %% 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', [], 'Fnlm');  io_i = io_i + 1; % Force Sensors
    +
    +%% Run the linearization
    +G_iff = linearize(mdl, io, 0);
    +G_iff.InputName  = {'Fnl1', 'Fnl2', 'Fnl3', 'Fnl4', 'Fnl5', 'Fnl6'};
    +G_iff.OutputName = {'Fnlm1', 'Fnlm2', 'Fnlm3', 'Fnlm4', 'Fnlm5', 'Fnlm6'};
    +
    +
    +
    +
    + +
    +

    2.2 Plant

    +
    +

    +The obtained plant for IFF is shown in Figure 2. +

    + + +
    +

    cascade_vc_iff_plant.png +

    +

    Figure 2: IFF Plant (png, pdf)

    +
    +
    +
    + +
    +

    2.3 Root Locus

    +
    +

    +As seen in the root locus (Figure 3, no damping can be added to modes corresponding to the resonance of the micro-station. +

    + +

    +However, critical damping can be achieve for the resonances of the nano-hexapod as shown in the zoomed part of the root (Figure 3, left part). +The maximum damping is obtained for a control gain of \(\approx 70\). +

    + + +
    +

    cascade_vc_iff_root_locus.png +

    +

    Figure 3: Root Locus for the IFF control (png, pdf)

    +
    +
    +
    + +
    +

    2.4 Controller and Loop Gain

    +
    +

    +We create the \(6 \times 6\) diagonal Integral Force Feedback controller. +The obtained loop gain is shown in Figure 4. +

    +
    +
    Kiff = -70/s*eye(6);
    +
    +
    + + +
    +

    cascade_vc_iff_loop_gain.png +

    +

    Figure 4: Obtained Loop gain the IFF Control (png, pdf)

    +
    +
    +
    +
    + +
    +

    3 High Authority Control in the joint space - \(\bm{K}_\mathcal{L}\)

    +
    +

    + +

    +
    +
    +

    3.1 Identification of the damped plant

    +
    +

    +Let’s identify the dynamics from \(\bm{\tau}^\prime\) to \(d\bm{\mathcal{L}}\) as shown in Figure 1. +

    + +
    +
    %% 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, '/Micro-Station'], 3, 'output', [], 'Dnlm');  io_i = io_i + 1; % Leg Displacement
    +
    +%% Run the linearization
    +Gl = linearize(mdl, io, 0);
    +Gl.InputName  = {'Fnl1', 'Fnl2', 'Fnl3', 'Fnl4', 'Fnl5', 'Fnl6'};
    +Gl.OutputName = {'Dnlm1', 'Dnlm2', 'Dnlm3', 'Dnlm4', 'Dnlm5', 'Dnlm6'};
    +
    +
    + +

    +There are some unstable poles in the Plant with very small imaginary parts. +These unstable poles are probably not physical, and they disappear when taking the minimum realization of the plant. +

    +
    +
    isstable(Gl)
    +Gl = minreal(Gl);
    +isstable(Gl)
    +
    +
    +
    +
    + +
    +

    3.2 Obtained Plant

    +
    +

    +The obtained dynamics is shown in Figure 5. +

    + +

    +Few things can be said on the dynamics: +

    +
      +
    • the dynamics of the diagonal elements are almost all the same
    • +
    • the system is well decoupled below the resonances of the nano-hexapod (1Hz)
    • +
    • the dynamics of the diagonal elements are almost equivalent to a critically damped mass-spring-system with some spurious resonances above 50Hz corresponding to the resonances of the micro-station
    • +
    + + +
    +

    cascade_vc_hac_joint_plant.png +

    +

    Figure 5: Plant for the High Authority Control in the Joint Space (png, pdf)

    +
    +
    +
    + +
    +

    3.3 Controller Design and Loop Gain

    +
    +

    +As the plant is well decoupled, a diagonal plant is designed. +

    + +
    +
    wc = 2*pi*5; % Bandwidth Bandwidth [rad/s]
    +
    +h = 2; % Lead parameter
    +
    +Kl = (1/h) * (1 + s/wc*h)/(1 + s/wc/h) * ... % Lead
    +     (1/h) * (1 + s/wc*h)/(1 + s/wc/h) * ... % Lead
    +     (s + 2*pi*10)/s * ... % Weak Integrator
    +     (s + 2*pi*1)/s * ... % Weak Integrator
    +     1/(1 + s/2/pi/10); % Low pass filter after crossover
    +
    +% Normalization of the gain of have a loop gain of 1 at frequency wc
    +Kl = Kl.*diag(1./diag(abs(freqresp(Gl*Kl, wc))));
    +
    +
    +
    +
    +
    + +
    +

    4 On the usefulness of the High Authority Control loop / Linearization loop

    +
    +

    +Let’s see what happens is we omit the HAC loop and we directly try to control the damped plant using the measurement of the sample with respect to the granite \(\bm{\mathcal{X}}\). +

    + +

    +We can do that in two different ways: +

    +
      +
    • in the task space as shown in Figure 6
    • +
    • in the space of the legs as shown in Figure 7
    • +
    + + +
    +

    control_architecture_iff_X.png +

    +

    Figure 6: IFF control + primary controller in the task space

    +
    + + +
    +

    control_architecture_iff_L.png +

    +

    Figure 7: HAC-LAC control architecture in the frame of the legs

    +
    +
    + +
    +

    4.1 Identification

    +
    +
    +
    initializeController('type', 'hac-iff');
    +
    +
    + +
    +
    %% Name of the Simulink File
    +mdl = 'nass_model';
    +
    +%% Input/Output definition
    +clear io; io_i = 1;
    +io(io_i) = linio([mdl, '/Controller/HAC-IFF/Kx'],  1, 'input');    io_i = io_i + 1;
    +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  = {'F1', 'F2', 'F3', 'F4', 'F5', 'F6'};
    +G.OutputName = {'Ex', 'Ey', 'Ez', 'Erx', 'Ery', 'Erz'};
    +
    +
    + +
    +
    isstable(G)
    +G = -minreal(G);
    +isstable(G)
    +
    +
    +
    +
    + +
    +

    4.2 Plant in the Task space

    +
    +

    +The obtained plant is shown in Figure +

    + +
    +
    Gx = G*inv(nano_hexapod.J');
    +
    +
    +
    +
    + +
    +

    4.3 Plant in the Leg’s space

    +
    +
    +
    Gl = nano_hexapod.J*G;
    +
    +
    +
    +
    +
    + +
    +

    5 Primary Controller in the task space - \(\bm{K}_\mathcal{X}\)

    +
    +

    + +

    +
    +
    +

    5.1 Identification of the linearized plant

    +
    +

    +We know identify the dynamics between \(\bm{r}_{\mathcal{X}_n}\) and \(\bm{r}_\mathcal{X}\). +

    +
    +
    %% Name of the Simulink File
    +mdl = 'nass_model';
    +
    +%% Input/Output definition
    +clear io; io_i = 1;
    +io(io_i) = linio([mdl, '/Controller/Cascade-HAC-LAC/Kx'],  1, 'input'); io_i = io_i + 1;
    +io(io_i) = linio([mdl, '/Tracking Error'], 1, 'output', [], 'En');      io_i = io_i + 1; % Position Errror
    +
    +%% Run the linearization
    +Gx = linearize(mdl, io, 0);
    +Gx.InputName  = {'rL1', 'rL2', 'rL3', 'rL4', 'rL5', 'rL6'};
    +Gx.OutputName = {'Ex', 'Ey', 'Ez', 'Erx', 'Ery', 'Erz'};
    +
    +
    + +

    +As before, we take the minimum realization. +

    +
    +
    isstable(Gx)
    +Gx = -minreal(Gx);
    +isstable(Gx)
    +
    +
    +
    +
    + +
    +

    5.2 Obtained Plant

    +
    +
    +

    5.3 Controller Design

    +
    +
    +
    wc = 2*pi*200; % Bandwidth Bandwidth [rad/s]
    +
    +h = 2; % Lead parameter
    +
    +Kx = (1/h) * (1 + s/wc*h)/(1 + s/wc/h) * ...
    +     (s + 2*pi*10)/s * ...
    +     (s + 2*pi*100)/s * ...
    +     1/(1+s/2/pi/500); % For Piezo
    +% Kx = (1/h) * (1 + s/wc*h)/(1 + s/wc/h) * (s + 2*pi*10)/s * (s + 2*pi*1)/s ; % For voice coil
    +
    +% Normalization of the gain of have a loop gain of 1 at frequency wc
    +Kx = Kx.*diag(1./diag(abs(freqresp(Gx*Kx, wc))));
    +
    +
    +
    +
    +
    + +
    +

    6 Simulation

    +
    +
    +
    load('mat/conf_simulink.mat');
    +set_param(conf_simulink, 'StopTime', '2');
    +
    +
    + +

    +And we simulate the system. +

    +
    +
    sim('nass_model');
    +
    +
    + +
    +
    cascade_hac_lac_lorentz = simout;
    +save('./mat/cascade_hac_lac.mat', 'cascade_hac_lac_lorentz', '-append');
    +
    +
    +
    +
    + +
    +

    7 Results

    +
    +
    +
    +

    7.1 Load the simulation results

    +
    +
    +
    load('./mat/experiment_tomography.mat', 'tomo_align_dist');
    +load('./mat/cascade_hac_lac.mat', 'cascade_hac_lac', 'cascade_hac_lac_lorentz');
    +
    +
    +
    +
    + +
    +

    7.2 Control effort

    +
    +
    +

    7.3 Load the simulation results

    +
    +
    +
    n_av = 4;
    +han_win = hanning(ceil(length(cascade_hac_lac.Em.En.Data(:,1))/n_av));
    +
    +
    + +
    +
    t = cascade_hac_lac.Em.En.Time;
    +Ts = t(2)-t(1);
    +
    +[pxx_ol, f] = pwelch(tomo_align_dist.Em.En.Data, han_win, [], [], 1/Ts);
    +[pxx_ca, ~] = pwelch(cascade_hac_lac.Em.En.Data, han_win, [], [], 1/Ts);
    +[pxx_vc, ~] = pwelch(cascade_hac_lac_lorentz.Em.En.Data, han_win, [], [], 1/Ts);
    +
    +
    +
    +
    +

    Author: Dehaeze Thomas

    -

    Created: 2020-03-23 lun. 10:05

    +

    Created: 2020-03-25 mer. 19:22

    diff --git a/docs/figs/cascade_vc_hac_joint_plant.pdf b/docs/figs/cascade_vc_hac_joint_plant.pdf new file mode 100644 index 0000000..360a5c4 Binary files /dev/null and b/docs/figs/cascade_vc_hac_joint_plant.pdf differ diff --git a/docs/figs/cascade_vc_hac_joint_plant.png b/docs/figs/cascade_vc_hac_joint_plant.png new file mode 100644 index 0000000..8770c14 Binary files /dev/null and b/docs/figs/cascade_vc_hac_joint_plant.png differ diff --git a/docs/figs/cascade_vc_iff_loop_gain.pdf b/docs/figs/cascade_vc_iff_loop_gain.pdf new file mode 100644 index 0000000..b9b7bfd Binary files /dev/null and b/docs/figs/cascade_vc_iff_loop_gain.pdf differ diff --git a/docs/figs/cascade_vc_iff_loop_gain.png b/docs/figs/cascade_vc_iff_loop_gain.png new file mode 100644 index 0000000..c13edba Binary files /dev/null and b/docs/figs/cascade_vc_iff_loop_gain.png differ diff --git a/docs/figs/cascade_vc_iff_plant.pdf b/docs/figs/cascade_vc_iff_plant.pdf new file mode 100644 index 0000000..c806003 Binary files /dev/null and b/docs/figs/cascade_vc_iff_plant.pdf differ diff --git a/docs/figs/cascade_vc_iff_plant.png b/docs/figs/cascade_vc_iff_plant.png new file mode 100644 index 0000000..13aa175 Binary files /dev/null and b/docs/figs/cascade_vc_iff_plant.png differ diff --git a/docs/figs/cascade_vc_iff_root_locus.pdf b/docs/figs/cascade_vc_iff_root_locus.pdf new file mode 100644 index 0000000..ba4c14a Binary files /dev/null and b/docs/figs/cascade_vc_iff_root_locus.pdf differ diff --git a/docs/figs/cascade_vc_iff_root_locus.png b/docs/figs/cascade_vc_iff_root_locus.png new file mode 100644 index 0000000..2b3b1a8 Binary files /dev/null and b/docs/figs/cascade_vc_iff_root_locus.png differ diff --git a/docs/figs/control_architecture_iff_L.pdf b/docs/figs/control_architecture_iff_L.pdf new file mode 100644 index 0000000..e833a72 Binary files /dev/null and b/docs/figs/control_architecture_iff_L.pdf differ diff --git a/docs/figs/control_architecture_iff_L.png b/docs/figs/control_architecture_iff_L.png new file mode 100644 index 0000000..7cb71b0 Binary files /dev/null and b/docs/figs/control_architecture_iff_L.png differ diff --git a/docs/figs/control_architecture_iff_X.pdf b/docs/figs/control_architecture_iff_X.pdf new file mode 100644 index 0000000..2fc94a8 Binary files /dev/null and b/docs/figs/control_architecture_iff_X.pdf differ diff --git a/docs/figs/control_architecture_iff_X.png b/docs/figs/control_architecture_iff_X.png new file mode 100644 index 0000000..b6d9704 Binary files /dev/null and b/docs/figs/control_architecture_iff_X.png differ diff --git a/docs/figs/hac_lac_control_schematic.pdf b/docs/figs/hac_lac_control_schematic.pdf index ed1f636..f6af74c 100644 Binary files a/docs/figs/hac_lac_control_schematic.pdf 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 index 9261aa9..f79ad57 100644 Binary files a/docs/figs/hac_lac_control_schematic.png and b/docs/figs/hac_lac_control_schematic.png differ diff --git a/docs/index.html b/docs/index.html index 7194af1..551b1b2 100644 --- a/docs/index.html +++ b/docs/index.html @@ -4,7 +4,7 @@ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> - + Simscape Model of the Nano-Active-Stabilization-System @@ -202,28 +202,50 @@ @@ -245,9 +267,11 @@
  • 6. Tuning of the Dynamics of the Simscape model (link)
  • 7. Disturbances (link)
  • 8. Tomography Experiment (link)
  • -
  • 9. Active Damping Techniques on the Uni-axial Model (link)
  • -
  • 10. Active Damping Techniques on the full Simscape Model (link)
  • -
  • 11. Useful Matlab Functions (link)
  • +
  • 9. Effect of support’s compliance uncertainty on the plant (link)
  • +
  • 10. Active Damping Techniques on the Uni-axial Model (link)
  • +
  • 11. Active Damping Techniques on the full Simscape Model (link)
  • +
  • 12. Control of the Nano-Active-Stabilization-System (link)
  • +
  • 13. Useful Matlab Functions (link)
  • @@ -356,27 +380,39 @@ Tomography experiments are simulated and the results are presented -

    9 Active Damping Techniques on the Uni-axial Model (link)

    +
    +

    9 Effect of support’s compliance uncertainty on the plant (link)

    +In this document, is studied how uncertainty on the micro-station compliance will affect the uncertainty of the isolation platform to be designed. +

    +
    +
    + +
    +

    10 Active Damping Techniques on the Uni-axial Model (link)

    +
    +

    Active damping techniques are applied to the Uniaxial Simscape model.

    -

    10 Active Damping Techniques on the full Simscape Model (link)

    -
    +

    11 Active Damping Techniques on the full Simscape Model (link)

    +

    Active damping techniques are applied to the full Simscape model.

    +
    +

    12 Control of the Nano-Active-Stabilization-System (link)

    +
    -

    11 Useful Matlab Functions (link)

    -
    +

    13 Useful Matlab Functions (link)

    +

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

    @@ -389,7 +425,7 @@ These functions are all defined here.

    Author: Dehaeze Thomas

    -

    Created: 2020-03-17 mar. 17:30

    +

    Created: 2020-03-25 mer. 19:21

    diff --git a/docs/simscape_subsystems.html b/docs/simscape_subsystems.html index 2d643a7..047b70f 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 @@ -261,169 +261,169 @@ for the JavaScript code in this tag.
    -
    -

    Function description

    -
    +
    +

    Function description

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

    Optional Parameters

    -
    +
    +

    Optional Parameters

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

    Structure initialization

    -
    +
    +

    Structure initialization

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

    Add Type

    -
    +
    +

    Add Type

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

    Save the Structure

    -
    +
    +

    Save the Structure

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

    -
    -

    Function description

    -
    +
    +

    Function description

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

    Optional Parameters

    -
    +
    +

    Optional Parameters

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

    Structure initialization

    -
    +
    +

    Structure initialization

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

    Add Type

    -
    +
    +

    Add Type

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

    Save the Structure

    -
    +
    +

    Save the Structure

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

    -
    -

    Simscape Model

    -
    +
    +

    Simscape Model

    +

    The model of the Ground is composed of:

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

    Function description

    -
    +
    +

    Function description

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

    Optional Parameters

    -
    +
    +

    Optional Parameters

    +
    arguments
       args.type char {mustBeMember(args.type,{'none', 'rigid'})} = 'rigid'
    @@ -677,9 +677,9 @@ The model of the Ground is composed of:
     
    -
    -

    Structure initialization

    -
    +
    +

    Structure initialization

    +

    First, we initialize the granite structure.

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

    Add Type

    -
    +
    +

    Add Type

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

    Save the Structure

    -
    +
    +

    Save the Structure

    +

    The ground structure is saved.

    @@ -751,9 +751,9 @@ The ground structure is saved.

    -
    -

    Simscape Model

    -
    +
    +

    Simscape Model

    +

    The Simscape model of the granite is composed of:

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

    Function description

    -
    +
    +

    Function description

    +
    function [granite] = initializeGranite(args)
     
    @@ -792,9 +792,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'
    @@ -810,9 +810,9 @@ The output sample_pos corresponds to the impact point of the X-ray.
     
    -
    -

    Structure initialization

    -
    +
    +

    Structure initialization

    +

    First, we initialize the granite structure.

    @@ -844,9 +844,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.

    @@ -866,9 +866,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)]
    @@ -877,9 +877,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');
    @@ -892,9 +892,9 @@ granite.C = [4.0e5; 1.1e5; 9.0e5]; % [N/(m/s)]
     
    -
    -

    Save the Structure

    -
    +
    +

    Save the Structure

    +

    The granite structure is saved.

    @@ -906,17 +906,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:

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

    Function description

    -
    +
    +

    Function description

    +
    function [ty] = initializeTy(args)
     
    @@ -956,9 +956,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'
    @@ -969,9 +969,9 @@ It is used to impose the motion in the Y direction
     
    -
    -

    Structure initialization

    -
    +
    +

    Structure initialization

    +

    First, we initialize the ty structure.

    @@ -1003,9 +1003,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).

    @@ -1050,9 +1050,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)]
    @@ -1061,9 +1061,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');
    @@ -1076,9 +1076,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.

    @@ -1090,17 +1090,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:

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

    Function description

    -
    +
    +

    Function description

    +
    function [ry] = initializeRy(args)
     
    @@ -1140,9 +1140,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'
    @@ -1154,9 +1154,9 @@ The Ry motion is imposed by the input.
     
    -
    -

    Structure initialization

    -
    +
    +

    Structure initialization

    +

    First, we initialize the ry structure.

    @@ -1189,9 +1189,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.

    @@ -1229,9 +1229,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];
    @@ -1240,9 +1240,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');
    @@ -1255,9 +1255,9 @@ ry.C = [1e5;   1e5; 1e5;   3e4;   1e3; 3e4];
     
    -
    -

    Save the Structure

    -
    +
    +

    Save the Structure

    +

    The ry structure is saved.

    @@ -1269,17 +1269,17 @@ The ry structure is saved.
    -
    -

    7 Spindle

    +
    +

    7 Spindle

    -
    -

    Simscape Model

    -
    +
    +

    Simscape Model

    +

    The Simscape model of the Spindle is composed of:

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

    Function description

    -
    +
    +

    Function description

    +
    function [rz] = initializeRz(args)
     
    @@ -1315,9 +1315,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'
    @@ -1328,9 +1328,9 @@ The Simscape model of the Spindle is composed of:
     
    -
    -

    Structure initialization

    -
    +
    +

    Structure initialization

    +

    First, we initialize the rz structure.

    @@ -1362,9 +1362,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.

    @@ -1385,9 +1385,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];
    @@ -1396,9 +1396,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');
    @@ -1411,9 +1411,9 @@ rz.C = [4e4; 4e4; 7e4; 1e4; 1e4; 1e4];
     
    -
    -

    Save the Structure

    -
    +
    +

    Save the Structure

    +

    The rz structure is saved.

    @@ -1425,17 +1425,17 @@ The rz structure is saved.
    -
    -

    8 Micro Hexapod

    +
    +

    8 Micro Hexapod

    -
    -

    Simscape Model

    -
    +
    +

    Simscape Model

    +

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

    -
    -

    Function description

    -
    +
    +

    Function description

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

    Optional Parameters

    -
    +
    +

    Optional Parameters

    +
    arguments
         args.type      char   {mustBeMember(args.type,{'none', 'rigid', 'flexible', 'modal-analysis', 'init'})} = 'flexible'
    @@ -1506,9 +1506,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);
    @@ -1538,9 +1538,9 @@ Equilibrium position of the each joint.
     
    -
    -

    Add Type

    -
    +
    +

    Add Type

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

    Save the Structure

    -
    +
    +

    Save the Structure

    +

    The micro_hexapod structure is saved.

    @@ -1581,9 +1581,9 @@ The micro_hexapod structure is saved.

    -
    -

    Simscape Model

    -
    +
    +

    Simscape Model

    +

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

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

    Function description

    -
    +
    +

    Function description

    +
    function [axisc] = initializeAxisc(args)
     
    @@ -1618,9 +1618,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'
    @@ -1630,9 +1630,9 @@ The Simscape model of the Center of gravity compensator is composed of:
     
    -
    -

    Structure initialization

    -
    +
    +

    Structure initialization

    +

    First, we initialize the axisc structure.

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

    Add Type

    -
    +
    +

    Add Type

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

    Material and Geometry

    -
    +
    +

    Material and Geometry

    +

    Properties of the Material and link to the geometry files.

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

    Save the Structure

    -
    +
    +

    Save the Structure

    +

    The axisc structure is saved.

    @@ -1709,9 +1709,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 @@ -1733,9 +1733,9 @@ The output mirror_center corresponds to the center of the Sphere an

    -
    -

    Function description

    -
    +
    +

    Function description

    +
    function [] = initializeMirror(args)
     
    @@ -1743,9 +1743,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'
    @@ -1757,9 +1757,9 @@ The output mirror_center corresponds to the center of the Sphere an
     
    -
    -

    Structure initialization

    -
    +
    +

    Structure initialization

    +

    First, we initialize the mirror structure.

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

    Material and Geometry

    -
    +
    +

    Material and Geometry

    +

    We define the geometrical values.

    @@ -1864,9 +1864,9 @@ Finally, we close the shape.
    -
    -

    Save the Structure

    -
    +
    +

    Save the Structure

    +

    The mirror structure is saved.

    @@ -1878,17 +1878,17 @@ The mirror structure is saved.
    -
    -

    11 Nano Hexapod

    +
    +

    11 Nano Hexapod

    -
    -

    Simscape Model

    -
    +
    +

    Simscape Model

    +

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

    -
    -

    Function description

    -
    +
    +

    Function description

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

    Optional Parameters

    -
    +
    +

    Optional Parameters

    +
    arguments
         args.type      char   {mustBeMember(args.type,{'none', 'rigid', 'flexible'})} = 'flexible'
    @@ -1958,9 +1958,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);
    @@ -1988,9 +1988,9 @@ nano_hexapod.dLi = dLi;
     
    -
    -

    Add Type

    -
    +
    +

    Add Type

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

    Save the Structure

    -
    +
    +

    Save the Structure

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

    -
    -

    Simscape Model

    -
    +
    +

    Simscape Model

    +

    The Simscape model of the sample environment is composed of:

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

    Function description

    -
    +
    +

    Function description

    +
    function [sample] = initializeSample(args)
     
    @@ -2064,9 +2064,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'
    @@ -2082,9 +2082,9 @@ This could be the case for cable forces for instance.
     
    -
    -

    Structure initialization

    -
    +
    +

    Structure initialization

    +

    First, we initialize the sample structure.

    @@ -2114,9 +2114,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.

    @@ -2130,9 +2130,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)]
    @@ -2141,9 +2141,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');
    @@ -2156,9 +2156,9 @@ sample.C = 0.1 * sqrt(sample.K
    -

    Save the Structure

    -
    +
    +

    Save the Structure

    +

    The sample structure is saved.

    @@ -2178,9 +2178,9 @@ The sample structure is saved.

    -
    -

    Function Declaration and Documentation

    -
    +
    +

    Function Declaration and Documentation

    +
    function [] = initializeController(args)
     
    @@ -2188,21 +2188,21 @@ The sample structure is saved.
    -
    -

    Optional Parameters

    -
    +
    +

    Optional Parameters

    +
    arguments
    -  args.type char {mustBeMember(args.type,{'open-loop', 'iff', 'dvf', 'hac-dvf', 'ref-track-L', 'ref-track-iff-L', 'cascade-hac-lac'})} = 'open-loop'
    +  args.type char {mustBeMember(args.type,{'open-loop', 'iff', 'dvf', 'hac-dvf', 'ref-track-L', 'ref-track-iff-L', 'cascade-hac-lac', 'hac-iff'})} = 'open-loop'
     end
     
    -
    -

    Structure initialization

    -
    +
    +

    Structure initialization

    +

    First, we initialize the controller structure.

    @@ -2232,15 +2232,17 @@ First, we initialize the controller structure. controller.type = 6; case 'cascade-hac-lac' controller.type = 7; + case 'hac-iff' + controller.type = 8; end
    -
    -

    Save the Structure

    -
    +
    +

    Save the Structure

    +

    The controller structure is saved.

    @@ -2260,9 +2262,9 @@ The controller structure is saved.

    -
    -

    Function Declaration and Documentation

    -
    +
    +

    Function Declaration and Documentation

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

    Optional Parameters

    -
    +
    +

    Optional Parameters

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

    Translation Stage

    -
    +
    +

    Translation Stage

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

    Tilt Stage

    -
    +
    +

    Tilt Stage

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

    Spindle

    -
    +
    +

    Spindle

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

    Micro Hexapod

    -
    +
    +

    Micro Hexapod

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

    Nano Hexapod

    -
    +
    +

    Nano Hexapod

    +
    %% Nano-Hexapod
     t = [0, Ts];
    @@ -2549,9 +2551,9 @@ Dnl = struct('time', t, 
     
    -
    -

    Save

    -
    +
    +

    Save

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

    Function Declaration and Documentation

    -
    +
    +

    Function Declaration and Documentation

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

    Optional Parameters

    -
    +
    +

    Optional Parameters

    +
    arguments
         % Global parameter to enable or disable the disturbances
    @@ -2796,9 +2798,9 @@ 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');
     
    @@ -2815,9 +2817,9 @@ Frz_z = Frz_z - Frz_z(1);

    -
    -

    Function Declaration and Documentation

    -
    +
    +

    Function Declaration and Documentation

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

    Optional Parameters

    -
    +
    +

    Optional Parameters

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

    Structure initialization

    -
    +
    +

    Structure initialization

    +

    First, we initialize the pos_error structure.

    @@ -2886,9 +2888,9 @@ pos_error.Rz = args.Rz;
    -
    -

    Save

    -
    +
    +

    Save

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

    Author: Dehaeze Thomas

    -

    Created: 2020-03-23 lun. 10:05

    +

    Created: 2020-03-25 mer. 19:20

    diff --git a/docs/uncertainty_support.html b/docs/uncertainty_support.html new file mode 100644 index 0000000..80d4a16 --- /dev/null +++ b/docs/uncertainty_support.html @@ -0,0 +1,859 @@ + + + + + + + + +Effect of Uncertainty on the support’s dynamics on the isolation platform dynamics + + + + + + + + + + + + + + + +
    + UP + | + HOME +
    +

    Effect of Uncertainty on the support’s dynamics on the isolation platform dynamics

    + + +

    +In this document we will consider an isolation platform (e.g. the nano-hexapod) on top of a flexible support (e.g. the micro-station). +

    + +

    +The goal is to study: +

    +
      +
    • how does the dynamics of the support influence the dynamics of the plant to control
    • +
    • similarly: how does the uncertainty on the support’s dynamics will be transferred to uncertainty on the plant
    • +
    • what design choice should be made in order to minimize the resulting uncertainty on the plant
    • +
    + +

    +Two models are made to study these effects: +

    +
      +
    • In section 1, simple mass-spring-damper systems are chosen to model both the isolation platform and the flexible support
    • +
    • In section 2, we consider arbitrary support dynamics with multiplicative input uncertainty to study the unmodelled dynamics of the support
    • +
    + +
    +

    1 Simple Introductory Example

    +
    +

    + +

    +

    +Let’s consider the system shown in Figure 1 consisting of: +

    +
      +
    • A support represented by a mass \(m^\prime\), a stiffness \(k^\prime\) and a dashpot \(c^\prime\)
    • +
    • An isolation platform represented by a mass \(m\), a stiffness \(k\) and a dashpot \(c\) and an actuator \(F\)
    • +
    + +

    +The goal is to stabilize \(x\) using \(F\) in spite of uncertainty on the support mechanical properties. +

    + + +
    +

    2dof_system_stiffness_uncertainty.png +

    +

    Figure 1: Two degrees-of-freedom system

    +
    +
    + +
    +

    1.1 Equations of motion

    +
    +

    +If we write the equation of motion of the system in Figure 1, we obtain: +

    +\begin{align} + ms^2 x &= F + (cs + k) (x^\prime - x) \\ + m^\prime s^2 x^\prime &= -F - (c^\prime s + k^\prime) x^\prime + (cs + k)(x - x^\prime) +\end{align} + +

    +After eliminating \(x^\prime\), we obtain: +

    +\begin{equation} +\label{org2d73355} + \frac{x}{F} = \frac{m^\prime s^2 + c^\prime s + k^\prime}{ms^2(cs + k) + (ms^2 + cs + k)(m^\prime s^2 + c^\prime s + k^\prime)} +\end{equation} +
    +
    + +
    +

    1.2 Initialization of the support dynamics

    +
    +

    +Let the support have: +

    +
      +
    • a nominal mass of \(m^\prime = 1000\ [kg]\)
    • +
    • a nominal stiffness of \(k^\prime = 10^8\ [N/m]\)
    • +
    • a nominal damping of \(c^\prime = 10^5\ [N/(m/s)]\)
    • +
    + +
    +
    mpi = 1e3;
    +cpi = 5e4;
    +kpi = 1e8;
    +
    +
    + +

    +Let’s also consider some uncertainty in those parameters: +

    +
    +
    mp = ureal('m', mpi, 'Percentage', 30);
    +cp = ureal('c', cpi, 'Percentage', 30);
    +kp = ureal('k', kpi, 'Percentage', 30);
    +
    +
    + +

    +The compliance of the support without the isolation platform is \(\frac{1}{m^\prime s^2 + c^\prime s + k^\prime}\) and its bode plot is shown in Figure 2. +

    + +

    +One can see that support has a resonance frequency of \(\omega_0^\prime = 50\ Hz\). +

    + + +
    +

    nominal_support_compliance_dynamics.png +

    +

    Figure 2: Nominal compliance of the support (png, pdf)

    +
    +
    +
    + +
    +

    1.3 Initialization of the isolation platform

    +
    +

    +Let’s first fix the mass of the payload to be isolated: +

    +
    +
    m = 100;
    +
    +
    + +

    +And we generate three isolation platforms: +

    +
      +
    • A soft one with \(\omega_0 = 0.1 \omega_0^\prime = 5\ Hz\)
    • +
    • A medium stiff one with \(\omega_0 = \omega_0^\prime = 50\ Hz\)
    • +
    • A stiff one with \(\omega_0 = 10 \omega_0^\prime = 500\ Hz\)
    • +
    +
    +
    + +
    +

    1.4 Comparison

    +
    +

    +The obtained dynamics from \(F\) to \(x\) for the three isolation platform are shown in Figure 3. +

    + + +
    +

    plant_dynamics_uncertainty_stiff_mid_soft.png +

    +

    Figure 3: Obtained plant for the three isolation platforms considered (png, pdf)

    +
    +
    +
    + +
    +

    1.5 Conclusion

    +
    +
    +

    +The soft platform dynamics does not seems to depend on the dynamics of the support. +

    + +
    +
    +
    +
    + +
    +

    2 Generalization to arbitrary dynamics

    +
    +

    + +

    +
    +
    +

    2.1 Introduction

    +
    +

    +Let’s now consider a general support described by its compliance \(G^\prime(s) = \frac{x^\prime}{F^\prime}\) as shown in Figure 4. +

    + + +
    +

    general_support_compliance.png +

    +

    Figure 4: General support

    +
    + +

    +Now let’s consider the system consisting of a mass-spring-system (the isolation platform) on top of a general support as shown in Figure 5. +

    + +
    +

    general_support_with_isolator.png +

    +

    Figure 5: Mass-Spring-Damper system on top of a general support

    +
    +
    +
    + +
    +

    2.2 Equations of motion

    +
    +

    +We have to following equations of motion: +

    +\begin{align} + ms^2 x &= F + (cs + k) (x^\prime - x) \\ + F^\prime &= -F + (cs + k)(x - x^\prime) \\ + \frac{x^\prime}{F^\prime} &= G^\prime(s) +\end{align} + +

    +And by eliminating \(F^\prime\) and \(x^\prime\), we find the plant dynamics \(G(s) = \frac{x}{F}\). +

    + +
    +\begin{equation} + \frac{x}{F} = \frac{1}{ms^2 + cs + k + ms^2(cs + k)G^\prime(s)} \label{eq:plant_dynamics_general_support} +\end{equation} + +
    + +

    +In order to verify that the formula is correct, let’s take the same mass-spring-damper system used in the system shown in Figure 1: +\[ \frac{x^\prime}{F^\prime} = \frac{1}{m^\prime s^2 + c^\prime s + k^\prime} \] +

    + +

    +And we obtain +\[ \frac{x}{F} = \frac{m^\prime s^2 + c^\prime s + k^\prime}{(ms^2 + cs + k)(m^\prime s^2 + c^\prime s + k^\prime) + ms^2(cs + k)} \] +Which is the same transfer function that was obtained in section 1 (Eq. \eqref{org2d73355}). +

    +
    +
    + +
    +

    2.3 Compliance of the Support

    +
    +

    +We model the support by a mass-spring-damper model with some uncertainty. +

    + +

    +The nominal compliance of the support is corresponding to the compliance of a mass-spring-damper system with a mass of \(1000\ kg\) and a stiffness of \(10^8\ [N/m]\). +The main resonance of the support is then \(\omega^\prime = \sqrt{\frac{m^\prime}{k^\prime}} \approx 50\ Hz\). +

    + +
    +
    m0 = 1e3;
    +c0 = 5e4;
    +k0 = 1e8;
    +
    +Gp0 = 1/(m0*s^2 + c0*s + k0);
    +
    +
    + +

    +Let’s represent the uncertainty on the compliance of the support by a multiplicative uncertainty (Figure 6): +\[ G^\prime(s) = G_0^\prime(s)(1 + w_I^\prime(s)\Delta_I(s)) \quad |\Delta_I(j\omega)| < 1\ \forall \omega \] +

    + +

    +This could represent unmodelled dynamics or unknown parameters of the support. +

    + + +
    +

    input_uncertainty_set.png +

    +

    Figure 6: Input Multiplicative Uncertainty

    +
    + +

    +We choose a simple uncertainty weight: +\[ w_I(s) = \frac{\tau s + r_0}{(\tau/r_\infty) s + 1} \] +where \(r_0\) is the relative uncertainty at steady-state, \(1/\tau\) is the frequency at which the relative uncertainty reaches \(100\ \%\), and \(r_\infty\) is the magnitude of the weight at high frequency. +

    + +

    +The parameters are defined below. +

    +
    +
    r0 = 0.5;
    +tau = 1/(50*2*pi);
    +rinf = 10;
    +
    +wI = (tau*s + r0)/((tau/rinf)*s + 1);
    +
    +
    + +

    +We then generate a complex \(\Delta\). +

    +
    +
    DeltaI = ucomplex('A',0);
    +
    +
    + +

    +We generate the uncertain plant \(G^\prime(s)\). +

    +
    +
    Gp = Gp0*(1+wI*DeltaI);
    +
    +
    + +

    +A set of uncertainty support’s compliance transfer functions is shown in Figure 7. +

    + + +
    +

    compliance_support_uncertainty.png +

    +

    Figure 7: Uncertainty of the support’s compliance (png, pdf)

    +
    +
    +
    + +
    +

    2.4 Effect of the Isolation platform Stiffness.

    +
    +

    +Let’s first fix the mass of the payload to be isolated: +

    +
    +
    m = 100;
    +
    +
    + +

    +And we generate three isolation platforms: +

    +
      +
    • A soft one with \(\omega_0 = 5\ Hz\)
    • +
    • A medium stiff one with \(\omega_0 = 50\ Hz\)
    • +
    • A stiff one with \(\omega_0 = 500\ Hz\)
    • +
    + +

    +Soft Isolation Platform: +

    +
    +
    k_soft = m*(2*pi*5)^2;
    +c_soft = 0.1*sqrt(m*k_soft);
    +
    +G_soft = 1/(m*s^2 + c_soft*s + k_soft + m*s^2*(c_soft*s + k_soft)*Gp);
    +
    +
    + +

    +Mid Isolation Platform +

    +
    +
    k_mid = m*(2*pi*50)^2;
    +c_mid = 0.1*sqrt(m*k_mid);
    +
    +G_mid = 1/(m*s^2 + c_mid*s + k_mid + m*s^2*(c_mid*s + k_mid)*Gp);
    +
    +
    + +

    +Stiff Isolation Platform +

    +
    +
    k_stiff = m*(2*pi*500)^2;
    +c_stiff = 0.1*sqrt(m*k_stiff);
    +
    +G_stiff = 1/(m*s^2 + c_stiff*s + k_stiff + m*s^2*(c_stiff*s + k_stiff)*Gp);
    +
    +
    + +

    +The obtained transfer functions \(x/F\) for each of the three platforms are shown in Figure 8. +

    + +
    +

    plant_uncertainty_stiffness_isolator.png +

    +

    Figure 8: Obtained plant for the three isolators (png, pdf)

    +
    + +

    +The obtain result is very similar to the one obtain in section 1, except for the stiff isolation that experience lot’s of uncertainty at high frequency. +This is due to the fact that with the current model, at high frequency, the support’s compliance uncertainty is much higher than the previous model. +

    +
    +
    + +
    +

    2.5 Equivalent Inverse Multiplicative Uncertainty

    +
    +

    +Let’s express the uncertainty of the plant \(x/F\) as a function of the parameters as well as of the uncertainty on the platform’s compliance: +

    +\begin{align*} + \frac{x}{F} &= \frac{1}{ms^2 + cs + k + ms^2(cs + k)G_0^\prime(s)(1 + w_I(s)\Delta(s))}\\ + &= \frac{1}{ms^2 + cs + k + ms^2(cs + k)G_0^\prime(s) + ms^2(cs + k)G_0^\prime(s) w_I(s)\Delta(s)}\\ + &= \frac{1}{ms^2 + cs + k + ms^2(cs + k)G_0^\prime(s)} \cdot \frac{1}{1 + \frac{ms^2(cs + k)G_0^\prime(s) w_I(s)}{ms^2 + cs + k + ms^2(cs + k)G_0^\prime(s)} \Delta(s)}\\ +\end{align*} + +

    +We can rewrite that as an inverse multiplicative uncertainty (Figure 9): +

    +
    +\begin{equation} + \frac{x}{F} = G_0(s) (1 + w_{iI}(s) \Delta(s))^{-1} +\end{equation} +

    +with: +

    +
      +
    • \(G_0(s) = \frac{1}{ms^2 + cs + k + ms^2(cs + k)G_0^\prime(s)}\)
    • +
    • \(w_{iI}(s) = \frac{ms^2(cs + k)G_0^\prime(s) w_I(s)}{ms^2 + cs + k + ms^2(cs + k)G_0^\prime(s)} = G_0(s) ms^2(cs + k)G_0^\prime(s) w_I(s)\)
    • +
    + +
    + + +
    +

    inverse_uncertainty_set.png +

    +

    Figure 9: Inverse Multiplicative Uncertainty

    +
    +
    +
    + +
    +

    2.6 Reduce the Uncertainty on the plant

    +
    +

    +Now that we know the expression of the uncertainty on the plant, we can wonder what parameters of the isolation platform would lower the plant uncertainty, or at least bring the uncertainty to reasonable level. +

    + +

    +The uncertainty of the plant is described by an inverse multiplicative uncertainty with the following weight: +\[ w_{iI}(s) = \frac{ms^2(cs + k)G_0^\prime(s) w_I(s)}{ms^2 + cs + k + ms^2(cs + k)G_0^\prime(s)} \] +

    + +

    +Let’s study separately the effect of the platform’s mass, damping and stiffness. +

    +
    + +
    +

    2.6.1 Effect of the platform’s stiffness \(k\)

    +
    +

    +Let’s fix \(\xi = \frac{c}{2\sqrt{km}} = 0.1\), \(m = 100\ [kg]\) and see the evolution of \(|w_{iI}(j\omega)|\) with \(k\). +

    + +

    +This is first shown for few values of the stiffness \(k\) in figure 10 +

    + + +
    +

    inverse_multiplicative_uncertainty_norm_few_k.png +

    +

    Figure 10: caption (png, pdf)

    +
    + +

    +The norm of the uncertainty weight \(|w_iI(j\omega)|\) is displayed as a function of \(\omega\) and \(k\) in Figure 11. +

    + + +
    +

    inverse_multiplicative_uncertainty_norm_k.png +

    +

    Figure 11: Evolution of the norm of the uncertainty weight \(|w_{iI}(j\omega)|\) as a function of the platform’s stiffness \(k\) (png, pdf)

    +
    + +

    +Instead of plotting as a function of the platform’s stiffness, we can plot as a function of \(\omega_0/\omega_0^\prime\) where: +

    +
      +
    • \(\omega_0\) is the resonance of the platform alone
    • +
    • \(\omega_0^\prime\) is the resonance of the support alone
    • +
    + +

    +The obtain plot is shown in Figure 12. +In that case, we can see that with a platform’s resonance frequency 10 times lower than the resonance of the support, we get less than \(1\%\) uncertainty. +

    + + +
    +

    inverse_multiplicative_uncertainty_k_normalized_frequency.png +

    +

    Figure 12: Evolution of the norm of the uncertainty weight \(|w_{iI}(j\omega)|\) as a function of the frequency ratio \(\omega_0/\omega_0^\prime\) (png, pdf)

    +
    +
    +
    + +
    +

    2.6.2 Effect of the platform’s damping \(c\)

    +
    +

    +Let’s fix \(k = 10^7\ [N/m]\), \(m = 100\ [kg]\) and see the evolution of \(|w_{iI}(j\omega)|\) with the isolator damping \(c\) (Figure 13). +

    + + +
    +

    inverse_multiplicative_uncertainty_norm_c.png +

    +

    Figure 13: Evolution of the norm of the uncertainty weight \(|w_{iI}(j\omega)|\) as a function of the platform’s damping ratio \(\xi\) (png, pdf)

    +
    +
    +
    + + +
    +

    2.6.3 Effect of the platform’s mass \(m\)

    +
    +

    +Let’s fix \(k = 10^7\ [N/m]\), \(\xi = \frac{c}{2\sqrt{km}} = 0.1\) and see the evolution of \(|w_{iI}(j\omega)|\) with the payload mass \(m\) (Figure 14). +

    + + +
    +

    inverse_multiplicative_uncertainty_norm_m.png +

    +

    Figure 14: Evolution of the norm of the uncertainty weight \(|w_{iI}(j\omega)|\) as a function of the payload mass \(m\) (png, pdf)

    +
    +
    +
    +
    + +
    +

    2.7 Conclusion

    +
    +

    +If the goal is to have an acceptable (\(<10\%\)) uncertainty on the plant until the highest frequency, two design choice for the isolation platform are possible: +

    +
      +
    • a very soft isolation platform \(\omega_0 \ll \omega_0^\prime\)
    • +
    • a very stiff isolation platform \(\omega_0 \gg \omega_0^\prime\)
    • +
    + +

    +If a very soft isolation platform is used, the uncertainty due to the support’s compliance is filtered out and never reaches problematic values. +

    + +

    +If a very stiff isolation platform is used, the uncertainty will be high around \(\omega_0^\prime\) and may reach unacceptable value. +It will then be high around \(\omega_0\) and probably be higher than one. +Thus, if a stiff isolation platform is used, the recommendation is to have the largest possible resonance frequency, as the control bandwidth will be limited by the first resonance of the isolation platform (if not already limited by the resonance of the support). +

    +
    +
    +
    +
    +
    +

    Author: Dehaeze Thomas

    +

    Created: 2020-03-25 mer. 19:20

    +
    + + diff --git a/mat/cascade_hac_lac.mat b/mat/cascade_hac_lac.mat index 090e5b9..fdfb9d6 100644 Binary files a/mat/cascade_hac_lac.mat and b/mat/cascade_hac_lac.mat differ diff --git a/mat/conf_log.mat b/mat/conf_log.mat index 4b3a718..e40e9c9 100644 Binary files a/mat/conf_log.mat and b/mat/conf_log.mat differ diff --git a/mat/conf_simscape.mat b/mat/conf_simscape.mat index 4413f39..94c9f37 100644 Binary files a/mat/conf_simscape.mat and b/mat/conf_simscape.mat differ diff --git a/mat/controller.mat b/mat/controller.mat index 3dcb904..c2e3996 100644 Binary files a/mat/controller.mat and b/mat/controller.mat differ diff --git a/mat/nass_disturbances.mat b/mat/nass_disturbances.mat index 00a7953..ba98730 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 3aeeba1..1919daa 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 f1fd124..4ef4f8a 100644 Binary files a/mat/stages.mat and b/mat/stages.mat differ diff --git a/matlab/nass_model.slx b/matlab/nass_model.slx index 9747e84..caf701e 100644 Binary files a/matlab/nass_model.slx and b/matlab/nass_model.slx differ diff --git a/org/control_hac_lac.org b/org/control_hac_lac.org index e8803dd..0d6923e 100644 --- a/org/control_hac_lac.org +++ b/org/control_hac_lac.org @@ -77,7 +77,7 @@ It is then compare to the wanted position of the Sample $\bm{r}_\mathcal{X}$ in \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[->] (Kx.east) node[above right]{$\bm{\tau}^\prime$} -- (addF.west); \draw[->] (addF.east) -- (G.west) node[above left]{$\bm{\tau}$}; \draw[->] ($(outputL.east) + (0.4, 0)$)node[branch](L){} |- (subl.east); @@ -294,6 +294,100 @@ The design of the associated decentralized controller is explained in [[file:con K_dvf = -K_dvf*eye(6); #+end_src +* Uncertainty Improvements thanks to the LAC control +#+begin_src matlab + K_dvf_backup = K_dvf; + initializeController('type', 'hac-dvf'); +#+end_src + +#+begin_src matlab + masses = [1, 10, 50]; % [kg] +#+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 +#+end_src + +#+begin_src matlab :exports none + Gm = {zeros(length(masses))}; + + K_dvf = tf(zeros(6)); + Kx = tf(zeros(6)); + + for i = 1:length(masses) + initializeSample('mass', masses(i)); + + %% Run the linearization + G = linearize(mdl, io, 0); + G.InputName = {'Fnl1', 'Fnl2', 'Fnl3', 'Fnl4', 'Fnl5', 'Fnl6'}; + G.OutputName = {'Ex', 'Ey', 'Ez', 'Erx', 'Ery', 'Erz'}; + + Gm(i) = {G}; + end +#+end_src + +#+begin_src matlab :exports none + Gm_iff = {zeros(length(masses))}; + + K_dvf = K_dvf_backup; + Kx = tf(zeros(6)); + + for i = 1:length(masses) + initializeSample('mass', masses(i)); + + %% Run the linearization + G = linearize(mdl, io, 0); + G.InputName = {'Fnl1', 'Fnl2', 'Fnl3', 'Fnl4', 'Fnl5', 'Fnl6'}; + G.OutputName = {'Ex', 'Ey', 'Ez', 'Erx', 'Ery', 'Erz'}; + + Gm_iff(i) = {G}; + end +#+end_src + +#+begin_src matlab :exports none + freqs = logspace(0, 3, 1000); + + figure; + + ax1 = subplot(2, 1, 1); + hold on; + for i = 1:length(Gm_iff) + set(gca,'ColorOrderIndex',i); + plot(freqs, abs(squeeze(freqresp(Gm{i}(1, 1), freqs, 'Hz'))), '-'); + set(gca,'ColorOrderIndex',i); + plot(freqs, abs(squeeze(freqresp(Gm_iff{i}(1, 1), 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:length(Gm_iff) + set(gca,'ColorOrderIndex',i); + plot(freqs, 180/pi*angle(squeeze(freqresp(Gm{i}(1, 1), freqs, 'Hz'))), '-', ... + 'DisplayName', sprintf('$M = %.0f$ [kg]', masses(i))); + set(gca,'ColorOrderIndex',i); + plot(freqs, 180/pi*angle(squeeze(freqresp(Gm_iff{i}(1, 1), freqs, 'Hz'))), '--', ... + 'HandleVisibility', 'off'); + 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('location', 'southwest'); + + linkaxes([ax1,ax2],'x'); + xlim([freqs(1), freqs(end)]); +#+end_src + * High Authority Control - $\bm{K}_\mathcal{X}$ ** Identification of the damped plant #+begin_src matlab diff --git a/org/control_voice_coil.org b/org/control_voice_coil.org index d9d3fc3..bbd36c8 100644 --- a/org/control_voice_coil.org +++ b/org/control_voice_coil.org @@ -42,3 +42,1063 @@ #+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 study the use of a voice coil based nano-hexapod. +That is to say a nano-hexapod with a very small stiffness. + +#+name: fig:cascade_control_architecture +#+caption: Cascaded Control consisting of (from inner to outer loop): IFF, Linearization Loop, Tracking Control in the frame of the Legs +#+RESULTS: +[[file:figs/cascade_control_architecture.png]] + +* Matlab Init :noexport:ignore: +#+begin_src matlab :tangle no :exports none :results silent :noweb yes :var current_dir=(file-name-directory buffer-file-name) +<> +#+end_src + +#+begin_src matlab :exports none :results silent :noweb yes +<> +#+end_src + +#+begin_src matlab :tangle no + simulinkproject('../'); +#+end_src + +#+begin_src matlab + open('nass_model.slx') +#+end_src + +* 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 voice coil based hexapod and the sample has a mass of 1kg. +#+begin_src matlab + initializeNanoHexapod('actuator', 'lorentz'); + 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 + +#+begin_src matlab + initializeController('type', 'cascade-hac-lac'); +#+end_src + +#+begin_src matlab + initializeSimscapeConfiguration('gravity', true); +#+end_src + +We log the signals. +#+begin_src matlab + initializeLoggingConfiguration('log', 'all'); +#+end_src + +#+begin_src matlab + Kx = tf(zeros(6)); + Kl = tf(zeros(6)); + Kiff = tf(zeros(6)); +#+end_src + +* Low Authority Control - Integral Force Feedback $\bm{K}_\text{IFF}$ +<> +** Identification +Let's first identify the plant for the IFF controller. +#+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', [], 'Fnlm'); io_i = io_i + 1; % Force Sensors + + %% Run the linearization + G_iff = linearize(mdl, io, 0); + G_iff.InputName = {'Fnl1', 'Fnl2', 'Fnl3', 'Fnl4', 'Fnl5', 'Fnl6'}; + G_iff.OutputName = {'Fnlm1', 'Fnlm2', 'Fnlm3', 'Fnlm4', 'Fnlm5', 'Fnlm6'}; +#+end_src + +** Plant +The obtained plant for IFF is shown in Figure [[fig:cascade_vc_iff_plant]]. + +#+begin_src matlab :exports none + freqs = logspace(-1, 3, 1000); + + figure; + + ax1 = subplot(2, 2, 1); + hold on; + for i = 1:6 + plot(freqs, abs(squeeze(freqresp(G_iff(i, i), freqs, 'Hz')))); + end + hold off; + set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log'); + ylabel('Amplitude [N/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(G_iff(i, i), freqs, 'Hz'))), 'DisplayName', sprintf('$\\tau_{m,%i}/\\tau_%i$', i, 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('location', 'northeast'); + + ax3 = subplot(2, 2, 2); + hold on; + for i = 1:5 + for j = i+1:6 + plot(freqs, abs(squeeze(freqresp(G_iff(i, j), freqs, 'Hz'))), 'color', [0, 0, 0, 0.2]); + end + end + set(gca,'ColorOrderIndex',1); + plot(freqs, abs(squeeze(freqresp(G_iff(1, 1), freqs, 'Hz')))); + hold off; + set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log'); + ylabel('Amplitude [N/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(G_iff(i, j), freqs, 'Hz'))), 'color', [0, 0, 0, 0.2]); + end + end + set(gca,'ColorOrderIndex',1); + plot(freqs, 180/pi*angle(squeeze(freqresp(G_iff(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 + +#+header: :tangle no :exports results :results none :noweb yes +#+begin_src matlab :var filepath="figs/cascade_vc_iff_plant.pdf" :var figsize="full-tall" :post pdf2svg(file=*this*, ext="png") +<> +#+end_src + +#+name: fig:cascade_vc_iff_plant +#+caption: IFF Plant ([[./figs/cascade_vc_iff_plant.png][png]], [[./figs/cascade_vc_iff_plant.pdf][pdf]]) +[[file:figs/cascade_vc_iff_plant.png]] + +** Root Locus +As seen in the root locus (Figure [[fig:cascade_vc_iff_root_locus]], no damping can be added to modes corresponding to the resonance of the micro-station. + +However, critical damping can be achieve for the resonances of the nano-hexapod as shown in the zoomed part of the root (Figure [[fig:cascade_vc_iff_root_locus]], left part). +The maximum damping is obtained for a control gain of $\approx 70$. + +#+begin_src matlab :exports none + gains = logspace(0, 4, 500); + + figure; + + subplot(1, 2, 1); + hold on; + plot(real(pole(G_iff)), imag(pole(G_iff)), 'x'); + set(gca,'ColorOrderIndex',1); + plot(real(tzero(G_iff)), imag(tzero(G_iff)), 'o'); + for i = 1:length(gains) + set(gca,'ColorOrderIndex',1); + cl_poles = pole(feedback(G_iff, -(gains(i)/s)*eye(6))); + plot(real(cl_poles), imag(cl_poles), '.'); + end + ylim([0, 2*pi*500]); + xlim([-2*pi*500,0]); + xlabel('Real Part') + ylabel('Imaginary Part') + axis square + + subplot(1, 2, 2); + hold on; + plot(real(pole(G_iff)), imag(pole(G_iff)), 'x'); + set(gca,'ColorOrderIndex',1); + plot(real(tzero(G_iff)), imag(tzero(G_iff)), 'o'); + for i = 1:length(gains) + set(gca,'ColorOrderIndex',1); + cl_poles = pole(feedback(G_iff, -(gains(i)/s)*eye(6))); + plot(real(cl_poles), imag(cl_poles), '.'); + end + ylim([0, 2*pi*8]); + xlim([-2*pi*8,0]); + xlabel('Real Part') + ylabel('Imaginary Part') + axis square +#+end_src + +#+header: :tangle no :exports results :results none :noweb yes +#+begin_src matlab :var filepath="figs/cascade_vc_iff_root_locus.pdf" :var figsize="wide-tall" :post pdf2svg(file=*this*, ext="png") +<> +#+end_src + +#+name: fig:cascade_vc_iff_root_locus +#+caption: Root Locus for the IFF control ([[./figs/cascade_vc_iff_root_locus.png][png]], [[./figs/cascade_vc_iff_root_locus.pdf][pdf]]) +[[file:figs/cascade_vc_iff_root_locus.png]] + +** Controller and Loop Gain +We create the $6 \times 6$ diagonal Integral Force Feedback controller. +The obtained loop gain is shown in Figure [[fig:cascade_vc_iff_loop_gain]]. +#+begin_src matlab + Kiff = -70/s*eye(6); +#+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(Kiff(i,i)*G_iff(i,i), freqs, 'Hz')))); + end + hold off; + set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log'); + ylabel('Loop Gain'); set(gca, 'XTickLabel',[]); + + ax2 = subplot(2, 1, 2); + hold on; + for i = 1:6 + plot(freqs, 180/pi*angle(squeeze(freqresp(Kiff(i,i)*G_iff(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 + +#+header: :tangle no :exports results :results none :noweb yes +#+begin_src matlab :var filepath="figs/cascade_vc_iff_loop_gain.pdf" :var figsize="full-tall" :post pdf2svg(file=*this*, ext="png") +<> +#+end_src + +#+name: fig:cascade_vc_iff_loop_gain +#+caption: Obtained Loop gain the IFF Control ([[./figs/cascade_vc_iff_loop_gain.png][png]], [[./figs/cascade_vc_iff_loop_gain.pdf][pdf]]) +[[file:figs/cascade_vc_iff_loop_gain.png]] + +* High Authority Control in the joint space - $\bm{K}_\mathcal{L}$ +<> +** Identification of the damped plant +Let's identify the dynamics from $\bm{\tau}^\prime$ to $d\bm{\mathcal{L}}$ as shown in Figure [[fig:cascade_control_architecture]]. + +#+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, '/Micro-Station'], 3, 'output', [], 'Dnlm'); io_i = io_i + 1; % Leg Displacement + + %% Run the linearization + Gl = linearize(mdl, io, 0); + Gl.InputName = {'Fnl1', 'Fnl2', 'Fnl3', 'Fnl4', 'Fnl5', 'Fnl6'}; + Gl.OutputName = {'Dnlm1', 'Dnlm2', 'Dnlm3', 'Dnlm4', 'Dnlm5', 'Dnlm6'}; +#+end_src + +There are some unstable poles in the Plant with very small imaginary parts. +These unstable poles are probably not physical, and they disappear when taking the minimum realization of the plant. +#+begin_src matlab + isstable(Gl) + Gl = minreal(Gl); + isstable(Gl) +#+end_src + +** Obtained Plant +The obtained dynamics is shown in Figure [[fig:cascade_vc_hac_joint_plant]]. + +Few things can be said on the dynamics: +- the dynamics of the diagonal elements are almost all the same +- the system is well decoupled below the resonances of the nano-hexapod (1Hz) +- the dynamics of the diagonal elements are almost equivalent to a critically damped mass-spring-system with some spurious resonances above 50Hz corresponding to the resonances of the micro-station + +#+begin_src matlab :exports none + freqs = logspace(-1, 3, 1000); + + figure; + + ax1 = subplot(2, 2, 1); + hold on; + for i = 1:6 + plot(freqs, abs(squeeze(freqresp(Gl(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(Gl(i, i), freqs, 'Hz'))), 'DisplayName', sprintf('$d\\mathcal{L}_%i/\\tau_%i$', i, 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(Gl(i, j), freqs, 'Hz'))), 'color', [0, 0, 0, 0.2]); + end + end + set(gca,'ColorOrderIndex',1); + plot(freqs, abs(squeeze(freqresp(Gl(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(Gl(i, j), freqs, 'Hz'))), 'color', [0, 0, 0, 0.2]); + end + end + set(gca,'ColorOrderIndex',1); + plot(freqs, 180/pi*angle(squeeze(freqresp(Gl(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 + +#+header: :tangle no :exports results :results none :noweb yes +#+begin_src matlab :var filepath="figs/cascade_vc_hac_joint_plant.pdf" :var figsize="full-tall" :post pdf2svg(file=*this*, ext="png") +<> +#+end_src + +#+name: fig:cascade_vc_hac_joint_plant +#+caption: Plant for the High Authority Control in the Joint Space ([[./figs/cascade_vc_hac_joint_plant.png][png]], [[./figs/cascade_vc_hac_joint_plant.pdf][pdf]]) +[[file:figs/cascade_vc_hac_joint_plant.png]] + +** Controller Design and Loop Gain +As the plant is well decoupled, a diagonal plant is designed. + +#+begin_src matlab + wc = 2*pi*5; % Bandwidth Bandwidth [rad/s] + + h = 2; % Lead parameter + + Kl = (1/h) * (1 + s/wc*h)/(1 + s/wc/h) * ... % Lead + (1/h) * (1 + s/wc*h)/(1 + s/wc/h) * ... % Lead + (s + 2*pi*10)/s * ... % Weak Integrator + (s + 2*pi*1)/s * ... % Weak Integrator + 1/(1 + s/2/pi/10); % Low pass filter after crossover + + % Normalization of the gain of have a loop gain of 1 at frequency wc + Kl = Kl.*diag(1./diag(abs(freqresp(Gl*Kl, wc)))); +#+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(Gl(i, i)*Kl(i,i), freqs, 'Hz')))); + end + hold off; + set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log'); + ylabel('Loop Gain'); set(gca, 'XTickLabel',[]); + + ax2 = subplot(2, 1, 2); + hold on; + for i = 1:6 + plot(freqs, 180/pi*angle(squeeze(freqresp(Gl(i, i)*Kl(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 :exports none :tangle no + isstable(feedback(Gl*Kl, eye(6), -1)) +#+end_src + +* On the usefulness of the High Authority Control loop / Linearization loop +** Introduction :ignore: +Let's see what happens is we omit the HAC loop and we directly try to control the damped plant using the measurement of the sample with respect to the granite $\bm{\mathcal{X}}$. + +We can do that in two different ways: +- in the task space as shown in Figure [[fig:control_architecture_iff_X]] +- in the space of the legs as shown in Figure [[fig:control_architecture_iff_L]] + +#+begin_src latex :file control_architecture_iff_X.pdf + \begin{tikzpicture} + % Blocs + \node[block={3.0cm}{3.0cm}] (P) {Plant}; + \coordinate[] (inputF) at ($(P.south west)!0.5!(P.north west)$); + \coordinate[] (outputF) at ($(P.south east)!0.8!(P.north east)$); + \coordinate[] (outputX) at ($(P.south east)!0.5!(P.north east)$); + \coordinate[] (outputL) at ($(P.south east)!0.2!(P.north east)$); + + \node[block, above=0.4 of P] (Kiff) {$\bm{K}_\text{IFF}$}; + \node[addb={+}{}{-}{}{}, left= of inputF] (addF) {}; + \node[block, left= of addF] (J) {$\bm{J}^{-T}$}; + \node[block, left= of J] (K) {$\bm{K}_\mathcal{X}$}; + \node[addb={+}{}{}{}{-}, left= of K] (subr) {}; + + % Connections and labels + \draw[->] (outputF) -- ++(1, 0) node[below left]{$\bm{\tau}_m$}; + \draw[->] ($(outputF) + (0.6, 0)$)node[branch]{} |- (Kiff.east); + \draw[->] (Kiff.west) -| (addF.north); + \draw[->] (addF.east) -- (inputF) node[above left]{$\bm{\tau}$}; + + \draw[->] (outputL) -- ++(1, 0) node[above left]{$d\bm{\mathcal{L}}$}; + + \draw[->] (outputX) -- ++(1.6, 0); + \draw[->] ($(outputX) + (1.2, 0)$)node[branch]{} node[above]{$\bm{\mathcal{X}}$} -- ++(0, -2) -| (subr.south); + + \draw[<-] (subr.west)node[above left]{$\bm{r}_{\mathcal{X}}$} -- ++(-1, 0); + \draw[->] (subr.east) -- (K.west) node[above left]{$\bm{\epsilon}_{\mathcal{X}}$}; + \draw[->] (K.east) -- (J.west) node[above left]{$\bm{\mathcal{F}}$}; + \draw[->] (J.east) -- (addF.west) node[above left]{$\bm{\tau}^\prime$}; + \end{tikzpicture} +#+end_src + +#+name: fig:control_architecture_iff_X +#+caption: IFF control + primary controller in the task space +#+RESULTS: +[[file:figs/control_architecture_iff_X.png]] + +#+begin_src latex :file control_architecture_iff_L.pdf + \begin{tikzpicture} + % Blocs + \node[block={3.0cm}{3.0cm}] (P) {Plant}; + \coordinate[] (inputF) at ($(P.south west)!0.5!(P.north west)$); + \coordinate[] (outputF) at ($(P.south east)!0.8!(P.north east)$); + \coordinate[] (outputX) at ($(P.south east)!0.5!(P.north east)$); + \coordinate[] (outputL) at ($(P.south east)!0.2!(P.north east)$); + + \node[block, above=0.4 of P] (Kiff) {$\bm{K}_\text{IFF}$}; + \node[addb={+}{}{-}{}{}, left= of inputF] (addF) {}; + \node[block, left= of addF] (K) {$\bm{K}_\mathcal{L}$}; + \node[block, left= of K] (J) {$\bm{J}$}; + \node[addb={+}{}{}{}{-}, left= of J] (subr) {}; + + % Connections and labels + \draw[->] (outputF) -- ++(1, 0) node[below left]{$\bm{\tau}_m$}; + \draw[->] ($(outputF) + (0.6, 0)$)node[branch]{} |- (Kiff.east); + \draw[->] (Kiff.west) -| (addF.north); + \draw[->] (addF.east) -- (inputF) node[above left]{$\bm{\tau}$}; + + \draw[->] (outputL) -- ++(1, 0) node[above left]{$d\bm{\mathcal{L}}$}; + + \draw[->] (outputX) -- ++(1.6, 0); + \draw[->] ($(outputX) + (1.2, 0)$)node[branch]{} node[above]{$\bm{\mathcal{X}}$} -- ++(0, -2) -| (subr.south); + + \draw[<-] (subr.west)node[above left]{$\bm{r}_{\mathcal{X}}$} -- ++(-1, 0); + \draw[->] (subr.east) -- (J.west) node[above left]{$\bm{\epsilon}_{\mathcal{X}}$}; + \draw[->] (J.east) -- (K.west) node[above left]{$\bm{\epsilon}_{\mathcal{L}}$}; + \draw[->] (K.east) -- (addF.west) node[above left]{$\bm{\tau}^\prime$}; + \end{tikzpicture} +#+end_src + +#+name: fig:control_architecture_iff_L +#+caption: HAC-LAC control architecture in the frame of the legs +#+RESULTS: +[[file:figs/control_architecture_iff_L.png]] + +** Identification +#+begin_src matlab + initializeController('type', 'hac-iff'); +#+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/HAC-IFF/Kx'], 1, 'input'); io_i = io_i + 1; + 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 = {'F1', 'F2', 'F3', 'F4', 'F5', 'F6'}; + G.OutputName = {'Ex', 'Ey', 'Ez', 'Erx', 'Ery', 'Erz'}; +#+end_src + +#+begin_src matlab + isstable(G) + G = -minreal(G); + isstable(G) +#+end_src + +** Plant in the Task space +The obtained plant is shown in Figure + +#+begin_src matlab + Gx = G*inv(nano_hexapod.J'); +#+end_src + +#+begin_src matlab :exports none + freqs = logspace(-1, 4, 1000); + + labels = {'$\epsilon_x/\mathcal{F}_{x}$', '$\epsilon_y/\mathcal{F}_{y}$', '$\epsilon_z/\mathcal{F}_{z}$', '$\epsilon_{R_x}/\mathcal{M}_{x}$', '$\epsilon_{R_y}/\mathcal{M}_{y}$', '$\epsilon_{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 + +** Plant in the Leg's space +#+begin_src matlab + Gl = nano_hexapod.J*G; +#+end_src + +#+begin_src matlab :exports none + freqs = logspace(-1, 4, 1000); + + figure; + + ax1 = subplot(2, 2, 1); + hold on; + for i = 1:6 + plot(freqs, abs(squeeze(freqresp(Gl(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(Gl(i, i), freqs, 'Hz'))), 'DisplayName', sprintf('$d\\mathcal{L}_%i/\\tau_%i$', i, 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(Gl(i, j), freqs, 'Hz'))), 'color', [0, 0, 0, 0.2]); + end + end + set(gca,'ColorOrderIndex',1); + plot(freqs, abs(squeeze(freqresp(Gl(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(Gl(i, j), freqs, 'Hz'))), 'color', [0, 0, 0, 0.2]); + end + end + set(gca,'ColorOrderIndex',1); + plot(freqs, 180/pi*angle(squeeze(freqresp(Gl(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 + +* Primary Controller in the task space - $\bm{K}_\mathcal{X}$ +<> +** Identification of the linearized plant +We know identify the dynamics between $\bm{r}_{\mathcal{X}_n}$ and $\bm{r}_\mathcal{X}$. +#+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/Cascade-HAC-LAC/Kx'], 1, 'input'); io_i = io_i + 1; + io(io_i) = linio([mdl, '/Tracking Error'], 1, 'output', [], 'En'); io_i = io_i + 1; % Position Errror + + %% Run the linearization + Gx = linearize(mdl, io, 0); + Gx.InputName = {'rL1', 'rL2', 'rL3', 'rL4', 'rL5', 'rL6'}; + Gx.OutputName = {'Ex', 'Ey', 'Ez', 'Erx', 'Ery', 'Erz'}; +#+end_src + +As before, we take the minimum realization. +#+begin_src matlab + isstable(Gx) + Gx = -minreal(Gx); + isstable(Gx) +#+end_src + +** Obtained Plant +#+begin_src matlab :exports none + freqs = logspace(0, 4, 1000); + + labels = {'$\epsilon_x/r_{xn}$', '$\epsilon_y/r_{yn}$', '$\epsilon_z/r_{zn}$', '$\epsilon_{R_x}/r_{R_xn}$', '$\epsilon_{R_y}/r_{R_yn}$', '$\epsilon_{R_z}/r_{R_zn}$'}; + + 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 +#+begin_src matlab + wc = 2*pi*200; % Bandwidth Bandwidth [rad/s] + + h = 2; % Lead parameter + + Kx = (1/h) * (1 + s/wc*h)/(1 + s/wc/h) * ... + (s + 2*pi*10)/s * ... + (s + 2*pi*100)/s * ... + 1/(1+s/2/pi/500); % For Piezo + % Kx = (1/h) * (1 + s/wc*h)/(1 + s/wc/h) * (s + 2*pi*10)/s * (s + 2*pi*1)/s ; % For voice coil + + % 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); + + figure; + + ax1 = subplot(2, 1, 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('Loop Gain'); set(gca, 'XTickLabel',[]); + + ax2 = subplot(2, 1, 2); + hold on; + for i = 1:6 + plot(freqs, 180/pi*angle(squeeze(freqresp(Gx(i, i)*Kx(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 :exports none :tangle no + isstable(feedback(Gx*Kx, eye(6), -1)) +#+end_src + +* Simulation +#+begin_src matlab + load('mat/conf_simulink.mat'); + set_param(conf_simulink, 'StopTime', '2'); +#+end_src + +And we simulate the system. +#+begin_src matlab + sim('nass_model'); +#+end_src + +#+begin_src matlab + cascade_hac_lac_lorentz = simout; + save('./mat/cascade_hac_lac.mat', 'cascade_hac_lac_lorentz', '-append'); +#+end_src + +* Results +** Load the simulation results +#+begin_src matlab + load('./mat/experiment_tomography.mat', 'tomo_align_dist'); + load('./mat/cascade_hac_lac.mat', 'cascade_hac_lac', 'cascade_hac_lac_lorentz'); +#+end_src + +** Control effort +#+begin_src matlab :exports none + figure; + ax1 = subplot(1, 2, 1); + hold on; + for i = 1:6 + plot(cascade_hac_lac.u.Time, cascade_hac_lac.u.Data(:, i)) + end + hold off; + xlabel('Time [s]'); ylabel('Force applied by the Actuators [N]'); + + ax2 = subplot(1, 2, 2); + hold on; + for i = 1:6 + plot(cascade_hac_lac_lorentz.u.Time, cascade_hac_lac_lorentz.u.Data(:, i)) + end + hold off; + xlabel('Time [s]'); ylabel('Force applied by the Actuators [N]'); +#+end_src + +#+begin_src matlab :exports none + load('mat/stages.mat', 'nano_hexapod'); + + F_pz = [nano_hexapod.J'*cascade_hac_lac.u.Data']'; + F_vc = [nano_hexapod.J'*cascade_hac_lac_lorentz.u.Data']'; + + % F_pz = [-nano_hexapod.J'*cascade_hac_lac.yn.Fnlm.Data']'; + % F_vc = [-nano_hexapod.J'*cascade_hac_lac_lorentz.yn.Fnlm.Data']'; +#+end_src + +#+begin_src matlab :exports none + labels = {'$\mathcal{F}_x$', '$\mathcal{F}_y$', '$\mathcal{F}_z$', '$\mathcal{M}_x$', '$\mathcal{M}_y$', '$\mathcal{M}_z$'}; + + figure; + ax1 = subplot(1, 2, 1); + hold on; + for i = 1:6 + plot(cascade_hac_lac.u.Time, F_pz(:, i), 'DisplayName', labels{i}) + end + hold off; + xlabel('Time [s]'); ylabel('Force/Torque Piezo [N, N$\cdot$m]'); + legend('location', 'northeast'); + + ax2 = subplot(1, 2, 2); + hold on; + for i = 1:6 + plot(cascade_hac_lac_lorentz.u.Time, F_vc(:, i), 'DisplayName', labels{i}) + end + hold off; + xlabel('Time [s]'); ylabel('Force/Torque Lorentz [N, N$\cdot$m]'); + legend('location', 'northeast'); +#+end_src + +** Load the simulation results +#+begin_src matlab + n_av = 4; + han_win = hanning(ceil(length(cascade_hac_lac.Em.En.Data(:,1))/n_av)); +#+end_src + +#+begin_src matlab + t = cascade_hac_lac.Em.En.Time; + Ts = t(2)-t(1); + + [pxx_ol, f] = pwelch(tomo_align_dist.Em.En.Data, han_win, [], [], 1/Ts); + [pxx_ca, ~] = pwelch(cascade_hac_lac.Em.En.Data, han_win, [], [], 1/Ts); + [pxx_vc, ~] = pwelch(cascade_hac_lac_lorentz.Em.En.Data, han_win, [], [], 1/Ts); +#+end_src + +#+begin_src matlab :exports none + figure; + ax1 = subplot(2, 3, 1); + hold on; + plot(f, sqrt(pxx_ol(:, 1))) + plot(f, sqrt(pxx_vc(:, 1))) + hold off; + xlabel('Frequency [Hz]'); + ylabel('$\Gamma_{D_x}$ [$m/\sqrt{Hz}$]'); + set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log'); + + ax2 = subplot(2, 3, 2); + hold on; + plot(f, sqrt(pxx_ol(:, 2))) + plot(f, sqrt(pxx_vc(:, 2))) + hold off; + xlabel('Frequency [Hz]'); + ylabel('$\Gamma_{D_y}$ [$m/\sqrt{Hz}$]'); + set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log'); + + ax3 = subplot(2, 3, 3); + hold on; + plot(f, sqrt(pxx_ol(:, 3))) + plot(f, sqrt(pxx_vc(:, 3))) + hold off; + xlabel('Frequency [Hz]'); + ylabel('$\Gamma_{D_z}$ [$m/\sqrt{Hz}$]'); + set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log'); + + ax4 = subplot(2, 3, 4); + hold on; + plot(f, sqrt(pxx_ol(:, 4))) + plot(f, sqrt(pxx_vc(:, 4))) + hold off; + xlabel('Frequency [Hz]'); + ylabel('$\Gamma_{R_x}$ [$rad/\sqrt{Hz}$]'); + set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log'); + + ax5 = subplot(2, 3, 5); + hold on; + plot(f, sqrt(pxx_ol(:, 5))) + plot(f, sqrt(pxx_vc(:, 5))) + hold off; + xlabel('Frequency [Hz]'); + ylabel('$\Gamma_{R_y}$ [$rad/\sqrt{Hz}$]'); + set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log'); + + ax6 = subplot(2, 3, 6); + hold on; + plot(f, sqrt(pxx_ol(:, 6)), 'DisplayName', '$\mu$-Station') + plot(f, sqrt(pxx_vc(:, 6)), 'DisplayName', 'Cascade') + hold off; + xlabel('Frequency [Hz]'); + ylabel('$\Gamma_{R_z}$ [$rad/\sqrt{Hz}$]'); + legend('location', 'southwest'); + set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log'); + + linkaxes([ax1,ax2,ax3,ax4,ax5,ax6],'x'); + xlim([f(2), f(end)]) +#+end_src + +#+begin_src matlab :exports none + figure; + ax1 = subplot(2, 3, 1); + hold on; + plot(f, sqrt(flip(-cumtrapz(flip(f), flip(pxx_ol(:, 1)))))) + plot(f, sqrt(flip(-cumtrapz(flip(f), flip(pxx_vc(:, 1)))))) + hold off; + xlabel('Frequency [Hz]'); + ylabel('CAS $D_x$ [$m$]'); + set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log'); + + ax2 = subplot(2, 3, 2); + hold on; + plot(f, sqrt(flip(-cumtrapz(flip(f), flip(pxx_ol(:, 2)))))) + plot(f, sqrt(flip(-cumtrapz(flip(f), flip(pxx_vc(:, 2)))))) + hold off; + xlabel('Frequency [Hz]'); + ylabel('CAS $D_y$ [$m$]'); + set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log'); + + ax3 = subplot(2, 3, 3); + hold on; + plot(f, sqrt(flip(-cumtrapz(flip(f), flip(pxx_ol(:, 3)))))) + plot(f, sqrt(flip(-cumtrapz(flip(f), flip(pxx_vc(:, 3)))))) + hold off; + xlabel('Frequency [Hz]'); + ylabel('CAS $D_z$ [$m$]'); + set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log'); + + ax4 = subplot(2, 3, 4); + hold on; + plot(f, sqrt(flip(-cumtrapz(flip(f), flip(pxx_ol(:, 4)))))) + plot(f, sqrt(flip(-cumtrapz(flip(f), flip(pxx_vc(:, 4)))))) + hold off; + xlabel('Frequency [Hz]'); + ylabel('CAS $R_x$ [$rad$]'); + set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log'); + + ax5 = subplot(2, 3, 5); + hold on; + plot(f, sqrt(flip(-cumtrapz(flip(f), flip(pxx_ol(:, 5)))))) + plot(f, sqrt(flip(-cumtrapz(flip(f), flip(pxx_vc(:, 5)))))) + hold off; + xlabel('Frequency [Hz]'); + ylabel('CAS $R_y$ [$rad$]'); + set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log'); + + ax6 = subplot(2, 3, 6); + hold on; + plot(f, sqrt(flip(-cumtrapz(flip(f), flip(pxx_ol(:, 6))))), 'DisplayName', '$\mu$-Station') + plot(f, sqrt(flip(-cumtrapz(flip(f), flip(pxx_vc(:, 6))))), 'DisplayName', 'Cascade') + hold off; + xlabel('Frequency [Hz]'); + ylabel('CAS $R_z$ [$rad$]'); + legend('location', 'southwest'); + set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log'); + + linkaxes([ax1,ax2,ax3,ax4,ax5,ax6],'x'); + xlim([f(2), f(end)]) +#+end_src + +#+begin_src matlab :exports none + figure; + ax1 = subplot(2, 3, 1); + hold on; + plot(tomo_align_dist.Em.En.Time, tomo_align_dist.Em.En.Data(:, 1)) + plot(cascade_hac_lac_lorentz.Em.En.Time, cascade_hac_lac_lorentz.Em.En.Data(:, 1)) + hold off; + xlabel('Time [s]'); + ylabel('Dx [m]'); + + ax2 = subplot(2, 3, 2); + hold on; + plot(tomo_align_dist.Em.En.Time, tomo_align_dist.Em.En.Data(:, 2)) + plot(cascade_hac_lac_lorentz.Em.En.Time, cascade_hac_lac_lorentz.Em.En.Data(:, 2)) + hold off; + xlabel('Time [s]'); + ylabel('Dy [m]'); + + ax3 = subplot(2, 3, 3); + hold on; + plot(tomo_align_dist.Em.En.Time, tomo_align_dist.Em.En.Data(:, 3)) + plot(cascade_hac_lac_lorentz.Em.En.Time, cascade_hac_lac_lorentz.Em.En.Data(:, 3)) + hold off; + xlabel('Time [s]'); + ylabel('Dz [m]'); + + ax4 = subplot(2, 3, 4); + hold on; + plot(tomo_align_dist.Em.En.Time, tomo_align_dist.Em.En.Data(:, 4)) + plot(cascade_hac_lac_lorentz.Em.En.Time, cascade_hac_lac_lorentz.Em.En.Data(:, 4)) + hold off; + xlabel('Time [s]'); + ylabel('Rx [rad]'); + + ax5 = subplot(2, 3, 5); + hold on; + plot(tomo_align_dist.Em.En.Time, tomo_align_dist.Em.En.Data(:, 5)) + plot(cascade_hac_lac_lorentz.Em.En.Time, cascade_hac_lac_lorentz.Em.En.Data(:, 5)) + hold off; + xlabel('Time [s]'); + ylabel('Ry [rad]'); + + ax6 = subplot(2, 3, 6); + hold on; + plot(tomo_align_dist.Em.En.Time, tomo_align_dist.Em.En.Data(:, 6), 'DisplayName', '$\mu$-Station') + plot(cascade_hac_lac_lorentz.Em.En.Time, cascade_hac_lac_lorentz.Em.En.Data(:, 6), 'DisplayName', 'Cascade') + hold off; + xlabel('Time [s]'); + ylabel('Rz [rad]'); + legend(); + + linkaxes([ax1,ax2,ax3,ax4],'x'); + xlim([0.5, inf]); +#+end_src diff --git a/org/index.org b/org/index.org index a81f4dd..4e96e0e 100644 --- a/org/index.org +++ b/org/index.org @@ -82,12 +82,16 @@ Now that the dynamics of the Model have been tuned and the Disturbances have inc Tomography experiments are simulated and the results are presented [[./experiments.org][here]]. +* Effect of support's compliance uncertainty on the plant ([[file:uncertainty_support.org][link]]) +In this document, is studied how uncertainty on the micro-station compliance will affect the uncertainty of the isolation platform to be designed. + * Active Damping Techniques on the Uni-axial Model ([[./active_damping_uniaxial.org][link]]) Active damping techniques are applied to the Uniaxial Simscape model. * Active Damping Techniques on the full Simscape Model ([[file:control_active_damping.org][link]]) Active damping techniques are applied to the full Simscape model. +* Control of the Nano-Active-Stabilization-System ([[file:control.org][link]]) * Useful Matlab Functions ([[./functions.org][link]]) Many matlab functions are shared among all the files of the projects. diff --git a/org/simscape_subsystems.org b/org/simscape_subsystems.org index 86fe303..6ac4c49 100644 --- a/org/simscape_subsystems.org +++ b/org/simscape_subsystems.org @@ -1458,7 +1458,7 @@ The =sample= structure is saved. :END: #+begin_src matlab arguments - args.type char {mustBeMember(args.type,{'open-loop', 'iff', 'dvf', 'hac-dvf', 'ref-track-L', 'ref-track-iff-L', 'cascade-hac-lac'})} = 'open-loop' + args.type char {mustBeMember(args.type,{'open-loop', 'iff', 'dvf', 'hac-dvf', 'ref-track-L', 'ref-track-iff-L', 'cascade-hac-lac', 'hac-iff'})} = 'open-loop' end #+end_src @@ -1491,6 +1491,8 @@ First, we initialize the =controller= structure. controller.type = 6; case 'cascade-hac-lac' controller.type = 7; + case 'hac-iff' + controller.type = 8; end #+end_src diff --git a/org/uncertainty_support.org b/org/uncertainty_support.org index d5063f1..3a1d10d 100644 --- a/org/uncertainty_support.org +++ b/org/uncertainty_support.org @@ -993,7 +993,7 @@ If a very stiff isolation platform is used, the uncertainty will be high around It will then be high around $\omega_0$ and probably be higher than one. Thus, if a stiff isolation platform is used, the recommendation is to have the largest possible resonance frequency, as the control bandwidth will be limited by the first resonance of the isolation platform (if not already limited by the resonance of the support). -* Numerical Analysis for the NASS +* Numerical Analysis for the NASS :noexport: <> ** Introduction :ignore: diff --git a/src/initializeController.m b/src/initializeController.m index e26f560..2b6c628 100644 --- a/src/initializeController.m +++ b/src/initializeController.m @@ -1,7 +1,7 @@ function [] = initializeController(args) arguments - args.type char {mustBeMember(args.type,{'open-loop', 'iff', 'dvf', 'hac-dvf', 'ref-track-L', 'ref-track-iff-L', 'cascade-hac-lac'})} = 'open-loop' + args.type char {mustBeMember(args.type,{'open-loop', 'iff', 'dvf', 'hac-dvf', 'ref-track-L', 'ref-track-iff-L', 'cascade-hac-lac', 'hac-iff'})} = 'open-loop' end controller = struct(); @@ -21,6 +21,8 @@ switch args.type controller.type = 6; case 'cascade-hac-lac' controller.type = 7; + case 'hac-iff' + controller.type = 8; end save('./mat/controller.mat', 'controller');