Skip to content

Commit 2a0066b

Browse files
committed
cleanup predict! method for custom constraints
1 parent c29e29c commit 2a0066b

File tree

5 files changed

+96
-86
lines changed

5 files changed

+96
-86
lines changed

src/controller/execute.jl

Lines changed: 34 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,12 @@ See also [`LinMPC`](@ref), [`ExplicitMPC`](@ref), [`NonLinMPC`](@ref).
3131
- `mpc::PredictiveController` : solve optimization problem of `mpc`.
3232
- `ry=mpc.estim.model.yop` : current output setpoints ``\mathbf{r_y}(k)``.
3333
- `d=[]` : current measured disturbances ``\mathbf{d}(k)``.
34-
- `D̂=repeat(d, mpc.Hp)` or *`Dhat`* : predicted measured disturbances ``\mathbf{D̂}`` (constant
35-
in the future by default, or ``\mathbf{d̂}(k+j)=\mathbf{d}(k)`` for ``j=1`` to ``H_p``).
36-
- `R̂y=repeat(ry, mpc.Hp)` or *`Rhaty`* : predicted output setpoints ``\mathbf{R̂_y}`` (constant
37-
in the future by default, or ``\mathbf{r̂_y}(k+j)=\mathbf{r_y}(k)`` for ``j=1`` to ``H_p``).
38-
- `R̂u=mpc.Uop` or *`Rhatu`* : predicted manipulated input setpoints ``\mathbf{R̂_u}`` (constant
39-
in the future by default, or ``\mathbf{r̂_u}(k+j)=\mathbf{u_{op}}`` for ``j=0`` to ``H_p-1``).
34+
- `D̂=repeat(d, mpc.Hp)` or *`Dhat`* : predicted measured disturbances ``\mathbf{D̂}``, constant
35+
in the future by default or ``\mathbf{d̂}(k+j)=\mathbf{d}(k)`` for ``j=1`` to ``H_p``.
36+
- `R̂y=repeat(ry, mpc.Hp)` or *`Rhaty`* : predicted output setpoints ``\mathbf{R̂_y}``, constant
37+
in the future by default or ``\mathbf{r̂_y}(k+j)=\mathbf{r_y}(k)`` for ``j=1`` to ``H_p``.
38+
- `R̂u=mpc.Uop` or *`Rhatu`* : predicted manipulated input setpoints, constant in the future
39+
by default or ``\mathbf{r̂_u}(k+j)=\mathbf{u_{op}}`` for ``j=0`` to ``H_p-1``.
4040
4141
# Examples
4242
```jldoctest
@@ -135,8 +135,8 @@ function getinfo(mpc::PredictiveController{NT}) where NT<:Real
135135
info[:Ŷ] = Ŷ0 + mpc.Yop
136136
info[:x̂end] = x̂0end + mpc.estim.x̂op
137137
info[:Ŷs] = Ŷs
138-
info[:R̂y] = mpc.R̂y0 + mpc.Yop
139-
info[:R̂u] = mpc.R̂u0 + mpc.Uop
138+
info[:R̂y] = mpc.R̂y
139+
info[:R̂u] = mpc.R̂u
140140
# --- non-Unicode fields ---
141141
info[:DeltaU] = info[:ΔU]
142142
info[:epsilon] = info[]
@@ -198,14 +198,14 @@ function initpred!(mpc::PredictiveController, model::LinModel, d, D̂, R̂y, R̂
198198
mul!(F, mpc.G, mpc.d0, 1, 1)
199199
mul!(F, mpc.J, mpc.D̂0, 1, 1)
200200
end
201-
mpc.R̂y0 .= R̂y .- mpc.Yop
202-
Cy = F .- mpc.R̂y0
201+
mpc.R̂y .= R̂y
202+
Cy = F .- (R̂y .- mpc.Yop)
203203
M_Hp_Ẽ = mpc.M_Hp*mpc.
204204
mul!(q̃, M_Hp_Ẽ', Cy)
205205
r .= dot(Cy, mpc.M_Hp, Cy)
206206
if ~mpc.noR̂u
207-
mpc.R̂u0 .= R̂u .- mpc.Uop
208-
Cu = mpc.T_lastu0 .- mpc.R̂u0
207+
mpc.R̂u .= R̂u
208+
Cu = mpc.T_lastu0 .- (R̂u .- mpc.Uop)
209209
L_Hp_S̃ = mpc.L_Hp*mpc.
210210
mul!(q̃, L_Hp_S̃', Cu, 1, 1)
211211
r .+= dot(Cu, mpc.L_Hp, Cu)
@@ -217,7 +217,7 @@ end
217217
@doc raw"""
218218
initpred!(mpc::PredictiveController, model::SimModel, d, D̂, R̂y, R̂u)
219219
220-
Init `ŷ, F, d0, D̂0, D̂e, R̂y0, R̂u0` vectors when model is not a [`LinModel`](@ref).
220+
Init `ŷ, F, d0, D̂0, D̂e, R̂y, R̂u` vectors when model is not a [`LinModel`](@ref).
221221
"""
222222
function initpred!(mpc::PredictiveController, model::SimModel, d, D̂, R̂y, R̂u)
223223
mul!(mpc.T_lastu0, mpc.T, mpc.estim.lastu0)
@@ -229,9 +229,9 @@ function initpred!(mpc::PredictiveController, model::SimModel, d, D̂, R̂y, R̂
229229
mpc.D̂e[1:model.nd] .= d
230230
mpc.D̂e[model.nd+1:end] .=
231231
end
232-
mpc.R̂y0 .= (R̂y .- mpc.Yop)
232+
mpc.R̂y .= R̂y
233233
if ~mpc.noR̂u
234-
mpc.R̂u0 .= (R̂u .- mpc.Uop)
234+
mpc.R̂u .= R̂u
235235
end
236236
return nothing
237237
end
@@ -356,57 +356,55 @@ function predict!(Ŷ0, x̂0, x̂0next, u0, û0, mpc::PredictiveController, mod
356356
end
357357

358358
"""
359-
obj_nonlinprog!(U0 , Ȳ, _ , mpc::PredictiveController, model::LinModel, Ŷ0, ΔŨ)
359+
obj_nonlinprog!( _ , _ , mpc::PredictiveController, model::LinModel, Ŷe, Ue, ΔŨ)
360360
361361
Nonlinear programming objective function when `model` is a [`LinModel`](@ref).
362362
363-
The function is called by the nonlinear optimizer of [`NonLinMPC`](@ref) controllers. It can
363+
The method is called by the nonlinear optimizer of [`NonLinMPC`](@ref) controllers. It can
364364
also be called on any [`PredictiveController`](@ref)s to evaluate the objective function `J`
365-
at specific input increments `ΔŨ` and predictions `Ŷ0` values. It mutates the `U0` and
366-
`Ȳ` arguments.
365+
at specific `Ue`, `Ŷe` and `ΔŨ`, values. It does not mutate any argument.
367366
"""
368367
function obj_nonlinprog!(
369-
U0, Ȳ, _ , mpc::PredictiveController, model::LinModel, Ŷ0, ΔŨ::AbstractVector{NT}
368+
_, _, mpc::PredictiveController, model::LinModel, Ŷe, Ue, ΔŨ::AbstractVector{NT}
370369
) where NT <: Real
371-
J = obj_quadprog(ΔŨ, mpc.H̃, mpc.q̃) + mpc.r[]
372-
E_JE = obj_econ!(U0, Ȳ, mpc, model, Ŷ0, ΔŨ)
373-
return J + E_JE
370+
JQP = obj_quadprog(ΔŨ, mpc.H̃, mpc.q̃) + mpc.r[]
371+
E_JE = obj_econ!(Ue, Ŷe, mpc, model)
372+
return JQP + E_JE
374373
end
375374

376375
"""
377-
obj_nonlinprog!(U0, Ȳ, Ū, mpc::PredictiveController, model::SimModel, Ŷ0, ΔŨ)
376+
obj_nonlinprog!(Ȳ, Ū, mpc::PredictiveController, model::SimModel, Ŷe, Ue, ΔŨ)
378377
379-
Nonlinear programming objective function when `model` is not a [`LinModel`](@ref). The
378+
Nonlinear programming objective method when `model` is not a [`LinModel`](@ref). The
380379
function `dot(x, A, x)` is a performant way of calculating `x'*A*x`. This method mutates
381-
`U0`, `Ȳ` and `Ū` arguments (input over `Hp`, and output and input setpoint tracking error,
382-
respectively).
380+
`Ȳ` and `Ū` arguments, without assuming any initial values (it recuperates the values in
381+
`Ŷe` and `Ue` arguments).
383382
"""
384383
function obj_nonlinprog!(
385-
U0, Ȳ, Ū, mpc::PredictiveController, model::SimModel, Ŷ0, ΔŨ::AbstractVector{NT}
384+
Ȳ, Ū, mpc::PredictiveController, model::SimModel, Ŷe, Ue, ΔŨ::AbstractVector{NT}
386385
) where NT<:Real
386+
nu, ny = model.nu, model.ny
387387
# --- output setpoint tracking term ---
388-
Ȳ .= mpc.R̂y0 .- Ŷ0
388+
Ȳ .= Ŷe[ny+1:end]
389+
Ȳ .= mpc.R̂y .-
389390
JR̂y = dot(Ȳ, mpc.M_Hp, Ȳ)
390391
# --- move suppression and slack variable term ---
391392
JΔŨ = dot(ΔŨ, mpc.Ñ_Hc, ΔŨ)
392-
# --- input over prediction horizon ---
393-
if !mpc.noR̂u || !iszero(mpc.E)
394-
U0 .= mul!(U0, mpc.S̃, ΔŨ) .+ mpc.T_lastu0
395-
end
396393
# --- input setpoint tracking term ---
397394
if !mpc.noR̂u
398-
Ū .= mpc.R̂u0 .- U0
395+
Ū .= Ue[1:end-nu]
396+
Ū .= mpc.R̂u .-
399397
JR̂u = dot(Ū, mpc.L_Hp, Ū)
400398
else
401399
JR̂u = 0.0
402400
end
403401
# --- economic term ---
404-
E_JE = obj_econ!(U0, Ȳ, mpc, model, Ŷ0, ΔŨ)
402+
E_JE = obj_econ!(Ue, Ŷe, mpc, model)
405403
return JR̂y + JΔŨ + JR̂u + E_JE
406404
end
407405

408406
"By default, the economic term is zero."
409-
obj_econ!( _ , _ , ::PredictiveController, ::SimModel, _ , _ ) = 0.0
407+
obj_econ!( _ , _ , ::PredictiveController, ::SimModel) = 0.0
410408

411409
@doc raw"""
412410
optim_objective!(mpc::PredictiveController) -> ΔŨ

