diff --git a/src/controller/execute.jl b/src/controller/execute.jl index 80134fffa..d01e99de6 100644 --- a/src/controller/execute.jl +++ b/src/controller/execute.jl @@ -155,7 +155,7 @@ function getinfo(mpc::PredictiveController{NT}) where NT<:Real U .= U0 .+ mpc.Uop Ŷ .= Ŷ0 .+ mpc.Yop D̂ .= mpc.D̂0 + mpc.Dop - J = obj_nonlinprog!(Ŷ0, U0, mpc, model, Ue, Ŷe, ΔŨ) + J = obj_nonlinprog!(Ŷ0, U0, mpc, Ue, Ŷe, ΔŨ) Ŷs = similar(mpc.Yop) predictstoch!(Ŷs, mpc, mpc.estim) info[:ΔU] = Z̃[1:mpc.Hc*model.nu] @@ -387,33 +387,20 @@ end iszero_nc(mpc::PredictiveController) = (mpc.con.nc == 0) """ - obj_nonlinprog!( _ , _ , mpc::PredictiveController, model::LinModel, Ue, Ŷe, _ , Z̃) - -Nonlinear programming objective function when `model` is a [`LinModel`](@ref). - -The method is called by the nonlinear optimizer of [`NonLinMPC`](@ref) controllers. It can -also be called on any [`PredictiveController`](@ref)s to evaluate the objective function `J` -at specific `Ue`, `Ŷe` and `Z̃`, values. It does not mutate any argument. -""" -function obj_nonlinprog!( - _, _, mpc::PredictiveController, model::LinModel, Ue, Ŷe, _ , Z̃::AbstractVector{NT} -) where NT <: Real - JQP = obj_quadprog(Z̃, mpc.H̃, mpc.q̃) + mpc.r[] - E_JE = obj_econ(mpc, model, Ue, Ŷe) - return JQP + E_JE -end - -""" - obj_nonlinprog!(Ȳ, Ū, mpc::PredictiveController, model::SimModel, Ue, Ŷe, ΔŨ) + obj_nonlinprog!(Ȳ, Ū, mpc::PredictiveController, Ue, Ŷe, ΔŨ) Nonlinear programming objective method when `model` is not a [`LinModel`](@ref). The function `dot(x, A, x)` is a performant way of calculating `x'*A*x`. This method mutates `Ȳ` and `Ū` arguments, without assuming any initial values (it recuperates the values in `Ŷe` and `Ue` arguments). + +Note that a specialized version on [`LinModel`](@ref) that uses the Hessian matrix `mpc.H̃` +is actually slower in the [`MultipleShooting`](@ref) case, so only one method is defined. """ function obj_nonlinprog!( - Ȳ, Ū, mpc::PredictiveController, model::SimModel, Ue, Ŷe, ΔŨ::AbstractVector{NT} + Ȳ, Ū, mpc::PredictiveController, Ue, Ŷe, ΔŨ::AbstractVector{NT} ) where NT<:Real + model = mpc.estim.model nu, ny = model.nu, model.ny # --- output setpoint tracking term --- if mpc.weights.iszero_M_Hp[] diff --git a/src/controller/nonlinmpc.jl b/src/controller/nonlinmpc.jl index 4f2a3c943..18c7fc29e 100644 --- a/src/controller/nonlinmpc.jl +++ b/src/controller/nonlinmpc.jl @@ -584,7 +584,7 @@ function addinfo!(info, mpc::NonLinMPC{NT}) where NT<:Real ) function J!(Z̃, ΔŨ, x̂0end, Ue, Ŷe, U0, Ŷ0, Û0, K, X̂0, gc, g, geq) update_predictions!(ΔŨ, x̂0end, Ue, Ŷe, U0, Ŷ0, Û0, K, X̂0, gc, g, geq, mpc, Z̃) - return obj_nonlinprog!(Ŷ0, U0, mpc, model, Ue, Ŷe, ΔŨ) + return obj_nonlinprog!(Ŷ0, U0, mpc, Ue, Ŷe, ΔŨ) end if !isnothing(mpc.hessian) _, ∇J, ∇²J = value_gradient_and_hessian(J!, mpc.hessian, mpc.Z̃, J_cache...) @@ -780,7 +780,7 @@ function get_nonlinobj_op(mpc::NonLinMPC, optim::JuMP.GenericModel{JNT}) where J geq::Vector{JNT} = zeros(JNT, neq) function J!(Z̃, ΔŨ, x̂0end, Ue, Ŷe, U0, Ŷ0, Û0, K, X̂0, gc, g, geq) update_predictions!(ΔŨ, x̂0end, Ue, Ŷe, U0, Ŷ0, Û0, K, X̂0, gc, g, geq, mpc, Z̃) - return obj_nonlinprog!(Ŷ0, U0, mpc, model, Ue, Ŷe, ΔŨ) + return obj_nonlinprog!(Ŷ0, U0, mpc, Ue, Ŷe, ΔŨ) end Z̃_J = fill(myNaN, nZ̃) # NaN to force update at first call J_cache = (