@@ -23,8 +23,8 @@ struct NonLinMPC{
2323 E:: NT
2424 JE:: JEfunc
2525 p:: P
26- R̂u0 :: Vector{NT}
27- R̂y0 :: Vector{NT}
26+ R̂u :: Vector{NT}
27+ R̂y :: Vector{NT}
2828 noR̂u:: Bool
2929 S̃:: Matrix{NT}
3030 T:: Matrix{NT}
@@ -62,7 +62,7 @@ struct NonLinMPC{
6262 N_Hc = Hermitian (convert (Matrix{NT}, N_Hc), :L )
6363 L_Hp = Hermitian (convert (Matrix{NT}, L_Hp), :L )
6464 # dummy vals (updated just before optimization):
65- R̂y0, R̂u0 , T_lastu0 = zeros (NT, ny* Hp), zeros (NT, nu* Hp), zeros (NT, nu* Hp)
65+ R̂y, R̂u , T_lastu0 = zeros (NT, ny* Hp), zeros (NT, nu* Hp), zeros (NT, nu* Hp)
6666 noR̂u = iszero (L_Hp)
6767 S, T = init_ΔUtoU (model, Hp, Hc)
6868 E, G, J, K, V, B, ex̂, gx̂, jx̂, kx̂, vx̂, bx̂ = init_predmat (estim, model, Hp, Hc)
@@ -86,7 +86,7 @@ struct NonLinMPC{
8686 ΔŨ, ŷ,
8787 Hp, Hc, nϵ,
8888 M_Hp, Ñ_Hc, L_Hp, Ewt, JE, p,
89- R̂u0, R̂y0 , noR̂u,
89+ R̂u, R̂y , noR̂u,
9090 S̃, T, T_lastu0,
9191 Ẽ, F, G, J, K, V, B,
9292 H̃, q̃, r,
@@ -375,7 +375,6 @@ function get_mutating_gc(NT, gc)
375375 gc! = if ismutating_gc
376376 gc
377377 else
378- println (" YO!" )
379378 function gc! (LHS, Ue, Ŷe, D̂e, p, ϵ)
380379 LHS .= gc (Ue, Ŷe, D̂e, p, ϵ)
381380 return nothing
@@ -385,14 +384,13 @@ function get_mutating_gc(NT, gc)
385384end
386385
387386function test_custom_functions (JE, gc!, uop; Uop, dop, Dop, ΔŨ, p)
387+ # TODO : contunue here (important to guide the users, sim! can be used on NonLinModel
388+ # but there is no similar function for the custom functions of NonLinMPC)
388389 Ue = [Uop; uop]
389390 D̂e = [dop; Dop]
390391 Ŷ0, x̂0next =
391392 Ŷ0, x̂0end = predict! (Ŷ0, x̂0, x̂0next, u0, û0, mpc, model, mpc. ΔŨ)
392-
393-
394393 JE = JE (Uop, Uop, Dop, p)
395-
396394end
397395
398396"""
@@ -475,31 +473,33 @@ function get_optim_functions(mpc::NonLinMPC, ::JuMP.GenericModel{JNT}) where JNT
475473 model = mpc. estim. model
476474 nu, ny, nx̂, Hp = model. nu, model. ny, mpc. estim. nx̂, mpc. Hp
477475 ng, nΔŨ, nU, nŶ = length (mpc. con. i_g), length (mpc. ΔŨ), Hp* nu, Hp* ny
476+ nUe, nŶe = nU + nu, nŶ + ny
478477 Nc = nΔŨ + 3
479478 ΔŨ_cache:: DiffCache{Vector{JNT}, Vector{JNT}} = DiffCache (zeros (JNT, nΔŨ), Nc)
480- Ŷ0_cache :: DiffCache{Vector{JNT}, Vector{JNT}} = DiffCache (zeros (JNT, nŶ ), Nc)
481- U0_cache :: DiffCache{Vector{JNT}, Vector{JNT}} = DiffCache (zeros (JNT, nU ), Nc)
482- g_cache :: DiffCache{Vector{JNT}, Vector{JNT}} = DiffCache (zeros (JNT, ng), Nc)
483- x̂0_cache :: DiffCache{Vector{JNT}, Vector{JNT}} = DiffCache (zeros (JNT, nx̂), Nc)
484- x̂0next_cache :: DiffCache{Vector{JNT}, Vector{JNT}} = DiffCache (zeros (JNT, nx̂), Nc)
485- u0_cache :: DiffCache{Vector{JNT}, Vector{JNT}} = DiffCache (zeros (JNT, nu), Nc)
486- û0_cache :: DiffCache{Vector{JNT}, Vector{JNT}} = DiffCache (zeros (JNT, nu), Nc)
487- Ȳ_cache :: DiffCache{Vector{JNT}, Vector{JNT}} = DiffCache (zeros (JNT, nŶ), Nc)
488- Ū_cache :: DiffCache{Vector{JNT}, Vector{JNT}} = DiffCache (zeros (JNT, nU), Nc)
479+ Ŷe_cache :: DiffCache{Vector{JNT}, Vector{JNT}} = DiffCache (zeros (JNT, nŶe ), Nc)
480+ Ue_cache :: DiffCache{Vector{JNT}, Vector{JNT}} = DiffCache (zeros (JNT, nUe ), Nc)
481+ Ȳ_cache :: DiffCache{Vector{JNT}, Vector{JNT}} = DiffCache (zeros (JNT, nŶ), Nc)
482+ Ū_cache :: DiffCache{Vector{JNT}, Vector{JNT}} = DiffCache (zeros (JNT, nU), Nc)
483+ x̂0_cache :: DiffCache{Vector{JNT}, Vector{JNT}} = DiffCache (zeros (JNT, nx̂), Nc)
484+ x̂0next_cache :: DiffCache{Vector{JNT}, Vector{JNT}} = DiffCache (zeros (JNT, nx̂), Nc)
485+ u0_cache :: DiffCache{Vector{JNT}, Vector{JNT}} = DiffCache (zeros (JNT, nu), Nc)
486+ û0_cache :: DiffCache{Vector{JNT}, Vector{JNT}} = DiffCache (zeros (JNT, nu), Nc)
487+ g_cache :: DiffCache{Vector{JNT}, Vector{JNT}} = DiffCache (zeros (JNT, ng), Nc)
489488 function Jfunc (ΔŨtup:: T... ) where T<: Real
490489 ΔŨ1 = ΔŨtup[begin ]
491490 ΔŨ, g = get_tmp (ΔŨ_cache, ΔŨ1), get_tmp (g_cache, ΔŨ1)
492491 for i in eachindex (ΔŨtup)
493492 ΔŨ[i] = ΔŨtup[i] # ΔŨ .= ΔŨtup seems to produce a type instability
494- end
495- Ŷ0 = get_tmp (Ŷ0_cache, ΔŨ1)
493+ end
494+ Ŷe, Ue = get_tmp (Ŷe_cache, ΔŨ1), get_tmp (Ue_cache, ΔŨ1)
495+ Ȳ, Ū = get_tmp (Ȳ_cache, ΔŨ1), get_tmp (Ū_cache, ΔŨ1)
496496 x̂0, x̂0next = get_tmp (x̂0_cache, ΔŨ1), get_tmp (x̂0next_cache, ΔŨ1)
497- u0, û0 = get_tmp (u0_cache, ΔŨ1), get_tmp (û0_cache, ΔŨ1)
498- Ŷ0, x̂0end = predict! (Ŷ0, x̂0, x̂0next, u0, û0, mpc, model, ΔŨ)
497+ u0, û0 = get_tmp (u0_cache, ΔŨ1), get_tmp (û0_cache, ΔŨ1)
498+ Ŷ0, x̂0end = predict! (Ȳ, x̂0, x̂0next, u0, û0, mpc, model, ΔŨ)
499+ Ŷe, Ue = extended_predictions! (Ŷe, Ue, Ū, mpc, model, Ŷ0, ΔŨ)
499500 g = get_tmp (g_cache, ΔŨ1)
500501 g = con_nonlinprog! (g, mpc, model, x̂0end, Ŷ0, ΔŨ)
501- U0, Ȳ, Ū = get_tmp (U0_cache, ΔŨ1), get_tmp (Ȳ_cache, ΔŨ1), get_tmp (Ū_cache, ΔŨ1)
502- return obj_nonlinprog! (U0, Ȳ, Ū, mpc, model, Ŷ0, ΔŨ):: T
502+ return obj_nonlinprog! (Ȳ, Ū, mpc, model, Ŷe, Ue, ΔŨ):: T
503503 end
504504 function gfunc_i (i, ΔŨtup:: NTuple{N, T} ) where {N, T<: Real }
505505 ΔŨ1 = ΔŨtup[begin ]
@@ -508,10 +508,13 @@ function get_optim_functions(mpc::NonLinMPC, ::JuMP.GenericModel{JNT}) where JNT
508508 for i in eachindex (ΔŨtup)
509509 ΔŨ[i] = ΔŨtup[i] # ΔŨ .= ΔŨtup seems to produce a type instability
510510 end
511- Ŷ0 = get_tmp (Ŷ0_cache, ΔŨ1)
511+ Ŷe, Ue = get_tmp (Ŷe_cache, ΔŨ1), get_tmp (Ue_cache, ΔŨ1)
512+ Ȳ, Ū = get_tmp (Ȳ_cache, ΔŨ1), get_tmp (Ū_cache, ΔŨ1)
512513 x̂0, x̂0next = get_tmp (x̂0_cache, ΔŨ1), get_tmp (x̂0next_cache, ΔŨ1)
513- u0, û0 = get_tmp (u0_cache, ΔŨ1), get_tmp (û0_cache, ΔŨ1)
514- Ŷ0, x̂0end = predict! (Ŷ0, x̂0, x̂0next, u0, û0, mpc, model, ΔŨ)
514+ u0, û0 = get_tmp (u0_cache, ΔŨ1), get_tmp (û0_cache, ΔŨ1)
515+ Ŷ0, x̂0end = predict! (Ȳ, x̂0, x̂0next, u0, û0, mpc, model, ΔŨ)
516+ Ŷe, Ue = extended_predictions! (Ŷe, Ue, Ū, mpc, model, Ŷ0, ΔŨ)
517+ g = get_tmp (g_cache, ΔŨ1)
515518 g = con_nonlinprog! (g, mpc, model, x̂0end, Ŷ0, ΔŨ)
516519 end
517520 return g[i]:: T
@@ -520,6 +523,27 @@ function get_optim_functions(mpc::NonLinMPC, ::JuMP.GenericModel{JNT}) where JNT
520523 return Jfunc, gfunc
521524end
522525
526+ """
527+ extended_predictions!(Ŷe, Ue, Ū, mpc, model, Ŷ0, ΔŨ) -> Ŷe, Ue
528+
529+ Compute the extended predictions `Ŷe` and `Ue` for the nonlinear optimization.
530+
531+ The function mutates `Ŷe`, `Ue` and `Ū` in arguments, without assuming any initial values.
532+ """
533+ function extended_predictions! (Ŷe, Ue, Ū, mpc, model, Ŷ0, ΔŨ)
534+ ny, nu = model. ny, model. nu
535+ # --- extended output predictions Ŷe = [ŷ(k); Ŷ] ---
536+ Ŷe[1 : ny] .= mpc. ŷ
537+ Ŷe[ny+ 1 : end ] .= Ŷ0 .+ mpc. Yop
538+ # --- extended manipulated inputs Ue = [U; u(k+Hp-1)] ---
539+ U0 = Ū
540+ U0 .= mul! (U0, mpc. S̃, ΔŨ) .+ mpc. T_lastu0
541+ Ue[1 : end - nu] .= U0 .+ mpc. Uop
542+ # u(k + Hp) = u(k + Hp - 1) since Δu(k+Hp) = 0 (because Hc ≤ Hp):
543+ Ue[end - nu+ 1 : end ] .= @views Ue[end - 2 nu+ 1 : end - nu]
544+ return Ŷe, Ue
545+ end
546+
523547" Set the nonlinear constraints on the output predictions `Ŷ` and terminal states `x̂end`."
524548function setnonlincon! (
525549 mpc:: NonLinMPC , :: NonLinModel , optim:: JuMP.GenericModel{JNT}
579603" No nonlinear constraints if `model` is a [`LinModel`](@ref), return `g` unchanged."
580604con_nonlinprog! (g, :: NonLinMPC , :: LinModel , _ , _ , _ ) = g
581605
582- " Evaluate the economic term of the objective function for [`NonLinMPC`](@ref)."
583- function obj_econ! (U0, Ȳ, mpc:: NonLinMPC , model:: SimModel , Ŷ0, ΔŨ)
584- if ! iszero (mpc. E)
585- ny, Hp, ŷ, D̂e = model. ny, mpc. Hp, mpc. ŷ, mpc. D̂e
586- U = U0
587- U .+ = mpc. Uop
588- uend = @views U[(end - model. nu+ 1 ): end ]
589- Ŷ = Ȳ
590- Ŷ .= Ŷ0 .+ mpc. Yop
591- Ue = [U; uend]
592- Ŷe = [ŷ; Ŷ]
593- E_JE = mpc. E* mpc. JE (Ue, Ŷe, D̂e, mpc. p)
594- else
595- E_JE = 0.0
596- end
606+ " Evaluate the economic term `E*JE` of the objective function for [`NonLinMPC`](@ref)."
607+ function obj_econ! (Ue, Ŷe, mpc:: NonLinMPC , model:: SimModel )
608+ E_JE = iszero (mpc. E) ? 0.0 : mpc. E* mpc. JE (Ue, Ŷe, mpc. D̂e, mpc. p)
597609 return E_JE
598610end
0 commit comments