1235 lines
48 KiB
TeX
1235 lines
48 KiB
TeX
|
% Created 2021-02-02 mar. 18:51
|
||
|
% Intended LaTeX compiler: pdflatex
|
||
|
\documentclass[tocnp, secbreak, minted]{cleanreport}
|
||
|
\usepackage[utf8]{inputenc}
|
||
|
\usepackage[T1]{fontenc}
|
||
|
\usepackage{graphicx}
|
||
|
\usepackage{grffile}
|
||
|
\usepackage{longtable}
|
||
|
\usepackage{wrapfig}
|
||
|
\usepackage{rotating}
|
||
|
\usepackage[normalem]{ulem}
|
||
|
\usepackage{amsmath}
|
||
|
\usepackage{textcomp}
|
||
|
\usepackage{amssymb}
|
||
|
\usepackage{capt-of}
|
||
|
\usepackage{hyperref}
|
||
|
\usepackage[most]{tcolorbox}
|
||
|
\usepackage{bm}
|
||
|
\usepackage{booktabs}
|
||
|
\usepackage{tabularx}
|
||
|
\usepackage{array}
|
||
|
\usepackage{siunitx}
|
||
|
\newcommand{\authorFirstName}{Thomas}
|
||
|
\newcommand{\authorLastName}{Dehaeze}
|
||
|
\newcommand{\authorEmail}{dehaeze.thomas@gmail.com}
|
||
|
\usepackage[cache=false]{minted}
|
||
|
\usemintedstyle{autumn}
|
||
|
\setminted[matlab]{linenos=true, breaklines=true, tabsize=4, fontsize=\scriptsize, autogobble=true}
|
||
|
\makeatletter
|
||
|
\preto\Gin@extensions{png,}
|
||
|
\DeclareGraphicsRule{.png}{pdf}{.pdf}{\noexpand\Gin@base.pdf}
|
||
|
\makeatother
|
||
|
\addbibresource{ref.bib}
|
||
|
\author{Dehaeze Thomas}
|
||
|
\date{\today}
|
||
|
\title{Sensor Fusion - Test Bench}
|
||
|
\hypersetup{
|
||
|
pdfauthor={Dehaeze Thomas},
|
||
|
pdftitle={Sensor Fusion - Test Bench},
|
||
|
pdfkeywords={},
|
||
|
pdfsubject={},
|
||
|
pdfcreator={Emacs 27.1 (Org mode 9.5)},
|
||
|
pdflang={English}}
|
||
|
\begin{document}
|
||
|
|
||
|
\maketitle
|
||
|
\setcounter{tocdepth}{2}
|
||
|
\tableofcontents
|
||
|
|
||
|
|
||
|
In this document, we wish the experimentally validate sensor fusion of inertial sensors.
|
||
|
|
||
|
This document is divided into the following sections:
|
||
|
\begin{itemize}
|
||
|
\item Section \ref{sec:experimental_setup}: the experimental setup is described
|
||
|
\item Section \ref{sec:first_identification}: a first identification of the system dynamics is performed
|
||
|
\item Section \ref{sec:integral_force_feedback}: the integral force feedback active damping technique is applied on the system
|
||
|
\item Section \ref{sec:optimal_excitation}: the optimal excitation signal is determine in order to have the best possible system dynamics estimation
|
||
|
\item Section \ref{sec:inertial_sensor_dynamics}: the inertial sensor dynamics are experimentally estimated
|
||
|
\item Section \ref{sec:inertial_sensor_noise}: the inertial sensor noises are estimated and the \(\mathcal{H}_2\) synthesis of complementary filters is performed in order to yield a super sensor with minimal noise
|
||
|
\item Section \ref{sec:inertial_sensor_uncertainty}: the dynamical uncertainty of the inertial sensors is estimated. Then the \(\mathcal{H}_\infty\) synthesis of complementary filters is performed in order to minimize the super sensor dynamical uncertainty
|
||
|
\item Section \ref{sec:optimal_sensor_fusion}: Optimal sensor fusion is performed using the \(\mathcal{H}_2/\mathcal{H}_\infty\) synthesis
|
||
|
\end{itemize}
|
||
|
|
||
|
\section{Experimental Setup}
|
||
|
\label{sec:org946e8f3}
|
||
|
\label{sec: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.
|
||
|
|
||
|
A schematic of the test-bench used is shown in Figure \ref{fig:exp_setup_sensor_fusion} and a picture of it is shown in Figure \ref{fig:test-bench-sensor-fusion-picture}.
|
||
|
|
||
|
\begin{figure}[htbp]
|
||
|
\centering
|
||
|
\includegraphics[scale=1]{figs/exp_setup_sensor_fusion.png}
|
||
|
\caption{\label{fig:exp_setup_sensor_fusion}Schematic of the test-bench}
|
||
|
\end{figure}
|
||
|
|
||
|
\begin{figure}[htbp]
|
||
|
\centering
|
||
|
\includegraphics[scale=1]{figs/test-bench-sensor-fusion-picture.png}
|
||
|
\caption{\label{fig:test-bench-sensor-fusion-picture}Picture of the test-bench}
|
||
|
\end{figure}
|
||
|
|
||
|
|
||
|
Two inertial sensors are used:
|
||
|
\begin{itemize}
|
||
|
\item An vertical accelerometer \emph{PCB 393B05} (\href{doc/TM-VIB-Seismic\_Lowres.pdf}{doc})
|
||
|
\item A vertical geophone \emph{Mark Product L-22}
|
||
|
\end{itemize}
|
||
|
|
||
|
Basic characteristics of both sensors are shown in Tables \ref{tab:393B05_spec} and \ref{tab:L22_spec}.
|
||
|
|
||
|
\begin{table}[htbp]
|
||
|
\caption{\label{tab:393B05_spec}Accelerometer (393B05) Specifications}
|
||
|
\centering
|
||
|
\begin{tabular}{ll}
|
||
|
\textbf{Specification} & \textbf{Value}\\
|
||
|
\hline
|
||
|
Sensitivity & 1.02 [V/(m/s2)]\\
|
||
|
Resonant Frequency & > 2.5 [kHz]\\
|
||
|
Resolution (1 to 10kHz) & 0.00004 [m/s2 rms]\\
|
||
|
\end{tabular}
|
||
|
\end{table}
|
||
|
|
||
|
\begin{table}[htbp]
|
||
|
\caption{\label{tab:L22_spec}Geophone (L22) Specifications}
|
||
|
\centering
|
||
|
\begin{tabular}{ll}
|
||
|
\textbf{Specification} & \textbf{Value}\\
|
||
|
\hline
|
||
|
Sensitivity & To be measured [V/(m/s)]\\
|
||
|
Resonant Frequency & 2 [Hz]\\
|
||
|
\end{tabular}
|
||
|
\end{table}
|
||
|
|
||
|
The ADC used are the IO131 Speedgoat module (\href{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 (\href{doc/de-dlpva-100-b.pdf}{doc}).
|
||
|
The force sensor signal is amplified using a Low Noise Voltage Preamplifier from Ametek (\href{doc/model\_5113.pdf}{doc}).
|
||
|
|
||
|
The excitation signal is amplified by a linear amplified from Cedrat (LA75B) with a gain equals to 20 (\href{doc/LA75B.pdf}{doc}).
|
||
|
|
||
|
Geophone electronics:
|
||
|
\begin{itemize}
|
||
|
\item gain: 10 (20dB)
|
||
|
\item low pass filter: 1.5Hz
|
||
|
\item hifh pass filter: 100kHz (2nd order)
|
||
|
\end{itemize}
|
||
|
|
||
|
Force Sensor electronics:
|
||
|
\begin{itemize}
|
||
|
\item gain: 10 (20dB)
|
||
|
\item low pass filter: 1st order at 3Hz
|
||
|
\item high pass filter: 1st order at 30kHz
|
||
|
\end{itemize}
|
||
|
|
||
|
\section{First identification of the system}
|
||
|
\label{sec:org9f0c4bc}
|
||
|
\label{sec:first_identification}
|
||
|
In this section, a first identification of each elements of the system is performed.
|
||
|
This include the dynamics from the actuator to the force sensor, interferometer and inertial sensors.
|
||
|
|
||
|
Each of the dynamics is compared with the dynamics identified form a Simscape model.
|
||
|
\subsection{Load Data}
|
||
|
\label{sec:org1fb8239}
|
||
|
The data is loaded in the Matlab workspace.
|
||
|
\begin{minted}[]{matlab}
|
||
|
id_ol = load('identification_noise_bis.mat', 'd', 'acc_1', 'acc_2', 'geo_1', 'geo_2', 'f_meas', 'u', 't');
|
||
|
\end{minted}
|
||
|
|
||
|
Then, any offset is removed.
|
||
|
\begin{minted}[]{matlab}
|
||
|
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{minted}
|
||
|
|
||
|
\subsection{Excitation Signal}
|
||
|
\label{sec:org94ea93c}
|
||
|
The generated voltage used to excite the system is a white noise and can be seen in Figure \ref{fig:excitation_signal_first_identification}.
|
||
|
|
||
|
\begin{figure}[htbp]
|
||
|
\centering
|
||
|
\includegraphics[scale=1]{figs/excitation_signal_first_identification.png}
|
||
|
\caption{\label{fig:excitation_signal_first_identification}Voltage excitation signal}
|
||
|
\end{figure}
|
||
|
|
||
|
\subsection{Identified Plant}
|
||
|
\label{sec:org2786526}
|
||
|
The transfer function from the excitation voltage to the mass displacement and to the force sensor stack voltage are identified using the \texttt{tfestimate} command.
|
||
|
|
||
|
\begin{minted}[]{matlab}
|
||
|
Ts = id_ol.t(2) - id_ol.t(1);
|
||
|
win = hann(ceil(10/Ts));
|
||
|
\end{minted}
|
||
|
|
||
|
\begin{minted}[]{matlab}
|
||
|
[tf_fmeas_est, f] = tfestimate(id_ol.u, id_ol.f_meas, win, [], [], 1/Ts); % [V/V]
|
||
|
[tf_G_ol_est, ~] = tfestimate(id_ol.u, id_ol.d, win, [], [], 1/Ts); % [m/V]
|
||
|
\end{minted}
|
||
|
|
||
|
The bode plots of the obtained dynamics are shown in Figures \ref{fig:force_sensor_bode_plot} and \ref{fig:displacement_sensor_bode_plot}.
|
||
|
|
||
|
\begin{figure}[htbp]
|
||
|
\centering
|
||
|
\includegraphics[scale=1]{figs/force_sensor_bode_plot.png}
|
||
|
\caption{\label{fig:force_sensor_bode_plot}Bode plot of the dynamics from excitation voltage to measured force sensor stack voltage}
|
||
|
\end{figure}
|
||
|
|
||
|
\begin{figure}[htbp]
|
||
|
\centering
|
||
|
\includegraphics[scale=1]{figs/displacement_sensor_bode_plot.png}
|
||
|
\caption{\label{fig:displacement_sensor_bode_plot}Bode plot of the dynamics from excitation voltage to displacement of the mass as measured by the interferometer}
|
||
|
\end{figure}
|
||
|
|
||
|
\subsection{Simscape Model - Comparison}
|
||
|
\label{sec:org38a7789}
|
||
|
A simscape model representing the test-bench has been developed.
|
||
|
The same transfer functions as the one identified using the test-bench can be obtained thanks to the simscape model.
|
||
|
|
||
|
They are compared in Figure \ref{fig:simscape_comp_iff_plant} and \ref{fig:simscape_comp_disp_plant}.
|
||
|
It is shown that there is a good agreement between the model and the experiment.
|
||
|
|
||
|
\begin{minted}[]{matlab}
|
||
|
load('piezo_amplified_3d.mat', 'int_xyz', 'int_i', 'n_xyz', 'n_i', 'nodes', 'M', 'K');
|
||
|
\end{minted}
|
||
|
|
||
|
\begin{figure}[htbp]
|
||
|
\centering
|
||
|
\includegraphics[scale=1]{figs/simscape_comp_iff_plant.png}
|
||
|
\caption{\label{fig:simscape_comp_iff_plant}Comparison of the dynamics from excitation voltage to measured force sensor stack voltage - Identified dynamics and Simscape Model}
|
||
|
\end{figure}
|
||
|
|
||
|
\begin{figure}[htbp]
|
||
|
\centering
|
||
|
\includegraphics[scale=1]{figs/simscape_comp_disp_plant.png}
|
||
|
\caption{\label{fig:simscape_comp_disp_plant}Comparison of the dynamics from excitation voltage to measured mass displacement - Identified dynamics and Simscape Model}
|
||
|
\end{figure}
|
||
|
|
||
|
\subsection{Integral Force Feedback}
|
||
|
\label{sec:org47d5680}
|
||
|
The force sensor stack can be used to damp the system.
|
||
|
This makes the system easier to excite properly without too much amplification near resonances.
|
||
|
|
||
|
This is done thanks to the integral force feedback control architecture.
|
||
|
|
||
|
The force sensor stack signal is integrated (or rather low pass filtered) and fed back to the force sensor stacks.
|
||
|
|
||
|
The low pass filter used as the controller is defined below:
|
||
|
\begin{minted}[]{matlab}
|
||
|
Kiff = 102/(s + 2*pi*2);
|
||
|
\end{minted}
|
||
|
|
||
|
The integral force feedback control strategy is applied to the simscape model as well as to the real test bench.
|
||
|
|
||
|
The damped system is then identified again using a noise excitation.
|
||
|
|
||
|
The data is loaded into Matlab and any offset is removed.
|
||
|
\begin{minted}[]{matlab}
|
||
|
id_cl = load('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);
|
||
|
\end{minted}
|
||
|
|
||
|
The transfer functions are estimated using \texttt{tfestimate}.
|
||
|
\begin{minted}[]{matlab}
|
||
|
[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{minted}
|
||
|
|
||
|
The dynamics from driving voltage to the measured displacement are compared both in the open-loop and IFF case, and for the test-bench experimental identification and for the Simscape model in Figure \ref{fig:iff_ol_cl_identified_simscape_comp}.
|
||
|
This shows that the Integral Force Feedback architecture effectively damps the first resonance of the system.
|
||
|
|
||
|
\begin{figure}[htbp]
|
||
|
\centering
|
||
|
\includegraphics[scale=1]{figs/iff_ol_cl_identified_simscape_comp.png}
|
||
|
\caption{\label{fig:iff_ol_cl_identified_simscape_comp}Comparison of the open-loop and closed-loop (IFF) dynamics for both the real identification and the Simscape one}
|
||
|
\end{figure}
|
||
|
|
||
|
\subsection{Inertial Sensors}
|
||
|
\label{sec:orgfc5acd9}
|
||
|
In order to estimate the dynamics of the inertial sensor (the transfer function from the ``absolute'' displacement to the measured voltage), the following experiment can be performed:
|
||
|
\begin{itemize}
|
||
|
\item The mass is excited such that is relative displacement as measured by the interferometer is much larger that the ground ``absolute'' motion.
|
||
|
\item The transfer function from the measured displacement by the interferometer to the measured voltage generated by the inertial sensors can be estimated.
|
||
|
\end{itemize}
|
||
|
|
||
|
The first point is quite important in order to have a good coherence between the interferometer measurement and the inertial sensor measurement.
|
||
|
|
||
|
Here, a first identification is performed were the excitation signal is a white noise.
|
||
|
|
||
|
|
||
|
As usual, the data is loaded and any offset is removed.
|
||
|
\begin{minted}[]{matlab}
|
||
|
id = load('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);
|
||
|
\end{minted}
|
||
|
|
||
|
Then the transfer functions from the measured displacement by the interferometer to the generated voltage of the inertial sensors are computed..
|
||
|
\begin{minted}[]{matlab}
|
||
|
Ts = id.t(2) - id.t(1);
|
||
|
win = hann(ceil(10/Ts));
|
||
|
\end{minted}
|
||
|
|
||
|
\begin{minted}[]{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{minted}
|
||
|
|
||
|
The same transfer functions are estimated using the Simscape model.
|
||
|
|
||
|
The obtained dynamics of the accelerometer are compared in Figure \ref{fig:comp_dynamics_accelerometer} while the one of the geophones are compared in Figure \ref{fig:comp_dynamics_geophone}.
|
||
|
|
||
|
\begin{figure}[htbp]
|
||
|
\centering
|
||
|
\includegraphics[scale=1]{figs/comp_dynamics_accelerometer.png}
|
||
|
\caption{\label{fig:comp_dynamics_accelerometer}Comparison of the measured accelerometer dynamics}
|
||
|
\end{figure}
|
||
|
|
||
|
\begin{figure}[htbp]
|
||
|
\centering
|
||
|
\includegraphics[scale=1]{figs/comp_dynamics_geophone.png}
|
||
|
\caption{\label{fig:comp_dynamics_geophone}Comparison of the measured geophone dynamics}
|
||
|
\end{figure}
|
||
|
|
||
|
\section{Optimal IFF Development}
|
||
|
\label{sec:orgb6f0a44}
|
||
|
\label{sec:integral_force_feedback}
|
||
|
In this section, a proper identification of the transfer function from the force actuator to the force sensor is performed.
|
||
|
Then, an optimal IFF controller is developed and applied experimentally.
|
||
|
|
||
|
The damped system is identified to verified the effectiveness of the added method.
|
||
|
\subsection{Load Data}
|
||
|
\label{sec:orgd2c4449}
|
||
|
The experimental data is loaded and any offset is removed.
|
||
|
\begin{minted}[]{matlab}
|
||
|
id_ol = load('identification_noise_bis.mat', 'd', 'acc_1', 'acc_2', 'geo_1', 'geo_2', 'f_meas', 'u', 't');
|
||
|
\end{minted}
|
||
|
|
||
|
\begin{minted}[]{matlab}
|
||
|
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{minted}
|
||
|
|
||
|
\subsection{Experimental Data}
|
||
|
\label{sec:orge97f045}
|
||
|
The transfer function from force actuator to force sensors is estimated.
|
||
|
|
||
|
The coherence shown in Figure \ref{fig:iff_identification_coh} shows that the excitation signal is good enough.
|
||
|
|
||
|
\begin{minted}[]{matlab}
|
||
|
Ts = id_ol.t(2) - id_ol.t(1);
|
||
|
win = hann(ceil(10/Ts));
|
||
|
\end{minted}
|
||
|
|
||
|
\begin{minted}[]{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{minted}
|
||
|
|
||
|
\begin{figure}[htbp]
|
||
|
\centering
|
||
|
\includegraphics[scale=1]{figs/iff_identification_coh.png}
|
||
|
\caption{\label{fig:iff_identification_coh}Coherence for the identification of the IFF plant}
|
||
|
\end{figure}
|
||
|
|
||
|
The obtained dynamics is shown in Figure \ref{fig:iff_identification_bode_plot}.
|
||
|
|
||
|
\begin{figure}[htbp]
|
||
|
\centering
|
||
|
\includegraphics[scale=1]{figs/iff_identification_bode_plot.png}
|
||
|
\caption{\label{fig:iff_identification_bode_plot}Bode plot of the identified IFF plant}
|
||
|
\end{figure}
|
||
|
|
||
|
\subsection{Model of the IFF Plant}
|
||
|
\label{sec:orge4307c5}
|
||
|
In order to plot the root locus for the IFF control strategy, a model of the identified plant is developed.
|
||
|
|
||
|
It consists of several poles and zeros are shown below.
|
||
|
\begin{minted}[]{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{minted}
|
||
|
|
||
|
The comparison of the identified dynamics and the developed model is done in Figure \ref{fig:iff_plant_model}.
|
||
|
|
||
|
\begin{figure}[htbp]
|
||
|
\centering
|
||
|
\includegraphics[scale=1]{figs/iff_plant_model.png}
|
||
|
\caption{\label{fig:iff_plant_model}IFF Plant + Model}
|
||
|
\end{figure}
|
||
|
|
||
|
\subsection{Root Locus and optimal Controller}
|
||
|
\label{sec:orgb8dd861}
|
||
|
Now, the root locus for the Integral Force Feedback strategy is computed and shown in Figure \ref{fig:iff_root_locus}.
|
||
|
|
||
|
Note that the controller used is not a pure integrator but rather a first order low pass filter with a cut-off frequency set at 2Hz.
|
||
|
|
||
|
\begin{figure}[htbp]
|
||
|
\centering
|
||
|
\includegraphics[scale=1]{figs/iff_root_locus.png}
|
||
|
\caption{\label{fig:iff_root_locus}Root Locus for the IFF control}
|
||
|
\end{figure}
|
||
|
|
||
|
The controller that yield maximum damping (shown by the red cross in Figure \ref{fig:iff_root_locus}) is:
|
||
|
\begin{minted}[]{matlab}
|
||
|
Kiff_opt = 102/(s + 2*pi*2);
|
||
|
\end{minted}
|
||
|
|
||
|
\subsection{Verification of the achievable damping}
|
||
|
\label{sec:orgb0f79ca}
|
||
|
A new identification is performed with the IFF control strategy applied to the system.
|
||
|
|
||
|
Data is loaded and offset removed.
|
||
|
\begin{minted}[]{matlab}
|
||
|
id_cl = load('identification_noise_iff_bis.mat', 'd', 'acc_1', 'acc_2', 'geo_1', 'geo_2', 'f_meas', 'u', 't');
|
||
|
\end{minted}
|
||
|
|
||
|
\begin{minted}[]{matlab}
|
||
|
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{minted}
|
||
|
|
||
|
The open-loop and closed-loop dynamics are estimated.
|
||
|
\begin{minted}[]{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{minted}
|
||
|
|
||
|
The obtained coherence is shown in Figure \ref{fig:Gd_identification_iff_coherence} and the dynamics in Figure \ref{fig:Gd_identification_iff_bode_plot}.
|
||
|
|
||
|
\begin{figure}[htbp]
|
||
|
\centering
|
||
|
\includegraphics[scale=1]{figs/Gd_identification_iff_coherence.png}
|
||
|
\caption{\label{fig:Gd_identification_iff_coherence}Coherence for the transfer function from F to d, with and without IFF}
|
||
|
\end{figure}
|
||
|
|
||
|
|
||
|
\begin{figure}[htbp]
|
||
|
\centering
|
||
|
\includegraphics[scale=1]{figs/Gd_identification_iff_bode_plot.png}
|
||
|
\caption{\label{fig:Gd_identification_iff_bode_plot}Coherence for the transfer function from F to d, with and without IFF}
|
||
|
\end{figure}
|
||
|
|
||
|
\section{Generate the excitation signal}
|
||
|
\label{sec:org043d407}
|
||
|
\label{sec:optimal_excitation}
|
||
|
In order to properly estimate the dynamics of the inertial sensor, the excitation signal must be properly chosen.
|
||
|
|
||
|
The requirements on the excitation signal is:
|
||
|
\begin{itemize}
|
||
|
\item General much larger motion that the measured motion during the huddle test
|
||
|
\item Don't damage the actuator
|
||
|
\end{itemize}
|
||
|
|
||
|
To determine the perfect voltage signal to be generated, we need two things:
|
||
|
\begin{itemize}
|
||
|
\item the transfer function from voltage to mass displacement
|
||
|
\item the PSD of the measured motion by the inertial sensors
|
||
|
\item not saturate the sensor signals
|
||
|
\item provide enough signal/noise ratio (good coherence) in the frequency band of interest (\textasciitilde{}0.5Hz to 3kHz)
|
||
|
\end{itemize}
|
||
|
\subsection{Transfer function from excitation signal to displacement}
|
||
|
\label{sec:orgc386ade}
|
||
|
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{minted}[]{matlab}
|
||
|
id_cl = load('identification_noise_iff_bis.mat', 'd', 'acc_1', 'acc_2', 'geo_1', 'geo_2', 'f_meas', 'u', 't');
|
||
|
\end{minted}
|
||
|
|
||
|
\begin{minted}[]{matlab}
|
||
|
Ts = id_cl.t(2) - id_cl.t(1);
|
||
|
win = hann(ceil(10/Ts));
|
||
|
\end{minted}
|
||
|
|
||
|
\begin{minted}[]{matlab}
|
||
|
[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{minted}
|
||
|
|
||
|
Approximate transfer function from voltage output to generated displacement when IFF is used, in [m/V].
|
||
|
\begin{minted}[]{matlab}
|
||
|
G_d_est = -5e-6*(2*pi*230)^2/(s^2 + 2*0.3*2*pi*240*s + (2*pi*240)^2);
|
||
|
\end{minted}
|
||
|
|
||
|
\begin{figure}[htbp]
|
||
|
\centering
|
||
|
\includegraphics[scale=1]{figs/Gd_plant_estimation.png}
|
||
|
\caption{\label{fig:Gd_plant_estimation}Estimation of the transfer function from the excitation signal to the generated displacement}
|
||
|
\end{figure}
|
||
|
|
||
|
\subsection{Motion measured during Huddle test}
|
||
|
\label{sec:org34b9217}
|
||
|
We now compute the PSD of the measured motion by the inertial sensors during the huddle test.
|
||
|
\begin{minted}[]{matlab}
|
||
|
ht = load('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);
|
||
|
\end{minted}
|
||
|
|
||
|
\begin{minted}[]{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{minted}
|
||
|
|
||
|
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{minted}[]{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{minted}
|
||
|
|
||
|
\begin{figure}[htbp]
|
||
|
\centering
|
||
|
\includegraphics[scale=1]{figs/huddle_test_psd_motion.png}
|
||
|
\caption{\label{fig:huddle_test_psd_motion}ASD of the motion measured by the sensors}
|
||
|
\end{figure}
|
||
|
|
||
|
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 \texttt{G\_exc} that corresponds to the wanted generated motion.
|
||
|
\begin{minted}[]{matlab}
|
||
|
G_exc = 0.2e-6/(1 + s/2/pi/2)/(1 + s/2/pi/50);
|
||
|
\end{minted}
|
||
|
|
||
|
And we create a time domain signal \texttt{y\_d} that have the spectral density described by \texttt{G\_exc}.
|
||
|
\begin{minted}[]{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{minted}
|
||
|
|
||
|
\begin{minted}[]{matlab}
|
||
|
[pxx, ~] = pwelch(y_d, win, 0, [], Fs);
|
||
|
\end{minted}
|
||
|
|
||
|
\begin{figure}[htbp]
|
||
|
\centering
|
||
|
\includegraphics[scale=1]{figs/comp_huddle_test_excited_motion_psd.png}
|
||
|
\caption{\label{fig:comp_huddle_test_excited_motion_psd}Comparison of the ASD of the motion during Huddle and the wanted generated motion}
|
||
|
\end{figure}
|
||
|
|
||
|
|
||
|
We can now generate the voltage signal that will generate the wanted motion.
|
||
|
\begin{minted}[]{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{minted}
|
||
|
|
||
|
\begin{figure}[htbp]
|
||
|
\centering
|
||
|
\includegraphics[scale=1]{figs/optimal_exc_signal_time.png}
|
||
|
\caption{\label{fig:optimal_exc_signal_time}Generated excitation signal}
|
||
|
\end{figure}
|
||
|
|
||
|
\section{Identification of the Inertial Sensors Dynamics}
|
||
|
\label{sec:org8247cdc}
|
||
|
\label{sec:inertial_sensor_dynamics}
|
||
|
Using the excitation signal generated in Section \ref{sec:optimal_excitation}, the dynamics of the inertial sensors are identified.
|
||
|
\subsection{Load Data}
|
||
|
\label{sec:org672e9e4}
|
||
|
Both the measurement data during the identification test and during an ``huddle test'' are loaded.
|
||
|
\begin{minted}[]{matlab}
|
||
|
id = load('identification_noise_opt_iff.mat', 'd', 'acc_1', 'acc_2', 'geo_1', 'geo_2', 'f_meas', 'u', 't');
|
||
|
ht = load('huddle_test.mat', 'd', 'acc_1', 'acc_2', 'geo_1', 'geo_2', 'f_meas', 'u', 't');
|
||
|
\end{minted}
|
||
|
|
||
|
\begin{minted}[]{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{minted}
|
||
|
|
||
|
\begin{minted}[]{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{minted}
|
||
|
|
||
|
\subsection{Compare PSD during Huddle and and during identification}
|
||
|
\label{sec:org5c0ada4}
|
||
|
The Power Spectral Density of the measured motion during the huddle test and during the identification test are compared in Figures \ref{fig:comp_psd_huddle_test_identification_acc} and \ref{fig:comp_psd_huddle_test_identification_geo}.
|
||
|
|
||
|
\begin{minted}[]{matlab}
|
||
|
Ts = ht.t(2) - ht.t(1);
|
||
|
win = hann(ceil(10/Ts));
|
||
|
\end{minted}
|
||
|
|
||
|
\begin{minted}[]{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);
|
||
|
\end{minted}
|
||
|
|
||
|
\begin{minted}[]{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{minted}
|
||
|
|
||
|
\begin{figure}[htbp]
|
||
|
\centering
|
||
|
\includegraphics[scale=1]{figs/comp_psd_huddle_test_identification_acc.png}
|
||
|
\caption{\label{fig:comp_psd_huddle_test_identification_acc}Comparison of the PSD of the measured motion during the Huddle test and during the identification}
|
||
|
\end{figure}
|
||
|
|
||
|
\begin{figure}[htbp]
|
||
|
\centering
|
||
|
\includegraphics[scale=1]{figs/comp_psd_huddle_test_identification_geo.png}
|
||
|
\caption{\label{fig:comp_psd_huddle_test_identification_geo}Comparison of the PSD of the measured motion during the Huddle test and during the identification}
|
||
|
\end{figure}
|
||
|
|
||
|
\subsection{Compute transfer functions}
|
||
|
\label{sec:org410c99d}
|
||
|
The transfer functions from the motion as measured by the interferometer (and that should represent the absolute motion of the mass) to the inertial sensors are estimated:
|
||
|
\begin{minted}[]{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{minted}
|
||
|
|
||
|
The obtained coherence are shown in Figure \ref{fig:id_sensor_dynamics_coherence}.
|
||
|
|
||
|
\begin{figure}[htbp]
|
||
|
\centering
|
||
|
\includegraphics[scale=1]{figs/id_sensor_dynamics_coherence.png}
|
||
|
\caption{\label{fig:id_sensor_dynamics_coherence}Coherence for the estimation of the sensor dynamics}
|
||
|
\end{figure}
|
||
|
|
||
|
We also make a simplified model of the inertial sensors to be compared with the identified dynamics.
|
||
|
\begin{minted}[]{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{minted}
|
||
|
|
||
|
The model and identified dynamics show good agreement (Figures \ref{fig:id_sensor_dynamics_accelerometers} and \ref{fig:id_sensor_dynamics_geophones}.)
|
||
|
|
||
|
\begin{figure}[htbp]
|
||
|
\centering
|
||
|
\includegraphics[scale=1]{figs/id_sensor_dynamics_accelerometers.png}
|
||
|
\caption{\label{fig:id_sensor_dynamics_accelerometers}Identified dynamics of the accelerometers}
|
||
|
\end{figure}
|
||
|
|
||
|
\begin{figure}[htbp]
|
||
|
\centering
|
||
|
\includegraphics[scale=1]{figs/id_sensor_dynamics_geophones.png}
|
||
|
\caption{\label{fig:id_sensor_dynamics_geophones}Identified dynamics of the geophones}
|
||
|
\end{figure}
|
||
|
|
||
|
\section{Inertial Sensor Noise and the \(\mathcal{H}_2\) Synthesis of complementary filters}
|
||
|
\label{sec:org24cccda}
|
||
|
\label{sec:inertial_sensor_noise}
|
||
|
In this section, the noise of the inertial sensors (geophones and accelerometers) is estimated.
|
||
|
\subsection{Load Data}
|
||
|
\label{sec:org3669b51}
|
||
|
As before, the identification data is loaded and any offset if removed.
|
||
|
\begin{minted}[]{matlab}
|
||
|
id = load('identification_noise_opt_iff.mat', 'd', 'acc_1', 'acc_2', 'geo_1', 'geo_2', 'f_meas', 'u', 't');
|
||
|
\end{minted}
|
||
|
|
||
|
\begin{minted}[]{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{minted}
|
||
|
|
||
|
\subsection{ASD of the Measured displacement}
|
||
|
\label{sec:orgb545abb}
|
||
|
The Power Spectral Density of the displacement as measured by the interferometer and the inertial sensors is computed.
|
||
|
\begin{minted}[]{matlab}
|
||
|
Ts = id.t(2) - id.t(1);
|
||
|
win = hann(ceil(10/Ts));
|
||
|
\end{minted}
|
||
|
|
||
|
\begin{minted}[]{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);
|
||
|
\end{minted}
|
||
|
|
||
|
Let's use a model of the accelerometer and geophone to compute the motion from the measured voltage.
|
||
|
\begin{minted}[]{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{minted}
|
||
|
|
||
|
The obtained ASD in \(m/\sqrt{Hz}\) is shown in Figure \ref{fig:measure_displacement_all_sensors}.
|
||
|
|
||
|
\begin{figure}[htbp]
|
||
|
\centering
|
||
|
\includegraphics[scale=1]{figs/measure_displacement_all_sensors.png}
|
||
|
\caption{\label{fig:measure_displacement_all_sensors}ASD of the measured displacement as measured by all the sensors}
|
||
|
\end{figure}
|
||
|
|
||
|
\subsection{ASD of the Sensor Noise}
|
||
|
\label{sec:orge92b139}
|
||
|
The noise of a sensor can be estimated using two identical sensors by computing:
|
||
|
\begin{itemize}
|
||
|
\item the Power Spectral Density of the measured motion by the two sensors
|
||
|
\item the Cross Spectral Density between the two sensors (coherence)
|
||
|
\end{itemize}
|
||
|
|
||
|
This technique to estimate the sensor noise is described in \cite{barzilai98_techn_measur_noise_sensor_presen}.
|
||
|
|
||
|
The Power Spectral Density of the sensor noise can be estimated using the following equation:
|
||
|
\begin{equation}
|
||
|
|S_n(\omega)| = |S_{x_1}(\omega)| \Big( 1 - \gamma_{x_1 x_2}(\omega) \Big)
|
||
|
\end{equation}
|
||
|
with \(S_{x_1}\) the PSD of one of the sensor and \(\gamma_{x_1 x_2}\) the coherence between the two sensors.
|
||
|
|
||
|
The coherence between the two accelerometers and between the two geophones is computed.
|
||
|
\begin{minted}[]{matlab}
|
||
|
[coh_acc, ~] = mscohere(id.acc_1, id.acc_2, win, [], [], 1/Ts);
|
||
|
[coh_geo, ~] = mscohere(id.geo_1, id.geo_2, win, [], [], 1/Ts);
|
||
|
\end{minted}
|
||
|
|
||
|
Finally, the Power Spectral Density of the sensors is computed and converted in \([m^2/Hz]\).
|
||
|
\begin{minted}[]{matlab}
|
||
|
pN_acc = p_id_acc1.*(1 - coh_acc) .* ... % [V^2/Hz]
|
||
|
1./abs(squeeze(freqresp(G_acc*s^2, f, 'Hz'))).^2; % [(m/V)^2]
|
||
|
pN_geo = p_id_geo1.*(1 - coh_geo) .* ... % [V^2/Hz]
|
||
|
1./abs(squeeze(freqresp(G_geo*s, f, 'Hz'))).^2; % [(m/V)^2]
|
||
|
\end{minted}
|
||
|
|
||
|
The ASD of obtained noises are compared with the ASD of the measured signals in Figure \ref{fig:noise_inertial_sensors_comparison}.
|
||
|
\begin{figure}[htbp]
|
||
|
\centering
|
||
|
\includegraphics[scale=1]{figs/noise_inertial_sensors_comparison.png}
|
||
|
\caption{\label{fig:noise_inertial_sensors_comparison}Comparison of the computed ASD of the noise of the two inertial sensors}
|
||
|
\end{figure}
|
||
|
|
||
|
\subsection{Noise Model}
|
||
|
\label{sec:org7fd73d1}
|
||
|
Transfer functions are adjusted in order to fit the ASD of the sensor noises (expressed in \([m/s/\sqrt{Hz}]\) for more easy fitting).
|
||
|
|
||
|
These transfer functions are defined below and compared with the measured ASD in Figure \ref{fig:noise_models_velocity}.
|
||
|
\begin{minted}[]{matlab}
|
||
|
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)]
|
||
|
\end{minted}
|
||
|
|
||
|
\begin{figure}[htbp]
|
||
|
\centering
|
||
|
\includegraphics[scale=1]{figs/noise_models_velocity.png}
|
||
|
\caption{\label{fig:noise_models_velocity}ASD of the velocity noise measured by the sensors and the noise models}
|
||
|
\end{figure}
|
||
|
|
||
|
\subsection{\(\mathcal{H}_2\) Synthesis of the Complementary Filters}
|
||
|
\label{sec:orgc1953b2}
|
||
|
We now wish to synthesize two complementary filters to merge the geophone and the accelerometer signal in such a way that the fused signal has the lowest possible RMS noise.
|
||
|
|
||
|
To do so, we use the \(\mathcal{H}_2\) synthesis where the transfer functions representing the noise density of both sensors are used as weights.
|
||
|
|
||
|
The generalized plant used for the synthesis is defined below.
|
||
|
\begin{minted}[]{matlab}
|
||
|
P = [0 N_acc 1;
|
||
|
N_geo -N_acc 0];
|
||
|
\end{minted}
|
||
|
|
||
|
And the \(\mathcal{H}_2\) synthesis is done using the \texttt{h2syn} command.
|
||
|
\begin{minted}[]{matlab}
|
||
|
[H_geo, ~, gamma] = h2syn(P, 1, 1);
|
||
|
H_acc = 1 - H_geo;
|
||
|
\end{minted}
|
||
|
|
||
|
The obtained complementary filters are shown in Figure \ref{fig:complementary_filters_velocity_H2}.
|
||
|
|
||
|
\begin{figure}[htbp]
|
||
|
\centering
|
||
|
\includegraphics[scale=1]{figs/complementary_filters_velocity_H2.png}
|
||
|
\caption{\label{fig:complementary_filters_velocity_H2}Obtained Complementary Filters}
|
||
|
\end{figure}
|
||
|
|
||
|
\subsection{Results}
|
||
|
\label{sec:org3e27ebd}
|
||
|
Finally, the signals of both sensors are merged using the complementary filters and the super sensor noise is estimated and compared with the individual sensor noises in Figure \ref{fig:super_sensor_noise_asd_velocity}.
|
||
|
|
||
|
\begin{figure}[htbp]
|
||
|
\centering
|
||
|
\includegraphics[scale=1]{figs/super_sensor_noise_asd_velocity.png}
|
||
|
\caption{\label{fig:super_sensor_noise_asd_velocity}ASD of the super sensor noise (velocity)}
|
||
|
\end{figure}
|
||
|
|
||
|
Finally, the Cumulative Power Spectrum is computed and compared in Figure \ref{fig:super_sensor_noise_cas_velocity}.
|
||
|
\begin{minted}[]{matlab}
|
||
|
[~, i_1Hz] = min(abs(f - 1));
|
||
|
\end{minted}
|
||
|
|
||
|
\begin{minted}[]{matlab}
|
||
|
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)));
|
||
|
\end{minted}
|
||
|
|
||
|
\begin{figure}[htbp]
|
||
|
\centering
|
||
|
\includegraphics[scale=1]{figs/super_sensor_noise_cas_velocity.png}
|
||
|
\caption{\label{fig:super_sensor_noise_cas_velocity}Cumulative Power Spectrum of the Sensor Noise (velocity)}
|
||
|
\end{figure}
|
||
|
|
||
|
\section{Inertial Sensor Dynamics Uncertainty and the \(\mathcal{H}_\infty\) Synthesis of complementary filters}
|
||
|
\label{sec:org18f6d67}
|
||
|
\label{sec:inertial_sensor_uncertainty}
|
||
|
When merging two sensors, it is important to be sure that we correctly know the sensor dynamics near the merging frequency.
|
||
|
Thus, identifying the uncertainty on the sensor dynamics is quite important to perform a robust merging.
|
||
|
\subsection{Load Data}
|
||
|
\label{sec:org5d94970}
|
||
|
Data is loaded and offset is removed.
|
||
|
|
||
|
\begin{minted}[]{matlab}
|
||
|
id = load('identification_noise_opt_iff.mat', 'd', 'acc_1', 'acc_2', 'geo_1', 'geo_2', 'f_meas', 'u', 't');
|
||
|
\end{minted}
|
||
|
|
||
|
\begin{minted}[]{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{minted}
|
||
|
|
||
|
\subsection{Compute the dynamics of both sensors}
|
||
|
\label{sec:org69af94a}
|
||
|
The dynamics of inertial sensors are estimated (in \([V/m]\)).
|
||
|
\begin{minted}[]{matlab}
|
||
|
Ts = id.t(2) - id.t(1);
|
||
|
win = hann(ceil(10/Ts));
|
||
|
\end{minted}
|
||
|
|
||
|
\begin{minted}[]{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{minted}
|
||
|
|
||
|
The (nominal) models of the inertial sensors from the absolute displacement to the generated voltage are defined below:
|
||
|
\begin{minted}[]{matlab}
|
||
|
G_acc = 1/(1 + s/2/pi/2000)
|
||
|
G_geo = -1200*s^2/(s^2 + 2*0.7*2*pi*2*s + (2*pi*2)^2);
|
||
|
\end{minted}
|
||
|
|
||
|
These models are very simplistic models, and we then take into account the un-modelled dynamics with dynamical uncertainty.
|
||
|
|
||
|
\subsection{Dynamics uncertainty estimation}
|
||
|
\label{sec:org8c17435}
|
||
|
Weights representing the dynamical uncertainty of the sensors are defined below.
|
||
|
\begin{minted}[]{matlab}
|
||
|
w_acc = createWeight('n', 2, 'G0', 10, 'G1', 0.2, 'Gc', 1, 'w0', 6*2*pi) * ...
|
||
|
createWeight('n', 2, 'G0', 1, 'G1', 5/0.2, 'Gc', 1/0.2, 'w0', 1300*2*pi);
|
||
|
|
||
|
w_geo = createWeight('n', 2, 'G0', 0.6, 'G1', 0.2, 'Gc', 0.3, 'w0', 3*2*pi) * ...
|
||
|
createWeight('n', 2, 'G0', 1, 'G1', 10/0.2, 'Gc', 1/0.2, 'w0', 800*2*pi);
|
||
|
\end{minted}
|
||
|
|
||
|
The measured dynamics are compared with the modelled one as well as the modelled uncertainty in Figure \ref{fig:dyn_uncertainty_acc} for the accelerometers and in Figure \ref{fig:dyn_uncertainty_geo} for the geophones.
|
||
|
|
||
|
\begin{figure}[htbp]
|
||
|
\centering
|
||
|
\includegraphics[scale=1]{figs/dyn_uncertainty_acc.png}
|
||
|
\caption{\label{fig:dyn_uncertainty_acc}Modeled dynamical uncertainty and meaured dynamics of the accelerometers}
|
||
|
\end{figure}
|
||
|
|
||
|
\begin{figure}[htbp]
|
||
|
\centering
|
||
|
\includegraphics[scale=1]{figs/dyn_uncertainty_geo.png}
|
||
|
\caption{\label{fig:dyn_uncertainty_geo}Modeled dynamical uncertainty and meaured dynamics of the geophones}
|
||
|
\end{figure}
|
||
|
|
||
|
\subsection{\(\mathcal{H}_\infty\) Synthesis of Complementary Filters}
|
||
|
\label{sec:orgefb73b5}
|
||
|
A last weight is now defined that represents the maximum dynamical uncertainty that is allowed for the super sensor.
|
||
|
\begin{minted}[]{matlab}
|
||
|
wu = inv(createWeight('n', 2, 'G0', 0.7, 'G1', 0.3, 'Gc', 0.4, 'w0', 3*2*pi) * ...
|
||
|
createWeight('n', 2, 'G0', 1, 'G1', 6/0.3, 'Gc', 1/0.3, 'w0', 1200*2*pi));
|
||
|
\end{minted}
|
||
|
|
||
|
This dynamical uncertainty is compared with the two sensor uncertainties in Figure \ref{fig:uncertainty_weight_and_sensor_uncertainties}.
|
||
|
\begin{figure}[htbp]
|
||
|
\centering
|
||
|
\includegraphics[scale=1]{figs/uncertainty_weight_and_sensor_uncertainties.png}
|
||
|
\caption{\label{fig:uncertainty_weight_and_sensor_uncertainties}Individual sensor uncertainty (normalized by their dynamics) and the wanted maximum super sensor noise uncertainty}
|
||
|
\end{figure}
|
||
|
|
||
|
The generalized plant used for the synthesis is defined:
|
||
|
\begin{minted}[]{matlab}
|
||
|
P = [wu*w_acc -wu*w_acc;
|
||
|
0 wu*w_geo;
|
||
|
1 0];
|
||
|
\end{minted}
|
||
|
|
||
|
And the \(\mathcal{H}_\infty\) synthesis using the \texttt{hinfsyn} command is performed.
|
||
|
\begin{minted}[]{matlab}
|
||
|
[H_geo, ~, gamma, ~] = hinfsyn(P, 1, 1,'TOLGAM', 0.001, 'METHOD', 'ric', 'DISPLAY', 'on');
|
||
|
\end{minted}
|
||
|
|
||
|
\begin{verbatim}
|
||
|
Test bounds: 0.8556 <= gamma <= 1.34
|
||
|
|
||
|
gamma X>=0 Y>=0 rho(XY)<1 p/f
|
||
|
1.071e+00 0.0e+00 0.0e+00 0.000e+00 p
|
||
|
9.571e-01 0.0e+00 0.0e+00 9.436e-16 p
|
||
|
9.049e-01 0.0e+00 0.0e+00 1.084e-15 p
|
||
|
8.799e-01 0.0e+00 0.0e+00 1.191e-16 p
|
||
|
8.677e-01 0.0e+00 0.0e+00 6.905e-15 p
|
||
|
8.616e-01 0.0e+00 0.0e+00 0.000e+00 p
|
||
|
8.586e-01 1.1e-17 0.0e+00 6.917e-16 p
|
||
|
8.571e-01 0.0e+00 0.0e+00 6.991e-17 p
|
||
|
8.564e-01 0.0e+00 0.0e+00 1.492e-16 p
|
||
|
|
||
|
Best performance (actual): 0.8563
|
||
|
\end{verbatim}
|
||
|
|
||
|
The complementary filter is defined as follows:
|
||
|
\begin{minted}[]{matlab}
|
||
|
H_acc = 1 - H_geo;
|
||
|
\end{minted}
|
||
|
|
||
|
The bode plot of the obtained complementary filters is shown in Figure
|
||
|
\begin{figure}[htbp]
|
||
|
\centering
|
||
|
\includegraphics[scale=1]{figs/h_infinity_obtained_complementary_filters.png}
|
||
|
\caption{\label{fig:h_infinity_obtained_complementary_filters}Bode plot of the obtained complementary filters using the \(\mathcal{H}_\infty\) synthesis}
|
||
|
\end{figure}
|
||
|
|
||
|
\subsection{Obtained Super Sensor Dynamical Uncertainty}
|
||
|
\label{sec:org1f65afd}
|
||
|
The obtained super sensor dynamical uncertainty is shown in Figure \ref{fig:super_sensor_uncertainty_h_infinity}.
|
||
|
|
||
|
\begin{figure}[htbp]
|
||
|
\centering
|
||
|
\includegraphics[scale=1]{figs/super_sensor_uncertainty_h_infinity.png}
|
||
|
\caption{\label{fig:super_sensor_uncertainty_h_infinity}Obtained Super sensor dynamics uncertainty}
|
||
|
\end{figure}
|
||
|
|
||
|
\section{Optimal and Robust sensor fusion using the \(\mathcal{H}_2/\mathcal{H}_\infty\) synthesis}
|
||
|
\label{sec:orgbc2335a}
|
||
|
\label{sec:optimal_sensor_fusion}
|
||
|
\subsection{Noise and Dynamical uncertainty weights}
|
||
|
\label{sec:orgc6785ad}
|
||
|
\begin{minted}[]{matlab}
|
||
|
N_acc = (s/(2*pi*2000) + 1)^2/(s + 0.1*2*pi)/(s + 1e3*2*pi)/(1 + s/2/pi/1e3); % [m/sqrt(Hz)]
|
||
|
N_geo = 4e-4*((s + 2*pi)/(2*pi*200) + 1)/(s + 1e3*2*pi)/(1 + s/2/pi/1e3); % [m/sqrt(Hz)]
|
||
|
\end{minted}
|
||
|
|
||
|
\begin{minted}[]{matlab}
|
||
|
w_acc = createWeight('n', 2, 'G0', 10, 'G1', 0.2, 'Gc', 1, 'w0', 6*2*pi) * ...
|
||
|
createWeight('n', 2, 'G0', 1, 'G1', 5/0.2, 'Gc', 1/0.2, 'w0', 1300*2*pi);
|
||
|
|
||
|
w_geo = createWeight('n', 2, 'G0', 0.6, 'G1', 0.2, 'Gc', 0.3, 'w0', 3*2*pi) * ...
|
||
|
createWeight('n', 2, 'G0', 1, 'G1', 10/0.2, 'Gc', 1/0.2, 'w0', 800*2*pi);
|
||
|
\end{minted}
|
||
|
|
||
|
\begin{minted}[]{matlab}
|
||
|
wu = inv(createWeight('n', 2, 'G0', 0.7, 'G1', 0.3, 'Gc', 0.4, 'w0', 3*2*pi) * ...
|
||
|
createWeight('n', 2, 'G0', 1, 'G1', 6/0.3, 'Gc', 1/0.3, 'w0', 1200*2*pi));
|
||
|
\end{minted}
|
||
|
|
||
|
\begin{minted}[]{matlab}
|
||
|
P = [wu*w_acc -wu*w_acc;
|
||
|
0 wu*w_geo;
|
||
|
N_acc -N_acc;
|
||
|
0 N_geo;
|
||
|
1 0];
|
||
|
\end{minted}
|
||
|
|
||
|
And the mixed \(\mathcal{H}_2/\mathcal{H}_\infty\) synthesis is performed.
|
||
|
\begin{minted}[]{matlab}
|
||
|
[H_geo, ~] = h2hinfsyn(ss(P), 1, 1, 2, [0, 1], 'HINFMAX', 1, 'H2MAX', Inf, 'DKMAX', 100, 'TOL', 1e-3, 'DISPLAY', 'on');
|
||
|
\end{minted}
|
||
|
|
||
|
\begin{minted}[]{matlab}
|
||
|
H_acc = 1 - H_geo;
|
||
|
\end{minted}
|
||
|
|
||
|
\subsection{Obtained Super Sensor Noise}
|
||
|
\label{sec:orgaab21f6}
|
||
|
\begin{minted}[]{matlab}
|
||
|
freqs = logspace(0, 4, 1000);
|
||
|
PSD_Sgeo = abs(squeeze(freqresp(N_geo, freqs, 'Hz'))).^2;
|
||
|
PSD_Sacc = abs(squeeze(freqresp(N_acc, freqs, 'Hz'))).^2;
|
||
|
PSD_Hss = abs(squeeze(freqresp(N_acc*H_acc, freqs, 'Hz'))).^2 + ...
|
||
|
abs(squeeze(freqresp(N_geo*H_geo, freqs, 'Hz'))).^2;
|
||
|
\end{minted}
|
||
|
|
||
|
\begin{figure}[htbp]
|
||
|
\centering
|
||
|
\includegraphics[scale=1]{figs/psd_sensors_htwo_hinf_synthesis.png}
|
||
|
\caption{\label{fig:psd_sensors_htwo_hinf_synthesis}Power Spectral Density of the Super Sensor obtained with the mixed \(\mathcal{H}_2/\mathcal{H}_\infty\) synthesis}
|
||
|
\end{figure}
|
||
|
|
||
|
\subsection{Obtained Super Sensor Dynamical Uncertainty}
|
||
|
\label{sec:org7c783d3}
|
||
|
\begin{figure}[htbp]
|
||
|
\centering
|
||
|
\includegraphics[scale=1]{figs/super_sensor_dynamical_uncertainty_Htwo_Hinf.png}
|
||
|
\caption{\label{fig:super_sensor_dynamical_uncertainty_Htwo_Hinf}Super sensor dynamical uncertainty (solid curve) when using the mixed \(\mathcal{H}_2/\mathcal{H}_\infty\) Synthesis}
|
||
|
\end{figure}
|
||
|
|
||
|
\subsection{Experimental Super Sensor Dynamical Uncertainty}
|
||
|
\label{sec:org9d88724}
|
||
|
The super sensor dynamics is shown in Figure \ref{fig:super_sensor_optimal_uncertainty}.
|
||
|
|
||
|
\begin{figure}[htbp]
|
||
|
\centering
|
||
|
\includegraphics[scale=1]{figs/super_sensor_optimal_uncertainty.png}
|
||
|
\caption{\label{fig:super_sensor_optimal_uncertainty}Inertial Sensor dynamics as well as the super sensor dynamics}
|
||
|
\end{figure}
|
||
|
|
||
|
\subsection{Experimental Super Sensor Noise}
|
||
|
\label{sec:org96d37f0}
|
||
|
The obtained super sensor noise is shown in Figure \ref{fig:super_sensor_optimal_noise}.
|
||
|
|
||
|
\begin{figure}[htbp]
|
||
|
\centering
|
||
|
\includegraphics[scale=1]{figs/super_sensor_optimal_noise.png}
|
||
|
\caption{\label{fig:super_sensor_optimal_noise}ASD of the super sensor obtained using the \(\mathcal{H}_2/\mathcal{H}_\infty\) synthesis}
|
||
|
\end{figure}
|
||
|
|
||
|
\section{Matlab Functions}
|
||
|
\label{sec:org5109d75}
|
||
|
\label{sec:matlab_functions}
|
||
|
\subsection{\texttt{createWeight}}
|
||
|
\label{sec:orgf435513}
|
||
|
\label{sec:createWeight}
|
||
|
|
||
|
This Matlab function is accessible \href{src/createWeight.m}{here}.
|
||
|
|
||
|
\begin{minted}[]{matlab}
|
||
|
function [W] = createWeight(args)
|
||
|
% createWeight -
|
||
|
%
|
||
|
% Syntax: [in_data] = createWeight(in_data)
|
||
|
%
|
||
|
% Inputs:
|
||
|
% - n - Weight Order
|
||
|
% - G0 - Low frequency Gain
|
||
|
% - G1 - High frequency Gain
|
||
|
% - Gc - Gain of W at frequency w0
|
||
|
% - w0 - Frequency at which |W(j w0)| = Gc
|
||
|
%
|
||
|
% Outputs:
|
||
|
% - W - Generated Weight
|
||
|
|
||
|
arguments
|
||
|
args.n (1,1) double {mustBeInteger, mustBePositive} = 1
|
||
|
args.G0 (1,1) double {mustBeNumeric, mustBePositive} = 0.1
|
||
|
args.G1 (1,1) double {mustBeNumeric, mustBePositive} = 10
|
||
|
args.Gc (1,1) double {mustBeNumeric, mustBePositive} = 1
|
||
|
args.w0 (1,1) double {mustBeNumeric, mustBePositive} = 1
|
||
|
end
|
||
|
|
||
|
mustBeBetween(args.G0, args.Gc, args.G1);
|
||
|
|
||
|
s = tf('s');
|
||
|
|
||
|
W = (((1/args.w0)*sqrt((1-(args.G0/args.Gc)^(2/args.n))/(1-(args.Gc/args.G1)^(2/args.n)))*s + (args.G0/args.Gc)^(1/args.n))/((1/args.G1)^(1/args.n)*(1/args.w0)*sqrt((1-(args.G0/args.Gc)^(2/args.n))/(1-(args.Gc/args.G1)^(2/args.n)))*s + (1/args.Gc)^(1/args.n)))^args.n;
|
||
|
|
||
|
end
|
||
|
|
||
|
% Custom validation function
|
||
|
function mustBeBetween(a,b,c)
|
||
|
if ~((a > b && b > c) || (c > b && b > a))
|
||
|
eid = 'createWeight:inputError';
|
||
|
msg = 'Gc should be between G0 and G1.';
|
||
|
throwAsCaller(MException(eid,msg))
|
||
|
end
|
||
|
end
|
||
|
\end{minted}
|
||
|
|
||
|
\subsection{\texttt{plotMagUncertainty}}
|
||
|
\label{sec:orgff4d677}
|
||
|
\label{sec:plotMagUncertainty}
|
||
|
|
||
|
This Matlab function is accessible \href{src/plotMagUncertainty.m}{here}.
|
||
|
|
||
|
\begin{minted}[]{matlab}
|
||
|
function [p] = plotMagUncertainty(W, freqs, args)
|
||
|
% plotMagUncertainty -
|
||
|
%
|
||
|
% Syntax: [p] = plotMagUncertainty(W, freqs, args)
|
||
|
%
|
||
|
% Inputs:
|
||
|
% - W - Multiplicative Uncertainty Weight
|
||
|
% - freqs - Frequency Vector [Hz]
|
||
|
% - args - Optional Arguments:
|
||
|
% - G
|
||
|
% - color_i
|
||
|
% - opacity
|
||
|
%
|
||
|
% Outputs:
|
||
|
% - p - Plot Handle
|
||
|
|
||
|
arguments
|
||
|
W
|
||
|
freqs double {mustBeNumeric, mustBeNonnegative}
|
||
|
args.G = tf(1)
|
||
|
args.color_i (1,1) double {mustBeInteger, mustBePositive} = 1
|
||
|
args.opacity (1,1) double {mustBeNumeric, mustBeNonnegative} = 0.3
|
||
|
args.DisplayName char = ''
|
||
|
end
|
||
|
|
||
|
% Get defaults colors
|
||
|
colors = get(groot, 'defaultAxesColorOrder');
|
||
|
|
||
|
p = patch([freqs flip(freqs)], ...
|
||
|
[abs(squeeze(freqresp(args.G, freqs, 'Hz'))).*(1 + abs(squeeze(freqresp(W, freqs, 'Hz')))); ...
|
||
|
flip(abs(squeeze(freqresp(args.G, freqs, 'Hz'))).*max(1 - abs(squeeze(freqresp(W, freqs, 'Hz'))), 1e-6))], 'w', ...
|
||
|
'DisplayName', args.DisplayName);
|
||
|
|
||
|
p.FaceColor = colors(args.color_i, :);
|
||
|
p.EdgeColor = 'none';
|
||
|
p.FaceAlpha = args.opacity;
|
||
|
|
||
|
end
|
||
|
\end{minted}
|
||
|
|
||
|
\subsection{\texttt{plotPhaseUncertainty}}
|
||
|
\label{sec:orgacbe668}
|
||
|
\label{sec:plotPhaseUncertainty}
|
||
|
|
||
|
This Matlab function is accessible \href{src/plotPhaseUncertainty.m}{here}.
|
||
|
|
||
|
\begin{minted}[]{matlab}
|
||
|
function [p] = plotPhaseUncertainty(W, freqs, args)
|
||
|
% plotPhaseUncertainty -
|
||
|
%
|
||
|
% Syntax: [p] = plotPhaseUncertainty(W, freqs, args)
|
||
|
%
|
||
|
% Inputs:
|
||
|
% - W - Multiplicative Uncertainty Weight
|
||
|
% - freqs - Frequency Vector [Hz]
|
||
|
% - args - Optional Arguments:
|
||
|
% - G
|
||
|
% - color_i
|
||
|
% - opacity
|
||
|
%
|
||
|
% Outputs:
|
||
|
% - p - Plot Handle
|
||
|
|
||
|
arguments
|
||
|
W
|
||
|
freqs double {mustBeNumeric, mustBeNonnegative}
|
||
|
args.G = tf(1)
|
||
|
args.color_i (1,1) double {mustBeInteger, mustBePositive} = 1
|
||
|
args.opacity (1,1) double {mustBeNumeric, mustBePositive} = 0.3
|
||
|
args.DisplayName char = ''
|
||
|
end
|
||
|
|
||
|
% Get defaults colors
|
||
|
colors = get(groot, 'defaultAxesColorOrder');
|
||
|
|
||
|
% Compute Phase Uncertainty
|
||
|
Dphi = 180/pi*asin(abs(squeeze(freqresp(W, freqs, 'Hz'))));
|
||
|
Dphi(abs(squeeze(freqresp(W, freqs, 'Hz'))) > 1) = 360;
|
||
|
|
||
|
% Compute Plant Phase
|
||
|
G_ang = 180/pi*angle(squeeze(freqresp(args.G, freqs, 'Hz')));
|
||
|
|
||
|
p = patch([freqs flip(freqs)], [G_ang+Dphi; flip(G_ang-Dphi)], 'w', ...
|
||
|
'DisplayName', args.DisplayName);
|
||
|
|
||
|
p.FaceColor = colors(args.color_i, :);
|
||
|
p.EdgeColor = 'none';
|
||
|
p.FaceAlpha = args.opacity;
|
||
|
|
||
|
end
|
||
|
\end{minted}
|
||
|
|
||
|
\bibliography{ref}
|
||
|
|
||
|
\printbibliography
|
||
|
\end{document}
|