11const DEFAULT_LINMPC_OPTIMIZER = OSQP. MathOptInterfaceOSQP. Optimizer
2- const DEFAULT_LINMPC_TRANSCRIPTION = :singleshooting
2+ const DEFAULT_LINMPC_TRANSCRIPTION = SingleShooting ()
33
44struct LinMPC{
55 NT<: Real ,
66 SE<: StateEstimator ,
7+ TM<: TranscriptionMethod ,
78 JM<: JuMP.GenericModel
89} <: PredictiveController{NT}
910 estim:: SE
1011 # note: `NT` and the number type `JNT` in `JuMP.GenericModel{JNT}` can be
1112 # different since solvers that support non-Float64 are scarce.
12- transcription:: Symbol
13+ transcription:: TM
1314 optim:: JM
1415 con:: ControllerConstraint{NT, Nothing}
1516 ΔŨ:: Vector{NT}
@@ -44,17 +45,17 @@ struct LinMPC{
4445 buffer:: PredictiveControllerBuffer{NT}
4546 function LinMPC {NT} (
4647 estim:: SE , Hp, Hc, M_Hp, N_Hc, L_Hp, Cwt,
47- transcription, optim:: JM
48- ) where {NT<: Real , SE<: StateEstimator , JM<: JuMP.GenericModel }
48+ transcription:: TM , optim:: JM
49+ ) where {NT<: Real , SE<: StateEstimator , TM <: TranscriptionMethod , JM<: JuMP.GenericModel }
4950 model = estim. model
5051 nu, ny, nd, nx̂ = model. nu, model. ny, model. nd, estim. nx̂
5152 ŷ = copy (model. yop) # dummy vals (updated just before optimization)
5253 weights = ControllerWeights {NT} (model, Hp, Hc, M_Hp, N_Hc, L_Hp, Cwt)
5354 # dummy vals (updated just before optimization):
5455 R̂y, R̂u, T_lastu = zeros (NT, ny* Hp), zeros (NT, nu* Hp), zeros (NT, nu* Hp)
55- S, T = init_ZtoU (estim, Hp, Hc, transcription )
56+ S, T = init_ZtoU (estim, transcription, Hp, Hc )
5657 E, G, J, K, V, B, ex̂, gx̂, jx̂, kx̂, vx̂, bx̂ = init_predmat (
57- estim, model , Hp, Hc, transcription
58+ model, estim, transcription , Hp, Hc
5859 )
5960 # dummy vals (updated just before optimization):
6061 F, fx̂ = zeros (NT, ny* Hp), zeros (NT, nx̂)
@@ -71,7 +72,7 @@ struct LinMPC{
7172 nΔŨ = size (Ẽ, 2 )
7273 ΔŨ = zeros (NT, nΔŨ)
7374 buffer = PredictiveControllerBuffer {NT} (nu, ny, nd, Hp, Hc, nϵ)
74- mpc = new {NT, SE, JM} (
75+ mpc = new {NT, SE, TM, JM} (
7576 estim, transcription, optim, con,
7677 ΔŨ, ŷ,
7778 Hp, Hc, nϵ,
@@ -98,7 +99,7 @@ Construct a linear predictive controller based on [`LinModel`](@ref) `model`.
9899The controller minimizes the following objective function at each discrete time ``k``:
99100```math
100101\b egin{aligned}
101- \m in_{\m athbf{ΔU }, ϵ} \m athbf{(R̂_y - Ŷ)}' \m athbf{M}_{H_p} \m athbf{(R̂_y - Ŷ)}
102+ \m in_{\m athbf{Z }, ϵ} \m athbf{(R̂_y - Ŷ)}' \m athbf{M}_{H_p} \m athbf{(R̂_y - Ŷ)}
102103 + \m athbf{(ΔU)}' \m athbf{N}_{H_c} \m athbf{(ΔU)} \\
103104 + \m athbf{(R̂_u - U)}' \m athbf{L}_{H_p} \m athbf{(R̂_u - U)}
104105 + C ϵ^2
@@ -114,8 +115,10 @@ subject to [`setconstraint!`](@ref) bounds, and in which the weight matrices are
114115\e nd{aligned}
115116```
116117Time-varying and non-diagonal weights are also supported. Modify the last block in
117- ``\m athbf{M}_{H_p}`` to specify a terminal weight. The ``\m athbf{ΔU}`` includes the input
118- increments ``\m athbf{Δu}(k+j) = \m athbf{u}(k+j) - \m athbf{u}(k+j-1)`` from ``j=0`` to
118+ ``\m athbf{M}_{H_p}`` to specify a terminal weight. The content of the decision variable
119+ vector ``\m athbf{Z}`` depends on the chosen [`TranscriptionMethod`](@ref) (default to
120+ [`SingleShooting`](@ref)). The ``\m athbf{ΔU}`` includes the input increments
121+ ``\m athbf{Δu}(k+j) = \m athbf{u}(k+j) - \m athbf{u}(k+j-1)`` from ``j=0`` to
119122``H_c-1``, the ``\m athbf{Ŷ}`` vector, the output predictions ``\m athbf{ŷ}(k+j)`` from
120123``j=1`` to ``H_p``, and the ``\m athbf{U}`` vector, the manipulated inputs ``\m athbf{u}(k+j)``
121124from ``j=0`` to ``H_p-1``. The slack variable ``ϵ`` relaxes the constraints, as described
@@ -135,12 +138,10 @@ arguments. This controller allocates memory at each time step for the optimizati
135138- `N_Hc=diagm(repeat(Nwt,Hc))` : positive semidefinite symmetric matrix ``\m athbf{N}_{H_c}``.
136139- `L_Hp=diagm(repeat(Lwt,Hp))` : positive semidefinite symmetric matrix ``\m athbf{L}_{H_p}``.
137140- `Cwt=1e5` : slack variable weight ``C`` (scalar), use `Cwt=Inf` for hard constraints only.
138- - `transcription=:singleshooting` : transcription method for the nonlinear optimization
139- problem, can be `:singleshooting` or `:multipleshoting`.
141+ - `transcription=SingleShooting()` : a [`TranscriptionMethod`](@ref) for the optimization.
140142- `optim=JuMP.Model(OSQP.MathOptInterfaceOSQP.Optimizer)` : quadratic optimizer used in
141143 the predictive controller, provided as a [`JuMP.Model`](https://jump.dev/JuMP.jl/stable/api/JuMP/#JuMP.Model)
142144 (default to [`OSQP`](https://osqp.org/docs/parsers/jump.html) optimizer).
143-
144145- additional keyword arguments are passed to [`SteadyKalmanFilter`](@ref) constructor.
145146
146147# Examples
@@ -171,9 +172,11 @@ LinMPC controller with a sample time Ts = 4.0 s, OSQP optimizer, SteadyKalmanFil
171172 | :------------------- | :------------------------------------------------------- | :--------------- |
172173 | ``H_p`` | prediction horizon (integer) | `()` |
173174 | ``H_c`` | control horizon (integer) | `()` |
175+ | ``\m athbf{Z}`` | decision variable vector (excluding ``ϵ``) | var. |
174176 | ``\m athbf{ΔU}`` | manipulated input increments over ``H_c`` | `(nu*Hc,)` |
175177 | ``\m athbf{D̂}`` | predicted measured disturbances over ``H_p`` | `(nd*Hp,)` |
176178 | ``\m athbf{Ŷ}`` | predicted outputs over ``H_p`` | `(ny*Hp,)` |
179+ | ``\m athbf{X̂}`` | predicted states over ``H_p`` | `(nx̂*Hp,)` |
177180 | ``\m athbf{U}`` | manipulated inputs over ``H_p`` | `(nu*Hp,)` |
178181 | ``\m athbf{R̂_y}`` | predicted output setpoints over ``H_p`` | `(ny*Hp,)` |
179182 | ``\m athbf{R̂_u}`` | predicted manipulated input setpoints over ``H_p`` | `(nu*Hp,)` |
@@ -194,7 +197,7 @@ function LinMPC(
194197 N_Hc = diagm (repeat (Nwt, Hc)),
195198 L_Hp = diagm (repeat (Lwt, Hp)),
196199 Cwt = DEFAULT_CWT,
197- transcription = DEFAULT_LINMPC_TRANSCRIPTION,
200+ transcription:: TranscriptionMethod = DEFAULT_LINMPC_TRANSCRIPTION,
198201 optim:: JuMP.GenericModel = JuMP. Model (DEFAULT_LINMPC_OPTIMIZER, add_bridges= false ),
199202 kwargs...
200203)
@@ -237,7 +240,7 @@ function LinMPC(
237240 N_Hc = diagm (repeat (Nwt, Hc)),
238241 L_Hp = diagm (repeat (Lwt, Hp)),
239242 Cwt = DEFAULT_CWT,
240- transcription = DEFAULT_LINMPC_TRANSCRIPTION,
243+ transcription:: TranscriptionMethod = DEFAULT_LINMPC_TRANSCRIPTION,
241244 optim:: JM = JuMP. Model (DEFAULT_LINMPC_OPTIMIZER, add_bridges= false ),
242245) where {NT<: Real , SE<: StateEstimator{NT} , JM<: JuMP.GenericModel }
243246 isa (estim. model, LinModel) || error (" estim.model type must be a LinModel" )
0 commit comments