1067 lines
34 KiB
HTML
1067 lines
34 KiB
HTML
<?xml version="1.0" encoding="utf-8"?>
|
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
|
|
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
|
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
|
|
<head>
|
|
<!-- 2020-11-27 ven. 23:12 -->
|
|
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
|
|
<title>Robust Control - \(\mathcal{H}_\infty\) Synthesis</title>
|
|
<meta name="generator" content="Org mode" />
|
|
<meta name="author" content="Dehaeze Thomas" />
|
|
<link rel="stylesheet" type="text/css" href="https://research.tdehaeze.xyz/css/style.css"/>
|
|
<script type="text/javascript" src="https://research.tdehaeze.xyz/js/script.js"></script>
|
|
<script>MathJax = {
|
|
tex: {
|
|
tags: 'ams',
|
|
macros: {bm: ["\\boldsymbol{#1}",1],}
|
|
}
|
|
};
|
|
</script>
|
|
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js"></script>
|
|
</head>
|
|
<body>
|
|
<div id="org-div-home-and-up">
|
|
<a accesskey="h" href="../index.html"> UP </a>
|
|
|
|
|
<a accesskey="H" href="../index.html"> HOME </a>
|
|
</div><div id="content">
|
|
<h1 class="title">Robust Control - \(\mathcal{H}_\infty\) Synthesis</h1>
|
|
<div id="table-of-contents">
|
|
<h2>Table of Contents</h2>
|
|
<div id="text-table-of-contents">
|
|
<ul>
|
|
<li><a href="#org983bccb">1. Introduction to the Control Methodology - Model Based Control</a>
|
|
<ul>
|
|
<li><a href="#org18f2c71">1.1. Control Methodology</a></li>
|
|
<li><a href="#org49ba16e">1.2. Some Background: From Classical Control to Robust Control</a></li>
|
|
<li><a href="#org3998425">1.3. Example System</a></li>
|
|
</ul>
|
|
</li>
|
|
<li><a href="#org2f14f6e">2. Classical Open Loop Shaping</a>
|
|
<ul>
|
|
<li><a href="#orgadf1fa2">2.1. Introduction to Open Loop Shaping</a></li>
|
|
<li><a href="#org480ec5c">2.2. Example of Open Loop Shaping</a></li>
|
|
<li><a href="#org81a2b10">2.3. \(\mathcal{H}_\infty\) Loop Shaping Synthesis</a></li>
|
|
<li><a href="#org8f1b4c8">2.4. Example of the \(\mathcal{H}_\infty\) Loop Shaping Synthesis</a></li>
|
|
</ul>
|
|
</li>
|
|
<li><a href="#orga39391a">3. First Step in the \(\mathcal{H}_\infty\) world</a>
|
|
<ul>
|
|
<li><a href="#orgafc7a12">3.1. The \(\mathcal{H}_\infty\) Norm</a></li>
|
|
<li><a href="#org5ab38ae">3.2. \(\mathcal{H}_\infty\) Synthesis</a></li>
|
|
<li><a href="#org3371822">3.3. The Generalized Plant</a></li>
|
|
<li><a href="#orgbf413fb">3.4. From a Classical Feedback Architecture to a Generalized Plant</a></li>
|
|
<li><a href="#org5b0f8f6">3.5. The General Synthesis Problem Formulation</a></li>
|
|
</ul>
|
|
</li>
|
|
<li><a href="#org0a60e2d">4. Modern Interpretation of the Control Specifications</a>
|
|
<ul>
|
|
<li><a href="#orgeaf9df5">4.1. Introduction</a></li>
|
|
</ul>
|
|
</li>
|
|
<li><a href="#org73188d9">5. Resources</a></li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
|
|
<div id="outline-container-org983bccb" class="outline-2">
|
|
<h2 id="org983bccb"><span class="section-number-2">1</span> Introduction to the Control Methodology - Model Based Control</h2>
|
|
<div class="outline-text-2" id="text-1">
|
|
</div>
|
|
<div id="outline-container-org18f2c71" class="outline-3">
|
|
<h3 id="org18f2c71"><span class="section-number-3">1.1</span> Control Methodology</h3>
|
|
<div class="outline-text-3" id="text-1-1">
|
|
<p>
|
|
The typical methodology when applying Model Based Control to a plant is schematically shown in Figure <a href="#orgc0a3638">1</a>.
|
|
It consists of three steps:
|
|
</p>
|
|
<ol class="org-ol">
|
|
<li><b>Identification or modeling</b>: \(\Longrightarrow\) mathematical model</li>
|
|
<li><b>Translate the specifications into mathematical criteria</b>:
|
|
<ul class="org-ul">
|
|
<li><span class="underline">Specifications</span>: Response Time, Noise Rejection, Maximum input amplitude, Robustness, …</li>
|
|
<li><span class="underline">Mathematical Criteria</span>: Cost Function, Shape of TF</li>
|
|
</ul></li>
|
|
<li><b>Synthesis</b>: research of \(K\) that satisfies the specifications for the model of the system</li>
|
|
</ol>
|
|
|
|
|
|
<div id="orgc0a3638" class="figure">
|
|
<p><img src="figs/control-procedure.png" alt="control-procedure.png" />
|
|
</p>
|
|
<p><span class="figure-number">Figure 1: </span>Typical Methodoly for Model Based Control</p>
|
|
</div>
|
|
|
|
<p>
|
|
In this document, we will mainly focus on steps 2 and 3.
|
|
</p>
|
|
</div>
|
|
</div>
|
|
|
|
<div id="outline-container-org49ba16e" class="outline-3">
|
|
<h3 id="org49ba16e"><span class="section-number-3">1.2</span> Some Background: From Classical Control to Robust Control</h3>
|
|
<div class="outline-text-3" id="text-1-2">
|
|
<table id="orgd1f0c28" border="2" cellspacing="0" cellpadding="6" rules="groups" frame="hsides">
|
|
<caption class="t-above"><span class="table-number">Table 1:</span> Table summurazing the main differences between classical, modern and robust control</caption>
|
|
|
|
<colgroup>
|
|
<col class="org-left" />
|
|
|
|
<col class="org-center" />
|
|
|
|
<col class="org-center" />
|
|
|
|
<col class="org-center" />
|
|
</colgroup>
|
|
<thead>
|
|
<tr>
|
|
<th scope="col" class="org-left"> </th>
|
|
<th scope="col" class="org-center"><b>Classical Control</b></th>
|
|
<th scope="col" class="org-center"><b>Modern Control</b></th>
|
|
<th scope="col" class="org-center"><b>Robust Control</b></th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr>
|
|
<td class="org-left"><b>Date</b></td>
|
|
<td class="org-center">1930-</td>
|
|
<td class="org-center">1960-</td>
|
|
<td class="org-center">1980-</td>
|
|
</tr>
|
|
</tbody>
|
|
<tbody>
|
|
<tr>
|
|
<td class="org-left"><b>Tools</b></td>
|
|
<td class="org-center">Transfer Functions</td>
|
|
<td class="org-center">State Space formulation</td>
|
|
<td class="org-center">Systems and Signals Norms (\(\mathcal{H}_\infty\), \(\mathcal{H}_2\) Norms)</td>
|
|
</tr>
|
|
|
|
<tr>
|
|
<td class="org-left"> </td>
|
|
<td class="org-center">Nyquist Plots</td>
|
|
<td class="org-center">Riccati Equations</td>
|
|
<td class="org-center">Closed Loop Transfer Functions</td>
|
|
</tr>
|
|
|
|
<tr>
|
|
<td class="org-left"> </td>
|
|
<td class="org-center">Bode Plots</td>
|
|
<td class="org-center"> </td>
|
|
<td class="org-center">Open/Closed Loop Shaping</td>
|
|
</tr>
|
|
|
|
<tr>
|
|
<td class="org-left"> </td>
|
|
<td class="org-center">Phase and Gain margins</td>
|
|
<td class="org-center"> </td>
|
|
<td class="org-center">Weighting Functions</td>
|
|
</tr>
|
|
|
|
<tr>
|
|
<td class="org-left"> </td>
|
|
<td class="org-center"> </td>
|
|
<td class="org-center"> </td>
|
|
<td class="org-center">Disk margin</td>
|
|
</tr>
|
|
</tbody>
|
|
<tbody>
|
|
<tr>
|
|
<td class="org-left"><b>Control Architectures</b></td>
|
|
<td class="org-center">Proportional, Integral, Derivative</td>
|
|
<td class="org-center">Full State Feedback</td>
|
|
<td class="org-center">General Control Configuration</td>
|
|
</tr>
|
|
|
|
<tr>
|
|
<td class="org-left"> </td>
|
|
<td class="org-center">Leads, Lags</td>
|
|
<td class="org-center">LQR, LQG</td>
|
|
<td class="org-center"> </td>
|
|
</tr>
|
|
|
|
<tr>
|
|
<td class="org-left"> </td>
|
|
<td class="org-center"> </td>
|
|
<td class="org-center">Kalman Filters</td>
|
|
<td class="org-center"> </td>
|
|
</tr>
|
|
</tbody>
|
|
<tbody>
|
|
<tr>
|
|
<td class="org-left"><b>Advantages</b></td>
|
|
<td class="org-center">Study Stability</td>
|
|
<td class="org-center">Automatic Synthesis</td>
|
|
<td class="org-center">Automatic Synthesis</td>
|
|
</tr>
|
|
|
|
<tr>
|
|
<td class="org-left"> </td>
|
|
<td class="org-center">Simple</td>
|
|
<td class="org-center">MIMO</td>
|
|
<td class="org-center">MIMO</td>
|
|
</tr>
|
|
|
|
<tr>
|
|
<td class="org-left"> </td>
|
|
<td class="org-center">Natural</td>
|
|
<td class="org-center">Optimization Problem</td>
|
|
<td class="org-center">Optimization Problem</td>
|
|
</tr>
|
|
|
|
<tr>
|
|
<td class="org-left"> </td>
|
|
<td class="org-center"> </td>
|
|
<td class="org-center"> </td>
|
|
<td class="org-center">Guaranteed Robustness</td>
|
|
</tr>
|
|
|
|
<tr>
|
|
<td class="org-left"> </td>
|
|
<td class="org-center"> </td>
|
|
<td class="org-center"> </td>
|
|
<td class="org-center">Easy specification of performances</td>
|
|
</tr>
|
|
</tbody>
|
|
<tbody>
|
|
<tr>
|
|
<td class="org-left"><b>Disadvantages</b></td>
|
|
<td class="org-center">Manual Method</td>
|
|
<td class="org-center">No Guaranteed Robustness</td>
|
|
<td class="org-center">Required knowledge of specific tools</td>
|
|
</tr>
|
|
|
|
<tr>
|
|
<td class="org-left"> </td>
|
|
<td class="org-center">Only SISO</td>
|
|
<td class="org-center">Difficult Rejection of Perturbations</td>
|
|
<td class="org-center">Need a reasonably good model of the system</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
|
|
<div id="outline-container-org3998425" class="outline-3">
|
|
<h3 id="org3998425"><span class="section-number-3">1.3</span> Example System</h3>
|
|
<div class="outline-text-3" id="text-1-3">
|
|
<p>
|
|
Let’s consider the model shown in Figure <a href="#org6c29b14">2</a>.
|
|
It could represent a suspension system with a payload to position or isolate using an force actuator and an inertial sensor.
|
|
The notations used are listed in Table <a href="#org2590b80">2</a>.
|
|
</p>
|
|
|
|
|
|
<div id="org6c29b14" class="figure">
|
|
<p><img src="figs/mech_sys_1dof_inertial_contr.png" alt="mech_sys_1dof_inertial_contr.png" />
|
|
</p>
|
|
<p><span class="figure-number">Figure 2: </span>Test System consisting of a payload with a mass \(m\) on top of an active system with a stiffness \(k\), damping \(c\) and an actuator. A feedback controller \(K(s)\) is added to position / isolate the payload.</p>
|
|
</div>
|
|
|
|
<table id="org2590b80" border="2" cellspacing="0" cellpadding="6" rules="groups" frame="hsides">
|
|
<caption class="t-above"><span class="table-number">Table 2:</span> Example system variables</caption>
|
|
|
|
<colgroup>
|
|
<col class="org-left" />
|
|
|
|
<col class="org-left" />
|
|
|
|
<col class="org-left" />
|
|
|
|
<col class="org-left" />
|
|
</colgroup>
|
|
<thead>
|
|
<tr>
|
|
<th scope="col" class="org-left"><b>Notation</b></th>
|
|
<th scope="col" class="org-left"><b>Description</b></th>
|
|
<th scope="col" class="org-left"><b>Value</b></th>
|
|
<th scope="col" class="org-left"><b>Unit</b></th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr>
|
|
<td class="org-left">\(m\)</td>
|
|
<td class="org-left">Payload’s mass to position / isolate</td>
|
|
<td class="org-left">\(10\)</td>
|
|
<td class="org-left">[kg]</td>
|
|
</tr>
|
|
|
|
<tr>
|
|
<td class="org-left">\(k\)</td>
|
|
<td class="org-left">Stiffness of the suspension system</td>
|
|
<td class="org-left">\(10^6\)</td>
|
|
<td class="org-left">[N/m]</td>
|
|
</tr>
|
|
|
|
<tr>
|
|
<td class="org-left">\(c\)</td>
|
|
<td class="org-left">Damping coefficient of the suspension system</td>
|
|
<td class="org-left">\(400\)</td>
|
|
<td class="org-left">[N/(m/s)]</td>
|
|
</tr>
|
|
|
|
<tr>
|
|
<td class="org-left">\(y\)</td>
|
|
<td class="org-left">Payload absolute displacement (measured by an inertial sensor)</td>
|
|
<td class="org-left"> </td>
|
|
<td class="org-left">[m]</td>
|
|
</tr>
|
|
|
|
<tr>
|
|
<td class="org-left">\(d\)</td>
|
|
<td class="org-left">Ground displacement, it acts as a disturbance</td>
|
|
<td class="org-left"> </td>
|
|
<td class="org-left">[m]</td>
|
|
</tr>
|
|
|
|
<tr>
|
|
<td class="org-left">\(u\)</td>
|
|
<td class="org-left">Actuator force</td>
|
|
<td class="org-left"> </td>
|
|
<td class="org-left">[N]</td>
|
|
</tr>
|
|
|
|
<tr>
|
|
<td class="org-left">\(r\)</td>
|
|
<td class="org-left">Wanted position of the mass (the reference)</td>
|
|
<td class="org-left"> </td>
|
|
<td class="org-left">[m]</td>
|
|
</tr>
|
|
|
|
<tr>
|
|
<td class="org-left">\(\epsilon = r - y\)</td>
|
|
<td class="org-left">Position error</td>
|
|
<td class="org-left"> </td>
|
|
<td class="org-left">[m]</td>
|
|
</tr>
|
|
|
|
<tr>
|
|
<td class="org-left">\(K\)</td>
|
|
<td class="org-left">Feedback controller</td>
|
|
<td class="org-left">to be designed</td>
|
|
<td class="org-left">[N/m]</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
|
|
<div class="exercice" id="org60eec50">
|
|
<p>
|
|
Derive the following open-loop transfer functions:
|
|
</p>
|
|
\begin{align}
|
|
G(s) &= \frac{y}{u} \\
|
|
G_d(s) &= \frac{y}{d}
|
|
\end{align}
|
|
|
|
<details><summary>Hint</summary>
|
|
<p>
|
|
You can follow this generic procedure:
|
|
</p>
|
|
<ol class="org-ol">
|
|
<li>List all applied forces ot the mass: Actuator force, Stiffness force (Hooke’s law), …</li>
|
|
<li>Apply the Newton’s Second Law on the payload
|
|
\[ m \ddot{y} = \Sigma F \]</li>
|
|
<li>Transform the differential equations into the Laplace domain:
|
|
\[ \frac{d\ \cdot}{dt} \Leftrightarrow \cdot \times s \]</li>
|
|
<li>Write \(y(s)\) as a function of \(u(s)\) and \(w(s)\)</li>
|
|
</ol>
|
|
</details>
|
|
|
|
<details><summary>Results</summary>
|
|
\begin{align}
|
|
G(s) &= \frac{1}{m s^2 + cs + k} \\
|
|
G_d(s) &= \frac{cs + k}{m s^2 + cs + k}
|
|
\end{align}
|
|
</details>
|
|
|
|
</div>
|
|
|
|
<p>
|
|
Having obtained \(G(s)\) and \(G_d(s)\), we can transform the system shown in Figure <a href="#org6c29b14">2</a> into a classical feedback form as shown in Figure <a href="#org1e99301">6</a>.
|
|
</p>
|
|
|
|
|
|
<div id="org9295a3c" class="figure">
|
|
<p><img src="figs/classical_feedback_test_system.png" alt="classical_feedback_test_system.png" />
|
|
</p>
|
|
<p><span class="figure-number">Figure 3: </span>Block diagram corresponding to the example system</p>
|
|
</div>
|
|
|
|
|
|
<p>
|
|
Let’s define the system parameters on Matlab.
|
|
</p>
|
|
<div class="org-src-container">
|
|
<pre class="src src-matlab"><span class="linenr">1: </span>k = 1e6; <span class="org-comment">% Stiffness [N/m]</span>
|
|
<span class="linenr">2: </span>c = 4e2; <span class="org-comment">% Damping [N/(m/s)]</span>
|
|
<span class="linenr">3: </span>m = 10; <span class="org-comment">% Mass [kg]</span>
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
And now the system dynamics \(G(s)\) and \(G_d(s)\) (their bode plots are shown in Figures <a href="#orgc2b7d7d">4</a> and <a href="#orgf203cd9">5</a>).
|
|
</p>
|
|
<div class="org-src-container">
|
|
<pre class="src src-matlab"><span class="linenr">4: </span>G = 1<span class="org-type">/</span>(m<span class="org-type">*</span>s<span class="org-type">^</span>2 <span class="org-type">+</span> c<span class="org-type">*</span>s <span class="org-type">+</span> k); <span class="org-comment">% Plant</span>
|
|
<span class="linenr">5: </span>Gd = (c<span class="org-type">*</span>s <span class="org-type">+</span> k)<span class="org-type">/</span>(m<span class="org-type">*</span>s<span class="org-type">^</span>2 <span class="org-type">+</span> c<span class="org-type">*</span>s <span class="org-type">+</span> k); <span class="org-comment">% Disturbance</span>
|
|
</pre>
|
|
</div>
|
|
|
|
|
|
<div id="orgc2b7d7d" class="figure">
|
|
<p><img src="figs/bode_plot_example_afm.png" alt="bode_plot_example_afm.png" />
|
|
</p>
|
|
<p><span class="figure-number">Figure 4: </span>Bode plot of the plant \(G(s)\)</p>
|
|
</div>
|
|
|
|
|
|
<div id="orgf203cd9" class="figure">
|
|
<p><img src="figs/bode_plot_example_Gd.png" alt="bode_plot_example_Gd.png" />
|
|
</p>
|
|
<p><span class="figure-number">Figure 5: </span>Magnitude of the disturbance transfer function \(G_d(s)\)</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div id="outline-container-org2f14f6e" class="outline-2">
|
|
<h2 id="org2f14f6e"><span class="section-number-2">2</span> Classical Open Loop Shaping</h2>
|
|
<div class="outline-text-2" id="text-2">
|
|
</div>
|
|
<div id="outline-container-orgadf1fa2" class="outline-3">
|
|
<h3 id="orgadf1fa2"><span class="section-number-3">2.1</span> Introduction to Open Loop Shaping</h3>
|
|
<div class="outline-text-3" id="text-2-1">
|
|
<div class="definition" id="orgba735c5">
|
|
<p>
|
|
The <b>Loop Gain</b> \(L(s)\) usually refers to as the product of the controller and the plant (Figure <a href="#org1e99301">6</a>):
|
|
</p>
|
|
\begin{equation}
|
|
L(s) = G(s) \cdot K(s) \label{eq:loop_gain}
|
|
\end{equation}
|
|
|
|
|
|
<div id="org1e99301" class="figure">
|
|
<p><img src="figs/open_loop_shaping.png" alt="open_loop_shaping.png" />
|
|
</p>
|
|
<p><span class="figure-number">Figure 6: </span>Classical Feedback Architecture</p>
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div class="definition" id="org53d42d3">
|
|
<p>
|
|
<b>Open Loop Shaping</b> refers to a control design technique where the controller \(K(s)\) is designed such that the <b>Open Loop Gain</b> \(L(s)\) has desirable shape.
|
|
</p>
|
|
|
|
</div>
|
|
|
|
<p>
|
|
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)\):
|
|
</p>
|
|
<ul class="org-ul">
|
|
<li><b>Performance</b>: \(L\) large</li>
|
|
<li><b>Good disturbance rejection</b>: \(L\) large</li>
|
|
<li><b>Limitation of measurement noise on plant output</b>: \(L\) small</li>
|
|
<li><b>Small magnitude of input signal</b>: \(K\) and \(L\) small</li>
|
|
<li><b>Nominal stability</b>: \(L\) small (RHP zeros and time delays)</li>
|
|
<li><b>Robust stability</b>: \(L\) small (neglected dynamics)</li>
|
|
</ul>
|
|
|
|
<p>
|
|
The Open Loop shape is usually done manually has the loop gain \(L(s)\) depends linearly on \(K(s)\) \eqref{eq:loop_gain}.
|
|
</p>
|
|
|
|
<p>
|
|
\(K(s)\) then consists of a combination of leads, lags, notches, etc. such that \(L(s)\) has the wanted shape.
|
|
</p>
|
|
</div>
|
|
</div>
|
|
|
|
<div id="outline-container-org480ec5c" class="outline-3">
|
|
<h3 id="org480ec5c"><span class="section-number-3">2.2</span> Example of Open Loop Shaping</h3>
|
|
<div class="outline-text-3" id="text-2-2">
|
|
<div class="exampl" id="org9e97650">
|
|
<p>
|
|
Let’s take our example system and try to apply the Open-Loop shaping strategy to design a controller that fulfils the following specifications:
|
|
</p>
|
|
<ul class="org-ul">
|
|
<li><b>Performance</b>: Bandwidth of approximately 10Hz</li>
|
|
<li><b>Noise Attenuation</b>: Roll-off of -40dB/decade past 30Hz</li>
|
|
<li><b>Robustness</b>: Gain margin > 3dB and Phase margin > 30 deg</li>
|
|
</ul>
|
|
|
|
</div>
|
|
|
|
<div class="exercice" id="orgdf10f9e">
|
|
<p>
|
|
Using <code>SISOTOOL</code>, design a controller that fulfill the specifications.
|
|
</p>
|
|
|
|
<div class="org-src-container">
|
|
<pre class="src src-matlab">sisotool(G)
|
|
</pre>
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<p>
|
|
In order to have the wanted Roll-off, two integrators are used, a lead is also added to have sufficient phase margin.
|
|
</p>
|
|
|
|
<p>
|
|
The obtained controller is shown below, and the bode plot of the Loop Gain is shown in Figure <a href="#org2f8dcdc">7</a>.
|
|
</p>
|
|
<div class="org-src-container">
|
|
<pre class="src src-matlab">K = 14e8 <span class="org-type">*</span> ...<span class="org-comment"> % Gain</span>
|
|
1<span class="org-type">/</span>(s<span class="org-type">^</span>2) <span class="org-type">*</span> ...<span class="org-comment"> % Double Integrator</span>
|
|
1<span class="org-type">/</span>(1 <span class="org-type">+</span> s<span class="org-type">/</span>2<span class="org-type">/</span><span class="org-constant">pi</span><span class="org-type">/</span>40) <span class="org-type">*</span> ...<span class="org-comment"> % Low Pass Filter</span>
|
|
(1 <span class="org-type">+</span> s<span class="org-type">/</span>(2<span class="org-type">*</span><span class="org-constant">pi</span><span class="org-type">*</span>10<span class="org-type">/</span>sqrt(8)))<span class="org-type">/</span>(1 <span class="org-type">+</span> s<span class="org-type">/</span>(2<span class="org-type">*</span><span class="org-constant">pi</span><span class="org-type">*</span>10<span class="org-type">*</span>sqrt(8))); <span class="org-comment">% Lead</span>
|
|
</pre>
|
|
</div>
|
|
|
|
|
|
<div id="org2f8dcdc" class="figure">
|
|
<p><img src="figs/loop_gain_manual_afm.png" alt="loop_gain_manual_afm.png" />
|
|
</p>
|
|
<p><span class="figure-number">Figure 7: </span>Bode Plot of the obtained Loop Gain \(L(s) = G(s) K(s)\)</p>
|
|
</div>
|
|
|
|
<p>
|
|
And we can verify that we have the wanted stability margins:
|
|
</p>
|
|
<div class="org-src-container">
|
|
<pre class="src src-matlab">[Gm, Pm, <span class="org-type">~</span>, Wc] = margin(G<span class="org-type">*</span>K)
|
|
</pre>
|
|
</div>
|
|
|
|
<table border="2" cellspacing="0" cellpadding="6" rules="groups" frame="hsides">
|
|
|
|
|
|
<colgroup>
|
|
<col class="org-left" />
|
|
|
|
<col class="org-right" />
|
|
</colgroup>
|
|
<thead>
|
|
<tr>
|
|
<th scope="col" class="org-left"> </th>
|
|
<th scope="col" class="org-right">Manual Method</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr>
|
|
<td class="org-left">Gain Margin \(> 3\) [dB]</td>
|
|
<td class="org-right">3.1</td>
|
|
</tr>
|
|
|
|
<tr>
|
|
<td class="org-left">Phase Margin \(> 30\) [deg]</td>
|
|
<td class="org-right">35.4</td>
|
|
</tr>
|
|
|
|
<tr>
|
|
<td class="org-left">Crossover \(\approx 10\) [Hz]</td>
|
|
<td class="org-right">10.1</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
|
|
<div id="outline-container-org81a2b10" class="outline-3">
|
|
<h3 id="org81a2b10"><span class="section-number-3">2.3</span> \(\mathcal{H}_\infty\) Loop Shaping Synthesis</h3>
|
|
<div class="outline-text-3" id="text-2-3">
|
|
<p>
|
|
The Open Loop Shaping synthesis can be performed using the \(\mathcal{H}_\infty\) Synthesis.
|
|
</p>
|
|
|
|
<p>
|
|
Even though we will not go into details, we will provide one example.
|
|
</p>
|
|
|
|
<p>
|
|
Using Matlab, the \(\mathcal{H}_\infty\) synthesis of a controller based on the wanted open loop shape can be performed using the <code>loopsyn</code> command:
|
|
</p>
|
|
<div class="org-src-container">
|
|
<pre class="src src-matlab">K = loopsyn(G, Gd);
|
|
</pre>
|
|
</div>
|
|
<p>
|
|
where:
|
|
</p>
|
|
<ul class="org-ul">
|
|
<li><code>G</code> is the (LTI) plant</li>
|
|
<li><code>Gd</code> is the wanted loop shape</li>
|
|
<li><code>K</code> is the synthesize controller</li>
|
|
</ul>
|
|
|
|
<div class="seealso" id="orgb2606d2">
|
|
<p>
|
|
Matlab documentation of <code>loopsyn</code> (<a href="https://www.mathworks.com/help/robust/ref/loopsyn.html">link</a>).
|
|
</p>
|
|
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div id="outline-container-org8f1b4c8" class="outline-3">
|
|
<h3 id="org8f1b4c8"><span class="section-number-3">2.4</span> Example of the \(\mathcal{H}_\infty\) Loop Shaping Synthesis</h3>
|
|
<div class="outline-text-3" id="text-2-4">
|
|
<p>
|
|
Let’s reuse the previous plant.
|
|
</p>
|
|
|
|
<p>
|
|
Translate the specification into the wanted shape of the open loop gain.
|
|
</p>
|
|
<ul class="org-ul">
|
|
<li><b>Performance</b>: Bandwidth of approximately 10Hz: \(|L_w(j2 \pi 10)| = 1\)</li>
|
|
<li><b>Noise Attenuation</b>: Roll-off of -40dB/decade past 30Hz</li>
|
|
<li><b>Robustness</b>: Gain margin > 3dB and Phase margin > 30 deg</li>
|
|
</ul>
|
|
|
|
<div class="org-src-container">
|
|
<pre class="src src-matlab">Lw = 2.3e3 <span class="org-type">*</span> ...
|
|
1<span class="org-type">/</span>(s<span class="org-type">^</span>2) <span class="org-type">*</span> ...<span class="org-comment"> % Double Integrator</span>
|
|
(1 <span class="org-type">+</span> s<span class="org-type">/</span>(2<span class="org-type">*</span><span class="org-constant">pi</span><span class="org-type">*</span>10<span class="org-type">/</span>sqrt(3)))<span class="org-type">/</span>(1 <span class="org-type">+</span> s<span class="org-type">/</span>(2<span class="org-type">*</span><span class="org-constant">pi</span><span class="org-type">*</span>10<span class="org-type">*</span>sqrt(3))); <span class="org-comment">% Lead</span>
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
The \(\mathcal{H}_\infty\) optimal open loop shaping is performed using the <code>loopsyn</code> command:
|
|
</p>
|
|
<div class="org-src-container">
|
|
<pre class="src src-matlab">[K, <span class="org-type">~</span>, GAM] = loopsyn(G, Lw);
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
The Bode plot of the obtained controller is shown in Figure <a href="#org65199e4">8</a>.
|
|
</p>
|
|
|
|
<div class="important" id="orgede0579">
|
|
<p>
|
|
It is always important to analyze the controller after the synthesis is performed.
|
|
</p>
|
|
|
|
<p>
|
|
In the end, a synthesize controller is just a combination of low pass filters, high pass filters, notches, leads, etc.
|
|
</p>
|
|
|
|
</div>
|
|
|
|
<p>
|
|
Let’s briefly analyze this controller:
|
|
</p>
|
|
<ul class="org-ul">
|
|
<li>two integrators are used at low frequency to have the wanted low frequency high gain</li>
|
|
<li>a lead is added centered with the crossover frequency to increase the phase margin</li>
|
|
<li>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)</li>
|
|
</ul>
|
|
|
|
|
|
<div id="org65199e4" class="figure">
|
|
<p><img src="figs/open_loop_shaping_hinf_K.png" alt="open_loop_shaping_hinf_K.png" />
|
|
</p>
|
|
<p><span class="figure-number">Figure 8: </span>Obtained controller \(K\) using the open-loop \(\mathcal{H}_\infty\) shaping</p>
|
|
</div>
|
|
|
|
<p>
|
|
The obtained Loop Gain is shown in Figure <a href="#orga695393">9</a>.
|
|
</p>
|
|
|
|
|
|
<div id="orga695393" class="figure">
|
|
<p><img src="figs/open_loop_shaping_hinf_L.png" alt="open_loop_shaping_hinf_L.png" />
|
|
</p>
|
|
<p><span class="figure-number">Figure 9: </span>Obtained Open Loop Gain \(L(s) = G(s) K(s)\) and comparison with the wanted Loop gain \(L_w\)</p>
|
|
</div>
|
|
|
|
<p>
|
|
Let’s now compare the obtained stability margins of the \(\mathcal{H}_\infty\) controller and of the manually developed controller in Table <a href="#orgcdf47bb">3</a>.
|
|
</p>
|
|
|
|
<table id="orgcdf47bb" border="2" cellspacing="0" cellpadding="6" rules="groups" frame="hsides">
|
|
<caption class="t-above"><span class="table-number">Table 3:</span> Comparison of the characteristics obtained with the two methods</caption>
|
|
|
|
<colgroup>
|
|
<col class="org-left" />
|
|
|
|
<col class="org-right" />
|
|
|
|
<col class="org-right" />
|
|
</colgroup>
|
|
<thead>
|
|
<tr>
|
|
<th scope="col" class="org-left">Specifications</th>
|
|
<th scope="col" class="org-right">Manual Method</th>
|
|
<th scope="col" class="org-right">\(\mathcal{H}_\infty\) Method</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr>
|
|
<td class="org-left">Gain Margin \(> 3\) [dB]</td>
|
|
<td class="org-right">3.1</td>
|
|
<td class="org-right">31.7</td>
|
|
</tr>
|
|
|
|
<tr>
|
|
<td class="org-left">Phase Margin \(> 30\) [deg]</td>
|
|
<td class="org-right">35.4</td>
|
|
<td class="org-right">54.7</td>
|
|
</tr>
|
|
|
|
<tr>
|
|
<td class="org-left">Crossover \(\approx 10\) [Hz]</td>
|
|
<td class="org-right">10.1</td>
|
|
<td class="org-right">9.9</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div id="outline-container-orga39391a" class="outline-2">
|
|
<h2 id="orga39391a"><span class="section-number-2">3</span> First Step in the \(\mathcal{H}_\infty\) world</h2>
|
|
<div class="outline-text-2" id="text-3">
|
|
</div>
|
|
<div id="outline-container-orgafc7a12" class="outline-3">
|
|
<h3 id="orgafc7a12"><span class="section-number-3">3.1</span> The \(\mathcal{H}_\infty\) Norm</h3>
|
|
<div class="outline-text-3" id="text-3-1">
|
|
<div class="definition" id="orgb2ccce0">
|
|
<p>
|
|
The \(\mathcal{H}_\infty\) norm is defined as the peak of the maximum singular value of the frequency response
|
|
</p>
|
|
\begin{equation}
|
|
\|G(s)\|_\infty = \max_\omega \bar{\sigma}\big( G(j\omega) \big)
|
|
\end{equation}
|
|
|
|
<p>
|
|
For a SISO system \(G(s)\), it is simply the peak value of \(|G(j\omega)|\) as a function of frequency:
|
|
</p>
|
|
\begin{equation}
|
|
\|G(s)\|_\infty = \max_{\omega} |G(j\omega)| \label{eq:hinf_norm_siso}
|
|
\end{equation}
|
|
|
|
</div>
|
|
|
|
<div class="exampl" id="orgda64a0c">
|
|
<p>
|
|
And compute its \(\mathcal{H}_\infty\) norm using the <code>hinfnorm</code> function:
|
|
</p>
|
|
<div class="org-src-container">
|
|
<pre class="src src-matlab">hinfnorm(G)
|
|
</pre>
|
|
</div>
|
|
|
|
<pre class="example">
|
|
7.9216e-06
|
|
</pre>
|
|
|
|
|
|
<p>
|
|
The magnitude \(|G(j\omega)|\) of the plant \(G(s)\) as a function of frequency is shown in Figure <a href="#orge580adb">10</a>.
|
|
The maximum value of the magnitude over all frequencies does correspond to the \(\mathcal{H}_\infty\) norm of \(G(s)\) as Equation \eqref{eq:hinf_norm_siso} implies.
|
|
</p>
|
|
|
|
|
|
<div id="orge580adb" class="figure">
|
|
<p><img src="figs/hinfinity_norm_siso_bode.png" alt="hinfinity_norm_siso_bode.png" />
|
|
</p>
|
|
<p><span class="figure-number">Figure 10: </span>Example of the \(\mathcal{H}_\infty\) norm of a SISO system</p>
|
|
</div>
|
|
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div id="outline-container-org5ab38ae" class="outline-3">
|
|
<h3 id="org5ab38ae"><span class="section-number-3">3.2</span> \(\mathcal{H}_\infty\) Synthesis</h3>
|
|
<div class="outline-text-3" id="text-3-2">
|
|
<p>
|
|
<b>Optimization problem</b>:
|
|
\(\mathcal{H}_\infty\) synthesis is a method that uses an <b>algorithm</b> (LMI optimization, Riccati equation) to find a controller of the same order as the system so that the \(\mathcal{H}_\infty\) norms of defined transfer functions are minimized.
|
|
</p>
|
|
|
|
<p>
|
|
<b>Engineer work</b>:
|
|
</p>
|
|
<ol class="org-ol">
|
|
<li>Write the problem as standard \(\mathcal{H}_\infty\) problem</li>
|
|
<li>Translate the specifications as \(\mathcal{H}_\infty\) norms</li>
|
|
<li>Make the synthesis and analyze the obtain controller</li>
|
|
<li>Reduce the order of the controller for implementation</li>
|
|
</ol>
|
|
|
|
<p>
|
|
<b>Many ways to use the \(\mathcal{H}_\infty\) Synthesis</b>:
|
|
</p>
|
|
<ul class="org-ul">
|
|
<li>Traditional \(\mathcal{H}_\infty\) Synthesis</li>
|
|
<li>Mixed Sensitivity Loop Shaping</li>
|
|
<li>Fixed-Structure \(\mathcal{H}_\infty\) Synthesis</li>
|
|
<li>Signal Based \(\mathcal{H}_\infty\) Synthesis</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
|
|
<div id="outline-container-org3371822" class="outline-3">
|
|
<h3 id="org3371822"><span class="section-number-3">3.3</span> The Generalized Plant</h3>
|
|
<div class="outline-text-3" id="text-3-3">
|
|
|
|
<div id="org7392644" class="figure">
|
|
<p><img src="figs/general_plant.png" alt="general_plant.png" />
|
|
</p>
|
|
</div>
|
|
|
|
<table id="orgf7566b6" border="2" cellspacing="0" cellpadding="6" rules="groups" frame="hsides">
|
|
<caption class="t-above"><span class="table-number">Table 4:</span> Notations for the general configuration</caption>
|
|
|
|
<colgroup>
|
|
<col class="org-left" />
|
|
|
|
<col class="org-left" />
|
|
</colgroup>
|
|
<thead>
|
|
<tr>
|
|
<th scope="col" class="org-left">Notation</th>
|
|
<th scope="col" class="org-left">Meaning</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr>
|
|
<td class="org-left">\(P\)</td>
|
|
<td class="org-left">Generalized plant model</td>
|
|
</tr>
|
|
|
|
<tr>
|
|
<td class="org-left">\(w\)</td>
|
|
<td class="org-left">Exogenous inputs: commands, disturbances, noise</td>
|
|
</tr>
|
|
|
|
<tr>
|
|
<td class="org-left">\(z\)</td>
|
|
<td class="org-left">Exogenous outputs: signals to be minimized</td>
|
|
</tr>
|
|
|
|
<tr>
|
|
<td class="org-left">\(v\)</td>
|
|
<td class="org-left">Controller inputs: measurements</td>
|
|
</tr>
|
|
|
|
<tr>
|
|
<td class="org-left">\(u\)</td>
|
|
<td class="org-left">Control signals</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
|
|
\begin{equation}
|
|
\begin{bmatrix} z \\ v \end{bmatrix} = P \begin{bmatrix} w \\ u \end{bmatrix} = \begin{bmatrix} P_{11} & P_{12} \\ P_{21} & P_{22} \end{bmatrix} \begin{bmatrix} w \\ u \end{bmatrix}
|
|
\end{equation}
|
|
</div>
|
|
</div>
|
|
|
|
<div id="outline-container-orgbf413fb" class="outline-3">
|
|
<h3 id="orgbf413fb"><span class="section-number-3">3.4</span> From a Classical Feedback Architecture to a Generalized Plant</h3>
|
|
<div class="outline-text-3" id="text-3-4">
|
|
|
|
<div id="org6c156a7" class="figure">
|
|
<p><img src="figs/classical_feedback.png" alt="classical_feedback.png" />
|
|
</p>
|
|
<p><span class="figure-number">Figure 12: </span>Classical Feedback Architecture</p>
|
|
</div>
|
|
|
|
<table id="org2b76c2f" border="2" cellspacing="0" cellpadding="6" rules="groups" frame="hsides">
|
|
<caption class="t-above"><span class="table-number">Table 5:</span> Notations for the Classical Feedback Architecture</caption>
|
|
|
|
<colgroup>
|
|
<col class="org-left" />
|
|
|
|
<col class="org-left" />
|
|
</colgroup>
|
|
<thead>
|
|
<tr>
|
|
<th scope="col" class="org-left">Notation</th>
|
|
<th scope="col" class="org-left">Meaning</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr>
|
|
<td class="org-left">\(G\)</td>
|
|
<td class="org-left">Plant model</td>
|
|
</tr>
|
|
|
|
<tr>
|
|
<td class="org-left">\(K\)</td>
|
|
<td class="org-left">Controller</td>
|
|
</tr>
|
|
|
|
<tr>
|
|
<td class="org-left">\(r\)</td>
|
|
<td class="org-left">Reference inputs</td>
|
|
</tr>
|
|
|
|
<tr>
|
|
<td class="org-left">\(y\)</td>
|
|
<td class="org-left">Plant outputs</td>
|
|
</tr>
|
|
|
|
<tr>
|
|
<td class="org-left">\(u\)</td>
|
|
<td class="org-left">Control signals</td>
|
|
</tr>
|
|
|
|
<tr>
|
|
<td class="org-left">\(d\)</td>
|
|
<td class="org-left">Input Disturbance</td>
|
|
</tr>
|
|
|
|
<tr>
|
|
<td class="org-left">\(\epsilon\)</td>
|
|
<td class="org-left">Tracking Error</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
|
|
<p>
|
|
The procedure is:
|
|
</p>
|
|
<ol class="org-ol">
|
|
<li>define signals of the generalized plant</li>
|
|
<li>Remove \(K\) and rearrange the inputs and outputs</li>
|
|
</ol>
|
|
|
|
<div class="exercice" id="org205bea9">
|
|
<p>
|
|
Let’s find the Generalized plant of corresponding to the tracking control architecture shown in Figure <a href="#org506dd07">13</a>
|
|
</p>
|
|
|
|
|
|
<div id="org506dd07" class="figure">
|
|
<p><img src="figs/classical_feedback_tracking.png" alt="classical_feedback_tracking.png" />
|
|
</p>
|
|
<p><span class="figure-number">Figure 13: </span>Classical Feedback Control Architecture (Tracking)</p>
|
|
</div>
|
|
|
|
<p>
|
|
First, define the signals of the generalized plant:
|
|
</p>
|
|
<ul class="org-ul">
|
|
<li>Exogenous inputs: \(w = r\)</li>
|
|
<li>Signals to be minimized: \(z_1 = \epsilon\), \(z_2 = u\)</li>
|
|
<li>Control signals: \(v = y\)</li>
|
|
<li>Control inputs: \(u\)</li>
|
|
</ul>
|
|
|
|
<p>
|
|
Then, Remove \(K\) and rearrange the inputs and outputs.
|
|
We obtain the generalized plant shown in Figure <a href="#org08dc9a7">14</a>.
|
|
</p>
|
|
|
|
|
|
<div id="org08dc9a7" class="figure">
|
|
<p><img src="figs/mixed_sensitivity_ref_tracking.png" alt="mixed_sensitivity_ref_tracking.png" />
|
|
</p>
|
|
<p><span class="figure-number">Figure 14: </span>Generalized plant of the Classical Feedback Control Architecture (Tracking)</p>
|
|
</div>
|
|
|
|
<p>
|
|
Using Matlab, the generalized plant can be defined as follows:
|
|
</p>
|
|
<div class="org-src-container">
|
|
<pre class="src src-matlab">P = [1 <span class="org-type">-</span>G;
|
|
0 1;
|
|
1 <span class="org-type">-</span>G]
|
|
</pre>
|
|
</div>
|
|
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
|
|
<div id="outline-container-org5b0f8f6" class="outline-3">
|
|
<h3 id="org5b0f8f6"><span class="section-number-3">3.5</span> The General Synthesis Problem Formulation</h3>
|
|
<div class="outline-text-3" id="text-3-5">
|
|
<div class="important" id="org9695476">
|
|
<p>
|
|
The \(\mathcal{H}_\infty\) Synthesis objective is to find all stabilizing controllers \(K\) which minimize
|
|
</p>
|
|
\begin{equation}
|
|
\| F_l(P, K) \|_\infty = \max_{\omega} \overline{\sigma} \big( F_l(P, K)(j\omega) \big)
|
|
\end{equation}
|
|
|
|
</div>
|
|
|
|
|
|
<div id="org8ea68ac" class="figure">
|
|
<p><img src="figs/general_control_names.png" alt="general_control_names.png" />
|
|
</p>
|
|
<p><span class="figure-number">Figure 15: </span>General Control Configuration</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
|
|
<div id="outline-container-org0a60e2d" class="outline-2">
|
|
<h2 id="org0a60e2d"><span class="section-number-2">4</span> Modern Interpretation of the Control Specifications</h2>
|
|
<div class="outline-text-2" id="text-4">
|
|
</div>
|
|
<div id="outline-container-orgeaf9df5" class="outline-3">
|
|
<h3 id="orgeaf9df5"><span class="section-number-3">4.1</span> Introduction</h3>
|
|
<div class="outline-text-3" id="text-4-1">
|
|
<ul class="org-ul">
|
|
<li><b>Reference tracking</b> Overshoot, Static error, Setling time
|
|
<ul class="org-ul">
|
|
<li>\(S(s) = T_{r \rightarrow \epsilon}\)</li>
|
|
</ul></li>
|
|
<li><b>Disturbances rejection</b>
|
|
<ul class="org-ul">
|
|
<li>\(G(s) S(s) = T_{d \rightarrow \epsilon}\)</li>
|
|
</ul></li>
|
|
<li><b>Measurement noise filtering</b>
|
|
<ul class="org-ul">
|
|
<li>\(T(s) = T_{n \rightarrow \epsilon}\)</li>
|
|
</ul></li>
|
|
<li><b>Small command amplitude</b>
|
|
<ul class="org-ul">
|
|
<li>\(K(s) S(s) = T_{r \rightarrow u}\)</li>
|
|
</ul></li>
|
|
<li><b>Stability</b>
|
|
<ul class="org-ul">
|
|
<li>\(S(s)\), \(T(s)\), \(K(s)S(s)\), \(G(s)S(s)\)</li>
|
|
</ul></li>
|
|
<li><b>Robustness to plant uncertainty</b> (stability margins)</li>
|
|
<li><b>Controller implementation</b></li>
|
|
</ul>
|
|
|
|
<p>
|
|
**
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div id="outline-container-org73188d9" class="outline-2">
|
|
<h2 id="org73188d9"><span class="section-number-2">5</span> Resources</h2>
|
|
<div class="outline-text-2" id="text-5">
|
|
<p>
|
|
<div class="yt"><iframe width="100%" height="100%" src="https://www.youtube.com/embed/?listType=playlist&list=PLn8PRpmsu08qFLMfgTEzR8DxOPE7fBiin" frameborder="0" allowfullscreen></iframe></div>
|
|
</p>
|
|
|
|
<p>
|
|
<div class="yt"><iframe width="100%" height="100%" src="https://www.youtube.com/embed/?listType=playlist&list=PLsjPUqcL7ZIFHCObUU_9xPUImZ203gB4o" frameborder="0" allowfullscreen></iframe></div>
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div id="postamble" class="status">
|
|
<p class="author">Author: Dehaeze Thomas</p>
|
|
<p class="date">Created: 2020-11-27 ven. 23:12</p>
|
|
</div>
|
|
</body>
|
|
</html>
|