Tangle matlab files without comments

This commit is contained in:
2025-03-28 16:40:53 +01:00
parent a5ab404d2b
commit 122273e102
13 changed files with 779 additions and 1367 deletions

View File

@@ -16,53 +16,19 @@ mdl = 'nass_uniaxial_model';
%% Frequency Vector [Hz]
freqs = logspace(0, 3, 1000);
% #+name: fig:micro_station_uniaxial_model
% #+caption: Schematic of the Micro-Station measurement setup and uniaxial model.
% #+begin_figure
% #+attr_latex: :caption \subcaption{\label{fig:uniaxial_ustation_meas_dynamics_schematic}Measurement setup - Schematic}
% #+attr_latex: :options {0.69\textwidth}
% #+begin_subfigure
% #+attr_latex: :scale 1
% [[file:figs/uniaxial_ustation_meas_dynamics_schematic.png]]
% #+end_subfigure
% #+attr_latex: :caption \subcaption{\label{fig:uniaxial_model_micro_station}Uniaxial model of the micro-station}
% #+attr_latex: :options {0.29\textwidth}
% #+begin_subfigure
% #+attr_latex: :scale 1
% [[file:figs/uniaxial_model_micro_station.png]]
% #+end_subfigure
% #+end_figure
% Due to the bad coherence at low frequency, the frequency response functions will only be shown between 20 and 200Hz (solid lines in Figure ref:fig:uniaxial_comp_frf_meas_model).
%% Load measured FRF
load('meas_microstation_frf.mat');
% Masses are estimated from the CAD.
%% Parameters - Mass
mh = 15; % Micro Hexapod [kg]
mt = 1200; % Ty + Ry + Rz [kg]
mg = 2500; % Granite [kg]
% And stiffnesses from the data-sheet of stage manufacturers.
%% Parameters - Stiffnesses
kh = 6.11e+07; % [N/m]
kt = 5.19e+08; % [N/m]
kg = 9.50e+08; % [N/m]
% The damping coefficients are tuned to match the identified damping from the measurements.
%% Parameters - damping
ch = 2*0.05*sqrt(kh*mh); % [N/(m/s)]
ct = 2*0.05*sqrt(kt*mt); % [N/(m/s)]
@@ -88,27 +54,18 @@ G_id = linearize(mdl, io, 0.0);
G_id.InputName = {'Fg', 'Fh'};
G_id.OutputName = {'Dg', 'Dh'};
% Comparison of the model and measurements
% The comparison between the measurements and the model is shown in Figure ref:fig:uniaxial_comp_frf_meas_model.
% Only three modes are modelled with frequencies at 70Hz, 140Hz and 320Hz.
% As the model is simplistic, the goal is not to match exactly the measurement but to have a first approximation.
% More accurate models will be used later on.
%% Comparison of the measured FRF and identified ones from the uni-axial model
%% Comparison of the measured FRF and identified ones from the uniaxial model
figure;
tiledlayout(3, 1, 'TileSpacing', 'Compact', 'Padding', 'None');
ax1 = nexttile([2,1]);
hold on;
plot(f(f>20), abs(frf_Fhz_to_Dhz(f>20)), '-', 'color', colors(1,:), 'DisplayName', '$D_{h,z}/F_{h,z}$');
plot(f(f>20), abs(frf_Fgz_to_Dhz(f>20)), '-', 'color', colors(2,:), 'DisplayName', '$D_{h,z}/F_{g,z}$');
plot(f(f>20), abs(frf_Fgz_to_Dgz(f>20)), '-', 'color', colors(3,:), 'DisplayName', '$D_{g,z}/F_{g,z}$');
plot(freqs, abs(squeeze(freqresp(G_id('Dh', 'Fh'), freqs, 'Hz'))), '--', 'color', colors(1,:), 'DisplayName', '$D_{h,z}/F_{h,z}$ (model)');
plot(freqs, abs(squeeze(freqresp(G_id('Dh', 'Fg'), freqs, 'Hz'))), '--', 'color', colors(2,:), 'DisplayName', '$D_{h,z}/F_{g,z}$ (model)');
plot(freqs, abs(squeeze(freqresp(G_id('Dg', 'Fg'), freqs, 'Hz'))), '--', 'color', colors(3,:), 'DisplayName', '$D_{g,z}/F_{g,z}$ (model)');
plot(f(f>20), abs(frf_Fhz_to_Dhz(f>20)), '-', 'color', colors(1,:), 'DisplayName', '$x_{h,z}/F_{h,z}$');
plot(f(f>20), abs(frf_Fgz_to_Dhz(f>20)), '-', 'color', colors(2,:), 'DisplayName', '$x_{h,z}/F_{g,z}$');
plot(f(f>20), abs(frf_Fgz_to_Dgz(f>20)), '-', 'color', colors(3,:), 'DisplayName', '$x_{g,z}/F_{g,z}$');
plot(freqs, abs(squeeze(freqresp(G_id('Dh', 'Fh'), freqs, 'Hz'))), '--', 'color', colors(1,:), 'DisplayName', '$x_{h,z}/F_{h,z}$ (model)');
plot(freqs, abs(squeeze(freqresp(G_id('Dh', 'Fg'), freqs, 'Hz'))), '--', 'color', colors(2,:), 'DisplayName', '$x_{h,z}/F_{g,z}$ (model)');
plot(freqs, abs(squeeze(freqresp(G_id('Dg', 'Fg'), freqs, 'Hz'))), '--', 'color', colors(3,:), 'DisplayName', '$x_{g,z}/F_{g,z}$ (model)');
hold off;
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
ylabel('Amplitude [m/N]'); set(gca, 'XTickLabel',[]);

View File

@@ -19,15 +19,6 @@ freqs = logspace(0, 3, 1000);
%% Load the micro-station parameters
load('uniaxial_micro_station_parameters.mat')
% Nano-Hexapod Parameters
% The parameters for the nano-hexapod and sample are:
% - $m_s$ the sample mass that can vary from 1kg up to 50kg
% - $m_n$ the nano-hexapod mass which is set to 15kg
% - $k_n$ the nano-hexapod stiffness, which can vary depending on the chosen architecture/technology
% As a first example, let's choose a nano-hexapod stiffness of $10\,N/\mu m$ and a sample mass of 10kg.
%% Nano-Hexapod Parameters
mn = 15; % [kg]
kn = 1e7; % [N/m]
@@ -36,15 +27,6 @@ cn = 2*0.01*sqrt(mn*kn); % [N/(m/s)]
%% Sample Mass
ms = 10; % [kg]
% Obtained Dynamic Response
% The sensitivity to disturbances (i.e. $x_f$, $f_t$ and $f_s$) are shown in Figure ref:fig:uniaxial_sensitivity_dist_first_params.
% The /plant/ (i.e. the transfer function from actuator force $f$ to measured displacement $d$) is shown in Figure ref:fig:uniaxial_plant_first_params.
% #+begin_important
% For further analysis, 9 configurations are considered: three nano-hexapod stiffnesses ($k_n = 0.01\,N/\mu m$, $k_n = 1\,N/\mu m$ and $k_n = 100\,N/\mu m$) combined with three sample's masses ($m_s = 1\,kg$, $m_s = 25\,kg$ and $m_s = 50\,kg$).
% #+end_important
%% Use 1DoF Nano-Hexpod model
model_config = struct();
model_config.nhexa = "1dof";
@@ -63,44 +45,30 @@ G_ol = linearize(mdl, io, 0.0);
G_ol.InputName = {'f', 'fs', 'xf', 'ft'};
G_ol.OutputName = {'d'};
%% Sensitivity to disturbances
%% Sensitivity to disturbances - Fs
figure;
tiledlayout(1, 3, 'TileSpacing', 'Compact', 'Padding', 'None');
ax1 = nexttile();
hold on;
plot(freqs, abs(squeeze(freqresp(G_ol('d', 'fs'), freqs, 'Hz'))));
hold off;
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
ylabel('Amplitude $d/f_{s}$ [m/N]'); xlabel('Frequency [Hz]');
xticks([1e0, 1e1, 1e2]);
xlim([1, 500]);
ax2 = nexttile();
hold on;
%% Sensitivity to disturbances - Ft
figure;
plot(freqs, abs(squeeze(freqresp(G_ol('d', 'ft'), freqs, 'Hz'))));
hold off;
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
ylabel('Amplitude $d/f_{t}$ [m/N]'); xlabel('Frequency [Hz]');
xticks([1e0, 1e1, 1e2]);
xlim([1, 500]);
ax3 = nexttile();
hold on;
%% Sensitivity to disturbances - xf
figure;
plot(freqs, abs(squeeze(freqresp(G_ol('d', 'xf'), freqs, 'Hz'))));
hold off;
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
ylabel('Amplitude $d/x_{f}$ [m/m]'); xlabel('Frequency [Hz]');
xticks([1e0, 1e1, 1e2]);
linkaxes([ax1,ax2,ax3],'x');
xlim([1, 500]);
% #+name: fig:uniaxial_sensitivity_dist_first_params
% #+caption: Sensitivity of the relative motion $d$ to disturbances: $f_s$ the direct forces applied on the sample, $f_t$ disturbances from the micro-station stages and $x_f$ the floor motion (from left to right)
% #+RESULTS:
% [[file:figs/uniaxial_sensitivity_dist_first_params.png]]
ylim([1e-2, 1e2]);
%% Bode Plot of the transfer function from actuator forces to measured displacement by the metrology
figure;
@@ -126,8 +94,6 @@ ylim([-180, 0]);
linkaxes([ax1,ax2],'x');
xlim([1, 500]);
% Identification of all combination of stiffnesses / masses :noexport:
%% Use 1DoF Nano-Hexpod model
model_config = struct();
model_config.nhexa = "1dof";

View File

