Sensor Fusion - Test Bench

Table of Contents

1 Experimental Setup

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

Table 1: Inertial Sensors used
Type Model
Accelerometer PCB 393B05 - Vertical (link)
Geophone Mark Product L-22 - Vertical
Table 2: 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]
Table 3: Geophone (L22) Specifications
Specification Value
Sensitivity To be measured [V/(m/s)]
Resonant Frequency 2 [Hz]

The ADC used are the IO131 Speedgoat module (link) with a 16bit resolution over +/- 10V.

The geophone signals are amplified using a DLPVA-100-B-D voltage amplified from Femto (link). The force sensor signal is amplified using a Low Noise Voltage Preamplifier from Ametek (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

2 IFF Development

2.1 Load Data

id_ol = load('./mat/identification_noise_bis.mat', 'd', 'acc_1', 'acc_2', 'geo_1', 'geo_2', 'f_meas', 'u', 't');
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);

2.2 Experimental Data

Ts = id_ol.t(2) - id_ol.t(1);
win = hann(ceil(10/Ts));
[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);

iff_identification_coh.png

Figure 1: Coherence for the identification of the IFF plant

iff_identification_bode_plot.png

Figure 2: Bode plot of the identified IFF plant

2.3 Model of the IFF Plant

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

iff_plant_model.png

Figure 3: IFF Plant + Model

2.4 Root Locus and optimal Controller

iff_root_locus.png

Figure 4: Root Locus for the IFF control

The controller that yield maximum damping is:

Kiff_opt = 102/(s + 2*pi*2);

2.5 Verification of the achievable damping

A new identification is performed with the resonance damped. It helps to not induce too much motion at the resonance and damage the actuator.

id_cl = load('./mat/identification_noise_iff_bis.mat', 'd', 'acc_1', 'acc_2', 'geo_1', 'geo_2', 'f_meas', 'u', 't');
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);
[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);

Gd_identification_iff_coherence.png

Figure 5: Coherence for the transfer function from F to d, with and without IFF

Don’t really understand the low frequency behavior.

Gd_identification_iff_bode_plot.png

Figure 6: Coherence for the transfer function from F to d, with and without IFF

3 Generate the excitation signal

3.1 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)

3.2 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.

id_cl = load('./mat/identification_noise_iff_bis.mat', 'd', 'acc_1', 'acc_2', 'geo_1', 'geo_2', 'f_meas', 'u', 't');
Ts = id_cl.t(2) - id_cl.t(1);
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);

Approximate transfer function from voltage output to generated displacement when IFF is used, in [m/V].

G_d_est = -5e-6*(2*pi*230)^2/(s^2 + 2*0.3*2*pi*240*s + (2*pi*240)^2);

Gd_plant_estimation.png

Figure 7: Estimation of the transfer function from the excitation signal to the generated displacement

3.3 Motion measured during Huddle test

We now compute the PSD of the measured motion by the inertial sensors during the huddle test.

ht = load('./mat/huddle_test.mat', 'd', 'acc_1', 'acc_2', 'geo_1', 'geo_2', 'f_meas', 'u', 't');
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);
[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);

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.

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)]

huddle_test_psd_motion.png

Figure 8: ASD of the motion measured by the sensors

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.

G_exc = 0.2e-6/(1 + s/2/pi/2)/(1 + s/2/pi/50);

And we create a time domain signal y_d that have the spectral density described by G_exc.

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);
[pxx, ~] = pwelch(y_d, win, 0, [], Fs);

comp_huddle_test_excited_motion_psd.png

Figure 9: Comparison of the ASD of the motion during Huddle and the wanted generated motion

We can now generate the voltage signal that will generate the wanted motion.

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);

optimal_exc_signal_time.png

Figure 10: Generated excitation signal

4 Identification of the Inertial Sensors Dynamics

4.1 Load Data

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');
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);
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);