src/controller/explicitmpc.jl

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ struct ExplicitMPC{NT<:Real, SE<:StateEstimator} <: PredictiveController{NT}
99
Ñ_Hc::Hermitian{NT, Matrix{NT}}
1010
L_Hp::Hermitian{NT, Matrix{NT}}
1111
E::NT
12-
R̂u0::Vector{NT}
13-
R̂y0::Vector{NT}
12+
R̂u::Vector{NT}
13+
R̂y::Vector{NT}
1414
noR̂u::Bool
1515
::Matrix{NT}
1616
T::Matrix{NT}
@@ -49,7 +49,7 @@ struct ExplicitMPC{NT<:Real, SE<:StateEstimator} <: PredictiveController{NT}
4949
N_Hc = Hermitian(convert(Matrix{NT}, N_Hc), :L)
5050
L_Hp = Hermitian(convert(Matrix{NT}, L_Hp), :L)
5151
# dummy vals (updated just before optimization):
52-
R̂y0, R̂u0, T_lastu0 = zeros(NT, ny*Hp), zeros(NT, nu*Hp), zeros(NT, nu*Hp)
52+
R̂y, R̂u, T_lastu0 = zeros(NT, ny*Hp), zeros(NT, nu*Hp), zeros(NT, nu*Hp)
5353
noR̂u = iszero(L_Hp)
5454
S, T = init_ΔUtoU(model, Hp, Hc)
5555
E, G, J, K, V, B = init_predmat(estim, model, Hp, Hc)
@@ -72,7 +72,7 @@ struct ExplicitMPC{NT<:Real, SE<:StateEstimator} <: PredictiveController{NT}
7272
ΔŨ, ŷ,
7373
Hp, Hc, nϵ,
7474
M_Hp, Ñ_Hc, L_Hp, Ewt,
75-
R̂u0, R̂y0, noR̂u,
75+
R̂u, R̂y, noR̂u,
7676
S̃, T, T_lastu0,
7777
Ẽ, F, G, J, K, V, B,
7878
H̃, q̃, r,

