Skip to content

Commit 440dbca

Browse files
committed
clean up code structure
1 parent 694a49b commit 440dbca

File tree

3 files changed

+57
-41
lines changed

3 files changed

+57
-41
lines changed

src/controller/linmpc.jl

Lines changed: 24 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@ struct LinMPC{S<:StateEstimator} <: PredictiveController
3030
Ps::Matrix{Float64}
3131
d0::Vector{Float64}
3232
D̂0::Vector{Float64}
33-
Uop::Vector{Float64}
3433
Yop::Vector{Float64}
3534
Dop::Vector{Float64}
3635
function LinMPC{S}(estim::S, Hp, Hc, Mwt, Nwt, Lwt, Cwt, ru, optim) where {S<:StateEstimator}
@@ -48,11 +47,11 @@ struct LinMPC{S<:StateEstimator} <: PredictiveController
4847
S_Hp, T_Hp, S_Hc, T_Hc = init_ΔUtoU(nu, Hp, Hc)
4948
E, F, G, J, Kd, Q = init_deterpred(model, Hp, Hc)
5049
con, S̃_Hp, Ñ_Hc, Ẽ = init_defaultcon(model, Hp, Hc, C, S_Hp, S_Hc, N_Hc, E)
51-
nvar = size(Ẽ, 2)
5250
P̃, q̃ = init_quadprog(model, Ẽ, S̃_Hp, M_Hp, Ñ_Hc, L_Hp)
5351
Ks, Ps = init_stochpred(estim, Hp)
5452
d0, D̂0 = zeros(nd), zeros(nd*Hp)
55-
Uop, Yop, Dop = repeat(model.uop, Hp), repeat(model.yop, Hp), repeat(model.dop, Hp)
53+
Yop, Dop = repeat(model.yop, Hp), repeat(model.dop, Hp)
54+
nvar = size(Ẽ, 2)
5655
ΔŨ = zeros(nvar)
5756
mpc = new(
5857
estim, optim, con,
@@ -63,14 +62,9 @@ struct LinMPC{S<:StateEstimator} <: PredictiveController
6362
Ẽ, F, G, J, Kd, Q, P̃, q̃,
6463
Ks, Ps,
6564
d0, D̂0,
66-
Uop, Yop, Dop,
65+
Yop, Dop,
6766
)
68-
@variable(optim, ΔŨ[1:nvar])
69-
A = con.A[con.i_b, :]
70-
b = con.b[con.i_b]
71-
@constraint(optim, linconstraint, A*ΔŨ .≤ b)
72-
@objective(optim, Min, obj_quadprog(ΔŨ, mpc.P̃, mpc.q̃))
73-
set_silent(optim)
67+
init_optimization!(mpc)
7468
return mpc
7569
end
7670
end
@@ -199,11 +193,27 @@ function LinMPC(
199193
return LinMPC{S}(estim, Hp, Hc, Mwt, Nwt, Lwt, Cwt, ru, optim)
200194
end
201195

202-
"No nonlinear constraint for [`LinMPC`](@ref) controller."
203-
setnonlincon!(::LinMPC, ::LinModel) = nothing
196+
"""
197+
init_optimization!(mpc::LinMPC)
198+
199+
Init the quadratic optimization for [`LinMPC`](@ref) controllers.
200+
"""
201+
function init_optimization!(mpc::LinMPC)
202+
# --- variables and linear constraints ---
203+
optim, con = mpc.optim, mpc.con
204+
nvar = length(mpc.ΔŨ)
205+
set_silent(optim)
206+
@variable(optim, ΔŨvar[1:nvar])
207+
A = con.A[con.i_b, :]
208+
b = con.b[con.i_b]
209+
@constraint(optim, linconstraint, A*ΔŨvar .≤ b)
210+
# --- quadratic optimization init ---
211+
@objective(mpc.optim, Min, obj_quadprog(ΔŨvar, mpc.P̃, mpc.q̃))
212+
return nothing
213+
end
204214

205-
"Init quadratic programming `q̃` vector just before optimization."
206-
function init_objective!(mpc::LinMPC, ΔŨ)
215+
"Set quadratic programming `q̃` vector just before optimization."
216+
function set_objective!(mpc::LinMPC, ΔŨ)
207217
set_objective_function(mpc.optim, obj_quadprog(ΔŨ, mpc.P̃, mpc.q̃))
208218
return nothing
209219
end

src/controller/nonlinmpc.jl

Lines changed: 24 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@ struct NonLinMPC{S<:StateEstimator, JEFunc<:Function} <: PredictiveController
3232
Ps::Matrix{Float64}
3333
d0::Vector{Float64}
3434
D̂0::Vector{Float64}
35-
Uop::Vector{Float64}
3635
Yop::Vector{Float64}
3736
Dop::Vector{Float64}
3837
function NonLinMPC{S, JEFunc}(
@@ -52,11 +51,11 @@ struct NonLinMPC{S<:StateEstimator, JEFunc<:Function} <: PredictiveController
5251
S_Hp, T_Hp, S_Hc, T_Hc = init_ΔUtoU(nu, Hp, Hc)
5352
E, F, G, J, Kd, Q = init_deterpred(model, Hp, Hc)
5453
con, S̃_Hp, Ñ_Hc, Ẽ = init_defaultcon(model, Hp, Hc, C, S_Hp, S_Hc, N_Hc, E)
55-
nvar = size(Ẽ, 2)
5654
P̃, q̃ = init_quadprog(model, Ẽ, S̃_Hp, M_Hp, Ñ_Hc, L_Hp)
5755
Ks, Ps = init_stochpred(estim, Hp)
5856
d0, D̂0 = zeros(nd), zeros(nd*Hp)
59-
Uop, Yop, Dop = repeat(model.uop, Hp), repeat(model.yop, Hp), repeat(model.dop, Hp)
57+
Yop, Dop = repeat(model.yop, Hp), repeat(model.dop, Hp)
58+
nvar = size(Ẽ, 2)
6059
ΔŨ = zeros(nvar)
6160
mpc = new(
6261
estim, optim, con,
@@ -67,14 +66,9 @@ struct NonLinMPC{S<:StateEstimator, JEFunc<:Function} <: PredictiveController
6766
Ẽ, F, G, J, Kd, Q, P̃, q̃,
6867
Ks, Ps,
6968
d0, D̂0,
70-
Uop, Yop, Dop,
69+
Yop, Dop,
7170
)
72-
@variable(optim, ΔŨ[1:nvar])
73-
A = con.A[con.i_b, :]
74-
b = con.b[con.i_b]
75-
@constraint(optim, linconstraint, A*ΔŨ .≤ b)
76-
init_nonlinprog!(mpc, model)
77-
set_silent(optim)
71+
init_optimization!(mpc)
7872
return mpc
7973
end
8074
end
@@ -194,10 +188,23 @@ function NonLinMPC(
194188
end
195189

196190

197-
function init_nonlinprog!(mpc::NonLinMPC, model::SimModel)
191+
"""
192+
init_optimization!(mpc::NonLinMPC)
193+
194+
Init the nonlinear optimization for [`NonLinMPC`](@ref) controllers.
195+
"""
196+
function init_optimization!(mpc::NonLinMPC)
197+
# --- variables and linear constraints ---
198198
optim, con = mpc.optim, mpc.con
199-
ΔŨvar = optim[:ΔŨ]
200-
nvar = length(ΔŨvar)
199+
nvar = length(mpc.ΔŨ)
200+
set_silent(optim)
201+
@variable(optim, ΔŨvar[1:nvar])
202+
ΔŨvar = optim[:ΔŨvar]
203+
A = con.A[con.i_b, :]
204+
b = con.b[con.i_b]
205+
@constraint(optim, linconstraint, A*ΔŨvar .≤ b)
206+
# --- nonlinear optimization init ---
207+
model = mpc.estim.model
201208
last_ΔŨtup, C, Ŷ = nothing, nothing, nothing
202209
last_dΔŨtup, dC, dŶ = nothing, nothing, nothing
203210
function Jfunc(ΔŨtup::Float64...)
@@ -250,6 +257,7 @@ function init_nonlinprog!(mpc::NonLinMPC, model::SimModel)
250257
sym = Symbol("C_Ŷmax_$i")
251258
register(optim, sym, nvar, Cfunc[n + i], autodiff=true)
252259
end
260+
return nothing
253261
end
254262

255263

@@ -259,24 +267,20 @@ setnontlincon!(::NonLinMPC, ::LinModel) = nothing
259267
"Set the nonlinear constraints on the output predictions `Ŷ`."
260268
function setnonlincon!(mpc::NonLinMPC, model::NonLinModel)
261269
optim = mpc.optim
262-
ΔŨ = mpc.optim[:ΔŨ]
270+
ΔŨvar = mpc.optim[:ΔŨvar]
263271
con = mpc.con
264272
map(con -> delete(optim, con), all_nonlinear_constraints(optim))
265273
for i in findall(.!isinf.(con.Ŷmin))
266274
f_sym = Symbol("C_Ŷmin_$(i)")
267-
add_nonlinear_constraint(optim, :($(f_sym)($(ΔŨ...)) <= 0))
275+
add_nonlinear_constraint(optim, :($(f_sym)($(ΔŨvar...)) <= 0))
268276
end
269277
for i in findall(.!isinf.(con.Ŷmax))
270278
f_sym = Symbol("C_Ŷmax_$(i)")
271-
add_nonlinear_constraint(optim, :($(f_sym)($(ΔŨ...)) <= 0))
279+
add_nonlinear_constraint(optim, :($(f_sym)($(ΔŨvar...)) <= 0))
272280
end
273281
return nothing
274282
end
275283

276-
"Nonlinear programming objective does not require any initialization."
277-
init_objective!(mpc::NonLinMPC, _ ) = nothing
278-
279-
280284
"""
281285
obj_nonlinprog(mpc::NonLinMPC, model::LinModel, ΔŨ::Vector{Real})
282286

src/predictive_control.jl

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -183,15 +183,15 @@ function setconstraint!(
183183
)
184184
A = con.A[con.i_b, :]
185185
b = con.b[con.i_b]
186-
ΔŨ = mpc.optim[:ΔŨ]
186+
ΔŨvar = mpc.optim[:ΔŨvar]
187187
delete(mpc.optim, mpc.optim[:linconstraint])
188188
unregister(mpc.optim, :linconstraint)
189-
@constraint(mpc.optim, linconstraint, A*ΔŨ .≤ b)
189+
@constraint(mpc.optim, linconstraint, A*ΔŨvar .≤ b)
190190
setnonlincon!(mpc, model)
191191
return mpc
192192
end
193193

194-
"By default, there is no nonlinear constraint"
194+
"By default, there is no nonlinear constraint, thus do nothing."
195195
setnonlincon!(::PredictiveController, ::SimModel) = nothing
196196

197197
@doc raw"""
@@ -448,14 +448,14 @@ Optimize the objective function ``J`` of `mpc` controller.
448448
function optim_objective!(mpc::PredictiveController, p)
449449
optim = mpc.optim
450450
model = mpc.estim.model
451-
ΔŨ::Vector{VariableRef} = optim[:ΔŨ]
451+
ΔŨvar::Vector{VariableRef} = optim[:ΔŨvar]
452452
lastΔŨ = mpc.ΔŨ
453453
# initial ΔŨ (warm-start): [Δu_{k-1}(k); Δu_{k-1}(k+1); ... ; 0_{nu × 1}]
454454
ΔŨ0 = [lastΔŨ[(model.nu+1):(mpc.Hc*model.nu)]; zeros(model.nu)]
455455
# if soft constraints, append the last slack value ϵ_{k-1}:
456456
!isinf(mpc.C) && (ΔŨ0 = [ΔŨ0; lastΔŨ[end]])
457-
set_start_value.(ΔŨ, ΔŨ0)
458-
init_objective!(mpc, ΔŨ)
457+
set_start_value.(ΔŨvar, ΔŨ0)
458+
set_objective!(mpc, ΔŨvar)
459459
try
460460
optimize!(optim)
461461
catch err
@@ -472,11 +472,13 @@ function optim_objective!(mpc::PredictiveController, p)
472472
@warn "MPC termination status not OPTIMAL or LOCALLY_SOLVED ($status)"
473473
@debug solution_summary(optim)
474474
end
475-
mpc.ΔŨ[:] = isfatal(status) ? ΔŨ0 : value.(ΔŨ) # fatal status : use last value
475+
mpc.ΔŨ[:] = isfatal(status) ? ΔŨ0 : value.(ΔŨvar) # fatal status : use last value
476476
J_val = objective_value(optim) + p # add LinModel p constant (p=0 for NonLinModel)
477477
return mpc.ΔŨ, J_val
478478
end
479479

480+
"By default, no change to the objective function."
481+
set_objective!(::PredictiveController, _ ) = nothing
480482

481483
"Evaluate current output of `InternalModel` estimator."
482484
evalŷ!(estim::InternalModel, ym, d) = (mpc.ŷ[:] = estim(ym, d))

0 commit comments

Comments
 (0)