4.2 Compare PSD during Huddle and and during identification

Ts = ht.t(2) - ht.t(1);
win = hann(ceil(10/Ts));
[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);
[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);

comp_psd_huddle_test_identification.png

Figure 11: Comparison of the PSD of the measured motion during the Huddle test and during the identification

4.3 Compute transfer functions

[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);

id_sensor_dynamics_coherence.png

Figure 12: Coherence for the estimation of the sensor dynamics

Model of the inertial sensors:

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)]

id_sensor_dynamics_accelerometers.png

Figure 13: Identified dynamics of the accelerometers

id_sensor_dynamics_geophones.png

Figure 14: Identified dynamics of the geophones

5 Inertial Sensor Noise and H2 Synthesis

5.1 Load Data

id = load('./mat/identification_noise_opt_iff.mat', 'd', 'acc_1', 'acc_2', 'geo_1', 'geo_2', 'f_meas', 'u', 't');
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);

5.2 ASD of the Measured displacement

Ts = id.t(2) - id.t(1);
win = hann(ceil(10/Ts));
[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);

Let’s use a model of the accelerometer and geophone to compute the motion from the measured voltage.

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)]

measure_displacement_all_sensors.png

Figure 15: ASD of the measured displacement as measured by all the sensors

5.3 ASD of the Sensor Noise

  • [ ] Add formula to estimate the noise from data
[coh_acc, ~] = mscohere(id.acc_1, id.acc_2, win, [], [], 1/Ts);
[coh_geo, ~] = mscohere(id.geo_1, id.geo_2, win, [], [], 1/Ts);
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]
figure;
hold on;
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');
hold off;
set(gca, 'xscale', 'log'); set(gca, 'yscale', 'log');
xlabel('Frequency [Hz]'); ylabel('ASD $\left[\frac{m}{\sqrt{Hz}}\right]$');
xlim([1, 5000]); ylim([1e-13, 1e-5]);
legend('location', 'northeast');

noise_inertial_sensors_comparison.png

Figure 16: Comparison of the computed ASD of the noise of the two inertial sensors

5.4 Noise Model

N_acc = 1*(s/(2*pi*2000) + 1)^2/(s + 0.1*2*pi)/(s + 1e3*2*pi); % [m/sqrt(Hz)]
N_geo = 4e-4*(s/(2*pi*200) + 1)/(s + 1e3*2*pi); % [m/sqrt(Hz)]
freqs = logspace(0, 4, 1000);

figure;
hold on;
plot(f, pN_acc.*(2*pi*f), '-', 'DisplayName', 'Accelerometers - Noise');
plot(f, pN_geo.*(2*pi*f), '-', 'DisplayName', 'Geophones - Noise');
set(gca, 'ColorOrderIndex', 1);
plot(freqs, abs(squeeze(freqresp(N_acc, freqs, 'Hz'))), '--', 'DisplayName', 'Geophones - Noise Model');
plot(freqs, abs(squeeze(freqresp(N_geo, freqs, 'Hz'))), '--', 'DisplayName', 'Geophones - Noise Model');
hold off;
set(gca, 'xscale', 'log'); set(gca, 'yscale', 'log');
xlabel('Frequency [Hz]'); ylabel('ASD $\left[\frac{m/s}{\sqrt{Hz}}\right]$');
xlim([1, 5000]);
legend('location', 'northeast');

noise_models_velocity.png

Figure 17: ASD of the velocity noise measured by the sensors and the noise models

5.5 H2 Synthesis

The generalize plant is created.

P = [0      N_acc  1;
     N_geo -N_acc  0];

And we do the \(\mathcal{H}_2\) synthesis using the h2syn command.

[H_geo, ~, gamma] = h2syn(P, 1, 1);
H_acc = 1 - H_geo;

complementary_filters_velocity_H2.png

Figure 18: Obtained Complementary Filters

5.6 Results

freqs = logspace(0, 4, 1000);

