@@ -41,7 +41,7 @@ the following linear model accurately describes the plant dynamics:
4141We first need to construct a [ ` LinModel ` ] ( @ref ) objet with [ ` setop! ` ] ( @ref ) to handle the
4242operating points:
4343
44- ``` julia
44+ ``` @example 1
4545using ModelPredictiveControl, ControlSystemsBase
4646sys = [ tf(1.90, [18, 1]) tf(1.90, [18, 1]);
4747 tf(-0.74,[8, 1]) tf(0.74, [8, 1]) ]
@@ -65,7 +65,7 @@ y_L ≥ 45
6565We design our [ ` LinMPC ` ] ( @ref ) controllers by including the linear level constraint with
6666[ ` setconstraint! ` ] ( @ref ) (` ±Inf ` values should be used when there is no bound):
6767
68- ``` julia
68+ ``` @example 1
6969mpc = setconstraint!(LinMPC(model, Hp=15, Hc=2), ŷmin=[45, -Inf])
7070```
7171
@@ -83,7 +83,7 @@ measurements to ensure a bumpless transfer. Since `model` simulates our plant he
8383output will initialize the states. [ ` LinModel ` ] ( @ref ) objects are callable for this purpose
8484(an alias for [ ` evaloutput ` ] ( @ref ) ):
8585
86- ``` julia
86+ ``` @example 1
8787u = model.uop
8888y = model() # or equivalently : y = evaloutput(model)
8989initstate!(mpc, u, y)
@@ -93,7 +93,7 @@ nothing # hide
9393We can then close the loop and test ` mpc ` performance on the simulator by imposing step
9494changes on output setpoints `` \mathbf{r_y} `` and on a load disturbance `` \mathbf{u_d} `` :
9595
96- ``` julia
96+ ``` @example 1
9797function test_mpc(mpc, model)
9898 N = 200
9999 ry, ud = [50, 30], [0, 0]
@@ -103,15 +103,14 @@ function test_mpc(mpc, model)
103103 for k = 0:N-1
104104 y = model() # simulated measurements
105105 k == 50 && (ry = [50, 35])
106- k == 100 && (ry = [55 , 30 ])
107- k == 150 && (ud = [- 25 , 0 ])
106+ k == 100 && (ry = [54 , 30])
107+ k == 150 && (ud = [0, -20 ])
108108 u = mpc(ry) # or equivalently : u = moveinput!(mpc, ry)
109109 u_data[:,k+1] = u
110110 y_data[:,k+1] = y
111111 ry_data[:,k+1] = ry
112112 updatestate!(mpc, u, y) # update mpc state estimate
113113 updatestate!(model, u + ud) # update simulator with disturbance
114- println (getinfo (mpc)[2 ][:Ŷs ])
115114 end
116115 return u_data, y_data, ry_data
117116end
@@ -128,7 +127,7 @@ end of the `for` loop. The same logic applies for `model`.
128127
129128Lastly, we plot the closed-loop test with the ` Plots ` package:
130129
131- ``` julia
130+ ``` @example 1
132131using Plots
133132function plot_data(t_data, u_data, y_data, ry_data)
134133 p1 = plot(t_data, y_data[1,:], label="meas."); ylabel!("level")
@@ -151,21 +150,23 @@ using Pkg; Pkg.add("DAQP")
151150```
152151
153152Also, compared to the default setting, adding the integrating states at the model inputs may
154- improve the closed-loop performance. Load disturbances are indeed very frequent in real-life
155- control problems. Constructing a [ ` LinMPC ` ] ( @ref ) with ` DAQP ` and input integrators:
153+ improve the closed-loop performance. Load disturbances are indeed very frequent in many
154+ real-life control problems. Constructing a [ ` LinMPC ` ] ( @ref ) with ` DAQP ` and input integrators:
156155
157- ``` julia
156+ ``` @example 1
158157using JuMP, DAQP
159158daqp = Model(DAQP.Optimizer)
160159estim = SteadyKalmanFilter(model, nint_u=[1, 1])
161160mpc2 = setconstraint!(LinMPC(estim, Hp=15, Hc=2, optim=daqp), ŷmin=[45, -Inf])
162161```
163162
164- leads to identical results here:
163+ leads to similar computational times, but it does accelerate the rejection of the load
164+ disturbance and eliminates the level constraint violation:
165165
166- ``` julia
166+ ``` @example 1
167167setstate!(model, zeros(model.nx))
168168initstate!(mpc2, model.uop, model())
169169u_data2, y_data2, ry_data2 = test_mpc(mpc2, model)
170170plot_data(t_data, u_data2, y_data2, ry_data2)
171171```
172+
0 commit comments