Skip to content

Commit e04ec3a

Browse files
authored
Merge pull request #310 from JuliaControl/custom_linconstraint
added: custom linear inequality constraints for `LinMPC` and `NonLinMPC`
2 parents faba5ee + b4ba499 commit e04ec3a

16 files changed

Lines changed: 1050 additions & 483 deletions

README.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,9 +81,10 @@ for more detailed examples.
8181
- 📸 **Linearization**: Auto-differentiation for exact Jacobians.
8282
- ⚙️ **Adaptive MPC**: Manual model updates or automatic successive linearization.
8383
- 🏎️ **Explicit MPC**: Specialized for unconstrained problems.
84-
- 🚧 **Constraints**: Soft/hard limits on inputs, outputs, increments, and terminal states.
84+
- 🚧 **Bounds**: Soft/hard limits on inputs, outputs, increments, and terminal states.
85+
- 🚫 **Contraints**: Soft/hard custom linear and nonlinear inequality constraints.
8586
- 🔁 **Feedback**: Internal model or state estimators (see features below).
86-
- 📡 **Feedforward**: Integrated support for measured disturbances.
87+
- 📡 **Feedforward**: Integrated support for measured disturbances.
8788
- 🔮 **Preview**: Custom predictions for setpoints and measured disturbances.
8889
- 📈 **Offset-Free**: Automatic model augmentation with integrators.
8990
- 📊 **Visuals**: Easy integration with `Plots.jl`.

docs/src/index.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ real-time optimization. Modern MPCs based on closed-loop state estimators are th
1414
of the package, but classical approaches that rely on internal models are also possible. The
1515
`JuMP` and `DifferentiationInterface` dependencies allows the user to test different
1616
optimizers and automatic differentiation (AD) backends easily if the performances of the
17-
default settings are not satisfactory.
17+
default settings are not satisfactory. Linear MPC controllers can be exported to lightweight
18+
and standalone C code via the `LinearMPC` package extension.
1819

1920
The documentation is divided in two parts:
2021

