@@ -26,6 +26,8 @@ const LinConVector = Vector{ConstraintRef{
2626 ScalarShape
2727}}
2828
29+ const InfoDictType = Union{Vector{Float64}, Float64}
30+
2931" Include all the data for the constraints of [`PredictiveController`](@ref)"
3032struct ControllerConstraint
3133 Umin :: Vector{Float64}
@@ -249,17 +251,67 @@ function moveinput!(
249251 R̂y:: Vector{<:Real} = repeat (ry, mpc. Hp),
250252 D̂ :: Vector{<:Real} = repeat (d, mpc. Hp),
251253 ym:: Union{Vector{<:Real}, Nothing} = nothing
252- )
254+ )
255+ validate_setpointdist (mpc, ry, d, R̂y, D̂)
253256 getestimates! (mpc, mpc. estim, ym, d)
254257 predictstoch! (mpc, mpc. estim, d, ym)
255- p = initpred! (mpc, mpc. estim. model, d, D̂, R̂y)
258+ initpred! (mpc, mpc. estim. model, d, D̂, R̂y)
256259 linconstraint! (mpc, mpc. estim. model)
257- ΔŨ, _ = optim_objective! (mpc, p )
260+ ΔŨ = optim_objective! (mpc)
258261 Δu = ΔŨ[1 : mpc. estim. model. nu] # receding horizon principle: only Δu(k) is used (1st one)
259262 u = mpc. estim. lastu0 + mpc. estim. model. uop + Δu
260263 return u
261264end
262265
266+ #=
267+
268+
269+ "Include the additional information about the optimum to ease troubleshooting."
270+ mutable struct OptimInfo
271+ ΔŨ::Vector{Float64}
272+ ϵ ::Float64
273+ J ::Float64
274+ u ::Vector{Float64}
275+ U ::Vector{Float64}
276+ ŷ ::Vector{Float64}
277+ Ŷ ::Vector{Float64}
278+ ŷs::Vector{Float64}
279+ Ŷs::Vector{Float64}
280+ end
281+ =#
282+
283+ #=
284+ function write_info!(mpc::LinMPC, ΔŨ, J, ŷs, Ŷs)
285+ mpc.info.ΔŨ = ΔŨ
286+ mpc.info.ϵ = isinf(mpc.C) ? NaN : ΔŨ[end]
287+ mpc.info.J = J
288+ mpc.info.U = mpc.S̃_Hp*ΔŨ + mpc.T_Hp*(mpc.estim.lastu0 + mpc.estim.model.uop)
289+ mpc.info.u = mpc.info.U[1:mpc.estim.model.nu]
290+ mpc.info.ŷ = mpc.ŷ
291+ mpc.info.Ŷ = mpc.Ẽ*ΔŨ + mpc.F
292+ mpc.info.ŷs, mpc.info.Ŷs = ŷs, Ŷs
293+ end
294+ =#
295+
296+ function getinfo (mpc:: PredictiveController )
297+ sol_summary = solution_summary (mpc. optim)
298+ info = Dict {Symbol, InfoDictType} ()
299+ info[:ΔU ] = mpc. ΔŨ[1 : mpc. Hc* mpc. estim. model. nu]
300+ info[:ϵ ] = isinf (mpc. C) ? NaN : mpc. ΔŨ[end ]
301+ info[:J ] = objective_value (mpc. optim) + mpc. p[begin ]
302+ info[:U ] = mpc. S̃_Hp* mpc. ΔŨ + mpc. T_Hp* (mpc. estim. lastu0 + mpc. estim. model. uop)
303+ info[:u ] = info[:U ][1 : mpc. estim. model. nu]
304+ info[:d ] = mpc. d
305+ info[:D̂ ] = mpc. D̂
306+ info[:ŷ ] = mpc. ŷ
307+ info[:Ŷ ] = predict (mpc, mpc. estim. model, mpc. ΔŨ)
308+ info[:Ŷs ] = mpc. Ŷs
309+ info[:Ŷd ] = info[:Ŷ ] - info[:Ŷs ]
310+ info[:R̂y ] = mpc. R̂y
311+ info[:R̂u ] = mpc. R̂u
312+ return info, sol_summary
313+ end
314+
263315"""
264316 setstate!(mpc::PredictiveController, x̂)
265317
@@ -285,6 +337,13 @@ Call [`updatestate!`](@ref) on `mpc.estim` [`StateEstimator`](@ref).
285337"""
286338updatestate! (mpc:: PredictiveController , u, ym, d= Float64[]) = updatestate! (mpc. estim,u,ym,d)
287339
340+ function validate_setpointdist (mpc:: PredictiveController , ry, d, R̂y, D̂)
341+ ny, nd, Hp = mpc. estim. model. ny, mpc. estim. model. nd, mpc. Hp
342+ size (ry) ≠ (ny,) && error (" ry size $(size (ry)) ≠ output size ($ny ,)" )
343+ size (d) ≠ (nd,) && error (" d size $(size (d)) ≠ measured dist. size ($nd ,)" )
344+ size (R̂y) ≠ (ny* Hp,) && error (" R̂y size $(size (R̂y)) ≠ output size × Hp ($(ny* Hp) ,)" )
345+ size (D̂) ≠ (nd* Hp,) && error (" D̂ size $(size (D̂)) ≠ measured dist. size × Hp ($(nd* Hp) ,)" )
346+ end
288347
289348"""
290349 getestimates!(mpc::PredictiveController, estim::StateEstimator)
@@ -355,14 +414,14 @@ function initpred!(mpc::PredictiveController, model::LinModel, d, D̂, R̂y)
355414 mpc. R̂y[:] = R̂y
356415 Ẑ = mpc. F - R̂y
357416 mpc. q̃[:] = 2 (mpc. M_Hp* mpc. Ẽ)' * Ẑ
358- p = Ẑ' * mpc. M_Hp* Ẑ
417+ mpc . p[:] = [ Ẑ' * mpc. M_Hp* Ẑ]
359418 if ~ isempty (mpc. R̂u)
360419 lastu = mpc. estim. lastu0 + model. uop
361420 V̂ = mpc. T_Hp* lastu - mpc. R̂u
362- mpc. q̃[:] = mpc . q̃ + 2 (mpc. L_Hp* mpc. T_Hp)' * V̂
363- p += V̂' * mpc. L_Hp* V̂
421+ mpc. q̃[:] += 2 (mpc. L_Hp* mpc. T_Hp)' * V̂
422+ mpc . p[:] += [ V̂' * mpc. L_Hp* V̂]
364423 end
365- return p
424+ return nothing
366425end
367426
368427@doc raw """
@@ -378,8 +437,7 @@ function initpred!(mpc::PredictiveController, model::SimModel, d, D̂, R̂y)
378437 mpc. d[:], mpc. D̂[:] = d, D̂
379438 end
380439 mpc. R̂y[:] = R̂y
381- p = 0.0 # only used for LinModel objects
382- return p
440+ return nothing
383441end
384442
385443"""
448506
449507Optimize the objective function ``J`` of `mpc` controller.
450508"""
451- function optim_objective! (mpc:: PredictiveController , p )
509+ function optim_objective! (mpc:: PredictiveController )
452510 optim = mpc. optim
453511 model = mpc. estim. model
454512 ΔŨvar:: Vector{VariableRef} = optim[:ΔŨvar ]
@@ -476,8 +534,7 @@ function optim_objective!(mpc::PredictiveController, p)
476534 @debug solution_summary (optim)
477535 end
478536 mpc. ΔŨ[:] = isfatal (status) ? ΔŨ0 : value .(ΔŨvar) # fatal status : use last value
479- J_val = objective_value (optim) + p # add LinModel p constant (p=0 for NonLinModel)
480- return mpc. ΔŨ, J_val
537+ return mpc. ΔŨ
481538end
482539
483540" By default, no change to the objective function."
@@ -653,14 +710,16 @@ useless at optimization but required to evaluate the minimal ``J`` value.
653710"""
654711function init_quadprog (:: LinModel , Ẽ, S_Hp, M_Hp, N_Hc, L_Hp)
655712 P̃ = 2 * Hermitian (Ẽ' * M_Hp* Ẽ + N_Hc + S_Hp' * L_Hp* S_Hp)
656- q̃ = zeros (size (P̃, 1 )) # dummy value (updated just before optimization)
657- return P̃, q̃
713+ q̃ = zeros (size (P̃, 1 )) # dummy value (updated just before optimization)
714+ p = zeros (1 ) # dummy value (updated just before optimization)
715+ return P̃, q̃, p
658716end
659717" Return empty matrices if `model` is not a [`LinModel`](@ref)."
660718function init_quadprog (:: SimModel , Ẽ, S_Hp, M_Hp, N_Hc, L_Hp)
661719 P̃ = Hermitian (zeros (0 , 0 ))
662720 q̃ = zeros (0 )
663- return P̃, q̃
721+ p = zeros (1 ) # dummy value (updated just before optimization)
722+ return P̃, q̃, p
664723end
665724
666725" Return the quadratic programming objective function, see [`init_quadprog`](@ref)."
0 commit comments