digital-brain/content/zettels/system_identification.md

434 lines
16 KiB
Markdown
Raw Normal View History

2020-04-20 18:58:10 +02:00
+++
title = "System Identification"
2022-03-15 16:40:48 +01:00
author = ["Dehaeze Thomas"]
2020-04-20 18:58:10 +02:00
draft = false
+++
Tags
2022-03-15 16:40:48 +01:00
: [Modal Analysis]({{< relref "modal_analysis.md" >}})
2024-12-13 22:47:22 +01:00
## System Identification {#system-identification}
2022-04-19 14:16:30 +02:00
2024-12-13 22:47:22 +01:00
### Problem Definition {#problem-definition}
2022-04-19 14:16:30 +02:00
2024-12-13 22:47:22 +01:00
The goal of a system identification is to extract a model (usually a LTI transfer function) from experimental data.
The system is represented in Figure <fig:siso_identification_schematic_simplier> with one input \\(u\\) and one output \\(y\_m\\) affected by some disturbances and noise \\(d\\).
2022-04-19 14:16:30 +02:00
<a id="figure--fig:siso-identification-schematic-simplier"></a>
2024-12-13 22:47:22 +01:00
{{< figure src="/ox-hugo/siso_identification_schematic_simplier.png" caption="<span class=\"figure-number\">Figure 1: </span>Simpler Block diagram of the SISO system identification" >}}
2022-04-19 14:16:30 +02:00
2024-12-13 22:47:22 +01:00
The goal of system identification is to compute the transfer function \\(G\\) from known excitation signal \\(u\\) and from a measure of \\(y\_m\\).
2022-04-19 14:16:30 +02:00
2024-12-13 22:47:22 +01:00
There are different ways of obtaining a model \\(G\\) of the system summarized in Table <tab:system_identification_model_types>.
For mechatronics systems, _frequency domain identification_ is the norm.
2022-04-19 14:16:30 +02:00
2024-12-13 22:47:22 +01:00
<a id="table--tab:system-identification-model-types"></a>
<div class="table-caption">
<span class="table-number"><a href="#table--tab:system-identification-model-types">Table 1</a>:</span>
Different ways to obtain a model
2022-04-19 14:16:30 +02:00
</div>
2024-12-13 22:47:22 +01:00
| | **Advantages** | **Disadvantages** |
|-------------------------------------|---------------------------------------------------------|-------------------------------------------------|
| Physical Modeling | Understanding dynamics, no measurements | Low accuracy, time consuming |
| Time domain identification | Parametric models, small data sets, non-linearity, MIMO | order/structure selection can be time consuming |
| **Frequency domain identification** | easy, intuitive, user-defined model fitting | fitting MIMO parametric model can be difficult |
As an example, a second order plant will be used:
```matlab
G = 1/(1 + 0.1*s/(2*pi*40) + s^2/(2*pi*40)^2); % Plant model
```
The sampling time of the recorded digital signal is 1ms.
### Open-loop identification {#open-loop-identification}
In open-loop identification (Figure <fig:siso_identification_schematic_simplier_open_loop>), a test signal \\(u\\) is used to _excite_ the system in the frequency range of interest.
The signal \\(u\\) can typically be a swept sine, noise or multi-sine.
<a id="figure--fig:siso-identification-schematic-simplier-open-loop"></a>
{{< figure src="/ox-hugo/siso_identification_schematic_simplier_open_loop.png" caption="<span class=\"figure-number\">Figure 2: </span>Open Loop signal identification" >}}
The plant estimate \\(\hat{G}(j\omega)\\) is computed as follows:
\\[ \hat{G}(j\omega) = \frac{\Phi\_{yu}(\omega)}{\Phi\_{u}(\omega)} \\]
with \\(\phi\_{u}(\omega)\\) is the spectrum of \\(u\\) and \\(\Phi\_{yu}(\omega)\\) is the cross-spectrum of \\(u\\) and \\(y\\).
In Matlab, the transfer function can be extracted from the data using:
```matlab
Nfft = floor(1/Ts); % Size of the window [-]
win = hanning(Nfft); % Hanning window
Noverlap = floor(Nfft/2); % Overlap of 50%
% Identified Transfer Functions
[Gm, f] = tfestimate(data.du, data.y, win, Noverlap, Nfft, 1/Ts);
```
Then, the bode plot of the obtained transfer function is compared against the plant model including a 1.5 sample time delay (Figure <fig:system_identification_ol_comp_plant>).
<a id="figure--fig:system-identification-ol-comp-plant"></a>
{{< figure src="/ox-hugo/system_identification_ol_comp_plant.png" caption="<span class=\"figure-number\">Figure 3: </span>Comparison of the plant transfer function with the identified FRF in Open-Loop" >}}
### Verification of the Identification Quality - Coherence {#verification-of-the-identification-quality-coherence}
In order to assess the quality of the obtained FRF, the _coherence_ can be computed using the `mscohere` Matlab function.
```matlab
[coh, f] = mscohere(data.du, data.y, win, Noverlap, Nfft, 1/Ts);
```
The result for the example is shown in Figure <fig:system_identification_ol_coh>.
At high frequency, the measurement noise dominates and the coherence is poor.
<a id="figure--fig:system-identification-ol-coh"></a>
{{< figure src="/ox-hugo/system_identification_ol_coh.png" caption="<span class=\"figure-number\">Figure 4: </span>Comparison of the plant transfer function with the identified FRF in Open-Loop" >}}
### Closed-Loop identification {#closed-loop-identification}
If the open-loop system is unstable, a first simple controller needs to be designed to stabilizes the system.
Then, the plant can be identified from closed-loop system identification (Figure <fig:siso_identification_schematic_simplier_closed_loop>).
2022-04-19 14:16:30 +02:00
2024-12-13 22:47:22 +01:00
<a id="figure--fig:siso-identification-schematic-simplier-closed-loop"></a>
2022-04-19 14:16:30 +02:00
2024-12-13 22:47:22 +01:00
{{< figure src="/ox-hugo/siso_identification_schematic_simplier_closed_loop.png" caption="<span class=\"figure-number\">Figure 5: </span>Closed Loop signal identification" >}}
2022-04-19 14:16:30 +02:00
2024-12-13 22:47:22 +01:00
To perform plant identification in closed-loop:
- Chose \\(d\_u\\) (sweep sine, multi-sine, noise, ...)
- Measure \\(u\\) and \\(y\\)
- Compute the process sensitivity:
\\[ GS(j\omega) = \frac{\Phi\_{yd\_u}(\omega)}{\Phi\_{d\_u}(\omega)} \\]
- Compute the Sensitivity:
\\[ S(j\omega) = \frac{\Phi\_{ud\_u}(\omega)}{\Phi\_{d\_u}(\omega)} \\]
- Then the plan estimate \\(\hat{G}(j\omega)\\) can be computed:
\\[ \hat{G}(j\omega) = \frac{GS(j\omega)}{S(j\omega)} \\]
In Matlab, this can be done with the following code:
```matlab
Nfft = floor(1/Ts); % Size of the window [-]
win = hanning(Nfft); % Hanning window
Noverlap = floor(Nfft/2); % Overlap of 50%
[S, f] = tfestimate(data.du, data.u, win, Noverlap, Nfft, 1/Ts);
[GS, ~] = tfestimate(data.du, data.y, win, Noverlap, Nfft, 1/Ts);
Gm = GS ./ S;
K = (1 ./ S - 1) ./ Gm;
T = 1 - S;
```
### Multi-Input Multi-Output Plant {#multi-input-multi-output-plant}
This can be generalized to a MIMO plant (Figure <fig:siso_identification_schematic_simplier_closed_loop>).
<a id="figure--fig:siso-identification-schematic-simplier-closed-loop"></a>
{{< figure src="/ox-hugo/mimo_identification_schematic_simplier_closed_loop.png" caption="<span class=\"figure-number\">Figure 6: </span>Closed Loop signal identification (MIMO case)" >}}
Suppose a plan with \\(m\\) inputs and \\(n\\) outputs.
\\(\bm{G}\\) is therefore a \\(n \times m\\) plant, and the controller \\(\bm{K}\\) an \\(m \times n\\) system.
Input sensitivity is an \\(m \times m\\) system:
\\[ \bm{S}\_i = (\bm{I}\_{m} + \bm{K}\bm{G})^{-1} \\]
And process sensitivity is an \\(m \times m\\) system:
\\[ \bm{GS} = \bm{G} (I\_m + KG)^{-1} \\]
And the \\(n \times m\\) plant can be computed using:
\\[ GS \cdot S^{-1} = \bm{G} (I\_m + KG)^{-1} (\bm{I}\_{m} + \bm{K}\bm{G}) = G \\]
To estimate the full plant, \\(m\\) separate identification needs to be performed (one for each input):
- Chose the excitation signal for the \\(i^{th}\\) input: \\(d\_{ui}\\) (sweep sine, multi-sine, noise, ...)
- Measure \\(u\_i\\) and \\(\bm{y}\\)
- Compute the \\(i^{th}\\) column of the process sensitivity (\\(j\\) from \\(1\\) to \\(n\\)):
\\[ GS\_{ij}(j\omega) = \frac{\Phi\_{y\_jd\_{ui}}(\omega)}{\Phi\_{d\_{ui}}(\omega)} \\]
- Compute the \\(i^{th}\\) column of the input sensitivity (\\(j\\) from \\(1\\) to \\(n\\)):
\\[ S\_{ij}(j\omega) = \frac{\Phi\_{u\_jd\_{ui}}(\omega)}{\Phi\_{d\_{ui}}(\omega)} \\]
When the complete \\(GS\\) and \\(S\\) matrices are identified, the plan estimate \\(\hat{\bm{G}}(j\omega)\\) can be computed:
\\[ \hat{\bm{G}}(j\omega) = \bm{GS}(j\omega) \bm{S\_i}^{-1}(j\omega) \\]
## Design of the Excitation Signal {#design-of-the-excitation-signal}
<span class="org-target" id="org-target--sec-system-identification-excitation-signal"></span>
### Introduction {#introduction}
2022-04-19 14:16:30 +02:00
There are several choices for excitation signals:
- Impulse, Steps
- Sweep Sinus
2024-12-13 22:47:22 +01:00
- Random noise, Periodic signals (PRBS)
- Multi-Sine
2022-04-19 14:16:30 +02:00
2024-12-13 23:41:19 +01:00
A good review is given in <&pintelon12_system_ident> (chapter 5).
2022-04-19 14:16:30 +02:00
2024-12-13 22:47:22 +01:00
### Random noise with specific ASD {#random-noise-with-specific-asd}
2022-04-19 14:16:30 +02:00
The ASD of the measured output is:
\begin{equation}
\Gamma\_{y\_m}(\omega) = \Gamma\_d(\omega) + \Gamma\_u(\omega) \cdot |G(j\omega)|
\end{equation}
And we want the effect of the excitation signal to be much higher than the effect of the exogenous signals (measurement noise, input noise, disturbances).
\begin{equation}
\Gamma\_u(\omega) \gg \Gamma\_d(\omega) \cdot |G(j\omega)|^{-1}
\end{equation}
Note that \\(\Gamma\_d(\omega)\\) can be estimated by measuring the system output in the absence of any excitation signal.
The plant magnitude \\(|G(j\omega)|\\) can be roughly estimated from a first identification with bad coherence.
In order to design a random excitation signal with specific spectral characteristics, first a signal with an ASD equal to one is generated (i.e. white noise with unity ASD):
```matlab
Ts = 1e-4; % Sampling Time [s]
t = 0:Ts:10; % Time Vector [s]
%% Signal with an ASD equal to one
u_norm = sqrt(1/2/Ts)*randn(length(t), 1);
```
Then, a transfer function whose magnitude \\(|G\_u(j\omega)|\\) has the same shape as the wanted excitation ASD \\(\Gamma\_u(\omega)\\) is designed:
```matlab
%% Transfer function representing the wanted ASD
G_u = tf([1], [1/2/pi/100 1]);
```
Finally `lsim` is used to compute the shaped excitation signal.
```matlab
%% Shape the ASD of the excitation signal
u = lsim(G_u, u_norm, t);
```
2024-12-13 22:47:22 +01:00
### Choose Sampling Frequency and Duration of Excitation {#choose-sampling-frequency-and-duration-of-excitation}
2022-04-19 14:16:30 +02:00
<div class="important">
The sampling frequency \\(F\_s\\) will determine the maximum frequency \\(F\_{\text{max}}\\) that can be estimated (see Nyquist theorem):
\begin{equation}
F\_{\text{max}} = \frac{1}{2} F\_s
\end{equation}
</div>
<div class="important">
The duration of excitation \\(T\_{\text{exc}}\\) will determine the minimum frequency \\(F\_{\text{min}}\\) that can be estimated:
\begin{equation}
F\_{\text{min}} = \frac{1}{T\_{\text{exc}}}
\end{equation}
It will also corresponds to the frequency resolution \\(\Delta f\\):
\begin{equation}
\Delta f = \frac{1}{T\_{\text{exc}}}
\end{equation}
</div>
In order to increase the estimation quality, averaging can be use with a longer excitation duration.
A factor 10 is usually good enough, therefore the excitation time can be taken as:
\begin{equation}
T\_{\text{exc}} \approx \frac{10}{F\_{\text{min}}}
\end{equation}
<div class="exampl">
Therefore, if the system has to be identified from 1Hz up to 500Hz, the sampling frequency should be:
\begin{equation}
F\_s = 2 F\_{\text{max}} = 1\\,\text{kHz}
\end{equation}
Then, the excitation duration should be (10 averaging):
\begin{equation}
T\_{\text{exc}} = \frac{10}{1} = 10\\,s
\end{equation}
</div>
2024-12-13 22:47:22 +01:00
### Multi-Sine {#multi-sine}
2022-04-19 14:16:30 +02:00
2024-12-13 23:41:19 +01:00
Multi-sine signal excitation has many advantages as compared to random noise:
- the signal power at each frequency can be precisely chosen
- the signal is periodic and therefore necessitate no windowing (therefore increasing the obtained FRF quality)
It can be generated with the following code.
```matlab
%% Generate multinsine signal
Fs = 1e3; % Sampling Frequency [Hz]
Ns = 1e3; % Signal length [-]
f = linspace(0, Fs/2, Ns/2); % Frequency Vector [Hz]
% Define the wanted ASD of the test signal [unit/sqrt(Hz)]
wanted_asd = 3*ones(1,Ns);
f_min = 10; % [Hz]
f_max = 300; % [Hz]
wanted_asd([1:round(Ns*f_min/Fs)]) = 0;
wanted_asd([round(Ns*f_max/Fs+1):end]) = 0;
% Generate the multi-sine signal
u = generate_multisine(Fs, Ns, ...
'asd', wanted_asd, ...
'type', 'schroeder');
```
The ASD of the generated signal is exactly as expected (Figure <fig:system_identification_multi_sine_asd>)
```matlab
[pxx, f] = pwelch(u, ones(Ns,1), [], Ns, Fs);
```
<a id="figure--fig:system-identification-multi-sine-asd"></a>
{{< figure src="/ox-hugo/system_identification_multi_sine_asd.png" caption="<span class=\"figure-number\">Figure 7: </span>Amplitude Spectral Density of the multi-sine signal" >}}
In the time domain, it is shown in Figure <fig:system_identification_multi_sine_time>.
<a id="figure--fig:system-identification-multi-sine-time"></a>
{{< figure src="/ox-hugo/system_identification_multi_sine_time.png" caption="<span class=\"figure-number\">Figure 8: </span>Generated Multi-Sine signal" >}}
Then, the open-loop identification is performed, and the FRF is computed using the following code (not that no window is being used!).
Only the first period (here of 1s) is discarded to remove transient effects.
```matlab
% Skip the first period (transient)
[Gm, f] = tfestimate(data.du(Ns:end), data.y(Ns:end), ones(Ns,1), [], Ns, Fs);
```
The obtained FRF is shown in Figure <fig:system_identification_multi_sine_frf>.
The quality of the obtained FRF is only good in the defined range.
<a id="figure--fig:system-identification-multi-sine-frf"></a>
{{< figure src="/ox-hugo/system_identification_multi_sine_frf.png" caption="<span class=\"figure-number\">Figure 9: </span>Obtained FRF using the multi-sine excitation signal" >}}
2022-04-19 14:16:30 +02:00
2024-12-13 22:47:22 +01:00
### `generatemultisine` - Matlab Function {#generatemultisine-matlab-function}
2022-04-19 14:16:30 +02:00
2024-12-13 23:41:19 +01:00
The synthesis of multi-sine with minimal "crest factor" is taken from <&schroeder70_synth_low_peak_factor_signal>.
The Matlab code is adapted from [here](https://bholmesqub.github.io/thesis/chapters/identification-design/multi-sine/).
2022-04-19 14:16:30 +02:00
```matlab
2024-12-13 22:47:22 +01:00
function y = generate_multisine(Fs, Ns, args)
%% Input parsing
arguments
Fs % Sampling frequency of the generated test signal
Ns % Length of the generated test signal
args.asd double {mustBeNumeric, mustBeNonnegative} = 0
args.type char {mustBeMember(args.type,{'schroeder', 'normal'})} = 'schroeder'
end
%% Find amplitude response
if args.asd == 0
% If magnitude response is zero, set default to "unitary ASD"
mag = (ones(1, Ns)*2*sqrt(Fs)/sqrt(Ns)).^2;
mag(round(Ns/2+1):end) = 0;
else
if length(args.asd) ~= Ns
error('ASD must be of length Ns');
end
mag = (args.asd*2*sqrt(Fs)/sqrt(Ns)).^2;
end
if any(mag(round(Ns/2+1):end))
warning('Non-zero magnitude values present outside of frequency limits.');
mag(round(Ns/2+1):end) = 0;
end
%% Find phase response
switch args.type
case 'schroeder'
phase = schroederPhases(Ns, mag);
case 'normal'
phase = randn(1, Ns);
otherwise
error('type must be "Schroeder" or "normal"');
end
%% Generate multisine signal
% Frequency domain representation
Y = sqrt(mag/2).*exp(sqrt(-1).*phase);
% IFFT to time domain
y = ifft(forceFFTSymmetry(Y))*(Ns/2);
%% Find zero crossing closest to zero
% Heuristic method of finding minimum gradient zero crossing
ySign = y>0;
zeroInds = find((ySign(2:end) ~= ySign(1:end-1)));
% Find the index with the smallest gradient around the zero crossing.
zeroGrad = zeros(1,length(zeroInds));
for nn=1:length(zeroInds)
zeroGrad(nn) = abs(y(zeroInds(nn)) - y(zeroInds(nn)+1));
end
[~, minInd] = min(zeroGrad);
yWrapped = [y(zeroInds(minInd):end) y(1:zeroInds(minInd)-1)];
y = yWrapped;
end
%% Generate phases as defined in "Synthesis of Low-Peak-Factor Signals and
% Binary Sequences With Low Autocorrelation" by M. R. Schroeder
function phase = schroederPhases(Ns, mag)
rel_mag = mag./sum(mag); % Normalize magnitude for Schroeder's algorithm
phase = zeros(1, Ns);
for nn=2:floor(Ns/2+1)
ll=1:(nn-1);
phase(nn) = -2*pi*sum((nn-ll).*rel_mag(ll));
end
end
%% forceFFTSymmetry A function to force conjugate symmetry on an FFT such that when an
% IFFT is performed the result is a real signal.
% The function has been written to replace MATLAB's ifft(X,'symmetric'), as this function
% is not compatible with MATLAB Coder.
function Y = forceFFTSymmetry(X)
Y = X;
XStartFlipped = fliplr(X(2:floor(end/2)));
Y(ceil(end/2)+2:end) = real(XStartFlipped) - sqrt(complex(-1))*imag(XStartFlipped);
end
2022-04-19 14:16:30 +02:00
```
## Reference Books {#reference-books}
2024-12-13 22:47:22 +01:00
- <pintelon12_system_ident>
- <schoukens12_master>
2022-04-19 14:16:30 +02:00
2022-03-15 16:40:48 +01:00
## Bibliography {#bibliography}
2024-12-13 22:47:22 +01:00
<./biblio/references.bib>