Re-worked section 2
This commit is contained in:
1 parent
0d13665c50
commit
6ce8fb5cba
6 files changed
+1226
-669
No files matched your search
@@ -14,6 +14,8 @@
|
||||
|
||||
#+HTML_MATHJAX: align: center tagside: right font: TeX
|
||||
|
||||
#+CSL_STYLE: ieee.csl
|
||||
|
||||
#+PROPERTY: header-args:matlab :session *MATLAB*
|
||||
#+PROPERTY: header-args:matlab+ :comments org
|
||||
#+PROPERTY: header-args:matlab+ :results none
|
||||
@@ -455,24 +457,27 @@ The Bode plots of $G(s)$ and $G_d(s)$ are shown in Figures [[fig:bode_plot_examp
|
||||
|
||||
** Introduction :ignore:
|
||||
|
||||
- Section [[sec:open_loop_shaping_introduction]]
|
||||
- Section [[sec:loop_shaping_example]]
|
||||
- Section [[sec:h_infinity_open_loop_shaping]]
|
||||
- Section [[sec:h_infinity_open_loop_shaping_example]]
|
||||
After an introduction to classical Loop Shaping in Section [[sec:open_loop_shaping_introduction]], a practical example is given in Section [[sec:loop_shaping_example]].
|
||||
Such Loop Shaping is usually performed manually with tools coming from the classical control theory.
|
||||
|
||||
However, the $\mathcal{H}_\infty$ synthesis can be used to automate the Loop Shaping process.
|
||||
This is presented in Section [[sec:h_infinity_open_loop_shaping]] and applied on the same example in Section [[sec:h_infinity_open_loop_shaping_example]].
|
||||
|
||||
** Introduction to Loop Shaping
|
||||
<<sec:open_loop_shaping_introduction>>
|
||||
|
||||
#+begin_definition
|
||||
*Loop Shaping* refers to a design procedure that involves explicitly shaping the magnitude of the *Loop Transfer Function* $L(s)$.
|
||||
*Loop Shaping* refers to a control design procedure that involves explicitly shaping the magnitude of the *Loop Transfer Function* $L(s)$.
|
||||
#+end_definition
|
||||
|
||||
#+begin_definition
|
||||
The *Loop Gain* $L(s)$ usually refers to as the product of the controller and the plant ("Gain around the loop", see Figure [[fig:open_loop_shaping]]):
|
||||
The *Loop Gain* (or Loop transfer function) $L(s)$ usually refers to as the product of the controller and the plant (see Figure [[fig:open_loop_shaping]]):
|
||||
\begin{equation}
|
||||
L(s) = G(s) \cdot K(s) \label{eq:loop_gain}
|
||||
\end{equation}
|
||||
|
||||
Its name comes from the fact that this is actually the "gain around the loop".
|
||||
|
||||
#+begin_src latex :file open_loop_shaping.pdf
|
||||
\begin{tikzpicture}
|
||||
\node[addb={+}{}{}{}{-}] (addsub) at (0, 0){};
|
||||
@@ -499,17 +504,19 @@ The *Loop Gain* $L(s)$ usually refers to as the product of the controller and th
|
||||
[[file:figs/open_loop_shaping.png]]
|
||||
#+end_definition
|
||||
|
||||
This synthesis method is widely used as many characteristics of the closed-loop system depend on the shape of the open loop gain $L(s)$ such as:
|
||||
- *Performance*: $L$ large
|
||||
This synthesis method is one of main way controllers are design in the classical control theory.
|
||||
It is widely used and generally successful as many characteristics of the closed-loop system depend on the shape of the open loop gain $L(s)$ such as:
|
||||
- *Good Tracking*: $L$ large
|
||||
- *Good disturbance rejection*: $L$ large
|
||||
- *Limitation of measurement noise on plant output*: $L$ small
|
||||
- *Small magnitude of input signal*: $K$ and $L$ small
|
||||
- *Attenuation of measurement noise on plant output*: $L$ small
|
||||
- *Small magnitude of input signal*: $L$ small
|
||||
- *Nominal stability*: $L$ small (RHP zeros and time delays)
|
||||
- *Robust stability*: $L$ small (neglected dynamics)
|
||||
|
||||
The Open Loop shape is usually done manually has the loop gain $L(s)$ depends linearly on $K(s)$ eqref:eq:loop_gain.
|
||||
|
||||
$K(s)$ then consists of a combination of leads, lags, notches, etc. such that $L(s)$ has the wanted shape (an example is shown in Figure [[fig:open_loop_shaping_shape]]).
|
||||
The shaping of the Loop Gain is done manually by combining several leads, lags, notches...
|
||||
This process is very much simplified by the fact that the loop gain $L(s)$ depends *linearly* on $K(s)$ eqref:eq:loop_gain.
|
||||
A typical wanted Loop Shape is shown in Figure [[fig:open_loop_shaping_shape]].
|
||||
Another interesting Loop shape called "Bode Step" is described in cite:lurie02_system_archit_trades_using_bode.
|
||||
|
||||
#+begin_src latex :file open_loop_shaping_shape.pdf
|
||||
\begin{tikzpicture}
|
||||
@@ -530,12 +537,12 @@ $K(s)$ then consists of a combination of leads, lags, notches, etc. such that $L
|
||||
\path[shift={(0,1.8)}, fill=red!50!white] (0.5, 1.25) -- (2, 0.5) -| coordinate[near start](lfshaping) cycle;
|
||||
\path[shift={(0,2.2)}, fill=red!50!white] (6, -0.5) -- (7.5, -1.25) |- coordinate[near end](hfshaping) cycle;
|
||||
|
||||
\draw[<-] (lfshaping) -- ++(0, -0.8) node[below, align=center]{Reference\\Tracking};
|
||||
\draw[<-] (hfshaping) -- ++(0, 0.8) node[above, align=center]{Noise\\Rejection};
|
||||
\draw[<-] (lfshaping) -- ++(0, -0.8) node[below, align=center]{{\scriptsize Ref. tracking}\\{\scriptsize Dist. rejection}};
|
||||
\draw[<-] (hfshaping) -- ++(0, 0.8) node[above, align=center]{{\scriptsize Noise attenuation}};
|
||||
|
||||
% Crossover frequency
|
||||
\node[below] (wc) at (4,2){$\omega_c$};
|
||||
\draw[<-] (wc.south) -- ++(0, -0.4) node[below, align=center]{Bandwidth};
|
||||
\draw[<-] (wc.south) -- ++(0, -0.4) node[below, align=center]{{\scriptsize Bandwidth}};
|
||||
|
||||
% Phase
|
||||
\draw[] (0.5, -2) -- (2, -2)[out=0, in=-180] to (4, -1.25)[out=0, in=-180] to
|
||||
@@ -543,7 +550,7 @@ $K(s)$ then consists of a combination of leads, lags, notches, etc. such that $L
|
||||
-1.25)[out=0, in=-180] to (6, -2) -- (7.5, -2);
|
||||
|
||||
% Phase Margin
|
||||
\draw[->, dashed] (4, -2) -- (4, -1.25) node[above]{Phase Margin};
|
||||
\draw[->, dashed] (4, -2) -- (4, -1.25) node[above]{{\scriptsize Phase Margin}};
|
||||
\draw[dashed] (0, -2) node[left]{$-\pi$} -- (7.5, -2);
|
||||
\end{tikzpicture}
|
||||
#+end_src
|
||||
@@ -553,34 +560,65 @@ $K(s)$ then consists of a combination of leads, lags, notches, etc. such that $L
|
||||
#+RESULTS:
|
||||
[[file:figs/open_loop_shaping_shape.png]]
|
||||
|
||||
** Example of Open Loop Shaping
|
||||
The shaping of *closed-loop* transfer functions is obviously not as simple as they don't depend linearly on $K(s)$.
|
||||
But this is were the $\mathcal{H}_\infty$ Synthesis will be useful!
|
||||
More details on that in Sections [[sec:modern_interpretation_specification]] and [[sec:closed-loop-shaping]].
|
||||
|
||||
** Example of Manual Open Loop Shaping
|
||||
<<sec:loop_shaping_example>>
|
||||
|
||||
#+begin_exampl
|
||||
Let's take our example system and try to apply the Open-Loop shaping strategy to design a controller that fulfils the following specifications:
|
||||
- *Performance*: Bandwidth of approximately 10Hz
|
||||
- *Noise Attenuation*: Roll-off of -40dB/decade past 30Hz
|
||||
- *Robustness*: Gain margin > 3dB and Phase margin > 30 deg
|
||||
Let's take our example system described in Section [[sec:example_system]] and design a controller using the Open-Loop shaping synthesis approach.
|
||||
The specifications are:
|
||||
1. *Disturbance rejection*: Highest possible rejection below 1Hz
|
||||
2. *Positioning speed*: Bandwidth of approximately 10Hz
|
||||
3. *Noise attenuation*: Roll-off of -40dB/decade past 30Hz
|
||||
4. *Robustness*: Gain margin > 3dB and Phase margin > 30 deg
|
||||
#+end_exampl
|
||||
|
||||
#+begin_exercice
|
||||
Using =SISOTOOL=, design a controller that fulfill the specifications.
|
||||
Using =SISOTOOL=, design a controller that fulfills the specifications.
|
||||
|
||||
#+begin_src matlab :eval no :tangle no
|
||||
sisotool(G)
|
||||
#+end_src
|
||||
|
||||
#+HTML: <details><summary>Hint</summary>
|
||||
You can follow this procedure:
|
||||
1. In order to have good disturbance rejection at low frequency, add a simple or double *integrator*
|
||||
2. In terms of the loop gain, the *bandwidth* can be defined at the frequency $\omega_c$ where $|l(j\omega_c)|$ first crosses 1 from above.
|
||||
Therefore, adjust the *gain* such that $L(j\omega)$ crosses 1 at around 10Hz
|
||||
3. The roll-off at high frequency for noise attenuation should already be good enough.
|
||||
If not, add a *low pass filter*
|
||||
4. Add a *Lead* centered around the crossover frequency (10 Hz) and tune it such that sufficient phase margin is added.
|
||||
Verify that the gain margin is good enough.
|
||||
#+HTML: </details>
|
||||
#+end_exercice
|
||||
|
||||
In order to have the wanted Roll-off, two integrators are used, a lead is also added to have sufficient phase margin.
|
||||
|
||||
The obtained controller is shown below, and the bode plot of the Loop Gain is shown in Figure [[fig:loop_gain_manual_afm]].
|
||||
Let's say we came up with the following controller.
|
||||
#+begin_src matlab
|
||||
K = 14e8 * ... % Gain
|
||||
1/(s^2) * ... % Double Integrator
|
||||
K = 14e8 * ... % Gain
|
||||
1/(s^2) * ... % Double Integrator
|
||||
1/(1 + s/2/pi/40) * ... % Low Pass Filter
|
||||
(1 + s/(2*pi*10/sqrt(8)))/(1 + s/(2*pi*10*sqrt(8))); % Lead
|
||||
#+end_src
|
||||
|
||||
The bode plot of the Loop Gain is shown in Figure [[fig:loop_gain_manual_afm]] and we can verify that we have the wanted stability margins using the =margin= command:
|
||||
#+begin_src matlab
|
||||
[Gm, Pm, ~, Wc] = margin(G*K)
|
||||
#+end_src
|
||||
|
||||
#+begin_src matlab :exports results :results value table replace :tangle no :post addhdr(*this*)
|
||||
data2orgtable([Gm; Pm; Wc/2/pi], {'Gain Margin $> 3$ [dB]', 'Phase Margin $> 30$ [deg]', 'Crossover $\approx 10$ [Hz]'}, {'Requirements', 'Manual Method'}, ' %.1f ');
|
||||
#+end_src
|
||||
|
||||
#+RESULTS:
|
||||
| Requirements | Manual Method |
|
||||
|-----------------------------+---------------|
|
||||
| Gain Margin $> 3$ [dB] | 3.1 |
|
||||
| Phase Margin $> 30$ [deg] | 35.4 |
|
||||
| Crossover $\approx 10$ [Hz] | 10.1 |
|
||||
|
||||
#+begin_src matlab :exports none
|
||||
freqs = logspace(0, 3, 1000);
|
||||
|
||||
@@ -617,106 +655,62 @@ The obtained controller is shown below, and the bode plot of the Loop Gain is sh
|
||||
#+RESULTS:
|
||||
[[file:figs/loop_gain_manual_afm.png]]
|
||||
|
||||
And we can verify that we have the wanted stability margins:
|
||||
#+begin_src matlab
|
||||
[Gm, Pm, ~, Wc] = margin(G*K)
|
||||
#+end_src
|
||||
|
||||
#+begin_src matlab :exports results :results value table replace :tangle no :post addhdr(*this*)
|
||||
data2orgtable([Gm; Pm; Wc/2/pi], {'Gain Margin $> 3$ [dB]', 'Phase Margin $> 30$ [deg]', 'Crossover $\approx 10$ [Hz]'}, {'Requirements', 'Manual Method'}, ' %.1f ');
|
||||
#+end_src
|
||||
|
||||
#+RESULTS:
|
||||
| Requirements | Manual Method |
|
||||
|-----------------------------+---------------|
|
||||
| Gain Margin $> 3$ [dB] | 3.1 |
|
||||
| Phase Margin $> 30$ [deg] | 35.4 |
|
||||
| Crossover $\approx 10$ [Hz] | 10.1 |
|
||||
|
||||
** $\mathcal{H}_\infty$ Loop Shaping Synthesis
|
||||
<<sec:h_infinity_open_loop_shaping>>
|
||||
|
||||
The Open Loop Shaping synthesis can be performed using the $\mathcal{H}_\infty$ Synthesis.
|
||||
The synthesis of controllers based on the Loop Shaping method can be automated using the $\mathcal{H}_\infty$ Synthesis.
|
||||
|
||||
Even though we will not go into details, we will provide one example.
|
||||
|
||||
Using Matlab, the $\mathcal{H}_\infty$ Loop Shaping Synthesis can be performed using the =loopsyn= command:
|
||||
Using Matlab, it can be easily performed using the =loopsyn= command:
|
||||
#+begin_src matlab :eval no :tangle no
|
||||
K = loopsyn(G, Gd);
|
||||
K = loopsyn(G, Lw);
|
||||
#+end_src
|
||||
where:
|
||||
- =G= is the (LTI) plant
|
||||
- =Gd= is the wanted loop shape
|
||||
- =Lw= is the wanted loop shape
|
||||
- =K= is the synthesize controller
|
||||
|
||||
#+begin_seealso
|
||||
Matlab documentation of =loopsyn= ([[https://www.mathworks.com/help/robust/ref/loopsyn.html][link]]).
|
||||
#+end_seealso
|
||||
|
||||
Therefore, by just providing the wanted loop shape and the plant model, the $\mathcal{H}_\infty$ Loop Shaping synthesis generates a /stabilizing/ controller such that the obtained loop gain $L(s)$ matches the specified one with an accuracy $\gamma$.
|
||||
|
||||
Even though we will not go into details and explain how such synthesis is working, an example is provided in the next section.
|
||||
|
||||
** Example of the $\mathcal{H}_\infty$ Loop Shaping Synthesis
|
||||
<<sec:h_infinity_open_loop_shaping_example>>
|
||||
|
||||
Let's reuse the previous plant.
|
||||
To apply the $\mathcal{H}_\infty$ Loop Shaping Synthesis, the wanted shape of the loop gain should be determined from the specifications.
|
||||
This is summarized in Table [[tab:open_loop_shaping_specifications]].
|
||||
|
||||
Translate the specification into the wanted shape of the open loop gain.
|
||||
- *Performance*: Bandwidth of approximately 10Hz: $|L_w(j2 \pi 10)| = 1$
|
||||
- *Noise Attenuation*: Roll-off of -40dB/decade past 30Hz
|
||||
- *Robustness*: Gain margin > 3dB and Phase margin > 30 deg
|
||||
Such shape corresponds to the typical wanted Loop gain Shape shown in Figure [[fig:open_loop_shaping_shape]].
|
||||
|
||||
#+name: tab:open_loop_shaping_specifications
|
||||
#+caption: Wanted Loop Shape corresponding to each specification
|
||||
| | Specification | Corresponding Loop Shape |
|
||||
|-------------------------+---------------------------------------------+-----------------------------------------------------------------|
|
||||
| *Disturbance Rejection* | Highest possible rejection below 1Hz | Slope of -40dB/decade at low frequency to have a high loop gain |
|
||||
| *Positioning Speed* | Bandwidth of approximately 10Hz | $L$ crosses 1 at 10Hz: $\vert L_w(j2 \pi 10)\vert = 1$ |
|
||||
| *Noise Attenuation* | Roll-off of -40dB/decade past 30Hz | Roll-off of -40dB/decade past 30Hz |
|
||||
| *Robustness* | Gain margin > 3dB and Phase margin > 30 deg | Slope of -20dB/decade near the crossover |
|
||||
|
||||
Then, a (stable, minimum phase) transfer function $L_w(s)$ should be created that has the same gain as the wanted shape of the Loop gain.
|
||||
For this example, a double integrator and a lead centered on 10Hz are used.
|
||||
Then the gain is adjusted such that the $|L_w(j2 \pi 10)| = 1$.
|
||||
|
||||
Using Matlab, we have:
|
||||
#+begin_src matlab
|
||||
Lw = 2.3e3 * ...
|
||||
1/(s^2) * ... % Double Integrator
|
||||
(1 + s/(2*pi*10/sqrt(3)))/(1 + s/(2*pi*10*sqrt(3))); % Lead
|
||||
#+end_src
|
||||
|
||||
The $\mathcal{H}_\infty$ optimal open loop shaping synthesis is performed using the =loopsyn= command:
|
||||
The $\mathcal{H}_\infty$ open loop shaping synthesis is then performed using the =loopsyn= command:
|
||||
#+begin_src matlab
|
||||
[K, ~, GAM] = loopsyn(G, Lw);
|
||||
#+end_src
|
||||
|
||||
#+begin_important
|
||||
It is always important to analyze the controller after the synthesis is performed.
|
||||
|
||||
In the end, a synthesize controller is just a combination of low pass filters, high pass filters, notches, leads, etc.
|
||||
#+end_important
|
||||
|
||||
Let's briefly analyze the obtained controller which bode plot is shown in Figure [[fig:open_loop_shaping_hinf_K]]:
|
||||
- two integrators are used at low frequency to have the wanted low frequency high gain
|
||||
- a lead is added centered with the crossover frequency to increase the phase margin
|
||||
- a notch is added at the resonance of the plant to increase the gain margin (this is very typical of $\mathcal{H}_\infty$ controllers, and can be an issue, more info on that latter)
|
||||
|
||||
#+begin_src matlab :exports none
|
||||
freqs = logspace(0, 3, 1000);
|
||||
|
||||
figure;
|
||||
tiledlayout(3, 1, 'TileSpacing', 'None', 'Padding', 'None');
|
||||
|
||||
ax1 = nexttile([2,1]);
|
||||
plot(freqs, abs(squeeze(freqresp(K, freqs, 'Hz'))));
|
||||
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
|
||||
ylabel('Magnitude'); set(gca, 'XTickLabel',[]);
|
||||
hold off;
|
||||
|
||||
ax2 = nexttile;
|
||||
plot(freqs, 180/pi*angle(squeeze(freqresp(K, freqs, 'Hz'))));
|
||||
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'lin');
|
||||
yticks(-360:90:360); ylim([-180, 90]);
|
||||
xlabel('Frequency [Hz]'); ylabel('Phase [deg]');
|
||||
|
||||
linkaxes([ax1,ax2],'x');
|
||||
xlim([freqs(1), freqs(end)]);
|
||||
#+end_src
|
||||
|
||||
#+begin_src matlab :tangle no :exports results :results file replace
|
||||
exportFig('figs/open_loop_shaping_hinf_K.pdf', 'width', 'wide', 'height', 'normal');
|
||||
#+end_src
|
||||
|
||||
#+name: fig:open_loop_shaping_hinf_K
|
||||
#+caption: Obtained controller $K$ using the open-loop $\mathcal{H}_\infty$ shaping
|
||||
#+RESULTS:
|
||||
[[file:figs/open_loop_shaping_hinf_K.png]]
|
||||
|
||||
The obtained Loop Gain is shown in Figure [[fig:open_loop_shaping_hinf_L]] and matches the specified one by a factor $\gamma$.
|
||||
The obtained Loop Gain is shown in Figure [[fig:open_loop_shaping_hinf_L]] and matches the specified one by a factor $\gamma \approx 2$.
|
||||
|
||||
#+begin_src matlab :exports none
|
||||
freqs = logspace(0, 3, 1000);
|
||||
@@ -758,7 +752,51 @@ The obtained Loop Gain is shown in Figure [[fig:open_loop_shaping_hinf_L]] and m
|
||||
#+RESULTS:
|
||||
[[file:figs/open_loop_shaping_hinf_L.png]]
|
||||
|
||||
Let's now compare the obtained stability margins of the $\mathcal{H}_\infty$ controller and of the manually developed controller in Table [[tab:open_loop_shaping_compare]].
|
||||
|
||||
#+begin_important
|
||||
When using the $\mathcal{H}_\infty$ Synthesis, it is usually recommended to analyze the obtained controller.
|
||||
|
||||
This is usually done by breaking down the controller into simple elements such as low pass filters, high pass filters, notches, leads, etc.
|
||||
#+end_important
|
||||
|
||||
Let's briefly analyze the obtained controller which bode plot is shown in Figure [[fig:open_loop_shaping_hinf_K]]:
|
||||
- two integrators are used at low frequency to have the wanted low frequency high gain
|
||||
- a lead is added centered with the crossover frequency to increase the phase margin
|
||||
- a notch is added at the resonance of the plant to increase the gain margin (this is very typical of $\mathcal{H}_\infty$ controllers, and can be an issue, more info on that latter)
|
||||
|
||||
#+begin_src matlab :exports none
|
||||
freqs = logspace(0, 3, 1000);
|
||||
|
||||
figure;
|
||||
tiledlayout(3, 1, 'TileSpacing', 'None', 'Padding', 'None');
|
||||
|
||||
ax1 = nexttile([2,1]);
|
||||
plot(freqs, abs(squeeze(freqresp(K, freqs, 'Hz'))));
|
||||
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
|
||||
ylabel('Magnitude'); set(gca, 'XTickLabel',[]);
|
||||
hold off;
|
||||
|
||||
ax2 = nexttile;
|
||||
plot(freqs, 180/pi*angle(squeeze(freqresp(K, freqs, 'Hz'))));
|
||||
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'lin');
|
||||
yticks(-360:90:360); ylim([-180, 90]);
|
||||
xlabel('Frequency [Hz]'); ylabel('Phase [deg]');
|
||||
|
||||
linkaxes([ax1,ax2],'x');
|
||||
xlim([freqs(1), freqs(end)]);
|
||||
#+end_src
|
||||
|
||||
#+begin_src matlab :tangle no :exports results :results file replace
|
||||
exportFig('figs/open_loop_shaping_hinf_K.pdf', 'width', 'wide', 'height', 'normal');
|
||||
#+end_src
|
||||
|
||||
#+name: fig:open_loop_shaping_hinf_K
|
||||
#+caption: Obtained controller $K$ using the open-loop $\mathcal{H}_\infty$ shaping
|
||||
#+RESULTS:
|
||||
[[file:figs/open_loop_shaping_hinf_K.png]]
|
||||
|
||||
|
||||
Let's finally compare the obtained stability margins of the $\mathcal{H}_\infty$ controller and of the manually developed controller in Table [[tab:open_loop_shaping_compare]].
|
||||
|
||||
#+begin_src matlab :exports none
|
||||
[Gm_2, Pm_2, ~, Wc_2] = margin(G*K)
|
||||
|
||||
Reference in new issue
Block a user