docs/src/internals/predictive_control.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,9 @@ ModelPredictiveControl.init_defectmat
2020
ModelPredictiveControl.relaxU
2121
ModelPredictiveControl.relaxΔU
2222
ModelPredictiveControl.relaxŶ
23+
ModelPredictiveControl.relaxW
2324
ModelPredictiveControl.relaxterminal
25+
ModelPredictiveControl.augmentdefect
2426
ModelPredictiveControl.init_quadprog
2527
ModelPredictiveControl.init_stochpred
2628
ModelPredictiveControl.init_matconstraint_mpc
@@ -31,7 +33,7 @@ ModelPredictiveControl.get_nonlincon_oracle(::NonLinMPC, ::ModelPredictiveContro
3133
## Update Quadratic Optimization
3234

3335
```@docs
34-
ModelPredictiveControl.initpred!(::PredictiveController, ::LinModel, ::Any, ::Any, ::Any, ::Any, ::Any)
36+
ModelPredictiveControl.initpred!(::PredictiveController, ::LinModel, ::Any, ::Any, ::Any, ::Any, ::Any, ::Any)
3537
ModelPredictiveControl.linconstraint!(::PredictiveController, ::LinModel, ::TranscriptionMethod)
3638
ModelPredictiveControl.linconstrainteq!
3739
```

ext/LinearMPCext.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,7 @@ end
180180

181181
function validate_constraints(mpc::ModelPredictiveControl.LinMPC)
182182
nΔU = mpc.Hc * mpc.estim.model.nu
183+
mpc.con.nw > 0 && error("Conversion of custom linear inequality constraints is not supported for now.")
183184
mpc.weights.isinf_C && return nothing # only hard constraints are entirely supported
184185
C_umin, C_umax = -mpc.con.A_Umin[:, end], -mpc.con.A_Umax[:, end]
185186
C_Δumin, C_Δumax = -mpc.con.A_ΔŨmin[1:nΔU, end], -mpc.con.A_ΔŨmax[1:nΔU, end]

src/controller/construct.jl

Lines changed: 292 additions & 71 deletions
Large diffs are not rendered by default.

src/controller/execute.jl

Lines changed: 65 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ function moveinput!(
7272
@warn "preparestate! should be called before moveinput! with current estimators"
7373
end
7474
validate_args(mpc, ry, d, lastu, D̂, R̂y, R̂u)
75-
initpred!(mpc, mpc.estim.model, d, lastu, D̂, R̂y, R̂u)
75+
initpred!(mpc, mpc.estim.model, ry, d, lastu, D̂, R̂y, R̂u)
7676
linconstraint!(mpc, mpc.estim.model, mpc.transcription)
7777
linconstrainteq!(mpc, mpc.estim.model, mpc.transcription)
7878
= optim_objective!(mpc)
@@ -202,7 +202,7 @@ function addinfo!(info, mpc::PredictiveController)
202202
end
203203

204204
@doc raw"""
205-
initpred!(mpc::PredictiveController, model::LinModel, d, lastu, D̂, R̂y, R̂u) -> nothing
205+
initpred!(mpc::PredictiveController, model::LinModel, ry, d, lastu, D̂, R̂y, R̂u) -> nothing
206206
207207
Init linear model prediction matrices `F, q̃, r` and current estimated output `ŷ`.
208208
@@ -221,8 +221,8 @@ They are computed with these equations using in-place operations:
221221
\end{aligned}
222222
```
223223
"""
224-
function initpred!(mpc::PredictiveController, model::LinModel, d, lastu, D̂, R̂y, R̂u)
225-
F = initpred_common!(mpc, model, d, lastu, D̂, R̂y, R̂u)
224+
function initpred!(mpc::PredictiveController, model::LinModel, ry, d, lastu, D̂, R̂y, R̂u)
225+
F = initpred_common!(mpc, model, ry, d, lastu, D̂, R̂y, R̂u)
226226
F .+= mpc.B # F = F + B
227227
mul!(F, mpc.K, mpc.estim.x̂0, 1, 1) # F = F + K*x̂0
228228
mul!(F, mpc.V, mpc.lastu0, 1, 1) # F = F + V*lastu0
@@ -254,24 +254,26 @@ function initpred!(mpc::PredictiveController, model::LinModel, d, lastu, D̂, R
254254
end
255255

256256
@doc raw"""
257-
initpred!(mpc::PredictiveController, model::SimModel, d, lastu, D̂, R̂y, R̂u)
257+
initpred!(mpc::PredictiveController, model::SimModel, ry, d, lastu, D̂, R̂y, R̂u) -> nothing
258258
259259
Init `lastu0, ŷ, F, d0, D̂0, D̂e, R̂y, R̂u` vectors when model is not a [`LinModel`](@ref).
260260
"""
261-
function initpred!(mpc::PredictiveController, model::SimModel, d, lastu, D̂, R̂y, R̂u)
262-
F = initpred_common!(mpc, model, d, lastu, D̂, R̂y, R̂u)
261+
function initpred!(mpc::PredictiveController, model::SimModel, ry, d, lastu, D̂, R̂y, R̂u)
262+
initpred_common!(mpc, model, ry, d, lastu, D̂, R̂y, R̂u)
263263
return nothing
264264
end
265265

266266
"""
267-
initpred_common!(mpc::PredictiveController, model::SimModel, d, lastu, D̂, R̂y, R̂u) -> F
267+
initpred_common!(mpc::PredictiveController, model::SimModel, ry, d, lastu, D̂, R̂y, R̂u) -> F
268268
269269
Common computations of `initpred!` for all types of [`SimModel`](@ref).
270270
271271
Will also init `mpc.F` with 0 values, or with the stochastic predictions `Ŷs` if `mpc.estim`
272272
is an [`InternalModel`](@ref). The function returns `mpc.F`.
273273
"""
274-
function initpred_common!(mpc::PredictiveController, model::SimModel, d, lastu, D̂, R̂y, R̂u)
274+
function initpred_common!(
275+
mpc::PredictiveController, model::SimModel, ry, d, lastu, D̂, R̂y, R̂u
276+
)
275277
mpc.lastu0 .= lastu .- model.uop
276278
mul!(mpc.Tu_lastu0, mpc.Tu, mpc.lastu0)
277279
mpc.ŷ .= evaloutput(mpc.estim, d)
@@ -281,6 +283,7 @@ function initpred_common!(mpc::PredictiveController, model::SimModel, d, lastu,
281283
mpc.D̂e[1:model.nd] .= d
282284
mpc.D̂e[model.nd+1:end] .=
283285
end
286+
mpc.ry .= ry
284287
mpc.R̂y .= R̂y
285288
mpc.R̂u .= R̂u
286289
predictstoch!(mpc.F, mpc, mpc.estim)
@@ -300,6 +303,45 @@ end
300303
"Fill `Ŷs` vector with 0 values when `estim` is not an [`InternalModel`](@ref)."
301304
predictstoch!(Ŷs, mpc::PredictiveController, ::StateEstimator) = (Ŷs .= 0; nothing)
302305

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+
303345
"""
304346
extended_vectors!(Ue, Ŷe, mpc::PredictiveController, U0, Ŷ0) -> Ue, Ŷe
305347
@@ -626,18 +668,28 @@ function setmodel_controller!(mpc::PredictiveController, uop_old, x̂op_old)
626668
weights = mpc.weights
627669
nu, ny, nd, Hp, Hc, nb = model.nu, model.ny, model.nd, mpc.Hp, mpc.Hc, mpc.nb
628670
optim, con = mpc.optim, mpc.con
671+
nZ = get_nZ(estim, transcription, Hp, Hc)
672+
Pu = mpc.P̃u[:, 1:nZ]
629673
# --- prediction matrices ---
630674
E, G, J, K, V, B, ex̂, gx̂, jx̂, kx̂, vx̂, bx̂ = init_predmat(
631675
model, estim, transcription, Hp, Hc, nb
632676
)
633677
A_Ymin, A_Ymax, Ẽ = relaxŶ(E, con.C_ymin, con.C_ymax, mpc.nϵ)
678+
A_Wmin, A_Wmax, Ẽw = relaxW(E, Pu, Hp, con.W̄y, con.W̄u, con.C_wmin, con.C_wmax, mpc.nϵ)
634679
A_x̂min, A_x̂max, ẽx̂ = relaxterminal(ex̂, con.c_x̂min, con.c_x̂max, mpc.nϵ)
635680
mpc.Ẽ .=
636681
mpc.G .= G
637682
mpc.J .= J
638683
mpc.K .= K
639684
mpc.V .= V
640685
mpc.B .= B
686+
# --- terminal constraints ---
687+
con.ẽx̂ .= ẽx̂
688+
con.gx̂ .= gx̂
689+
con.jx̂ .= jx̂
690+
con.kx̂ .= kx̂
691+
con.vx̂ .= vx̂
692+
con.bx̂ .= bx̂
641693
# --- defect matrices ---
642694
Eŝ, Gŝ, Jŝ, Kŝ, Vŝ, Bŝ = init_defectmat(model, estim, transcription, Hp, Hc, nb)
643695
A_ŝ, Ẽŝ = augmentdefect(Eŝ, mpc.nϵ)
@@ -647,15 +699,13 @@ function setmodel_controller!(mpc::PredictiveController, uop_old, x̂op_old)
647699
con.Kŝ .= Kŝ
648700
con.Vŝ .= Vŝ
649701
con.Bŝ .= Bŝ
702+
# --- custom linear constraints ---
703+
con.Ẽw .= Ẽw
650704
# --- linear inequality constraints ---
651-
con.ẽx̂ .= ẽx̂
652-
con.gx̂ .= gx̂
653-
con.jx̂ .= jx̂
654-
con.kx̂ .= kx̂
655-
con.vx̂ .= vx̂
656-
con.bx̂ .= bx̂
657705
con.A_Ymin .= A_Ymin
658706
con.A_Ymax .= A_Ymax
707+
con.A_Wmin .= A_Wmin
708+
con.A_Wmax .= A_Wmax
659709
con.A_x̂min .= A_x̂min
660710
con.A_x̂max .= A_x̂max
661711
con.A .= [

src/controller/explicitmpc.jl

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ struct ExplicitMPC{
77
transcription::SingleShooting
88
::Vector{NT}
99
::Vector{NT}
10+
ry::Vector{NT}
1011
Hp::Int
1112
Hc::Int
1213
::Int
@@ -44,7 +45,7 @@ struct ExplicitMPC{
4445
) where {NT<:Real, SE<:StateEstimator, CW<:ControllerWeights}
4546
model = estim.model
4647
nu, ny, nd, nx̂ = model.nu, model.ny, model.nd, estim.nx̂
47-
= copy(model.yop) # dummy vals (updated just before optimization)
48+
, ry = copy(model.yop), copy(model.yop) # dummy vals (updated just before optimization)
4849
= 0 # no slack variable ϵ for ExplicitMPC
4950
# dummy vals (updated just before optimization):
5051
R̂y, R̂u, Tu_lastu0 = zeros(NT, ny*Hp), zeros(NT, nu*Hp), zeros(NT, nu*Hp)
@@ -54,8 +55,7 @@ struct ExplicitMPC{
5455
PΔu = init_ZtoΔU(estim, transcription, Hp, Hc)
5556
Pu, Tu = init_ZtoU(estim, transcription, Hp, Hc, nb)
5657
E, G, J, K, V, B = init_predmat(model, estim, transcription, Hp, Hc, nb)
57-
# dummy val (updated just before optimization):
58-
F = zeros(NT, ny*Hp)
58+
F = zeros(NT, ny*Hp) # dummy value (updated just before optimization)
5959
P̃Δu, P̃u, Ẽ = PΔu, Pu, E # no slack variable ϵ for ExplicitMPC
6060
= init_quadprog(model, transcription, weights, Ẽ, P̃Δu, P̃u)
6161
# dummy vals (updated just before optimization):
@@ -71,7 +71,7 @@ struct ExplicitMPC{
7171
mpc = new{NT, SE, CW}(
7272
estim,
7373
transcription,
74-
Z̃, ŷ,
74+
Z̃, ŷ, ry,
7575
Hp, Hc, nϵ, nb,
7676
weights,
7777
R̂u, R̂y,
@@ -106,8 +106,9 @@ The controller minimizes the following objective function at each discrete time
106106
See [`LinMPC`](@ref) for the variable definitions. This controller does not support
107107
constraints but the computational costs are extremely low (array division), therefore
108108
suitable for applications that require small sample times. The keyword arguments are
109-
identical to [`LinMPC`](@ref), except for `Cwt`, `transcription` and `optim`, which are not
110-
supported. It uses a [`SingleShooting`](@ref) transcription method and is allocation-free.
109+
identical to [`LinMPC`](@ref), except for `Cwt`, `Wy`, `Wu`, `Wd`, `Wr`, `transcription` and
110+
`optim`, which are not supported. It uses a [`SingleShooting`](@ref) transcription method
111+
and is allocation-free.
111112
112113
This method uses the default state estimator, a [`SteadyKalmanFilter`](@ref) with default
113114
arguments.

src/controller/linmpc.jl

Lines changed: 35 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ struct LinMPC{
1616
con::ControllerConstraint{NT, Nothing}
1717
::Vector{NT}
1818
::Vector{NT}
19+
ry::Vector{NT}
1920
Hp::Int
2021
Hc::Int
2122
::Int
@@ -48,7 +49,8 @@ struct LinMPC{
4849
Dop::Vector{NT}
4950
buffer::PredictiveControllerBuffer{NT}
5051
function LinMPC{NT}(
51-
estim::SE, Hp, Hc, nb, weights::CW,
52+
estim::SE, Hp, Hc, nb, weights::CW,
53+
Wy, Wu, Wd, Wr,
5254
transcription::TM, optim::JM
5355
) where {
5456
NT<:Real,
@@ -58,26 +60,27 @@ struct LinMPC{
5860
JM<:JuMP.GenericModel
5961
}
6062
model = estim.model
61-
nu, ny, nd, nx̂ = model.nu, model.ny, model.nd, estim.nx̂
62-
= copy(model.yop) # dummy vals (updated just before optimization)
63+
nu, ny, nd = model.nu, model.ny, model.nd
64+
, ry = copy(model.yop), copy(model.yop) # dummy vals (updated just before optimization)
6365
# dummy vals (updated just before optimization):
6466
R̂y, R̂u, Tu_lastu0 = zeros(NT, ny*Hp), zeros(NT, nu*Hp), zeros(NT, nu*Hp)
6567
lastu0 = zeros(NT, nu)
68+
Wy, Wu, Wd, Wr = validate_custom_lincon(model, Wy, Wu, Wd, Wr)
6669
validate_transcription(model, transcription)
6770
PΔu = init_ZtoΔU(estim, transcription, Hp, Hc)
6871
Pu, Tu = init_ZtoU(estim, transcription, Hp, Hc, nb)
6972
E, G, J, K, V, B, ex̂, gx̂, jx̂, kx̂, vx̂, bx̂ = init_predmat(
7073
model, estim, transcription, Hp, Hc, nb
7174
)
75+
F = zeros(NT, ny*Hp) # dummy value (updated just before optimization)
7276
Eŝ, Gŝ, Jŝ, Kŝ, Vŝ, Bŝ = init_defectmat(model, estim, transcription, Hp, Hc, nb)
73-
# dummy vals (updated just before optimization):
74-
F, fx̂, Fŝ = zeros(NT, ny*Hp), zeros(NT, nx̂), zeros(NT, nx̂*Hp)
7577
con, nϵ, P̃Δu, P̃u, Ẽ = init_defaultcon_mpc(
7678
estim, weights, transcription,
7779
Hp, Hc,
7880
PΔu, Pu, E,
79-
ex̂, fx̂, gx̂, jx̂, kx̂, vx̂, bx̂,
80-
Eŝ, Fŝ, Gŝ, Jŝ, Kŝ, Vŝ, Bŝ
81+
ex̂, gx̂, jx̂, kx̂, vx̂, bx̂,
82+
Eŝ, Gŝ, Jŝ, Kŝ, Vŝ, Bŝ,
83+
Wy, Wu, Wd, Wr
8184
)
8285
= init_quadprog(model, transcription, weights, Ẽ, P̃Δu, P̃u)
8386
# dummy vals (updated just before optimization):
@@ -91,7 +94,7 @@ struct LinMPC{
9194
buffer = PredictiveControllerBuffer(estim, transcription, Hp, Hc, nϵ)
9295
mpc = new{NT, SE, CW, TM, JM}(
9396
estim, transcription, optim, con,
94-
Z̃, ŷ,
97+
Z̃, ŷ, ry,
9598
Hp, Hc, nϵ, nb,
9699
weights,
97100
R̂u, R̂y,
@@ -147,6 +150,7 @@ This method uses the default state estimator, a [`SteadyKalmanFilter`](@ref) wit
147150
arguments. This controller allocates memory at each time step for the optimization.
148151
149152
# Arguments
153+
150154
- `model::LinModel` : model used for controller predictions and state estimations.
151155
- `Hp::Int=10+nk` : prediction horizon ``H_p``, `nk` is the number of delays in `model`.
152156
- `Hc::Union{Int, Vector{Int}}=2` : control horizon ``H_c``, custom move blocking pattern is
@@ -157,6 +161,10 @@ arguments. This controller allocates memory at each time step for the optimizati
157161
- `M_Hp=Diagonal(repeat(Mwt,Hp))` : positive semidefinite symmetric matrix ``\mathbf{M}_{H_p}``.
158162
- `N_Hc=Diagonal(repeat(Nwt,Hc))` : positive semidefinite symmetric matrix ``\mathbf{N}_{H_c}``.
159163
- `L_Hp=Diagonal(repeat(Lwt,Hp))` : positive semidefinite symmetric matrix ``\mathbf{L}_{H_p}``.
164+
- `Wy=nothing` : custom linear constraint matrix for output (see Extended Help).
165+
- `Wu=nothing` : custom linear constraint matrix for manipulated input (see Extended Help).
166+
- `Wd=nothing` : custom linear constraint matrix for meas. disturbance (see Extended Help).
167+
- `Wr=nothing` : custom linear constraint matrix for output setpoint (see Extended Help).
160168
- `Cwt=1e5` : slack variable weight ``C`` (scalar), use `Cwt=Inf` for hard constraints only.
161169
- `transcription=SingleShooting()` : [`SingleShooting`](@ref) or [`MultipleShooting`](@ref).
162170
- `optim=JuMP.Model(OSQP.MathOptInterfaceOSQP.Optimizer)` : quadratic optimizer used in
@@ -191,6 +199,11 @@ LinMPC controller with a sample time Ts = 4.0 s:
191199
for over-actuated systems, when `nu > ny` (e.g. prioritize solutions with lower
192200
economical costs). The default `Lwt` value implies that this feature is disabled by default.
193201
202+
The custom linear constraint matrices `Wy`, `Wu`, `Wd`, and `Wr` allow to define
203+
constraints based on linear combinations of outputs, manipulated inputs, measured
204+
disturbances, and output setpoints, respectively. See the Extended Help section in
205+
[`setconstraint!`](@ref) documentation for more details.
206+
194207
The objective function follows this nomenclature:
195208
196209
| VARIABLE | DESCRIPTION | SIZE |
@@ -221,13 +234,20 @@ function LinMPC(
221234
M_Hp = Diagonal(repeat(Mwt, Hp)),
222235
N_Hc = Diagonal(repeat(Nwt, get_Hc(move_blocking(Hp, Hc)))),
223236
L_Hp = Diagonal(repeat(Lwt, Hp)),
237+
Wy = nothing,
238+
Wu = nothing,
239+
Wd = nothing,
240+
Wr = nothing,
224241
Cwt = DEFAULT_CWT,
225242
transcription::ShootingMethod = DEFAULT_LINMPC_TRANSCRIPTION,
226243
optim::JuMP.GenericModel = JuMP.Model(DEFAULT_LINMPC_OPTIMIZER, add_bridges=false),
227244
kwargs...
228245
)
229246
estim = SteadyKalmanFilter(model; kwargs...)
230-
return LinMPC(estim; Hp, Hc, Mwt, Nwt, Lwt, Cwt, M_Hp, N_Hc, L_Hp, transcription, optim)
247+
return LinMPC(
248+
estim;
249+
Hp, Hc, Mwt, Nwt, Lwt, Cwt, M_Hp, N_Hc, L_Hp, Wy, Wu, Wd, Wr, transcription, optim
250+
)
231251
end
232252

233253

@@ -270,9 +290,13 @@ function LinMPC(
270290
M_Hp = Diagonal(repeat(Mwt, Hp)),
271291
N_Hc = Diagonal(repeat(Nwt, get_Hc(move_blocking(Hp, Hc)))),
272292
L_Hp = Diagonal(repeat(Lwt, Hp)),
293+
Wy = nothing,
294+
Wu = nothing,
295+
Wd = nothing,
296+
Wr = nothing,
273297
Cwt = DEFAULT_CWT,
274298
transcription::ShootingMethod = DEFAULT_LINMPC_TRANSCRIPTION,
275-
optim::JM = JuMP.Model(DEFAULT_LINMPC_OPTIMIZER, add_bridges=false),
299+
optim::JM = JuMP.Model(DEFAULT_LINMPC_OPTIMIZER, add_bridges=false)
276300
) where {NT<:Real, SE<:StateEstimator{NT}, JM<:JuMP.GenericModel}
277301
isa(estim.model, LinModel) || error(MSG_LINMODEL_ERR)
278302
nk = estimate_delays(estim.model)
@@ -283,7 +307,7 @@ function LinMPC(
283307
nb = move_blocking(Hp, Hc)
284308
Hc = get_Hc(nb)
285309
weights = ControllerWeights(estim.model, Hp, Hc, M_Hp, N_Hc, L_Hp, Cwt)
286-
return LinMPC{NT}(estim, Hp, Hc, nb, weights, transcription, optim)
310+
return LinMPC{NT}(estim, Hp, Hc, nb, weights, Wy, Wu, Wd, Wr, transcription, optim)
287311
end
288312

289313
"""

0 commit comments

Comments
 (0)