@@ -115,7 +115,7 @@ struct LinMPC{S<:StateEstimator} <: PredictiveController
115115 i_nonInf = .! isinf .(b)
116116 A = A[i_nonInf, :]
117117 b = b[i_nonInf]
118- @constraint (optim, constraint_lin , A* ΔŨ .≤ b)
118+ @constraint (optim, linconstraint , A* ΔŨ .≤ b)
119119 ΔŨ0 = zeros (nvar)
120120 ϵ = isinf (C) ? NaN : 0.0 # C = Inf means hard constraints only
121121 u, U = copy (model. uop), repeat (model. uop, Hp)
263263
264264
265265
266- struct NonLinMPC{S<: StateEstimator } <: PredictiveController
266+ struct NonLinMPC{S<: StateEstimator , JEFunc <: Function } <: PredictiveController
267267 estim:: S
268268 optim:: JuMP.Model
269269 info:: OptimInfo
@@ -274,6 +274,7 @@ struct NonLinMPC{S<:StateEstimator} <: PredictiveController
274274 L_Hp:: Diagonal{Float64, Vector{Float64}}
275275 C:: Float64
276276 E:: Float64
277+ JE:: JEFunc
277278 R̂u:: Vector{Float64}
278279 Umin :: Vector{Float64}
279280 Umax :: Vector{Float64}
@@ -306,9 +307,9 @@ struct NonLinMPC{S<:StateEstimator} <: PredictiveController
306307 Ps:: Matrix{Float64}
307308 Yop:: Vector{Float64}
308309 Dop:: Vector{Float64}
309- function NonLinMPC {S} (
310- estim:: S , Hp, Hc, Mwt, Nwt, Lwt, Cwt, Ewt, J_E , ru, optim
311- ) where {S<: StateEstimator }
310+ function NonLinMPC {S, JEFunc } (
311+ estim:: S , Hp, Hc, Mwt, Nwt, Lwt, Cwt, Ewt, JE :: JEFunc , ru, optim
312+ ) where {S<: StateEstimator , JEFunc <: Function }
312313 model = estim. model
313314 nu, ny = model. nu, model. ny
314315 validate_weights (model, Hp, Hc, Mwt, Nwt, Lwt, Cwt, ru, Ewt)
@@ -345,7 +346,7 @@ struct NonLinMPC{S<:StateEstimator} <: PredictiveController
345346 # i_nonInf = .!isinf.(b)
346347 # A = A[i_nonInf, :]
347348 # b = b[i_nonInf]
348- # @constraint(optim, constraint_lin , A*ΔŨ .≤ b)
349+ # @constraint(optim, linconstraint , A*ΔŨ .≤ b)
349350 ΔŨ0 = zeros (nvar)
350351 ϵ = isinf (C) ? NaN : 0.0 # C = Inf means hard constraints only
351352 u, U = copy (model. uop), repeat (model. uop, Hp)
@@ -355,7 +356,7 @@ struct NonLinMPC{S<:StateEstimator} <: PredictiveController
355356 return new (
356357 estim, optim, info,
357358 Hp, Hc,
358- M_Hp, Ñ_Hc, L_Hp, Cwt, Ewt, R̂u,
359+ M_Hp, Ñ_Hc, L_Hp, Cwt, Ewt, JE, R̂u,
359360 Umin, Umax, ΔŨmin, ΔŨmax, Ŷmin, Ŷmax,
360361 c_Umin, c_Umax, c_ΔUmin, c_ΔUmax, c_Ŷmin, c_Ŷmax,
361362 S̃_Hp, T_Hp, S̃_Hc, T_Hc,
@@ -390,8 +391,10 @@ the manipulated inputs, the predicted outputs and measured disturbances from ``k
390391 \m athbf{Ŷ}_E = \b egin{bmatrix} \m athbf{ŷ}(k) \\ \m athbf{Ŷ} \e nd{bmatrix} \t ext{,} \q quad
391392 \m athbf{D̂}_E = \b egin{bmatrix} \m athbf{d}(k) \\ \m athbf{D̂} \e nd{bmatrix}
392393```
394+ since ``H_c ≤ H_p`` implies that ``\m athbf{u}(k+H_p) = \m athbf{u}(k+H_p-1)``.
395+
393396!!! tip
394- Replace any of the 3 arguments with `_` if not needed (see `J_E ` default value below).
397+ Replace any of the 3 arguments with `_` if not needed (see `JE ` default value below).
395398
396399This method uses the default state estimator, an [`UnscentedKalmanFilter`](@ref) with
397400default arguments.
@@ -405,7 +408,7 @@ default arguments.
405408- `Lwt=fill(0.0,model.nu)` : main diagonal of ``\m athbf{L}`` weight matrix (vector)
406409- `Cwt=1e5` : slack variable weight ``C`` (scalar), use `Cwt=Inf` for hard constraints only
407410- `Ewt=1.0` : economic costs weight ``E`` (scalar).
408- - `J_E =(_,_,_)->0.0` : economic function ``J_E(\m athbf{U}_E, \m athbf{D̂}_E, \m athbf{Ŷ}_E)``.
411+ - `JE =(_,_,_)->0.0` : economic function ``J_E(\m athbf{U}_E, \m athbf{D̂}_E, \m athbf{Ŷ}_E)``.
409412- `ru=model.uop` : manipulated input setpoints ``\m athbf{r_u}`` (vector)
410413- `optim=JuMP.Model(Ipopt.Optimizer)` : nonlinear optimizer used in the predictive
411414 controller, provided as a [`JuMP.Model`](https://jump.dev/JuMP.jl/stable/reference/models/#JuMP.Model)
@@ -461,11 +464,11 @@ function NonLinMPC(
461464 Lwt = fill (0.0 , estim. model. nu),
462465 Cwt = 1e5 ,
463466 Ewt = 1.0 ,
464- J_E = (_,_,_) -> 0.0 ,
467+ JE :: JEFunc = (_,_,_) -> 0.0 ,
465468 ru = estim. model. uop,
466469 optim:: JuMP.Model = JuMP. Model (OSQP. MathOptInterfaceOSQP. Optimizer)
467- ) where {S<: StateEstimator }
468- return NonLinMPC {S} (estim, Hp, Hc, Mwt, Nwt, Lwt, Cwt, Ewt, J_E , ru, optim)
470+ ) where {S<: StateEstimator , JEFunc <: Function }
471+ return NonLinMPC {S, JEFunc } (estim, Hp, Hc, Mwt, Nwt, Lwt, Cwt, Ewt, JE , ru, optim)
469472end
470473
471474@doc raw """
@@ -611,9 +614,9 @@ function setconstraint!(
611614 A = A[i_nonInf, :]
612615 b = b[i_nonInf]
613616 ΔŨ = mpc. optim[:ΔŨ ]
614- delete (mpc. optim, mpc. optim[:constraint_lin ])
615- unregister (mpc. optim, :constraint_lin )
616- @constraint (mpc. optim, constraint_lin , A* ΔŨ .≤ b)
617+ delete (mpc. optim, mpc. optim[:linconstraint ])
618+ unregister (mpc. optim, :linconstraint )
619+ @constraint (mpc. optim, linconstraint , A* ΔŨ .≤ b)
617620 return mpc
618621end
619622
@@ -674,12 +677,12 @@ function moveinput!(
674677 R̂y:: Vector{<:Real} = repeat (ry, mpc. Hp),
675678 D̂ :: Vector{<:Real} = repeat (d, mpc. Hp),
676679 ym:: Union{Vector{<:Real}, Nothing} = nothing
677- ) where {C<: PredictiveController }
680+ ) where {C<: PredictiveController }
678681 lastu = mpc. info. u
679682 x̂d, x̂s = split_state (mpc. estim)
680683 ŷs, Ŷs = predict_stoch (mpc, mpc. estim, x̂s, d, ym)
681684 F, q̃, p = init_prediction (mpc, mpc. estim. model, d, D̂, Ŷs, R̂y, x̂d, lastu)
682- b = init_constraint (mpc, mpc. estim. model, F, lastu )
685+ b, _ = init_constraint (mpc, mpc. estim. model, lastu, F )
683686 ΔŨ, J = optim_objective! (mpc, b, q̃, p)
684687 write_info! (mpc, ΔŨ, J, ŷs, Ŷs, lastu, F, ym, d)
685688 Δu = ΔŨ[1 : mpc. estim. model. nu] # receding horizon principle: only Δu(k) is used (1st one)
@@ -760,7 +763,9 @@ Init linear model prediction matrices `F`, `q̃` and `p`.
760763
761764See [`init_deterpred`](@ref) and [`init_quadprog`](@ref) for the definition of the matrices.
762765"""
763- function init_prediction (mpc, model:: LinModel , d, D̂, Ŷs, R̂y, x̂d, lastu)
766+ function init_prediction (
767+ mpc:: C , model:: LinModel , d, D̂, Ŷs, R̂y, x̂d, lastu
768+ ) where {C<: PredictiveController }
764769 F = mpc. Kd* x̂d + mpc. Q* (lastu - model. uop) + Ŷs + mpc. Yop
765770 if model. nd ≠ 0
766771 F += mpc. G* (d - model. dop) + mpc. J* (D̂ - mpc. Dop)
@@ -778,11 +783,11 @@ end
778783
779784
780785@doc raw """
781- init_constraint(mpc, ::LinModel, F)
786+ init_constraint(mpc::PredictiveController , ::LinModel, lastu , F)
782787
783788Init `b` vector for the linear model inequality constraints (``\m athbf{A ΔŨ ≤ b}``).
784789"""
785- function init_constraint (mpc:: C , :: LinModel , F, lastu ) where {C<: PredictiveController }
790+ function init_constraint (mpc:: C , :: LinModel , lastu, F ) where {C<: PredictiveController }
786791 b = [
787792 - mpc. Umin + mpc. T_Hc* lastu
788793 + mpc. Umax - mpc. T_Hc* lastu
@@ -793,7 +798,24 @@ function init_constraint(mpc::C, ::LinModel, F, lastu) where {C<:PredictiveContr
793798 ]
794799 i_nonInf = .! isinf .(b)
795800 b = b[i_nonInf]
796- return b
801+ return b, i_nonInf
802+ end
803+
804+ @doc raw """
805+ init_constraint(mpc::PredictiveController, ::NonLinModel, lastu)
806+
807+ Init `b` without predicted output ``\m athbf{Ŷ}`` constraints for [`NonLinModel`](@ref).
808+ """
809+ function init_constraint (mpc:: C , :: NonLinModel , lastu, _ ) where {C<: PredictiveController }
810+ b = [
811+ - mpc. Umin + mpc. T_Hc* lastu
812+ + mpc. Umax - mpc. T_Hc* lastu
813+ - mpc. ΔŨmin
814+ + mpc. ΔŨmax
815+ ]
816+ i_nonInf = .! isinf .(b)
817+ b = b[i_nonInf]
818+ return b, i_nonInf
797819end
798820
799821"""
@@ -807,7 +829,7 @@ function optim_objective!(mpc::LinMPC, b, q̃, p)
807829 ΔŨ = optim[:ΔŨ ]
808830 lastΔŨ = mpc. info. ΔŨ
809831 set_objective_function (optim, obj_quadprog (ΔŨ, mpc. P̃, q̃))
810- set_normalized_rhs .(optim[:constraint_lin ], b)
832+ set_normalized_rhs .(optim[:linconstraint ], b)
811833 # initial ΔŨ (warm-start): [Δu_{k-1}(k); Δu_{k-1}(k+1); ... ; 0_{nu × 1}]
812834 ΔŨ0 = [lastΔŨ[(model. nu+ 1 ): (mpc. Hc* model. nu)]; zeros (model. nu)]
813835 # if soft constraints, append the last slack value ϵ_{k-1}:
@@ -1120,8 +1142,8 @@ function relaxŶ(::LinModel, C, c_Ŷmin, c_Ŷmax, E)
11201142 return A_Ŷmin, A_Ŷmax, Ẽ
11211143end
11221144
1123- " Return empty matrices for models different than [`LinModel `](@ref)"
1124- function relaxŶ (:: SimModel , C, c_Ŷmin, c_Ŷmax, E)
1145+ " Return empty matrices if model is a [`NonLinModel `](@ref)"
1146+ function relaxŶ (:: NonLinModel , C, c_Ŷmin, c_Ŷmax, E)
11251147 Ẽ = ! isinf (C) ? [E zeros (0 , 1 )] : E
11261148 A_Ŷmin, A_Ŷmax = Ẽ, Ẽ
11271149 return A_Ŷmin, A_Ŷmax, Ẽ
0 commit comments