Rework just before grammar check

This commit is contained in:
2024-10-24 18:53:51 +02:00
parent 09e101fb75
commit 12f4934efc
22 changed files with 1715 additions and 714 deletions

23
matlab/mat/acc_pos.txt Normal file
View File

@@ -0,0 +1,23 @@
23 1.5500e-001 -9.0000e-002 -5.9400e-001
22 0.0000e+000 1.8000e-001 -5.9400e-001
21 -1.5500e-001 -9.0000e-002 -5.9400e-001
20 8.6490e-001 -5.0600e-001 -9.5060e-001
19 8.7500e-001 7.9900e-001 -9.5060e-001
18 -7.3500e-001 8.1400e-001 -9.5060e-001
17 -7.3000e-001 -5.2600e-001 -9.5060e-001
16 2.9500e-001 -4.8100e-001 -7.8560e-001
15 4.5000e-001 5.3400e-001 -7.8560e-001
14 -4.8000e-001 5.3400e-001 -7.8560e-001
13 -3.2000e-001 -4.4600e-001 -7.8560e-001
12 4.7500e-001 -4.1900e-001 -4.2730e-001
11 4.7500e-001 4.2400e-001 -4.2730e-001
10 -4.6500e-001 4.0700e-001 -4.2730e-001
9 -4.7500e-001 -4.1400e-001 -4.2730e-001
8 3.8000e-001 -3.0000e-001 -4.1680e-001
7 4.2000e-001 2.8000e-001 -4.1680e-001
6 -4.2000e-001 2.8000e-001 -4.1680e-001
5 -3.8500e-001 -3.0000e-001 -4.1680e-001
4 6.4000e-002 -6.4000e-002 -2.7000e-001
3 6.4000e-002 6.4000e-002 -2.7000e-001
2 -6.4000e-002 6.4000e-002 -2.7000e-001
1 -6.4000e-002 -6.4000e-002 -2.7000e-001

BIN
matlab/mat/frf_com.mat Normal file

Binary file not shown.

BIN
matlab/mat/frf_matrix.mat Normal file

Binary file not shown.

BIN
matlab/mat/geometry.mat Normal file

Binary file not shown.

Binary file not shown.

BIN
matlab/mat/meas_raw_1.mat Normal file

Binary file not shown.

Binary file not shown.

16
matlab/mat/mode_damps.txt Normal file
View File

@@ -0,0 +1,16 @@
12.20318
11.66888
6.19561
2.79104
2.76253
4.34928
1.25546
3.65470
2.94088
3.19084
1.55526
3.13166
2.76141
1.34304
2.43201
1.38400

16
matlab/mat/mode_freqs.txt Normal file
View File

@@ -0,0 +1,16 @@
11.86509
18.55747
37.82163
39.07850
56.31944
69.78452
72.49325
84.83446
91.26350
105.47266
106.57165
112.67669
124.20538
145.30034
150.52113
165.42632

View File

@@ -0,0 +1,16 @@
4.13559e+003 +6.22828e+003
2.76278e+002 +1.74197e+004
-1.32270e+004 +2.17346e+004
-2.48397e+005 -1.60998e+005
-4.23967e+004 +7.06852e+004
-7.36964e+003 +4.57024e+004
1.37806e+005 +3.00336e+005
-1.31109e+004 +2.81759e+004
5.59259e+003 -4.27543e+004
-5.28869e+004 +6.38436e+003
3.71578e+004 +1.57745e+004
-4.24659e+004 +7.90956e+003
-3.57355e+004 +1.13161e+005
5.24764e+004 -1.45211e+005
1.97228e+005 +2.51758e+005
-3.00273e+005 +3.27201e+005

View File

@@ -0,0 +1,16 @@
4.98475e+005 -2.49344e+005
2.02102e+006 +2.05017e+005
4.96035e+006 +3.45724e+006
-4.12180e+007 +5.98638e+007
2.45891e+007 +1.56880e+007
1.98796e+007 +4.09986e+006
1.37577e+008 -6.10466e+007
1.47532e+007 +7.53272e+006
-2.44115e+007 -3.92655e+006
3.11045e+006 +3.51656e+007
1.09485e+007 -2.47140e+007
4.65546e+006 +3.02251e+007
8.75076e+007 +3.03162e+007
-1.31915e+008 -4.96844e+007
2.42567e+008 -1.80683e+008
3.35742e+008 +3.16782e+008

1104
matlab/mat/mode_shapes.txt Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,18 @@
0.045
0.144
-1.251
0.052
0.258
-0.778
0.000
0.014
-0.600
0.000
-0.005
-0.628
0.000
0.000
-0.580
-0.004
0.006
-0.319

View File

