@@ -198,7 +198,7 @@ function setconstraint!(
198198 model, con, optim = mpc. estim. model, mpc. con, mpc. optim
199199 nu, ny, nx̂, Hp, Hc = model. nu, model. ny, mpc. estim. nx̂, mpc. Hp, mpc. Hc
200200 notSolvedYet = (termination_status (optim) == OPTIMIZE_NOT_CALLED)
201- C, E, ex̂ = mpc. C, mpc. Ẽ[:, 1 : nu* Hc], mpc. ex̂
201+ C, E, ex̂ = mpc. C, mpc. Ẽ[:, 1 : nu* Hc], mpc. ẽx̂[:, 1 : nu * Hc]
202202 isnothing (Umin) && ! isnothing (umin) && (Umin = repeat (umin, Hp))
203203 isnothing (Umax) && ! isnothing (umax) && (Umax = repeat (umax, Hp))
204204 isnothing (ΔUmin) && ! isnothing (Δumin) && (ΔUmin = repeat (Δumin, Hc))
@@ -386,18 +386,19 @@ Get additional information about `mpc` controller optimum to ease troubleshootin
386386The function should be called after calling [`moveinput!`](@ref). It returns the dictionary
387387`info` with the following fields:
388388
389- - `:ΔU` : optimal manipulated input increments over `Hc` ``(\m athbf{ΔU})``
390- - `:ϵ` : optimal slack variable ``(ϵ)``
391- - `:J` : objective value optimum ``(J)``
392- - `:U` : optimal manipulated inputs over `Hp` ``(\m athbf{U})``
393- - `:u` : current optimal manipulated input ``(\m athbf{u})``
394- - `:d` : current measured disturbance ``(\m athbf{d})``
395- - `:D̂` : predicted measured disturbances over `Hp` ``(\m athbf{D̂})``
396- - `:ŷ` : current estimated output ``(\m athbf{ŷ})``
397- - `:Ŷ` : optimal predicted outputs over `Hp` ``(\m athbf{Ŷ})``
398- - `:Ŷs` : predicted stochastic output over `Hp` of [`InternalModel`](@ref) ``(\m athbf{Ŷ_s})``
399- - `:R̂y` : predicted output setpoint over `Hp` ``(\m athbf{R̂_y})``
400- - `:R̂u` : predicted manipulated input setpoint over `Hp` ``(\m athbf{R̂_u})``
389+ - `:ΔU` : optimal manipulated input increments over `Hc` ``(\m athbf{ΔU})``
390+ - `:ϵ` : optimal slack variable ``(ϵ)``
391+ - `:J` : objective value optimum ``(J)``
392+ - `:U` : optimal manipulated inputs over `Hp` ``(\m athbf{U})``
393+ - `:u` : current optimal manipulated input ``(\m athbf{u})``
394+ - `:d` : current measured disturbance ``(\m athbf{d})``
395+ - `:D̂` : predicted measured disturbances over `Hp` ``(\m athbf{D̂})``
396+ - `:ŷ` : current estimated output ``(\m athbf{ŷ})``
397+ - `:Ŷ` : optimal predicted outputs over `Hp` ``(\m athbf{Ŷ})``
398+ - `:x̂end : optimal terminal states ``(\m athbf{x̂}_{k-1}(k+H_p))``
399+ - `:Ŷs` : predicted stochastic output over `Hp` of [`InternalModel`](@ref) ``(\m athbf{Ŷ_s})``
400+ - `:R̂y` : predicted output setpoint over `Hp` ``(\m athbf{R̂_y})``
401+ - `:R̂u` : predicted manipulated input setpoint over `Hp` ``(\m athbf{R̂_u})``
401402
402403For [`LinMPC`](@ref) and [`NonLinMPC`](@ref), the field `:sol` also contains the optimizer
403404solution summary that can be printed. Lastly, the optimal economic cost `:JE` is also
@@ -416,17 +417,18 @@ julia> round.(getinfo(mpc)[:Ŷ], digits=3)
416417"""
417418function getinfo (mpc:: PredictiveController )
418419 info = Dict {Symbol, InfoDictType} ()
419- x̂, Ŷ = similar (mpc. estim. x̂), similar (mpc. Ŷop)
420- predict! (x̂, Ŷ, mpc, mpc. estim. model, mpc. ΔŨ)
421- info[:ΔU ] = mpc. ΔŨ[1 : mpc. Hc* mpc. estim. model. nu]
422- info[:ϵ ] = isinf (mpc. C) ? NaN : mpc. ΔŨ[end ]
423- info[:J ] = obj_nonlinprog (mpc, mpc. estim. model, Ŷ, mpc. ΔŨ) + mpc. p[]
424- info[:U ] = mpc. S̃* mpc. ΔŨ + mpc. T* (mpc. estim. lastu0 + mpc. estim. model. uop)
425- info[:u ] = info[:U ][1 : mpc. estim. model. nu]
426- info[:d ] = mpc. d0 + mpc. estim. model. dop
427- info[:D̂ ] = mpc. D̂0 + mpc. Dop
428- info[:ŷ ] = mpc. ŷ
429- info[:Ŷ ] = Ŷ
420+ Ŷ, x̂ = similar (mpc. Ŷop), similar (mpc. estim. x̂)
421+ Ŷ, x̂end = predict! (Ŷ, x̂, mpc, mpc. estim. model, mpc. ΔŨ)
422+ info[:ΔU ] = mpc. ΔŨ[1 : mpc. Hc* mpc. estim. model. nu]
423+ info[:ϵ ] = isinf (mpc. C) ? NaN : mpc. ΔŨ[end ]
424+ info[:J ] = obj_nonlinprog (mpc, mpc. estim. model, Ŷ, mpc. ΔŨ) + mpc. p[]
425+ info[:U ] = mpc. S̃* mpc. ΔŨ + mpc. T* (mpc. estim. lastu0 + mpc. estim. model. uop)
426+ info[:u ] = info[:U ][1 : mpc. estim. model. nu]
427+ info[:d ] = mpc. d0 + mpc. estim. model. dop
428+ info[:D̂ ] = mpc. D̂0 + mpc. Dop
429+ info[:ŷ ] = mpc. ŷ
430+ info[:Ŷ ] = Ŷ
431+ info[:x̂end ] = x̂end
430432 info[:Ŷs ] = mpc. Ŷop - repeat (mpc. estim. model. yop, mpc. Hp) # Ŷop = Ŷs + Yop
431433 info[:R̂y ] = mpc. R̂y
432434 info[:R̂u ] = mpc. R̂u
@@ -592,25 +594,27 @@ end
592594predictstoch! (:: PredictiveController , :: StateEstimator , _ , _ ) = nothing
593595
594596@doc raw """
595- predict!( _ , Ŷ , mpc::PredictiveController, model::LinModel, ΔŨ)
597+ predict!(Ŷ, x̂ , mpc::PredictiveController, model::LinModel, ΔŨ) -> Ŷ, x̂end
596598
597- Compute the outputs predictions ``\m athbf{Ŷ}`` when `model` is a [`LinModel`](@ref).
599+ Compute the predictions `Ŷ` and terminal states `x̂end` if model is a [`LinModel`](@ref).
600+
601+ The method mutates `Ŷ` and `x̂` vector arguments. The `x̂end` vector is used for
602+ the terminal constraints applied on ``\m athbf{x̂}_{k-1}(k+H_p)``.
598603"""
599- function predict! ( _ , Ŷ, mpc:: PredictiveController , :: LinModel , ΔŨ:: Vector{T} ) where {T<: Real }
600- mul! (Ŷ, mpc. Ẽ, ΔŨ) + mpc. F # in-place operations to reduce allocations
601- return nothing
604+ function predict! (Ŷ, x̂, mpc:: PredictiveController , :: LinModel , ΔŨ:: Vector{T} ) where {T<: Real }
605+ # in-place operations to reduce allocations :
606+ mul! (Ŷ, mpc. Ẽ, ΔŨ) + mpc. F
607+ mul! (x̂, mpc. ẽx̂, ΔŨ) + mpc. fx̂
608+ x̂end = x̂
609+ return Ŷ, x̂end
602610end
603611
604612@doc raw """
605- predict!(x̂, Ŷ, mpc::PredictiveController, model::SimModel, ΔŨ)
606-
607- Compute ``\m athbf{x̂}_{k-1}(k+H_p)``, ``\m athbf{Ŷ}`` if `model` is not a [`LinModel`](@ref).
613+ predict!(Ŷ, x̂, mpc::PredictiveController, model::SimModel, ΔŨ) -> Ŷ, x̂end
608614
609- The method mutates `x̂` and `Ŷ` vector arguments. After a `predict!` call, `x̂` will contain
610- the states at the end of the prediction horizon ``\m athbf{x̂}_{k-1}(k+H_p)`` (used for
611- terminal constraints).
615+ Compute both vectors if `model` is not a [`LinModel`](@ref).
612616"""
613- function predict! (x̂, Ŷ , mpc:: PredictiveController , model:: SimModel , ΔŨ:: Vector{T} ) where {T<: Real }
617+ function predict! (Ŷ, x̂ , mpc:: PredictiveController , model:: SimModel , ΔŨ:: Vector{T} ) where {T<: Real }
614618 nu, ny, nd, Hp, Hc = model. nu, model. ny, model. nd, mpc. Hp, mpc. Hc
615619 u0:: Vector{T} = copy (mpc. estim. lastu0)
616620 d0:: Vector{T} = copy (mpc. d0)
@@ -624,7 +628,8 @@ function predict!(x̂, Ŷ, mpc::PredictiveController, model::SimModel, ΔŨ::V
624628 Ŷ[(1 + ny* (j- 1 )): (ny* j)] = ĥ (mpc. estim, x̂, d0)
625629 end
626630 Ŷ[:] = Ŷ + mpc. Ŷop # Ŷop = Ŷs + Yop, and Ŷs=0 if mpc.estim is not an InternalModel
627- return nothing
631+ x̂end = x̂
632+ return Ŷ, x̂end
628633end
629634
630635@doc raw """
@@ -980,7 +985,7 @@ function init_defaultcon(estim, Hp, Hc, C, S, N_Hc, E, ex̂)
980985 A_Umin, A_Umax, S̃ = relaxU (C, c_Umin, c_Umax, S)
981986 A_ΔŨmin, A_ΔŨmax, ΔŨmin, ΔŨmax, Ñ_Hc = relaxΔU (C, c_ΔUmin, c_ΔUmax, ΔUmin, ΔUmax, N_Hc)
982987 A_Ymin, A_Ymax, Ẽ = relaxŶ (model, C, c_Ymin, c_Ymax, E)
983- A_x̂min, A_x̂max = relaxterminal (model, C, c_x̂min, c_x̂max, ex̂)
988+ A_x̂min, A_x̂max, ẽx̂ = relaxterminal (model, C, c_x̂min, c_x̂max, ex̂)
984989 i_Umin, i_Umax = .! isinf .(Umin), .! isinf .(Umax)
985990 i_ΔŨmin, i_ΔŨmax = .! isinf .(ΔŨmin), .! isinf .(ΔŨmax)
986991 i_Ymin, i_Ymax = .! isinf .(Ymin), .! isinf .(Ymax)
@@ -996,7 +1001,7 @@ function init_defaultcon(estim, Hp, Hc, C, S, N_Hc, E, ex̂)
9961001 A_Umin , A_Umax, A_ΔŨmin, A_ΔŨmax , A_Ymin, A_Ymax, A_x̂min, A_x̂max,
9971002 A , b , i_b , c_Ymin , c_Ymax, c_x̂min, c_x̂max,
9981003 )
999- return con, S̃, Ñ_Hc, Ẽ
1004+ return con, S̃, Ñ_Hc, Ẽ, ẽx̂
10001005end
10011006
10021007" Repeat predictive controller constraints over prediction `Hp` and control `Hc` horizons."
@@ -1105,7 +1110,7 @@ function relaxŶ(::LinModel, C, c_Ymin, c_Ymax, E)
11051110 if ! isinf (C) # ΔŨ = [ΔU; ϵ]
11061111 # ϵ impacts predicted output constraint calculations:
11071112 A_Ymin, A_Ymax = - [E c_Ymin], [E - c_Ymax]
1108- # ϵ has not impact on output predictions
1113+ # ϵ has no impact on output predictions
11091114 Ẽ = [E zeros (size (E, 1 ), 1 )]
11101115 else # ΔŨ = ΔU (only hard constraints)
11111116 Ẽ = E
@@ -1117,7 +1122,7 @@ end
11171122" Return empty matrices if model is not a [`LinModel`](@ref)"
11181123function relaxŶ (:: SimModel , C, c_Ymin, c_Ymax, E)
11191124 Ẽ = ! isinf (C) ? [E zeros (0 , 1 )] : E
1120- A_Ymin, A_Ymax = Ẽ, Ẽ
1125+ A_Ymin, A_Ymax = - Ẽ, Ẽ
11211126 return A_Ymin, A_Ymax, Ẽ
11221127end
11231128
@@ -1128,16 +1133,23 @@ TBW
11281133"""
11291134function relaxterminal (:: LinModel , C, c_x̂min, c_x̂max, ex̂)
11301135 if ! isinf (C) # ΔŨ = [ΔU; ϵ]
1131- # ϵ impacts predicted terminal state calculations:
1132- A_x̂min, A_x̂max = - [ex̂ c_x̂min], [ex̂ - c_x̂max]
1136+ # ϵ impacts terminal constraint calculations:
1137+ A_x̂min, A_x̂max = - [ex̂ c_x̂min], [ex̂ - c_x̂max]
1138+ # ϵ has no impact on terminal state predictions
1139+ ẽx̂ = [ex̂ zeros (size (ex̂, 1 ), 1 )]
11331140 else # ΔŨ = ΔU (only hard constraints)
1141+ ẽx̂ = ex̂
11341142 A_x̂min, A_x̂max = - ex̂, ex̂
11351143 end
1136- return A_x̂min, A_x̂max
1144+ return A_x̂min, A_x̂max, ẽx̂
11371145end
11381146
11391147" Return empty matrices if model is not a [`LinModel`](@ref)"
1140- relaxterminal (:: SimModel , C, c_x̂min, c_x̂max, ex̂) = - ex̂, ex̂
1148+ function relaxterminal (:: SimModel , C, c_x̂min, c_x̂max, ex̂)
1149+ ẽx̂ = ! isinf (C) ? [ex̂ zeros (0 , 1 )] : ex̂
1150+ A_x̂min, A_x̂max = - ẽx̂, ẽx̂
1151+ return A_x̂min, A_x̂max, ẽx̂
1152+ end
11411153
11421154
11431155@doc raw """
0 commit comments