@@ -19,100 +19,76 @@ freqs = logspace(0, 3, 1000);
%% Load the micro-station parameters
load('uniaxial_micro_station_parameters.mat');
% Ground Motion
% The geophone fixed to the floor to measure the floor motion.
%% Load floor motion data
%% Compute Floor Motion Spectral Density
% Load floor motion data
% t: time in [s]
% V: measured voltage genrated by the geophone and amplified by a 60dB gain voltage amplifier [V]
load('ground_motion_measurement.mat', 't', 'V');
% Geophone Transfer Function
Tg = 88; % Sensitivity [V/(m/s)]
w0 = 2*2*pi; % Cut-off frequency [rad/s]
xi = 0.7; % Damping ratio
G_geo = Tg*s*s^2/(s^2 + 2*xi*w0*s + w0^2); % Geophone's transfer function [V/m]
% The voltage generated by each geophone is amplified using a voltage amplifier (gain of 60dB) before going to the ADC.
% The sensitivity of the geophone as well as the gain of the voltage amplifier are then taken into account to reconstruct the floor displacement.
% Voltage amplifier transfer function
g0 = 10^(60/20); % [abs]
%% Sensitivity of the geophone
S0 = 88; % Sensitivity [V/(m/s)]
f0 = 2; % Cut-off frequency [Hz]
% Compute measured voltage PSD
Ts = (t(2)-t(1)); % Sampling Time [s]
Nfft = floor(2/Ts);
win = hanning(Nfft);
Noverlap = floor(Nfft/2);
S = S0*(s/2/pi/f0)/(1+s/2/pi/f0); % Geophone's transfer function [V/(m/s)]
%% Gain of the voltage amplifier
G0_db = 60; % [dB]
G0 = 10^(G0_db/20); % [abs]
%% Transfer function from measured voltage to displacement
G_geo = 1/S/G0/s; % [m/V]
% The PSD $S_{V_f}$ of the measured voltage $V_f$ is computed.
%% Compute measured voltage PSD
Fs = 1/(t(2)-t(1)); % Sampling Frequency [Hz]
win = hanning(ceil(2*Fs)); % Hanning window
[psd_V, f] = pwelch(V, win, [], [], Fs); % [V^2/Hz]
% The PSD of the corresponding displacement can be computed as follows:
% \begin{equation}
% S_{x_f}(\omega) = \frac{S_{V_f}(\omega)}{|S_{\text{geo}}(j\omega)| \cdot G_{\text{amp}} \cdot \omega}
% \end{equation}
% with:
% - $S_{\text{geo}}$ the sensitivity of the Geophone in $[Vs/m]$
% - $G_{\text{amp}}$ the gain of the voltage amplifier
% - $\omega$ is here to integrate and have the displacement instead of the velocity
%% Ground Motion ASD
psd_xf = psd_V.*abs(squeeze(freqresp(G_geo, f, 'Hz'))).^2; % [m^2/Hz]
% The amplitude spectral density $\Gamma_{x_f}$ of the measured displacement $x_f$ is shown in Figure ref:fig:uniaxial_asd_floor_motion_id31.
[psd_V, f] = pwelch(V, win, Noverlap, Nfft, 1/Ts); % [V^2/Hz]
% Ground Motion ASD
psd_xf = psd_V./abs(squeeze(freqresp(G_geo*g0, f, 'Hz'))).^2; % [m^2/Hz]
%% Amplitude Spectral Density of the measured Floor motion on ID31
figure;
hold on;
plot(f, sqrt(psd_xf), 'DisplayName', '$\Gamma_{x_{f}}$');
hold off;
set(gca, 'xscale', 'log'); set(gca, 'yscale', 'log');
xlabel('Frequency [Hz]'); ylabel('Ampl. Spectral Density $\left[\frac{m}{\sqrt{Hz}}\right]$')
xlim([1, 500]);
legend('location', 'northeast', 'FontSize', 8, 'NumColumns', 1);
xlim([1, 500]);
xticks([1e0, 1e1, 1e2]);
% Stage Vibration
% During Spindle rotation (here at 6rpm), the granite velocity and micro-hexapod's top platform velocity are measured with the geophones.
%% Estimation of the Spectral density of the stage vibrations
%% Measured velocity of granite and hexapod during spindle rotation
% Measured velocity of granite and hexapod during spindle rotation
% t: time in [s]
% vg: measured granite velocity [m/s]
% vg: measured micro-hexapod's top platform velocity [m/s]
load('meas_spindle_on.mat', 't', 'vg', 'vh');
spindle_off = load('meas_spindle_off.mat', 't', 'vg', 'vh'); % No Rotation
% The Power Spectral Density of the relative velocity between the hexapod and the granite is computed.
%% Compute Power Spectral Density of the relative velocity between granite and hexapod during spindle rotation
% Compute Power Spectral Density of the relative velocity between granite and hexapod during spindle rotation
Fs = 1/(t(2)-t(1)); % Sampling Frequency [Hz]
win = hanning(ceil(2*Fs)); % Hanning window
[psd_vft, f] = pwelch(vh-vg, win, [], [], Fs); % [(m/s)^2/Hz]
[psd_off, ~] = pwelch(spindle_off.vh-spindle_off.vg, win, [], [], Fs); % [(m/s)^2/Hz]
% Disable the Nano-Hexpod for now
model_config = struct();
model_config.nhexa = "none";
model_config.controller = "open_loop";
% Identify the transfer function from u to taum
clear io; io_i = 1;
io(io_i) = linio([mdl, '/micro_station/ft'], 1, 'openinput'); io_i = io_i + 1; % Stage Disturbance Force
io(io_i) = linio([mdl, '/micro_station/xg'], 1, 'openoutput'); io_i = io_i + 1; % Absolute motion of Granite
io(io_i) = linio([mdl, '/micro_station/xh'], 1, 'openoutput'); io_i = io_i + 1; % Absolute motion of Hexapod
% It is then integrated to obtain the Amplitude Spectral Density of the relative motion which is compared with a non-rotating case (Figure ref:fig:uniaxial_asd_vibration_spindle_rotation).
% It is shown that the spindle rotation induces vibrations in a wide frequency spectrum.
% Perform the model extraction
G = linearize(mdl, io, 0.0);
G.InputName = {'ft'};
G.OutputName = {'Dg', 'Dh'};
% Power Spectral Density of the equivalent force ft [N/Hz^2]
psd_ft = (psd_vft./(2*pi*f).^2)./abs(squeeze(freqresp(G('Dh', 'ft') - G('Dg', 'ft'), f, 'Hz'))).^2;
%% Amplitude Spectral Density of the relative motion measured between the granite and the micro-hexapod's top platform during Spindle rotating
figure;
@@ -125,49 +101,6 @@ xlabel('Frequency [Hz]'); ylabel('Ampl. Spectral Density $\left[\frac{m}{\sqrt{H
legend('location', 'northeast', 'FontSize', 8, 'NumColumns', 1);
xlim([1, 500]); ylim([1e-12, 1e-7])
% #+name: fig:uniaxial_asd_vibration_spindle_rotation
% #+caption: Amplitude Spectral Density of the relative motion measured between the granite and the micro-hexapod's top platform during Spindle rotating
% #+RESULTS:
% [[file:figs/uniaxial_asd_vibration_spindle_rotation.png]]
% In order to compute the equivalent disturbance force $f_t$ that induces such motion, the transfer function from $f_t$ to the relative motion of the hexapod's top platform and the granite is extracted from the model.
%% Disable the Nano-Hexpod for now
model_config = struct();
model_config.nhexa = "none";
model_config.controller = "open_loop";
%% Identify the transfer function from u to taum
clear io; io_i = 1;
io(io_i) = linio([mdl, '/micro_station/ft'], 1, 'openinput'); io_i = io_i + 1; % Stage Disturbance Force
io(io_i) = linio([mdl, '/micro_station/xg'], 1, 'openoutput'); io_i = io_i + 1; % Absolute motion of Granite
io(io_i) = linio([mdl, '/micro_station/xh'], 1, 'openoutput'); io_i = io_i + 1; % Absolute motion of Hexapod
%% Perform the model extraction
G = linearize(mdl, io, 0.0);
G.InputName = {'ft'};
G.OutputName = {'Dg', 'Dh'};
% The power spectral density $\Gamma_{f_{t}}$ of the disturbance force can be computed as follows:
% \begin{equation}
% \Gamma_{f_{t}}(\omega) = \frac{\Gamma_{v_{t}}(\omega)}{|G_{\text{model}}(j\omega)|^2}
% \end{equation}
% with:
% - $\Gamma_{v_{t}}$ the measured power spectral density of the relative motion between the micro-hexapod's top platform and the granite during the spindle's rotation
% - $G_{\text{model}}$ the transfer function (extracted from the uniaxial model) from $f_t$ to the relative motion between the micro-hexapod's top platform and the granite
%% Power Spectral Density of the equivalent force ft
psd_ft = (psd_vft./(2*pi*f).^2)./abs(squeeze(freqresp(G('Dh', 'ft') - G('Dg', 'ft'), f, 'Hz'))).^2;
% The obtained amplitude spectral density of the disturbance force $f_t$ is shown in Figure ref:fig:uniaxial_asd_disturbance_force.
%% Estimated disturbance force ft from measurement and uniaxial model
figure;
hold on;

View File

@@ -21,29 +21,8 @@ load('uniaxial_plants.mat', 'G_vc_light', 'G_md_light', 'G_pz_light', ...
'G_vc_mid', 'G_md_mid', 'G_pz_mid', ...
'G_vc_heavy', 'G_md_heavy', 'G_pz_heavy');
% Sensitivity to disturbances
% From the Uni-axial model, the transfer function from the disturbances ($f_s$, $x_f$ and $f_t$) to the displacement $d$ are computed.
% This is done for *two extreme sample masses* $m_s = 1\,\text{kg}$ and $m_s = 50\,\text{kg}$ and *three nano-hexapod stiffnesses*:
% - $k_n = 0.01\,N/\mu m$ that could represent a voice coil actuator with soft flexible guiding
% - $k_n = 1\,N/\mu m$ that could represent a voice coil actuator with a stiff flexible guiding or a mechanically amplified piezoelectric actuator
% - $k_n = 100\,N/\mu m$ that could represent a stiff piezoelectric stack actuator
% The obtained sensitivity to disturbances for the three nano-hexapod stiffnesses are shown in Figure ref:fig:uniaxial_sensitivity_disturbances_nano_hexapod_stiffnesses for the light sample (same conclusions can be drawn with the heavy one).
% #+begin_important
% From Figure ref:fig:uniaxial_sensitivity_disturbances_nano_hexapod_stiffnesses, the following can be concluded for the *soft nano-hexapod*:
% - It is more sensitive to forces applied on the sample (cable forces for instance), which is expected due to the lower stiffness
% - Between the suspension mode of the nano-hexapod (here at 5Hz) and the first mode of the micro-station (here at 70Hz), the disturbances induced by the stage vibrations are filtered out.
% - Above the suspension mode of the nano-hexapod, the sample's motion is unaffected by the floor motion, and therefore the sensitivity to floor motion is close to $1$.
% #+end_important
%% Sensitivity to disturbances for three different nano-hexpod stiffnesses
figure;
tiledlayout(1, 3, 'TileSpacing', 'Compact', 'Padding', 'None');
ax1 = nexttile();
hold on;
plot(freqs, abs(squeeze(freqresp(G_vc_light('d', 'fs'), freqs, 'Hz'))));
plot(freqs, abs(squeeze(freqresp(G_md_light('d', 'fs'), freqs, 'Hz'))));
@@ -52,8 +31,10 @@ hold off;
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
ylabel('Amplitude $d/f_{s}$ [m/N]'); xlabel('Frequency [Hz]');
xticks([1e0, 1e1, 1e2]);
xlim([1, 500]);
ax2 = nexttile();
%% Sensitivity to disturbances for three different nano-hexpod stiffnesses
figure;
hold on;
plot(freqs, abs(squeeze(freqresp(G_vc_light('d', 'ft'), freqs, 'Hz'))));
plot(freqs, abs(squeeze(freqresp(G_md_light('d', 'ft'), freqs, 'Hz'))));
@@ -62,8 +43,10 @@ hold off;
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
ylabel('Amplitude $d/f_{t}$ [m/N]'); xlabel('Frequency [Hz]');
xticks([1e0, 1e1, 1e2]);
xlim([1, 500]);
ax3 = nexttile();
%% Sensitivity to disturbances for three different nano-hexpod stiffnesses
figure;
hold on;
plot(freqs, abs(squeeze(freqresp(G_vc_light('d', 'xf'), freqs, 'Hz'))), 'DisplayName', '$k_n = 0.01\,N/\mu m$');
plot(freqs, abs(squeeze(freqresp(G_md_light('d', 'xf'), freqs, 'Hz'))), 'DisplayName', '$k_n = 1 \,N/\mu m$');
@@ -72,24 +55,12 @@ hold off;
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
ylabel('Amplitude $d/x_{f}$ [m/m]'); xlabel('Frequency [Hz]');
xticks([1e0, 1e1, 1e2]);
legend('location', 'southeast', 'FontSize', 8, 'NumColumns', 1);
linkaxes([ax1,ax2,ax3],'x');
leg = legend('location', 'southeast', 'FontSize', 8, 'NumColumns', 1);
leg.ItemTokenSize(1) = 15
xlim([1, 500]);
% Open-Loop Dynamic Noise Budgeting
% Now, the power spectral density of the disturbances is taken into account to estimate the residual motion $d$ in each case.
% The Cumulative Amplitude Spectrum of the relative motion $d$ due to both the floor motion $x_f$ and the stage vibrations $f_t$ are shown in Figure ref:fig:uniaxial_cas_d_disturbances_stiffnesses for the three nano-hexapod stiffnesses.
% It is shown that the effect of the floor motion is much less than the stage vibrations, except for the soft nano-hexapod below 5Hz.
%% Cumulative Amplitude Spectrum of the relative motion d, due to both the floor motion and the stage vibrations
figure;
tiledlayout(1, 1, 'TileSpacing', 'Compact', 'Padding', 'None');
ax1 = nexttile();
hold on;
plot(f, sqrt(flip(-cumtrapz(flip(f), flip(psd_ft.*abs(squeeze(freqresp(G_vc_light('d', 'ft'), f, 'Hz'))).^2)))), '-', 'color', colors(1,:), 'DisplayName', '$f_t$');
plot(f, sqrt(flip(-cumtrapz(flip(f), flip(psd_ft.*abs(squeeze(freqresp(G_md_light('d', 'ft'), f, 'Hz'))).^2)))), '-', 'color', colors(2,:), 'DisplayName', '$f_t$');
@@ -99,51 +70,41 @@ plot(f, sqrt(flip(-cumtrapz(flip(f), flip(psd_xf.*abs(squeeze(freqresp(G_md_ligh
plot(f, sqrt(flip(-cumtrapz(flip(f), flip(psd_xf.*abs(squeeze(freqresp(G_pz_light('d', 'xf'), f, 'Hz'))).^2)))), '--', 'color', colors(3,:), 'DisplayName', '$x_f$ ($k_n = 100 \,N/\mu m$)');
hold off;
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
ylabel('Cumulative Ampl. Spectrum [m]'); xlabel('Frequency [Hz]');
legend('location', 'southwest', 'FontSize', 8, 'NumColumns', 2);
ylabel('CAS [m]'); xlabel('Frequency [Hz]');
leg = legend('location', 'southwest', 'FontSize', 8, 'NumColumns', 2);
leg.ItemTokenSize(1) = 15
xlim([1, 500]);
ylim([1e-12, 1e-6])
% #+name: fig:uniaxial_cas_d_disturbances_stiffnesses
% #+caption: Cumulative Amplitude Spectrum of the relative motion d, due to both the floor motion and the stage vibrations (light sample)
% #+RESULTS:
% [[file:figs/uniaxial_cas_d_disturbances_stiffnesses.png]]
% The total cumulative amplitude spectrum for the three nano-hexapod stiffnesses and for the two sample's masses are shown in Figure ref:fig:uniaxial_cas_d_disturbances_payload_masses.
% The conclusion is that the sample's mass has little effect on the cumulative amplitude spectrum of the relative motion $d$.
ylim([1e-12, 3e-6])
%% Cumulative Amplitude Spectrum of the relative motion d due to all disturbances, for two sample masses
figure;
tiledlayout(1, 1, 'TileSpacing', 'Compact', 'Padding', 'None');
ax1 = nexttile();
hold on;
plot(f, sqrt(flip(-cumtrapz(flip(f), flip(psd_ft.*abs(squeeze(freqresp(G_vc_light('d', 'ft'), f, 'Hz'))).^2 + ...
psd_xf.*abs(squeeze(freqresp(G_vc_light('d', 'xf'), f, 'Hz'))).^2)))), '-', ...
'color', colors(1,:), 'DisplayName', '$m_s = 1\,kg$');
'color', colors(1,:), 'DisplayName', '$m_s = 1\,kg$, $k_n = 0.01\,N/\mu m$');
plot(f, sqrt(flip(-cumtrapz(flip(f), flip(psd_ft.*abs(squeeze(freqresp(G_md_light('d', 'ft'), f, 'Hz'))).^2 + ...
psd_xf.*abs(squeeze(freqresp(G_md_light('d', 'xf'), f, 'Hz'))).^2)))), '-', ...
'color', colors(2,:), 'DisplayName', '$m_s = 1\,kg$');
'color', colors(2,:), 'DisplayName', '$m_s = 1\,kg$, $k_n = 1\,N/\mu m$');
plot(f, sqrt(flip(-cumtrapz(flip(f), flip(psd_ft.*abs(squeeze(freqresp(G_pz_light('d', 'ft'), f, 'Hz'))).^2 + ...
psd_xf.*abs(squeeze(freqresp(G_pz_light('d', 'xf'), f, 'Hz'))).^2)))), '-', ...
'color', colors(3,:), 'DisplayName', '$m_s = 1\,kg$');
'color', colors(3,:), 'DisplayName', '$m_s = 1\,kg$, $k_n = 100\,N/\mu m$');
plot(f, sqrt(flip(-cumtrapz(flip(f), flip(psd_ft.*abs(squeeze(freqresp(G_vc_heavy('d', 'ft'), f, 'Hz'))).^2 + ...
psd_xf.*abs(squeeze(freqresp(G_vc_heavy('d', 'xf'), f, 'Hz'))).^2)))), '--', ...
'color', colors(1,:), 'DisplayName', '$m_s = 50\,kg$ ($k_n = 0.01\,N/\mu m$)');
'color', colors(1,:), 'DisplayName', '$m_s = 50\,kg$, $k_n = 0.01\,N/\mu m$');
plot(f, sqrt(flip(-cumtrapz(flip(f), flip(psd_ft.*abs(squeeze(freqresp(G_md_heavy('d', 'ft'), f, 'Hz'))).^2 + ...
psd_xf.*abs(squeeze(freqresp(G_md_heavy('d', 'xf'), f, 'Hz'))).^2)))), '--', ...
'color', colors(2,:), 'DisplayName', '$m_s = 50\,kg$ ($k_n = 1\,N/\mu m$)');
'color', colors(2,:), 'DisplayName', '$m_s = 50\,kg$, $k_n = 1\,N/\mu m$');
plot(f, sqrt(flip(-cumtrapz(flip(f), flip(psd_ft.*abs(squeeze(freqresp(G_pz_heavy('d', 'ft'), f, 'Hz'))).^2 + ...
psd_xf.*abs(squeeze(freqresp(G_pz_heavy('d', 'xf'), f, 'Hz'))).^2)))), '--', ...
'color', colors(3,:), 'DisplayName', '$m_s = 50\,kg$ ($k_n = 100\,N/\mu m$)');
'color', colors(3,:), 'DisplayName', '$m_s = 50\,kg$, $k_n = 100\,N/\mu m$');
plot([1, 1e3], [20e-9, 20e-9], 'k--', 'HandleVisibility', 'off');
text(4, 1e-8, '20 nm RMS', 'horizontalalignment', 'center');
hold off;
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
ylabel('Cumulative Ampl. Spectrum [m]'); xlabel('Frequency [Hz]');
legend('location', 'southwest', 'FontSize', 8, 'NumColumns', 2);
ylabel('CAS [m]'); xlabel('Frequency [Hz]');
leg = legend('location', 'southwest', 'FontSize', 8, 'NumColumns', 1);
leg.ItemTokenSize(1) = 15
xlim([1, 500]);
ylim([1e-11, 3e-6])
ylim([1e-12, 3e-6])

File diff suppressed because it is too large Load Diff

View File

@@ -32,23 +32,9 @@ load('uniaxial_damped_plants.mat', 'G_iff_vc_light', 'G_iff_md_light', 'G_iff_pz
'G_rdc_vc_heavy', 'G_rdc_md_heavy', 'G_rdc_pz_heavy', ...
'G_dvf_vc_heavy', 'G_dvf_md_heavy', 'G_dvf_pz_heavy');
% Damped Plant Dynamics
% <<ssec:uniaxial_position_control_damped_dynamics>>
% As was shown in Section ref:sec:uniaxial_active_damping, all three proposed active damping techniques yield similar damping plants.
% Therefore, /Integral Force Feedback/ will be used in this section to study the HAC-LAC performance.
% The obtained damped plants for the three nano-hexapod stiffnesses are shown in Figure ref:fig:uniaxial_hac_iff_damped_plants_masses.
% For $k_n = 0.01\,N/\mu m$ and $k_n = 1\,N/\mu m$, except from the nano-hexapod mode, the dynamics is quite simple and can be well approximated by a second order plant.
% However, this is not the case for the stiff nano-hexapod ($k_n = 100\,N/\mu m$) where two modes can be seen (Figure ref:fig:uniaxial_hac_iff_damped_plants_masses, right).
% This is due to the interaction between the micro-station (modelled modes at 70Hz, 140Hz and 320Hz) and the nano-hexapod.
% Such effect will be explained in Section ref:sec:uniaxial_support_compliance.
%% Damped plant - Robustness to change of sample's mass
figure;
tiledlayout(3, 3, 'TileSpacing', 'Compact', 'Padding', 'None');
tiledlayout(3, 1, 'TileSpacing', 'Compact', 'Padding', 'None');
ax1 = nexttile([2,1]);
hold on;
@@ -62,41 +48,8 @@ text(20, 4e-8, sprintf('Small\nInteraction'), 'horizontalalignment', 'center');
hold off;
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
ylabel('Amplitude [m/N]'); set(gca, 'XTickLabel',[]);
title('$k_n = 0.01\,N/\mu m$');
ylim([5e-10, 1e-3]);
ax2 = nexttile([2,1]);
hold on;
plot(freqs, abs(squeeze(freqresp(G_md_light('d', 'f'), freqs, 'Hz'))), 'color', [colors(1,:), 0.5]);
plot(freqs, abs(squeeze(freqresp(G_iff_md_light('d', 'f'), freqs, 'Hz'))), 'color', colors(1,:));
plot(freqs, abs(squeeze(freqresp(G_iff_md_mid( 'd', 'f'), freqs, 'Hz'))), 'color', colors(2,:));
plot(freqs, abs(squeeze(freqresp(G_iff_md_heavy('d', 'f'), freqs, 'Hz'))), 'color', colors(3,:));
loglog(10.^(0.4*cos([0:0.01:2*pi])+log10(200)), ...
10.^(0.8*sin([0:0.01:2*pi]-pi/4)+log10(2e-8)), 'k--');
text(40, 1e-8, sprintf('Small\nInteraction'), 'horizontalalignment', 'center');
hold off;
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
set(gca, 'XTickLabel',[]); set(gca, 'YTickLabel',[]);
title('$k_n = 1\,N/\mu m$');
ylim([5e-10, 1e-3]);
ax3 = nexttile([2,1]);
hold on;
plot(freqs, abs(squeeze(freqresp(G_pz_light('d', 'f'), freqs, 'Hz'))), 'color', [colors(1,:), 0.5], 'DisplayName', '$m_s = 1\,kg$, OL');
plot(freqs, abs(squeeze(freqresp(G_iff_pz_light('d', 'f'), freqs, 'Hz'))), 'color', colors(1,:), 'DisplayName', '$m_s = 1\,kg$, IFF');
plot(freqs, abs(squeeze(freqresp(G_iff_pz_mid( 'd', 'f'), freqs, 'Hz'))), 'color', colors(2,:), 'DisplayName', '$m_s = 25\,kg$, IFF');
plot(freqs, abs(squeeze(freqresp(G_iff_pz_heavy('d', 'f'), freqs, 'Hz'))), 'color', colors(3,:), 'DisplayName', '$m_s = 50\,kg$, IFF');
loglog(10.^(0.8*cos([0:0.01:2*pi])+log10(350)), ...
10.^(1.2*sin([0:0.01:2*pi])+log10(8e-9)), 'k--', 'HandleVisibility', 'off');
text(200, 5e-7, sprintf('$\\mu$ Station\nCoupling'), 'horizontalalignment', 'center');
hold off;
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
set(gca, 'XTickLabel',[]); set(gca, 'YTickLabel',[]);
title('$k_n = 100\,N/\mu m$');
ylim([5e-10, 1e-3]);
ldg = legend('location', 'northeast', 'FontSize', 8, 'NumColumns', 1);
ldg.ItemTokenSize = [20, 1];
ax1b = nexttile();
hold on;
plot(freqs, 180/pi*unwrap(angle(squeeze(freqresp(G_vc_light('d', 'f'), freqs, 'Hz')))), 'color', [colors(1,:), 0.5]);
@@ -110,6 +63,25 @@ xticks([1e0, 1e1, 1e2]);
yticks(-360:90:360);
ylim([-200, 20]);
linkaxes([ax1,ax1b],'x');
xlim([1, 1e3]);
figure;
tiledlayout(3, 1, 'TileSpacing', 'Compact', 'Padding', 'None');
ax2 = nexttile([2,1]);
hold on;
plot(freqs, abs(squeeze(freqresp(G_md_light('d', 'f'), freqs, 'Hz'))), 'color', [colors(1,:), 0.5]);
plot(freqs, abs(squeeze(freqresp(G_iff_md_light('d', 'f'), freqs, 'Hz'))), 'color', colors(1,:));
plot(freqs, abs(squeeze(freqresp(G_iff_md_mid( 'd', 'f'), freqs, 'Hz'))), 'color', colors(2,:));
plot(freqs, abs(squeeze(freqresp(G_iff_md_heavy('d', 'f'), freqs, 'Hz'))), 'color', colors(3,:));
loglog(10.^(0.4*cos([0:0.01:2*pi])+log10(200)), ...
10.^(0.8*sin([0:0.01:2*pi]-pi/4)+log10(2e-8)), 'k--');
text(40, 1e-8, sprintf('Small\nInteraction'), 'horizontalalignment', 'center');
hold off;
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
set(gca, 'XTickLabel',[]); set(gca, 'YTickLabel',[]);
ylim([5e-10, 1e-3]);
ax2b = nexttile();
hold on;
plot(freqs, 180/pi*unwrap(angle(squeeze(freqresp(G_md_light('d', 'f'), freqs, 'Hz')))), 'color', [colors(1,:), 0.5]);
@@ -123,6 +95,27 @@ xticks([1e0, 1e1, 1e2]);
yticks(-360:90:360);
ylim([-200, 20]);
linkaxes([ax2,ax2b],'x');
xlim([1, 1e3]);
figure;
tiledlayout(3, 1, 'TileSpacing', 'Compact', 'Padding', 'None');
ax3 = nexttile([2,1]);
hold on;
plot(freqs, abs(squeeze(freqresp(G_pz_light('d', 'f'), freqs, 'Hz'))), 'color', [colors(1,:), 0.5], 'DisplayName', '$m_s = 1\,kg$, OL');
plot(freqs, abs(squeeze(freqresp(G_iff_pz_light('d', 'f'), freqs, 'Hz'))), 'color', colors(1,:), 'DisplayName', '$m_s = 1\,kg$, IFF');
plot(freqs, abs(squeeze(freqresp(G_iff_pz_mid( 'd', 'f'), freqs, 'Hz'))), 'color', colors(2,:), 'DisplayName', '$m_s = 25\,kg$, IFF');
plot(freqs, abs(squeeze(freqresp(G_iff_pz_heavy('d', 'f'), freqs, 'Hz'))), 'color', colors(3,:), 'DisplayName', '$m_s = 50\,kg$, IFF');
loglog(10.^(0.8*cos([0:0.01:2*pi])+log10(350)), ...
10.^(1.2*sin([0:0.01:2*pi])+log10(8e-9)), 'k--', 'HandleVisibility', 'off');
text(200, 5e-7, sprintf('$\\mu$ Station\nCoupling'), 'horizontalalignment', 'center');
hold off;
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
set(gca, 'XTickLabel',[]); set(gca, 'YTickLabel',[]);
ylim([5e-10, 1e-3]);
ldg = legend('location', 'northeast', 'FontSize', 8, 'NumColumns', 1);
ldg.ItemTokenSize = [20, 1];
ax3b = nexttile();
hold on;
plot(freqs, 180/pi*unwrap(angle(squeeze(freqresp(G_pz_light('d', 'f'), freqs, 'Hz')))), 'color', [colors(1,:), 0.5]);
@@ -136,72 +129,9 @@ xticks([1e0, 1e1, 1e2]);
yticks(-360:90:360);
ylim([-200, 20]);
linkaxes([ax1,ax2,ax3,ax1b,ax2b,ax3b],'x');
linkaxes([ax3,ax3b],'x');
xlim([1, 1e3]);
% Position Feedback Controller
% <<ssec:uniaxial_position_control_design>>
% The objective now is to design a position feedback controller for each of the three nano-hexapods that are robust to the change of sample's mass.
% The required feedback bandwidth was approximately determined in Section ref:sec:uniaxial_noise_budgeting:
% - $\approx 10\,\text{Hz}$ for the soft nano-hexapod ($k_n = 0.01\,N/\mu m$).
% Near this frequency, the plants are equivalent to a mass line.
% The gain of the mass line can vary up to a fact $\approx 5$ (suspended mass from $16\,kg$ up to $65\,kg$).
% This means that the designed controller will need to have large gain margins to be robust to the change of sample's mass.
% - $\approx 50\,\text{Hz}$ for the relatively stiff nano-hexapod ($k_n = 1\,N/\mu m$).
% Similarly to the soft nano-hexapod, the plants near the crossover frequency are equivalent to a mass line.
% It will be probably easier to have a little bit more bandwidth in this configuration to be further away from the nano-hexapod suspension mode.
% - $\approx 100\,\text{Hz}$ for the stiff nano-hexapod ($k_n = 100\,N/\mu m$).
% Contrary to the two first nano-hexapod stiffnesses, here the plants have more complex dynamics near the wanted crossover frequency.
% The micro-station is not stiff enough to have a clear stiffness line at this frequency.
% Therefore, there are both a change of phase and gain depending on the sample's mass.
% This makes the robust design of the controller a little bit more complicated.
% Position feedback controllers are designed for each nano-hexapod such that it is stable for all considered sample masses with similar stability margins (see Nyquist plots in Figure ref:fig:uniaxial_nyquist_hac).
% These high authority controllers are generally composed of a lag at low frequency for disturbance rejection, a lead to increase the phase margin near the crossover frequency and a low pass filter to increase the robustness to high frequency dynamics.
% The controllers used for the three nano-hexapod are shown in Equation eqref:eq:uniaxial_hac_formulas, and the parameters are summarized in Table ref:tab:uniaxial_feedback_controller_parameters.
% \begin{subequations} \label{eq:uniaxial_hac_formulas}
% \begin{align}
% K_{\text{soft}}(s) &= g \cdot
% \underbrace{\frac{s + \omega_0}{s + \omega_i}}_{\text{lag}} \cdot
% \underbrace{\frac{1 + \frac{s}{\omega_c/\sqrt{a}}}{1 + \frac{s}{\omega_c \sqrt{a}}}}_{\text{lead}} \cdot
% \underbrace{\frac{1}{1 + \frac{s}{\omega_l}}}_{\text{LPF}} \\
% K_{\text{mid}}(s) &= g \cdot
% \underbrace{\left(\frac{s + \omega_0}{s + \omega_i}\right)^2}_{\text{2 lags}} \cdot
% \underbrace{\frac{1 + \frac{s}{\omega_c/\sqrt{a}}}{1 + \frac{s}{\omega_c \sqrt{a}}}}_{\text{lead}} \cdot
% \underbrace{\frac{1}{1 + \frac{s}{\omega_l}}}_{\text{LPF}} \\
% K_{\text{stiff}}(s) &= g \cdot
% \underbrace{\left(\frac{1}{s + \omega_i}\right)^2}_{\text{2 lags}} \cdot
% \underbrace{\left(\frac{1 + \frac{s}{\omega_c/\sqrt{a}}}{1 + \frac{s}{\omega_c \sqrt{a}}}\right)^2}_{\text{2 leads}} \cdot
% \underbrace{\frac{1}{1 + \frac{s}{\omega_l}}}_{\text{LPF}}
% \end{align}
% \end{subequations}
% #+name: tab:uniaxial_feedback_controller_parameters
% #+caption: Parameters used for the position feedback controllers
% #+attr_latex: :environment tabularx :width \linewidth :align lXXX
% #+attr_latex: :center t :booktabs t
% | | *Soft* | *Moderately stiff* | *Stiff* |
% |--------+-------------------------------------------+--------------------------------------------+------------------------------------------|
% | *Gain* | $g = 4 \cdot 10^5$ | $g = 3 \cdot 10^6$ | $g = 6 \cdot 10^12$ |
% | *Lead* | $a = 5$, $\omega_c = 20\,Hz$ | $a = 4$, $\omega_c = 70\,Hz$ | $a = 5$, $\omega_c = 100\,Hz$ |
% | *Lag* | $\omega_0 = 5\,Hz$, $\omega_i = 0.01\,Hz$ | $\omega_0 = 20\,Hz$, $\omega_i = 0.01\,Hz$ | $\omega_i = 0.01\,Hz$ |
% | *LPF* | $\omega_l = 200\,Hz$ | $\omega_l = 300\,Hz$ | $\omega_l = 500\,Hz$ |
% The loop gains for the three nano-hexapod are shown in Figure ref:fig:uniaxial_loop_gain_hac.
% We can see that:
% - for the soft and moderately stiff nano-hexapod, the crossover frequency varies a lot with the sample mass.
% This is due to the fact that the crossover frequency corresponds to the mass line of the plant.
% - for the stiff nano-hexapod, the obtained crossover frequency is not at high as what was estimated necessary.
% The crossover frequency in that case is close to the stiffness line of the plant, which makes the robust design of the controller easier.
% Note that these controllers were quickly tuned by hand and not designed using any optimization methods.
% The goal is just to have a first estimation of the attainable performance.
%% High Authority Controller - Soft Nano-Hexapod
% Lead to increase phase margin
a = 5; % Amount of phase lead / width of the phase lead / high frequency gain
@@ -311,63 +241,163 @@ legend('location', 'northeast', 'FontSize', 8, 'NumColumns', 1);
xlim([-3.8, 0.2]); ylim([-2, 2]);
axis square;
%% Nyquist Plot - Hight Authority Controller - Soft Nano-Hexapod
figure;
hold on;
plot(real(L_vc_light), +imag(L_vc_light), '-', 'color', colors(1,:), 'DisplayName', '$m_s = 1\,$kg')
plot(real(L_vc_light), -imag(L_vc_light), '-', 'color', colors(1,:), 'HandleVisibility', 'off')
plot(real(L_vc_mid ), +imag(L_vc_mid ), '-', 'color', colors(2,:), 'DisplayName', '$m_s = 25\,$kg')
plot(real(L_vc_mid ), -imag(L_vc_mid ), '-', 'color', colors(2,:), 'HandleVisibility', 'off')
plot(real(L_vc_heavy), +imag(L_vc_heavy), '-', 'color', colors(3,:), 'DisplayName', '$m_s = 50\,$kg')
plot(real(L_vc_heavy), -imag(L_vc_heavy), '-', 'color', colors(3,:), 'HandleVisibility', 'off')
% Minimum modul margin
vc_mod_margin = min([min(abs(L_vc_light + 1)), min(abs(L_vc_mid + 1)), min(abs(L_vc_heavy + 1))]);
plot(-1 + vc_mod_margin*cos(linspace(0,2*pi,100)), vc_mod_margin*sin(linspace(0,2*pi,100)), 'k-', 'DisplayName', sprintf('$r = %.2f$', vc_mod_margin))
plot(-1, 0, 'kx', 'HandleVisibility', 'off');
hold off;
set(gca, 'XScale', 'lin'); set(gca, 'YScale', 'lin');
xlabel('Real'); ylabel('Imag');
leg = legend('location', 'southwest', 'FontSize', 8, 'NumColumns', 1);
leg.ItemTokenSize(1) = 15
xlim([-3.8, 0.2]); ylim([-2, 2]);
axis square;
%% Nyquist Plot - Hight Authority Controller - Soft Nano-Hexapod
figure;
hold on;
plot(real(L_md_light), +imag(L_md_light), '-', 'color', colors(1,:), 'DisplayName', '$m_s = 1\,$kg')
plot(real(L_md_light), -imag(L_md_light), '-', 'color', colors(1,:), 'HandleVisibility', 'off')
plot(real(L_md_mid ), +imag(L_md_mid ), '-', 'color', colors(2,:), 'DisplayName', '$m_s = 25\,$kg')
plot(real(L_md_mid ), -imag(L_md_mid ), '-', 'color', colors(2,:), 'HandleVisibility', 'off')
plot(real(L_md_heavy), +imag(L_md_heavy), '-', 'color', colors(3,:), 'DisplayName', '$m_s = 50\,$kg')
plot(real(L_md_heavy), -imag(L_md_heavy), '-', 'color', colors(3,:), 'HandleVisibility', 'off')
% Minimum modul margin
md_mod_margin = min([min(abs(L_md_light + 1)), min(abs(L_md_mid + 1)), min(abs(L_md_heavy + 1))]);
plot(-1 + md_mod_margin*cos(linspace(0,2*pi,100)), md_mod_margin*sin(linspace(0,2*pi,100)), 'k-', 'DisplayName', sprintf('$r = %.2f$', md_mod_margin))
plot(-1, 0, 'kx', 'HandleVisibility', 'off');
hold off;
set(gca, 'XScale', 'lin'); set(gca, 'YScale', 'lin');
xlabel('Real'); ylabel('Imag');
leg = legend('location', 'southwest', 'FontSize', 8, 'NumColumns', 1);
leg.ItemTokenSize(1) = 15
xlim([-3.8, 0.2]); ylim([-2, 2]);
axis square;
% #+name: fig:uniaxial_nyquist_hac
% #+caption: Nyquist Plot - Hight Authority Controller for all three nano-hexapod stiffnesses (soft one in blue, moderately stiff in red and very stiff in yellow) and all sample masses (corresponding to the three curves of each color)
% #+RESULTS:
% [[file:figs/uniaxial_nyquist_hac.png]]
%% Nyquist Plot - Hight Authority Controller - Soft Nano-Hexapod
figure;
hold on;
plot(real(L_pz_light), +imag(L_pz_light), '-', 'color', colors(1,:), 'DisplayName', '$m_s = 1\,$kg')
plot(real(L_pz_light), -imag(L_pz_light), '-', 'color', colors(1,:), 'HandleVisibility', 'off')
plot(real(L_pz_mid ), +imag(L_pz_mid ), '-', 'color', colors(2,:), 'DisplayName', '$m_s = 25\,$kg')
plot(real(L_pz_mid ), -imag(L_pz_mid ), '-', 'color', colors(2,:), 'HandleVisibility', 'off')
plot(real(L_pz_heavy), +imag(L_pz_heavy), '-', 'color', colors(3,:), 'DisplayName', '$m_s = 50\,$kg')
plot(real(L_pz_heavy), -imag(L_pz_heavy), '-', 'color', colors(3,:), 'HandleVisibility', 'off')
% Minimum modul margin
pz_mod_margin = min([min(abs(L_pz_light + 1)), min(abs(L_pz_mid + 1)), min(abs(L_pz_heavy + 1))]);
plot(-1 + pz_mod_margin*cos(linspace(0,2*pi,100)), pz_mod_margin*sin(linspace(0,2*pi,100)), 'k-', 'DisplayName', sprintf('$r = %.2f$', pz_mod_margin))
plot(-1, 0, 'kx', 'HandleVisibility', 'off');
hold off;
set(gca, 'XScale', 'lin'); set(gca, 'YScale', 'lin');
xlabel('Real'); ylabel('Imag');
leg = legend('location', 'southwest', 'FontSize', 8, 'NumColumns', 1);
leg.ItemTokenSize(1) = 15
xlim([-3.8, 0.2]); ylim([-2, 2]);
axis square;
%% Loop Gain - High Authority Controller for all three nano-hexapod stiffnesses and all sample masses
%% Loop Gain - High Authority Controller - Relatively soft nano-hexapod
figure;
tiledlayout(3, 1, 'TileSpacing', 'Compact', 'Padding', 'None');
ax1 = nexttile([2,1]);
hold on;
plot(freqs, abs(L_vc_light), 'color', [colors(1,:), 0.5], 'DisplayName', '$k_n = 0.01\,N/\mu m$');
plot(freqs, abs(L_vc_mid), 'color', [colors(1,:), 0.5], 'HandleVisibility', 'off');
plot(freqs, abs(L_vc_heavy), 'color', [colors(1,:), 0.5], 'HandleVisibility', 'off');
plot(freqs, abs(L_md_light), 'color', [colors(2,:), 0.5], 'DisplayName', '$k_n = 1\,N/\mu m$');
plot(freqs, abs(L_md_mid), 'color', [colors(2,:), 0.5], 'HandleVisibility', 'off');
plot(freqs, abs(L_md_heavy), 'color', [colors(2,:), 0.5], 'HandleVisibility', 'off');
plot(freqs, abs(L_pz_light), 'color', [colors(3,:), 0.5], 'DisplayName', '$k_n = 100\,N/\mu m$');
plot(freqs, abs(L_pz_mid), 'color', [colors(3,:), 0.5], 'HandleVisibility', 'off');
plot(freqs, abs(L_pz_heavy), 'color', [colors(3,:), 0.5], 'HandleVisibility', 'off');
plot(freqs, abs(L_vc_light), 'color', colors(1,:), 'DisplayName', '$m_s = 1\,$kg');
plot(freqs, abs(L_vc_mid), 'color', colors(2,:), 'DisplayName', '$m_s = 25\,$kg');
plot(freqs, abs(L_vc_heavy), 'color', colors(3,:), 'DisplayName', '$m_s = 50\,$kg');
hold off;
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
ylabel('Loop Gain'); set(gca, 'XTickLabel',[]);
ylim([1e-3, 1e3]);
legend('location', 'northeast', 'FontSize', 8, 'NumColumns', 1);
yticks([1e-2, 1, 1e2])
leg = legend('location', 'southwest', 'FontSize', 8, 'NumColumns', 1);
leg.ItemTokenSize(1) = 15
ax2 = nexttile;
hold on;
plot(freqs, 180/pi*unwrap(angle(L_vc_light)), 'color', [colors(1,:), 0.5]);
plot(freqs, 180/pi*unwrap(angle(L_vc_mid )), 'color', [colors(1,:), 0.5]);
plot(freqs, 180/pi*unwrap(angle(L_vc_heavy)), 'color', [colors(1,:), 0.5]);
plot(freqs, 180/pi*unwrap(angle(L_md_light)), 'color', [colors(2,:), 0.5]);
plot(freqs, 180/pi*unwrap(angle(L_md_mid )), 'color', [colors(2,:), 0.5]);
plot(freqs, 180/pi*unwrap(angle(L_md_heavy)), 'color', [colors(2,:), 0.5]);
plot(freqs, 180/pi*unwrap(angle(L_pz_light)), 'color', [colors(3,:), 0.5]);
plot(freqs, 180/pi*unwrap(angle(L_pz_mid )), 'color', [colors(3,:), 0.5]);
plot(freqs, 180/pi*unwrap(angle(L_pz_heavy)), 'color', [colors(3,:), 0.5]);
plot(freqs, 180/pi*unwrap(angle(L_vc_light)), 'color', colors(1,:));
plot(freqs, 180/pi*unwrap(angle(L_vc_mid )), 'color', colors(2,:));
plot(freqs, 180/pi*unwrap(angle(L_vc_heavy)), 'color', colors(3,:));
hold off;
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'lin');
xlabel('Frequency [Hz]'); ylabel('Phase [deg]');
hold off;
yticks(-360:90:360);
ylim([-270, 0]);
yticks(-360:45:360);
ylim([-225, -90]);
linkaxes([ax1,ax2],'x');
xlim([1, 500]);
xticks([1, 10, 100]);
% Closed-Loop Noise Budgeting
% <<ssec:uniaxial_position_control_cl_noise_budget>>
%% Loop Gain - High Authority Controller - Relatively stiff nano-hexapod
figure;
tiledlayout(3, 1, 'TileSpacing', 'Compact', 'Padding', 'None');
% The high authority position feedback controllers are then implemented and the closed-loop sensitivity to disturbances are computed.
% These are compared with the open-loop and damped plants cases in Figure ref:fig:uniaxial_sensitivity_dist_hac_lac for just one configuration (moderately stiff nano-hexapod with 25kg sample's mass).
% As expected, the sensitivity to disturbances is decreased in the controller bandwidth and slightly increase outside this bandwidth.
ax1 = nexttile([2,1]);
hold on;
plot(freqs, abs(L_md_light), 'color', colors(1,:), 'DisplayName', '$m_s = 1\,$kg');
plot(freqs, abs(L_md_mid), 'color', colors(2,:), 'DisplayName', '$m_s = 25\,$kg');
plot(freqs, abs(L_md_heavy), 'color', colors(3,:), 'DisplayName', '$m_s = 50\,$kg');
hold off;
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
ylabel('Loop Gain'); set(gca, 'XTickLabel',[]);
ylim([1e-3, 1e3]);
yticks([1e-2, 1, 1e2])
ax2 = nexttile;
hold on;
plot(freqs, 180/pi*unwrap(angle(L_md_light)), 'color', colors(1,:));
plot(freqs, 180/pi*unwrap(angle(L_md_mid )), 'color', colors(2,:));
plot(freqs, 180/pi*unwrap(angle(L_md_heavy)), 'color', colors(3,:));
hold off;
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'lin');
xlabel('Frequency [Hz]'); ylabel('Phase [deg]');
hold off;
yticks(-360:45:360);
ylim([-225, -90]);
linkaxes([ax1,ax2],'x');
xlim([1, 500]);
xticks([1, 10, 100]);
%% Loop Gain - High Authority Controller - Stiff nano-hexapod
figure;
tiledlayout(3, 1, 'TileSpacing', 'Compact', 'Padding', 'None');
ax1 = nexttile([2,1]);
hold on;
plot(freqs, abs(L_pz_light), 'color', colors(1,:), 'DisplayName', '$m_s = 1\,$kg');
plot(freqs, abs(L_pz_mid), 'color', colors(2,:), 'DisplayName', '$m_s = 25\,$kg');
plot(freqs, abs(L_pz_heavy), 'color', colors(3,:), 'DisplayName', '$m_s = 50\,$kg');
hold off;
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
ylabel('Loop Gain'); set(gca, 'XTickLabel',[]);
ylim([1e-3, 1e3]);
yticks([1e-2, 1, 1e2])
ax2 = nexttile;
hold on;
plot(freqs, 180/pi*unwrap(angle(L_pz_light)), 'color', colors(1,:));
plot(freqs, 180/pi*unwrap(angle(L_pz_mid )), 'color', colors(2,:));
plot(freqs, 180/pi*unwrap(angle(L_pz_heavy)), 'color', colors(3,:));
hold off;
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'lin');
xlabel('Frequency [Hz]'); ylabel('Phase [deg]');
hold off;
yticks(-360:45:360);
ylim([-225, -90]);
linkaxes([ax1,ax2],'x');
xlim([1, 500]);
xticks([1, 10, 100]);
%% Compute Closed Loop Systems
G_hac_iff_vc_light = feedback(G_iff_vc_light, K_hac_vc, 'name', -1);
@@ -391,9 +421,6 @@ isstable(G_hac_iff_pz_light) && isstable(G_hac_iff_pz_mid) && isstable(G_hac_iff
%% Change of sensitivity to disturbances with LAC and with HAC-LAC
figure;
tiledlayout(1, 3, 'TileSpacing', 'Compact', 'Padding', 'None');
ax1 = nexttile();
hold on;
plot(freqs, abs(squeeze(freqresp(G_md_mid( 'd', 'fs'), freqs, 'Hz'))), 'k-');
plot(freqs, abs(squeeze(freqresp(G_iff_md_mid('d', 'fs'), freqs, 'Hz'))), 'color', colors(1,:));
@@ -402,8 +429,9 @@ hold off;
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
xticks([1e0, 1e1, 1e2]);
ylabel('Amplitude $d/f_{s}$ [m/N]'); xlabel('Frequency [Hz]');
xlim([1, 500]);
ax2 = nexttile();
figure;
hold on;
plot(freqs, abs(squeeze(freqresp(G_md_mid( 'd', 'ft'), freqs, 'Hz'))), 'k-');
plot(freqs, abs(squeeze(freqresp(G_iff_md_mid('d', 'ft'), freqs, 'Hz'))), 'color', colors(1,:));
@@ -412,8 +440,9 @@ hold off;
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
xticks([1e0, 1e1, 1e2]);
ylabel('Amplitude $d/f_{t}$ [m/N]'); xlabel('Frequency [Hz]');
xlim([1, 500]);
ax3 = nexttile();
figure;
hold on;
plot(freqs, abs(squeeze(freqresp(G_md_mid( 'd', 'xf'), freqs, 'Hz'))), 'k-', 'DisplayName', 'OL');
plot(freqs, abs(squeeze(freqresp(G_iff_md_mid('d', 'xf'), freqs, 'Hz'))), 'color', colors(1,:), 'DisplayName', 'IFF');
@@ -423,27 +452,10 @@ set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
xticks([1e0, 1e1, 1e2]);
ylabel('Amplitude $d/x_{f}$ [m/m]'); xlabel('Frequency [Hz]');
legend('location', 'southeast', 'FontSize', 8, 'NumColumns', 1);
linkaxes([ax1,ax2,ax3],'x');
xlim([1, 500]);
% #+name: fig:uniaxial_sensitivity_dist_hac_lac
% #+caption: Change of sensitivity to disturbances with LAC and with HAC-LAC. Nano-Hexapod with $k_n = 1\,N/\mu m$ and sample mass of $25\,kg$ are used.
% #+RESULTS:
% [[file:figs/uniaxial_sensitivity_dist_hac_lac.png]]
% The cumulative amplitude spectrum of the motion $d$ is computed for all nano-hexapod configurations, all sample masses and in the open-loop (OL), damped (IFF) and position controlled (HAC-IFF) cases.
% The results are shown in Figure ref:fig:uniaxial_cas_hac_lac.
% Obtained root mean square values of the distance $d$ are better for the soft nano-hexapod ($\approx 25\,nm$ to $\approx 35\,nm$ depending on the sample's mass) than for the stiffer nano-hexapod (from $\approx 30\,nm$ to $\approx 70\,nm$).
%% Cumulative Amplitude Spectrum for all three nano-hexapod stiffnesses - Comparison of OL, IFF and HAC-LAC cases
figure;
tiledlayout(1, 3, 'TileSpacing', 'Compact', 'Padding', 'None');
ax1 = nexttile();
hold on;
plot(f, sqrt(flip(-cumtrapz(flip(f), flip(psd_ft.*abs(squeeze(freqresp(G_vc_mid('d', 'ft'), f, 'Hz'))).^2 + ...
psd_xf.*abs(squeeze(freqresp(G_vc_mid('d', 'xf'), f, 'Hz'))).^2)))), '-', ...
@@ -477,9 +489,10 @@ set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
xticks([1e0, 1e1, 1e2]);
ylabel('CAS of $d$ [m]'); xlabel('Frequency [Hz]');
legend('location', 'southwest', 'FontSize', 8, 'NumColumns', 1);
title('$k_n = 0.01\,N/\mu m$');
xlim([1, 500]);
ylim([2e-10, 3e-6])
ax2 = nexttile();
figure;
hold on;
plot(f, sqrt(flip(-cumtrapz(flip(f), flip(psd_ft.*abs(squeeze(freqresp(G_md_mid('d', 'ft'), f, 'Hz'))).^2 + ...
psd_xf.*abs(squeeze(freqresp(G_md_mid('d', 'xf'), f, 'Hz'))).^2)))), '-', ...
@@ -512,9 +525,10 @@ hold off;
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
xticks([1e0, 1e1, 1e2]);
xlabel('Frequency [Hz]'); set(gca, 'YTickLabel',[]);
title('$k_n = 1\,N/\mu m$');
xlim([1, 500]);
ylim([2e-10, 3e-6])
ax3 = nexttile();
figure;
hold on;
plot(f, sqrt(flip(-cumtrapz(flip(f), flip(psd_ft.*abs(squeeze(freqresp(G_pz_mid('d', 'ft'), f, 'Hz'))).^2 + ...
psd_xf.*abs(squeeze(freqresp(G_pz_mid('d', 'xf'), f, 'Hz'))).^2)))), '-', ...
@@ -547,8 +561,5 @@ hold off;
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
xticks([1e0, 1e1, 1e2]);
xlabel('Frequency [Hz]'); set(gca, 'YTickLabel',[]);
title('$k_n = 100\,N/\mu m$');
linkaxes([ax1,ax2,ax3],'xy');
xlim([1, 500]);
ylim([2e-10, 3e-6])

View File

@@ -16,15 +16,6 @@ load('uniaxial_micro_station_parameters.mat')
%% Frequency Vector [Hz]
freqs = logspace(0, 3, 1000);
% Neglected support compliance
% Let's first neglect the limited compliance of the micro-station and use the uniaxial model show in Figure ref:fig:uniaxial_support_compliance_nano_hexapod_only.
% Let's choose a nano-hexapod mass (including the payload) of $20\,\text{kg}$ and three hexapod stiffnesses such that their resonance frequencies are at $\omega_{\nu} = 10\,\text{Hz}$, $\omega_{\nu} = 70\,\text{Hz}$ and $\omega_{\nu} = 400\,\text{Hz}$.
% The obtained transfer functions from $F$ to $L^\prime$ are shown in Figure ref:fig:uniaxial_effect_support_compliance_neglected.
% When neglecting the support compliance, large feedback bandwidth can be achieve for all three Nano-Hexapod.
%% Nano-Hexapod Parameters
m = 20; % Mass [kg]
@@ -37,7 +28,7 @@ k_mid = m*(2*pi*70)^2; % Stiffness [N/m]
c_mid = 0.1*2*sqrt(m*k_mid); % Damping [N/(m/s)]
% "Stiff" Nano-Hexapod
k_stiff = m*(2*pi*400)^2; % Stiffness [N/m]
k_stiff = m*(2*pi*350)^2; % Stiffness [N/m]
c_stiff = 0.1*2*sqrt(m*k_stiff); % Damping [N/(m/s)]
%% Compute the transfer functions for considered nano-hexapods - From F to L'
@@ -50,54 +41,46 @@ G_mid_a = 1/(m*s^2 + c_mid*s + k_mid); % Transfer function from F to L'
% "Stiff" Nano-Hexapod
G_stiff_a = 1/(m*s^2 + c_stiff*s + k_stiff); % Transfer function from F to L'
%% Obtained transfer functions from F to L when neglecing support compliance
%% Obtained transfer functions from F to L when neglecting support compliance
freqs = logspace(0, 3, 1000);
figure;
tiledlayout(1, 3, 'TileSpacing', 'Compact', 'Padding', 'None');
ax1 = nexttile();
hold on;
plot(freqs, abs(squeeze(freqresp(G_soft_a, freqs, 'Hz'))), '-', 'color', colors(1,:));
text(50, 5e-5, '$\omega_\nu =$ 10Hz', 'horizontalalignment', 'center');
text(50, 5e-5, '$\omega_n =$ 10Hz', 'horizontalalignment', 'center');
hold off;
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
ylabel('Magnitude [m/N]');
xlabel('Frequency [Hz]'); ylabel('Magnitude [m/N]');
xlim([freqs(1), freqs(end)]);
xticks([1e0, 1e1, 1e2]);
title('"Soft" $\nu$-hexapod');
ylim([1e-9, 1e-4]);
yticks([1e-9, 1e-7, 1e-5]);
ax2 = nexttile();
figure;
hold on;
plot(freqs, abs(squeeze(freqresp(G_mid_a, freqs, 'Hz'))), '-', 'color', colors(1,:));
text(70, 3e-6, '$\omega_\nu =$ 70Hz', 'horizontalalignment', 'center');
text(70, 3e-6, '$\omega_n =$ 70Hz', 'horizontalalignment', 'center');
hold off;
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
xlabel('Frequency [Hz]');
set(gca, 'YTickLabel',[]);
xlabel('Frequency [Hz]'); set(gca, 'YTickLabel',[]);
xlim([freqs(1), freqs(end)]);
xticks([1e0, 1e1, 1e2]);
title('"Mid" $\nu$-hexapod');
ylim([1e-9, 1e-4]);
yticks([1e-9, 1e-7, 1e-5]);
ax3 = nexttile();
figure;
hold on;
plot(freqs, abs(squeeze(freqresp(G_stiff_a, freqs, 'Hz'))), '-', 'color', colors(1,:), ...
'DisplayName', '$L^\prime/F$');
text(200, 8e-8, '$\omega_\nu =$ 400Hz', 'horizontalalignment', 'center');
text(200, 8e-8, '$\omega_n =$ 400Hz', 'horizontalalignment', 'center');
hold off;
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
set(gca, 'YTickLabel',[]);
xlabel('Frequency [Hz]'); set(gca, 'YTickLabel',[]);
legend('location', 'northeast');
xticks([1e0, 1e1, 1e2]);
title('"Stiff" $\nu$-hexapod');
linkaxes([ax1,ax2,ax3],'xy');
xlim([freqs(1), freqs(end)]);
xticks([1e0, 1e1, 1e2]);
ylim([1e-9, 1e-4]);
% Effect of support compliance on $L/F$
% Let's now add some support compliance and use the model shown in Figure ref:fig:uniaxial_support_compliance_test_system.
% The parameters of the support (i.e. $m^{\prime}$, $c^{\prime}$ and $k^{\prime}$) are chosen in such a way that the main vertical mode at $\omega_\mu = 70\,\text{Hz}$ seen on the micro-station is matched (Figure ref:fig:uniaxial_comp_frf_meas_model, yellow curve).
yticks([1e-9, 1e-7, 1e-5]);
%% Parameters of the support compliance
w0h = 2*pi*70; % [rad/s]
@@ -120,27 +103,10 @@ G_mid_r = (1 - m*s^2*G_mid)/(c_mid*s + k_mid); % L/F
G_stiff = (mh*s^2 + ch*s + kh)/(m*s^2*(c_stiff*s + k_stiff) + (m*s^2 + c_stiff*s + k_stiff)*(mh*s^2 + ch*s + kh)); % d/F
G_stiff_r = (1 - m*s^2*G_stiff)/(c_stiff*s + k_stiff); % L/F
% The transfer functions from $F$ to $L$ (i.e. control of the relative motion of the nano-hexapod) and from $L$ to $d$ (i.e. control of the position between the nano-hexapod and the fixed granite) can then be computed.
% When the relative displacement of the nano-hexapod $L$ is to be controlled (dynamics shown in Figure ref:fig:uniaxial_effect_support_compliance_dynamics), having a stiff nano-hexapod (i.e. with a suspension mode at higher frequency than the mode of the support) makes the dynamics less affected by the limited support compliance (Figure ref:fig:uniaxial_effect_support_compliance_dynamics, right).
% This is why it is very common to have stiff piezoelectric stages fixed at the very top of positioning stages.
% In such case, the control of the piezoelectric stage using its integrated metrology (typically capacitive sensors) is quite simple as the plant is not much affected by the dynamics of the support on which is it fixed.
% # Add references of such stations with piezo stages on top
% If a soft nano-hexapod is used, the support dynamics appears in the dynamics between $F$ and $L$ (see Figure ref:fig:uniaxial_effect_support_compliance_dynamics, left) which will impact the control robustness and performance.
%% Effect of the support compliance on the transfer functions from F to L and from F to d
figure;
freqs = logspace(0, 3, 1000);
figure;
tiledlayout(1, 3, 'TileSpacing', 'Compact', 'Padding', 'None');
ax1 = nexttile();
hold on;
plot(freqs, abs(squeeze(freqresp(G_soft_a, freqs, 'Hz'))), '-', 'color', colors(1,:));
plot(freqs, abs(squeeze(freqresp(G_soft_r, freqs, 'Hz'))), '-', 'color', colors(2,:));
@@ -149,23 +115,26 @@ loglog(10.^(0.3*cos(0:0.01:2*pi)+log10(60)), ...
text(8, 3e-7, sprintf('Support\nDynamics'), 'horizontalalignment', 'center');
hold off;
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
xlabel('Frequency [Hz]'); ylabel('Magnitude [m/N]');
xlim([freqs(1), freqs(end)]);
xticks([1e0, 1e1, 1e2]);
title('"Soft" $\nu$-hexapod');
ylabel('Magnitude [m/N]');
ylim([1e-9, 1e-4]);
yticks([1e-9, 1e-7, 1e-5]);
ax2 = nexttile();
figure;
hold on;
plot(freqs, abs(squeeze(freqresp(G_mid_a, freqs, 'Hz'))), '-', 'color', colors(1,:));
plot(freqs, abs(squeeze(freqresp(G_mid_r, freqs, 'Hz'))), '-', 'color', colors(2,:));
hold off;
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
xlabel('Frequency [Hz]');
xticks([1e0, 1e1, 1e2]);
title('"Mid" $\nu$-hexapod');
set(gca, 'YTickLabel',[]);
xlim([freqs(1), freqs(end)]);
xticks([1e0, 1e1, 1e2]);
ylim([1e-9, 1e-4]);
yticks([1e-9, 1e-7, 1e-5]);
ax3 = nexttile();
figure;
hold on;
plot(freqs, abs(squeeze(freqresp(G_stiff_a, freqs, 'Hz'))), '-', 'color', colors(1,:), ...
'DisplayName', '$L^\prime/F$');
@@ -176,30 +145,17 @@ loglog(10.^(0.3*cos(0:0.01:2*pi)+log10(50)), ...
text(50, 3e-8, 'No effect', 'horizontalalignment', 'center');
hold off;
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
set(gca, 'YTickLabel',[]);
xticks([1e0, 1e1, 1e2]);
title('"Stiff" $\nu$-hexapod');
xlabel('Frequency [Hz]'); set(gca, 'YTickLabel',[]);
legend('location', 'northeast', 'FontSize', 8, 'NumColumns', 1);
linkaxes([ax1,ax2,ax3],'xy');
xlim([freqs(1), freqs(end)]);
xticks([1e0, 1e1, 1e2]);
ylim([1e-9, 1e-4]);
% Effect of support compliance on $d/F$
% When the motion to be controlled is the relative displacement $d$ between the granite and the nano-hexapod's top platform, the effect of the support compliance on the plant dynamics is opposite than what was previously observed.
% Indeed, using a "soft" nano-hexapod (i.e. with a suspension mode at lower frequency than the mode of the support) makes the dynamics less affected by the support dynamics (Figure ref:fig:uniaxial_effect_support_compliance_dynamics_d, left).
% On the contrary, if a "stiff" nano-hexapod is used, the support dynamics appears in the plant dynamics (Figure ref:fig:uniaxial_effect_support_compliance_dynamics_d, right).
yticks([1e-9, 1e-7, 1e-5]);
%% Effect of the support compliance on the transfer functions from F to L and from F to d
figure;
freqs = logspace(0, 3, 1000);
figure;
tiledlayout(1, 3, 'TileSpacing', 'Compact', 'Padding', 'None');
ax1 = nexttile();
hold on;
plot(freqs, abs(squeeze(freqresp(G_soft_a, freqs, 'Hz'))), '-', 'color', colors(1,:));
plot(freqs, abs(squeeze(freqresp(G_soft, freqs, 'Hz'))), '-', 'color', colors(3,:));
@@ -208,23 +164,26 @@ loglog(10.^(0.3*cos(0:0.01:2*pi)+log10(60)), ...
text(8, 3e-7, 'No effect', 'horizontalalignment', 'center');
hold off;
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
xlabel('Frequency [Hz]'); ylabel('Magnitude [m/N]');
xlim([freqs(1), freqs(end)]);
xticks([1e0, 1e1, 1e2]);
title('"Soft" $\nu$-hexapod');
ylabel('Magnitude [m/N]');
ylim([1e-9, 1e-4]);
yticks([1e-9, 1e-7, 1e-5]);
ax2 = nexttile();
figure;
hold on;
plot(freqs, abs(squeeze(freqresp(G_mid_a, freqs, 'Hz'))), '-', 'color', colors(1,:));
plot(freqs, abs(squeeze(freqresp(G_mid, freqs, 'Hz'))), '-', 'color', colors(3,:));
hold off;
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
xlabel('Frequency [Hz]');
xticks([1e0, 1e1, 1e2]);
title('"Mid" $\nu$-hexapod');
set(gca, 'YTickLabel',[]);
xlim([freqs(1), freqs(end)]);
xticks([1e0, 1e1, 1e2]);
ylim([1e-9, 1e-4]);
yticks([1e-9, 1e-7, 1e-5]);
ax3 = nexttile();
figure;
hold on;
plot(freqs, abs(squeeze(freqresp(G_stiff_a, freqs, 'Hz'))), '-', 'color', colors(1,:), ...
'DisplayName', '$L^\prime/F$');
@@ -235,11 +194,9 @@ loglog(10.^(0.4*cos(0:0.01:2*pi)+log10(50)), ...
text(50, 2e-7, sprintf('Support\nDynamics'), 'horizontalalignment', 'center');
hold off;
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
set(gca, 'YTickLabel',[]);
xticks([1e0, 1e1, 1e2]);
title('"Stiff" $\nu$-hexapod');
xlabel('Frequency [Hz]'); set(gca, 'YTickLabel',[]);
legend('location', 'northeast', 'FontSize', 8, 'NumColumns', 1);
linkaxes([ax1,ax2,ax3],'xy');
xlim([freqs(1), freqs(end)]);
xticks([1e0, 1e1, 1e2]);
ylim([1e-9, 1e-4]);
yticks([1e-9, 1e-7, 1e-5]);

View File

@@ -30,21 +30,6 @@ load('uniaxial_high_authority_controllers.mat', 'K_hac_vc', 'K_hac_md', 'K_hac_p
%% Frequency Vector [Hz]
freqs = logspace(0, 3, 1000);
% Impact on the plant dynamics
% <<ssec:uniaxial_payload_dynamics_effect_dynamics>>
% To study the impact of sample dynamics, the following sample configurations are considered:
% - rigid sample, corresponding to Figure ref:fig:uniaxial_paylaod_dynamics_rigid_schematic
% - two flexible samples with a resonance at $\omega_s = 200\,\text{Hz}$ and at $\omega_s = 20\,\text{Hz}$ respectively, corresponding to Figure ref:fig:uniaxial_paylaod_dynamics_schematic
% - for all cases, two sample masses are considered: $m_s = 1\,\text{kg}$ and $m_s = 50\,\text{kg}$
% The transfer functions from the nano-hexapod force to the motion of the nano-hexapod top platform are computed for all the above configurations and are compared for a soft Nano-Hexapod $k_n = 0.01\,N/\mu m$ in Figure ref:fig:uniaxial_payload_dynamics_soft_nano_hexapod.
% It can be seen that the mode of the sample adds an anti-resonance followed by a resonance (zero/pole pattern).
% The frequency of the anti-resonance corresponds to the "free" resonance of the sample $\omega_s = \sqrt{k_s/m_s}$.
% The flexibility of the sample also changes the high frequency gain (the mass line is shifted from $\frac{1}{(m_n + m_s)s^2}$ to $\frac{1}{m_ns^2}$).
%% Soft Nano-Hexapod
% Light payload mass
mn = 15; % Nano-Hexapod mass [kg]
@@ -90,7 +75,7 @@ G_vc_stiff_heavy = (ms*s^2 + cs*s + ks)/((mn*s^2 + cn*s + kn)*(ms*s^2 + cs*s + k
%% Effect of the payload dynamics on the soft Nano-Hexapod. Light sample on the right, and heavy sample on the left
figure;
tiledlayout(3, 2, 'TileSpacing', 'Compact', 'Padding', 'None');
tiledlayout(3, 1, 'TileSpacing', 'Compact', 'Padding', 'None');
ax1 = nexttile([2,1]);
hold on;
@@ -101,24 +86,6 @@ hold off;
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
ylabel('Amplitude [m/N]'); set(gca, 'XTickLabel',[]);
ylim([1e-10, 1e-2])
title('$k_n = 0.01\,N/\mu m$, $m_s = 1\,kg$');
ax2 = nexttile([2,1]);
hold on;
plot(freqs, abs(squeeze(freqresp(G_vc_rigid_heavy, freqs, 'Hz'))), '-', 'color', colors(1,:), 'DisplayName', 'Rigid sample');
plot(freqs, abs(squeeze(freqresp(G_vc_stiff_heavy, freqs, 'Hz'))), '-', 'color', colors(2,:), 'DisplayName', '$\omega_s = 200\,Hz$');
plot(freqs, abs(squeeze(freqresp(G_vc_soft_heavy, freqs, 'Hz'))), '-', 'color', colors(3,:), 'DisplayName', '$\omega_s = 20\,Hz$');
plot(freqs, abs(squeeze(freqresp(1/(mn*s^2), freqs, 'Hz'))), '-', 'color', [0,0,0,0.5], 'DisplayName', '$\frac{1}{m_n s^2}$');
plot(freqs, abs(squeeze(freqresp(1/((mn + ms)*s^2), freqs, 'Hz'))), '--', 'color', [0,0,0,0.5], 'DisplayName', '$\frac{1}{(m_n + m_s) s^2}$');
text(2.2, 3e-3, '$\omega_n = \sqrt{\frac{k_n}{m_n + m_s}}$', 'horizontalalignment', 'left');
text(20, 1e-8, '$\omega_s = \sqrt{\frac{k_s}{m_s}}$', 'horizontalalignment', 'center');
hold off;
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
set(gca, 'XTickLabel',[]); set(gca, 'YTickLabel',[]);
title('$k_n = 0.01\,N/\mu m$, $m_s = 50\,kg$');
ldg = legend('location', 'northeast', 'FontSize', 8, 'NumColumns', 1);
ldg.ItemTokenSize = [20, 1];
ylim([1e-10, 1e-2])
ax1b = nexttile();
hold on;
@@ -132,6 +99,28 @@ xticks([1e0, 1e1, 1e2]);
yticks(-360:90:360);
ylim([-200, 20]);
linkaxes([ax1,ax1b],'x');
xlim([1, 1000]);
figure;
tiledlayout(3, 1, 'TileSpacing', 'Compact', 'Padding', 'None');
ax2 = nexttile([2,1]);
hold on;
plot(freqs, abs(squeeze(freqresp(G_vc_rigid_heavy, freqs, 'Hz'))), '-', 'color', colors(1,:), 'DisplayName', 'Rigid sample');
plot(freqs, abs(squeeze(freqresp(G_vc_stiff_heavy, freqs, 'Hz'))), '-', 'color', colors(2,:), 'DisplayName', '$\omega_s = 200\,Hz$');
plot(freqs, abs(squeeze(freqresp(G_vc_soft_heavy, freqs, 'Hz'))), '-', 'color', colors(3,:), 'DisplayName', '$\omega_s = 20\,Hz$');
plot(freqs, abs(squeeze(freqresp(1/(mn*s^2), freqs, 'Hz'))), '-', 'color', [0,0,0,0.5], 'DisplayName', '$\frac{1}{m_n s^2}$');
plot(freqs, abs(squeeze(freqresp(1/((mn + ms)*s^2), freqs, 'Hz'))), '--', 'color', [0,0,0,0.5], 'DisplayName', '$\frac{1}{(m_n + m_s) s^2}$');
text(2.2, 2e-3, '$\omega_n = \sqrt{\frac{k_n}{m_n + m_s}}$', 'horizontalalignment', 'left');
text(20, 1e-8, '$\omega_s = \sqrt{\frac{k_s}{m_s}}$', 'horizontalalignment', 'center');
hold off;
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
ylabel('Amplitude [m/N]'); set(gca, 'XTickLabel',[]);
ldg = legend('location', 'northeast', 'FontSize', 8, 'NumColumns', 1);
ldg.ItemTokenSize = [20, 1];
ylim([1e-10, 1e-2])
ax2b = nexttile();
hold on;
plot(freqs, 180/pi*unwrap(angle(squeeze(freqresp(G_vc_rigid_heavy, freqs, 'Hz')))), '-', 'color', colors(1,:));
@@ -139,27 +128,14 @@ plot(freqs, 180/pi*unwrap(angle(squeeze(freqresp(G_vc_stiff_heavy, freqs, 'Hz'))
plot(freqs, 180/pi*unwrap(angle(squeeze(freqresp(G_vc_soft_heavy, freqs, 'Hz')))), '-', 'color', colors(3,:));
hold off;
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'lin');
xlabel('Frequency [Hz]'); set(gca, 'YTickLabel',[]);
xlabel('Frequency [Hz]'); ylabel('Phase [deg]');
xticks([1e0, 1e1, 1e2]);
yticks(-360:90:360);
ylim([-200, 20]);
linkaxes([ax1,ax1b],'x');
linkaxes([ax2,ax2b],'x');
xlim([1, 1000]);
% #+name: fig:uniaxial_payload_dynamics_soft_nano_hexapod
% #+caption: Effect of the payload dynamics on the soft Nano-Hexapod. Light sample on the right, and heavy sample on the left
% #+RESULTS:
% [[file:figs/uniaxial_payload_dynamics_soft_nano_hexapod.png]]
% The same transfer functions are now compared when using a stiff nano-hexapod ($k_n = 100\,N/\mu m$) in Figure ref:fig:uniaxial_payload_dynamics_stiff_nano_hexapod.
% In that case, the sample's resonance $\omega_n$ is smaller than the nano-hexapod resonance $\omega_n$.
% This changes the zero/pole pattern to a pole/zero pattern (the frequency of the zero still being equal to $\omega_s$).
% Even tough the added sample's flexibility still changes the high frequency mass line from $\frac{1}{(m_n + m_s)s^2}$ to $\frac{1}{m_ns^2}$, the overall dynamics is much less impacted, even if the sample mass is high (see yellow curve in Figure ref:fig:uniaxial_payload_dynamics_stiff_nano_hexapod, right).
%% Stiff Nano-Hexapod
% Light payload mass
mn = 15; % Nano-Hexapod mass [kg]
@@ -205,7 +181,7 @@ G_pz_stiff_heavy = (ms*s^2 + cs*s + ks)/((mn*s^2 + cn*s + kn)*(ms*s^2 + cs*s + k
%% Effect of the payload dynamics on the stiff Nano-Hexapod. Light sample on the right, and heavy sample on the left
figure;
tiledlayout(3, 2, 'TileSpacing', 'Compact', 'Padding', 'None');
tiledlayout(3, 1, 'TileSpacing', 'Compact', 'Padding', 'None');
ax1 = nexttile([2,1]);
hold on;
@@ -215,21 +191,7 @@ plot(freqs, abs(squeeze(freqresp(G_pz_soft_light, freqs, 'Hz'))), '-', 'color',
hold off;
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
ylabel('Amplitude [m/N]'); set(gca, 'XTickLabel',[]);
ylim([1e-10, 1e-2])
title('$k_n = 100\,N/\mu m$, $m_s = 1\,kg$');
ax2 = nexttile([2,1]);
hold on;
plot(freqs, abs(squeeze(freqresp(G_pz_rigid_heavy, freqs, 'Hz'))), '-', 'color', colors(1,:), 'DisplayName', 'Rigid sample');
plot(freqs, abs(squeeze(freqresp(G_pz_stiff_heavy, freqs, 'Hz'))), '-', 'color', colors(2,:), 'DisplayName', 'Stiff sample: $\omega_s = 200\,Hz$');
plot(freqs, abs(squeeze(freqresp(G_pz_soft_heavy, freqs, 'Hz'))), '-', 'color', colors(3,:), 'DisplayName', 'Soft sample: $\omega_s = 20\,Hz$');
hold off;
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
set(gca, 'XTickLabel',[]); set(gca, 'YTickLabel',[]);
title('$k_n = 100\,N/\mu m$, $m_s = 50\,kg$');
ylim([1e-10, 1e-2])
ldg = legend('location', 'northeast', 'FontSize', 8, 'NumColumns', 1);
ldg.ItemTokenSize = [20, 1];
ylim([1e-10, 1e-6])
ax1b = nexttile();
hold on;
@@ -243,6 +205,24 @@ xticks([1e0, 1e1, 1e2]);
yticks(-360:90:360);
ylim([-200, 20]);
linkaxes([ax1,ax1b],'x');
xlim([1, 1000]);
figure;
tiledlayout(3, 1, 'TileSpacing', 'Compact', 'Padding', 'None');
ax2 = nexttile([2,1]);
hold on;
plot(freqs, abs(squeeze(freqresp(G_pz_rigid_heavy, freqs, 'Hz'))), '-', 'color', colors(1,:), 'DisplayName', 'Rigid sample');
plot(freqs, abs(squeeze(freqresp(G_pz_stiff_heavy, freqs, 'Hz'))), '-', 'color', colors(2,:), 'DisplayName', 'Stiff sample: $\omega_s = 200\,Hz$');
plot(freqs, abs(squeeze(freqresp(G_pz_soft_heavy, freqs, 'Hz'))), '-', 'color', colors(3,:), 'DisplayName', 'Soft sample: $\omega_s = 20\,Hz$');
hold off;
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
ylabel('Amplitude [m/N]'); set(gca, 'XTickLabel',[]);
ylim([1e-10, 1e-6])
ldg = legend('location', 'northwest', 'FontSize', 8, 'NumColumns', 1);
ldg.ItemTokenSize = [20, 1];
ax2b = nexttile();
hold on;
plot(freqs, 180/pi*unwrap(angle(squeeze(freqresp(G_pz_rigid_heavy, freqs, 'Hz')))), '-', 'color', colors(1,:));
@@ -250,34 +230,14 @@ plot(freqs, 180/pi*unwrap(angle(squeeze(freqresp(G_pz_stiff_heavy, freqs, 'Hz'))
plot(freqs, 180/pi*unwrap(angle(squeeze(freqresp(G_pz_soft_heavy, freqs, 'Hz')))), '-', 'color', colors(3,:));
hold off;
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'lin');
xlabel('Frequency [Hz]'); set(gca, 'YTickLabel',[]);
xlabel('Frequency [Hz]'); ylabel('Phase [deg]');
xticks([1e0, 1e1, 1e2]);
yticks(-360:90:360);
ylim([-200, 20]);
linkaxes([ax1,ax1b],'x');
linkaxes([ax2,ax2b],'x');
xlim([1, 1000]);
% #+name: fig:uniaxial_sample_flexibility_control
% #+caption: Uniaxial model considering a flexibility between the nano-hexapod top platform and the sample. In that case the measured and controlled distance $d$ is different from the distance $y$ that is wish to be controlled
% #+RESULTS:
% [[file:figs/uniaxial_sample_flexibility_control.png]]
% After the system dynamics extracted from the model, IFF is applied using the same gains as the ones used in Section ref:sec:uniaxial_active_damping.
% Thanks to the collocation between the nano-hexapod and the force sensor used for IFF, the damped plants are still stable and similar damping values are obtained than when considering a rigid sample.
% The High Authority Controllers used in Section ref:sec:uniaxial_position_control are then implemented on the damped plants.
% The obtained closed-loop systems are stable, indicating good robustness.
% Finally, closed-loop noise budgeting is computed for the obtained the closed-loop system and the cumulative amplitude spectrum of $d$ and $y$ are shown in Figure ref:fig:uniaxial_sample_flexibility_noise_budget_y.
% The cumulative amplitude spectrum of the measured distance $d$ (Figure ref:fig:uniaxial_sample_flexibility_noise_budget_d) shows that the added flexibility at the sample location have very little effect on the control performance.
% However, the cumulative amplitude spectrum of the distance $y$ (Figure ref:fig:uniaxial_sample_flexibility_noise_budget_y) shows that the stability of $y$ is degraded when the sample flexibility is considered and is degraded as $\omega_s$ is lowered.
% What happens is that above $\omega_s$, even though the motion $d$ can be controlled perfectly, the sample's mass is "isolated" from the motion of the nano-hexapod and the control on $y$ is not effective.
%% Nano-Hexpod model
model_config = struct();
model_config.controller = "open_loop";
@@ -398,82 +358,40 @@ isstable(G_hac_iff_pz_light_stiff)
%% Cumulative Amplitude Spectrum of d - Effect of Sample's flexibility
figure;
tiledlayout(1, 2, 'TileSpacing', 'Compact', 'Padding', 'None');
ax1 = nexttile();
hold on;
plot(f, sqrt(flip(-cumtrapz(flip(f), flip(psd_ft.*abs(squeeze(freqresp(G_hac_iff_vc_light_rigid('d', 'ft'), f, 'Hz'))).^2 + ...
psd_xf.*abs(squeeze(freqresp(G_hac_iff_vc_light_rigid('d', 'xf'), f, 'Hz'))).^2)))), '-', ...
'DisplayName', 'Rigid sample');
plot(f, sqrt(flip(-cumtrapz(flip(f), flip(psd_ft.*abs(squeeze(freqresp(G_hac_iff_vc_light_stiff('d', 'ft'), f, 'Hz'))).^2 + ...
psd_xf.*abs(squeeze(freqresp(G_hac_iff_vc_light_stiff('d', 'xf'), f, 'Hz'))).^2)))), '-', ...
'DisplayName', 'Stiff $\omega_s = 200\,$Hz');
plot(f, sqrt(flip(-cumtrapz(flip(f), flip(psd_ft.*abs(squeeze(freqresp(G_hac_iff_vc_light_soft('d', 'ft'), f, 'Hz'))).^2 + ...
psd_xf.*abs(squeeze(freqresp(G_hac_iff_vc_light_soft('d', 'xf'), f, 'Hz'))).^2)))), '-', ...
'DisplayName', 'Soft $\omega_s = 20\,$Hz');
hold off;
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
xticks([1e0, 1e1, 1e2]);
ylabel('CAS of $d$ [m]'); xlabel('Frequency [Hz]');
legend('location', 'southwest', 'FontSize', 8, 'NumColumns', 1);
title('$k_n = 0.01\,N/\mu m$');
ax2 = nexttile();
hold on;
plot(f, sqrt(flip(-cumtrapz(flip(f), flip(psd_ft.*abs(squeeze(freqresp(G_hac_iff_pz_light_rigid('d', 'ft'), f, 'Hz'))).^2 + ...
psd_xf.*abs(squeeze(freqresp(G_hac_iff_pz_light_rigid('d', 'xf'), f, 'Hz'))).^2)))), '-');
psd_xf.*abs(squeeze(freqresp(G_hac_iff_pz_light_rigid('d', 'xf'), f, 'Hz'))).^2)))), '-', ...
'DisplayName', 'Rigid sample');
plot(f, sqrt(flip(-cumtrapz(flip(f), flip(psd_ft.*abs(squeeze(freqresp(G_hac_iff_pz_light_stiff('d', 'ft'), f, 'Hz'))).^2 + ...
psd_xf.*abs(squeeze(freqresp(G_hac_iff_pz_light_stiff('d', 'xf'), f, 'Hz'))).^2)))), '-');
psd_xf.*abs(squeeze(freqresp(G_hac_iff_pz_light_stiff('d', 'xf'), f, 'Hz'))).^2)))), '-', ...
'DisplayName', '$\omega_s = 200\,$Hz');
plot(f, sqrt(flip(-cumtrapz(flip(f), flip(psd_ft.*abs(squeeze(freqresp(G_hac_iff_pz_light_soft('d', 'ft'), f, 'Hz'))).^2 + ...
psd_xf.*abs(squeeze(freqresp(G_hac_iff_pz_light_soft('d', 'xf'), f, 'Hz'))).^2)))), '-');
psd_xf.*abs(squeeze(freqresp(G_hac_iff_pz_light_soft('d', 'xf'), f, 'Hz'))).^2)))), '-', ...
'DisplayName', '$\omega_s = 20\,$Hz');
hold off;
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
ylabel('CAS of $d$ [m]'); xlabel('Frequency [Hz]');
legend('location', 'southwest', 'FontSize', 8, 'NumColumns', 1);
xlim([1, 500]);
xticks([1e0, 1e1, 1e2]);
xlabel('Frequency [Hz]'); set(gca, 'YTickLabel',[]);
title('$k_n = 100\,N/\mu m$');
xlim([1, 500]);
linkaxes([ax1,ax2],'xy');
xlim([1, 500]);
ylim([2e-10, 2e-7])
%% Cumulative Amplitude Spectrum - Effect of Sample's flexibility
figure;
tiledlayout(1, 2, 'TileSpacing', 'Compact', 'Padding', 'None');
ax1 = nexttile();
hold on;
plot(f, sqrt(flip(-cumtrapz(flip(f), flip(psd_ft.*abs(squeeze(freqresp(G_hac_iff_vc_light_rigid('y', 'ft'), f, 'Hz'))).^2 + ...
psd_xf.*abs(squeeze(freqresp(G_hac_iff_vc_light_rigid('y', 'xf'), f, 'Hz'))).^2)))), '-', ...
'DisplayName', 'Rigid sample');
plot(f, sqrt(flip(-cumtrapz(flip(f), flip(psd_ft.*abs(squeeze(freqresp(G_hac_iff_vc_light_stiff('y', 'ft'), f, 'Hz'))).^2 + ...
psd_xf.*abs(squeeze(freqresp(G_hac_iff_vc_light_stiff('y', 'xf'), f, 'Hz'))).^2)))), '-', ...
'DisplayName', 'Stiff $\omega_s = 200\,$Hz');
plot(f, sqrt(flip(-cumtrapz(flip(f), flip(psd_ft.*abs(squeeze(freqresp(G_hac_iff_vc_light_soft('y', 'ft'), f, 'Hz'))).^2 + ...
psd_xf.*abs(squeeze(freqresp(G_hac_iff_vc_light_soft('y', 'xf'), f, 'Hz'))).^2)))), '-', ...
'DisplayName', 'Soft $\omega_s = 20\,$Hz');
hold off;
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
xticks([1e0, 1e1, 1e2]);
ylabel('CAS of $y$ [m]'); xlabel('Frequency [Hz]');
legend('location', 'southwest', 'FontSize', 8, 'NumColumns', 1);
title('$k_n = 0.01\,N/\mu m$');
ax2 = nexttile();
hold on;
plot(f, sqrt(flip(-cumtrapz(flip(f), flip(psd_ft.*abs(squeeze(freqresp(G_hac_iff_pz_light_rigid('y', 'ft'), f, 'Hz'))).^2 + ...
psd_xf.*abs(squeeze(freqresp(G_hac_iff_pz_light_rigid('y', 'xf'), f, 'Hz'))).^2)))), '-');
psd_xf.*abs(squeeze(freqresp(G_hac_iff_pz_light_rigid('y', 'xf'), f, 'Hz'))).^2)))), '-', ...
'DisplayName', 'Rigid sample');
plot(f, sqrt(flip(-cumtrapz(flip(f), flip(psd_ft.*abs(squeeze(freqresp(G_hac_iff_pz_light_stiff('y', 'ft'), f, 'Hz'))).^2 + ...
psd_xf.*abs(squeeze(freqresp(G_hac_iff_pz_light_stiff('y', 'xf'), f, 'Hz'))).^2)))), '-');
psd_xf.*abs(squeeze(freqresp(G_hac_iff_pz_light_stiff('y', 'xf'), f, 'Hz'))).^2)))), '-', ...
'DisplayName', '$\omega_s = 200\,$Hz');
plot(f, sqrt(flip(-cumtrapz(flip(f), flip(psd_ft.*abs(squeeze(freqresp(G_hac_iff_pz_light_soft('y', 'ft'), f, 'Hz'))).^2 + ...
psd_xf.*abs(squeeze(freqresp(G_hac_iff_pz_light_soft('y', 'xf'), f, 'Hz'))).^2)))), '-');
psd_xf.*abs(squeeze(freqresp(G_hac_iff_pz_light_soft('y', 'xf'), f, 'Hz'))).^2)))), '-', ...
'DisplayName', '$\omega_s = 20\,$Hz');
hold off;
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
ylabel('CAS of $y$ [m]'); xlabel('Frequency [Hz]');
legend('location', 'southwest', 'FontSize', 8, 'NumColumns', 1);
xlim([1, 500]);
xticks([1e0, 1e1, 1e2]);
xlabel('Frequency [Hz]'); set(gca, 'YTickLabel',[]);
title('$k_n = 100\,N/\mu m$');
xlim([1, 500]);
linkaxes([ax1,ax2],'xy');
xlim([1, 500]);
ylim([2e-10, 2e-7])