figure;
hold on;
plot(f, pN_acc.*(2*pi*f), '-', 'DisplayName', 'Accelerometers - Noise');
plot(f, pN_geo.*(2*pi*f), '-', 'DisplayName', 'Geophones - Noise');
plot(f, sqrt((pN_acc.*(2*pi*f)).^2.*abs(squeeze(freqresp(H_acc, f, 'Hz'))).^2 + (pN_geo.*(2*pi*f)).^2.*abs(squeeze(freqresp(H_geo, f, 'Hz'))).^2), 'k-', 'DisplayName', 'Super Sensor - Noise');
hold off;
set(gca, 'xscale', 'log'); set(gca, 'yscale', 'log');
xlabel('Frequency [Hz]'); ylabel('ASD $\left[\frac{m/s}{\sqrt{Hz}}\right]$');
xlim([1, 5000]);
legend('location', 'northeast');

super_sensor_noise_asd_velocity.png

Figure 19: ASD of the super sensor noise (velocity)

Integrate only down to 1Hz.

[~, i_1Hz] = min(abs(f - 1));
CPS_acc = 1/pi*flip(-cumtrapz(2*pi*flip(f), flip((pN_acc.*(2*pi*f)).^2)));
CPS_geo = 1/pi*flip(-cumtrapz(2*pi*flip(f), flip((pN_geo.*(2*pi*f)).^2)));
CPS_SS  = 1/pi*flip(-cumtrapz(2*pi*flip(f), flip((pN_acc.*(2*pi*f)).^2.*abs(squeeze(freqresp(H_acc, f, 'Hz'))).^2 + (pN_geo.*(2*pi*f)).^2.*abs(squeeze(freqresp(H_geo, f, 'Hz'))).^2)));

super_sensor_noise_cas_velocity.png

Figure 20: Cumulative Power Spectrum of the Sensor Noise (velocity)

6 Inertial Sensor Dynamics Uncertainty

6.1 Load Data

id = load('./mat/identification_noise_opt_iff.mat', 'd', 'acc_1', 'acc_2', 'geo_1', 'geo_2', 'f_meas', 'u', 't');
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);

6.2 Compute the dynamics of both sensors

Ts = id.t(2) - id.t(1);
win = hann(ceil(10/Ts));
[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);

Model of the inertial sensors:

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)]

6.3 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

6.4 Dynamical Uncertainty

[T_acc, ~] = tfestimate(id.acc_1, id.acc_2, win, [], [], Fs);
[T_geo, ~] = tfestimate(id.geo_1, id.geo_2, win, [], [], Fs);

7 To Order

7.1 Huddle Test

The goal here is to measure the noise of the inertial sensors. Is also permits to measure the motion level when nothing is actuated.

7.1.1 Load Data

ht = load('./mat/huddle_test.mat', 'd', 'acc_1', 'acc_2', 'geo_1', 'geo_2', 'f_meas', 'u', 't');

7.1.2 Detrend Data

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]

7.1.3 Compute PSD

We first define the parameters for the frequency domain analysis.

Ts = ht.t(2) - ht.t(1); % [s]
Fs = 1/Ts; % [Hz]

win = hanning(ceil(1*Fs));

Then we compute the Power Spectral Density using pwelch function.

[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);

huddle_test_measured_voltage_inertial_sensors.png

Figure 21: ASD of the measured voltage from the inertial sensors during the Huddle test

7.1.4 Sensor Noise in Volts

[coh_acc, ~] = mscohere(ht.acc_1, ht.acc_2, win, [], [], Fs);
[coh_geo, ~] = mscohere(ht.geo_1, ht.geo_2, win, [], [], Fs);
pN_acc = p_acc1.*(1 - coh_acc);
pN_geo = p_geo1.*(1 - coh_geo);

PSD of the ADC quantization noise.

Sq = (20/2^16)^2/(12*Fs);
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');

