sensor-fusion-test-bench/index.org

1130 lines
38 KiB
Org Mode
Raw Normal View History

2020-08-19 10:29:15 +02:00
#+TITLE: Sensor Fusion - Test Bench
:DRAWER:
#+LANGUAGE: en
#+EMAIL: dehaeze.thomas@gmail.com
#+AUTHOR: Dehaeze Thomas
#+HTML_HEAD: <link rel="stylesheet" type="text/css" href="./css/htmlize.css"/>
#+HTML_HEAD: <link rel="stylesheet" type="text/css" href="./css/readtheorg.css"/>
#+HTML_HEAD: <link rel="stylesheet" type="text/css" href="./css/zenburn.css"/>
#+HTML_HEAD: <script type="text/javascript" src="./js/jquery.min.js"></script>
#+HTML_HEAD: <script type="text/javascript" src="./js/bootstrap.min.js"></script>
#+HTML_HEAD: <script type="text/javascript" src="./js/jquery.stickytableheaders.min.js"></script>
#+HTML_HEAD: <script type="text/javascript" src="./js/readtheorg.js"></script>
#+PROPERTY: header-args:latex :headers '("\\usepackage{tikz}" "\\usepackage{import}" "\\import{$HOME/Cloud/tikz/org/}{config.tex}")
#+PROPERTY: header-args:latex+ :imagemagick t :fit yes
#+PROPERTY: header-args:latex+ :iminoptions -scale 100% -density 150
#+PROPERTY: header-args:latex+ :imoutoptions -quality 100
#+PROPERTY: header-args:latex+ :results raw replace :buffer no
#+PROPERTY: header-args:latex+ :eval no-export
#+PROPERTY: header-args:latex+ :exports both
#+PROPERTY: header-args:latex+ :mkdirp yes
#+PROPERTY: header-args:latex+ :output-dir figs
#+PROPERTY: header-args:latex+ :post pdf2svg(file=*this*, ext="png")
#+PROPERTY: header-args:matlab :session *MATLAB*
#+PROPERTY: header-args:matlab+ :tangle filters.m
#+PROPERTY: header-args:matlab+ :comments org
#+PROPERTY: header-args:matlab+ :exports both
#+PROPERTY: header-args:matlab+ :results none
#+PROPERTY: header-args:matlab+ :eval no-export
#+PROPERTY: header-args:matlab+ :noweb yes
#+PROPERTY: header-args:matlab+ :mkdirp yes
#+PROPERTY: header-args:matlab+ :output-dir figs
:END:
* Experimental Setup
2020-09-09 21:13:39 +02:00
The goal of this experimental setup is to experimentally merge inertial sensors.
To merge the sensors, optimal and robust complementary filters are designed.
The inertial sensors used are shown in Table
#+name: tab:inertial_sensors
#+caption: Inertial Sensors used
| *Type* | *Model* |
2020-08-19 10:29:15 +02:00
|---------------+------------------------------|
| Accelerometer | PCB 393B05 - Vertical ([[https://www.pcb.com/products?m=393B05][link]]) |
2020-09-09 21:13:39 +02:00
| Geophone | Mark Product L-22 - Vertical |
#+name: tab:393B05_spec
#+caption: Accelerometer (393B05) Specifications
| *Specification* | *Value* |
|-------------------------+--------------------|
| Sensitivity | 1.02 [V/(m/s2)] |
| Resonant Frequency | > 2.5 [kHz] |
| Resolution (1 to 10kHz) | 0.00004 [m/s2 rms] |
#+name: tab:L22_spec
#+caption: Geophone (L22) Specifications
| *Specification* | *Value* |
|-------------------------+--------------------------|
| Sensitivity | To be measured [V/(m/s)] |
| Resonant Frequency | 2 [Hz] |
The ADC used are the IO131 Speedgoat module ([[https://www.speedgoat.com/products/io-connectivity-analog-io131][link]]) with a 16bit resolution over +/- 10V.
The geophone signals are amplified using a DLPVA-100-B-D voltage amplified from Femto ([[https://www.femto.de/en/products/voltage-amplifiers/variable-gain-100-khz-dlpva.html][link]]).
The force sensor signal is amplified using a Low Noise Voltage Preamplifier from Ametek ([[https://www.ameteksi.com/support-center/legacy-products/signal-recovery-legacy/5113-low-noise-preamplifier][link]]).
Geophone electronics:
- gain: 10 (20dB)
- low pass filter: 1.5Hz
- hifh pass filter: 100kHz (2nd order)
Force Sensor electronics:
- gain: 10 (20dB)
- low pass filter: 1st order at 3Hz
- high pass filter: 1st order at 30kHz
2020-08-19 10:29:15 +02:00
* Huddle Test
2020-09-09 21:13:39 +02:00
** Introduction :ignore:
The goal here is to measure the noise of the inertial sensors.
Is also permits to measure the motion level when nothing is actuated.
** Matlab Init :noexport:ignore:
2020-08-19 10:29:15 +02:00
#+begin_src matlab :tangle no :exports none :results silent :noweb yes :var current_dir=(file-name-directory buffer-file-name)
<<matlab-dir>>
#+end_src
#+begin_src matlab :exports none :results silent :noweb yes
<<matlab-init>>
#+end_src
** Load Data
#+begin_src matlab
2020-09-09 21:13:39 +02:00
ht = load('./mat/huddle_test.mat', 'd', 'acc_1', 'acc_2', 'geo_1', 'geo_2', 'f_meas', 'u', 't');
2020-08-19 10:29:15 +02:00
#+end_src
2020-09-09 21:13:39 +02:00
** Detrend Data
2020-08-19 10:29:15 +02:00
#+begin_src matlab
2020-09-09 21:13:39 +02:00
ht.d = detrend(ht.d, 0); % [m]
ht.acc_1 = detrend(ht.acc_1, 0); % [V]
ht.acc_2 = detrend(ht.acc_2, 0); % [V]
ht.geo_1 = detrend(ht.geo_1, 0); % [V]
ht.geo_2 = detrend(ht.geo_2, 0); % [V]
ht.f_meas = detrend(ht.f_meas, 0); % [V]
2020-08-19 10:29:15 +02:00
#+end_src
2020-09-09 21:13:39 +02:00
** Compute PSD
We first define the parameters for the frequency domain analysis.
#+begin_src matlab
Ts = ht.t(2) - ht.t(1); % [s]
Fs = 1/Ts; % [Hz]
win = hanning(ceil(1*Fs));
#+end_src
2020-08-19 10:29:15 +02:00
2020-09-09 21:13:39 +02:00
Then we compute the Power Spectral Density using =pwelch= function.
2020-08-19 10:29:15 +02:00
#+begin_src matlab
2020-09-09 21:13:39 +02:00
[p_d, f] = pwelch(ht.d, win, [], [], 1/Ts);
[p_acc1, ~] = pwelch(ht.acc_1, win, [], [], 1/Ts);
[p_acc2, ~] = pwelch(ht.acc_2, win, [], [], 1/Ts);
[p_geo1, ~] = pwelch(ht.geo_1, win, [], [], 1/Ts);
[p_geo2, ~] = pwelch(ht.geo_2, win, [], [], 1/Ts);
[p_fmeas, ~] = pwelch(ht.f_meas, win, [], [], 1/Ts);
#+end_src
#+begin_src matlab :exports none
figure;
ax1 = subplot(1, 2, 1);
hold on;
plot(f, sqrt(p_acc1));
plot(f, sqrt(p_acc2));
hold off;
set(gca, 'xscale', 'log');
set(gca, 'yscale', 'log');
xlabel('Frequency [Hz]'); ylabel('ASD Accelerometers $[V/\sqrt{Hz}]$')
xlim([1, 5000]);
ax2 = subplot(1, 2, 2);
hold on;
plot(f, sqrt(p_geo1));
plot(f, sqrt(p_geo2));
hold off;
set(gca, 'xscale', 'log');
set(gca, 'yscale', 'log');
xlabel('Frequency [Hz]'); ylabel('ASD Geophones $[V/\sqrt{Hz}]$')
xlim([1, 5000]);
#+end_src
2020-08-19 10:29:15 +02:00
2020-09-09 21:13:39 +02:00
#+begin_src matlab :tangle no :exports results :results file replace
exportFig('figs/huddle_test_measured_voltage_inertial_sensors.pdf', 'width', 'full', 'height', 'tall');
2020-08-19 10:29:15 +02:00
#+end_src
2020-09-09 21:13:39 +02:00
#+name: fig:huddle_test_measured_voltage_inertial_sensors
#+caption: ASD of the measured voltage from the inertial sensors during the Huddle test
#+RESULTS:
[[file:figs/huddle_test_measured_voltage_inertial_sensors.png]]
** Sensor Noise in Volts
2020-08-19 10:29:15 +02:00
#+begin_src matlab
2020-09-09 21:13:39 +02:00
[coh_acc, ~] = mscohere(ht.acc_1, ht.acc_2, win, [], [], Fs);
[coh_geo, ~] = mscohere(ht.geo_1, ht.geo_2, win, [], [], Fs);
#+end_src
2020-08-19 10:29:15 +02:00
2020-09-09 21:13:39 +02:00
#+begin_src matlab
pN_acc = p_acc1.*(1 - coh_acc);
pN_geo = p_geo1.*(1 - coh_geo);
2020-08-19 10:29:15 +02:00
#+end_src
2020-09-09 21:13:39 +02:00
PSD of the ADC quantization noise.
2020-08-19 10:29:15 +02:00
#+begin_src matlab
2020-09-09 21:13:39 +02:00
Sq = (20/2^16)^2/(12*Fs);
2020-08-19 10:29:15 +02:00
#+end_src
2020-09-09 21:13:39 +02:00
#+begin_src matlab :results none
figure;
hold on;
plot(f, sqrt(pN_acc), '-', 'DisplayName', 'Accelerometers');
plot(f, sqrt(pN_geo), '-', 'DisplayName', 'Geophones');
plot(f, ones(size(f))*sqrt(Sq), '-', 'DisplayName', 'ADC');
hold off;
set(gca, 'xscale', 'log'); set(gca, 'yscale', 'log');
xlabel('Frequency [Hz]'); ylabel('ASD of the Measurement Noise $[V/\sqrt{Hz}]$');
xlim([1, 5000]);
legend('location', 'northeast');
#+end_src
* Sensor Dynamics
** Introduction :ignore:
Thanks to the interferometer, it is possible to compute the transfer function from the mass displacement to the voltage generated by the inertial sensors.
This permits to estimate the sensor dynamics and to calibrate the sensors.
** Matlab Init :noexport:ignore:
#+begin_src matlab :tangle no :exports none :results silent :noweb yes :var current_dir=(file-name-directory buffer-file-name)
<<matlab-dir>>
#+end_src
#+begin_src matlab :exports none :results silent :noweb yes
<<matlab-init>>
#+end_src
** Load Data
2020-08-19 10:29:15 +02:00
#+begin_src matlab
2020-09-09 21:13:39 +02:00
ht = load('./mat/huddle_test.mat', 'd', 'acc_1', 'acc_2', 'geo_1', 'geo_2', 'f_meas', 'u', 't');
id_ol = load('./mat/identification_noise_bis.mat', 'd', 'acc_1', 'acc_2', 'geo_1', 'geo_2', 'f_meas', 'u', 't');
#+end_src
#+begin_src matlab :exports none
ht.d = detrend(ht.d, 0); % [m]
ht.acc_1 = detrend(ht.acc_1, 0); % [V]
ht.acc_2 = detrend(ht.acc_2, 0); % [V]
ht.geo_1 = detrend(ht.geo_1, 0); % [V]
ht.geo_2 = detrend(ht.geo_2, 0); % [V]
ht.f_meas = detrend(ht.f_meas, 0); % [V]
#+end_src
#+begin_src matlab :exports none
id_ol.d = detrend(id_ol.d, 0);
id_ol.acc_1 = detrend(id_ol.acc_1, 0);
id_ol.acc_2 = detrend(id_ol.acc_2, 0);
id_ol.geo_1 = detrend(id_ol.geo_1, 0);
id_ol.geo_2 = detrend(id_ol.geo_2, 0);
id_ol.f_meas = detrend(id_ol.f_meas, 0);
id_ol.u = detrend(id_ol.u, 0);
#+end_src
** Time Domain Signals
Excitation signal: noise.
#+begin_src matlab :exports none
figure;
plot(id_ol.t, id_ol.u);
xlim([0 0.1]);
xlabel('Time [s]'); ylabel('Excitation Signal [V]');
#+end_src
#+begin_src matlab :tangle no :exports results :results file replace
exportFig('figs/first_exc_signal_time.pdf', 'width', 'wide', 'height', 'normal');
#+end_src
#+name: fig:first_exc_signal_time
#+caption: Excitation signal used for the first identification
#+RESULTS:
[[file:figs/first_exc_signal_time.png]]
** Identification of the IFF Plant
*** Experimental Data
#+begin_src matlab
Ts = ht.t(2) - ht.t(1);
win = hann(ceil(10/Ts));
#+end_src
#+begin_src matlab
[tf_fmeas_est, f] = tfestimate(id_ol.u, id_ol.f_meas, win, [], [], 1/Ts); % [V/m]
[co_fmeas_est, ~] = mscohere( id_ol.u, id_ol.f_meas, win, [], [], 1/Ts);
#+end_src
#+begin_src matlab :exports none
2020-08-19 10:29:15 +02:00
figure;
hold on;
2020-09-09 21:13:39 +02:00
plot(f, co_fmeas_est, '-')
set(gca, 'Xscale', 'log'); set(gca, 'Yscale', 'lin');
ylabel('Coherence'); xlabel('Frequency [Hz]');
2020-08-19 10:29:15 +02:00
hold off;
2020-09-09 21:13:39 +02:00
xlim([1, 1e3]); ylim([0, 1])
2020-08-19 10:29:15 +02:00
#+end_src
2020-09-09 21:13:39 +02:00
#+begin_src matlab :tangle no :exports results :results file replace
exportFig('figs/iff_identification_coh.pdf', 'width', 'wide', 'height', 'normal');
#+end_src
2020-08-19 10:29:15 +02:00
2020-09-09 21:13:39 +02:00
#+name: fig:iff_identification_coh
#+caption: Coherence for the identification of the IFF plant
#+RESULTS:
[[file:figs/iff_identification_coh.png]]
#+begin_src matlab :exports none
figure;
ax1 = subplot(2, 1, 1);
hold on;
plot(f, abs(tf_fmeas_est), '-')
set(gca, 'Xscale', 'log'); set(gca, 'Yscale', 'log');
ylabel('Amplitude'); xlabel('Frequency [Hz]');
hold off;
ax2 = subplot(2, 1, 2);
hold on;
plot(f, 180/pi*angle(tf_fmeas_est), '-')
set(gca, 'Xscale', 'log'); set(gca, 'Yscale', 'lin');
ylabel('Phase'); xlabel('Frequency [Hz]');
hold off;
linkaxes([ax1,ax2], 'x');
xlim([1, 1e3]);
2020-08-19 10:29:15 +02:00
#+end_src
2020-09-09 21:13:39 +02:00
#+begin_src matlab :tangle no :exports results :results file replace
exportFig('figs/iff_identification_bode_plot.pdf', 'width', 'full', 'height', 'full');
2020-08-19 10:29:15 +02:00
#+end_src
2020-09-09 21:13:39 +02:00
#+name: fig:iff_identification_bode_plot
#+caption: Bode plot of the identified IFF plant
#+RESULTS:
[[file:figs/iff_identification_bode_plot.png]]
*** Model of the IFF Plant
#+begin_src matlab
wz = 2*pi*102;
xi_z = 0.01;
wp = 2*pi*239.4;
xi_p = 0.015;
Giff = 2.2*(s^2 + 2*xi_z*s*wz + wz^2)/(s^2 + 2*xi_p*s*wp + wp^2) * ... % Dynamics
10*(s/3/pi/(1 + s/3/pi)) * ... % Low pass filter and gain of the voltage amplifier
exp(-Ts*s); % Time delay induced by ADC/DAC
#+end_src
#+begin_src matlab :exports none
2020-08-19 10:29:15 +02:00
figure;
2020-09-09 21:13:39 +02:00
ax1 = subplot(2, 1, 1);
2020-08-19 10:29:15 +02:00
hold on;
2020-09-09 21:13:39 +02:00
plot(f, abs(tf_fmeas_est), '.')
plot(f, abs(squeeze(freqresp(Giff, f, 'Hz'))), 'k-')
set(gca, 'Xscale', 'log'); set(gca, 'Yscale', 'log');
ylabel('Amplitude [V/V]'); set(gca, 'XTickLabel',[]);
2020-08-19 10:29:15 +02:00
hold off;
2020-09-09 21:13:39 +02:00
ylim([1e-2, 1e3])
ax2 = subplot(2, 1, 2);
hold on;
plot(f, 180/pi*angle(tf_fmeas_est), '.')
plot(f, 180/pi*angle(squeeze(freqresp(Giff, f, 'Hz'))), 'k-')
set(gca, 'Xscale', 'log'); set(gca, 'Yscale', 'lin');
ylabel('Phase'); xlabel('Frequency [Hz]');
hold off;
ylim([-180, 180]);
yticks([-180, -90, 0, 90, 180]);
linkaxes([ax1,ax2], 'x');
xlim([0.5, 5e3]);
#+end_src
#+begin_src matlab :tangle no :exports results :results file replace
exportFig('figs/iff_plant_model.pdf', 'width', 'large', 'height', 'full');
#+end_src
#+name: fig:iff_plant_model
#+caption: IFF Plant + Model
#+RESULTS:
[[file:figs/iff_plant_model.png]]
*** Root Locus and optimal Controller
#+begin_src matlab :exports none
gains = logspace(0, 5, 1000);
figure;
hold on;
plot(real(pole(Giff)), imag(pole(Giff)), 'kx');
plot(real(tzero(Giff)), imag(tzero(Giff)), 'ko');
for i = 1:length(gains)
cl_poles = pole(feedback(Giff, gains(i)/(s + 2*pi*2)));
plot(real(cl_poles), imag(cl_poles), 'k.');
end
cl_poles = pole(feedback(Giff, 102/(s + 2*pi*2)));
plot(real(cl_poles), imag(cl_poles), 'rx');
ylim([0, 1800]);
xlim([-1600,200]);
xlabel('Real Part')
ylabel('Imaginary Part')
axis square
#+end_src
#+begin_src matlab :tangle no :exports results :results file replace
exportFig('figs/iff_root_locus.pdf', 'width', 'wide', 'height', 'tall');
#+end_src
#+name: fig:iff_root_locus
#+caption: Root Locus for the IFF control
#+RESULTS:
[[file:figs/iff_root_locus.png]]
The controller that yield maximum damping is:
#+begin_src matlab
Kiff_opt = 102/(s + 2*pi*2);
#+end_src
** Identification of Sensor Dynamics with IFF activated
*** Signals
A new identification is performed with the resonance damped.
It helps to not induce too much motion at the resonance and damage the actuator.
#+begin_src matlab
id_cl = load('./mat/identification_noise_iff_bis.mat', 'd', 'acc_1', 'acc_2', 'geo_1', 'geo_2', 'f_meas', 'u', 't');
#+end_src
#+begin_src matlab :exports none
id_cl.d = detrend(id_cl.d, 0);
id_cl.acc_1 = detrend(id_cl.acc_1, 0);
id_cl.acc_2 = detrend(id_cl.acc_2, 0);
id_cl.geo_1 = detrend(id_cl.geo_1, 0);
id_cl.geo_2 = detrend(id_cl.geo_2, 0);
id_cl.f_meas = detrend(id_cl.f_meas, 0);
id_cl.u = detrend(id_cl.u, 0);
#+end_src
*** Verification of the achievable damping
#+begin_src matlab
[tf_G_ol_est, f] = tfestimate(id_ol.u, id_ol.d, win, [], [], 1/Ts);
[co_G_ol_est, ~] = mscohere( id_ol.u, id_ol.d, win, [], [], 1/Ts);
[tf_G_cl_est, ~] = tfestimate(id_cl.u, id_cl.d, win, [], [], 1/Ts);
[co_G_cl_est, ~] = mscohere( id_cl.u, id_cl.d, win, [], [], 1/Ts);
#+end_src
#+begin_src matlab :exports none
figure;
hold on;
plot(f, co_G_ol_est, '-', 'DisplayName', 'OL')
plot(f, co_G_cl_est, '-', 'DisplayName', 'IFF')
set(gca, 'Xscale', 'log'); set(gca, 'Yscale', 'lin');
ylabel('Coherence'); xlabel('Frequency [Hz]');
hold off;
xlim([1, 1e3]); ylim([0, 1])
legend('location', 'southwest');
#+end_src
#+begin_src matlab :tangle no :exports results :results file replace
exportFig('figs/Gd_identification_iff_coherence.pdf', 'width', 'wide', 'height', 'normal');
#+end_src
#+name: fig:Gd_identification_iff_coherence
#+caption: Coherence for the transfer function from F to d, with and without IFF
#+RESULTS:
[[file:figs/Gd_identification_iff_coherence.png]]
Don't really understand the low frequency behavior.
#+begin_src matlab :exports none
figure;
ax1 = subplot(2, 1, 1);
hold on;
plot(f, abs(tf_G_ol_est), '-', 'DisplayName', 'OL')
plot(f, abs(tf_G_cl_est), '-', 'DisplayName', 'IFF')
set(gca, 'Xscale', 'log'); set(gca, 'Yscale', 'log');
ylabel('Amplitude [m/V]'); set(gca, 'XTickLabel',[]);
hold off;
legend('location', 'northeast');
ylim([2e-7, 2e-4]);
ax2 = subplot(2, 1, 2);
hold on;
plot(f, 180/pi*angle(tf_G_ol_est), '-')
plot(f, 180/pi*angle(tf_G_cl_est), '-')
set(gca, 'Xscale', 'log'); set(gca, 'Yscale', 'lin');
ylabel('Phase'); xlabel('Frequency [Hz]');
hold off;
ylim([-180, 180]);
yticks([-180, -90, 0, 90, 180]);
linkaxes([ax1,ax2], 'x');
xlim([1, 1e3]);
#+end_src
#+begin_src matlab :tangle no :exports results :results file replace
exportFig('figs/Gd_identification_iff_bode_plot.pdf', 'width', 'full', 'height', 'full');
#+end_src
#+name: fig:Gd_identification_iff_bode_plot
#+caption: Coherence for the transfer function from F to d, with and without IFF
#+RESULTS:
[[file:figs/Gd_identification_iff_bode_plot.png]]
** Generate the excitation signal
*** Requirements
The requirements on the excitation signal is:
- General much larger motion that the measured motion during the huddle test
- Don't damage the actuator
To determine the perfect voltage signal to be generated, we need two things:
- the transfer function from voltage to mass displacement
- the PSD of the measured motion by the inertial sensors
- not saturate the sensor signals
- provide enough signal/noise ratio (good coherence) in the frequency band of interest (~0.5Hz to 3kHz)
*** Transfer function from excitation signal to displacement
Let's first estimate the transfer function from the excitation signal in [V] to the generated displacement in [m] as measured by the inteferometer.
#+begin_src matlab
id_cl = load('./mat/identification_noise_iff_bis.mat', 'd', 'acc_1', 'acc_2', 'geo_1', 'geo_2', 'f_meas', 'u', 't');
#+end_src
#+begin_src matlab :exports none
id_cl.d = detrend(id_cl.d, 0);
id_cl.acc_1 = detrend(id_cl.acc_1, 0);
id_cl.acc_2 = detrend(id_cl.acc_2, 0);
id_cl.geo_1 = detrend(id_cl.geo_1, 0);
id_cl.geo_2 = detrend(id_cl.geo_2, 0);
id_cl.f_meas = detrend(id_cl.f_meas, 0);
id_cl.u = detrend(id_cl.u, 0);
#+end_src
#+begin_src matlab
win = hann(ceil(10/Ts));
[tf_G_cl_est, f] = tfestimate(id_cl.u, id_cl.d, win, [], [], 1/Ts);
[co_G_cl_est, ~] = mscohere( id_cl.u, id_cl.d, win, [], [], 1/Ts);
#+end_src
Approximate transfer function from voltage output to generated displacement when IFF is used, in [m/V].
#+begin_src matlab
G_d_est = -5e-6*(2*pi*230)^2/(s^2 + 2*0.3*2*pi*240*s + (2*pi*240)^2);
#+end_src
#+begin_src matlab :exports none
figure;
ax1 = subplot(2, 1, 1);
hold on;
plot(f, abs(tf_G_cl_est), '-')
plot(f, abs(squeeze(freqresp(G_d_est, f, 'Hz'))), '--')
set(gca, 'Xscale', 'log'); set(gca, 'Yscale', 'log');
ylabel('Amplitude [m/V]'); set(gca, 'XTickLabel',[]);
hold off;
ax2 = subplot(2, 1, 2);
hold on;
plot(f, 180/pi*angle(tf_G_cl_est), '-')
plot(f, 180/pi*angle(squeeze(freqresp(G_d_est, f, 'Hz'))), '--')
set(gca, 'Xscale', 'log'); set(gca, 'Yscale', 'lin');
ylabel('Phase'); xlabel('Frequency [Hz]');
hold off;
linkaxes([ax1,ax2], 'x');
xlim([10, 1000]);
#+end_src
#+begin_src matlab :tangle no :exports results :results file replace
exportFig('figs/Gd_plant_estimation.pdf', 'width', 'full', 'height', 'full');
#+end_src
#+name: fig:Gd_plant_estimation
#+caption: Estimation of the transfer function from the excitation signal to the generated displacement
#+RESULTS:
[[file:figs/Gd_plant_estimation.png]]
*** Motion measured during Huddle test
We now compute the PSD of the measured motion by the inertial sensors during the huddle test.
#+begin_src matlab
ht = load('./mat/huddle_test.mat', 'd', 'acc_1', 'acc_2', 'geo_1', 'geo_2', 'f_meas', 'u', 't');
#+end_src
#+begin_src matlab :exports none
ht.d = detrend(ht.d, 0);
ht.acc_1 = detrend(ht.acc_1, 0);
ht.acc_2 = detrend(ht.acc_2, 0);
ht.geo_1 = detrend(ht.geo_1, 0);
ht.geo_2 = detrend(ht.geo_2, 0);
#+end_src
#+begin_src matlab
[p_d, f] = pwelch(ht.d, win, [], [], 1/Ts);
[p_acc1, ~] = pwelch(ht.acc_1, win, [], [], 1/Ts);
[p_acc2, ~] = pwelch(ht.acc_2, win, [], [], 1/Ts);
[p_geo1, ~] = pwelch(ht.geo_1, win, [], [], 1/Ts);
[p_geo2, ~] = pwelch(ht.geo_2, win, [], [], 1/Ts);
#+end_src
Using an estimated model of the sensor dynamics from the documentation of the sensors, we can compute the ASD of the motion in $m/\sqrt{Hz}$ measured by the sensors.
#+begin_src matlab
G_acc = 1/(1 + s/2/pi/2500); % [V/(m/s2)]
G_geo = -120*s^2/(s^2 + 2*0.7*2*pi*2*s + (2*pi*2)^2); % [V/(m/s)]
#+end_src
#+begin_src matlab :exports none
figure;
hold on;
set(gca, 'ColorOrderIndex', 1);
plot(f, sqrt(p_acc1)./abs(squeeze(freqresp(G_acc*s^2, f, 'Hz'))), ...
'DisplayName', 'Accelerometer');
set(gca, 'ColorOrderIndex', 1);
plot(f, sqrt(p_acc2)./abs(squeeze(freqresp(G_acc*s^2, f, 'Hz'))), ...
'HandleVisibility', 'off');
set(gca, 'ColorOrderIndex', 2);
plot(f, sqrt(p_geo1)./abs(squeeze(freqresp(G_geo*s, f, 'Hz'))), ...
'DisplayName', 'Geophone');
set(gca, 'ColorOrderIndex', 2);
plot(f, sqrt(p_geo2)./abs(squeeze(freqresp(G_geo*s, f, 'Hz'))), ...
'HandleVisibility', 'off');
set(gca, 'ColorOrderIndex', 3);
plot(f, sqrt(pxx), 'k-', ...
'DisplayName', 'Excitation');
plot(f, sqrt(p_d), 'DisplayName', 'Interferometer');
hold off;
set(gca, 'Xscale', 'log'); set(gca, 'Yscale', 'log');
ylabel('ASD [$m/\sqrt{Hz}$]'); xlabel('Frequency [Hz]');
title('Huddle Test')
legend();
#+end_src
#+begin_src matlab :tangle no :exports results :results file replace
exportFig('figs/huddle_test_psd_motion.pdf', 'width', 'wide', 'height', 'tall');
#+end_src
#+name: fig:huddle_test_psd_motion
#+caption: ASD of the motion measured by the sensors
#+RESULTS:
[[file:figs/huddle_test_psd_motion.png]]
From the ASD of the motion measured by the sensors, we can create an excitation signal that will generate much motion motion that the motion under no excitation.
We create =G_exc= that corresponds to the wanted generated motion.
#+begin_src matlab
G_exc = 0.2e-6/(1 + s/2/pi/2)/(1 + s/2/pi/50);
#+end_src
And we create a time domain signal =y_d= that have the spectral density described by =G_exc=.
#+begin_src matlab
Fs = 1/Ts;
t = 0:Ts:180; % Time Vector [s]
u = sqrt(Fs/2)*randn(length(t), 1); % Signal with an ASD equal to one
y_d = lsim(G_exc, u, t);
#+end_src
#+begin_src matlab
[pxx, ~] = pwelch(y_d, win, 0, [], Fs);
#+end_src
#+begin_src matlab :exports none
figure;
hold on;
set(gca, 'ColorOrderIndex', 1);
plot(f, sqrt(p_acc1)./abs(squeeze(freqresp(G_acc*s^2, f, 'Hz'))), ...
'DisplayName', 'Accelerometer');
set(gca, 'ColorOrderIndex', 1);
plot(f, sqrt(p_acc2)./abs(squeeze(freqresp(G_acc*s^2, f, 'Hz'))), ...
'HandleVisibility', 'off');
set(gca, 'ColorOrderIndex', 2);
plot(f, sqrt(p_geo1)./abs(squeeze(freqresp(G_geo*s, f, 'Hz'))), ...
'DisplayName', 'Geophone');
set(gca, 'ColorOrderIndex', 2);
plot(f, sqrt(p_geo2)./abs(squeeze(freqresp(G_geo*s, f, 'Hz'))), ...
'HandleVisibility', 'off');
set(gca, 'ColorOrderIndex', 3);
plot(f, sqrt(pxx), 'k-', ...
'DisplayName', 'Excitation');
plot(f, sqrt(p_d), 'DisplayName', 'Interferometer');
hold off;
set(gca, 'Xscale', 'log'); set(gca, 'Yscale', 'log');
ylabel('ASD [$m/\sqrt{Hz}$]'); xlabel('Frequency [Hz]');
title('Huddle Test')
legend();
#+end_src
#+begin_src matlab :tangle no :exports results :results file replace
exportFig('figs/comp_huddle_test_excited_motion_psd.pdf', 'width', 'wide', 'height', 'tall');
#+end_src
#+name: fig:comp_huddle_test_excited_motion_psd
#+caption: Comparison of the ASD of the motion during Huddle and the wanted generated motion
#+RESULTS:
[[file:figs/comp_huddle_test_excited_motion_psd.png]]
We can now generate the voltage signal that will generate the wanted motion.
#+begin_src matlab
y_v = lsim(G_exc * ... % from unit PSD to shaped PSD
(1 + s/2/pi/50) * ... % Inverse of pre-filter included in the Simulink file
1/G_d_est * ... % Wanted displacement => required voltage
1/(1 + s/2/pi/5e3), ... % Add some high frequency filtering
u, t);
#+end_src
#+begin_src matlab :exports none
figure;
plot(t, y_v)
xlabel('Time [s]'); ylabel('Voltage [V]');
#+end_src
#+begin_src matlab :tangle no :exports results :results file replace
exportFig('figs/optimal_exc_signal_time.pdf', 'width', 'wide', 'height', 'normal');
#+end_src
#+name: fig:optimal_exc_signal_time
#+caption: Generated excitation signal
#+RESULTS:
[[file:figs/optimal_exc_signal_time.png]]
** Identification of the Inertial Sensors Dynamics
*** Load Data
#+begin_src matlab
id = load('./mat/identification_noise_opt_iff.mat', 'd', 'acc_1', 'acc_2', 'geo_1', 'geo_2', 'f_meas', 'u', 't');
ht = load('./mat/huddle_test.mat', 'd', 'acc_1', 'acc_2', 'geo_1', 'geo_2', 'f_meas', 'u', 't');
#+end_src
#+begin_src matlab
ht.d = detrend(ht.d, 0);
ht.acc_1 = detrend(ht.acc_1, 0);
ht.acc_2 = detrend(ht.acc_2, 0);
ht.geo_1 = detrend(ht.geo_1, 0);
ht.geo_2 = detrend(ht.geo_2, 0);
ht.f_meas = detrend(ht.f_meas, 0);
#+end_src
#+begin_src matlab
id.d = detrend(id.d, 0);
id.acc_1 = detrend(id.acc_1, 0);
id.acc_2 = detrend(id.acc_2, 0);
id.geo_1 = detrend(id.geo_1, 0);
id.geo_2 = detrend(id.geo_2, 0);
id.f_meas = detrend(id.f_meas, 0);
#+end_src
*** Compare PSD during Huddle and and during identification
#+begin_src matlab
Ts = ht.t(2) - ht.t(1);
win = hann(ceil(10/Ts));
#+end_src
#+begin_src matlab
[p_id_d, f] = pwelch(id.d, win, [], [], 1/Ts);
[p_id_acc1, ~] = pwelch(id.acc_1, win, [], [], 1/Ts);
[p_id_acc2, ~] = pwelch(id.acc_2, win, [], [], 1/Ts);
[p_id_geo1, ~] = pwelch(id.geo_1, win, [], [], 1/Ts);
[p_id_geo2, ~] = pwelch(id.geo_2, win, [], [], 1/Ts);
[p_id_fmeas, ~] = pwelch(id.f_meas, win, [], [], 1/Ts);
#+end_src
#+begin_src matlab
[p_ht_d, ~] = pwelch(ht.d, win, [], [], 1/Ts);
[p_ht_acc1, ~] = pwelch(ht.acc_1, win, [], [], 1/Ts);
[p_ht_acc2, ~] = pwelch(ht.acc_2, win, [], [], 1/Ts);
[p_ht_geo1, ~] = pwelch(ht.geo_1, win, [], [], 1/Ts);
[p_ht_geo2, ~] = pwelch(ht.geo_2, win, [], [], 1/Ts);
[p_ht_fmeas, ~] = pwelch(ht.f_meas, win, [], [], 1/Ts);
#+end_src
#+begin_src matlab :exports none
figure;
ax1 = subplot(1, 2, 1);
hold on;
set(gca, 'ColorOrderIndex', 1);
plot(f, p_ht_acc1, 'DisplayName', 'Huddle Test');
set(gca, 'ColorOrderIndex', 1);
plot(f, p_ht_acc2, 'HandleVisibility', 'off');
set(gca, 'ColorOrderIndex', 2);
plot(f, p_id_acc1, 'DisplayName', 'Identification Test');
set(gca, 'ColorOrderIndex', 2);
plot(f, p_id_acc2, 'HandleVisibility', 'off');
hold off;
set(gca, 'Xscale', 'log'); set(gca, 'Yscale', 'log');
ylabel('PSD [$V^2/Hz$]'); xlabel('Frequency [Hz]');
title('Huddle Test - Accelerometers')
legend();
ax1 = subplot(1, 2, 2);
hold on;
set(gca, 'ColorOrderIndex', 1);
plot(f, p_ht_geo1, 'DisplayName', 'Huddle Test');
set(gca, 'ColorOrderIndex', 1);
plot(f, p_ht_geo2, 'HandleVisibility', 'off');
set(gca, 'ColorOrderIndex', 2);
plot(f, p_id_geo1, 'DisplayName', 'Identification Test');
set(gca, 'ColorOrderIndex', 2);
plot(f, p_id_geo2, 'HandleVisibility', 'off');
hold off;
set(gca, 'Xscale', 'log'); set(gca, 'Yscale', 'log');
ylabel('PSD [$V^2/Hz$]'); xlabel('Frequency [Hz]');
title('Huddle Test - Geophones')
legend();
#+end_src
#+begin_src matlab :tangle no :exports results :results file replace
exportFig('figs/comp_psd_huddle_test_identification.pdf', 'width', 'full', 'height', 'full');
#+end_src
#+name: fig:comp_psd_huddle_test_identification
#+caption: Comparison of the PSD of the measured motion during the Huddle test and during the identification
#+RESULTS:
[[file:figs/comp_psd_huddle_test_identification.png]]
*** Compute transfer functions
#+begin_src matlab
[tf_acc1_est, f] = tfestimate(id.d, id.acc_1, win, [], [], 1/Ts);
[co_acc1_est, ~] = mscohere( id.d, id.acc_1, win, [], [], 1/Ts);
[tf_acc2_est, ~] = tfestimate(id.d, id.acc_2, win, [], [], 1/Ts);
[co_acc2_est, ~] = mscohere( id.d, id.acc_2, win, [], [], 1/Ts);
[tf_geo1_est, ~] = tfestimate(id.d, id.geo_1, win, [], [], 1/Ts);
[co_geo1_est, ~] = mscohere( id.d, id.geo_1, win, [], [], 1/Ts);
[tf_geo2_est, ~] = tfestimate(id.d, id.geo_2, win, [], [], 1/Ts);
[co_geo2_est, ~] = mscohere( id.d, id.geo_2, win, [], [], 1/Ts);
#+end_src
#+begin_src matlab :exports none
figure;
hold on;
set(gca, 'ColorOrderIndex', 1);
plot(f, co_acc1_est, '-', 'DisplayName', 'Accelerometer')
set(gca, 'ColorOrderIndex', 1);
plot(f, co_acc2_est, '-', 'HandleVisibility', 'off')
set(gca, 'ColorOrderIndex', 2);
plot(f, co_geo1_est, '-', 'DisplayName', 'Geophone')
set(gca, 'ColorOrderIndex', 2);
plot(f, co_geo2_est, '-', 'HandleVisibility', 'off')
set(gca, 'Xscale', 'log'); set(gca, 'Yscale', 'lin');
ylabel('Coherence'); xlabel('Frequency [Hz]');
hold off;
xlim([2, 2e3]); ylim([0, 1])
legend();
#+end_src
#+begin_src matlab :tangle no :exports results :results file replace
exportFig('figs/id_sensor_dynamics_coherence.pdf', 'width', 'wide', 'height', 'normal');
#+end_src
#+name: fig:id_sensor_dynamics_coherence
#+caption: Coherence for the estimation of the sensor dynamics
#+RESULTS:
[[file:figs/id_sensor_dynamics_coherence.png]]
Model of the inertial sensors:
#+begin_src matlab
G_acc = 1/(1 + s/2/pi/2500); % [V/(m/s2)]
G_geo = -1200*s^2/(s^2 + 2*0.7*2*pi*2*s + (2*pi*2)^2); % [[V/(m/s)]
#+end_src
#+begin_src matlab :exports none
figure;
ax1 = subplot(2, 1, 1);
hold on;
plot(f, abs(tf_acc1_est./(1i*2*pi*f).^2), '.')
plot(f, abs(tf_acc2_est./(1i*2*pi*f).^2), '.')
plot(f, abs(squeeze(freqresp(G_acc, f, 'Hz'))), 'k-')
set(gca, 'Xscale', 'log'); set(gca, 'Yscale', 'log');
ylabel('Amplitude $\left[\frac{V}{m/s^2}\right]$'); set(gca, 'XTickLabel',[]);
hold off;
ax2 = subplot(2, 1, 2);
hold on;
plot(f, 180/pi*angle(tf_acc1_est./(1i*2*pi*f).^2), '.')
plot(f, 180/pi*angle(tf_acc2_est./(1i*2*pi*f).^2), '.')
plot(f, 180/pi*angle(squeeze(freqresp(G_acc, f, 'Hz'))), 'k-')
set(gca, 'Xscale', 'log'); set(gca, 'Yscale', 'lin');
ylabel('Phase'); xlabel('Frequency [Hz]');
hold off;
linkaxes([ax1,ax2], 'x');
xlim([2, 2e3]);
#+end_src
#+begin_src matlab :tangle no :exports results :results file replace
exportFig('figs/id_sensor_dynamics_accelerometers.pdf', 'width', 'full', 'height', 'full');
#+end_src
#+name: fig:id_sensor_dynamics_accelerometers
#+caption: Identified dynamics of the accelerometers
#+RESULTS:
[[file:figs/id_sensor_dynamics_accelerometers.png]]
#+begin_src matlab :exports none
figure;
ax1 = subplot(2, 1, 1);
hold on;
plot(f, abs(tf_geo1_est./(1i*2*pi*f)), '.')
plot(f, abs(tf_geo2_est./(1i*2*pi*f)), '.')
plot(f, abs(squeeze(freqresp(G_geo, f, 'Hz'))), 'k-')
set(gca, 'Xscale', 'log'); set(gca, 'Yscale', 'log');
ylabel('Amplitude $\left[\frac{V}{m/s}\right]$'); set(gca, 'XTickLabel',[]);
hold off;
ax2 = subplot(2, 1, 2);
hold on;
plot(f, 180/pi*angle(tf_geo1_est./(1i*2*pi*f)), '.')
plot(f, 180/pi*angle(tf_geo2_est./(1i*2*pi*f)), '.')
plot(f, 180/pi*angle(squeeze(freqresp(G_geo, f, 'Hz'))), 'k-')
set(gca, 'Xscale', 'log'); set(gca, 'Yscale', 'lin');
ylabel('Phase'); xlabel('Frequency [Hz]');
hold off;
linkaxes([ax1,ax2], 'x');
xlim([0.5, 2e3]);
#+end_src
#+begin_src matlab :tangle no :exports results :results file replace
exportFig('figs/id_sensor_dynamics_geophones.pdf', 'width', 'full', 'height', 'full');
#+end_src
#+name: fig:id_sensor_dynamics_geophones
#+caption: Identified dynamics of the geophones
#+RESULTS:
[[file:figs/id_sensor_dynamics_geophones.png]]
** Inertial Sensor Noise
*** Load Data
#+begin_src matlab
id = load('./mat/identification_noise_opt_iff.mat', 'd', 'acc_1', 'acc_2', 'geo_1', 'geo_2', 'f_meas', 'u', 't');
#+end_src
#+begin_src matlab
id.d = detrend(id.d, 0);
id.acc_1 = detrend(id.acc_1, 0);
id.acc_2 = detrend(id.acc_2, 0);
id.geo_1 = detrend(id.geo_1, 0);
id.geo_2 = detrend(id.geo_2, 0);
id.f_meas = detrend(id.f_meas, 0);
#+end_src
*** ASD of the Measured displacement
#+begin_src matlab
Ts = ht.t(2) - ht.t(1);
win = hann(ceil(10/Ts));
#+end_src
#+begin_src matlab
[p_id_d, f] = pwelch(id.d, win, [], [], 1/Ts);
[p_id_acc1, ~] = pwelch(id.acc_1, win, [], [], 1/Ts);
[p_id_acc2, ~] = pwelch(id.acc_2, win, [], [], 1/Ts);
[p_id_geo1, ~] = pwelch(id.geo_1, win, [], [], 1/Ts);
[p_id_geo2, ~] = pwelch(id.geo_2, win, [], [], 1/Ts);
[p_id_fmeas, ~] = pwelch(id.f_meas, win, [], [], 1/Ts);
#+end_src
Let's use a model of the accelerometer and geophone to compute the motion from the measured voltage.
#+begin_src matlab
G_acc = 1/(1 + s/2/pi/2500); % [V/(m/s2)]
G_geo = -1200*s^2/(s^2 + 2*0.7*2*pi*2*s + (2*pi*2)^2); % [[V/(m/s)]
#+end_src
#+begin_src matlab :exports none
figure;
hold on;
set(gca, 'ColorOrderIndex', 1);
plot(f, sqrt(p_id_acc1)./abs(squeeze(freqresp(G_acc*s^2, f, 'Hz'))), ...
'DisplayName', 'Accelerometer');
set(gca, 'ColorOrderIndex', 1);
plot(f, sqrt(p_id_acc2)./abs(squeeze(freqresp(G_acc*s^2, f, 'Hz'))), ...
'HandleVisibility', 'off');
set(gca, 'ColorOrderIndex', 2);
plot(f, sqrt(p_id_geo1)./abs(squeeze(freqresp(G_geo*s, f, 'Hz'))), ...
'DisplayName', 'Geophone');
set(gca, 'ColorOrderIndex', 2);
plot(f, sqrt(p_id_geo2)./abs(squeeze(freqresp(G_geo*s, f, 'Hz'))), ...
'HandleVisibility', 'off');
set(gca, 'ColorOrderIndex', 3);
plot(f, sqrt(p_id_d), 'DisplayName', 'Interferometer');
hold off;
set(gca, 'Xscale', 'log'); set(gca, 'Yscale', 'log');
ylabel('ASD [$m/\sqrt{Hz}$]'); xlabel('Frequency [Hz]');
title('Huddle Test')
legend();
#+end_src
#+begin_src matlab :tangle no :exports results :results file replace
exportFig('figs/measure_displacement_all_sensors.pdf', 'width', 'full', 'height', 'full');
#+end_src
#+name: fig:measure_displacement_all_sensors
#+caption: ASD of the measured displacement as measured by all the sensors
#+RESULTS:
[[file:figs/measure_displacement_all_sensors.png]]
*** ASD of the Sensor Noise
- [ ] Add formula to estimate the noise from data
#+begin_src matlab
[coh_acc, ~] = mscohere(id.acc_1, id.acc_2, win, [], [], Fs);
[coh_geo, ~] = mscohere(id.geo_1, id.geo_2, win, [], [], Fs);
#+end_src
#+begin_src matlab
pN_acc = sqrt(p_id_acc1.*(1 - coh_acc)) .* ... % [V/sqrt(Hz)]
1./abs(squeeze(freqresp(G_acc*s^2, f, 'Hz'))); % [m/V]
pN_geo = sqrt(p_id_geo1.*(1 - coh_geo)) .* ... % [V/sqrt(Hz)]
1./abs(squeeze(freqresp(G_geo*s, f, 'Hz'))); % [m/V]
2020-08-19 10:29:15 +02:00
#+end_src
#+begin_src matlab :results none
figure;
hold on;
2020-09-09 21:13:39 +02:00
plot(f, sqrt(p_id_acc1)./abs(squeeze(freqresp(G_acc*s^2, f, 'Hz'))), ...
'DisplayName', 'Accelerometer');
plot(f, sqrt(p_id_geo1)./abs(squeeze(freqresp(G_geo*s, f, 'Hz'))), ...
'DisplayName', 'Geophone');
plot(f, pN_acc, '-', 'DisplayName', 'Accelerometers - Noise');
plot(f, pN_geo, '-', 'DisplayName', 'Geophones - Noise');
2020-08-19 10:29:15 +02:00
hold off;
2020-09-09 21:13:39 +02:00
set(gca, 'xscale', 'log'); set(gca, 'yscale', 'log');
xlabel('Frequency [Hz]'); ylabel('ASD $\left[\frac{m}{\sqrt{Hz}}\right]$');
2020-08-19 10:29:15 +02:00
xlim([1, 5000]);
2020-09-09 21:13:39 +02:00
legend('location', 'northeast');
#+end_src
#+begin_src matlab :tangle no :exports results :results file replace
exportFig('figs/noise_inertial_sensors_comparison.pdf', 'width', 'full', 'height', 'full');
2020-08-19 10:29:15 +02:00
#+end_src
2020-09-09 21:13:39 +02:00
#+name: fig:noise_inertial_sensors_comparison
#+caption: Comparison of the computed ASD of the noise of the two inertial sensors
#+RESULTS:
[[file:figs/noise_inertial_sensors_comparison.png]]
2020-08-19 10:29:15 +02:00
2020-09-09 21:13:39 +02:00
** TODO Inertial Sensor Dynamics Uncertainty
*** Load Data
#+begin_src matlab
id = load('./mat/identification_noise_opt_iff.mat', 'd', 'acc_1', 'acc_2', 'geo_1', 'geo_2', 'f_meas', 'u', 't');
#+end_src
#+begin_src matlab
id.d = detrend(id.d, 0);
id.acc_1 = detrend(id.acc_1, 0);
id.acc_2 = detrend(id.acc_2, 0);
id.geo_1 = detrend(id.geo_1, 0);
id.geo_2 = detrend(id.geo_2, 0);
id.f_meas = detrend(id.f_meas, 0);
#+end_src
*** Compute the dynamics of both sensors
#+begin_src matlab
[tf_acc1_est, f] = tfestimate(id.d, id.acc_1, win, [], [], 1/Ts);
[co_acc1_est, ~] = mscohere( id.d, id.acc_1, win, [], [], 1/Ts);
[tf_acc2_est, ~] = tfestimate(id.d, id.acc_2, win, [], [], 1/Ts);
[co_acc2_est, ~] = mscohere( id.d, id.acc_2, win, [], [], 1/Ts);
[tf_geo1_est, ~] = tfestimate(id.d, id.geo_1, win, [], [], 1/Ts);
[co_geo1_est, ~] = mscohere( id.d, id.geo_1, win, [], [], 1/Ts);
[tf_geo2_est, ~] = tfestimate(id.d, id.geo_2, win, [], [], 1/Ts);
[co_geo2_est, ~] = mscohere( id.d, id.geo_2, win, [], [], 1/Ts);
#+end_src
Model of the inertial sensors:
#+begin_src matlab
G_acc = 1/(1 + s/2/pi/2500); % [V/(m/s2)]
G_geo = -1200*s^2/(s^2 + 2*0.7*2*pi*2*s + (2*pi*2)^2); % [[V/(m/s)]
#+end_src
#+begin_src matlab :exports none
figure;
ax1 = subplot(2, 1, 1);
hold on;
plot(f, abs(tf_acc1_est./(1i*2*pi*f).^2), '.')
plot(f, abs(tf_acc2_est./(1i*2*pi*f).^2), '.')
plot(f, abs(squeeze(freqresp(G_acc, f, 'Hz'))), 'k-')
set(gca, 'Xscale', 'log'); set(gca, 'Yscale', 'log');
ylabel('Amplitude $\left[\frac{V}{m/s^2}\right]$'); set(gca, 'XTickLabel',[]);
hold off;
ax2 = subplot(2, 1, 2);
hold on;
plot(f, 180/pi*angle(tf_acc1_est./(1i*2*pi*f).^2), '.')
plot(f, 180/pi*angle(tf_acc2_est./(1i*2*pi*f).^2), '.')
plot(f, 180/pi*angle(squeeze(freqresp(G_acc, f, 'Hz'))), 'k-')
set(gca, 'Xscale', 'log'); set(gca, 'Yscale', 'lin');
ylabel('Phase'); xlabel('Frequency [Hz]');
hold off;
linkaxes([ax1,ax2], 'x');
xlim([2, 2e3]);
#+end_src
*** Dynamics uncertainty estimation
- [ ] Create a weight for both sensors and a nominal model
- [ ] Make sure the dynamics measured are inside the uncertain model
- [ ] Compare the uncertainties
*** Dynamical Uncertainty
2020-08-19 10:29:15 +02:00
#+begin_src matlab :results none
2020-09-09 21:13:39 +02:00
[T_acc, ~] = tfestimate(id.acc_1, id.acc_2, win, [], [], Fs);
[T_geo, ~] = tfestimate(id.geo_1, id.geo_2, win, [], [], Fs);
2020-08-19 10:29:15 +02:00
#+end_src
#+begin_src matlab :results none :exports none
figure;
ax1 = subplot(2, 1, 1);
hold on;
plot(f, abs(T_acc), 'DisplayName', 'Accelerometers');
plot(f, abs(T_geo), 'DisplayName', 'Geophones');
hold off;
set(gca, 'xscale', 'log'); set(gca, 'yscale', 'log');
set(gca, 'XTickLabel',[]);
ylabel('Magnitude');
legend('location', 'southeast');
ax2 = subplot(2, 1, 2);
hold on;
plot(f, 180/pi*phase(T_acc));
plot(f, 180/pi*phase(T_geo));
hold off;
set(gca, 'xscale', 'log');
ylim([-180, 180]);
yticks([-180, -90, 0, 90, 180]);
xlabel('Frequency [Hz]'); ylabel('Phase [deg]');
linkaxes([ax1,ax2],'x');
xlim([1, 5000]);
#+end_src
2020-09-09 21:13:39 +02:00
** Compare Time domain Estimation of the displacement
Let's compare the measured accelerations instead of displacement (no integration).
2020-08-19 10:29:15 +02:00
#+begin_src matlab
2020-09-09 21:13:39 +02:00
G_lpf = 1/(1 + s/2/pi/5e3);
acc1_a = lsim(1/G_acc*G_lpf, id.acc_1, id.t);
acc2_a = lsim(1/G_acc*G_lpf, id.acc_2, id.t);
2020-08-19 10:29:15 +02:00
#+end_src
#+begin_src matlab
2020-09-09 21:13:39 +02:00
geo1_a = lsim(1/G_geo*s*G_lpf, id.geo_1, id.t);
geo2_a = lsim(1/G_geo*s*G_lpf, id.geo_2, id.t);
2020-08-19 10:29:15 +02:00
#+end_src
2020-09-09 21:13:39 +02:00
#+begin_src matlab
int_a = lsim(s^2*G_lpf*G_lpf, id.d, id.t);
#+end_src
#+begin_src matlab
2020-08-19 10:29:15 +02:00
figure;
hold on;
2020-09-09 21:13:39 +02:00
plot(id.t, int_a);
plot(id.t, acc1_a);
plot(id.t, acc2_a);
plot(id.t, geo1_a);
plot(id.t, geo2_a);
2020-08-19 10:29:15 +02:00
hold off;
2020-09-09 21:13:39 +02:00
xlabel('Time [s]'); ylabel('Acceleration [m]');
2020-08-19 10:29:15 +02:00
#+end_src