Skip to content

Commit ff83e5d

Browse files
committed
move terminal constraint data to constraint struct
1 parent de951ae commit ff83e5d

File tree

5 files changed

+81
-64
lines changed

5 files changed

+81
-64
lines changed

docs/src/internals/predictive_control.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ ModelPredictiveControl.init_linconstraint
2525
ModelPredictiveControl.relaxU
2626
ModelPredictiveControl.relaxΔU
2727
ModelPredictiveControl.relaxŶ
28+
ModelPredictiveControl.relaxterminal
2829
```
2930

3031
## Predictions

src/controller/explicitmpc.jl

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,6 @@ struct ExplicitMPC{SE<:StateEstimator} <: PredictiveController
2020
J::Matrix{Float64}
2121
K::Matrix{Float64}
2222
V::Matrix{Float64}
23-
ẽx̂::Matrix{Float64}
24-
fx̂::Vector{Float64}
25-
gx̂::Matrix{Float64}
26-
jx̂::Matrix{Float64}
27-
kx̂::Matrix{Float64}
28-
vx̂::Matrix{Float64}
2923
::Hermitian{Float64, Matrix{Float64}}
3024
::Vector{Float64}
3125
p::Vector{Float64}
@@ -50,8 +44,8 @@ struct ExplicitMPC{SE<:StateEstimator} <: PredictiveController
5044
R̂y, R̂u = zeros(ny*Hp), zeros(nu*Hp) # dummy vals (updated just before optimization)
5145
noR̂u = iszero(L_Hp)
5246
S, T = init_ΔUtoU(nu, Hp, Hc)
53-
E, F, G, J, K, V, ex̂, fx̂, gx̂, jx̂, kx̂, vx̂ = init_predmat(estim, model, Hp, Hc)
54-
S̃, Ñ_Hc, Ẽ, ẽx̂ = S, N_Hc, E, ex̂ # no slack variable ϵ for ExplicitMPC
47+
E, F, G, J, K, V = init_predmat(estim, model, Hp, Hc)
48+
S̃, Ñ_Hc, Ẽ = S, N_Hc, E # no slack variable ϵ for ExplicitMPC
5549
P̃, q̃, p = init_quadprog(model, Ẽ, S̃, M_Hp, Ñ_Hc, L_Hp)
5650
P̃_chol = cholesky(P̃)
5751
Ks, Ps = init_stochpred(estim, Hp)
@@ -65,7 +59,7 @@ struct ExplicitMPC{SE<:StateEstimator} <: PredictiveController
6559
Hp, Hc,
6660
M_Hp, Ñ_Hc, L_Hp, Cwt, Ewt, R̂u, R̂y, noR̂u,
6761
S̃, T,
68-
Ẽ, F, G, J, K, V, ẽx̂, fx̂, gx̂, jx̂, kx̂, vx̂, P̃, q̃, p,
62+
Ẽ, F, G, J, K, V, P̃, q̃, p,
6963
P̃_chol,
7064
Ks, Ps,
7165
d0, D̂0,
@@ -191,6 +185,15 @@ function optim_objective!(mpc::ExplicitMPC)
191185
return lmul!(-1, ldiv!(mpc.ΔŨ, mpc.P̃_chol, mpc.q̃))
192186
end
193187

188+
"Compute the predictions but not the terminal states if `mpc` is an [`ExplicitMPC`](@ref)."
189+
function predict!(Ŷ, x̂, mpc::ExplicitMPC, ::LinModel, ΔŨ::Vector{T}) where {T<:Real}
190+
# in-place operations to reduce allocations :
191+
mul!(Ŷ, mpc.Ẽ, ΔŨ) + mpc.F
192+
x̂[:] .= NaN
193+
return Ŷ, x̂
194+
end
195+
196+
194197
"""
195198
addinfo!(info, mpc::ExplicitMPC) -> info
196199

src/controller/linmpc.jl

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,6 @@ struct LinMPC{SE<:StateEstimator} <: PredictiveController
2222
J::Matrix{Float64}
2323
K::Matrix{Float64}
2424
V::Matrix{Float64}
25-
ẽx̂::Matrix{Float64}
26-
fx̂::Vector{Float64}
27-
gx̂::Matrix{Float64}
28-
jx̂::Matrix{Float64}
29-
kx̂::Matrix{Float64}
30-
vx̂::Matrix{Float64}
3125
::Hermitian{Float64, Matrix{Float64}}
3226
::Vector{Float64}
3327
p::Vector{Float64}
@@ -51,7 +45,7 @@ struct LinMPC{SE<:StateEstimator} <: PredictiveController
5145
noR̂u = iszero(L_Hp)
5246
S, T = init_ΔUtoU(nu, Hp, Hc)
5347
E, F, G, J, K, V, ex̂, fx̂, gx̂, jx̂, kx̂, vx̂ = init_predmat(estim, model, Hp, Hc)
54-
con, S̃, Ñ_Hc, Ẽ, ẽx̂ = init_defaultcon(estim, Hp, Hc, C, S, N_Hc, E, ex̂)
48+
con, S̃, Ñ_Hc, Ẽ = init_defaultcon(estim, Hp, Hc, C, S, N_Hc, E, ex̂, fx̂, gx̂, jx̂, kx̂, vx̂)
5549
P̃, q̃, p = init_quadprog(model, Ẽ, S̃, M_Hp, Ñ_Hc, L_Hp)
5650
Ks, Ps = init_stochpred(estim, Hp)
5751
d0, D̂0 = zeros(nd), zeros(nd*Hp)
@@ -64,7 +58,7 @@ struct LinMPC{SE<:StateEstimator} <: PredictiveController
6458
Hp, Hc,
6559
M_Hp, Ñ_Hc, L_Hp, Cwt, Ewt, R̂u, R̂y, noR̂u,
6660
S̃, T,
67-
Ẽ, F, G, J, K, V, ẽx̂, fx̂, gx̂, jx̂, kx̂, vx̂, P̃, q̃, p,
61+
Ẽ, F, G, J, K, V, P̃, q̃, p,
6862
Ks, Ps,
6963
d0, D̂0,
7064
Ŷop, Dop,

src/controller/nonlinmpc.jl

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,6 @@ struct NonLinMPC{SE<:StateEstimator, JEfunc<:Function} <: PredictiveController
2525
J::Matrix{Float64}
2626
K::Matrix{Float64}
2727
V::Matrix{Float64}
28-
ẽx̂::Matrix{Float64}
29-
fx̂::Vector{Float64}
30-
gx̂::Matrix{Float64}
31-
jx̂::Matrix{Float64}
32-
kx̂::Matrix{Float64}
33-
vx̂::Matrix{Float64}
3428
::Hermitian{Float64, Matrix{Float64}}
3529
::Vector{Float64}
3630
p::Vector{Float64}
@@ -55,7 +49,7 @@ struct NonLinMPC{SE<:StateEstimator, JEfunc<:Function} <: PredictiveController
5549
noR̂u = iszero(L_Hp)
5650
S, T = init_ΔUtoU(nu, Hp, Hc)
5751
E, F, G, J, K, V, ex̂, fx̂, gx̂, jx̂, kx̂, vx̂ = init_predmat(estim, model, Hp, Hc)
58-
con, S̃, Ñ_Hc, Ẽ, ẽx̂ = init_defaultcon(estim, Hp, Hc, C, S, N_Hc, E, ex̂)
52+
con, S̃, Ñ_Hc, Ẽ = init_defaultcon(estim, Hp, Hc, C, S, N_Hc, E, ex̂, fx̂, gx̂, jx̂, kx̂, vx̂)
5953
P̃, q̃, p = init_quadprog(model, Ẽ, S̃, M_Hp, Ñ_Hc, L_Hp)
6054
Ks, Ps = init_stochpred(estim, Hp)
6155
d0, D̂0 = zeros(nd), zeros(nd*Hp)
@@ -68,7 +62,7 @@ struct NonLinMPC{SE<:StateEstimator, JEfunc<:Function} <: PredictiveController
6862
Hp, Hc,
6963
M_Hp, Ñ_Hc, L_Hp, Cwt, Ewt, JE, R̂u, R̂y, noR̂u,
7064
S̃, T,
71-
Ẽ, F, G, J, K, V, ẽx̂, fx̂, gx̂, jx̂, kx̂, vx̂, P̃, q̃, p,
65+
Ẽ, F, G, J, K, V, P̃, q̃, p,
7266
Ks, Ps,
7367
d0, D̂0,
7468
Ŷop, Dop,

src/predictive_control.jl

Lines changed: 64 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -38,29 +38,35 @@ const InfoDictType = Union{JuMP._SolutionSummary, Vector{Float64}, Float64}
3838

3939
"Include all the data for the constraints of [`PredictiveController`](@ref)"
4040
struct ControllerConstraint
41-
Umin ::Vector{Float64}
42-
Umax ::Vector{Float64}
43-
ΔŨmin ::Vector{Float64}
44-
ΔŨmax ::Vector{Float64}
45-
Ymin ::Vector{Float64}
46-
Ymax ::Vector{Float64}
47-
x̂min ::Vector{Float64}
48-
x̂max ::Vector{Float64}
49-
A_Umin ::Matrix{Float64}
50-
A_Umax ::Matrix{Float64}
51-
A_ΔŨmin::Matrix{Float64}
52-
A_ΔŨmax::Matrix{Float64}
53-
A_Ymin ::Matrix{Float64}
54-
A_Ymax ::Matrix{Float64}
55-
A_x̂min ::Matrix{Float64}
56-
A_x̂max ::Matrix{Float64}
57-
A ::Matrix{Float64}
58-
b ::Vector{Float64}
59-
i_b ::BitVector
60-
c_Ymin ::Vector{Float64}
61-
c_Ymax ::Vector{Float64}
62-
c_x̂min ::Vector{Float64}
63-
c_x̂max ::Vector{Float64}
41+
ẽx̂ ::Matrix{Float64}
42+
fx̂ ::Vector{Float64}
43+
gx̂ ::Matrix{Float64}
44+
jx̂ ::Matrix{Float64}
45+
kx̂ ::Matrix{Float64}
46+
vx̂ ::Matrix{Float64}
47+
Umin ::Vector{Float64}
48+
Umax ::Vector{Float64}
49+
ΔŨmin ::Vector{Float64}
50+
ΔŨmax ::Vector{Float64}
51+
Ymin ::Vector{Float64}
52+
Ymax ::Vector{Float64}
53+
x̂min ::Vector{Float64}
54+
x̂max ::Vector{Float64}
55+
A_Umin ::Matrix{Float64}
56+
A_Umax ::Matrix{Float64}
57+
A_ΔŨmin ::Matrix{Float64}
58+
A_ΔŨmax ::Matrix{Float64}
59+
A_Ymin ::Matrix{Float64}
60+
A_Ymax ::Matrix{Float64}
61+
A_x̂min ::Matrix{Float64}
62+
A_x̂max ::Matrix{Float64}
63+
A ::Matrix{Float64}
64+
b ::Vector{Float64}
65+
i_b ::BitVector
66+
c_Ymin ::Vector{Float64}
67+
c_Ymax ::Vector{Float64}
68+
c_x̂min ::Vector{Float64}
69+
c_x̂max ::Vector{Float64}
6470
end
6571

6672
@doc raw"""
@@ -198,7 +204,7 @@ function setconstraint!(
198204
model, con, optim = mpc.estim.model, mpc.con, mpc.optim
199205
nu, ny, nx̂, Hp, Hc = model.nu, model.ny, mpc.estim.nx̂, mpc.Hp, mpc.Hc
200206
notSolvedYet = (termination_status(optim) == OPTIMIZE_NOT_CALLED)
201-
C, E, ex̂ = mpc.C, mpc.Ẽ[:, 1:nu*Hc], mpc.ẽx̂[:, 1:nu*Hc]
207+
C, E, ex̂ = mpc.C, mpc.Ẽ[:, 1:nu*Hc], mpc.con.ẽx̂[:, 1:nu*Hc]
202208
isnothing(Umin) && !isnothing(umin) && (Umin = repeat(umin, Hp))
203209
isnothing(Umax) && !isnothing(umax) && (Umax = repeat(umax, Hp))
204210
isnothing(ΔUmin) && !isnothing(Δumin) && (ΔUmin = repeat(Δumin, Hc))
@@ -604,7 +610,7 @@ the terminal constraints applied on ``\mathbf{x̂}_{k-1}(k+H_p)``.
604610
function predict!(Ŷ, x̂, mpc::PredictiveController, ::LinModel, ΔŨ::Vector{T}) where {T<:Real}
605611
# in-place operations to reduce allocations :
606612
mul!(Ŷ, mpc.Ẽ, ΔŨ) + mpc.F
607-
mul!(x̂, mpc.ẽx̂, ΔŨ) + mpc.fx̂
613+
mul!(x̂, mpc.con.ẽx̂, ΔŨ) + mpc.con.fx̂
608614
end =
609615
return Ŷ, x̂end
610616
end
@@ -640,17 +646,19 @@ Set `b` vector for the linear model inequality constraints (``\mathbf{A ΔŨ
640646
Also init ``\mathbf{f_x̂}`` vector for the terminal constraints, see [`init_predmat`](@ref).
641647
"""
642648
function linconstraint!(mpc::PredictiveController, model::LinModel)
643-
mpc.fx̂[:] = mpc.kx̂ * mpc.estim.+ mpc.vx̂ * mpc.estim.lastu0
644-
mpc.fx̂[:] = model.nd 0 ? mpc.fx̂ + mpc.gx̂ * mpc.d0 + mpc.jx̂ * mpc.D̂0 : mpc.fx̂
649+
mpc.con.fx̂[:] = mpc.con.kx̂ * mpc.estim.+ mpc.con.vx̂ * mpc.estim.lastu0
650+
if model.nd 0
651+
mpc.con.fx̂[:] = mpc.con.fx̂ + mpc.con.gx̂ * mpc.d0 + mpc.con.jx̂ * mpc.D̂0
652+
end
645653
mpc.con.b[:] = [
646654
-mpc.con.Umin + mpc.T*(mpc.estim.lastu0 + model.uop)
647655
+mpc.con.Umax - mpc.T*(mpc.estim.lastu0 + model.uop)
648656
-mpc.con.ΔŨmin
649657
+mpc.con.ΔŨmax
650658
-mpc.con.Ymin + mpc.F
651659
+mpc.con.Ymax - mpc.F
652-
-mpc.con.x̂min + mpc.fx̂
653-
+mpc.con.x̂max - mpc.fx̂
660+
-mpc.con.x̂min + mpc.con.fx̂
661+
+mpc.con.x̂max - mpc.con.fx̂
654662
]
655663
lincon::LinConVector = mpc.optim[:linconstraint]
656664
set_normalized_rhs.(lincon, mpc.con.b[mpc.con.i_b])
@@ -961,13 +969,13 @@ function obj_nonlinprog(
961969
end
962970

963971
"""
964-
init_defaultcon(estim, C, S, N_Hc, E, ex̂) -> con, S̃, Ñ_Hc, Ẽ, ẽx̂
972+
init_defaultcon(estim, C, S, N_Hc, E, ex̂, fx̂, gx̂, jx̂, kx̂, vx̂) -> con, S̃, Ñ_Hc, Ẽ
965973
966974
Init `ControllerConstraint` struct with default parameters based on estimator `estim`.
967975
968-
Also return `S̃`, `Ñ_Hc`, `Ẽ` and ẽx̂ matrices for the the augmented decision vector `ΔŨ`.
976+
Also return `S̃`, `Ñ_Hc` and `Ẽ` matrices for the the augmented decision vector `ΔŨ`.
969977
"""
970-
function init_defaultcon(estim, Hp, Hc, C, S, N_Hc, E, ex̂)
978+
function init_defaultcon(estim, Hp, Hc, C, S, N_Hc, E, ex̂, fx̂, gx̂, jx̂, kx̂, vx̂)
971979
model = estim.model
972980
nu, ny, nx̂ = model.nu, model.ny, estim.nx̂
973981
umin, umax = fill(-Inf, nu), fill(+Inf, nu)
@@ -997,11 +1005,12 @@ function init_defaultcon(estim, Hp, Hc, C, S, N_Hc, E, ex̂)
9971005
)
9981006
b = zeros(size(A, 1)) # dummy b vector (updated just before optimization)
9991007
con = ControllerConstraint(
1000-
Umin , Umax , ΔŨmin , ΔŨmax , Ymin , Ymax, x̂min, x̂max,
1001-
A_Umin , A_Umax, A_ΔŨmin, A_ΔŨmax , A_Ymin, A_Ymax, A_x̂min, A_x̂max,
1002-
A , b , i_b , c_Ymin , c_Ymax, c_x̂min, c_x̂max,
1008+
ẽx̂ , fx̂ , gx̂ , jx̂ , kx̂ , vx̂ ,
1009+
Umin , Umax , ΔŨmin , ΔŨmax , Ymin , Ymax , x̂min , x̂max,
1010+
A_Umin , A_Umax, A_ΔŨmin, A_ΔŨmax , A_Ymin , A_Ymax , A_x̂min , A_x̂max,
1011+
A , b , i_b , c_Ymin , c_Ymax , c_x̂min , c_x̂max ,
10031012
)
1004-
return con, S̃, Ñ_Hc, Ẽ, ẽx̂
1013+
return con, S̃, Ñ_Hc, Ẽ
10051014
end
10061015

10071016
"Repeat predictive controller constraints over prediction `Hp` and control `Hc` horizons."
@@ -1126,10 +1135,26 @@ function relaxŶ(::SimModel, C, c_Ymin, c_Ymax, E)
11261135
return A_Ymin, A_Ymax, Ẽ
11271136
end
11281137

1129-
"""
1130-
relaxterminal(::LinModel, C, c_x̂min, c_x̂max, ex̂)
1138+
@doc raw"""
1139+
relaxterminal(::LinModel, C, c_x̂min, c_x̂max, ex̂) -> A_x̂min, A_x̂max, ẽx̂
11311140
1132-
TBW
1141+
Augment terminal state constraints with slack variable ϵ for softening.
1142+
1143+
Denoting the input increments augmented with the slack variable
1144+
``\mathbf{ΔŨ} = [\begin{smallmatrix} \mathbf{ΔU} \\ ϵ \end{smallmatrix}]``, it returns the
1145+
``\mathbf{ẽ_{x̂}}`` matrix that appears in the terminal state equation
1146+
``\mathbf{x̂}_{k-1}(k + H_p) = \mathbf{ẽ_x̂ ΔŨ + f_x̂}``, and the ``\mathbf{A}`` matrices for
1147+
the inequality constraints:
1148+
```math
1149+
\begin{bmatrix}
1150+
\mathbf{A_{x̂_{min}}} \\
1151+
\mathbf{A_{x̂_{max}}}
1152+
\end{bmatrix} \mathbf{ΔŨ} ≤
1153+
\begin{bmatrix}
1154+
- \mathbf{x̂_{min}} + \mathbf{f_x̂} \\
1155+
+ \mathbf{x̂_{max}} - \mathbf{f_x̂}
1156+
\end{bmatrix}
1157+
```
11331158
"""
11341159
function relaxterminal(::LinModel, C, c_x̂min, c_x̂max, ex̂)
11351160
if !isinf(C) # ΔŨ = [ΔU; ϵ]

0 commit comments

Comments
 (0)