Skip to content

Commit 407411d

Browse files
committed
test: NonLinMPC custom linear constraints violation
1 parent 4a95ae3 commit 407411d

File tree

3 files changed

+66
-37
lines changed

3 files changed

+66
-37
lines changed

src/controller/execute.jl

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,45 @@ end
303303
"Fill `Ŷs` vector with 0 values when `estim` is not an [`InternalModel`](@ref)."
304304
predictstoch!(Ŷs, mpc::PredictiveController, ::StateEstimator) = (Ŷs .= 0; nothing)
305305

306+
@doc raw"""
307+
linconstraint_custom!(mpc::PredictiveController, model::SimModel)
308+
309+
Init the ``\mathbf{F_w}`` vector for the custom linear inequality constraints.
310+
311+
See [`relaxW`](@ref) for the definition of the vector. The function does nothing if
312+
`mpc.con.nw < 1`.
313+
"""
314+
function linconstraint_custom!(mpc::PredictiveController, model::SimModel)
315+
mpc.con.nw < 1 && return nothing
316+
ny, nu, nd, buffer = model.ny, model.nu, model.nd, mpc.buffer
317+
Fw = mpc.con.Fw
318+
Ue_term, D̂e_term, R̂e_term = buffer.Ue, buffer.D̂e, buffer.Ŷe
319+
Fw .= 0
320+
Ue_term[1:end-nu] .= mpc.Tu_lastu0 .+ mpc.Uop
321+
Ue_term[end-nu+1:end] .= mpc.lastu0 .+ model.uop
322+
mul!(Fw, mpc.con.W̄u, Ue_term, 1, 1)
323+
if model.nd > 0
324+
D̂e_term[1:nd] .= mpc.d0 .+ model.dop
325+
D̂e_term[nd+1:end] .= mpc.D̂0 .+ mpc.Dop
326+
mul!(Fw, mpc.con.W̄d, D̂e_term, 1, 1)
327+
end
328+
R̂e_term[1:ny] .= mpc.ry
329+
R̂e_term[ny+1:end] .= mpc.R̂y
330+
mul!(Fw, mpc.con.W̄r, R̂e_term, 1, 1)
331+
return linconstraint_custom_outputs!(mpc, model)
332+
end
333+
334+
"Also include the `W̄y` term in the custom linear constraints for [`LinModel`](@ref)."
335+
function linconstraint_custom_outputs!(mpc::PredictiveController, model::LinModel)
336+
Ŷe_term, Fw, ny = mpc.buffer.Ŷe, mpc.con.Fw, model.ny
337+
Ŷe_term[1:ny] .= mpc.
338+
Ŷe_term[ny+1:end] .= mpc.F .+ mpc.Yop
339+
mul!(Fw, mpc.con.W̄y, Ŷe_term, 1, 1)
340+
return nothing
341+
end
342+
"Do nothing for other model types."
343+
linconstraint_custom_outputs!(::PredictiveController, ::SimModel) = nothing
344+
306345
"""
307346
extended_vectors!(Ue, Ŷe, mpc::PredictiveController, U0, Ŷ0) -> Ue, Ŷe
308347

src/controller/transcription.jl

Lines changed: 5 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -787,7 +787,7 @@ function linconstraint!(mpc::PredictiveController, model::LinModel, ::Transcript
787787
mul!(fx̂, mpc.con.gx̂, mpc.d0, 1, 1)
788788
mul!(fx̂, mpc.con.jx̂, mpc.D̂0, 1, 1)
789789
end
790-
mpc.con.nw > 0 && linconstraint_custom!(mpc, model)
790+
linconstraint_custom!(mpc, model)
791791
n = 0
792792
mpc.con.b[(n+1):(n+nU)] .= @. -mpc.con.U0min + mpc.Tu_lastu0
793793
n += nU
@@ -816,12 +816,12 @@ function linconstraint!(mpc::PredictiveController, model::LinModel, ::Transcript
816816
end
817817

818818
"Set `b` excluding predicted output constraints for `NonLinModel` and not `SingleShooting`."
819-
function linconstraint!(mpc::PredictiveController, ::NonLinModel, ::TranscriptionMethod)
819+
function linconstraint!(mpc::PredictiveController, model::NonLinModel, ::TranscriptionMethod)
820820
nU, nΔŨ = length(mpc.con.U0min), length(mpc.con.ΔŨmin)
821821
nW = length(mpc.con.Wmin)
822822
nx̂ = mpc.estim.nx̂
823823
# here, updating fx̂ is not necessary since fx̂ = 0
824-
mpc.con.nw > 0 && linconstraint_custom!(mpc, model)
824+
linconstraint_custom!(mpc, model)
825825
n = 0
826826
mpc.con.b[(n+1):(n+nU)] .= @. -mpc.con.U0min + mpc.Tu_lastu0
827827
n += nU
@@ -845,10 +845,10 @@ function linconstraint!(mpc::PredictiveController, ::NonLinModel, ::Transcriptio
845845
end
846846

847847
"Also exclude terminal constraints for `NonLinModel` and `SingleShooting`."
848-
function linconstraint!(mpc::PredictiveController, ::NonLinModel, ::SingleShooting)
848+
function linconstraint!(mpc::PredictiveController, model::NonLinModel, ::SingleShooting)
849849
nU, nΔŨ = length(mpc.con.U0min), length(mpc.con.ΔŨmin)
850850
nW = length(mpc.con.Wmin)
851-
mpc.con.nw > 0 && linconstraint_custom!(mpc, model)
851+
linconstraint_custom!(mpc, model)
852852
n = 0
853853
mpc.con.b[(n+1):(n+nU)] .= @. -mpc.con.U0min + mpc.Tu_lastu0
854854
n += nU
@@ -868,38 +868,6 @@ function linconstraint!(mpc::PredictiveController, ::NonLinModel, ::SingleShooti
868868
return nothing
869869
end
870870

871-
"Init the ``\\mathbf{F_w}`` vector for the linear model custom inequality constraints."
872-
function linconstraint_custom!(mpc::PredictiveController, model::SimModel)
873-
ny, nu, nd, buffer = model.ny, model.nu, model.nd, mpc.buffer
874-
Fw = mpc.con.Fw
875-
Ue_term, D̂e_term, R̂e_term = buffer.Ue, buffer.D̂e, buffer.Ŷe
876-
Fw .= 0
877-
Ue_term[1:end-nu] .= mpc.Tu_lastu0 .+ mpc.Uop
878-
Ue_term[end-nu+1:end] .= mpc.lastu0 .+ model.uop
879-
mul!(Fw, mpc.con.W̄u, Ue_term, 1, 1)
880-
if model.nd > 0
881-
D̂e_term[1:nd] .= mpc.d0 .+ model.dop
882-
D̂e_term[nd+1:end] .= mpc.D̂0 .+ mpc.Dop
883-
mul!(Fw, mpc.con.W̄d, D̂e_term, 1, 1)
884-
end
885-
R̂e_term[1:ny] .= mpc.ry
886-
R̂e_term[ny+1:end] .= mpc.R̂y
887-
mul!(Fw, mpc.con.W̄r, R̂e_term, 1, 1)
888-
return linconstraint_custom_outputs!(mpc, model)
889-
end
890-
891-
"Also include the `W̄y` term in the custom linear constraints for [`LinModel`](@ref)."
892-
function linconstraint_custom_outputs!(mpc::PredictiveController, model::LinModel)
893-
Ŷe_term, Fw, ny = mpc.buffer.Ŷe, mpc.con.Fw, model.ny
894-
Ŷe_term[1:ny] .= mpc.
895-
Ŷe_term[ny+1:end] .= mpc.F .+ mpc.Yop
896-
mul!(Fw, mpc.con.W̄y, Ŷe_term, 1, 1)
897-
return nothing
898-
end
899-
"Do nothing for other model types."
900-
linconstraint_custom_outputs!(::PredictiveController, ::SimModel) = nothing
901-
902-
903871
@doc raw"""
904872
linconstrainteq!(
905873
mpc::PredictiveController, model::LinModel, transcription::MultipleShooting

test/3_test_predictive_control.jl

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1523,6 +1523,28 @@ end
15231523
@test all(isapprox.(info[:Ŷ], 3.14; atol=1e-1))
15241524
@test all(isapprox.(info[:gc][Hp+1:end], 0.0; atol=1e-1))
15251525

1526+
linmodel2 = LinModel([tf([2], [2500, 1]) tf(0.1, [2000, 1])], 3000.0, i_d=[2])
1527+
f = (x,u,d,p) -> p.A*x + p.Bu*u + p.Bd*d
1528+
h = (x,d,p) -> p.C*x + p.Dd*d
1529+
nonlinmodel2 = NonLinModel(f, h, linmodel2.Ts, 1, 2, 1, 1, solver=nothing, p=linmodel2)
1530+
nonlinmodel2 = setop!(nonlinmodel2, uop=[25], dop=[30], yop=[50])
1531+
nmpc_wu = NonLinMPC(nonlinmodel2, Nwt=[0], Cwt=Inf, Hp=100, Hc=1, Wu=[1])
1532+
nmpc_wu = setconstraint!(nmpc_wu, wmax=[20])
1533+
preparestate!(nmpc_wu, [50], [30])
1534+
u = moveinput!(nmpc_wu, [100], [30])
1535+
@test all(isapprox.(getinfo(nmpc_wu)[:U], 20.0; atol=1e-1))
1536+
nmpc_wd = NonLinMPC(nonlinmodel2, Nwt=[0], Cwt=Inf, Hp=100, Hc=1, Wu=[1], Wd=[1])
1537+
nmpc_wd = setconstraint!(nmpc_wd, wmax=[45])
1538+
preparestate!(nmpc_wd, [50], [30])
1539+
u = moveinput!(nmpc_wd, [100], [30])
1540+
@test all(isapprox.(getinfo(nmpc_wd)[:U], 45-30; atol=1e-1))
1541+
nmpc_wr = NonLinMPC(nonlinmodel2, Nwt=[0], Cwt=Inf, Hp=100, Hc=1, Wu=[1], Wr=[1])
1542+
nmpc_wr = setconstraint!(nmpc_wr, wmax=[145])
1543+
preparestate!(nmpc_wr, [50], [30])
1544+
u = moveinput!(nmpc_wr, [100], [30])
1545+
@show getinfo(nmpc_wr)[:U]
1546+
@test all(isapprox.(getinfo(nmpc_wr)[:U], 145-100; atol=1e-1))
1547+
15261548
end
15271549

15281550
@testitem "NonLinMPC set model" setup=[SetupMPCtests] begin

0 commit comments

Comments
 (0)