7.2 Sensor Dynamics

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.

7.2.1 Time Domain Signals

Excitation signal: noise.

first_exc_signal_time.png

Figure 22: Excitation signal used for the first identification

7.3 H-2 Synthesis - Position

7.3.1 Noise Model

N_acc = 1e-4*(s/(2*pi*2000) + 1)^2/(s + 0.1*2*pi)^2; % [m/sqrt(Hz)]
N_geo = 7e-8*(s/(2*pi*200) + 1)/(s + 0.1*2*pi); % [m/sqrt(Hz)]
freqs = logspace(0, 4, 1000);

figure;
hold on;
plot(f, pN_acc, '-', 'DisplayName', 'Accelerometers - Noise');
plot(f, pN_geo, '-', 'DisplayName', 'Geophones - Noise');
set(gca, 'ColorOrderIndex', 1);
plot(freqs, abs(squeeze(freqresp(N_acc, freqs, 'Hz'))), '--', 'DisplayName', 'Geophones - Noise Model');
plot(freqs, abs(squeeze(freqresp(N_geo, freqs, 'Hz'))), '--', 'DisplayName', 'Geophones - Noise Model');
hold off;
set(gca, 'xscale', 'log'); set(gca, 'yscale', 'log');
xlabel('Frequency [Hz]'); ylabel('ASD $\left[\frac{m}{\sqrt{Hz}}\right]$');
xlim([1, 5000]); ylim([1e-13, 1e-5]);
legend('location', 'northeast');

inertial_sensor_noise_model.png

Figure 23: Measured ASD of the inertial sensor noise and generated noise weighting filters

7.3.2 H2 Synthesis

P = [0      N_acc  1;
     N_geo -N_acc  0];

And we do the \(\mathcal{H}_2\) synthesis using the h2syn command.

[H_geo, ~, gamma] = h2syn(P, 1, 1);
H_acc = 1 - H_geo;

opt_complementary_filters.png

7.3.3 Results

freqs = logspace(0, 4, 1000);

figure;
hold on;
plot(f, pN_acc, '-', 'DisplayName', 'Accelerometers - Noise');
plot(f, pN_geo, '-', 'DisplayName', 'Geophones - Noise');
plot(f, sqrt(pN_acc.^2.*abs(squeeze(freqresp(H_acc, f, 'Hz'))).^2 + pN_geo.^2.*abs(squeeze(freqresp(H_geo, f, 'Hz'))).^2), 'k-', 'DisplayName', 'Super Sensor - Noise');
hold off;
set(gca, 'xscale', 'log'); set(gca, 'yscale', 'log');
xlabel('Frequency [Hz]'); ylabel('ASD $\left[\frac{m}{\sqrt{Hz}}\right]$');
xlim([1, 5000]); ylim([1e-13, 1e-5]);
legend('location', 'northeast');

Integrate only down to 1Hz.

[~, i_1Hz] = min(abs(f - 1));
CPS_acc = 1/pi*flip(-cumtrapz(2*pi*flip(f), flip(pN_acc.^2)));
CPS_geo = 1/pi*flip(-cumtrapz(2*pi*flip(f), flip(pN_geo.^2)));
CPS_SS  = 1/pi*flip(-cumtrapz(2*pi*flip(f), flip(pN_acc.^2.*abs(squeeze(freqresp(H_acc, f, 'Hz'))).^2 + pN_geo.^2.*abs(squeeze(freqresp(H_geo, f, 'Hz'))).^2)));

7.4 Compare Time domain Estimation of the displacement

Let’s compare the measured accelerations instead of displacement (no integration).

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);
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);
int_a = lsim(s^2*G_lpf*G_lpf, id.d, id.t);
figure;
hold on;
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);
hold off;
xlabel('Time [s]'); ylabel('Acceleration [m]');

Author: Dehaeze Thomas

Created: 2020-09-14 lun. 09:51