|
211 | 211 | "Separate stochastic predictions are not needed if `estim` is not [`InternalModel`](@ref)." |
212 | 212 | predictstoch!(::PredictiveController, ::StateEstimator, _ , _ ) = nothing |
213 | 213 |
|
| 214 | +@doc raw""" |
| 215 | + linconstraint!(mpc::PredictiveController, model::LinModel) |
| 216 | +
|
| 217 | +Set `b` vector for the linear model inequality constraints (``\mathbf{A ΔŨ ≤ b}``). |
| 218 | +
|
| 219 | +Also init ``\mathbf{f_x̂}`` vector for the terminal constraints, see [`init_predmat`](@ref). |
| 220 | +""" |
| 221 | +function linconstraint!(mpc::PredictiveController, model::LinModel) |
| 222 | + mpc.con.fx̂[:] = mpc.con.kx̂ * mpc.estim.x̂ + mpc.con.vx̂ * mpc.estim.lastu0 |
| 223 | + if model.nd ≠ 0 |
| 224 | + mpc.con.fx̂[:] = mpc.con.fx̂ + mpc.con.gx̂ * mpc.d0 + mpc.con.jx̂ * mpc.D̂0 |
| 225 | + end |
| 226 | + lastu = mpc.estim.lastu0 + model.uop |
| 227 | + mpc.con.b[:] = [ |
| 228 | + -mpc.con.Umin + mpc.T*lastu |
| 229 | + +mpc.con.Umax - mpc.T*lastu |
| 230 | + -mpc.con.ΔŨmin |
| 231 | + +mpc.con.ΔŨmax |
| 232 | + -mpc.con.Ymin + mpc.F |
| 233 | + +mpc.con.Ymax - mpc.F |
| 234 | + -mpc.con.x̂min + mpc.con.fx̂ |
| 235 | + +mpc.con.x̂max - mpc.con.fx̂ |
| 236 | + ] |
| 237 | + lincon = mpc.optim[:linconstraint] |
| 238 | + set_normalized_rhs.(lincon, mpc.con.b[mpc.con.i_b]) |
| 239 | +end |
| 240 | + |
| 241 | +"Set `b` excluding predicted output constraints when `model` is not a [`LinModel`](@ref)." |
| 242 | +function linconstraint!(mpc::PredictiveController, model::SimModel) |
| 243 | + lastu = mpc.estim.lastu0 + model.uop |
| 244 | + mpc.con.b[:] = [ |
| 245 | + -mpc.con.Umin + mpc.T*lastu |
| 246 | + +mpc.con.Umax - mpc.T*lastu |
| 247 | + -mpc.con.ΔŨmin |
| 248 | + +mpc.con.ΔŨmax |
| 249 | + ] |
| 250 | + lincon = mpc.optim[:linconstraint] |
| 251 | + set_normalized_rhs.(lincon, mpc.con.b[mpc.con.i_b]) |
| 252 | +end |
| 253 | + |
214 | 254 | @doc raw""" |
215 | 255 | predict!(Ŷ, x̂, mpc::PredictiveController, model::LinModel, ΔŨ) -> Ŷ, x̂end |
216 | 256 |
|
@@ -250,44 +290,62 @@ function predict!(Ŷ, x̂, mpc::PredictiveController, model::SimModel, ΔŨ::V |
250 | 290 | return Ŷ, x̂end |
251 | 291 | end |
252 | 292 |
|
253 | | -@doc raw""" |
254 | | - linconstraint!(mpc::PredictiveController, model::LinModel) |
| 293 | +""" |
| 294 | + obj_nonlinprog(mpc::PredictiveController, model::LinModel, Ŷ, ΔŨ) |
255 | 295 |
|
256 | | -Set `b` vector for the linear model inequality constraints (``\mathbf{A ΔŨ ≤ b}``). |
| 296 | +Nonlinear programming objective function when `model` is a [`LinModel`](@ref). |
257 | 297 |
|
258 | | -Also init ``\mathbf{f_x̂}`` vector for the terminal constraints, see [`init_predmat`](@ref). |
| 298 | +The function is called by the nonlinear optimizer of [`NonLinMPC`](@ref) controllers. It can |
| 299 | +also be called on any [`PredictiveController`](@ref)s to evaluate the objective function `J` |
| 300 | +at specific input increments `ΔŨ` and predictions `Ŷ` values. |
259 | 301 | """ |
260 | | -function linconstraint!(mpc::PredictiveController, model::LinModel) |
261 | | - mpc.con.fx̂[:] = mpc.con.kx̂ * mpc.estim.x̂ + mpc.con.vx̂ * mpc.estim.lastu0 |
262 | | - if model.nd ≠ 0 |
263 | | - mpc.con.fx̂[:] = mpc.con.fx̂ + mpc.con.gx̂ * mpc.d0 + mpc.con.jx̂ * mpc.D̂0 |
| 302 | +function obj_nonlinprog( |
| 303 | + mpc::PredictiveController, model::LinModel, Ŷ, ΔŨ::Vector{NT} |
| 304 | +) where {NT<:Real} |
| 305 | + J = obj_quadprog(ΔŨ, mpc.H̃, mpc.q̃) + mpc.p[] |
| 306 | + if !iszero(mpc.E) |
| 307 | + U = mpc.S̃*ΔŨ + mpc.T*(mpc.estim.lastu0 + model.uop) |
| 308 | + UE = [U; U[(end - model.nu + 1):end]] |
| 309 | + ŶE = [mpc.ŷ; Ŷ] |
| 310 | + J += mpc.E*mpc.JE(UE, ŶE, mpc.D̂E) |
264 | 311 | end |
265 | | - lastu = mpc.estim.lastu0 + model.uop |
266 | | - mpc.con.b[:] = [ |
267 | | - -mpc.con.Umin + mpc.T*lastu |
268 | | - +mpc.con.Umax - mpc.T*lastu |
269 | | - -mpc.con.ΔŨmin |
270 | | - +mpc.con.ΔŨmax |
271 | | - -mpc.con.Ymin + mpc.F |
272 | | - +mpc.con.Ymax - mpc.F |
273 | | - -mpc.con.x̂min + mpc.con.fx̂ |
274 | | - +mpc.con.x̂max - mpc.con.fx̂ |
275 | | - ] |
276 | | - lincon = mpc.optim[:linconstraint] |
277 | | - set_normalized_rhs.(lincon, mpc.con.b[mpc.con.i_b]) |
| 312 | + return J |
278 | 313 | end |
279 | 314 |
|
280 | | -"Set `b` excluding predicted output constraints when `model` is not a [`LinModel`](@ref)." |
281 | | -function linconstraint!(mpc::PredictiveController, model::SimModel) |
282 | | - lastu = mpc.estim.lastu0 + model.uop |
283 | | - mpc.con.b[:] = [ |
284 | | - -mpc.con.Umin + mpc.T*lastu |
285 | | - +mpc.con.Umax - mpc.T*lastu |
286 | | - -mpc.con.ΔŨmin |
287 | | - +mpc.con.ΔŨmax |
288 | | - ] |
289 | | - lincon = mpc.optim[:linconstraint] |
290 | | - set_normalized_rhs.(lincon, mpc.con.b[mpc.con.i_b]) |
| 315 | +""" |
| 316 | + obj_nonlinprog(mpc::PredictiveController, model::SimModel, Ŷ, ΔŨ) |
| 317 | +
|
| 318 | +Nonlinear programming objective function when `model` is not a [`LinModel`](@ref). The |
| 319 | +function `dot(x, A, x)` is a performant way of calculating `x'*A*x`. |
| 320 | +""" |
| 321 | +function obj_nonlinprog( |
| 322 | + mpc::PredictiveController, model::SimModel, Ŷ, ΔŨ::Vector{NT} |
| 323 | +) where {NT<:Real} |
| 324 | + # --- output setpoint tracking term --- |
| 325 | + êy = mpc.R̂y - Ŷ |
| 326 | + JR̂y = dot(êy, mpc.M_Hp, êy) |
| 327 | + # --- move suppression and slack variable term --- |
| 328 | + JΔŨ = dot(ΔŨ, mpc.Ñ_Hc, ΔŨ) |
| 329 | + # --- input over prediction horizon --- |
| 330 | + if !mpc.noR̂u || !iszero(mpc.E) |
| 331 | + U = mpc.S̃*ΔŨ + mpc.T*(mpc.estim.lastu0 + model.uop) |
| 332 | + end |
| 333 | + # --- input setpoint tracking term --- |
| 334 | + if !mpc.noR̂u |
| 335 | + êu = mpc.R̂u - U |
| 336 | + JR̂u = dot(êu, mpc.L_Hp, êu) |
| 337 | + else |
| 338 | + JR̂u = 0.0 |
| 339 | + end |
| 340 | + # --- economic term --- |
| 341 | + if !iszero(mpc.E) |
| 342 | + UE = [U; U[(end - model.nu + 1):end]] |
| 343 | + ŶE = [mpc.ŷ; Ŷ] |
| 344 | + E_JE = mpc.E*mpc.JE(UE, ŶE, mpc.D̂E) |
| 345 | + else |
| 346 | + E_JE = 0.0 |
| 347 | + end |
| 348 | + return JR̂y + JΔŨ + JR̂u + E_JE |
291 | 349 | end |
292 | 350 |
|
293 | 351 | """ |
|
0 commit comments