@@ -12,48 +12,77 @@ colors = colororder;
% Location of the Accelerometers
% <<ssec:modal_accelerometers>>
% 4 tri-axis accelerometers are used for each solid body.
% Only 2 could have been used as only 6DOF have to be measured, however, we have chosen to have some *redundancy*.
% The location of the accelerometers fixed to the micro-station is essential as it defines where the dynamics is measured.
% A total of 23 accelerometers are fixed to the six key stages of the micro station: the lower and upper granites, the translation stage, the tilt stage, the spindle and the micro hexapod.
% The position of the accelerometers are visually shown on a CAD model in Figure ref:fig:modal_location_accelerometers and their precise locations with respect to a frame located at the point of interest are summarized in Table ref:tab:modal_position_accelerometers.
% Pictures of the accelerometers fixed to the translation stage and to the micro-hexapod are shown in Figure ref:fig:modal_accelerometer_pictures.
% This could also help us identify measurement problems or flexible modes is present.
% As all key stages of the micro-station are foreseen to behave as solid bodies, only 6 acrshort:dof can be considered per solid body.
% However, it was chosen to use four 3-axis accelerometers (i.e. 12 measured acrshort:dof) for each considered solid body to have some redundancy and to be able to verify the solid body assumption (see Section ref:ssec:modal_solid_body_assumption).
% The position of the accelerometers are:
% - 4 on the first granite
% - 4 on the second granite
% - 4 on top of the translation stage (figure ref:fig:accelerometers_ty)
% - 4 on top of the tilt stage
% - 3 on top of the spindle
% - 4 on top of the hexapod (figure ref:fig:accelerometers_hexapod)
% #+attr_latex: :options [t]{0.60\linewidth}
% #+begin_minipage
% #+name: fig:modal_location_accelerometers
% #+caption: Position of the accelerometers
% #+attr_latex: :width 0.99\linewidth :float nil
% [[file:figs/modal_location_accelerometers.png]]
% #+end_minipage
% \hfill
% #+attr_latex: :options [b]{0.38\linewidth}
% #+begin_minipage
% #+begin_scriptsize
% #+name: tab:modal_position_accelerometers
% #+caption: Positions in mm
% #+attr_latex: :environment tabularx :width \linewidth :placement [b] :align Xccc
% #+attr_latex: :booktabs t :float nil :center nil
% #+RESULTS:
% | | $x$ | $y$ | $z$ |
% |--------------+------+------+------|
% | Low. Granite | -730 | -526 | -951 |
% | Low. Granite | -735 | 814 | -951 |
% | Low. Granite | 875 | 799 | -951 |
% | Low. Granite | 865 | -506 | -951 |
% | Up. Granite | -320 | -446 | -786 |
% | Up. Granite | -480 | 534 | -786 |
% | Up. Granite | 450 | 534 | -786 |
% | Up. Granite | 295 | -481 | -786 |
% | Translation | -475 | -414 | -427 |
% | Translation | -465 | 407 | -427 |
% | Translation | 475 | 424 | -427 |
% | Translation | 475 | -419 | -427 |
% | Tilt | -385 | -300 | -417 |
% | Tilt | -420 | 280 | -417 |
% | Tilt | 420 | 280 | -417 |
% | Tilt | 380 | -300 | -417 |
% | Spindle | -155 | -90 | -594 |
% | Spindle | 0 | 180 | -594 |
% | Spindle | 155 | -90 | -594 |
% | Hexapod | -64 | -64 | -270 |
% | Hexapod | -64 | 64 | -270 |
% | Hexapod | 64 | 64 | -270 |
% | Hexapod | 64 | -64 | -270 |
% #+end_scriptsize
% #+end_minipage
% In total, 23 accelerometers are used: *69 DOFs are thus measured*.
% The precise determination of the position of each accelerometer is done using the SolidWorks model (shown on figure ref:fig:location_accelerometers).
% #+name: fig:accelerometer_pictures
% #+caption: Accelerometers fixed on the micro-station
% #+name: fig:modal_accelerometer_pictures
% #+caption: Accelerometers fixed on the micro-station stages
% #+attr_latex: :options [htbp]
% #+begin_figure
% #+attr_latex: :caption \subcaption{\label{fig:accelerometers_ty}$T_y$ stage}
% #+attr_latex: :caption \subcaption{\label{fig:modal_accelerometers_ty} $T_y$ stage}
% #+attr_latex: :options {0.49\textwidth}
% #+begin_subfigure
% #+attr_latex: :height 6cm
% [[file:figs/accelerometers_ty.jpg]]
% [[file:figs/modal_accelerometers_ty.jpg]]
% #+end_subfigure
% #+attr_latex: :caption \subcaption{\label{fig:accelerometers_hexapod}Micro-Hexapod}
% #+attr_latex: :caption \subcaption{\label{fig:modal_accelerometers_hexapod} Micro-Hexapod}
% #+attr_latex: :options {0.49\textwidth}
% #+begin_subfigure
% #+attr_latex: :height 6cm
% [[file:figs/accelerometers_hexapod.jpg]]
% [[file:figs/modal_accelerometers_hexapod.jpg]]
% #+end_subfigure
% #+end_figure
% #+name: fig:location_accelerometers
% #+caption: Position of the accelerometers using SolidWorks
% #+attr_latex: :width \linewidth
% [[file:figs/location_accelerometers.png]]
% The precise position of all the 23 accelerometer with respect to a frame located at the point of interest (located 270mm above the top platform of the hexapod) are shown in table ref:tab:position_accelerometers.
%% Load Accelerometer positions
acc_pos = readtable('mat/acc_pos.txt', 'ReadVariableNames', false);
@@ -61,59 +90,18 @@ acc_pos = table2array(acc_pos(:, 1:4));
[~, i] = sort(acc_pos(:, 1));
acc_pos = acc_pos(i, 2:4);
% Signal Processing :noexport:
% <<ssec:modal_signal_processing>>
% The measurements are averaged 10 times corresponding to 10 hammer impacts in order to reduce the effect of random noise.
% Windowing is also used on the force and response signals.
% A boxcar window (figure ref:fig:modal_windowing_force_signal) is used for the force signal as once the impact on the structure is done, the measured signal is meaningless.
% The parameters are:
% - *Start*: $3\%$
% - *Stop*: $7\%$
%% Boxcar window used for the force signal
figure;
plot(100*[0, 0.03, 0.03, 0.07, 0.07, 1], [0, 0, 1, 1, 0, 0]);
xlabel('Time [\%]'); ylabel('Amplitude');
xlim([0, 100]); ylim([0, 1]);
% #+name: fig:modal_windowing_force_signal
% #+caption: Boxcar window used for the force signal
% #+RESULTS:
% [[file:figs/modal_windowing_force_signal.png]]
% An exponential window (figure ref:fig:modal_windowing_acc_signal) is used for the response signal as we are measuring transient signals and most of the information is located at the beginning of the signal.
% The parameters are:
% - FlatTop:
% - *Start*: $3\%$
% - *Stop*: $2.96\%$
% - Decreasing point:
% - *X*: $60.4\%$
% - *Y*: $14.7\%$
%% Exponential window used for acceleration signal
x0 = 0.296;
xd = 0.604;
yd = 0.147;
alpha = log(yd)/(x0 - xd);
t = x0:0.01:1.01;
y = exp(-alpha*(t-x0));
figure;
plot(100*[0, 0.03, 0.03, x0, t], [0, 0, 1, 1, y]);
xlabel('Time [\%]'); ylabel('Amplitude');
xlim([0, 100]); ylim([0, 1]);
% Force and Response signals
% <<ssec:modal_measured_signals>>
% The force sensor of the instrumented hammer and the accelerometers signals are shown in the time domain in Figure ref:fig:modal_raw_meas.
% Sharp "impacts" can be seen for the force sensor, indicating wide frequency band excitation.
% For the accelerometer, a much more complex signal can be observed, indicating complex dynamics.
% The "normalized" acrfull:asd of the two signals are computed and shown in Figure ref:fig:modal_asd_acc_force.
% Conclusions based on the time domain signals can be clearly seen in the frequency domain (wide frequency content for the force signal and complex dynamics for the accelerometer).
% Similar results are obtained for all the measured frequency response functions.
%% Load raw data
meas1_raw = load('mat/meas_raw_1.mat');
@@ -126,46 +114,17 @@ impacts = [5.937, 11.228, 16.681, 22.205, 27.350, 32.714, 38.115, 43.888, 50.407
% Time vector [s]
time = linspace(0, meas1_raw.Track1_X_Resolution*length(meas1_raw.Track1), length(meas1_raw.Track1));
% The force sensor and the accelerometers signals are shown in the time domain in Figure ref:fig:modal_raw_meas.
% Sharp "impacts" can be seen for the force sensor, indicating wide frequency band excitation.
% For the accelerometer, many resonances can be seen on the right, indicating complex dynamics
%% Raw measurement of the Accelerometer
figure;
tiledlayout(1, 3, 'TileSpacing', 'Compact', 'Padding', 'None');
ax1 = nexttile([1,2]);
hold on;
plot(time, meas1_raw.Track2, 'DisplayName', 'Acceleration [$m/s^2$]');
plot(time, 1e-3*meas1_raw.Track1, 'DisplayName', 'Force [kN]');
plot(time-22.2, meas1_raw.Track2, 'DisplayName', '$X_{j}$ [$m/s^2$]');
plot(time-22.2, 1e-3*meas1_raw.Track1, 'DisplayName', '$F_{k}$ [kN]');
hold off;
xlabel('Time [s]');
ylabel('Amplitude');
xlim([0, time(end)]);
legend('location', 'northeast', 'FontSize', 8, 'NumColumns', 1);
ax2 = nexttile();
hold on;
plot(time, meas1_raw.Track2);
plot(time, 1e-3*meas1_raw.Track1);
hold off;
xlabel('Time [s]');
set(gca, 'YTickLabel',[]);
xlim([22.19, 22.4]);
linkaxes([ax1,ax2],'y');
xlim([0, 0.2]);
ylim([-2, 2]);
% #+name: fig:modal_raw_meas
% #+caption: Raw measurement of the acceleromter (blue) and of the force sensor at the Hammer tip (red). Zoom on one impact is shown on the right.
% #+RESULTS:
% [[file:figs/modal_raw_meas.png]]
legend('location', 'northeast', 'FontSize', 8, 'NumColumns', 1);
%% Frequency Analysis
Nfft = floor(5.0*Fs); % Number of frequency points
@@ -176,17 +135,11 @@ Noverlap = floor(Nfft/2); % Overlap for frequency analysis
[pxx_force, f] = pwelch(meas1_raw.Track1, win, Noverlap, Nfft, Fs);
[pxx_acc, ~] = pwelch(meas1_raw.Track2, win, Noverlap, Nfft, Fs);
% The "normalized" amplitude spectral density of the two signals are computed and shown in Figure ref:fig:modal_asd_acc_force.
% Conclusions based on the time domain signals can be clearly seen in the frequency domain (wide frequency content for the force signal and complex dynamics for the accelerometer).
%% Normalized Amplitude Spectral Density of the measured force and acceleration
figure;
hold on;
plot(f, sqrt(pxx_force./max(pxx_force(f<200))), 'DisplayName', 'Force');
plot(f, sqrt(pxx_acc./max(pxx_acc(f<200))), 'DisplayName', 'Acceleration');
plot(f, sqrt(pxx_acc./max(pxx_acc(f<200))), 'DisplayName', '$X_{j}$');
plot(f, sqrt(pxx_force./max(pxx_force(f<200))), 'DisplayName', '$F_{k}$');
hold off;
set(gca, 'XScale', 'lin'); set(gca, 'YScale', 'lin');
xlabel('Frequency [Hz]'); ylabel('Normalized Spectral Density');
@@ -197,12 +150,27 @@ legend('location', 'northeast', 'FontSize', 8, 'NumColumns', 1);
% #+name: fig:modal_asd_acc_force
% #+caption: Normalized Amplitude Spectral Density of the measured force and acceleration
% #+RESULTS:
% #+name: fig:modal_raw_meas_asd
% #+caption: Raw measurement of the acceleromter (blue) and of the force sensor at the Hammer tip (red) (\subref{fig:modal_raw_meas}). Computed Amplitude Spectral Density of the two signals (normalized) (\subref{fig:modal_asd_acc_force})
% #+attr_latex: :options [htbp]
% #+begin_figure
% #+attr_latex: :caption \subcaption{\label{fig:modal_raw_meas}Time domain signals}
% #+attr_latex: :options {0.49\textwidth}
% #+begin_subfigure
% #+attr_latex: :width 0.95\linewidth
% [[file:figs/modal_raw_meas.png]]
% #+end_subfigure
% #+attr_latex: :caption \subcaption{\label{fig:modal_asd_acc_force}Amplitude Spectral Density (normalized)}
% #+attr_latex: :options {0.49\textwidth}
% #+begin_subfigure
% #+attr_latex: :width 0.95\linewidth
% [[file:figs/modal_asd_acc_force.png]]
% #+end_subfigure
% #+end_figure
% The frequency response function from the applied force to the measured acceleration can then be computed (Figure ref:fig:modal_frf_acc_force).
% The frequency response function $H_{jk}$ from the applied force $F_{k}$ to the measured acceleration $X_j$ is then computed and shown Figure ref:fig:modal_frf_acc_force.
% The quality of the obtained data can be estimated using the /coherence/ function, which is shown in Figure ref:fig:modal_coh_acc_force.
% Good coherence is obtained from $20\,\text{Hz}$ to $200\,\text{Hz}$ which corresponds to the frequency range of interest.
%% Compute the transfer function and Coherence
@@ -217,16 +185,6 @@ set(gca, 'XScale', 'lin'); set(gca, 'YScale', 'log');
xlim([0, 200]);
xticks([0:20:200]);
% #+name: fig:modal_frf_acc_force
% #+caption: Frequency Response Function between the measured force and acceleration
% #+RESULTS:
% [[file:figs/modal_frf_acc_force.png]]
% The coherence between the input and output signals is also computed and found to be good between 20 and 200Hz (Figure ref:fig:modal_coh_acc_force).
%% Frequency Response Function between the force and the acceleration
figure;
plot(f, coh1);

View File

@@ -10,33 +10,84 @@ addpath('./mat/'); % Path for data
%% Colors for the figures
colors = colororder;
% Frequency Response Matrix
% <<ssec:modal_frf_matrix>>
% All the Frequency Response Functions measured are combined into one big array called the Frequency Response Matrix.
% The frequency response matrix is an $n \times p \times q$ matrix with:
% - $n$ the number of measurements: $23 \times 3$ (23 accelerometers measuring 3 directions each)
% - $p$ the number of excitation inputs: $3$
% - $q$ the number of frequency points $\omega_i$
% Thus, the FRF matrix is an $69 \times 3 \times 801$ matrix.
% #+name: fig:modal_local_to_global_coordinates
% #+caption: Schematic of the measured motions of a solid body
% #+RESULTS:
% [[file:figs/modal_local_to_global_coordinates.png]]
% For each frequency point $\omega_i$, a 2D matrix is obtained:
% \begin{equation}
% \text{FRF}(\omega_i) = \begin{bmatrix}
% \frac{D_{1_x}}{F_x}(\omega_i) & \frac{D_{1_x}}{F_y}(\omega_i) & \frac{D_{1_x}}{F_z}(\omega_i) \\
% \frac{D_{1_y}}{F_x}(\omega_i) & \frac{D_{1_y}}{F_y}(\omega_i) & \frac{D_{1_y}}{F_z}(\omega_i) \\
% \frac{D_{1_z}}{F_x}(\omega_i) & \frac{D_{1_z}}{F_y}(\omega_i) & \frac{D_{1_z}}{F_z}(\omega_i) \\
% \frac{D_{2_x}}{F_x}(\omega_i) & \frac{D_{2_x}}{F_y}(\omega_i) & \frac{D_{2_x}}{F_z}(\omega_i) \\
% \vdots & \vdots & \vdots \\
% \frac{D_{23_z}}{F_x}(\omega_i) & \frac{D_{23_z}}{F_y}(\omega_i) & \frac{D_{23_z}}{F_z}(\omega_i) \\
% The motion of the rigid body of figure ref:fig:modal_local_to_global_coordinates can be described by its displacement $\vec{\delta}p = [\delta p_x,\ \delta p_y,\ \delta p_z]$ and (small) rotations $[\delta \Omega_x,\ \delta \Omega_y,\ \delta \Omega_z]$ with respect to a reference frame $\{O\}$.
% The motion $\vec{\delta} p_{i}$ of a point $p_i$ can be computed from $\vec{\delta} p$ and $\bm{\delta \Omega}$ using equation eqref:eq:modal_compute_point_response, with $\bm{\delta\Omega}$ defined in equation eqref:eq:modal_rotation_matrix.
% \begin{equation}\label{eq:modal_compute_point_response}
% \vec{\delta} p_{i} &= \vec{\delta} p + \bm{\delta \Omega} \cdot \vec{p}_{i} \\
% \end{equation}
% \begin{equation}\label{eq:modal_rotation_matrix}
% \bm{\delta\Omega} = \begin{bmatrix}
% 0 & -\delta\Omega_z & \delta\Omega_y \\
% \delta\Omega_z & 0 & -\delta\Omega_x \\
% -\delta\Omega_y & \delta\Omega_x & 0
% \end{bmatrix}
% \end{equation}
% Writing this in a matrix form for the four points gives eqref:eq:modal_cart_to_acc.
% \begin{equation}\label{eq:modal_cart_to_acc}
% \left[\begin{array}{c}
% \delta p_{1x} \\ \delta p_{1y} \\ \delta p_{1z} \\\hline \vdots \\\hline \delta p_{4x} \\ \delta p_{4y} \\ \delta p_{4z}
% \end{array}\right] =
% \left[\begin{array}{ccc|ccc}
% 1 & 0 & 0 & 0 & p_{1z} & -p_{1y} \\
% 0 & 1 & 0 & -p_{1z} & 0 & p_{1x} \\
% 0 & 0 & 1 & p_{1y} & -p_{1x} & 0 \\ \hline
% & \vdots & & & \vdots & \\ \hline
% 1 & 0 & 0 & 0 & p_{4z} & -p_{4y} \\
% 0 & 1 & 0 & -p_{4z} & 0 & p_{4x} \\
% 0 & 0 & 1 & p_{4y} & -p_{4x} & 0
% \end{array}\right] \left[\begin{array}{c}
% \delta p_x \\ \delta p_y \\ \delta p_z \\ \hline \delta\Omega_x \\ \delta\Omega_y \\ \delta\Omega_z
% \end{array}\right]
% \end{equation}
% Provided that the four sensors are properly located, the system of equation eqref:eq:modal_cart_to_acc can be solved by matrix inversion[fn:5].
% The motion of the solid body expressed in a chosen frame $\{O\}$ can be determined using equation eqref:eq:modal_determine_global_disp.
% Note that this matrix inversion is equivalent to resolving a mean square problem.
% Therefore, having more accelerometers permits to have a better approximation of the motion of the solid body.
% \begin{equation}
% \left[\begin{array}{c}
% \delta p_x \\ \delta p_y \\ \delta p_z \\ \hline \delta\Omega_x \\ \delta\Omega_y \\ \delta\Omega_z
% \end{array}\right] =
% \left[\begin{array}{ccc|ccc}
% 1 & 0 & 0 & 0 & p_{1z} & -p_{1y} \\
% 0 & 1 & 0 & -p_{1z} & 0 & p_{1x} \\
% 0 & 0 & 1 & p_{1y} & -p_{1x} & 0 \\ \hline
% & \vdots & & & \vdots & \\ \hline
% 1 & 0 & 0 & 0 & p_{4z} & -p_{4y} \\
% 0 & 1 & 0 & -p_{4z} & 0 & p_{4x} \\
% 0 & 0 & 1 & p_{4y} & -p_{4x} & 0
% \end{array}\right]^{-1} \left[\begin{array}{c}
% \delta p_{1x} \\ \delta p_{1y} \\ \delta p_{1z} \\\hline \vdots \\\hline \delta p_{4x} \\ \delta p_{4y} \\ \delta p_{4z}
% \end{array}\right] \label{eq:modal_determine_global_disp}
% \end{equation}
% From the CAD model, the position of the center of mass of each considered solid body is computed (see Table ref:tab:modal_com_solid_bodies).
% Then, the position of each accelerometer with respect to the center of mass of the corresponding solid body can easily be derived.
%% Load frequency response matrix
load('frf_matrix.mat', 'freqs', 'frf');
%% Load Accelerometer positions
acc_pos = readtable('mat/acc_pos.txt', 'ReadVariableNames', false);
acc_pos = table2array(acc_pos(:, 1:4));
[~, i] = sort(acc_pos(:, 1));
acc_pos = acc_pos(i, 2:4);
%% Accelerometers ID connected to each solid body
solids = {};
solids.gbot = [17, 18, 19, 20]; % bottom granite
@@ -52,189 +103,29 @@ solid_names = fields(solids);
%% Save the acceleromter positions are well as the solid bodies
save('mat/geometry.mat', 'solids', 'solid_names', 'acc_pos');
% #+name: fig:aligned_accelerometers
% #+caption: Aligned measurement of the motion of a solid body
% #+RESULTS:
% [[file:figs/aligned_accelerometers.png]]
% The motion of the rigid body of figure ref:fig:aligned_accelerometers is defined by its displacement $\delta p$ and rotation $\vec{\Omega}$ with respect to the reference frame $\{O\}$.
% The motions at points $1$ and $2$ are:
% \begin{align*}
% \delta p_1 &= \delta p + \Omega \times p_1 \\
% \delta p_2 &= \delta p + \Omega \times p_2
% \end{align*}
% Taking only the $x$ direction:
% \begin{align*}
% \delta p_{x1} &= \delta p_x + \Omega_y p_{z1} - \Omega_z p_{y1} \\
% \delta p_{x2} &= \delta p_x + \Omega_y p_{z2} - \Omega_z p_{y2}
% \end{align*}
% However, we have $p_{1y} = p_{2y}$ and $p_{1z} = p_{2z}$ because of the co-linearity of the two sensors in the $x$ direction, and thus we obtain
% \begin{equation}
% \delta p_{x1} = \delta p_{x2}
% \end{equation}
% #+begin_important
% Two sensors that are measuring the motion of a rigid body in the direction of the line linking the two sensors should measure the same quantity.
% #+end_important
% We can verify that the rigid body assumption is correct by comparing the measurement of the sensors.
% From the table ref:tab:position_accelerometers, we can guess which sensors will give the same results in the X and Y directions.
% Comparison of such measurements in the X direction is shown on figure ref:fig:modal_solid_body_comp_x_dir.
% Similar result is obtained for the Y direction.
meas_dir = 1; % X
exc_dir = 1; % X
% Pair of accelerometers aligned in the X direction
acc_i = [1 , 4 ;
2 , 3 ;
5 , 8 ;
6 , 7 ;
9 , 12;
10, 11;
14, 15;
18, 19;
21, 23];
%% Comparaison of measured frequency response function for in the X directions for accelerometers aligned along X
figure;
tiledlayout(3, 3, 'TileSpacing', 'Compact', 'Padding', 'None');
for i = 1:size(acc_i, 1)
nexttile();
hold on;
plot(freqs, abs(squeeze(frf(meas_dir+3*(acc_i(i, 1)-1), exc_dir, :))), ...
'DisplayName', sprintf('%i', acc_i(i, 1)))
plot(freqs, abs(squeeze(frf(meas_dir+3*(acc_i(i, 2)-1), exc_dir, :))), ...
'DisplayName', sprintf('%i', acc_i(i, 2)))
hold off;
set(gca, 'XScale', 'lin'); set(gca, 'YScale', 'log');
if i > 6
xlabel('Frequency [Hz]');
legend('location', 'northeast', 'FontSize', 8, 'NumColumns', 1);
else
set(gca, 'XTickLabel',[]);
legend('location', 'southeast', 'FontSize', 8, 'NumColumns', 1);
end
if rem(i, 3) == 1
ylabel('Amplitude');
else
set(gca, 'YTickLabel',[]);
end
xlim([0, 200]); ylim([1e-5, 2e-2]);
end
% TODO Verification of the principle of reciprocity :noexport:
% <<ssec:modal_reciprocity_principle>>
% Because we expect our system to follow the principle of reciprocity.
% That is to say the response $X_j$ at some degree of freedom $j$ due to a force $F_k$ applied on DOF $k$ should be the same as the response $X_k$ due to a force $F_j$:
% \[ H_{jk} = \frac{X_j}{F_k} = \frac{X_k}{F_j} = H_{kj} \]
% This comes from the fact that we expect to have symmetric mass, stiffness and damping matrices.
% In order to access the quality of the data and the validity of the measured FRF, we then check that the reciprocity between $H_{jk}$ and $H_{kj}$ is of an acceptable level.
% We can verify this reciprocity using 3 different pairs of response/force.
dir_names = {'X', 'Y', 'Z'};
figure;
for i = 1:3
subplot(3, 1, i)
a = mod(i, 3)+1;
b = mod(i-2, 3)+1;
hold on;
plot(freqs, abs(squeeze(frf(3*(11-1)+a, b, :))), 'DisplayName', sprintf('$\\frac{F_%s}{D_%s}$', dir_names{a}, dir_names{b}));
plot(freqs, abs(squeeze(frf(3*(11-1)+b, a, :))), 'DisplayName', sprintf('$\\frac{F_%s}{D_%s}$', dir_names{b}, dir_names{a}));
hold off;
set(gca, 'XScale', 'lin'); set(gca, 'YScale', 'log');
if i == 3
xlabel('Frequency [Hz]');
else
set(gca, 'XTickLabel',[]);
end
if i == 2
ylabel('Amplitude [$\frac{m/s^2}{N}$]');
end
xlim([0, 200]);
legend('location', 'northwest');
end
% From accelerometer DOFs to solid body DOFs - Matlab Implementation
% First, we initialize a new FRF matrix =FRFs_O= which is an $n \times p \times q$ with:
% - $n$ is the number of DOFs of the considered 6 solid-bodies: $6 \times 6 = 36$
% - $p$ is the number of excitation inputs: $3$
% - $q$ is the number of frequency points $\omega_i$
% #+begin_important
% For each frequency point $\omega_i$, the FRF matrix =FRFs_O= is a $n\times p$ matrix:
% \begin{equation}
% \text{FRF}_\text{O}(\omega_i) = \begin{bmatrix}
% \frac{D_{1,T_x}}{F_x}(\omega_i) & \frac{D_{1,T_x}}{F_y}(\omega_i) & \frac{D_{1,T_x}}{F_z}(\omega_i) \\
% \frac{D_{1,T_y}}{F_x}(\omega_i) & \frac{D_{1,T_y}}{F_y}(\omega_i) & \frac{D_{1,T_y}}{F_z}(\omega_i) \\
% \frac{D_{1,T_z}}{F_x}(\omega_i) & \frac{D_{1,T_z}}{F_y}(\omega_i) & \frac{D_{1,T_z}}{F_z}(\omega_i) \\
% \frac{D_{1,R_x}}{F_x}(\omega_i) & \frac{D_{1,R_x}}{F_y}(\omega_i) & \frac{D_{1,R_x}}{F_z}(\omega_i) \\
% \frac{D_{1,R_y}}{F_x}(\omega_i) & \frac{D_{1,R_y}}{F_y}(\omega_i) & \frac{D_{1,R_y}}{F_z}(\omega_i) \\
% \frac{D_{1,R_z}}{F_x}(\omega_i) & \frac{D_{1,R_z}}{F_y}(\omega_i) & \frac{D_{1,R_z}}{F_z}(\omega_i) \\
% \frac{D_{2,T_x}}{F_x}(\omega_i) & \frac{D_{2,T_x}}{F_y}(\omega_i) & \frac{D_{2,T_x}}{F_z}(\omega_i) \\
% \vdots & \vdots & \vdots \\
% \frac{D_{6,R_z}}{F_x}(\omega_i) & \frac{D_{6,R_z}}{F_y}(\omega_i) & \frac{D_{6,R_z}}{F_z}(\omega_i)
% \end{bmatrix}
% \end{equation}
% where $D_i$ corresponds to the solid body number i.
% #+end_important
% Then, as we know the positions of the accelerometers on each solid body, and we have the response of those accelerometers, we can use the equations derived in the previous section to determine the response of each solid body expressed in the frame $\{O\}$.
FRFs_O = zeros(length(solid_names)*6, 3, 801);
for solid_i = 1:length(solid_names)
solids_i = solids.(solid_names{solid_i});
A = zeros(3*length(solids_i), 6);
for i = 1:length(solids_i)
acc_i = solids_i(i);
A(3*(i-1)+1:3*i, 1:3) = eye(3);
A(3*(i-1)+1:3*i, 4:6) = [ 0 acc_pos(acc_i, 3) -acc_pos(acc_i, 2) ;
-acc_pos(acc_i, 3) 0 acc_pos(acc_i, 1) ;
acc_pos(acc_i, 2) -acc_pos(acc_i, 1) 0];
end
for exc_dir = 1:3
FRFs_O((solid_i-1)*6+1:solid_i*6, exc_dir, :) = A\squeeze(FRFs((solids_i(1)-1)*3+1:solids_i(end)*3, exc_dir, :));
end
end
% Center of Mass of each solid body
% From solidworks, we can export the position of the center of mass of each solid body considered.
% These are summarized in Table ref:tab:modal_com_solid_bodies
%% Extract the CoM of considered solid bodies
model_com = reshape(table2array(readtable('mat/model_solidworks_com.txt', 'ReadVariableNames', false)), [3, 6]);
% From accelerometer DOFs to solid body DOFs - Expressed at the CoM
% First, we initialize a new FRF matrix which is an $n \times p \times q$ with:
% - $n$ is the number of DOFs of the considered 6 solid-bodies: $6 \times 6 = 36$
% - $p$ is the number of excitation inputs: $3$
% - $q$ is the number of frequency points $\omega_i$
% #+begin_important
% For each frequency point $\omega_i$, the FRF matrix is a $n\times p$ matrix:
% \begin{equation}
% \text{FRF}_\text{CoM}(\omega_i) = \begin{bmatrix}
% #+name: tab:modal_com_solid_bodies
% #+caption: Center of mass of considered solid bodies with respect to the "point of interest"
% #+attr_latex: :environment tabularx :width 0.6\linewidth :align lXXX
% #+attr_latex: :center t :booktabs t
% #+RESULTS:
% | | $X$ [mm] | $Y$ [mm] | $Z$ [mm] |
% |-------------------+----------+----------+----------|
% | Bottom Granite | 45 | 144 | -1251 |
% | Top granite | 52 | 258 | -778 |
% | Translation stage | 0 | 14 | -600 |
% | Tilt Stage | 0 | -5 | -628 |
% | Spindle | 0 | 0 | -580 |
% | Hexapod | -4 | 6 | -319 |
% Using eqref:eq:modal_determine_global_disp, the frequency response matrix $\mathbf{H}_\text{CoM}$ eqref:eq:modal_frf_matrix_com expressing the response at the center of mass of each solid body $D_i$ ($i$ from $1$ to $6$ for the $6$ considered solid bodies) can be computed from the initial acrshort:frf matrix $\mathbf{H}$.
% \begin{equation}\label{eq:modal_frf_matrix_com}
% \mathbf{H}_\text{CoM}(\omega_i) = \begin{bmatrix}
% \frac{D_{1,T_x}}{F_x}(\omega_i) & \frac{D_{1,T_x}}{F_y}(\omega_i) & \frac{D_{1,T_x}}{F_z}(\omega_i) \\
% \frac{D_{1,T_y}}{F_x}(\omega_i) & \frac{D_{1,T_y}}{F_y}(\omega_i) & \frac{D_{1,T_y}}{F_z}(\omega_i) \\
% \frac{D_{1,T_z}}{F_x}(\omega_i) & \frac{D_{1,T_z}}{F_y}(\omega_i) & \frac{D_{1,T_z}}{F_z}(\omega_i) \\
@@ -246,14 +137,10 @@ model_com = reshape(table2array(readtable('mat/model_solidworks_com.txt', 'ReadV
% \frac{D_{6,R_z}}{F_x}(\omega_i) & \frac{D_{6,R_z}}{F_y}(\omega_i) & \frac{D_{6,R_z}}{F_z}(\omega_i)
% \end{bmatrix}
% \end{equation}
% where 1, 2, ..., 6 corresponds to the 6 solid bodies.
% #+end_important
% Then, as we know the positions of the accelerometers on each solid body, and we have the response of those accelerometers, we can use the equations derived in the previous section to determine the response of each solid body expressed in their center of mass.
%% Frequency Response Matrix - Response expressed at the CoM of the solid bodies
FRFs_CoM = zeros(length(solid_names)*6, 3, 801);
frfs_CoM = zeros(length(solid_names)*6, 3, 801);
for solid_i = 1:length(solid_names)
% Number of accelerometers fixed to this solid body
@@ -273,43 +160,30 @@ for solid_i = 1:length(solid_names)
end
for exc_dir = 1:3
FRFs_CoM((solid_i-1)*6+1:solid_i*6, exc_dir, :) = A\squeeze(frf((solids_i(1)-1)*3+1:solids_i(end)*3, exc_dir, :));
frfs_CoM((solid_i-1)*6+1:solid_i*6, exc_dir, :) = A\squeeze(frf((solids_i(1)-1)*3+1:solids_i(end)*3, exc_dir, :));
end
end
%% Save the computed FRF at the CoM
save('mat/frf_com.mat', 'FRFs_CoM');
save('mat/frf_com.mat', 'frfs_CoM');
% Verify that we find the original FRF from the FRF in the global coordinates
% We have computed the Frequency Response Functions Matrix representing the response of the 6 solid bodies in their 6 DOFs with respect to their center of mass.
% Verification of solid body assumption
% <<ssec:modal_solid_body_assumption>>
% From the response of one body in its 6 DOFs, we should be able to compute the FRF of each of its accelerometer fixed to it during the measurement, supposing that this stage is a solid body.
% From the response of one solid body expressed by its 6 acrshortpl:dof (i.e. from $\mathbf{H}_{\text{CoM}}$), and using equation eqref:eq:modal_cart_to_acc, it is possible to compute the response of the same solid body at any considered position.
% In particular, the response at the location of the four accelerometers can be computed and compared with the original measurements $\mathbf{H}$.
% This is what is here done to check if solid body assumption is correct in the frequency band of interest.
% We can then compare the result with the original measurements.
% This will help us to determine if:
% - the previous inversion used is correct
% - the solid body assumption is correct in the frequency band of interest
% From the translation $\delta p$ and rotation $\delta \Omega$ of a solid body and the positions $p_i$ of the accelerometers attached to it, we can compute the response that would have been measured by the accelerometers using the following formula:
% \begin{align*}
% \delta p_1 &= \delta p + \delta\Omega p_1\\
% \delta p_2 &= \delta p + \delta\Omega p_2\\
% \delta p_3 &= \delta p + \delta\Omega p_3\\
% \delta p_4 &= \delta p + \delta\Omega p_4
% \end{align*}
% Thus, we can obtain the FRF matrix =FRFs_A= that gives the responses of the accelerometers to the forces applied by the hammer.
% It is implemented in matlab as follow:
FRFs_A = zeros(size(frf));
%% Compute the FRF at the accelerometer location from the CoM reponses
frfs_A = zeros(size(frf));
% For each excitation direction
for exc_dir = 1:3
% For each solid
for solid_i = 1:length(solid_names)
v0 = squeeze(FRFs_CoM((solid_i-1)*6+1:(solid_i-1)*6+3, exc_dir, :));
W0 = squeeze(FRFs_CoM((solid_i-1)*6+4:(solid_i-1)*6+6, exc_dir, :));
v0 = squeeze(frfs_CoM((solid_i-1)*6+1:(solid_i-1)*6+3, exc_dir, :));
W0 = squeeze(frfs_CoM((solid_i-1)*6+4:(solid_i-1)*6+6, exc_dir, :));
% For each accelerometer attached to the current solid
for acc_i = solids.(solid_names{solid_i})
@@ -318,20 +192,17 @@ for exc_dir = 1:3
% pos = acc_pos(acc_i, :).';
posX = [0 pos(3) -pos(2); -pos(3) 0 pos(1) ; pos(2) -pos(1) 0];
FRFs_A(3*(acc_i-1)+1:3*(acc_i-1)+3, exc_dir, :) = v0 + posX*W0;
frfs_A(3*(acc_i-1)+1:3*(acc_i-1)+3, exc_dir, :) = v0 + posX*W0;
end
end
end
% We then compare the original FRF measured for each accelerometer =FRFs= with the "recovered" FRF =FRFs_A= from the global FRF matrix in the common frame.
% The FRF for the 4 accelerometers on the Hexapod are compared on figure ref:fig:recovered_frf_comparison_hexa.
% All the FRF are matching very well in all the frequency range displayed.
% The FRF for accelerometers located on the translation stage are compared on figure ref:fig:recovered_frf_comparison_ty.
% The FRF are matching well until 100Hz.
% The comparison is made for the 4 accelerometers fixed to the micro-hexapod (Figure ref:fig:modal_comp_acc_solid_body_frf).
% The original frequency response functions and the ones computed from the CoM responses are well matching in the frequency range of interested.
% Similar results are obtained for the other solid bodies, indicating that the solid body assumption is valid, and that a multi-body model can be used to represent the dynamics of the micro-station.
% This also validates the reduction of the number of degrees of freedom from 69 (23 accelerometers with each 3 acrshort:dof) to 36 (6 solid bodies with 6 acrshort:dof).
%% Comparaison of the original accelerometer response and reconstructed response from the solid body response
@@ -344,7 +215,7 @@ exc_dir = 1; % Excited direction
accs_i = solids.(solid_names{solid_i}); % Accelerometers fixed to this solid body
figure;
tiledlayout(2, 2, 'TileSpacing', 'Compact', 'Padding', 'None');
tiledlayout(2, 2, 'TileSpacing', 'Tight', 'Padding', 'None');
for i = 1:length(accs_i)
acc_i = accs_i(i);
@@ -356,7 +227,7 @@ for i = 1:length(accs_i)
end
set(gca,'ColorOrderIndex',1)
for dir_i = 1:3
plot(freqs, abs(squeeze(FRFs_A(3*(acc_i-1)+dir_i, exc_dir, :))), '--', 'HandleVisibility', 'off');
plot(freqs, abs(squeeze(frfs_A(3*(acc_i-1)+dir_i, exc_dir, :))), '--', 'HandleVisibility', 'off');
end
hold off;
@@ -372,7 +243,8 @@ for i = 1:length(accs_i)
set(gca, 'YTickLabel',[]);
end
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
xlim([5, 200]); ylim([1e-6, 1e-1]);
legend('location', 'northwest', 'FontSize', 8, 'NumColumns', 1);
set(gca, 'XScale', 'lin'); set(gca, 'YScale', 'log');
xlim([0, 200]); ylim([1e-6, 3e-2]);
xticks([0:20:200]);
legend('location', 'southeast', 'FontSize', 8, 'NumColumns', 1);
end

View File

@@ -10,32 +10,29 @@ addpath('./mat/'); % Path for data
%% Colors for the figures
colors = colororder;
% Singular Value Decomposition - Modal Indication Function
% The Mode Indicator Functions are usually used on $n\times p$ FRF matrix where $n$ is a relatively large number of measurement DOFs and $p$ is the number of excitation DOFs, typically 3 or 4.
% Number of modes determination
% <<ssec:modal_number_of_modes>>
% The acrshort:mif is here applied to the $n\times p$ acrshort:frf matrix where $n$ is a relatively large number of measurement DOFs (here $n=69$) and $p$ is the number of excitation DOFs (here $p=3$).
% In these methods, the frequency dependent FRF matrix is subjected to a singular value decomposition analysis which thus yields a small number (3 or 4) of singular values, these also being frequency dependent.
% The complex modal indication function is defined in equation eqref:eq:modal_cmif where the diagonal matrix $\Sigma$ is obtained from a acrlong:svd of the acrshort:frf matrix as shown in equation eqref:eq:modal_svd.
% \begin{equation} \label{eq:modal_cmif}
% [CMIF(\omega)]_{p\times p} = [\Sigma(\omega)]_{p\times n}^T [\Sigma(\omega)]_{n\times p}
% \end{equation}
% These methods are used to *determine the number of modes* present in a given frequency range, to *identify repeated natural frequencies* and to pre-process the FRF data prior to modal analysis.
% \begin{equation} \label{eq:modal_svd}
% [H(\omega)]_{n\times p} = [U(\omega)]_{n\times n} [\Sigma(\omega)]_{n\times p} [V(\omega)]_{p\times p}^H
% \end{equation}
% From the documentation of the modal software:
% #+begin_quote
% The MIF consist of the singular values of the Frequency response function matrix. The number of MIFs equals the number of excitations.
% By the powerful singular value decomposition, the real signal space is separated from the noise space. Therefore, the MIFs exhibit the modes effectively.
% A peak in the MIFs plot usually indicate the existence of a structural mode, and two peaks at the same frequency point means the existence of two repeated modes.
% Moreover, the magnitude of the MIFs implies the strength of the a mode.
% #+end_quote
% The acrshort:mif therefore yields to $p$ values that are also frequency dependent.
% A peak in the acrshort:mif plot indicates the presence of a mode.
% Repeated modes can also be detected by multiple singular values are having peaks at the same frequency.
% The obtained acrshort:mif is shown on Figure ref:fig:modal_indication_function.
% A total of 16 modes are found between 0 and $200\,\text{Hz}$.
% The obtained natural frequencies and associated modal damping are summarized in Table ref:tab:modal_obtained_modes_freqs_damps.
% #+begin_important
% The *Complex Mode Indicator Function* is defined simply by the SVD of the FRF (sub) matrix:
% \begin{align*}
% [H(\omega)]_{n\times p} &= [U(\omega)]_{n\times n} [\Sigma(\omega)]_{n\times p} [V(\omega)]_{p\times p}^H\\
% [CMIF(\omega)]_{p\times p} &= [\Sigma(\omega)]_{p\times n}^T [\Sigma(\omega)]_{n\times p}
% \end{align*}
% #+end_important
% We compute the Complex Mode Indicator Function.
% The result is shown on Figure ref:fig:modal_indication_function.
%% Load frequency response matrix
load('frf_matrix.mat', 'freqs', 'frf');
%% Computation of the modal indication function
MIF = zeros(size(frf, 2), size(frf, 2), size(frf, 3));
@@ -58,35 +55,31 @@ xticks([0:20:200]);
xlim([0, 200]);
ylim([1e-6, 2e-2]);
% Composite Response Function
% An alternative is the Composite Response Function $HH(\omega)$ defined as the sum of all the measured FRF:
% \begin{equation}
% HH(\omega) = \sum_j\sum_kH_{jk}(\omega)
% Verification of the modal model validity
% <<ssec:modal_model_validity>>
% In order to check the validity of the modal model, the complete $n \times n$ acrshort:frf matrix $\mathbf{H}_{\text{syn}}$ is first synthesized from the modal parameters.
% Then, the elements of this acrshort:frf matrix $\mathbf{H}_{\text{syn}}$ that were already measured can be compared with the measured acrshort:frf matrix $\mathbf{H}$.
% In order to synthesize the full acrshort:frf matrix, the eigenvectors $\phi_r$ are first organized in a matrix from as shown in equation eqref:eq:modal_eigvector_matrix.
% \begin{equation}\label{eq:modal_eigvector_matrix}
% \Phi = \begin{bmatrix}
% & & & & &\\
% \phi_1 & \dots & \phi_N & \phi_1^* & \dots & \phi_N^* \\
% & & & & &
% \end{bmatrix}_{n \times 2m}
% \end{equation}
% Instead, we choose here to use the sum of the norms of the measured frf:
% \begin{equation}
% HH(\omega) = \sum_j\sum_k \left|H_{jk}(\omega) \right|
% The full acrshort:frf matrix $\mathbf{H}_{\text{syn}}$ can be synthesize using eqref:eq:modal_synthesized_frf.
% \begin{equation}\label{eq:modal_synthesized_frf}
% [\mathbf{H}_{\text{syn}}(\omega)]_{n\times n} = [\Phi]_{n\times2m} [\mathbf{H}_{\text{mod}}(\omega)]_{2m\times2m} [\Phi]_{2m\times n}^T
% \end{equation}
% The result is shown on figure ref:fig:modal_composite_reponse_function.
%% Composite Response Function
figure;
hold on;
plot(freqs, squeeze(sum(sum(abs(frf)))), '-k');
hold off;
xlabel('Frequency [Hz]'); ylabel('Amplitude');
xlim([0, 200]);
xticks([0:20:200]);
% Importation of the modal parameters on Matlab
% The obtained modal parameters are:
% - Resonance frequencies in Hertz
% - Modal damping ratio in percentage
% - (complex) Modes shapes for each measured DoF
% - Modal A and modal B which are parameters important for further normalization
% With $\mathbf{H}_{\text{mod}}(\omega)$ a diagonal matrix representing the response of the different modes eqref:eq:modal_modal_resp.
% \begin{equation}\label{eq:modal_modal_resp}
% \mathbf{H}_{\text{mod}}(\omega) = \text{diag}\left(\frac{1}{a_1 (j\omega - s_1)},\ \dots,\ \frac{1}{a_m (j\omega - s_m)}, \frac{1}{a_1^* (j\omega - s_1^*)},\ \dots,\ \frac{1}{a_m^* (j\omega - s_m^*)} \right)_{2m\times 2m}
% \end{equation}
%% Load modal parameters
@@ -123,149 +116,91 @@ for mod_i = 1:mod_n
end
end
% Modal Matrices
% We would like to arrange the obtained modal parameters into two modal matrices:
% \[ \Lambda = \begin{bmatrix}
% s_1 & & 0 \\
% & \ddots & \\
% 0 & & s_N
% \end{bmatrix}_{N \times N}; \quad \Psi = \begin{bmatrix}
% & & \\
% \{\psi_1\} & \dots & \{\psi_N\} \\
% & &
% \end{bmatrix}_{M \times N} \]
% \[ \{\psi_i\} = \begin{Bmatrix} \psi_{i, 1_x} & \psi_{i, 1_y} & \psi_{i, 1_z} & \psi_{i, 2_x} & \dots & \psi_{i, 23_z} \end{Bmatrix}^T \]
% $M$ is the number of DoF: here it is $23 \times 3 = 69$.
% $N$ is the number of mode
eigen_val_M = diag(2*pi*freqs_m.*(-damps_m/100 + j*sqrt(1 - (damps_m/100).^2)));
eigen_vec_M = reshape(mode_shapes, [mod_n, acc_n*dir_n]).';
% Each eigen vector is normalized: $\| \{\psi_i\} \|_2 = 1$
% However, the eigen values and eigen vectors appears as complex conjugates:
% \[ s_r, s_r^*, \{\psi\}_r, \{\psi\}_r^*, \quad r = 1, N \]
% In the end, they are $2N$ eigen values.
% We then build two extended eigen matrices as follow:
% \[ \mathcal{S} = \begin{bmatrix}
% s_1 & & & & & \\
% & \ddots & & & 0 & \\
% & & s_N & & & \\
% & & & s_1^* & & \\
% & 0 & & & \ddots & \\
% & & & & & s_N^*
% \end{bmatrix}_{2N \times 2N}; \quad \Phi = \begin{bmatrix}
% & & & & &\\
% \{\psi_1\} & \dots & \{\psi_N\} & \{\psi_1^*\} & \dots & \{\psi_N^*\} \\
% & & & & &
% \end{bmatrix}_{M \times 2N} \]
%% Create the eigenvalue and eigenvector matrices
eigen_val_M = diag(2*pi*freqs_m.*(-damps_m/100 + j*sqrt(1 - (damps_m/100).^2))); % Lambda = diagonal matrix
eigen_vec_M = reshape(mode_shapes, [mod_n, acc_n*dir_n]).'; % Phi, vecnorm(eigen_vec_M) = 1
% Add complex conjugate eigenvalues and eigenvectors
eigen_val_ext_M = blkdiag(eigen_val_M, conj(eigen_val_M));
eigen_vec_ext_M = [eigen_vec_M, conj(eigen_vec_M)];
% We also build the Modal A and Modal B matrices:
% \begin{equation}
% A = \begin{bmatrix}
% a_1 & & 0 \\
% & \ddots & \\
% 0 & & a_N
% \end{bmatrix}_{N \times N}; \quad B = \begin{bmatrix}
% b_1 & & 0 \\
% & \ddots & \\
% 0 & & b_N
% \end{bmatrix}_{N \times N}
% \end{equation}
% With $a_i$ is the "Modal A" parameter linked to mode i.
%% "Modal A" and "Modal B" matrices
modal_a_M = diag(complex(modal_a(:, 1), modal_a(:, 2)));
modal_b_M = diag(complex(modal_b(:, 1), modal_b(:, 2)));
modal_a_ext_M = blkdiag(modal_a_M, conj(modal_a_M));
modal_b_ext_M = blkdiag(modal_b_M, conj(modal_b_M));
% Matlab Implementation
%% Synthesize the full FRF matrix from the modal model
Hsyn = zeros(acc_n*dir_n, acc_n*dir_n, length(freqs));
for i = 1:length(freqs)
Hsyn(:, :, i) = eigen_vec_ext_M*((j*2*pi*freqs(i)).^2*inv(modal_a_ext_M)/(diag(j*2*pi*freqs(i) - diag(eigen_val_ext_M))))*eigen_vec_ext_M.';
Hsyn(:, :, i) = eigen_vec_ext_M*diag(1./(diag(modal_a_ext_M).*(j*2*pi*freqs(i) - diag(eigen_val_ext_M))))*eigen_vec_ext_M.';
end
% Because the synthesize frequency response functions are representing the displacement response in $[m/N]$, we multiply each element of the FRF matrix by $(j \omega)^2$ in order to obtain the acceleration response in $[m/s^2/N]$.
%% Derivate two times to to have the acceleration response
for i = 1:size(Hsyn, 1)
Hsyn(i, :, :) = squeeze(Hsyn(i, :, :)).*(j*2*pi*freqs).^2;
end
% Original and Synthesize FRF matrix comparison
acc_o = 1; dir_o = 1; dir_i = 1;
% The comparison between the original measured frequency response functions and the synthesized ones from the modal model is done in Figure ref:fig:modal_comp_acc_frf_modal.
% Whether the obtained match can be considered good or bad is quite arbitrary.
% Yet, the modal model seems to be able to represent the coupling between different nodes and different direction which is quite important in a control point of view.
% This can be seen in Figure ref:fig:modal_comp_acc_frf_modal_3 that shows the frequency response function between a force applied on node 11 (i.e. on the translation stage) in the $y$ direction to the measured acceleration at node $2$ (i.e. at the top of the micro-hexapod) in the $x$ direction.
acc_o = 11; dir_o = 3;
acc_i = 11; dir_i = 3;
figure;
ax1 = subplot(2, 1, 1);
hold on;
plot(freqs, abs(squeeze(frf(3*(acc_o-1)+dir_o, dir_i, :))), 'DisplayName', 'Original');
plot(freqs, abs(squeeze(Hsyn(3*(acc_o-1)+dir_o, 3*(11-1)+dir_i, :))), 'DisplayName', 'Synthesize');
plot(freqs, abs(squeeze(frf( 3*(acc_o-1)+dir_o, dir_i, :))), 'DisplayName', 'Measured');
plot(freqs, abs(squeeze(Hsyn(3*(acc_o-1)+dir_o, 3*(acc_i-1)+dir_i, :))), 'DisplayName', 'Synthesized');
hold off;
set(gca, 'xscale', 'lin');
set(gca, 'yscale', 'log');
set(gca, 'XTickLabel',[]);
xlabel('Frequency [Hz]');
ylabel('Magnitude [$\frac{m/s^2}{N}$]');
title(sprintf('From acc %i %s to acc %i %s', 11, dirs(dir_i), acc_o, dirs(dir_o)))
legend('location', 'northwest');
ax2 = subplot(2, 1, 2);
hold on;
plot(freqs, mod(180/pi*phase(squeeze(frf(3*(acc_o-1)+dir_o, dir_i, :)))+180, 360)-180);
plot(freqs, mod(180/pi*phase(squeeze(Hsyn(3*(acc_o-1)+dir_o, 3*(11-1)+dir_i, :)))+180, 360)-180);
hold off;
yticks(-360:90:360); ylim([-180, 180]);
xlabel('Frequency [Hz]'); ylabel('Phase [deg]');
linkaxes([ax1,ax2],'x');
ldg = legend('location', 'southeast', 'FontSize', 8, 'NumColumns', 1);
ldg.ItemTokenSize = [10, 1];
xticks([0:40:200]);
xlim([1, 200]);
ylim([1e-6, 1e-1]);
% Synthesize FRF that has not yet been measured
accs = [1]; dirs = [1:3];
acc_o = 15; dir_o = 3;
acc_i = 11; dir_i = 3;
figure;
ax1 = subplot(2, 1, 1);
hold on;
for acc_i = accs
for dir_i = dirs
plot(freqs, abs((1./(j*2*pi*freqs').^2).*squeeze(Hsyn(3*(acc_i-1)+dir_i, 3*(acc_i-1)+dir_i, :))), 'DisplayName', sprintf('Acc %i - %s', acc_i, dirs(dir_i)));
end
end
plot(freqs, abs(squeeze(frf( 3*(acc_o-1)+dir_o, dir_i, :))), 'DisplayName', 'Measured');
plot(freqs, abs(squeeze(Hsyn(3*(acc_o-1)+dir_o, 3*(acc_i-1)+dir_i, :))), 'DisplayName', 'Synthesized');
hold off;
set(gca, 'xscale', 'log'); set(gca, 'yscale', 'log');
set(gca, 'XTickLabel',[]);
ylabel('Magnitude [$\frac{m}{N}$]');
legend('location', 'southwest');
ax2 = subplot(2, 1, 2);
hold on;
for acc_i = accs
for dir_i = dirs
plot(freqs, mod(180/pi*phase((1./(j*2*pi*freqs').^2).*squeeze(Hsyn(3*(acc_i-1)+dir_i, 3*(acc_i-1)+dir_i, :)))+180, 360)-180);
end
end
hold off;
yticks(-360:90:360); ylim([-180, 180]);
set(gca, 'xscale', 'log');
xlabel('Frequency [Hz]'); ylabel('Phase [deg]');
linkaxes([ax1,ax2],'x');
set(gca, 'xscale', 'lin');
set(gca, 'yscale', 'log');
xlabel('Frequency [Hz]');
ylabel('Magnitude [$\frac{m/s^2}{N}$]');
ldg = legend('location', 'southeast', 'FontSize', 8, 'NumColumns', 1);
ldg.ItemTokenSize = [10, 1];
xticks([0:40:200]);
xlim([1, 200]);
ylim([1e-6, 1e-1]);
acc_o = 2; dir_o = 1;
acc_i = 11; dir_i = 2;
figure;
hold on;
plot(freqs, abs(squeeze(frf( 3*(acc_o-1)+dir_o, dir_i, :))), 'DisplayName', 'Measured');
plot(freqs, abs(squeeze(Hsyn(3*(acc_o-1)+dir_o, 3*(acc_i-1)+dir_i, :))), 'DisplayName', 'Synthesized');
hold off;
set(gca, 'xscale', 'lin');
set(gca, 'yscale', 'log');
xlabel('Frequency [Hz]');
ylabel('Magnitude [$\frac{m/s^2}{N}$]');
ldg = legend('location', 'southeast', 'FontSize', 8, 'NumColumns', 1);
ldg.ItemTokenSize = [10, 1];
xticks([0:40:200]);
xlim([1, 200]);
ylim([1e-6, 1e-1]);