Skip to content

Commit 40d1251

Browse files
committed
Merge branch 'main' into multiple_shooting
2 parents c18cf3b + 0ca6f85 commit 40d1251

File tree

9 files changed

+206
-153
lines changed

9 files changed

+206
-153
lines changed

Project.toml

Lines changed: 4 additions & 2 deletions
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 = "1.3.1"
4+
version = "1.3.2"
55

66
[deps]
77
ControlSystemsBase = "aaaaaaaa-a6ca-5380-bf3e-84a91bcd477e"
@@ -28,13 +28,15 @@ PrecompileTools = "1"
2828
ProgressLogging = "0.1"
2929
Random = "1.6"
3030
RecipesBase = "1"
31+
TestItemRunner = "1.1"
3132
julia = "1.10"
3233

3334
[extras]
3435
DAQP = "c47d62df-3981-49c8-9651-128b1cd08617"
3536
Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4"
3637
Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80"
3738
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
39+
TestItemRunner = "f8b46487-2199-4994-9208-9a1283c18c0a"
3840

3941
[targets]
40-
test = ["Test", "Documenter", "Plots", "DAQP"]
42+
test = ["Test", "TestItemRunner", "Documenter", "Plots", "DAQP"]

src/controller/execute.jl

Lines changed: 12 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -126,10 +126,7 @@ function getinfo(mpc::PredictiveController{NT}) where NT<:Real
126126
U, Ŷ = Ū, Ȳ
127127
U .= mul!(U, mpc.S̃, mpc.ΔŨ) .+ mpc.T_lastu
128128
Ŷ .= Ŷ0 .+ mpc.Yop
129-
oldF = copy(mpc.F)
130-
F = predictstoch!(mpc, mpc.estim)
131-
Ŷs .= F # predictstoch! init mpc.F with Ŷs value if estim is an InternalModel
132-
F .= oldF # restore old F value
129+
predictstoch!(Ŷs, mpc, mpc.estim)
133130
info[:ΔU] = mpc.ΔŨ[1:mpc.Hc*model.nu]
134131
info[] = mpc.== 1 ? mpc.ΔŨ[end] : zero(NT)
135132
info[:J] = J
@@ -230,7 +227,7 @@ function initpred!(mpc::PredictiveController, model::SimModel, d, D̂, R̂y, R̂
230227
end
231228

232229
"""
233-
initpred_common!(mpc::PredictiveController, model::SimModel, d, D̂, R̂y, R̂u) -> F
230+
initpred_common!(mpc::PredictiveController, model::SimModel, d, D̂, R̂y, R̂u) -> mpc.F
234231
235232
Common computations of `initpred!` for all types of [`SimModel`](@ref).
236233
@@ -250,23 +247,22 @@ function initpred_common!(mpc::PredictiveController, model::SimModel, d, D̂, R
250247
end
251248
mpc.R̂y .= R̂y
252249
mpc.R̂u .= R̂u
253-
F = predictstoch!(mpc, mpc.estim) # init mpc.F with Ŷs for InternalModel
254-
return F
250+
predictstoch!(mpc.F, mpc, mpc.estim)
251+
return mpc.F
255252
end
256253

257254
@doc raw"""
258-
predictstoch!(mpc::PredictiveController, estim::InternalModel) -> F
255+
predictstoch!(Ŷs, mpc::PredictiveController, estim::InternalModel) -> nothing
259256
260-
Init `mpc.F` vector with ``\mathbf{F = Ŷ_s}`` when `estim` is an [`InternalModel`](@ref).
257+
Fill `Ŷs` in-place with stochastic predictions if `estim` is an [`InternalModel`](@ref).
261258
"""
262-
function predictstoch!(mpc::PredictiveController, estim::InternalModel)
263-
Ŷs = mpc.F
259+
function predictstoch!(Ŷs, mpc::PredictiveController, estim::InternalModel)
264260
mul!(Ŷs, mpc.Ks, estim.x̂s)
265261
mul!(Ŷs, mpc.Ps, estim.ŷs, 1, 1)
266-
return mpc.F
262+
return nothing
267263
end
268-
"Separate stochastic predictions are not needed if `estim` is not [`InternalModel`](@ref)."
269-
predictstoch!(mpc::PredictiveController, ::StateEstimator) = (mpc.F .= 0)
264+
"Fill `Ŷs` vector with 0 values when `estim` is not an [`InternalModel`](@ref)."
265+
predictstoch!(Ŷs, mpc::PredictiveController, ::StateEstimator) = (Ŷs .= 0; nothing)
270266

271267
@doc raw"""
272268
linconstraint!(mpc::PredictiveController, model::LinModel)
@@ -588,11 +584,11 @@ Call `savetime!(mpc.estim.model)` and return the time `t`.
588584
savetime!(mpc::PredictiveController) = savetime!(mpc.estim.model)
589585

590586
"""
591-
periodsleep(mpc::PredictiveController) -> nothing
587+
periodsleep(mpc::PredictiveController, busywait=false) -> nothing
592588
593589
Call `periodsleep(mpc.estim.model)`.
594590
"""
595-
periodsleep(mpc::PredictiveController) = periodsleep(mpc.estim.model)
591+
periodsleep(mpc::PredictiveController, busywait=false) = periodsleep(mpc.estim.model, busywait)
596592

597593
"""
598594
setstate!(mpc::PredictiveController, x̂) -> mpc

src/estimator/execute.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -291,11 +291,11 @@ Call `savetime!(estim.model)` and return the time `t`.
291291
savetime!(estim::StateEstimator) = savetime!(estim.model)
292292

293293
"""
294-
periodsleep(estim::StateEstimator) -> nothing
294+
periodsleep(estim::StateEstimator, busywait=false) -> nothing
295295
296296
Call `periodsleep(estim.model)`.
297297
"""
298-
periodsleep(estim::StateEstimator) = periodsleep(estim.model)
298+
periodsleep(estim::StateEstimator, busywait=false) = periodsleep(estim.model, busywait)
299299

300300

301301
"""

test/0_test_module.jl

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
@testmodule SetupMPCtests begin
2+
using ControlSystemsBase
3+
Ts = 400.0
4+
sys = [ tf(1.90,[1800.0,1]) tf(1.90,[1800.0,1]) tf(1.90,[1800.0,1]);
5+
tf(-0.74,[800.0,1]) tf(0.74,[800.0,1]) tf(-0.74,[800.0,1]) ]
6+
sys_ss = minreal(ss(sys))
7+
Gss = c2d(sys_ss[:,1:2], Ts, :zoh)
8+
Gss2 = c2d(sys_ss[:,1:2], 0.5Ts, :zoh)
9+
export Ts, sys, sys_ss, Gss, Gss2
10+
end

test/test_sim_model.jl renamed to test/1_test_sim_model.jl

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,5 @@
1-
Ts = 4.0
2-
sys = [ tf(1.90,[18.0,1]) tf(1.90,[18.0,1]) tf(1.90,[18.0,1]);
3-
tf(-0.74,[8.0,1]) tf(0.74,[8.0,1]) tf(-0.74,[8.0,1]) ]
4-
sys_ss = minreal(ss(sys))
5-
Gss = c2d(sys_ss[:,1:2], Ts, :zoh)
6-
Gss2 = c2d(sys_ss[:,1:2], 0.5Ts, :zoh)
7-
8-
@testset "LinModel construction" begin
1+
@testitem "LinModel construction" setup=[SetupMPCtests] begin
2+
using .SetupMPCtests, ControlSystemsBase, LinearAlgebra
93
linmodel1 = LinModel(sys, Ts, i_u=1:2)
104
@test linmodel1.nx == 2
115
@test linmodel1.nu == 2
@@ -29,7 +23,7 @@ Gss2 = c2d(sys_ss[:,1:2], 0.5Ts, :zoh)
2923
@test linmodel2.dop zeros(0,1)
3024

3125
linmodel3 = LinModel(Gss, 0.5Ts)
32-
@test linmodel3.Ts == 2.0
26+
@test linmodel3.Ts == 200.0
3327
@test linmodel3.A Gss2.A
3428
@test linmodel3.C Gss2.C
3529

@@ -55,7 +49,7 @@ Gss2 = c2d(sys_ss[:,1:2], 0.5Ts, :zoh)
5549
@test linmodel5.yop [50,30]
5650
@test linmodel5.dop [20]
5751

58-
linmodel6 = LinModel([delay(4) delay(4)]*sys,Ts,i_d=[3])
52+
linmodel6 = LinModel([delay(Ts) delay(Ts)]*sys,Ts,i_d=[3])
5953
@test linmodel6.nx == 3
6054
@test sum(eigvals(linmodel6.A) .≈ 0) == 1
6155

@@ -103,7 +97,8 @@ Gss2 = c2d(sys_ss[:,1:2], 0.5Ts, :zoh)
10397
@test_throws ErrorException LinModel(sys_ss,Ts)
10498
end
10599

106-
@testset "LinModel sim methods" begin
100+
@testitem "LinModel sim methods" setup=[SetupMPCtests] begin
101+
using .SetupMPCtests, ControlSystemsBase
107102
linmodel1 = setop!(LinModel(Gss), uop=[10,50], yop=[50,30])
108103
@test updatestate!(linmodel1, [10, 50]) zeros(2)
109104
@test updatestate!(linmodel1, [10, 50], Float64[]) zeros(2)
@@ -123,26 +118,28 @@ end
123118
@test_throws DimensionMismatch evaloutput(linmodel1, zeros(1))
124119
end
125120

126-
@testset "LinModel real time simulations" begin
127-
linmodel1 = LinModel(tf(2, [10, 1]), 0.1)
121+
@testitem "LinModel real time simulations" setup=[SetupMPCtests] begin
122+
using .SetupMPCtests, ControlSystemsBase, LinearAlgebra
123+
linmodel1 = LinModel(tf(2, [10, 1]), 0.25)
128124
times1 = zeros(5)
129125
for i=1:5
130126
times1[i] = savetime!(linmodel1)
131127
updatestate!(linmodel1, [1])
132128
periodsleep(linmodel1)
133129
end
134-
@test all(isapprox.(diff(times1[2:end]), 0.1, atol=0.01))
135-
linmodel2 = LinModel(tf(2, [0.1, 1]), 0.001)
130+
@test all(isapprox.(diff(times1[2:end]), 0.25, atol=0.01))
131+
linmodel2 = LinModel(tf(2, [0.1, 1]), 0.25)
136132
times2 = zeros(5)
137133
for i=1:5
138134
times2[i] = savetime!(linmodel2)
139135
updatestate!(linmodel2, [1])
140136
periodsleep(linmodel2, true)
141137
end
142-
@test all(isapprox.(diff(times2[2:end]), 0.001, atol=0.0001))
138+
@test all(isapprox.(diff(times2[2:end]), 0.25, atol=0.0001))
143139
end
144140

145-
@testset "NonLinModel construction" begin
141+
@testitem "NonLinModel construction" setup=[SetupMPCtests] begin
142+
using .SetupMPCtests, ControlSystemsBase, LinearAlgebra
146143
linmodel1 = LinModel(sys,Ts,i_u=[1,2])
147144
f1(x,u,_,model) = model.A*x + model.Bu*u
148145
h1(x,_,model) = model.C*x
@@ -249,7 +246,8 @@ end
249246
(x,_)->linmodel1.C*x, Ts, 2, 4, 2, 1, solver=nothing)
250247
end
251248

