From a2917a50e9f50cefc3d280ec67b9d13d5b2c9f09 Mon Sep 17 00:00:00 2001 From: Thomas Dehaeze Date: Mon, 13 Jan 2020 11:42:31 +0100 Subject: [PATCH] Use new argument function validation technique --- active_damping/index.org | 572 ++++++++++++++++++++---------- active_damping_uniaxial/index.org | 42 +-- disturbances/index.org | 4 +- experiment_tomography/index.org | 36 +- identification/index.org | 12 +- kinematics/index.org | 3 +- positioning_error/index.org | 38 +- simscape_subsystems/index.org | 365 +++++++++---------- src/initDisturbances.m | 46 ++- src/initializeCedratPiezo.m | 12 +- src/initializeGranite.m | 14 +- src/initializeMicroHexapod.m | 22 +- src/initializeMirror.m | 24 +- src/initializeNanoHexapod.m | 26 +- src/initializeReferences.m | 119 ++++--- src/initializeRy.m | 14 +- src/initializeRz.m | 14 +- src/initializeSample.m | 21 +- src/initializeTy.m | 14 +- uniaxial/index.org | 32 +- 20 files changed, 770 insertions(+), 660 deletions(-) diff --git a/active_damping/index.org b/active_damping/index.org index 6e70a4a..0c27dd1 100644 --- a/active_damping/index.org +++ b/active_damping/index.org @@ -83,7 +83,7 @@ The disturbances are: We first look at the undamped system. The performance of this undamped system will be compared with the damped system using various techniques. -** Matlab Init :noexport:ignore: +** Matlab Init :noexport:ignore: #+begin_src matlab :tangle no :exports none :results silent :noweb yes :var current_dir=(file-name-directory buffer-file-name) <> #+end_src @@ -97,7 +97,7 @@ The performance of this undamped system will be compared with the damped system #+end_src #+begin_src matlab - open('active_damping/matlab/sim_nano_station_id.slx') + open('active_damping/matlab/sim_nass_active_damping.slx') #+end_src ** Init @@ -114,8 +114,8 @@ The nano-hexapod is a piezoelectric hexapod and the sample has a mass of 50kg. initializeMicroHexapod(); initializeAxisc(); initializeMirror(); - initializeNanoHexapod(struct('actuator', 'piezo')); - initializeSample(struct('mass', 50)); + initializeNanoHexapod('actuator', 'piezo'); + initializeSample('mass', 1); #+end_src All the controllers are set to 0. @@ -124,16 +124,321 @@ All the controllers are set to 0. save('./mat/controllers.mat', 'K', '-append'); K_iff = tf(zeros(6)); save('./mat/controllers.mat', 'K_iff', '-append'); - K_rmc = tf(zeros(6)); - save('./mat/controllers.mat', 'K_rmc', '-append'); K_dvf = tf(zeros(6)); save('./mat/controllers.mat', 'K_dvf', '-append'); #+end_src -** Identification -We identify the various transfer functions of the system +** Identification of the transfer function from disturbance to position error #+begin_src matlab - G = identifyPlant(); + %% Options for Linearized + options = linearizeOptions; + options.SampleTime = 0; + + %% Name of the Simulink File + mdl = 'sim_nass_active_damping'; + + %% Input/Output definition + clear io; io_i = 1; + io(io_i) = linio([mdl, '/Disturbances'], 1, 'openinput', [], 'Dwx'); io_i = io_i + 1; + io(io_i) = linio([mdl, '/Disturbances'], 1, 'openinput', [], 'Dwy'); io_i = io_i + 1; + io(io_i) = linio([mdl, '/Disturbances'], 1, 'openinput', [], 'Dwz'); io_i = io_i + 1; + io(io_i) = linio([mdl, '/Compute Error in NASS base'], 2, 'openoutput'); io_i = io_i + 1; + + %% Run the linearization + G = linearize(mdl, io, options); + G.InputName = {'Dwx', 'Dwy', 'Dwz'}; + G.OutputName = {'Edx', 'Edy', 'Edz', 'Erx', 'Ery', 'Erz'}; +#+end_src + +#+begin_src matlab :exports none + freqs = logspace(0, 3, 1000); + + figure; + hold on; + plot(freqs, abs(squeeze(freqresp(G('Edx', 'Dwx'), freqs, 'Hz'))), 'DisplayName', 'x'); + plot(freqs, abs(squeeze(freqresp(G('Edy', 'Dwz'), freqs, 'Hz'))), 'DisplayName', 'y'); + plot(freqs, abs(squeeze(freqresp(G('Edz', 'Dwz'), freqs, 'Hz'))), 'DisplayName', 'z'); + hold off; + set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log'); + xlabel('Frequency [Hz]'); ylabel('Amplitude [m/N]'); + legend('location', 'southeast') +#+end_src + +** Identification of the plant +#+begin_src matlab + %% Options for Linearized + options = linearizeOptions; + options.SampleTime = 0; + + %% Name of the Simulink File + mdl = 'sim_nass_active_damping'; + + %% Input/Output definition + clear io; io_i = 1; + io(io_i) = linio([mdl, '/Fnl'], 1, 'openinput'); io_i = io_i + 1; + io(io_i) = linio([mdl, '/Compute Error in NASS base'], 2, 'openoutput'); io_i = io_i + 1; + + %% Run the linearization + G = linearize(mdl, io, options); + G.InputName = {'Fnl1', 'Fnl2', 'Fnl3', 'Fnl4', 'Fnl5', 'Fnl6'}; + G.OutputName = {'Edx', 'Edy', 'Edz', 'Erx', 'Ery', 'Erz'}; +#+end_src + +#+begin_src matlab + load('mat/stages.mat', 'nano_hexapod'); + G_cart = G*inv(nano_hexapod.J'); + G_cart.InputName = {'Fnx', 'Fny', 'Fnz', 'Mnx', 'Mny', 'Mnz'}; +#+end_src + +#+begin_src matlab :exports none + freqs = logspace(0, 3, 1000); + + figure; + + ax1 = subplot(2, 1, 1); + hold on; + plot(freqs, abs(squeeze(freqresp(G_cart('Edx', 'Fnx'), freqs, 'Hz'))), 'DisplayName', '$T_{x}$'); + plot(freqs, abs(squeeze(freqresp(G_cart('Edy', 'Fny'), freqs, 'Hz'))), 'DisplayName', '$T_{y}$'); + plot(freqs, abs(squeeze(freqresp(G_cart('Edz', 'Fnz'), freqs, 'Hz'))), 'DisplayName', '$T_{z}$'); + hold off; + set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log'); + ylabel('Amplitude [m/N]'); set(gca, 'XTickLabel',[]); + legend('location', 'southwest') + + ax2 = subplot(2, 1, 2); + hold on; + plot(freqs, 180/pi*angle(squeeze(freqresp(G_cart('Edx', 'Fnx'), freqs, 'Hz')))); + plot(freqs, 180/pi*angle(squeeze(freqresp(G_cart('Edy', 'Fny'), freqs, 'Hz')))); + plot(freqs, 180/pi*angle(squeeze(freqresp(G_cart('Edz', 'Fnz'), 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],'x'); +#+end_src + +#+begin_src matlab :exports none + freqs = logspace(0, 3, 1000); + + figure; + + ax1 = subplot(2, 1, 1); + hold on; + plot(freqs, abs(squeeze(freqresp(G_cart('Erx', 'Mnx'), freqs, 'Hz'))), 'DisplayName', '$R_{x}$'); + plot(freqs, abs(squeeze(freqresp(G_cart('Ery', 'Mny'), freqs, 'Hz'))), 'DisplayName', '$R_{y}$'); + plot(freqs, abs(squeeze(freqresp(G_cart('Erz', 'Mnz'), freqs, 'Hz'))), 'DisplayName', '$R_{z}$'); + hold off; + set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log'); + ylabel('Amplitude [m/N]'); set(gca, 'XTickLabel',[]); + legend('location', 'southwest') + + ax2 = subplot(2, 1, 2); + hold on; + plot(freqs, 180/pi*angle(squeeze(freqresp(G_cart('Erx', 'Mnx'), freqs, 'Hz')))); + plot(freqs, 180/pi*angle(squeeze(freqresp(G_cart('Ery', 'Mny'), freqs, 'Hz')))); + plot(freqs, 180/pi*angle(squeeze(freqresp(G_cart('Erz', 'Mnz'), 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],'x'); +#+end_src + +** test +#+begin_src matlab + %% Options for Linearized + options = linearizeOptions; + options.SampleTime = 0; + + %% Name of the Simulink File + mdl = 'sim_nass_active_damping'; + + %% Input/Output definition + clear io; io_i = 1; + io(io_i) = linio([mdl, '/Micro-Station/Dy'], 1, 'openinput'); io_i = io_i + 1; + io(io_i) = linio([mdl, '/Compute Error in NASS base'], 2, 'openoutput'); io_i = io_i + 1; + + %% Run the linearization + G = linearize(mdl, io, options); + G.InputName = {'Dy'}; + G.OutputName = {'Edx', 'Edy', 'Edz', 'Erx', 'Ery', 'Erz'}; +#+end_src + +#+begin_src matlab :exports none + freqs = logspace(0, 3, 1000); + + figure; + + ax1 = subplot(2, 1, 1); + hold on; + plot(freqs, abs(squeeze(freqresp(G('Edy', 'Dy(1)'), freqs, 'Hz'))), 'DisplayName', '$T_{x}$'); + hold off; + set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log'); + ylabel('Amplitude [m/N]'); set(gca, 'XTickLabel',[]); + legend('location', 'southwest') + + ax2 = subplot(2, 1, 2); + hold on; + plot(freqs, 180/pi*angle(squeeze(freqresp(G('Edy', 'Dy(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],'x'); +#+end_src + +#+begin_src matlab :exports none + freqs = logspace(0, 3, 1000); + + figure; + + ax1 = subplot(2, 1, 1); + hold on; + plot(freqs, abs(squeeze(freqresp(G_cart('Erx', 'Mnx'), freqs, 'Hz'))), 'DisplayName', '$R_{x}$'); + plot(freqs, abs(squeeze(freqresp(G_cart('Ery', 'Mny'), freqs, 'Hz'))), 'DisplayName', '$R_{y}$'); + plot(freqs, abs(squeeze(freqresp(G_cart('Erz', 'Mnz'), freqs, 'Hz'))), 'DisplayName', '$R_{z}$'); + hold off; + set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log'); + ylabel('Amplitude [m/N]'); set(gca, 'XTickLabel',[]); + legend('location', 'southwest') + + ax2 = subplot(2, 1, 2); + hold on; + plot(freqs, 180/pi*angle(squeeze(freqresp(G_cart('Erx', 'Mnx'), freqs, 'Hz')))); + plot(freqs, 180/pi*angle(squeeze(freqresp(G_cart('Ery', 'Mny'), freqs, 'Hz')))); + plot(freqs, 180/pi*angle(squeeze(freqresp(G_cart('Erz', 'Mnz'), 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],'x'); +#+end_src + +** test on hexapod +#+begin_src matlab + %% Options for Linearized + options = linearizeOptions; + options.SampleTime = 0; + + %% Name of the Simulink File + mdl = 'test_nano_hexapod'; + + %% Input/Output definition + clear io; io_i = 1; + io(io_i) = linio([mdl, '/Fnl'], 1, 'openinput'); io_i = io_i + 1; + io(io_i) = linio([mdl, '/x'], 1, 'openoutput'); io_i = io_i + 1; + io(io_i) = linio([mdl, '/y'], 1, 'openoutput'); io_i = io_i + 1; + io(io_i) = linio([mdl, '/z'], 1, 'openoutput'); io_i = io_i + 1; + + %% Run the linearization + G = linearize(mdl, io, options); + G.InputName = {'Fnl1', 'Fnl2', 'Fnl3', 'Fnl4', 'Fnl5', 'Fnl6'}; + G.OutputName = {'x', 'y', 'z'}; +#+end_src + +#+begin_src matlab + %% Options for Linearized + options = linearizeOptions; + options.SampleTime = 0; + + %% Name of the Simulink File + mdl = 'test_nano_hexapod'; + + %% Input/Output definition + clear io; io_i = 1; + io(io_i) = linio([mdl, '/Fx'], 1, 'openinput'); io_i = io_i + 1; + io(io_i) = linio([mdl, '/x'], 1, 'openoutput'); io_i = io_i + 1; + io(io_i) = linio([mdl, '/y'], 1, 'openoutput'); io_i = io_i + 1; + io(io_i) = linio([mdl, '/z'], 1, 'openoutput'); io_i = io_i + 1; + + %% Run the linearization + G = linearize(mdl, io, options); + G.InputName = {'Fx'}; + G.OutputName = {'x', 'y', 'z'}; +#+end_src + +#+begin_src matlab :exports none + freqs = logspace(0, 3, 1000); + + figure; + + ax1 = subplot(2, 1, 1); + hold on; + plot(freqs, abs(squeeze(freqresp(G('Edy', 'Dy(1)'), freqs, 'Hz'))), 'DisplayName', '$T_{x}$'); + hold off; + set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log'); + ylabel('Amplitude [m/N]'); set(gca, 'XTickLabel',[]); + legend('location', 'southwest') + + ax2 = subplot(2, 1, 2); + hold on; + plot(freqs, 180/pi*angle(squeeze(freqresp(G('Edy', 'Dy(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],'x'); +#+end_src + +#+begin_src matlab :exports none + freqs = logspace(0, 3, 1000); + + figure; + + ax1 = subplot(2, 1, 1); + hold on; + plot(freqs, abs(squeeze(freqresp(G_cart('Erx', 'Mnx'), freqs, 'Hz'))), 'DisplayName', '$R_{x}$'); + plot(freqs, abs(squeeze(freqresp(G_cart('Ery', 'Mny'), freqs, 'Hz'))), 'DisplayName', '$R_{y}$'); + plot(freqs, abs(squeeze(freqresp(G_cart('Erz', 'Mnz'), freqs, 'Hz'))), 'DisplayName', '$R_{z}$'); + hold off; + set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log'); + ylabel('Amplitude [m/N]'); set(gca, 'XTickLabel',[]); + legend('location', 'southwest') + + ax2 = subplot(2, 1, 2); + hold on; + plot(freqs, 180/pi*angle(squeeze(freqresp(G_cart('Erx', 'Mnx'), freqs, 'Hz')))); + plot(freqs, 180/pi*angle(squeeze(freqresp(G_cart('Ery', 'Mny'), freqs, 'Hz')))); + plot(freqs, 180/pi*angle(squeeze(freqresp(G_cart('Erz', 'Mnz'), 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],'x'); +#+end_src + +** Identification of the dynamics for Active Damping +#+begin_src matlab + %% Options for Linearized + options = linearizeOptions; + options.SampleTime = 0; + + %% Name of the Simulink File + mdl = 'sim_nass_active_damping'; + + %% Input/Output definition + clear io; io_i = 1; + io(io_i) = linio([mdl, '/Fnl'], 1, 'openinput'); io_i = io_i + 1; + io(io_i) = linio([mdl, '/Micro-Station'], 3, 'openoutput', [], 'Dnlm'); io_i = io_i + 1; + io(io_i) = linio([mdl, '/Micro-Station'], 3, 'openoutput', [], 'Fnlm'); io_i = io_i + 1; + + %% Run the linearization + G = linearize(mdl, io, options); + G.InputName = {'Fnl1', 'Fnl2', 'Fnl3', 'Fnl4', 'Fnl5', 'Fnl6'}; + G.OutputName = {'Dnlm1', 'Dnlm2', 'Dnlm3', 'Dnlm4', 'Dnlm5', 'Dnlm6', ... + 'Fnlm1', 'Fnlm2', 'Fnlm3', 'Fnlm4', 'Fnlm5', 'Fnlm6'}; #+end_src And we save it for further analysis. @@ -141,6 +446,63 @@ And we save it for further analysis. save('./active_damping/mat/plants.mat', 'G', '-append'); #+end_src +** Plant for Active Damping +#+begin_src matlab :exports none + freqs = logspace(0, 3, 1000); + + figure; + + ax1 = subplot(2, 1, 1); + hold on; + for i = 1:6 + plot(freqs, abs(squeeze(freqresp(G(['Fnlm', num2str(i)], ['Fnl', num2str(i)]), freqs, 'Hz')))); + end + hold off; + set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log'); + ylabel('Amplitude [m/N]'); set(gca, 'XTickLabel',[]); + + ax2 = subplot(2, 1, 2); + hold on; + for i = 1:6 + plot(freqs, 180/pi*angle(squeeze(freqresp(G(['Fnlm', num2str(i)], ['Fnl', num2str(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 + freqs = logspace(0, 3, 1000); + + figure; + + ax1 = subplot(2, 1, 1); + hold on; + for i = 1:6 + plot(freqs, abs(squeeze(freqresp(G(['Dnlm', num2str(i)], ['Fnl', num2str(i)]), freqs, 'Hz')))); + end + hold off; + set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log'); + ylabel('Amplitude [m/N]'); set(gca, 'XTickLabel',[]); + + ax2 = subplot(2, 1, 2); + hold on; + for i = 1:6 + plot(freqs, 180/pi*angle(squeeze(freqresp(G(['Dnlm', num2str(i)], ['Fnl', num2str(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 + ** Sensitivity to disturbances The sensitivity to disturbances are shown on figure [[fig:sensitivity_dist_undamped]]. @@ -242,6 +604,7 @@ The "plant" (transfer function from forces applied by the nano-hexapod to the me #+CAPTION: Transfer Function from cartesian forces to displacement for the undamped plant ([[./figs/plant_undamped.png][png]], [[./figs/plant_undamped.pdf][pdf]]) [[file:figs/plant_undamped.png]] +** Tomography Experiment * Integral Force Feedback :PROPERTIES: :header-args:matlab+: :tangle matlab/iff.m @@ -269,185 +632,6 @@ Integral Force Feedback is applied. In section [[sec:iff_1dof]], IFF is applied on a uni-axial system to understand its behavior. Then, it is applied on the simscape model. -** One degree-of-freedom example -:PROPERTIES: -:header-args:matlab+: :tangle no -:END: -<> -*** Equations -#+begin_src latex :file iff_1dof.pdf :post pdf2svg(file=*this*, ext="png") :exports results - \begin{tikzpicture} - % Ground - \draw (-1, 0) -- (1, 0); - - % Ground Displacement - \draw[dashed] (-1, 0) -- ++(-0.5, 0) coordinate(w); - \draw[->] (w) -- ++(0, 0.5) node[left]{$w$}; - - % Mass - \draw[fill=white] (-1, 1.4) rectangle ++(2, 0.8) node[pos=0.5]{$m$}; - \node[forcesensor={0.4}{0.4}] (fsensn) at (0, 1){}; - \draw[] (-0.8, 1) -- (0.8, 1); - \node[left] at (fsensn.west) {$F_m$}; - - % Displacement of the mass - \draw[dashed] (-1, 2.2) -- ++(-0.5, 0) coordinate(x); - \draw[->] (x) -- ++(0, 0.5) node[left]{$x$}; - - % Spring, Damper, and Actuator - \draw[spring] (-0.8, 0) -- (-0.8, 1) node[midway, left=0.1]{$k$}; - \draw[damper] (0, 0) -- (0, 1) node[midway, left=0.2]{$c$}; - \draw[actuator={0.4}{0.2}] (0.8, 0) -- (0.8, 1) coordinate[midway, right=0.1](F); - - % Displacements - \node[block={0.8cm}{0.6cm}, right=0.6 of F] (Kiff) {$K$}; - \draw[->] (Kiff.west) -- (F) node[above right]{$F$}; - \draw[<-] (Kiff.east) -- ++(0.5, 0) |- (fsensn.east); - \end{tikzpicture} -#+end_src - -#+name: fig:iff_1dof -#+caption: Integral Force Feedback applied to a 1dof system -#+RESULTS: -[[file:figs/iff_1dof.png]] - -The dynamic of the system is described by the following equation: -\begin{equation} - ms^2x = F_d - kx - csx + kw + csw + F -\end{equation} -The measured force $F_m$ is: -\begin{align} - F_m &= F - kx - csx + kw + csw \\ - &= ms^2 x - F_d -\end{align} -The Integral Force Feedback controller is $K = -\frac{g}{s}$, and thus the applied force by this controller is: -\begin{equation} - F_{\text{IFF}} = -\frac{g}{s} F_m = -\frac{g}{s} (ms^2 x - F_d) -\end{equation} -Once the IFF is applied, the new dynamics of the system is: -\begin{equation} - ms^2x = F_d + F - kx - csx + kw + csw - \frac{g}{s} (ms^2x - F_d) -\end{equation} - -And finally: -\begin{equation} - x = F_d \frac{1 + \frac{g}{s}}{ms^2 + (mg + c)s + k} + F \frac{1}{ms^2 + (mg + c)s + k} + w \frac{k + cs}{ms^2 + (mg + c)s + k} -\end{equation} - -We can see that this: -- adds damping to the system by a value $mg$ -- lower the compliance as low frequency by a factor: $1 + g/s$ - -If we want critical damping: -\begin{equation} - \xi = \frac{1}{2} \frac{c + gm}{\sqrt{km}} = \frac{1}{2} -\end{equation} - -This is attainable if we have: -\begin{equation} - g = \frac{\sqrt{km} - c}{m} -\end{equation} - -*** 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 - -*** Matlab Example -Let define the system parameters. -#+begin_src matlab - m = 50; % [kg] - k = 1e6; % [N/m] - c = 1e3; % [N/(m/s)] -#+end_src - -The state space model of the system is defined below. -#+begin_src matlab - A = [-c/m -k/m; - 1 0]; - - B = [1/m 1/m -1; - 0 0 0]; - - C = [ 0 1; - -c -k]; - - D = [0 0 0; - 1 0 0]; - - sys = ss(A, B, C, D); - sys.InputName = {'F', 'Fd', 'wddot'}; - sys.OutputName = {'d', 'Fm'}; - sys.StateName = {'ddot', 'd'}; -#+end_src - -The controller $K_\text{IFF}$ is: -#+begin_src matlab - Kiff = -((sqrt(k*m)-c)/m)/s; - Kiff.InputName = {'Fm'}; - Kiff.OutputName = {'F'}; -#+end_src - -And the closed loop system is computed below. -#+begin_src matlab - sys_iff = feedback(sys, Kiff, 'name', +1); -#+end_src - -#+begin_src matlab :exports none - freqs = logspace(0, 3, 1000); - - figure; - - subplot(2, 2, 1); - title('Fd to d') - hold on; - plot(freqs, abs(squeeze(freqresp(sys('d', 'Fd'), freqs, 'Hz')))); - plot(freqs, abs(squeeze(freqresp(sys_iff('d', 'Fd'), freqs, 'Hz')))); - set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log'); - ylabel('Amplitude [m/N]'); xlabel('Frequency [Hz]'); - xlim([freqs(1), freqs(end)]); - - subplot(2, 2, 3); - title('Fd to x') - hold on; - plot(freqs, abs(squeeze(freqresp(sys('d', 'Fd'), freqs, 'Hz')))); - plot(freqs, abs(squeeze(freqresp(sys_iff('d', 'Fd'), freqs, 'Hz')))); - set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log'); - ylabel('Amplitude [m/N]'); xlabel('Frequency [Hz]'); - xlim([freqs(1), freqs(end)]); - - subplot(2, 2, 2); - title('w to d') - hold on; - plot(freqs, abs(squeeze(freqresp(sys('d', 'wddot')*s^2, freqs, 'Hz')))); - plot(freqs, abs(squeeze(freqresp(sys_iff('d', 'wddot')*s^2, freqs, 'Hz')))); - set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log'); - ylabel('Amplitude [m/m]'); xlabel('Frequency [Hz]'); - xlim([freqs(1), freqs(end)]); - - subplot(2, 2, 4); - title('w to x') - hold on; - plot(freqs, abs(squeeze(freqresp(1+sys('d', 'wddot')*s^2, freqs, 'Hz')))); - plot(freqs, abs(squeeze(freqresp(1+sys_iff('d', 'wddot')*s^2, freqs, 'Hz')))); - set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log'); - ylabel('Amplitude [m/m]'); xlabel('Frequency [Hz]'); - xlim([freqs(1), freqs(end)]); -#+end_src - -#+HEADER: :tangle no :exports results :results none :noweb yes -#+begin_src matlab :var filepath="figs/iff_1dof_sensitivitiy.pdf" :var figsize="full-tall" :post pdf2svg(file=*this*, ext="png") - <> -#+end_src - -#+NAME: fig:iff_1dof_sensitivitiy -#+CAPTION: Sensitivity to disturbance when IFF is applied on the 1dof system ([[./figs/iff_1dof_sensitivitiy.png][png]], [[./figs/iff_1dof_sensitivitiy.pdf][pdf]]) -[[file:figs/iff_1dof_sensitivitiy.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) <> @@ -566,8 +750,8 @@ Let's initialize the system prior to identification. initializeMicroHexapod(); initializeAxisc(); initializeMirror(); - initializeNanoHexapod(struct('actuator', 'piezo')); - initializeSample(struct('mass', 50)); + initializeNanoHexapod('actuator', 'piezo'); + initializeSample('mass', 50); #+end_src All the controllers are set to 0. @@ -1106,8 +1290,8 @@ Let's initialize the system prior to identification. initializeMicroHexapod(); initializeAxisc(); initializeMirror(); - initializeNanoHexapod(struct('actuator', 'piezo')); - initializeSample(struct('mass', 50)); + initializeNanoHexapod('actuator', 'piezo'); + initializeSample('mass', 50); #+end_src And initialize the controllers. @@ -1617,8 +1801,8 @@ Let's initialize the system prior to identification. initializeMicroHexapod(); initializeAxisc(); initializeMirror(); - initializeNanoHexapod(struct('actuator', 'piezo')); - initializeSample(struct('mass', 50)); + initializeNanoHexapod('actuator', 'piezo'); + initializeSample('mass', 50); #+end_src And initialize the controllers. diff --git a/active_damping_uniaxial/index.org b/active_damping_uniaxial/index.org index 37d3a3b..7473f88 100644 --- a/active_damping_uniaxial/index.org +++ b/active_damping_uniaxial/index.org @@ -1,4 +1,4 @@ -#+TITLE: Active Damping +#+TITLE: Active Damping with an uni-axial model :DRAWER: #+STARTUP: overview @@ -97,7 +97,7 @@ The performance of this undamped system will be compared with the damped system #+end_src #+begin_src matlab - open('active_damping/matlab/sim_nano_station_id.slx') + open('active_damping_uniaxial/matlab/sim_nano_station_id.slx') #+end_src ** Init @@ -114,8 +114,8 @@ The nano-hexapod is a piezoelectric hexapod and the sample has a mass of 50kg. initializeMicroHexapod(); initializeAxisc(); initializeMirror(); - initializeNanoHexapod(struct('actuator', 'piezo')); - initializeSample(struct('mass', 50)); + initializeNanoHexapod('actuator', 'piezo'); + initializeSample('mass', 50); #+end_src All the controllers are set to 0. @@ -138,7 +138,7 @@ We identify the various transfer functions of the system And we save it for further analysis. #+begin_src matlab - save('./active_damping/mat/plants.mat', 'G', '-append'); + save('./active_damping_uniaxial/mat/plants.mat', 'G', '-append'); #+end_src ** Sensitivity to disturbances @@ -462,13 +462,13 @@ And the closed loop system is computed below. #+end_src #+begin_src matlab - open('active_damping/matlab/sim_nano_station_id.slx') + open('active_damping_uniaxial/matlab/sim_nano_station_id.slx') #+end_src ** Control Design Let's load the undamped plant: #+begin_src matlab - load('./active_damping/mat/plants.mat', 'G'); + load('./active_damping_uniaxial/mat/plants.mat', 'G'); #+end_src Let's look at the transfer function from actuator forces in the nano-hexapod to the force sensor in the nano-hexapod legs for all 6 pairs of actuator/sensor (figure [[fig:iff_plant]]). @@ -566,8 +566,8 @@ Let's initialize the system prior to identification. initializeMicroHexapod(); initializeAxisc(); initializeMirror(); - initializeNanoHexapod(struct('actuator', 'piezo')); - initializeSample(struct('mass', 50)); + initializeNanoHexapod('actuator', 'piezo'); + initializeSample('mass', 50); #+end_src All the controllers are set to 0. @@ -589,7 +589,7 @@ We identify the system dynamics now that the IFF controller is ON. And we save the damped plant for further analysis #+begin_src matlab - save('./active_damping/mat/plants.mat', 'G_iff', '-append'); + save('./active_damping_uniaxial/mat/plants.mat', 'G_iff', '-append'); #+end_src ** Sensitivity to disturbances @@ -1001,13 +1001,13 @@ And the closed loop system is computed below. #+end_src #+begin_src matlab - open('active_damping/matlab/sim_nano_station_id.slx') + open('active_damping_uniaxial/matlab/sim_nano_station_id.slx') #+end_src ** Control Design Let's load the undamped plant: #+begin_src matlab - load('./active_damping/mat/plants.mat', 'G'); + load('./active_damping_uniaxial/mat/plants.mat', 'G'); #+end_src Let's look at the transfer function from actuator forces in the nano-hexapod to the measured displacement of the actuator for all 6 pairs of actuator/sensor (figure [[fig:rmc_plant]]). @@ -1106,8 +1106,8 @@ Let's initialize the system prior to identification. initializeMicroHexapod(); initializeAxisc(); initializeMirror(); - initializeNanoHexapod(struct('actuator', 'piezo')); - initializeSample(struct('mass', 50)); + initializeNanoHexapod('actuator', 'piezo'); + initializeSample('mass', 50); #+end_src And initialize the controllers. @@ -1129,7 +1129,7 @@ We identify the system dynamics now that the RMC controller is ON. And we save the damped plant for further analysis. #+begin_src matlab - save('./active_damping/mat/plants.mat', 'G_rmc', '-append'); + save('./active_damping_uniaxial/mat/plants.mat', 'G_rmc', '-append'); #+end_src ** Sensitivity to disturbances @@ -1514,13 +1514,13 @@ The obtained sensitivity to disturbances is shown in figure [[fig:dvf_1dof_sensi #+end_src #+begin_src matlab - open('active_damping/matlab/sim_nano_station_id.slx') + open('active_damping_uniaxial/matlab/sim_nano_station_id.slx') #+end_src ** Control Design Let's load the undamped plant: #+begin_src matlab - load('./active_damping/mat/plants.mat', 'G'); + load('./active_damping_uniaxial/mat/plants.mat', 'G'); #+end_src Let's look at the transfer function from actuator forces in the nano-hexapod to the measured velocity of the nano-hexapod platform in the direction of the corresponding actuator for all 6 pairs of actuator/sensor (figure [[fig:dvf_plant]]). @@ -1617,8 +1617,8 @@ Let's initialize the system prior to identification. initializeMicroHexapod(); initializeAxisc(); initializeMirror(); - initializeNanoHexapod(struct('actuator', 'piezo')); - initializeSample(struct('mass', 50)); + initializeNanoHexapod('actuator', 'piezo'); + initializeSample('mass', 50); #+end_src And initialize the controllers. @@ -1640,7 +1640,7 @@ We identify the system dynamics now that the RMC controller is ON. And we save the damped plant for further analysis. #+begin_src matlab - save('./active_damping/mat/plants.mat', 'G_dvf', '-append'); + save('./active_damping_uniaxial/mat/plants.mat', 'G_dvf', '-append'); #+end_src ** Sensitivity to disturbances @@ -1812,7 +1812,7 @@ Direct Velocity Feedback: ** Load the plants #+begin_src matlab - load('./active_damping/mat/plants.mat', 'G', 'G_iff', 'G_rmc', 'G_dvf'); + load('./active_damping_uniaxial/mat/plants.mat', 'G', 'G_iff', 'G_rmc', 'G_dvf'); #+end_src ** Sensitivity to Disturbance diff --git a/disturbances/index.org b/disturbances/index.org index f3822bc..a9c4023 100644 --- a/disturbances/index.org +++ b/disturbances/index.org @@ -217,8 +217,8 @@ We initialize all the stages. initializeMicroHexapod(); initializeAxisc(); initializeMirror(); - initializeNanoHexapod(struct('actuator', 'piezo')); - initializeSample(struct('mass', 50)); + initializeNanoHexapod('actuator', 'piezo'); + initializeSample('mass', 50); #+end_src * Identification diff --git a/experiment_tomography/index.org b/experiment_tomography/index.org index 4d5113d..29093b0 100644 --- a/experiment_tomography/index.org +++ b/experiment_tomography/index.org @@ -93,14 +93,14 @@ We first initialize all the stages. initializeMicroHexapod(); initializeAxisc(); initializeMirror(); - initializeNanoHexapod(struct('actuator', 'piezo')); - initializeSample(struct('mass', 1)); + initializeNanoHexapod('actuator', 'piezo'); + initializeSample('mass', 1); #+end_src We initialize the reference path for all the stages. All stage is set to its zero position except the Spindle which is rotating at 60rpm. #+begin_src matlab - initializeReferences(struct('Rz_type', 'rotating', 'Rz_period', 1)); + initializeReferences('Rz_type', 'rotating', 'Rz_period', 1); #+end_src * Tomography Experiment with no disturbances @@ -110,15 +110,14 @@ All stage is set to its zero position except the Spindle which is rotating at 60 ** Simulation Setup And we initialize the disturbances to be equal to zero. #+begin_src matlab - opts = struct(... + initDisturbances(... 'Dwx', false, ... % Ground Motion - X direction 'Dwy', false, ... % Ground Motion - Y direction 'Dwz', false, ... % Ground Motion - Z direction 'Fty_x', false, ... % Translation Stage - X direction 'Fty_z', false, ... % Translation Stage - Z direction 'Frz_z', false ... % Spindle - Z direction - ); - initDisturbances(opts); + ); #+end_src We simulate the model. @@ -221,15 +220,14 @@ And we save the obtained data. ** Simulation Setup We now activate the disturbances. #+begin_src matlab - opts = struct(... + initDisturbances(... 'Dwx', true, ... % Ground Motion - X direction 'Dwy', true, ... % Ground Motion - Y direction 'Dwz', true, ... % Ground Motion - Z direction 'Fty_x', true, ... % Translation Stage - X direction 'Fty_z', true, ... % Translation Stage - Z direction 'Frz_z', true ... % Spindle - Z direction - ); - initDisturbances(opts); + ); #+end_src We simulate the model. @@ -336,25 +334,24 @@ We first set the wanted translation of the Micro Hexapod. We initialize the reference path. #+begin_src matlab - initializeReferences(struct('Dh_pos', [P_micro_hexapod; 0; 0; 0], 'Rz_type', 'rotating', 'Rz_period', 1)); + initializeReferences('Dh_pos', [P_micro_hexapod; 0; 0; 0], 'Rz_type', 'rotating', 'Rz_period', 1); #+end_src We initialize the stages. #+begin_src matlab - initializeMicroHexapod(struct('AP', P_micro_hexapod)); + initializeMicroHexapod('AP', P_micro_hexapod); #+end_src And we initialize the disturbances to zero. #+begin_src matlab - opts = struct(... + initDisturbances(... 'Dwx', false, ... % Ground Motion - X direction 'Dwy', false, ... % Ground Motion - Y direction 'Dwz', false, ... % Ground Motion - Z direction 'Fty_x', false, ... % Translation Stage - X direction 'Fty_z', false, ... % Translation Stage - Z direction 'Frz_z', false ... % Spindle - Z direction - ); - initDisturbances(opts); + ); #+end_src We simulate the model. @@ -456,7 +453,7 @@ And we save the obtained data. ** Simulation Setup We set the reference path. #+begin_src matlab - initializeReferences(struct('Dy_type', 'triangular', 'Dy_amplitude', 10e-3, 'Dy_period', 1)); + initializeReferences('Dy_type', 'triangular', 'Dy_amplitude', 10e-3, 'Dy_period', 1); #+end_src We initialize the stages. @@ -469,21 +466,20 @@ We initialize the stages. initializeMicroHexapod(); initializeAxisc(); initializeMirror(); - initializeNanoHexapod(struct('actuator', 'piezo')); - initializeSample(struct('mass', 1)); + initializeNanoHexapod('actuator', 'piezo'); + initializeSample('mass', 1); #+end_src And we initialize the disturbances to zero. #+begin_src matlab - opts = struct(... + initDisturbances(... 'Dwx', false, ... % Ground Motion - X direction 'Dwy', false, ... % Ground Motion - Y direction 'Dwz', false, ... % Ground Motion - Z direction 'Fty_x', false, ... % Translation Stage - X direction 'Fty_z', false, ... % Translation Stage - Z direction 'Frz_z', false ... % Spindle - Z direction - ); - initDisturbances(opts); + ); #+end_src We simulate the model. diff --git a/identification/index.org b/identification/index.org index b97572d..97dfc23 100644 --- a/identification/index.org +++ b/identification/index.org @@ -88,8 +88,8 @@ We initialize all the stages. initializeMicroHexapod(); initializeAxisc(); initializeMirror(); - initializeNanoHexapod(struct('actuator', 'piezo')); - initializeSample(struct('mass', 50)); + initializeNanoHexapod('actuator', 'piezo'); + initializeSample('mass', 50); #+end_src ** Compute the transfer functions @@ -173,8 +173,8 @@ We initialize all the stages. initializeMicroHexapod(); initializeAxisc(); initializeMirror(); - initializeNanoHexapod(struct('actuator', 'piezo')); - initializeSample(struct('mass', 50)); + initializeNanoHexapod('actuator', 'piezo'); + initializeSample('mass', 50); #+end_src ** Identification @@ -297,8 +297,8 @@ We initialize all the stages. initializeMicroHexapod(); initializeAxisc(); initializeMirror(); - initializeNanoHexapod(struct('actuator', 'piezo')); - initializeSample(struct('mass', 50)); + initializeNanoHexapod('actuator', 'piezo'); + initializeSample('mass', 50); #+end_src ** Estimate the position of the CoM of each solid and compare with the one took for the Measurement Analysis diff --git a/kinematics/index.org b/kinematics/index.org index c1b0467..b78a493 100644 --- a/kinematics/index.org +++ b/kinematics/index.org @@ -177,7 +177,7 @@ We define the wanted position/orientation of the Hexapod under study. ARB = Rz*Ry*Rx; AP = [0.01; 0.02; 0.03]; % [m] - hexapod = initializeMicroHexapod(struct('AP', AP, 'ARB', ARB)); + hexapod = initializeMicroHexapod('AP', AP, 'ARB', ARB); #+end_src We run the simulation. @@ -203,6 +203,7 @@ And we verify that we indeed succeed to go to the wanted position. | -1.2659e-10 | 6.5603e-11 | 6.2183e-10 | | 1.0354e-10 | -5.2439e-11 | -5.2425e-10 | | -5.9816e-10 | 5.532e-10 | -1.7737e-10 | + * TODO Tests on the transformation from reference to wanted position :noexport: :PROPERTIES: :header-args:matlab+: :eval no diff --git a/positioning_error/index.org b/positioning_error/index.org index 44b4f22..2f819a2 100644 --- a/positioning_error/index.org +++ b/positioning_error/index.org @@ -102,13 +102,13 @@ We initialize all the stages. initializeMicroHexapod(); initializeAxisc(); initializeMirror(); - initializeNanoHexapod(struct('actuator', 'piezo')); - initializeSample(struct('mass', 50)); + initializeNanoHexapod('actuator', 'piezo'); + initializeSample('mass', 50); #+end_src We setup the reference path to be constant. #+begin_src matlab - opts = struct( ... + initializeReferences(... 'Ts', 1e-3, ... % Sampling Frequency [s] 'Dy_type', 'constant', ... % Either "constant" / "triangular" / "sinusoidal" 'Dy_amplitude', 5e-3, ... % Amplitude of the displacement [m] @@ -125,10 +125,7 @@ We setup the reference path to be constant. 'Rm_pos', [0, pi]', ... % Initial position of the two masses 'Dn_type', 'constant', ... % For now, only constant is implemented 'Dn_pos', [1e-3; 2e-3; 3e-3; 1*pi/180; 0; 1*pi/180] ... % Initial position [m,m,m,rad,rad,rad] of the top platform - ); - - - initializeReferences(opts); + ); #+end_src No position error for now (perfect positioning). @@ -253,13 +250,13 @@ We initialize all the stages. initializeMicroHexapod(); initializeAxisc(); initializeMirror(); - initializeNanoHexapod(struct('actuator', 'piezo')); - initializeSample(struct('mass', 50)); + initializeNanoHexapod('actuator', 'piezo'); + initializeSample('mass', 50); #+end_src We setup the reference path to be constant. #+begin_src matlab - opts = struct( ... + initializeReferences(... 'Ts', 1e-3, ... % Sampling Frequency [s] 'Dy_type', 'constant', ... % Either "constant" / "triangular" / "sinusoidal" 'Dy_amplitude', 0, ... % Amplitude of the displacement [m] @@ -273,9 +270,7 @@ We setup the reference path to be constant. 'Rm_pos', [0, pi]', ... % Initial position of the two masses 'Dn_type', 'constant', ... % For now, only constant is implemented 'Dn_pos', [0; 0; 0; 0; 0; 0] ... % Initial position [m,m,m,rad,rad,rad] of the top platform - ); - - initializeReferences(opts); + ); #+end_src Now we introduce some positioning error. @@ -383,8 +378,21 @@ Verify that the pose error corresponds to the positioning error of the stages. ** Verify that be imposing the error motion on the nano-hexapod, we indeed have zero error at the end We now keep the wanted pose but we impose a displacement of the nano hexapod corresponding to the measured position error. #+begin_src matlab - opts.Dn_pos = [Edx, Edy, Edz, Erx, Ery, Erz]'; - initializeReferences(opts); + initializeReferences(... + 'Ts', 1e-3, ... % Sampling Frequency [s] + 'Dy_type', 'constant', ... % Either "constant" / "triangular" / "sinusoidal" + 'Dy_amplitude', 0, ... % Amplitude of the displacement [m] + 'Ry_type', 'constant', ... % Either "constant" / "triangular" / "sinusoidal" + 'Ry_amplitude', 0, ... % Amplitude [rad] + 'Rz_type', 'constant', ... % Either "constant" / "rotating" + 'Rz_amplitude', 0*pi/180, ... % Initial angle [rad] + 'Dh_type', 'constant', ... % For now, only constant is implemented + 'Dh_pos', [0; 0; 0; 0; 0; 0], ... % Initial position [m,m,m,rad,rad,rad] of the top platform + 'Rm_type', 'constant', ... % For now, only constant is implemented + 'Rm_pos', [0, pi]', ... % Initial position of the two masses + 'Dn_type', 'constant', ... % For now, only constant is implemented + 'Dn_pos', [Edx, Edy, Edz, Erx, Ery, Erz]' ... % Initial position [m,m,m,rad,rad,rad] of the top platform + ); #+end_src And we run the simulation. diff --git a/simscape_subsystems/index.org b/simscape_subsystems/index.org index 45c75cc..be6f4f0 100644 --- a/simscape_subsystems/index.org +++ b/simscape_subsystems/index.org @@ -53,60 +53,81 @@ This Matlab function is accessible [[file:../src/initializeInputs.m][here]]. +*** Function Declaration and Documentation #+begin_src matlab - function [ref] = initializeReferences(opts_param) - %% Default values for opts - opts = struct( ... - 'Ts', 1e-3, ... % Sampling Frequency [s] - 'Tmax', 100, ... % Maximum simulation time [s] - 'Dy_type', 'constant', ... % Either "constant" / "triangular" / "sinusoidal" - 'Dy_amplitude', 0, ... % Amplitude of the displacement [m] - 'Dy_period', 1, ... % Period of the displacement [s] - 'Ry_type', 'constant', ... % Either "constant" / "triangular" / "sinusoidal" - 'Ry_amplitude', 0, ... % Amplitude [rad] - 'Ry_period', 1, ... % Period of the displacement [s] - 'Rz_type', 'constant', ... % Either "constant" / "rotating" - 'Rz_amplitude', 0, ... % Initial angle [rad] - 'Rz_period', 1, ... % Period of the rotating [s] - 'Dh_type', 'constant', ... % For now, only constant is implemented - 'Dh_pos', zeros(6, 1), ... % Initial position [m,m,m,rad,rad,rad] of the top platform (Pitch-Roll-Yaw Euler angles) - 'Rm_type', 'constant', ... % For now, only constant is implemented - 'Rm_pos', [0; pi], ... % Initial position of the two masses - 'Dn_type', 'constant', ... % For now, only constant is implemented - 'Dn_pos', zeros(6,1) ... % Initial position [m,m,m,rad,rad,rad] of the top platform - ); + function [ref] = initializeReferences(args) +#+end_src - %% Populate opts with input parameters - if exist('opts_param','var') - for opt = fieldnames(opts_param)' - opts.(opt{1}) = opts_param.(opt{1}); - end - end +*** Optional Parameters +#+begin_src matlab + arguments + % Sampling Frequency [s] + args.Ts (1,1) double {mustBeNumeric, mustBePositive} = 1e-3 + % Maximum simulation time [s] + args.Tmax (1,1) double {mustBeNumeric, mustBePositive} = 100 + % Either "constant" / "triangular" / "sinusoidal" + args.Dy_type char {mustBeMember(args.Dy_type,{'constant', 'triangular', 'sinusoidal'})} = 'constant' + % Amplitude of the displacement [m] + args.Dy_amplitude (1,1) double {mustBeNumeric} = 0 + % Period of the displacement [s] + args.Dy_period (1,1) double {mustBeNumeric, mustBePositive} = 1 + % Either "constant" / "triangular" / "sinusoidal" + args.Ry_type char {mustBeMember(args.Ry_type,{'constant', 'triangular', 'sinusoidal'})} = 'constant' + % Amplitude [rad] + args.Ry_amplitude (1,1) double {mustBeNumeric} = 0 + % Period of the displacement [s] + args.Ry_period (1,1) double {mustBeNumeric, mustBePositive} = 1 + % Either "constant" / "rotating" + args.Rz_type char {mustBeMember(args.Rz_type,{'constant', 'rotating'})} = 'constant' + % Initial angle [rad] + args.Rz_amplitude (1,1) double {mustBeNumeric} = 0 + % Period of the rotating [s] + args.Rz_period (1,1) double {mustBeNumeric, mustBePositive} = 1 + % For now, only constant is implemented + args.Dh_type char {mustBeMember(args.Dh_type,{'constant'})} = 'constant' + % Initial position [m,m,m,rad,rad,rad] of the top platform (Pitch-Roll-Yaw Euler angles) + args.Dh_pos (6,1) double {mustBeNumeric} = zeros(6, 1), ... + % For now, only constant is implemented + args.Rm_type char {mustBeMember(args.Rm_type,{'constant'})} = 'constant' + % Initial position of the two masses + args.Rm_pos (2,1) double {mustBeNumeric} = [0; pi] + % For now, only constant is implemented + args.Dn_type char {mustBeMember(args.Dn_type,{'constant'})} = 'constant' + % Initial position [m,m,m,rad,rad,rad] of the top platform + args.Dn_pos (6,1) double {mustBeNumeric} = zeros(6,1) + end +#+end_src + +*** Initialize Parameters +#+begin_src matlab %% Set Sampling Time - Ts = opts.Ts; - Tmax = opts.Tmax; + Ts = args.Ts; + Tmax = args.Tmax; %% Low Pass Filter to filter out the references s = zpk('s'); w0 = 2*pi*100; xi = 1; H_lpf = 1/(1 + 2*xi/w0*s + s^2/w0^2); +#+end_src +*** Translation Stage +#+begin_src matlab %% Translation stage - Dy t = 0:Ts:Tmax; % Time Vector [s] Dy = zeros(length(t), 1); Dyd = zeros(length(t), 1); Dydd = zeros(length(t), 1); - switch opts.Dy_type + switch args.Dy_type case 'constant' - Dy(:) = opts.Dy_amplitude; + Dy(:) = args.Dy_amplitude; Dyd(:) = 0; Dydd(:) = 0; case 'triangular' % This is done to unsure that we start with no displacement - Dy_raw = opts.Dy_amplitude*sawtooth(2*pi*t/opts.Dy_period,1/2); - i0 = find(t>=opts.Dy_period/4,1); + Dy_raw = args.Dy_amplitude*sawtooth(2*pi*t/args.Dy_period,1/2); + i0 = find(t>=args.Dy_period/4,1); Dy(1:end-i0+1) = Dy_raw(i0:end); Dy(end-i0+2:end) = Dy_raw(end); % we fix the last value @@ -115,29 +136,32 @@ This Matlab function is accessible [[file:../src/initializeInputs.m][here]]. Dyd = lsim(H_lpf*s, Dy, t); Dydd = lsim(H_lpf*s^2, Dy, t); case 'sinusoidal' - Dy(:) = opts.Dy_amplitude*sin(2*pi/opts.Dy_period*t); - Dyd = opts.Dy_amplitude*2*pi/opts.Dy_period*cos(2*pi/opts.Dy_period*t); - Dydd = -opts.Dy_amplitude*(2*pi/opts.Dy_period)^2*sin(2*pi/opts.Dy_period*t); + Dy(:) = args.Dy_amplitude*sin(2*pi/args.Dy_period*t); + Dyd = args.Dy_amplitude*2*pi/args.Dy_period*cos(2*pi/args.Dy_period*t); + Dydd = -args.Dy_amplitude*(2*pi/args.Dy_period)^2*sin(2*pi/args.Dy_period*t); otherwise warning('Dy_type is not set correctly'); end Dy = struct('time', t, 'signals', struct('values', Dy), 'deriv', Dyd, 'dderiv', Dydd); +#+end_src +*** Tilt Stage +#+begin_src matlab %% Tilt Stage - Ry t = 0:Ts:Tmax; % Time Vector [s] Ry = zeros(length(t), 1); Ryd = zeros(length(t), 1); Rydd = zeros(length(t), 1); - switch opts.Ry_type + switch args.Ry_type case 'constant' - Ry(:) = opts.Ry_amplitude; + Ry(:) = args.Ry_amplitude; Ryd(:) = 0; Rydd(:) = 0; case 'triangular' - Ry_raw = opts.Ry_amplitude*sawtooth(2*pi*t/opts.Ry_period,1/2); - i0 = find(t>=opts.Ry_period/4,1); + Ry_raw = args.Ry_amplitude*sawtooth(2*pi*t/args.Ry_period,1/2); + i0 = find(t>=args.Ry_period/4,1); Ry(1:end-i0+1) = Ry_raw(i0:end); Ry(end-i0+2:end) = Ry_raw(end); % we fix the last value @@ -146,29 +170,32 @@ This Matlab function is accessible [[file:../src/initializeInputs.m][here]]. Ryd = lsim(H_lpf*s, Ry, t); Rydd = lsim(H_lpf*s^2, Ry, t); case 'sinusoidal' - Ry(:) = opts.Ry_amplitude*sin(2*pi/opts.Ry_period*t); + Ry(:) = args.Ry_amplitude*sin(2*pi/args.Ry_period*t); - Ryd = opts.Ry_amplitude*2*pi/opts.Ry_period*cos(2*pi/opts.Ry_period*t); - Rydd = -opts.Ry_amplitude*(2*pi/opts.Ry_period)^2*sin(2*pi/opts.Ry_period*t); + Ryd = args.Ry_amplitude*2*pi/args.Ry_period*cos(2*pi/args.Ry_period*t); + Rydd = -args.Ry_amplitude*(2*pi/args.Ry_period)^2*sin(2*pi/args.Ry_period*t); otherwise warning('Ry_type is not set correctly'); end Ry = struct('time', t, 'signals', struct('values', Ry), 'deriv', Ryd, 'dderiv', Rydd); +#+end_src +*** Spindle +#+begin_src matlab %% Spindle - Rz t = 0:Ts:Tmax; % Time Vector [s] Rz = zeros(length(t), 1); Rzd = zeros(length(t), 1); Rzdd = zeros(length(t), 1); - switch opts.Rz_type + switch args.Rz_type case 'constant' - Rz(:) = opts.Rz_amplitude; + Rz(:) = args.Rz_amplitude; Rzd(:) = 0; Rzdd(:) = 0; case 'rotating' - Rz(:) = opts.Rz_amplitude+2*pi/opts.Rz_period*t; + Rz(:) = args.Rz_amplitude+2*pi/args.Rz_period*t; % The signal is filtered out Rz = lsim(H_lpf, Rz, t); @@ -179,29 +206,32 @@ This Matlab function is accessible [[file:../src/initializeInputs.m][here]]. end Rz = struct('time', t, 'signals', struct('values', Rz), 'deriv', Rzd, 'dderiv', Rzdd); +#+end_src +*** Micro Hexapod +#+begin_src matlab %% Micro-Hexapod t = [0, Ts]; Dh = zeros(length(t), 6); Dhl = zeros(length(t), 6); - switch opts.Dh_type + switch args.Dh_type case 'constant' - Dh = [opts.Dh_pos, opts.Dh_pos]; + Dh = [args.Dh_pos, args.Dh_pos]; - load('./mat/stages.mat', 'micro_hexapod'); + load('mat/stages.mat', 'micro_hexapod'); - AP = [opts.Dh_pos(1) ; opts.Dh_pos(2) ; opts.Dh_pos(3)]; + AP = [args.Dh_pos(1) ; args.Dh_pos(2) ; args.Dh_pos(3)]; - tx = opts.Dh_pos(4); - ty = opts.Dh_pos(5); - tz = opts.Dh_pos(6); + tx = args.Dh_pos(4); + ty = args.Dh_pos(5); + tz = args.Dh_pos(6); ARB = [cos(tz) -sin(tz) 0; sin(tz) cos(tz) 0; 0 0 1]*... [ cos(ty) 0 sin(ty); - 0 1 0; + 0 1 0; -sin(ty) 0 cos(ty)]*... [1 0 0; 0 cos(tx) -sin(tx); @@ -215,28 +245,37 @@ This Matlab function is accessible [[file:../src/initializeInputs.m][here]]. Dh = struct('time', t, 'signals', struct('values', Dh)); Dhl = struct('time', t, 'signals', struct('values', Dhl)); +#+end_src +*** Axis Compensation +#+begin_src matlab %% Axis Compensation - Rm t = [0, Ts]; - Rm = [opts.Rm_pos, opts.Rm_pos]; + Rm = [args.Rm_pos, args.Rm_pos]; Rm = struct('time', t, 'signals', struct('values', Rm)); +#+end_src +*** Nano Hexapod +#+begin_src matlab %% Nano-Hexapod t = [0, Ts]; Dn = zeros(length(t), 6); - switch opts.Dn_type + switch args.Dn_type case 'constant' - Dn = [opts.Dn_pos, opts.Dn_pos]; + Dn = [args.Dn_pos, args.Dn_pos]; otherwise warning('Dn_type is not set correctly'); end Dn = struct('time', t, 'signals', struct('values', Dn)); +#+end_src +*** Save +#+begin_src matlab %% Save - save('./mat/nass_references.mat', 'Dy', 'Ry', 'Rz', 'Dh', 'Dhl', 'Rm', 'Dn', 'Ts'); + save('mat/nass_references.mat', 'Dy', 'Ry', 'Rz', 'Dh', 'Dhl', 'Rm', 'Dn', 'Ts'); end #+end_src @@ -252,36 +291,35 @@ This Matlab function is accessible [[file:src/initDisturbances.m][here]]. *** Function Declaration and Documentation #+begin_src matlab - function [] = initDisturbances(opts_param) + function [] = initDisturbances(args) % initDisturbances - Initialize the disturbances % - % Syntax: [] = initDisturbances(opts_param) + % Syntax: [] = initDisturbances(args) % % Inputs: - % - opts_param - + % - args - #+end_src -*** Default values for the Options +*** Optional Parameters #+begin_src matlab - %% Default values for opts - opts = struct(... - 'Dwx', true, ... % Ground Motion - X direction - 'Dwy', true, ... % Ground Motion - Y direction - 'Dwz', true, ... % Ground Motion - Z direction - 'Fty_x', true, ... % Translation Stage - X direction - 'Fty_z', true, ... % Translation Stage - Z direction - 'Frz_z', true ... % Spindle - Z direction - ); - - %% Populate opts with input parameters - if exist('opts_param','var') - for opt = fieldnames(opts_param)' - opts.(opt{1}) = opts_param.(opt{1}); - end + arguments + % Ground Motion - X direction + args.Dwx logical {mustBeNumericOrLogical} = true + % Ground Motion - Y direction + args.Dwy logical {mustBeNumericOrLogical} = true + % Ground Motion - Z direction + args.Dwz logical {mustBeNumericOrLogical} = true + % Translation Stage - X direction + args.Fty_x logical {mustBeNumericOrLogical} = true + % Translation Stage - Z direction + args.Fty_z logical {mustBeNumericOrLogical} = true + % Spindle - Z direction + args.Frz_z logical {mustBeNumericOrLogical} = true end #+end_src + *** Load Data #+begin_src matlab load('./disturbances/mat/dist_psd.mat', 'dist_f'); @@ -317,7 +355,7 @@ We define some parameters that will be used in the algorithm. #+end_src #+begin_src matlab - if opts.Dwx + if args.Dwx theta = 2*pi*rand(N/2,1); % Generate random phase [rad] Cx = [0 ; C.*complex(cos(theta),sin(theta))]; Cx = [Cx; flipud(conj(Cx(2:end)))];; @@ -328,7 +366,7 @@ We define some parameters that will be used in the algorithm. #+end_src #+begin_src matlab - if opts.Dwy + if args.Dwy theta = 2*pi*rand(N/2,1); % Generate random phase [rad] Cx = [0 ; C.*complex(cos(theta),sin(theta))]; Cx = [Cx; flipud(conj(Cx(2:end)))];; @@ -339,7 +377,7 @@ We define some parameters that will be used in the algorithm. #+end_src #+begin_src matlab - if opts.Dwy + if args.Dwy theta = 2*pi*rand(N/2,1); % Generate random phase [rad] Cx = [0 ; C.*complex(cos(theta),sin(theta))]; Cx = [Cx; flipud(conj(Cx(2:end)))];; @@ -351,7 +389,7 @@ We define some parameters that will be used in the algorithm. *** Translation Stage - X direction #+begin_src matlab - if opts.Fty_x + if args.Fty_x phi = dist_f.psd_ty; % TODO - we take here the vertical direction which is wrong but approximate C = zeros(N/2,1); for i = 1:N/2 @@ -369,7 +407,7 @@ We define some parameters that will be used in the algorithm. *** Translation Stage - Z direction #+begin_src matlab - if opts.Fty_z + if args.Fty_z phi = dist_f.psd_ty; C = zeros(N/2,1); for i = 1:N/2 @@ -387,7 +425,7 @@ We define some parameters that will be used in the algorithm. *** Spindle - Z direction #+begin_src matlab - if opts.Frz_z + if args.Frz_z phi = dist_f.psd_rz; C = zeros(N/2,1); for i = 1:N/2 @@ -421,7 +459,7 @@ We define some parameters that will be used in the algorithm. *** Save #+begin_src matlab - save('./mat/nass_disturbances.mat', 'Dwx', 'Dwy', 'Dwz', 'Fty_x', 'Fty_z', 'Frz_z', 'Fd', 'Ts', 't'); + save('mat/nass_disturbances.mat', 'Dwx', 'Dwy', 'Dwz', 'Fty_x', 'Fty_z', 'Frz_z', 'Fd', 'Ts', 't'); #+end_src * Initialize Elements @@ -462,15 +500,9 @@ end This Matlab function is accessible [[file:../src/initializeGranite.m][here]]. #+begin_src matlab - function [granite] = initializeGranite(opts_param) - %% Default values for opts - opts = struct('rigid', false); - - %% Populate opts with input parameters - if exist('opts_param','var') - for opt = fieldnames(opts_param)' - opts.(opt{1}) = opts_param.(opt{1}); - end + function [granite] = initializeGranite(args) + arguments + args.rigid logical {mustBeNumericOrLogical} = false end %% @@ -486,7 +518,7 @@ This Matlab function is accessible [[file:../src/initializeGranite.m][here]]. granite.mass_top = 4000; % [kg] TODO %% Dynamical Properties - if opts.rigid + if args.rigid granite.k.x = 1e12; % [N/m] granite.k.y = 1e12; % [N/m] granite.k.z = 1e12; % [N/m] @@ -527,15 +559,9 @@ This Matlab function is accessible [[file:../src/initializeGranite.m][here]]. This Matlab function is accessible [[file:../src/initializeTy.m][here]]. #+begin_src matlab - function [ty] = initializeTy(opts_param) - %% Default values for opts - opts = struct('rigid', false); - - %% Populate opts with input parameters - if exist('opts_param','var') - for opt = fieldnames(opts_param)' - opts.(opt{1}) = opts_param.(opt{1}); - end + function [ty] = initializeTy(args) + arguments + args.rigid logical {mustBeNumericOrLogical} = false end %% @@ -582,7 +608,7 @@ This Matlab function is accessible [[file:../src/initializeTy.m][here]]. ty.m = 1000; % TODO [kg] %% Y-Translation - Dynamicals Properties - if opts.rigid + if args.rigid ty.k.ax = 1e12; % Axial Stiffness for each of the 4 guidance (y) [N/m] ty.k.rad = 1e12; % Radial Stiffness for each of the 4 guidance (x-z) [N/m] else @@ -608,15 +634,9 @@ This Matlab function is accessible [[file:../src/initializeTy.m][here]]. This Matlab function is accessible [[file:../src/initializeRy.m][here]]. #+begin_src matlab - function [ry] = initializeRy(opts_param) - %% Default values for opts - opts = struct('rigid', false); - - %% Populate opts with input parameters - if exist('opts_param','var') - for opt = fieldnames(opts_param)' - opts.(opt{1}) = opts_param.(opt{1}); - end + function [ry] = initializeRy(args) + arguments + args.rigid logical {mustBeNumericOrLogical} = false end %% @@ -643,7 +663,7 @@ This Matlab function is accessible [[file:../src/initializeRy.m][here]]. ry.m = 800; % TODO [kg] %% Tilt Stage - Dynamical Properties - if opts.rigid + if args.rigid ry.k.tilt = 1e10; % Rotation stiffness around y [N*m/deg] ry.k.h = 1e12; % Stiffness in the direction of the guidance [N/m] ry.k.rad = 1e12; % Stiffness in the top direction [N/m] @@ -678,15 +698,9 @@ This Matlab function is accessible [[file:../src/initializeRy.m][here]]. This Matlab function is accessible [[file:../src/initializeRz.m][here]]. #+begin_src matlab - function [rz] = initializeRz(opts_param) - %% Default values for opts - opts = struct('rigid', false); - - %% Populate opts with input parameters - if exist('opts_param','var') - for opt = fieldnames(opts_param)' - opts.(opt{1}) = opts_param.(opt{1}); - end + function [rz] = initializeRz(args) + arguments + args.rigid logical {mustBeNumericOrLogical} = false end %% @@ -711,7 +725,7 @@ This Matlab function is accessible [[file:../src/initializeRz.m][here]]. %% Spindle - Dynamical Properties - if opts.rigid + if args.rigid rz.k.rot = 1e10; % Rotational Stiffness (Rz) [N*m/deg] rz.k.tilt = 1e10; % Rotational Stiffness (Rx, Ry) [N*m/deg] rz.k.ax = 1e12; % Axial Stiffness (Z) [N/m] @@ -744,19 +758,11 @@ This Matlab function is accessible [[file:../src/initializeRz.m][here]]. This Matlab function is accessible [[file:../src/initializeMicroHexapod.m][here]]. #+begin_src matlab - function [micro_hexapod] = initializeMicroHexapod(opts_param) - %% Default values for opts - opts = struct(... - 'rigid', false, ... - 'AP', zeros(3, 1), ... % Wanted position in [m] of OB with respect to frame {A} - 'ARB', eye(3) ... % Rotation Matrix that represent the wanted orientation of frame {B} with respect to frame {A} - ); - - %% Populate opts with input parameters - if exist('opts_param','var') - for opt = fieldnames(opts_param)' - opts.(opt{1}) = opts_param.(opt{1}); - end + function [micro_hexapod] = initializeMicroHexapod(args) + arguments + args.rigid logical {mustBeNumericOrLogical} = false + args.AP (3,1) double {mustBeNumeric} = zeros(3,1) + args.ARB (3,3) double {mustBeNumeric} = eye(3) end %% Stewart Object @@ -792,7 +798,7 @@ This Matlab function is accessible [[file:../src/initializeMicroHexapod.m][here] Leg = struct(); Leg.stroke = 10e-3; % Maximum Stroke of each leg [m] - if opts.rigid + if args.rigid Leg.k.ax = 1e12; % Stiffness of each leg [N/m] else Leg.k.ax = 2e7; % Stiffness of each leg [N/m] @@ -844,7 +850,7 @@ This Matlab function is accessible [[file:../src/initializeMicroHexapod.m][here] micro_hexapod = initializeParameters(micro_hexapod); %% Setup equilibrium position of each leg - micro_hexapod.L0 = inverseKinematicsHexapod(micro_hexapod, opts.AP, opts.ARB); + micro_hexapod.L0 = inverseKinematicsHexapod(micro_hexapod, args.AP, args.ARB); %% Save save('./mat/stages.mat', 'micro_hexapod', '-append'); @@ -1003,18 +1009,10 @@ This Matlab function is accessible [[file:../src/initializeAxisc.m][here]]. This Matlab function is accessible [[file:../src/initializeMirror.m][here]]. #+begin_src matlab - function [] = initializeMirror(opts_param) - %% Default values for opts - opts = struct(... - 'shape', 'spherical', ... % spherical or conical - 'angle', 45 ... - ); - - %% Populate opts with input parameters - if exist('opts_param','var') - for opt = fieldnames(opts_param)' - opts.(opt{1}) = opts_param.(opt{1}); - end + function [] = initializeMirror(args) + arguments + args.shape char {mustBeMember(args.shape,{'spherical', 'conical'})} = 'spherical' + args.angle (1,1) double {mustBeNumeric, mustBePositive} = 45 end %% @@ -1029,7 +1027,7 @@ This Matlab function is accessible [[file:../src/initializeMirror.m][here]]. mirror.density = 2400; % Density of the mirror [kg/m3] mirror.color = [0.4 1.0 1.0]; % Color of the mirror - mirror.cone_length = mirror.rad*tand(opts.angle)+mirror.h+mirror.jacobian; % Distance from Apex point of the cone to jacobian point + mirror.cone_length = mirror.rad*tand(args.angle)+mirror.h+mirror.jacobian; % Distance from Apex point of the cone to jacobian point %% Shape mirror.shape = [... @@ -1039,14 +1037,14 @@ This Matlab function is accessible [[file:../src/initializeMirror.m][here]]. mirror.rad 0 ... ]; - if strcmp(opts.shape, 'spherical') + if strcmp(args.shape, 'spherical') mirror.sphere_radius = sqrt((mirror.jacobian+mirror.h)^2+mirror.rad^2); % Radius of the sphere [mm] for z = linspace(0, mirror.h, 101) mirror.shape = [mirror.shape; sqrt(mirror.sphere_radius^2-(z-mirror.jacobian-mirror.h)^2) z]; end - elseif strcmp(opts.shape, 'conical') - mirror.shape = [mirror.shape; mirror.rad+mirror.h/tand(opts.angle) mirror.h]; + elseif strcmp(args.shape, 'conical') + mirror.shape = [mirror.shape; mirror.rad+mirror.h/tand(args.angle) mirror.h]; else error('Shape should be either conical or spherical'); end @@ -1068,22 +1066,17 @@ This Matlab function is accessible [[file:../src/initializeMirror.m][here]]. This Matlab function is accessible [[file:../src/initializeNanoHexapod.m][here]]. #+begin_src matlab - function [nano_hexapod] = initializeNanoHexapod(opts_param) - %% Default values for opts - opts = struct('actuator', 'piezo'); - - %% Populate opts with input parameters - if exist('opts_param','var') - for opt = fieldnames(opts_param)' - opts.(opt{1}) = opts_param.(opt{1}); - end + function [nano_hexapod] = initializeNanoHexapod(args) + arguments + args.actuator char {mustBeMember(args.actuator,{'piezo', 'lorentz'})} = 'piezo' + args.AP (3,1) double {mustBeNumeric} = zeros(3,1) + args.ARB (3,3) double {mustBeNumeric} = eye(3) end %% Stewart Object nano_hexapod = struct(); nano_hexapod.h = 90; % Total height of the platform [mm] nano_hexapod.jacobian = 175; % Point where the Jacobian is computed => Center of rotation [mm] - % nano_hexapod.jacobian = 174.26; % Point where the Jacobian is computed => Center of rotation [mm] %% Bottom Plate BP = struct(); @@ -1113,12 +1106,12 @@ This Matlab function is accessible [[file:../src/initializeNanoHexapod.m][here]] Leg = struct(); Leg.stroke = 80e-6; % Maximum Stroke of each leg [m] - if strcmp(opts.actuator, 'piezo') + if strcmp(args.actuator, 'piezo') Leg.k.ax = 1e7; % Stiffness of each leg [N/m] - elseif strcmp(opts.actuator, 'lorentz') + elseif strcmp(args.actuator, 'lorentz') Leg.k.ax = 1e4; % Stiffness of each leg [N/m] else - error('opts.actuator should be piezo or lorentz'); + error('args.actuator should be piezo or lorentz'); end Leg.ksi.ax = 10; % Maximum amplification at resonance [] Leg.rad.bottom = 12; % Radius of the cylinder of the bottom part [mm] @@ -1167,6 +1160,9 @@ This Matlab function is accessible [[file:../src/initializeNanoHexapod.m][here]] %% nano_hexapod = initializeParameters(nano_hexapod); + %% Setup equilibrium position of each leg + nano_hexapod.L0 = inverseKinematicsHexapod(nano_hexapod, args.AP, args.ARB); + %% Save save('./mat/stages.mat', 'nano_hexapod', '-append'); @@ -1284,17 +1280,7 @@ This Matlab function is accessible [[file:../src/initializeNanoHexapod.m][here]] This Matlab function is accessible [[file:../src/initializeCedratPiezo.m][here]]. #+begin_src matlab - function [cedrat] = initializeCedratPiezo(opts_param) - %% Default values for opts - opts = struct(); - - %% Populate opts with input parameters - if exist('opts_param','var') - for opt = fieldnames(opts_param)' - opts.(opt{1}) = opts_param.(opt{1}); - end - end - + function [cedrat] = initializeCedratPiezo() %% Stewart Object cedrat = struct(); cedrat.k = 10e7; % Linear Stiffness of each "blade" [N/m] @@ -1323,20 +1309,13 @@ This Matlab function is accessible [[file:../src/initializeCedratPiezo.m][here]] This Matlab function is accessible [[file:../src/initializeSample.m][here]]. #+begin_src matlab - function [sample] = initializeSample(opts_param) - %% Default values for opts - sample = struct('radius', 100, ... - 'height', 300, ... - 'mass', 50, ... - 'offset', 0, ... - 'color', [0.45, 0.45, 0.45] ... - ); - - %% Populate opts with input parameters - if exist('opts_param','var') - for opt = fieldnames(opts_param)' - sample.(opt{1}) = opts_param.(opt{1}); - end + function [sample] = initializeSample(sample) + arguments + sample.radius (1,1) double {mustBeNumeric, mustBePositive} = 100 + sample.height (1,1) double {mustBeNumeric, mustBePositive} = 300 + sample.mass (1,1) double {mustBeNumeric, mustBePositive} = 50 + sample.offset (1,1) double {mustBeNumeric} = 0 + sample.color (1,3) double {mustBeNumeric} = [0.45, 0.45, 0.45] end %% diff --git a/src/initDisturbances.m b/src/initDisturbances.m index d95427c..8d68c19 100644 --- a/src/initDisturbances.m +++ b/src/initDisturbances.m @@ -1,26 +1,24 @@ -function [] = initDisturbances(opts_param) +function [] = initDisturbances(args) % initDisturbances - Initialize the disturbances % -% Syntax: [] = initDisturbances(opts_param) +% Syntax: [] = initDisturbances(args) % % Inputs: -% - opts_param - +% - args - -%% Default values for opts -opts = struct(... - 'Dwx', true, ... % Ground Motion - X direction - 'Dwy', true, ... % Ground Motion - Y direction - 'Dwz', true, ... % Ground Motion - Z direction - 'Fty_x', true, ... % Translation Stage - X direction - 'Fty_z', true, ... % Translation Stage - Z direction - 'Frz_z', true ... % Spindle - Z direction -); - -%% Populate opts with input parameters -if exist('opts_param','var') - for opt = fieldnames(opts_param)' - opts.(opt{1}) = opts_param.(opt{1}); - end +arguments + % Ground Motion - X direction + args.Dwx logical {mustBeNumericOrLogical} = true + % Ground Motion - Y direction + args.Dwy logical {mustBeNumericOrLogical} = true + % Ground Motion - Z direction + args.Dwz logical {mustBeNumericOrLogical} = true + % Translation Stage - X direction + args.Fty_x logical {mustBeNumericOrLogical} = true + % Translation Stage - Z direction + args.Fty_z logical {mustBeNumericOrLogical} = true + % Spindle - Z direction + args.Frz_z logical {mustBeNumericOrLogical} = true end load('./disturbances/mat/dist_psd.mat', 'dist_f'); @@ -44,7 +42,7 @@ for i = 1:N/2 C(i) = sqrt(phi(i)*df); end -if opts.Dwx +if args.Dwx theta = 2*pi*rand(N/2,1); % Generate random phase [rad] Cx = [0 ; C.*complex(cos(theta),sin(theta))]; Cx = [Cx; flipud(conj(Cx(2:end)))];; @@ -53,7 +51,7 @@ else Dwx = zeros(length(t), 1); end -if opts.Dwy +if args.Dwy theta = 2*pi*rand(N/2,1); % Generate random phase [rad] Cx = [0 ; C.*complex(cos(theta),sin(theta))]; Cx = [Cx; flipud(conj(Cx(2:end)))];; @@ -62,7 +60,7 @@ else Dwy = zeros(length(t), 1); end -if opts.Dwy +if args.Dwy theta = 2*pi*rand(N/2,1); % Generate random phase [rad] Cx = [0 ; C.*complex(cos(theta),sin(theta))]; Cx = [Cx; flipud(conj(Cx(2:end)))];; @@ -71,7 +69,7 @@ else Dwz = zeros(length(t), 1); end -if opts.Fty_x +if args.Fty_x phi = dist_f.psd_ty; % TODO - we take here the vertical direction which is wrong but approximate C = zeros(N/2,1); for i = 1:N/2 @@ -86,7 +84,7 @@ else Fty_x = zeros(length(t), 1); end -if opts.Fty_z +if args.Fty_z phi = dist_f.psd_ty; C = zeros(N/2,1); for i = 1:N/2 @@ -101,7 +99,7 @@ else Fty_z = zeros(length(t), 1); end -if opts.Frz_z +if args.Frz_z phi = dist_f.psd_rz; C = zeros(N/2,1); for i = 1:N/2 diff --git a/src/initializeCedratPiezo.m b/src/initializeCedratPiezo.m index b5f3b80..a91dc8e 100644 --- a/src/initializeCedratPiezo.m +++ b/src/initializeCedratPiezo.m @@ -1,14 +1,4 @@ -function [cedrat] = initializeCedratPiezo(opts_param) - %% Default values for opts - opts = struct(); - - %% Populate opts with input parameters - if exist('opts_param','var') - for opt = fieldnames(opts_param)' - opts.(opt{1}) = opts_param.(opt{1}); - end - end - +function [cedrat] = initializeCedratPiezo() %% Stewart Object cedrat = struct(); cedrat.k = 10e7; % Linear Stiffness of each "blade" [N/m] diff --git a/src/initializeGranite.m b/src/initializeGranite.m index fe27760..e3275c5 100644 --- a/src/initializeGranite.m +++ b/src/initializeGranite.m @@ -1,12 +1,6 @@ -function [granite] = initializeGranite(opts_param) - %% Default values for opts - opts = struct('rigid', false); - - %% Populate opts with input parameters - if exist('opts_param','var') - for opt = fieldnames(opts_param)' - opts.(opt{1}) = opts_param.(opt{1}); - end +function [granite] = initializeGranite(args) + arguments + args.rigid logical {mustBeNumericOrLogical} = false end %% @@ -22,7 +16,7 @@ function [granite] = initializeGranite(opts_param) granite.mass_top = 4000; % [kg] TODO %% Dynamical Properties - if opts.rigid + if args.rigid granite.k.x = 1e12; % [N/m] granite.k.y = 1e12; % [N/m] granite.k.z = 1e12; % [N/m] diff --git a/src/initializeMicroHexapod.m b/src/initializeMicroHexapod.m index 79a5d28..41da308 100644 --- a/src/initializeMicroHexapod.m +++ b/src/initializeMicroHexapod.m @@ -1,16 +1,8 @@ -function [micro_hexapod] = initializeMicroHexapod(opts_param) - %% Default values for opts - opts = struct(... - 'rigid', false, ... - 'AP', zeros(3, 1), ... % Wanted position in [m] of OB with respect to frame {A} - 'ARB', eye(3) ... % Rotation Matrix that represent the wanted orientation of frame {B} with respect to frame {A} - ); - - %% Populate opts with input parameters - if exist('opts_param','var') - for opt = fieldnames(opts_param)' - opts.(opt{1}) = opts_param.(opt{1}); - end +function [micro_hexapod] = initializeMicroHexapod(args) + arguments + args.rigid logical {mustBeNumericOrLogical} = false + args.AP (3,1) double {mustBeNumeric} = zeros(3,1) + args.ARB (3,3) double {mustBeNumeric} = eye(3) end %% Stewart Object @@ -46,7 +38,7 @@ function [micro_hexapod] = initializeMicroHexapod(opts_param) Leg = struct(); Leg.stroke = 10e-3; % Maximum Stroke of each leg [m] - if opts.rigid + if args.rigid Leg.k.ax = 1e12; % Stiffness of each leg [N/m] else Leg.k.ax = 2e7; % Stiffness of each leg [N/m] @@ -98,7 +90,7 @@ function [micro_hexapod] = initializeMicroHexapod(opts_param) micro_hexapod = initializeParameters(micro_hexapod); %% Setup equilibrium position of each leg - micro_hexapod.L0 = inverseKinematicsHexapod(micro_hexapod, opts.AP, opts.ARB); + micro_hexapod.L0 = inverseKinematicsHexapod(micro_hexapod, args.AP, args.ARB); %% Save save('./mat/stages.mat', 'micro_hexapod', '-append'); diff --git a/src/initializeMirror.m b/src/initializeMirror.m index 10234df..db9daf4 100644 --- a/src/initializeMirror.m +++ b/src/initializeMirror.m @@ -1,15 +1,7 @@ -function [] = initializeMirror(opts_param) - %% Default values for opts - opts = struct(... - 'shape', 'spherical', ... % spherical or conical - 'angle', 45 ... - ); - - %% Populate opts with input parameters - if exist('opts_param','var') - for opt = fieldnames(opts_param)' - opts.(opt{1}) = opts_param.(opt{1}); - end +function [] = initializeMirror(args) + arguments + args.shape char {mustBeMember(args.shape,{'spherical', 'conical'})} = 'spherical' + args.angle (1,1) double {mustBeNumeric, mustBePositive} = 45 end %% @@ -24,7 +16,7 @@ function [] = initializeMirror(opts_param) mirror.density = 2400; % Density of the mirror [kg/m3] mirror.color = [0.4 1.0 1.0]; % Color of the mirror - mirror.cone_length = mirror.rad*tand(opts.angle)+mirror.h+mirror.jacobian; % Distance from Apex point of the cone to jacobian point + mirror.cone_length = mirror.rad*tand(args.angle)+mirror.h+mirror.jacobian; % Distance from Apex point of the cone to jacobian point %% Shape mirror.shape = [... @@ -34,14 +26,14 @@ function [] = initializeMirror(opts_param) mirror.rad 0 ... ]; - if strcmp(opts.shape, 'spherical') + if strcmp(args.shape, 'spherical') mirror.sphere_radius = sqrt((mirror.jacobian+mirror.h)^2+mirror.rad^2); % Radius of the sphere [mm] for z = linspace(0, mirror.h, 101) mirror.shape = [mirror.shape; sqrt(mirror.sphere_radius^2-(z-mirror.jacobian-mirror.h)^2) z]; end - elseif strcmp(opts.shape, 'conical') - mirror.shape = [mirror.shape; mirror.rad+mirror.h/tand(opts.angle) mirror.h]; + elseif strcmp(args.shape, 'conical') + mirror.shape = [mirror.shape; mirror.rad+mirror.h/tand(args.angle) mirror.h]; else error('Shape should be either conical or spherical'); end diff --git a/src/initializeNanoHexapod.m b/src/initializeNanoHexapod.m index a450a3f..ea7af28 100644 --- a/src/initializeNanoHexapod.m +++ b/src/initializeNanoHexapod.m @@ -1,16 +1,8 @@ -function [nano_hexapod] = initializeNanoHexapod(opts_param) - %% Default values for opts - opts = struct(... - 'actuator', 'piezo', ... - 'AP', zeros(3, 1), ... % Wanted position in [m] of OB with respect to frame {A} - 'ARB', eye(3) ... % Rotation Matrix that represent the wanted orientation of frame {B} with respect to frame {A} - ); - - %% Populate opts with input parameters - if exist('opts_param','var') - for opt = fieldnames(opts_param)' - opts.(opt{1}) = opts_param.(opt{1}); - end +function [nano_hexapod] = initializeNanoHexapod(args) + arguments + args.actuator char {mustBeMember(args.actuator,{'piezo', 'lorentz'})} = 'piezo' + args.AP (3,1) double {mustBeNumeric} = zeros(3,1) + args.ARB (3,3) double {mustBeNumeric} = eye(3) end %% Stewart Object @@ -46,12 +38,12 @@ function [nano_hexapod] = initializeNanoHexapod(opts_param) Leg = struct(); Leg.stroke = 80e-6; % Maximum Stroke of each leg [m] - if strcmp(opts.actuator, 'piezo') + if strcmp(args.actuator, 'piezo') Leg.k.ax = 1e7; % Stiffness of each leg [N/m] - elseif strcmp(opts.actuator, 'lorentz') + elseif strcmp(args.actuator, 'lorentz') Leg.k.ax = 1e4; % Stiffness of each leg [N/m] else - error('opts.actuator should be piezo or lorentz'); + error('args.actuator should be piezo or lorentz'); end Leg.ksi.ax = 10; % Maximum amplification at resonance [] Leg.rad.bottom = 12; % Radius of the cylinder of the bottom part [mm] @@ -101,7 +93,7 @@ function [nano_hexapod] = initializeNanoHexapod(opts_param) nano_hexapod = initializeParameters(nano_hexapod); %% Setup equilibrium position of each leg - nano_hexapod.L0 = inverseKinematicsHexapod(nano_hexapod, opts.AP, opts.ARB); + nano_hexapod.L0 = inverseKinematicsHexapod(nano_hexapod, args.AP, args.ARB); %% Save save('./mat/stages.mat', 'nano_hexapod', '-append'); diff --git a/src/initializeReferences.m b/src/initializeReferences.m index 67506a2..f59c9ad 100644 --- a/src/initializeReferences.m +++ b/src/initializeReferences.m @@ -1,36 +1,45 @@ -function [ref] = initializeReferences(opts_param) +function [ref] = initializeReferences(args) -%% Default values for opts -opts = struct( ... - 'Ts', 1e-3, ... % Sampling Frequency [s] - 'Tmax', 100, ... % Maximum simulation time [s] - 'Dy_type', 'constant', ... % Either "constant" / "triangular" / "sinusoidal" - 'Dy_amplitude', 0, ... % Amplitude of the displacement [m] - 'Dy_period', 1, ... % Period of the displacement [s] - 'Ry_type', 'constant', ... % Either "constant" / "triangular" / "sinusoidal" - 'Ry_amplitude', 0, ... % Amplitude [rad] - 'Ry_period', 1, ... % Period of the displacement [s] - 'Rz_type', 'constant', ... % Either "constant" / "rotating" - 'Rz_amplitude', 0, ... % Initial angle [rad] - 'Rz_period', 1, ... % Period of the rotating [s] - 'Dh_type', 'constant', ... % For now, only constant is implemented - 'Dh_pos', zeros(6, 1), ... % Initial position [m,m,m,rad,rad,rad] of the top platform (Pitch-Roll-Yaw Euler angles) - 'Rm_type', 'constant', ... % For now, only constant is implemented - 'Rm_pos', [0; pi], ... % Initial position of the two masses - 'Dn_type', 'constant', ... % For now, only constant is implemented - 'Dn_pos', zeros(6,1) ... % Initial position [m,m,m,rad,rad,rad] of the top platform -); - -%% Populate opts with input parameters -if exist('opts_param','var') - for opt = fieldnames(opts_param)' - opts.(opt{1}) = opts_param.(opt{1}); - end +arguments + % Sampling Frequency [s] + args.Ts (1,1) double {mustBeNumeric, mustBePositive} = 1e-3 + % Maximum simulation time [s] + args.Tmax (1,1) double {mustBeNumeric, mustBePositive} = 100 + % Either "constant" / "triangular" / "sinusoidal" + args.Dy_type char {mustBeMember(args.Dy_type,{'constant', 'triangular', 'sinusoidal'})} = 'constant' + % Amplitude of the displacement [m] + args.Dy_amplitude (1,1) double {mustBeNumeric} = 0 + % Period of the displacement [s] + args.Dy_period (1,1) double {mustBeNumeric, mustBePositive} = 1 + % Either "constant" / "triangular" / "sinusoidal" + args.Ry_type char {mustBeMember(args.Ry_type,{'constant', 'triangular', 'sinusoidal'})} = 'constant' + % Amplitude [rad] + args.Ry_amplitude (1,1) double {mustBeNumeric} = 0 + % Period of the displacement [s] + args.Ry_period (1,1) double {mustBeNumeric, mustBePositive} = 1 + % Either "constant" / "rotating" + args.Rz_type char {mustBeMember(args.Rz_type,{'constant', 'rotating'})} = 'constant' + % Initial angle [rad] + args.Rz_amplitude (1,1) double {mustBeNumeric} = 0 + % Period of the rotating [s] + args.Rz_period (1,1) double {mustBeNumeric, mustBePositive} = 1 + % For now, only constant is implemented + args.Dh_type char {mustBeMember(args.Dh_type,{'constant'})} = 'constant' + % Initial position [m,m,m,rad,rad,rad] of the top platform (Pitch-Roll-Yaw Euler angles) + args.Dh_pos (6,1) double {mustBeNumeric} = zeros(6, 1), ... + % For now, only constant is implemented + args.Rm_type char {mustBeMember(args.Rm_type,{'constant'})} = 'constant' + % Initial position of the two masses + args.Rm_pos (2,1) double {mustBeNumeric} = [0; pi] + % For now, only constant is implemented + args.Dn_type char {mustBeMember(args.Dn_type,{'constant'})} = 'constant' + % Initial position [m,m,m,rad,rad,rad] of the top platform + args.Dn_pos (6,1) double {mustBeNumeric} = zeros(6,1) end %% Set Sampling Time -Ts = opts.Ts; -Tmax = opts.Tmax; +Ts = args.Ts; +Tmax = args.Tmax; %% Low Pass Filter to filter out the references s = zpk('s'); @@ -43,15 +52,15 @@ t = 0:Ts:Tmax; % Time Vector [s] Dy = zeros(length(t), 1); Dyd = zeros(length(t), 1); Dydd = zeros(length(t), 1); -switch opts.Dy_type +switch args.Dy_type case 'constant' - Dy(:) = opts.Dy_amplitude; + Dy(:) = args.Dy_amplitude; Dyd(:) = 0; Dydd(:) = 0; case 'triangular' % This is done to unsure that we start with no displacement - Dy_raw = opts.Dy_amplitude*sawtooth(2*pi*t/opts.Dy_period,1/2); - i0 = find(t>=opts.Dy_period/4,1); + Dy_raw = args.Dy_amplitude*sawtooth(2*pi*t/args.Dy_period,1/2); + i0 = find(t>=args.Dy_period/4,1); Dy(1:end-i0+1) = Dy_raw(i0:end); Dy(end-i0+2:end) = Dy_raw(end); % we fix the last value @@ -60,9 +69,9 @@ switch opts.Dy_type Dyd = lsim(H_lpf*s, Dy, t); Dydd = lsim(H_lpf*s^2, Dy, t); case 'sinusoidal' - Dy(:) = opts.Dy_amplitude*sin(2*pi/opts.Dy_period*t); - Dyd = opts.Dy_amplitude*2*pi/opts.Dy_period*cos(2*pi/opts.Dy_period*t); - Dydd = -opts.Dy_amplitude*(2*pi/opts.Dy_period)^2*sin(2*pi/opts.Dy_period*t); + Dy(:) = args.Dy_amplitude*sin(2*pi/args.Dy_period*t); + Dyd = args.Dy_amplitude*2*pi/args.Dy_period*cos(2*pi/args.Dy_period*t); + Dydd = -args.Dy_amplitude*(2*pi/args.Dy_period)^2*sin(2*pi/args.Dy_period*t); otherwise warning('Dy_type is not set correctly'); end @@ -75,14 +84,14 @@ Ry = zeros(length(t), 1); Ryd = zeros(length(t), 1); Rydd = zeros(length(t), 1); -switch opts.Ry_type +switch args.Ry_type case 'constant' - Ry(:) = opts.Ry_amplitude; + Ry(:) = args.Ry_amplitude; Ryd(:) = 0; Rydd(:) = 0; case 'triangular' - Ry_raw = opts.Ry_amplitude*sawtooth(2*pi*t/opts.Ry_period,1/2); - i0 = find(t>=opts.Ry_period/4,1); + Ry_raw = args.Ry_amplitude*sawtooth(2*pi*t/args.Ry_period,1/2); + i0 = find(t>=args.Ry_period/4,1); Ry(1:end-i0+1) = Ry_raw(i0:end); Ry(end-i0+2:end) = Ry_raw(end); % we fix the last value @@ -91,10 +100,10 @@ switch opts.Ry_type Ryd = lsim(H_lpf*s, Ry, t); Rydd = lsim(H_lpf*s^2, Ry, t); case 'sinusoidal' - Ry(:) = opts.Ry_amplitude*sin(2*pi/opts.Ry_period*t); + Ry(:) = args.Ry_amplitude*sin(2*pi/args.Ry_period*t); - Ryd = opts.Ry_amplitude*2*pi/opts.Ry_period*cos(2*pi/opts.Ry_period*t); - Rydd = -opts.Ry_amplitude*(2*pi/opts.Ry_period)^2*sin(2*pi/opts.Ry_period*t); + Ryd = args.Ry_amplitude*2*pi/args.Ry_period*cos(2*pi/args.Ry_period*t); + Rydd = -args.Ry_amplitude*(2*pi/args.Ry_period)^2*sin(2*pi/args.Ry_period*t); otherwise warning('Ry_type is not set correctly'); end @@ -107,13 +116,13 @@ Rz = zeros(length(t), 1); Rzd = zeros(length(t), 1); Rzdd = zeros(length(t), 1); -switch opts.Rz_type +switch args.Rz_type case 'constant' - Rz(:) = opts.Rz_amplitude; + Rz(:) = args.Rz_amplitude; Rzd(:) = 0; Rzdd(:) = 0; case 'rotating' - Rz(:) = opts.Rz_amplitude+2*pi/opts.Rz_period*t; + Rz(:) = args.Rz_amplitude+2*pi/args.Rz_period*t; % The signal is filtered out Rz = lsim(H_lpf, Rz, t); @@ -130,17 +139,17 @@ t = [0, Ts]; Dh = zeros(length(t), 6); Dhl = zeros(length(t), 6); -switch opts.Dh_type +switch args.Dh_type case 'constant' - Dh = [opts.Dh_pos, opts.Dh_pos]; + Dh = [args.Dh_pos, args.Dh_pos]; load('mat/stages.mat', 'micro_hexapod'); - AP = [opts.Dh_pos(1) ; opts.Dh_pos(2) ; opts.Dh_pos(3)]; + AP = [args.Dh_pos(1) ; args.Dh_pos(2) ; args.Dh_pos(3)]; - tx = opts.Dh_pos(4); - ty = opts.Dh_pos(5); - tz = opts.Dh_pos(6); + tx = args.Dh_pos(4); + ty = args.Dh_pos(5); + tz = args.Dh_pos(6); ARB = [cos(tz) -sin(tz) 0; sin(tz) cos(tz) 0; @@ -164,16 +173,16 @@ Dhl = struct('time', t, 'signals', struct('values', Dhl)); %% Axis Compensation - Rm t = [0, Ts]; -Rm = [opts.Rm_pos, opts.Rm_pos]; +Rm = [args.Rm_pos, args.Rm_pos]; Rm = struct('time', t, 'signals', struct('values', Rm)); %% Nano-Hexapod t = [0, Ts]; Dn = zeros(length(t), 6); -switch opts.Dn_type +switch args.Dn_type case 'constant' - Dn = [opts.Dn_pos, opts.Dn_pos]; + Dn = [args.Dn_pos, args.Dn_pos]; otherwise warning('Dn_type is not set correctly'); end diff --git a/src/initializeRy.m b/src/initializeRy.m index 720bea6..9418a8a 100644 --- a/src/initializeRy.m +++ b/src/initializeRy.m @@ -1,12 +1,6 @@ -function [ry] = initializeRy(opts_param) - %% Default values for opts - opts = struct('rigid', false); - - %% Populate opts with input parameters - if exist('opts_param','var') - for opt = fieldnames(opts_param)' - opts.(opt{1}) = opts_param.(opt{1}); - end +function [ry] = initializeRy(args) + arguments + args.rigid logical {mustBeNumericOrLogical} = false end %% @@ -33,7 +27,7 @@ function [ry] = initializeRy(opts_param) ry.m = 800; % TODO [kg] %% Tilt Stage - Dynamical Properties - if opts.rigid + if args.rigid ry.k.tilt = 1e10; % Rotation stiffness around y [N*m/deg] ry.k.h = 1e12; % Stiffness in the direction of the guidance [N/m] ry.k.rad = 1e12; % Stiffness in the top direction [N/m] diff --git a/src/initializeRz.m b/src/initializeRz.m index 6022577..0cda3e7 100644 --- a/src/initializeRz.m +++ b/src/initializeRz.m @@ -1,12 +1,6 @@ -function [rz] = initializeRz(opts_param) - %% Default values for opts - opts = struct('rigid', false); - - %% Populate opts with input parameters - if exist('opts_param','var') - for opt = fieldnames(opts_param)' - opts.(opt{1}) = opts_param.(opt{1}); - end +function [rz] = initializeRz(args) + arguments + args.rigid logical {mustBeNumericOrLogical} = false end %% @@ -31,7 +25,7 @@ function [rz] = initializeRz(opts_param) %% Spindle - Dynamical Properties - if opts.rigid + if args.rigid rz.k.rot = 1e10; % Rotational Stiffness (Rz) [N*m/deg] rz.k.tilt = 1e10; % Rotational Stiffness (Rx, Ry) [N*m/deg] rz.k.ax = 1e12; % Axial Stiffness (Z) [N/m] diff --git a/src/initializeSample.m b/src/initializeSample.m index ddd42d8..5755623 100644 --- a/src/initializeSample.m +++ b/src/initializeSample.m @@ -1,17 +1,10 @@ -function [sample] = initializeSample(opts_param) - %% Default values for opts - sample = struct('radius', 100, ... - 'height', 300, ... - 'mass', 50, ... - 'offset', 0, ... - 'color', [0.45, 0.45, 0.45] ... - ); - - %% Populate opts with input parameters - if exist('opts_param','var') - for opt = fieldnames(opts_param)' - sample.(opt{1}) = opts_param.(opt{1}); - end +function [sample] = initializeSample(sample) + arguments + sample.radius (1,1) double {mustBeNumeric, mustBePositive} = 100 + sample.height (1,1) double {mustBeNumeric, mustBePositive} = 300 + sample.mass (1,1) double {mustBeNumeric, mustBePositive} = 50 + sample.offset (1,1) double {mustBeNumeric} = 0 + sample.color (1,3) double {mustBeNumeric} = [0.45, 0.45, 0.45] end %% diff --git a/src/initializeTy.m b/src/initializeTy.m index 6ecc7b0..228f432 100644 --- a/src/initializeTy.m +++ b/src/initializeTy.m @@ -1,12 +1,6 @@ -function [ty] = initializeTy(opts_param) - %% Default values for opts - opts = struct('rigid', false); - - %% Populate opts with input parameters - if exist('opts_param','var') - for opt = fieldnames(opts_param)' - opts.(opt{1}) = opts_param.(opt{1}); - end +function [ty] = initializeTy(args) + arguments + args.rigid logical {mustBeNumericOrLogical} = false end %% @@ -53,7 +47,7 @@ function [ty] = initializeTy(opts_param) ty.m = 1000; % TODO [kg] %% Y-Translation - Dynamicals Properties - if opts.rigid + if args.rigid ty.k.ax = 1e12; % Axial Stiffness for each of the 4 guidance (y) [N/m] ty.k.rad = 1e12; % Radial Stiffness for each of the 4 guidance (x-z) [N/m] else diff --git a/uniaxial/index.org b/uniaxial/index.org index b8e0551..6c4a241 100644 --- a/uniaxial/index.org +++ b/uniaxial/index.org @@ -659,8 +659,8 @@ The nano-hexapod is a piezoelectric hexapod and the sample has a mass of 50kg. initializeMicroHexapod(); initializeAxisc(); initializeMirror(); - initializeNanoHexapod(struct('actuator', 'piezo')); - initializeSample(struct('mass', 50)); + initializeNanoHexapod('actuator', 'piezo'); + initializeSample('mass', 50); #+end_src All the controllers are set to 0 (Open Loop). @@ -1159,8 +1159,8 @@ Let's initialize the system prior to identification. initializeMicroHexapod(); initializeAxisc(); initializeMirror(); - initializeNanoHexapod(struct('actuator', 'piezo')); - initializeSample(struct('mass', 50)); + initializeNanoHexapod('actuator', 'piezo'); + initializeSample('mass', 50); #+end_src All the controllers are set to 0. @@ -1586,8 +1586,8 @@ Let's initialize the system prior to identification. initializeMicroHexapod(); initializeAxisc(); initializeMirror(); - initializeNanoHexapod(struct('actuator', 'piezo')); - initializeSample(struct('mass', 50)); + initializeNanoHexapod('actuator', 'piezo'); + initializeSample('mass', 50); #+end_src And initialize the controllers. @@ -2017,8 +2017,8 @@ Let's initialize the system prior to identification. initializeMicroHexapod(); initializeAxisc(); initializeMirror(); - initializeNanoHexapod(struct('actuator', 'piezo')); - initializeSample(struct('mass', 50)); + initializeNanoHexapod('actuator', 'piezo'); + initializeSample('mass', 50); #+end_src And initialize the controllers. @@ -2250,9 +2250,9 @@ Let's initialize the system prior to identification. initializeMicroHexapod(); initializeAxisc(); initializeMirror(); - initializeNanoHexapod(struct('actuator', 'piezo')); + initializeNanoHexapod('actuator', 'piezo'); initializeCedratPiezo(); - initializeSample(struct('mass', 50)); + initializeSample('mass', 50); #+end_src And initialize the controllers. @@ -2386,9 +2386,9 @@ Let's initialize the system prior to identification. initializeMicroHexapod(); initializeAxisc(); initializeMirror(); - initializeNanoHexapod(struct('actuator', 'piezo')); + initializeNanoHexapod('actuator', 'piezo'); initializeCedratPiezo(); - initializeSample(struct('mass', 50)); + initializeSample('mass', 50); #+end_src All the controllers are set to 0. @@ -2847,8 +2847,8 @@ The nano-hexapod is an hexapod with voice coils and the sample has a mass of 50k initializeMicroHexapod(); initializeAxisc(); initializeMirror(); - initializeNanoHexapod(struct('actuator', 'lorentz')); - initializeSample(struct('mass', 50)); + initializeNanoHexapod('actuator', 'lorentz'); + initializeSample('mass', 50); #+end_src All the controllers are set to 0 (Open Loop). @@ -3118,8 +3118,8 @@ Let's initialize the system prior to identification. initializeMicroHexapod(); initializeAxisc(); initializeMirror(); - initializeNanoHexapod(struct('actuator', 'lorentz')); - initializeSample(struct('mass', 50)); + initializeNanoHexapod('actuator', 'lorentz'); + initializeSample('mass', 50); #+end_src All the controllers are set to 0.