src/controller/linmpc.jl

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@ struct LinMPC{
1919
Ñ_Hc::Hermitian{NT, Matrix{NT}}
2020
L_Hp::Hermitian{NT, Matrix{NT}}
2121
E::NT
22-
R̂u0::Vector{NT}
23-
R̂y0::Vector{NT}
22+
R̂u::Vector{NT}
23+
R̂y::Vector{NT}
2424
noR̂u::Bool
2525
::Matrix{NT}
2626
T::Matrix{NT}
@@ -57,7 +57,7 @@ struct LinMPC{
5757
N_Hc = Hermitian(convert(Matrix{NT}, N_Hc), :L)
5858
L_Hp = Hermitian(convert(Matrix{NT}, L_Hp), :L)
5959
# dummy vals (updated just before optimization):
60-
R̂y0, R̂u0, T_lastu0 = zeros(NT, ny*Hp), zeros(NT, nu*Hp), zeros(NT, nu*Hp)
60+
R̂y, R̂u, T_lastu0 = zeros(NT, ny*Hp), zeros(NT, nu*Hp), zeros(NT, nu*Hp)
6161
noR̂u = iszero(L_Hp)
6262
S, T = init_ΔUtoU(model, Hp, Hc)
6363
E, G, J, K, V, B, ex̂, gx̂, jx̂, kx̂, vx̂, bx̂ = init_predmat(estim, model, Hp, Hc)
@@ -81,7 +81,7 @@ struct LinMPC{
8181
ΔŨ, ŷ,
8282
Hp, Hc, nϵ,
8383
M_Hp, Ñ_Hc, L_Hp, Ewt,
84-
R̂u0, R̂y0, noR̂u,
84+
R̂u, R̂y, noR̂u,
8585
S̃, T, T_lastu0,
8686
Ẽ, F, G, J, K, V, B,
8787
H̃, q̃, r,

src/controller/nonlinmpc.jl

Lines changed: 53 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@ struct NonLinMPC{
2323
E::NT
2424
JE::JEfunc
2525
p::P
26-
R̂u0::Vector{NT}
27-
R̂y0::Vector{NT}
26+
R̂u::Vector{NT}
27+
R̂y::Vector{NT}
2828
noR̂u::Bool
2929
::Matrix{NT}
3030
T::Matrix{NT}
@@ -62,7 +62,7 @@ struct NonLinMPC{
6262
N_Hc = Hermitian(convert(Matrix{NT}, N_Hc), :L)
6363
L_Hp = Hermitian(convert(Matrix{NT}, L_Hp), :L)
6464
# dummy vals (updated just before optimization):
65-
R̂y0, R̂u0, T_lastu0 = zeros(NT, ny*Hp), zeros(NT, nu*Hp), zeros(NT, nu*Hp)
65+
R̂y, R̂u, T_lastu0 = zeros(NT, ny*Hp), zeros(NT, nu*Hp), zeros(NT, nu*Hp)
6666
noR̂u = iszero(L_Hp)
6767
S, T = init_ΔUtoU(model, Hp, Hc)
6868
E, G, J, K, V, B, ex̂, gx̂, jx̂, kx̂, vx̂, bx̂ = init_predmat(estim, model, Hp, Hc)
@@ -86,7 +86,7 @@ struct NonLinMPC{
8686
ΔŨ, ŷ,
8787
Hp, Hc, nϵ,
8888
M_Hp, Ñ_Hc, L_Hp, Ewt, JE, p,
89-
R̂u0, R̂y0, noR̂u,
89+
R̂u, R̂y, noR̂u,
9090
S̃, T, T_lastu0,
9191
Ẽ, F, G, J, K, V, B,
9292
H̃, q̃, r,
@@ -375,7 +375,6 @@ function get_mutating_gc(NT, gc)
375375
gc! = if ismutating_gc
376376
gc
377377
else
378-
println("YO!")
379378
function gc!(LHS, Ue, Ŷe, D̂e, p, ϵ)
380379
LHS .= gc(Ue, Ŷe, D̂e, p, ϵ)
381380
return nothing
@@ -385,14 +384,13 @@ function get_mutating_gc(NT, gc)
385384
end
386385

387386
function test_custom_functions(JE, gc!, uop; Uop, dop, Dop, ΔŨ, p)
387+
# TODO: contunue here (important to guide the users, sim! can be used on NonLinModel
388+
# but there is no similar function for the custom functions of NonLinMPC)
388389
Ue = [Uop; uop]
389390
D̂e = [dop; Dop]
390391
Ŷ0, x̂0next =
391392
Ŷ0, x̂0end = predict!(Ŷ0, x̂0, x̂0next, u0, û0, mpc, model, mpc.ΔŨ)
392-
393-
394393
JE = JE(Uop, Uop, Dop, p)
395-
396394
end
397395

398396
"""
@@ -475,31 +473,33 @@ function get_optim_functions(mpc::NonLinMPC, ::JuMP.GenericModel{JNT}) where JNT
475473
model = mpc.estim.model
476474
nu, ny, nx̂, Hp = model.nu, model.ny, mpc.estim.nx̂, mpc.Hp
477475
ng, nΔŨ, nU, nŶ = length(mpc.con.i_g), length(mpc.ΔŨ), Hp*nu, Hp*ny
476+
nUe, nŶe = nU + nu, nŶ + ny
478477
Nc = nΔŨ + 3
479478
ΔŨ_cache::DiffCache{Vector{JNT}, Vector{JNT}} = DiffCache(zeros(JNT, nΔŨ), Nc)
480-
Ŷ0_cache::DiffCache{Vector{JNT}, Vector{JNT}} = DiffCache(zeros(JNT, nŶ), Nc)
481-
U0_cache::DiffCache{Vector{JNT}, Vector{JNT}} = DiffCache(zeros(JNT, nU), Nc)
482-
g_cache::DiffCache{Vector{JNT}, Vector{JNT}} = DiffCache(zeros(JNT, ng), Nc)
483-
x̂0_cache::DiffCache{Vector{JNT}, Vector{JNT}} = DiffCache(zeros(JNT, nx̂), Nc)
484-
x̂0next_cache::DiffCache{Vector{JNT}, Vector{JNT}} = DiffCache(zeros(JNT, nx̂), Nc)
485-
u0_cache::DiffCache{Vector{JNT}, Vector{JNT}} = DiffCache(zeros(JNT, nu), Nc)
486-
û0_cache::DiffCache{Vector{JNT}, Vector{JNT}} = DiffCache(zeros(JNT, nu), Nc)
487-
Ȳ_cache::DiffCache{Vector{JNT}, Vector{JNT}} = DiffCache(zeros(JNT, nŶ), Nc)
488-
Ū_cache::DiffCache{Vector{JNT}, Vector{JNT}} = DiffCache(zeros(JNT, nU), Nc)
479+
Ŷe_cache::DiffCache{Vector{JNT}, Vector{JNT}} = DiffCache(zeros(JNT, nŶe), Nc)
480+
Ue_cache::DiffCache{Vector{JNT}, Vector{JNT}} = DiffCache(zeros(JNT, nUe), Nc)
481+
Ȳ_cache::DiffCache{Vector{JNT}, Vector{JNT}} = DiffCache(zeros(JNT, nŶ), Nc)
482+
Ū_cache::DiffCache{Vector{JNT}, Vector{JNT}} = DiffCache(zeros(JNT, nU), Nc)
483+
x̂0_cache::DiffCache{Vector{JNT}, Vector{JNT}} = DiffCache(zeros(JNT, nx̂), Nc)
484+
x̂0next_cache::DiffCache{Vector{JNT}, Vector{JNT}} = DiffCache(zeros(JNT, nx̂), Nc)
485+
u0_cache::DiffCache{Vector{JNT}, Vector{JNT}} = DiffCache(zeros(JNT, nu), Nc)
486+
û0_cache::DiffCache{Vector{JNT}, Vector{JNT}} = DiffCache(zeros(JNT, nu), Nc)
487+
g_cache::DiffCache{Vector{JNT}, Vector{JNT}} = DiffCache(zeros(JNT, ng), Nc)
489488
function Jfunc(ΔŨtup::T...) where T<:Real
490489
ΔŨ1 = ΔŨtup[begin]
491490
ΔŨ, g = get_tmp(ΔŨ_cache, ΔŨ1), get_tmp(g_cache, ΔŨ1)
492491
for i in eachindex(ΔŨtup)
493492
ΔŨ[i] = ΔŨtup[i] # ΔŨ .= ΔŨtup seems to produce a type instability
494-
end
495-
Ŷ0 = get_tmp(Ŷ0_cache, ΔŨ1)
493+
end
494+
Ŷe, Ue = get_tmp(Ŷe_cache, ΔŨ1), get_tmp(Ue_cache, ΔŨ1)
495+
Ȳ, Ū = get_tmp(Ȳ_cache, ΔŨ1), get_tmp(Ū_cache, ΔŨ1)
496496
x̂0, x̂0next = get_tmp(x̂0_cache, ΔŨ1), get_tmp(x̂0next_cache, ΔŨ1)
497-
u0, û0 = get_tmp(u0_cache, ΔŨ1), get_tmp(û0_cache, ΔŨ1)
498-
Ŷ0, x̂0end = predict!(Ŷ0, x̂0, x̂0next, u0, û0, mpc, model, ΔŨ)
497+
u0, û0 = get_tmp(u0_cache, ΔŨ1), get_tmp(û0_cache, ΔŨ1)
498+
Ŷ0, x̂0end = predict!(Ȳ, x̂0, x̂0next, u0, û0, mpc, model, ΔŨ)
499+
Ŷe, Ue = extended_predictions!(Ŷe, Ue, Ū, mpc, model, Ŷ0, ΔŨ)
499500
g = get_tmp(g_cache, ΔŨ1)
500501
g = con_nonlinprog!(g, mpc, model, x̂0end, Ŷ0, ΔŨ)
501-
U0, Ȳ, Ū = get_tmp(U0_cache, ΔŨ1), get_tmp(Ȳ_cache, ΔŨ1), get_tmp(Ū_cache, ΔŨ1)
502-
return obj_nonlinprog!(U0, Ȳ, Ū, mpc, model, Ŷ0, ΔŨ)::T
502+
return obj_nonlinprog!(Ȳ, Ū, mpc, model, Ŷe, Ue, ΔŨ)::T
503503
end
504504
function gfunc_i(i, ΔŨtup::NTuple{N, T}) where {N, T<:Real}
505505
ΔŨ1 = ΔŨtup[begin]
@@ -508,10 +508,13 @@ function get_optim_functions(mpc::NonLinMPC, ::JuMP.GenericModel{JNT}) where JNT
508508
for i in eachindex(ΔŨtup)
509509
ΔŨ[i] = ΔŨtup[i] # ΔŨ .= ΔŨtup seems to produce a type instability
510510
end
511-
Ŷ0 = get_tmp(Ŷ0_cache, ΔŨ1)
511+
Ŷe, Ue = get_tmp(Ŷe_cache, ΔŨ1), get_tmp(Ue_cache, ΔŨ1)
512+
Ȳ, Ū = get_tmp(Ȳ_cache, ΔŨ1), get_tmp(Ū_cache, ΔŨ1)
512513
x̂0, x̂0next = get_tmp(x̂0_cache, ΔŨ1), get_tmp(x̂0next_cache, ΔŨ1)
513-
u0, û0 = get_tmp(u0_cache, ΔŨ1), get_tmp(û0_cache, ΔŨ1)
514-
Ŷ0, x̂0end = predict!(Ŷ0, x̂0, x̂0next, u0, û0, mpc, model, ΔŨ)
514+
u0, û0 = get_tmp(u0_cache, ΔŨ1), get_tmp(û0_cache, ΔŨ1)
515+
Ŷ0, x̂0end = predict!(Ȳ, x̂0, x̂0next, u0, û0, mpc, model, ΔŨ)
516+
Ŷe, Ue = extended_predictions!(Ŷe, Ue, Ū, mpc, model, Ŷ0, ΔŨ)
517+
g = get_tmp(g_cache, ΔŨ1)
515518
g = con_nonlinprog!(g, mpc, model, x̂0end, Ŷ0, ΔŨ)
516519
end
517520
return g[i]::T
@@ -520,6 +523,27 @@ function get_optim_functions(mpc::NonLinMPC, ::JuMP.GenericModel{JNT}) where JNT
520523
return Jfunc, gfunc
521524
end
522525

526+
"""
527+
extended_predictions!(Ŷe, Ue, Ū, mpc, model, Ŷ0, ΔŨ) -> Ŷe, Ue
528+
529+
Compute the extended predictions `Ŷe` and `Ue` for the nonlinear optimization.
530+
531+
The function mutates `Ŷe`, `Ue` and `Ū` in arguments, without assuming any initial values.
532+
"""
533+
function extended_predictions!(Ŷe, Ue, Ū, mpc, model, Ŷ0, ΔŨ)
534+
ny, nu = model.ny, model.nu
535+
# --- extended output predictions Ŷe = [ŷ(k); Ŷ] ---
536+
Ŷe[1:ny] .= mpc.
537+
Ŷe[ny+1:end] .= Ŷ0 .+ mpc.Yop
538+
# --- extended manipulated inputs Ue = [U; u(k+Hp-1)] ---
539+
U0 =
540+
U0 .= mul!(U0, mpc.S̃, ΔŨ) .+ mpc.T_lastu0
541+
Ue[1:end-nu] .= U0 .+ mpc.Uop
542+
# u(k + Hp) = u(k + Hp - 1) since Δu(k+Hp) = 0 (because Hc ≤ Hp):
543+
Ue[end-nu+1:end] .= @views Ue[end-2nu+1:end-nu]
544+
return Ŷe, Ue
545+
end
546+
523547
"Set the nonlinear constraints on the output predictions `Ŷ` and terminal states `x̂end`."
524548
function setnonlincon!(
525549
mpc::NonLinMPC, ::NonLinModel, optim::JuMP.GenericModel{JNT}
@@ -579,20 +603,8 @@ end
579603
"No nonlinear constraints if `model` is a [`LinModel`](@ref), return `g` unchanged."
580604
con_nonlinprog!(g, ::NonLinMPC, ::LinModel, _ , _ , _ ) = g
581605

582-
"Evaluate the economic term of the objective function for [`NonLinMPC`](@ref)."
583-
function obj_econ!(U0, Ȳ, mpc::NonLinMPC, model::SimModel, Ŷ0, ΔŨ)
584-
if !iszero(mpc.E)
585-
ny, Hp, ŷ, D̂e = model.ny, mpc.Hp, mpc.ŷ, mpc.D̂e
586-
U = U0
587-
U .+= mpc.Uop
588-
uend = @views U[(end-model.nu+1):end]
589-
=
590-
Ŷ .= Ŷ0 .+ mpc.Yop
591-
Ue = [U; uend]
592-
Ŷe = [ŷ; Ŷ]
593-
E_JE = mpc.E*mpc.JE(Ue, Ŷe, D̂e, mpc.p)
594-
else
595-
E_JE = 0.0
596-
end
606+
"Evaluate the economic term `E*JE` of the objective function for [`NonLinMPC`](@ref)."
607+
function obj_econ!(Ue, Ŷe, mpc::NonLinMPC, model::SimModel)
608+
E_JE = iszero(mpc.E) ? 0.0 : mpc.E*mpc.JE(Ue, Ŷe, mpc.D̂e, mpc.p)
597609
return E_JE
598610
end

test/test_predictive_control.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -479,7 +479,7 @@ end
479479
nonlinmodel = NonLinModel(f, h, Ts, 2, 4, 2, 1, p=linmodel1, solver=nothing)
480480
nmpc1 = NonLinMPC(nonlinmodel, Hp=15)
481481
@test isa(nmpc1.estim, UnscentedKalmanFilter)
482-
@test size(nmpc1.R̂y0, 1) == 15*nmpc1.estim.model.ny
482+
@test size(nmpc1.R̂y, 1) == 15*nmpc1.estim.model.ny
483483
nmpc2 = NonLinMPC(nonlinmodel, Hp=15, Hc=4, Cwt=Inf)
484484
@test size(nmpc2.Ẽ, 2) == 4*nonlinmodel.nu
485485
nmpc3 = NonLinMPC(nonlinmodel, Hp=15, Hc=4, Cwt=1e6)

0 commit comments

Comments
 (0)