Skip to content

Commit 3aff2fd

Browse files
committed
debug: ExplicitMPC correct error message for setconstraint!
improve coverage ignore `lcov.info` file
1 parent 074ee54 commit 3aff2fd

File tree

9 files changed

+83
-20
lines changed

9 files changed

+83
-20
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,4 @@ LocalPreferences.toml
55
.vscode/
66
*.cov
77
docs/Manifest.toml
8+
lcov.info

Project.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
name = "ModelPredictiveControl"
22
uuid = "61f9bdb8-6ae4-484a-811f-bbf86720c31c"
33
authors = ["Francis Gagnon"]
4-
version = "0.24.1"
4+
version = "1.0.0"
55

66
[deps]
77
ControlSystemsBase = "aaaaaaaa-a6ca-5380-bf3e-84a91bcd477e"

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ using Pkg; Pkg.add("ModelPredictiveControl")
2424
To construct model predictive controllers (MPCs), we must first specify a plant model that
2525
is typically extracted from input-output data using [system identification](https://github.com/baggepinnen/ControlSystemIdentification.jl).
2626
The model here is linear with one input, two outputs and a large time delay in the first
27-
channel:
27+
channel (a transfer matrix, with $s$ as the Laplace variable):
2828

2929
```math
3030
\mathbf{G}(s) = \frac{\mathbf{y}(s)}{\mathbf{u}(s)} =

src/controller/explicitmpc.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,7 @@ function ExplicitMPC(
167167
return ExplicitMPC{NT, SE}(estim, Hp, Hc, M_Hp, N_Hc, L_Hp)
168168
end
169169

170-
setconstraint!(::ExplicitMPC,kwargs...) = error("ExplicitMPC does not support constraints.")
170+
setconstraint!(::ExplicitMPC; kwargs...) = error("ExplicitMPC does not support constraints.")
171171

172172
function Base.show(io::IO, mpc::ExplicitMPC)
173173
Hp, Hc = mpc.Hp, mpc.Hc

src/model/solver.jl

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@ struct RungeKutta <: DiffSolver
1616
if order 4
1717
throw(ArgumentError("only 4th order Runge-Kutta is supported."))
1818
end
19+
if order < 1
20+
throw(ArgumentError("order must be greater than 0"))
21+
end
1922
if supersample < 1
2023
throw(ArgumentError("supersample must be greater than 0"))
2124
end
@@ -31,15 +34,7 @@ Create a Runge-Kutta solver with optional super-sampling.
3134
Only the 4th order Runge-Kutta is supported for now. The keyword argument `supersample`
3235
provides the number of internal steps (default to 1 step).
3336
"""
34-
function RungeKutta(order::Int=4; supersample::Int=1)
35-
if order < 1
36-
throw(ArgumentError("order must be greater than 0"))
37-
end
38-
if supersample < 1
39-
throw(ArgumentError("supersample must be greater than 0"))
40-
end
41-
return RungeKutta(order, supersample)
42-
end
37+
RungeKutta(order::Int=4; supersample::Int=1) = RungeKutta(order, supersample)
4338

4439
"Get the `f!` and `h!` functions for Runge-Kutta solver."
4540
function get_solver_functions(NT::DataType, solver::RungeKutta, fc!, hc!, Ts, _ , nx, _ , _ )

src/sim_model.jl

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -141,19 +141,19 @@ LinModel with a sample time Ts = 2.0 s and:
141141
"""
142142
function setname!(model::SimModel; u=nothing, y=nothing, d=nothing, x=nothing)
143143
if !isnothing(u)
144-
size(u) == (model.nu,) || error("u size must be $((model.nu,))")
144+
size(u) == (model.nu,) || throw(DimensionMismatch("u size must be $((model.nu,))"))
145145
model.uname .= u
146146
end
147147
if !isnothing(y)
148-
size(y) == (model.ny,) || error("y size must be $((model.ny,))")
148+
size(y) == (model.ny,) || throw(DimensionMismatch("y size must be $((model.ny,))"))
149149
model.yname .= y
150150
end
151151
if !isnothing(d)
152-
size(d) == (model.nd,) || error("d size must be $((model.nd,))")
152+
size(d) == (model.nd,) || throw(DimensionMismatch("d size must be $((model.nd,))"))
153153
model.dname .= d
154154
end
155155
if !isnothing(x)
156-
size(x) == (model.nx,) || error("x size must be $((model.nx,))")
156+
size(x) == (model.nx,) || throw(DimensionMismatch("x size must be $((model.nx,))"))
157157
model.xname .= x
158158
end
159159
return model

test/test_plot_sim.jl

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,18 @@ end
110110
@test all(p5[end-4][2][:y] .≈ +101)
111111
@test all(p5[end-3][2][:y] .≈ +102)
112112
@test all(p5[end-2][2][:y] .≈ +103)
113+
p6 = plot(res, plotxwithx̂=true, plotx̂min=true, plotx̂max=false)
114+
@test p6[1][1][:x] res.T_data
115+
@test all(p6[end-5][3][:y] .≈ -100)
116+
@test all(p6[end-4][3][:y] .≈ -101)
117+
@test all(p6[end-3][3][:y] .≈ -102)
118+
@test all(p6[end-2][3][:y] .≈ -103)
119+
p7 = plot(res, plotxwithx̂=true, plotx̂min=false, plotx̂max=true)
120+
@test p7[1][1][:x] res.T_data
121+
@test all(p7[end-5][3][:y] .≈ +100)
122+
@test all(p7[end-4][3][:y] .≈ +101)
123+
@test all(p7[end-3][3][:y] .≈ +102)
124+
@test all(p7[end-2][3][:y] .≈ +103)
113125
end
114126

115127
@testset "PredictiveController quick simulation" begin
@@ -147,7 +159,10 @@ end
147159
end
148160

149161
@testset "PredictiveController Plots" begin
150-
mpc = LinMPC(LinModel(sys, Ts, i_d=[3]), Lwt=[0.01, 0.01])
162+
estim = MovingHorizonEstimator(LinModel(sys, Ts, i_d=[3]), He=5)
163+
estim = setconstraint!(estim, x̂min=[-100,-101,-102,-103,-104,-105])
164+
estim = setconstraint!(estim, x̂max=[+100,+101,+102,+103,+104,+105])
165+
mpc = LinMPC(estim, Lwt=[0.01, 0.01])
151166
mpc = setconstraint!(mpc, umin=[-50, -51], umax=[52, 53], ymin=[-54,-55], ymax=[56,57])
152167
res = sim!(mpc, 15)
153168
p1 = plot(res, plotŷ=true)
@@ -198,4 +213,36 @@ end
198213
@test p8[1][1][:x] res.T_data
199214
@test all(p8[end-4][3][:y] .≈ 56.0)
200215
@test all(p8[end-3][3][:y] .≈ 57.0)
216+
p9 = plot(res, plotx̂=true, plotx̂min=true, plotx̂max=false)
217+
@test p9[1][1][:x] res.T_data
218+
@test all(p9[end-5][2][:y] .≈ -100.0)
219+
@test all(p9[end-4][2][:y] .≈ -101.0)
220+
@test all(p9[end-3][2][:y] .≈ -102.0)
221+
@test all(p9[end-2][2][:y] .≈ -103.0)
222+
@test all(p9[end-1][2][:y] .≈ -104.0)
223+
@test all(p9[end-0][2][:y] .≈ -105.0)
224+
p10 = plot(res, plotx̂=true, plotx̂min=false, plotx̂max=true)
225+
@test p10[1][1][:x] res.T_data
226+
@test all(p10[end-5][2][:y] .≈ +100.0)
227+
@test all(p10[end-4][2][:y] .≈ +101.0)
228+
@test all(p10[end-3][2][:y] .≈ +102.0)
229+
@test all(p10[end-2][2][:y] .≈ +103.0)
230+
@test all(p10[end-1][2][:y] .≈ +104.0)
231+
@test all(p10[end-0][2][:y] .≈ +105.0)
232+
p11 = plot(res, plotxwithx̂=true, plotx̂min=true, plotx̂max=false)
233+
@test p11[1][1][:x] res.T_data
234+
@test all(p11[end-5][3][:y] .≈ -100.0)
235+
@test all(p11[end-4][3][:y] .≈ -101.0)
236+
@test all(p11[end-3][3][:y] .≈ -102.0)
237+
@test all(p11[end-2][3][:y] .≈ -103.0)
238+
@test all(p11[end-1][2][:y] .≈ -104.0)
239+
@test all(p11[end-0][2][:y] .≈ -105.0)
240+
p12 = plot(res, plotxwithx̂=true, plotx̂min=false, plotx̂max=true)
241+
@test p12[1][1][:x] res.T_data
242+
@test all(p12[end-5][3][:y] .≈ +100.0)
243+
@test all(p12[end-4][3][:y] .≈ +101.0)
244+
@test all(p12[end-3][3][:y] .≈ +102.0)
245+
@test all(p12[end-2][3][:y] .≈ +103.0)
246+
@test all(p12[end-1][2][:y] .≈ +104.0)
247+
@test all(p12[end-0][2][:y] .≈ +105.0)
201248
end

test/test_predictive_control.jl

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,8 @@ end
134134
preparestate!(mpc1, [50, 30])
135135
updatestate!(mpc1, mpc1.estim.model.uop, [50, 30])
136136
@test mpc1.estim.x̂0 [0,0,0,0]
137-
preparestate!(mpc1, [50, 30])
137+
# do not call preparestate! before moveinput! for the warning:
138+
moveinput!(mpc1, [10, 50])
138139
@test_throws ArgumentError updatestate!(mpc1, [0,0])
139140
end
140141

@@ -348,6 +349,8 @@ end
348349
model2 = LinModel{Float32}(0.5*ones(1,1), ones(1,1), ones(1,1), zeros(1,0), zeros(1,0), 1.0)
349350
mpc13 = ExplicitMPC(model2)
350351
@test isa(mpc13, ExplicitMPC{Float32})
352+
353+
@test_throws ArgumentError LinMPC(model, Hp=0)
351354
end
352355

353356
@testset "ExplicitMPC moves and getinfo" begin

test/test_sim_model.jl

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,17 @@ Gss2 = c2d(sys_ss[:,1:2], 0.5Ts, :zoh)
7979
linmodel12 = LinModel{Float32}(Gss.A, Gss.B, Gss.C, zeros(2, 0), zeros(2, 0), Ts)
8080
@test isa(linmodel12, LinModel{Float32})
8181

82+
linmodel13 = LinModel(sys,Ts,i_d=[3])
83+
linmodel13 = setname!(linmodel13,
84+
u=["u_c", "u_h"],
85+
y=["y_L", "y_T"],
86+
d=["u_l"],
87+
x=["X_1", "X_2", "X_3", "X_4"]
88+
)
89+
@test all(linmodel13.uname .== ["u_c", "u_h"])
90+
@test all(linmodel13.yname .== ["y_L", "y_T"])
91+
@test all(linmodel13.dname .== ["u_l"])
92+
@test all(linmodel13.xname .== ["X_1", "X_2", "X_3", "X_4"])
8293

8394
@test_throws ErrorException LinModel(sys)
8495
@test_throws ErrorException LinModel(sys,-Ts)
@@ -101,7 +112,8 @@ end
101112
@test evaloutput(linmodel1, Float64[]) linmodel1(Float64[]) [50,30]
102113
x = initstate!(linmodel1, [10, 60])
103114
@test evaloutput(linmodel1) [50 + 19.0, 30 + 7.4]
104-
@test updatestate!(linmodel1, [10, 60]) x
115+
@test preparestate!(linmodel1, [10, 60]) x
116+
@test updatestate!(linmodel1, [10, 60]) x
105117
linmodel2 = LinModel(append(tf(1, [1, 0]), tf(2, [10, 1])), 1.0)
106118
x = initstate!(linmodel2, [10, 3])
107119
@test evaloutput(linmodel2) [0, 6]
@@ -188,13 +200,18 @@ end
188200
Dd = reshape([0], 1, 1)
189201
f3(x, u, d) = A*x + Bu*u+ Bd*d
190202
h3(x, d) = C*x + Dd*d
191-
nonlinmodel5 = NonLinModel(f3, h3, 1.0, 1, 2, 1, 1, solver=RungeKutta())
203+
solver=RungeKutta()
204+
@test string(solver) ==
205+
"4th order Runge-Kutta differential equation solver with 1 supersamples."
206+
nonlinmodel5 = NonLinModel(f3, h3, 1.0, 1, 2, 1, 1, solver=solver)
192207
xnext, y = similar(nonlinmodel5.x0), similar(nonlinmodel5.yop)
193208
nonlinmodel5.f!(xnext, [0; 0], [0], [0])
194209
@test xnext zeros(2)
195210
nonlinmodel5.h!(y, [0; 0], [0])
196211
@test y zeros(1)
197212

213+
214+
198215
function f2!(ẋ, x, u , d)
199216
mul!(ẋ, A, x)
200217
mul!(ẋ, Bu, u, 1, 1)

0 commit comments

Comments
 (0)