@@ -18,7 +18,8 @@ results ``\mathbf{u}(k)``. Following the receding horizon principle, the algorit
1818the optimal future manipulated inputs ``\m athbf{u}(k+1), \m athbf{u}(k+2), ...`` Note that
1919the method mutates `mpc` internal data but it does not modifies `mpc.estim` states. Call
2020[`preparestate!(mpc, ym, d)`](@ref) before `moveinput!`, and [`updatestate!(mpc, u, ym, d)`](@ref)
21- after, to update `mpc` state estimates.
21+ after, to update `mpc` state estimates. Setpoint and measured disturbance previews can
22+ be implemented with the `R̂y`, `R̂u` and `D̂` keyword arguments.
2223
2324Calling a [`PredictiveController`](@ref) object calls this method.
2425
@@ -35,8 +36,8 @@ See also [`LinMPC`](@ref), [`ExplicitMPC`](@ref), [`NonLinMPC`](@ref).
3536 in the future by default or ``\m athbf{d̂}(k+j)=\m athbf{d}(k)`` for ``j=1`` to ``H_p``.
3637- `R̂y=repeat(ry, mpc.Hp)` or *`Rhaty`* : predicted output setpoints ``\m athbf{R̂_y}``, constant
3738 in the future by default or ``\m athbf{r̂_y}(k+j)=\m athbf{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 ``\m athbf{r̂_u}(k+j)=\m athbf{u_{op}}`` for ``j=0`` to ``H_p-1``.
39+ - `R̂u=mpc.Uop` or *`Rhatu`* : predicted manipulated input setpoints `` \m athbf{R̂_u}`` , constant
40+ in the future by default or ``\m athbf{r̂_u}(k+j)=\m athbf{u_{op}}`` for ``j=0`` to ``H_p-1``.
4041
4142# Examples
4243```jldoctest
@@ -53,8 +54,8 @@ function moveinput!(
5354 mpc:: PredictiveController ,
5455 ry:: Vector = mpc. estim. model. yop,
5556 d :: Vector = mpc. buffer. empty;
56- Dhat :: Vector = repeat! (mpc. buffer. D̂, d, mpc. Hp),
57- Rhaty:: Vector = repeat! (mpc. buffer. R̂y , ry, mpc. Hp),
57+ Dhat :: Vector = repeat! (mpc. buffer. D̂, d, mpc. Hp),
58+ Rhaty:: Vector = repeat! (mpc. buffer. Ŷ , ry, mpc. Hp),
5859 Rhatu:: Vector = mpc. Uop,
5960 D̂ = Dhat,
6061 R̂y = Rhaty,
@@ -127,9 +128,9 @@ function getinfo(mpc::PredictiveController{NT}) where NT<:Real
127128 Ŷ = Ȳ
128129 Ŷ .= @views Ŷe[model. ny+ 1 : end ]
129130 oldF = copy (mpc. F)
130- predictstoch! (mpc, mpc. estim)
131- Ŷs .= mpc . F # predictstoch! init mpc.F with Ŷs value if estim is an InternalModel
132- mpc . F .= oldF # restore old F value
131+ F = predictstoch! (mpc, mpc. estim)
132+ Ŷs .= F # predictstoch! init mpc.F with Ŷs value if estim is an InternalModel
133+ F .= oldF # restore old F value
133134 info[:ΔU ] = mpc. ΔŨ[1 : mpc. Hc* model. nu]
134135 info[:ϵ ] = mpc. nϵ == 1 ? mpc. ΔŨ[end ] : zero (NT)
135136 info[:J ] = J
@@ -189,36 +190,26 @@ They are computed with these equations using in-place operations:
189190```
190191"""
191192function initpred! (mpc:: PredictiveController , model:: LinModel , d, D̂, R̂y, R̂u)
192- lastu = mpc. buffer. u
193- lastu .= mpc. estim. lastu0 .+ model. uop
194- mul! (mpc. T_lastu, mpc. T, lastu)
195- ŷ, F, q̃, r = mpc. ŷ, mpc. F, mpc. q̃, mpc. r
196- Cy, Cu, M_Hp_Ẽ, L_Hp_S̃ = mpc. buffer. Ŷ, mpc. buffer. U, mpc. buffer. Ẽ, mpc. buffer. S̃
197- ŷ .= evaloutput (mpc. estim, d)
198- predictstoch! (mpc, mpc. estim) # init F with Ŷs for InternalModel
193+ F = initpred_common! (mpc, model, d, D̂, R̂y, R̂u)
199194 F .+ = mpc. B # F = F + B
200195 mul! (F, mpc. K, mpc. estim. x̂0, 1 , 1 ) # F = F + K*x̂0
201196 mul! (F, mpc. V, mpc. estim. lastu0, 1 , 1 ) # F = F + V*lastu0
202197 if model. nd ≠ 0
203- mpc. d0 .= d .- model. dop
204- mpc. D̂0 .= D̂ .- mpc. Dop
205- mpc. D̂e[1 : model. nd] .= d
206- mpc. D̂e[model. nd+ 1 : end ] .= D̂
207198 mul! (F, mpc. G, mpc. d0, 1 , 1 ) # F = F + G*d0
208199 mul! (F, mpc. J, mpc. D̂0, 1 , 1 ) # F = F + J*D̂0
209200 end
201+ Cy, Cu, M_Hp_Ẽ, L_Hp_S̃ = mpc. buffer. Ŷ, mpc. buffer. U, mpc. buffer. Ẽ, mpc. buffer. S̃
202+ q̃, r = mpc. q̃, mpc. r
210203 q̃ .= 0
211204 r .= 0
212205 # --- output setpoint tracking term ---
213- mpc. R̂y .= R̂y
214206 if ! mpc. weights. iszero_M_Hp[]
215207 Cy .= F .+ mpc. Yop .- R̂y
216208 mul! (M_Hp_Ẽ, mpc. weights. M_Hp, mpc. Ẽ)
217209 mul! (q̃, M_Hp_Ẽ' , Cy, 1 , 1 ) # q̃ = q̃ + M_Hp*Ẽ'*Cy
218210 r .+ = dot (Cy, mpc. weights. M_Hp, Cy) # r = r + Cy'*M_Hp*Cy
219211 end
220212 # --- input setpoint tracking term ---
221- mpc. R̂u .= R̂u
222213 if ! mpc. weights. iszero_L_Hp[]
223214 Cu .= mpc. T_lastu .- R̂u
224215 mul! (L_Hp_S̃, mpc. weights. L_Hp, mpc. S̃)
@@ -236,11 +227,23 @@ end
236227Init `ŷ, F, d0, D̂0, D̂e, R̂y, R̂u` vectors when model is not a [`LinModel`](@ref).
237228"""
238229function initpred! (mpc:: PredictiveController , model:: SimModel , d, D̂, R̂y, R̂u)
230+ F = initpred_common! (mpc, model, d, D̂, R̂y, R̂u)
231+ return nothing
232+ end
233+
234+ """
235+ initpred_common!(mpc::PredictiveController, model::SimModel, d, D̂, R̂y, R̂u) -> F
236+
237+ Common computations of `initpred!` for all types of [`SimModel`](@ref).
238+
239+ Will init `mpc.F` with 0 values, or with the stochastic predictions `Ŷs` if `mpc.estim` is
240+ an [`InternalModel`](@ref). The function returns `mpc.F`.
241+ """
242+ function initpred_common! (mpc:: PredictiveController , model:: SimModel , d, D̂, R̂y, R̂u)
239243 lastu = mpc. buffer. u
240244 lastu .= mpc. estim. lastu0 .+ model. uop
241245 mul! (mpc. T_lastu, mpc. T, lastu)
242246 mpc. ŷ .= evaloutput (mpc. estim, d)
243- predictstoch! (mpc, mpc. estim) # init F with Ŷs for InternalModel
244247 if model. nd ≠ 0
245248 mpc. d0 .= d .- model. dop
246249 mpc. D̂0 .= D̂ .- mpc. Dop
@@ -249,22 +252,23 @@ function initpred!(mpc::PredictiveController, model::SimModel, d, D̂, R̂y, R̂
249252 end
250253 mpc. R̂y .= R̂y
251254 mpc. R̂u .= R̂u
252- return nothing
255+ F = predictstoch! (mpc, mpc. estim) # init mpc.F with Ŷs for InternalModel
256+ return F
253257end
254258
255259@doc raw """
256- predictstoch!(mpc::PredictiveController, estim::InternalModel)
260+ predictstoch!(mpc::PredictiveController, estim::InternalModel) -> F
257261
258262Init `mpc.F` vector with ``\m athbf{F = Ŷ_s}`` when `estim` is an [`InternalModel`](@ref).
259263"""
260- function predictstoch! (mpc:: PredictiveController{NT} , estim:: InternalModel ) where {NT <: Real }
264+ function predictstoch! (mpc:: PredictiveController , estim:: InternalModel )
261265 Ŷs = mpc. F
262266 mul! (Ŷs, mpc. Ks, estim. x̂s)
263267 mul! (Ŷs, mpc. Ps, estim. ŷs, 1 , 1 )
264- return nothing
268+ return mpc . F
265269end
266270" Separate stochastic predictions are not needed if `estim` is not [`InternalModel`](@ref)."
267- predictstoch! (mpc:: PredictiveController , :: StateEstimator ) = (mpc. F .= 0 ; nothing )
271+ predictstoch! (mpc:: PredictiveController , :: StateEstimator ) = (mpc. F .= 0 )
268272
269273@doc raw """
270274 linconstraint!(mpc::PredictiveController, model::LinModel)
@@ -320,7 +324,7 @@ function linconstraint!(mpc::PredictiveController, ::SimModel)
320324 mpc. con. b[(n+ 1 ): (n+ nΔŨ)] .= @. + mpc. con. ΔŨmax
321325 if any (mpc. con. i_b)
322326 lincon = mpc. optim[:linconstraint ]
323- JuMP. set_normalized_rhs (lincon, mpc. con. b[mpc. con. i_b])
327+ @views JuMP. set_normalized_rhs (lincon, mpc. con. b[mpc. con. i_b])
324328 end
325329 return nothing
326330end
@@ -476,12 +480,14 @@ solution. A failed optimization prints an `@error` log in the REPL and returns t
476480warm-start value.
477481"""
478482function optim_objective! (mpc:: PredictiveController{NT} ) where {NT<: Real }
479- optim = mpc. optim
480- model = mpc. estim . model
483+ model, optim = mpc . estim . model, mpc. optim
484+ nu, Hc = model . nu, mpc. Hc
481485 ΔŨvar:: Vector{JuMP.VariableRef} = optim[:ΔŨvar ]
482486 # initial ΔŨ (warm-start): [Δu_{k-1}(k); Δu_{k-1}(k+1); ... ; 0_{nu × 1}; ϵ_{k-1}]
483- ϵ0 = (mpc. nϵ == 1 ) ? mpc. ΔŨ[end ] : empty (mpc. ΔŨ)
484- ΔŨ0 = [mpc. ΔŨ[(model. nu+ 1 ): (mpc. Hc* model. nu)]; zeros (NT, model. nu); ϵ0]
487+ ΔŨ0 = mpc. buffer. ΔŨ
488+ ΔŨ0[1 : (Hc* nu- nu)] .= @views mpc. ΔŨ[nu+ 1 : Hc* nu]
489+ ΔŨ0[(Hc* nu- nu+ 1 ): (Hc* nu)] .= 0
490+ mpc. nϵ == 1 && (ΔŨ0[end ] = mpc. ΔŨ[end ])
485491 JuMP. set_start_value .(ΔŨvar, ΔŨ0)
486492 set_objective_linear_coef! (mpc, ΔŨvar)
487493 try
0 commit comments