@@ -9,13 +9,15 @@ import ModelPredictiveControl: isblockdiag
99
1010function Base. convert (:: Type{LinearMPC.MPC} , mpc:: ModelPredictiveControl.LinMPC )
1111 model, estim, weights = mpc. estim. model, mpc. estim, mpc. weights
12- nu, ny, nd, nx̂ = model. nu, model. ny, model. nd, estim. nx̂
12+ nu, ny, nx̂ = model. nu, model. ny, estim. nx̂
13+ Hp, Hc = mpc. Hp, mpc. Hc
14+ nΔU = Hc * nu
1315 validate_compatibility (mpc)
1416 # --- Model parameters ---
1517 F, G, Gd = estim. Â, estim. B̂u, estim. B̂d
1618 C, Dd = estim. Ĉ, estim. D̂d
17- Np = Hp = mpc . Hp
18- Nc = Hc = mpc . Hc
19+ Np = Hp
20+ Nc = Hc
1921 newmpc = LinearMPC. MPC (F, G; Gd, C, Dd, Np, Nc)
2022 # --- Operating points ---
2123 uoff = model. uop
@@ -33,19 +35,29 @@ function Base.convert(::Type{LinearMPC.MPC}, mpc::ModelPredictiveControl.LinMPC)
3335 Rr = weights. Ñ_Hc[1 : nu, 1 : nu]
3436 R = weights. L_Hp[1 : nu, 1 : nu]
3537 LinearMPC. set_objective! (newmpc; Q, Rr, R, Qf)
38+ # --- Custom move blocking ---
39+ LinearMPC. move_block! (newmpc, mpc. nb) # un-comment when debugged
40+ # ---- Constraint softening ---
3641 only_hard = weights. isinf_C
3742 if ! only_hard
3843 # LinearMPC relies on a different softening mechanism, so we apply
39- # an approximate conversion factor on the softening weight:
44+ # an approximate conversion factor on the softening weight Cwt:
45+ nsoft = sum ((mpc. con. A[:,end ] .< 0 ) .& (mpc. con. i_b)) - 1
46+ conversion_factor = 1 / 2 / nsoft
4047 Cwt = weights. Ñ_Hc[end , end ]
41- conversion_factor = 0.1 # 0.09066
4248 newmpc. settings. soft_weight = conversion_factor* Cwt
49+ C_u = - mpc. con. A_Umin[:, end ]
50+ C_Δu = - mpc. con. A_ΔŨmin[1 : nΔU, end ]
51+ C_y = - mpc. con. A_Ymin[:, end ]
52+ c_x̂ = - mpc. con. A_x̂min[:, end ]
53+ else
54+ C_u = zeros (nu* Hp)
55+ C_Δu = zeros (nu* Hc)
56+ C_y = zeros (ny* Hp)
57+ c_x̂ = zeros (nx̂)
4358 end
44- # --- Custom move blocking ---
45- LinearMPC. move_block! (newmpc, mpc. nb) # un-comment when debugged
4659 # --- Manipulated inputs constraints ---
4760 Umin, Umax = mpc. con. U0min + mpc. Uop, mpc. con. U0max + mpc. Uop
48- C_u = - mpc. con. A_Umin[:, end ]
4961 I_u = Matrix {Float64} (I, nu, nu)
5062 # add_constraint! does not support u bounds pass the control horizon Hc
5163 # so we compute the extremum bounds from k=Hc-1 to Hp, and apply them at k=Hc-1
@@ -70,9 +82,7 @@ function Base.convert(::Type{LinearMPC.MPC}, mpc::ModelPredictiveControl.LinMPC)
7082 end
7183 end
7284 # --- Input increment constraints ---
73- nΔU = Hc * nu
7485 ΔUmin, ΔUmax = mpc. con. ΔŨmin[1 : nΔU], mpc. con. ΔŨmax[1 : nΔU]
75- C_Δu = - mpc. con. A_ΔŨmin[1 : nΔU, end ]
7686 I_Δu = Matrix {Float64} (I, nu, nu)
7787 for k in 0 : Hc- 1
7888 Δumin_k, Δumax_k = ΔUmin[k* nu+ 1 : (k+ 1 )* nu], ΔUmax[k* nu+ 1 : (k+ 1 )* nu]
@@ -88,7 +98,6 @@ function Base.convert(::Type{LinearMPC.MPC}, mpc::ModelPredictiveControl.LinMPC)
8898 end
8999 # --- Output constraints ---
90100 Y0min, Y0max = mpc. con. Y0min, mpc. con. Y0max
91- C_y = - mpc. con. A_Ymin[:, end ]
92101 for k in 1 : Hp
93102 ymin_k, ymax_k = Y0min[(k- 1 )* ny+ 1 : k* ny], Y0max[(k- 1 )* ny+ 1 : k* ny]
94103 c_y_k = C_y[(k- 1 )* ny+ 1 : k* ny]
@@ -103,7 +112,6 @@ function Base.convert(::Type{LinearMPC.MPC}, mpc::ModelPredictiveControl.LinMPC)
103112 end
104113 # --- Terminal constraints ---
105114 x̂0min, x̂0max = mpc. con. x̂0min, mpc. con. x̂0max
106- c_x̂ = - mpc. con. A_x̂min[:, end ]
107115 I_x̂ = Matrix {Float64} (I, nx̂, nx̂)
108116 ks = [Hp + 1 ] # a `1` in ks argument corresponds to the present time step k+0
109117 for i in 1 : nx̂
165173
166174function validate_constraints (mpc:: ModelPredictiveControl.LinMPC )
167175 nΔU = mpc. Hc * mpc. estim. model. nu
176+ mpc. weights. isinf_C && return nothing # only hard constraints are entirely supported
168177 C_umin, C_umax = - mpc. con. A_Umin[:, end ], - mpc. con. A_Umax[:, end ]
169178 C_Δumin, C_Δumax = - mpc. con. A_ΔŨmin[1 : nΔU, end ], - mpc. con. A_ΔŨmax[1 : nΔU, end ]
170179 C_ymin, C_ymax = - mpc. con. A_Ymin[:, end ], - mpc. con. A_Ymax[:, end ]
0 commit comments