252-
@testset "NonLinModel sim methods" begin
249+
@testitem "NonLinModel sim methods" setup=[SetupMPCtests] begin
250+
using .SetupMPCtests, ControlSystemsBase, LinearAlgebra
253251
linmodel1 = LinModel(sys,Ts,i_u=[1,2])
254252
f1(x,u,_,model) = model.A*x + model.Bu*u
255253
h1(x,_,model) = model.C*x
@@ -268,7 +266,8 @@ end
268266
@test_throws DimensionMismatch evaloutput(nonlinmodel, zeros(1))
269267
end
270268

271-
@testset "NonLinModel linearization" begin
269+
@testitem "NonLinModel linearization" setup=[SetupMPCtests] begin
270+
using .SetupMPCtests, ControlSystemsBase, LinearAlgebra, ForwardDiff
272271
Ts = 1.0
273272
f1(x,u,d,_) = x.^5 + u.^4 + d.^3
274273
h1(x,d,_) = x.^2 + d
@@ -313,17 +312,18 @@ end
313312
linmodel3 = linearize(nonlinmodel3; x, u, d)
314313
for i=1:N
315314
ynl = nonlinmodel3(d)
316-
yl = linmodel3(d)
315+
global yl = linmodel3(d)
317316
Ynl[i] = ynl[1]
318317
Yl[i] = yl[1]
319-
linmodel3 = linearize(nonlinmodel3; u, d)
318+
global linmodel3 = linearize(nonlinmodel3; u, d)
320319
updatestate!(nonlinmodel3, u, d)
321320
updatestate!(linmodel3, u, d)
322321
end
323322
@test all(isapprox.(Ynl, Yl, atol=1e-6))
324323
end
325324

326-
@testset "NonLinModel real time simulations" begin
325+
@testitem "NonLinModel real time simulations" setup=[SetupMPCtests] begin
326+
using .SetupMPCtests, ControlSystemsBase, LinearAlgebra
327327
linmodel1 = LinModel(tf(2, [10, 1]), 0.1)
328328
nonlinmodel1 = NonLinModel(
329329
(x,u,_,_)->linmodel1.A*x + linmodel1.Bu*u,

0 commit comments

Comments
 (0)