|
180 | 180 | ├ 1 measured outputs ym (0 integrating states) |
181 | 181 | ├ 0 unmeasured outputs yu |
182 | 182 | └ 0 measured disturbances d</code></pre><p>does slightly improve the rejection of the step disturbance:</p><pre><code class="language-julia hljs">res_lin2 = sim!(mpc2, N, [180.0]; plant, x_0=[π, 0], y_step=[10]) |
183 | | -plot(res_lin2)</code></pre><p><img src="../plot10_NonLinMPC.svg" alt="plot10_NonLinMPC"/></p><p>The closed-loop performance is still lower than the nonlinear controller, as expected, but computations are about 210 times faster (0.000071 s versus 0.015 s per time steps, on average). However, remember that <code>linmodel</code> is only valid for angular positions near 180°. For example, the 180° setpoint response from 0° is unsatisfactory since the predictions are poor in the first quadrant:</p><pre><code class="language-julia hljs">res_lin3 = sim!(mpc2, N, [180.0]; plant, x_0=[0, 0]) |
| 183 | +plot(res_lin2)</code></pre><p><img src="../plot10_NonLinMPC.svg" alt="plot10_NonLinMPC"/></p><p>Additionally, similar results are obtained by using a sparse <a href="../../public/predictive_control/#MultipleShooting"><code>MultipleShooting</code></a> transcription, which is known to be more robust for unstable systems, with a solver that can explicilty handle sparsity like the default <code>OSQP</code>:</p><pre><code class="language-julia hljs">mpc_ms = LinMPC(skf; Hp, Hc, Mwt, Nwt, Cwt=Inf, transcription=MultipleShooting()) |
| 184 | +mpc_ms = setconstraint!(mpc_ms, umin=[-1.5], umax=[+1.5])</code></pre><pre class="documenter-example-output"><code class="nohighlight hljs ansi">LinMPC controller with a sample time Ts = 0.1 s: |
| 185 | +├ estimator: SteadyKalmanFilter |
| 186 | +├ model: LinModel |
| 187 | +├ optimizer: OSQP |
| 188 | +├ transcription: MultipleShooting |
| 189 | +└ dimensions: |
| 190 | + ├ 20 prediction steps Hp |
| 191 | + ├ 2 control steps Hc |
| 192 | + ├ 0 slack variable ϵ (control constraints) |
| 193 | + ├ 1 manipulated inputs u (1 integrating states) |
| 194 | + ├ 3 estimated states x̂ |
| 195 | + ├ 1 measured outputs ym (0 integrating states) |
| 196 | + ├ 0 unmeasured outputs yu |
| 197 | + └ 0 measured disturbances d</code></pre><p>Superimposing the previous disturbance rejection plot shows almost identical results:</p><pre><code class="language-julia hljs">res_ms = sim!(mpc_ms, N, [180.0]; plant, x_0=[π, 0], y_step=[10]) |
| 198 | +plot!(res_ms)</code></pre><p><img src="../plot10b_NonLinMPC.svg" alt="plot10b_NonLinMPC"/></p><p>The closed-loop performances are still lower than the nonlinear controller, as expected, but computations are about 210 times faster (0.000071 s versus 0.015 s per time steps, on average). However, remember that <code>linmodel</code> is only valid for angular positions near 180°. For example, the 180° setpoint response from 0° is unsatisfactory since the predictions are poor in the first quadrant:</p><pre><code class="language-julia hljs">res_lin3 = sim!(mpc2, N, [180.0]; plant, x_0=[0, 0]) |
184 | 199 | plot(res_lin3)</code></pre><p><img src="../plot11_NonLinMPC.svg" alt="plot11_NonLinMPC"/></p><p>Multiple linearized model and controller objects are required for large deviations from this operating point. This is known as gain scheduling. Another approach is adapting the model of the <a href="../../public/predictive_control/#LinMPC"><code>LinMPC</code></a> instance based on repeated online linearization.</p><h2 id="Adapting-the-Model-via-Successive-Linearization"><a class="docs-heading-anchor" href="#Adapting-the-Model-via-Successive-Linearization">Adapting the Model via Successive Linearization</a><a id="Adapting-the-Model-via-Successive-Linearization-1"></a><a class="docs-heading-anchor-permalink" href="#Adapting-the-Model-via-Successive-Linearization" title="Permalink"></a></h2><p>The <a href="../../public/generic_func/#ModelPredictiveControl.setmodel!"><code>setmodel!</code></a> method allows online adaptation of a linear plant model. Combined with the automatic linearization of <a href="../../public/sim_model/#ModelPredictiveControl.linearize"><code>linearize</code></a>, a successive linearization MPC can be designed with minimal efforts. The <a href="../../public/state_estim/#SteadyKalmanFilter"><code>SteadyKalmanFilter</code></a> does not support <a href="../../public/generic_func/#ModelPredictiveControl.setmodel!"><code>setmodel!</code></a> so we need to use the time-varying <a href="../../public/state_estim/#KalmanFilter"><code>KalmanFilter</code></a>, and we initialize it with a linearization at <span>$θ = ω = τ = 0$</span>:</p><pre><code class="language-julia hljs">linmodel = linearize(model, x=[0, 0], u=[0]) |
185 | 200 | kf = KalmanFilter(linmodel; σQ, σR, nint_u, σQint_u) |
186 | 201 | mpc3 = LinMPC(kf; Hp, Hc, Mwt, Nwt, Cwt=Inf, optim=daqp) |
|
218 | 233 | res_slin = sim_adapt!(mpc3, model, N, ry, plant, x_0, x̂_0) |
219 | 234 | plot(res_slin)</code></pre><p><img src="../plot12_NonLinMPC.svg" alt="plot12_NonLinMPC"/></p><p>and the 10° step disturbance:</p><pre><code class="language-julia hljs">x_0 = [π, 0]; x̂_0 = [π, 0, 0]; y_step = [10] |
220 | 235 | res_slin = sim_adapt!(mpc3, model, N, ry, plant, x_0, x̂_0, y_step) |
221 | | -plot(res_slin)</code></pre><p><img src="../plot13_NonLinMPC.svg" alt="plot13_NonLinMPC"/></p><p>The computations of the successive linearization MPC are about 75 times faster than the nonlinear MPC on average, an impressive gain for similar closed-loop performances!</p><section class="footnotes is-size-7"><ul><li class="footnote" id="footnote-1"><a class="tag is-link" href="#citeref-1">1</a>Arnström, D., Bemporad, A., and Axehill, D. (2022). A dual active-set solver for embedded quadratic programming using recursive LDLᵀ updates. IEEE Trans. Autom. Contr., 67(8). <a href="https://doi.org/doi:10.1109/TAC.2022.3176430">https://doi.org/doi:10.1109/TAC.2022.3176430</a>.</li></ul></section></article><nav class="docs-footer"><a class="docs-footer-prevpage" href="../linmpc/">« Linear Design</a><a class="docs-footer-nextpage" href="../mtk/">ModelingToolkit »</a><div class="flexbox-break"></div><p class="footer-message">Powered by <a href="https://github.com/JuliaDocs/Documenter.jl">Documenter.jl</a> and the <a href="https://julialang.org/">Julia Programming Language</a>.</p></nav></div><div class="modal" id="documenter-settings"><div class="modal-background"></div><div class="modal-card"><header class="modal-card-head"><p class="modal-card-title">Settings</p><button class="delete"></button></header><section class="modal-card-body"><p><label class="label">Theme</label><div class="select"><select id="documenter-themepicker"><option value="auto">Automatic (OS)</option><option value="documenter-light">documenter-light</option><option value="documenter-dark">documenter-dark</option><option value="catppuccin-latte">catppuccin-latte</option><option value="catppuccin-frappe">catppuccin-frappe</option><option value="catppuccin-macchiato">catppuccin-macchiato</option><option value="catppuccin-mocha">catppuccin-mocha</option></select></div></p><hr/><p>This document was generated with <a href="https://github.com/JuliaDocs/Documenter.jl">Documenter.jl</a> version 1.14.1 on <span class="colophon-date" title="Sunday 7 September 2025 21:22">Sunday 7 September 2025</span>. Using Julia version 1.11.6.</p></section><footer class="modal-card-foot"></footer></div></div></div></body></html> |
| 236 | +plot(res_slin)</code></pre><p><img src="../plot13_NonLinMPC.svg" alt="plot13_NonLinMPC"/></p><p>The computations of the successive linearization MPC are about 75 times faster than the nonlinear MPC on average, an impressive gain for similar closed-loop performances!</p><section class="footnotes is-size-7"><ul><li class="footnote" id="footnote-1"><a class="tag is-link" href="#citeref-1">1</a>Arnström, D., Bemporad, A., and Axehill, D. (2022). A dual active-set solver for embedded quadratic programming using recursive LDLᵀ updates. IEEE Trans. Autom. Contr., 67(8). <a href="https://doi.org/doi:10.1109/TAC.2022.3176430">https://doi.org/doi:10.1109/TAC.2022.3176430</a>.</li></ul></section></article><nav class="docs-footer"><a class="docs-footer-prevpage" href="../linmpc/">« Linear Design</a><a class="docs-footer-nextpage" href="../mtk/">ModelingToolkit »</a><div class="flexbox-break"></div><p class="footer-message">Powered by <a href="https://github.com/JuliaDocs/Documenter.jl">Documenter.jl</a> and the <a href="https://julialang.org/">Julia Programming Language</a>.</p></nav></div><div class="modal" id="documenter-settings"><div class="modal-background"></div><div class="modal-card"><header class="modal-card-head"><p class="modal-card-title">Settings</p><button class="delete"></button></header><section class="modal-card-body"><p><label class="label">Theme</label><div class="select"><select id="documenter-themepicker"><option value="auto">Automatic (OS)</option><option value="documenter-light">documenter-light</option><option value="documenter-dark">documenter-dark</option><option value="catppuccin-latte">catppuccin-latte</option><option value="catppuccin-frappe">catppuccin-frappe</option><option value="catppuccin-macchiato">catppuccin-macchiato</option><option value="catppuccin-mocha">catppuccin-mocha</option></select></div></p><hr/><p>This document was generated with <a href="https://github.com/JuliaDocs/Documenter.jl">Documenter.jl</a> version 1.14.1 on <span class="colophon-date" title="Monday 8 September 2025 17:51">Monday 8 September 2025</span>. Using Julia version 1.11.6.</p></section><footer class="modal-card-foot"></footer></div></div></div></body></html> |
0 commit comments