From 6fb8af8fec950e52ae67b99e0c8d8159f3ee6cee Mon Sep 17 00:00:00 2001 From: franckgaga Date: Wed, 3 Jul 2024 14:03:02 -0400 Subject: [PATCH 1/7] reduce allocations `setconstraint!` --- src/controller/construct.jl | 165 ++++++++++++++++++++------------- src/estimator/mhe/construct.jl | 156 ++++++++++++++++++------------- 2 files changed, 192 insertions(+), 129 deletions(-) diff --git a/src/controller/construct.jl b/src/controller/construct.jl index 75c68a9e..4589180a 100644 --- a/src/controller/construct.jl +++ b/src/controller/construct.jl @@ -146,98 +146,129 @@ function setconstraint!( model, con, optim = mpc.estim.model, mpc.con, mpc.optim nu, ny, nx̂, Hp, Hc, nϵ = model.nu, model.ny, mpc.estim.nx̂, mpc.Hp, mpc.Hc, mpc.nϵ notSolvedYet = (JuMP.termination_status(optim) == JuMP.OPTIMIZE_NOT_CALLED) - isnothing(Umin) && !isnothing(umin) && (Umin = repeat(umin, Hp)) - isnothing(Umax) && !isnothing(umax) && (Umax = repeat(umax, Hp)) - isnothing(ΔUmin) && !isnothing(Δumin) && (ΔUmin = repeat(Δumin, Hc)) - isnothing(ΔUmax) && !isnothing(Δumax) && (ΔUmax = repeat(Δumax, Hc)) - isnothing(Ymin) && !isnothing(ymin) && (Ymin = repeat(ymin, Hp)) - isnothing(Ymax) && !isnothing(ymax) && (Ymax = repeat(ymax, Hp)) - isnothing(C_umin) && !isnothing(c_umin) && (C_umin = repeat(c_umin, Hp)) - isnothing(C_umax) && !isnothing(c_umax) && (C_umax = repeat(c_umax, Hp)) - isnothing(C_Δumin) && !isnothing(c_Δumin) && (C_Δumin = repeat(c_Δumin, Hc)) - isnothing(C_Δumax) && !isnothing(c_Δumax) && (C_Δumax = repeat(c_Δumax, Hc)) - isnothing(C_ymin) && !isnothing(c_ymin) && (C_ymin = repeat(c_ymin, Hp)) - isnothing(C_ymax) && !isnothing(c_ymax) && (C_ymax = repeat(c_ymax, Hp)) - if !all(isnothing.((C_umin, C_umax, C_Δumin, C_Δumax, C_ymin, C_ymax, c_x̂min, c_x̂max))) - nϵ == 1 || throw(ArgumentError("Slack variable weight Cwt must be finite to set softness parameters")) - notSolvedYet || error("Cannot set softness parameters after calling moveinput!") - end - if !isnothing(Umin) - size(Umin) == (nu*Hp,) || throw(ArgumentError("Umin size must be $((nu*Hp,))")) + if isnothing(Umin) && !isnothing(umin) + size(umin) == (nu,) || throw(ArgumentError("umin size must be $((nu,))")) + for i = 1:nu*Hp + con.U0min[i] = umin[(i-1) % nu + 1] - mpc.Uop[i] + end + elseif !isnothing(Umin) + size(Umin) == (nu*Hp,) || throw(ArgumentError("Umin size must be $((nu*Hp,))")) con.U0min .= Umin .- mpc.Uop end - if !isnothing(Umax) + if isnothing(Umax) && !isnothing(umax) + size(umax) == (nu,) || throw(ArgumentError("umax size must be $((nu,))")) + for i = 1:nu*Hp + con.U0max[i] = umax[(i-1) % nu + 1] - mpc.Uop[i] + end + elseif !isnothing(Umax) size(Umax) == (nu*Hp,) || throw(ArgumentError("Umax size must be $((nu*Hp,))")) con.U0max .= Umax .- mpc.Uop end - if !isnothing(ΔUmin) + if isnothing(ΔUmin) && !isnothing(Δumin) + size(Δumin) == (nu,) || throw(ArgumentError("Δumin size must be $((nu,))")) + for i = 1:nu*Hc + con.ΔŨmin[i] = Δumin[(i-1) % nu + 1] + end + elseif !isnothing(ΔUmin) size(ΔUmin) == (nu*Hc,) || throw(ArgumentError("ΔUmin size must be $((nu*Hc,))")) con.ΔŨmin[1:nu*Hc] .= ΔUmin end - if !isnothing(ΔUmax) + if isnothing(ΔUmax) && !isnothing(Δumax) + size(Δumax) == (nu,) || throw(ArgumentError("Δumax size must be $((nu,))")) + for i = 1:nu*Hc + con.ΔŨmax[i] = Δumax[(i-1) % nu + 1] + end + elseif !isnothing(ΔUmax) size(ΔUmax) == (nu*Hc,) || throw(ArgumentError("ΔUmax size must be $((nu*Hc,))")) con.ΔŨmax[1:nu*Hc] .= ΔUmax end - if !isnothing(Ymin) + if isnothing(Ymin) && !isnothing(ymin) + size(ymin) == (ny,) || throw(ArgumentError("ymin size must be $((ny,))")) + for i = 1:ny*Hp + con.Y0min[i] = ymin[(i-1) % ny + 1] - mpc.Yop[i] + end + elseif !isnothing(Ymin) size(Ymin) == (ny*Hp,) || throw(ArgumentError("Ymin size must be $((ny*Hp,))")) con.Y0min .= Ymin .- mpc.Yop end - if !isnothing(Ymax) + if isnothing(Ymax) && !isnothing(ymax) + size(ymax) == (ny,) || throw(ArgumentError("ymax size must be $((ny,))")) + for i = 1:ny*Hp + con.Y0max[i] = ymax[(i-1) % ny + 1] - mpc.Yop[i] + end + elseif !isnothing(Ymax) size(Ymax) == (ny*Hp,) || throw(ArgumentError("Ymax size must be $((ny*Hp,))")) con.Y0max .= Ymax .- mpc.Yop end if !isnothing(x̂min) - size(x̂min) == (nx̂,) || throw(ArgumentError("x̂min size must be $((nx̂,))")) + size(x̂min) == (nx̂,) || throw(ArgumentError("x̂min size must be $((nx̂,))")) con.x̂0min .= x̂min .- mpc.estim.x̂op end if !isnothing(x̂max) - size(x̂max) == (nx̂,) || throw(ArgumentError("x̂max size must be $((nx̂,))")) + size(x̂max) == (nx̂,) || throw(ArgumentError("x̂max size must be $((nx̂,))")) con.x̂0max .= x̂max .- mpc.estim.x̂op end - if !isnothing(C_umin) - size(C_umin) == (nu*Hp,) || throw(ArgumentError("C_umin size must be $((nu*Hp,))")) - any(C_umin .< 0) && error("C_umin weights should be non-negative") - con.A_Umin[:, end] .= -C_umin - end - if !isnothing(C_umax) - size(C_umax) == (nu*Hp,) || throw(ArgumentError("C_umax size must be $((nu*Hp,))")) - any(C_umax .< 0) && error("C_umax weights should be non-negative") - con.A_Umax[:, end] .= -C_umax - end - if !isnothing(C_Δumin) - size(C_Δumin) == (nu*Hc,) || throw(ArgumentError("C_Δumin size must be $((nu*Hc,))")) - any(C_Δumin .< 0) && error("C_Δumin weights should be non-negative") - con.A_ΔŨmin[1:end-1, end] .= -C_Δumin - end - if !isnothing(C_Δumax) - size(C_Δumax) == (nu*Hc,) || throw(ArgumentError("C_Δumax size must be $((nu*Hc,))")) - any(C_Δumax .< 0) && error("C_Δumax weights should be non-negative") - con.A_ΔŨmax[1:end-1, end] .= -C_Δumax - end - if !isnothing(C_ymin) - size(C_ymin) == (ny*Hp,) || throw(ArgumentError("C_ymin size must be $((ny*Hp,))")) - any(C_ymin .< 0) && error("C_ymin weights should be non-negative") - con.C_ymin .= C_ymin - size(con.A_Ymin, 1) ≠ 0 && (con.A_Ymin[:, end] .= -con.C_ymin) # for LinModel - end - if !isnothing(C_ymax) - size(C_ymax) == (ny*Hp,) || throw(ArgumentError("C_ymax size must be $((ny*Hp,))")) - any(C_ymax .< 0) && error("C_ymax weights should be non-negative") - con.C_ymax .= C_ymax - size(con.A_Ymax, 1) ≠ 0 && (con.A_Ymax[:, end] .= -con.C_ymax) # for LinModel - end - if !isnothing(c_x̂min) - size(c_x̂min) == (nx̂,) || throw(ArgumentError("c_x̂min size must be $((nx̂,))")) - any(c_x̂min .< 0) && error("c_x̂min weights should be non-negative") - con.c_x̂min .= c_x̂min - size(con.A_x̂min, 1) ≠ 0 && (con.A_x̂min[:, end] .= -con.c_x̂min) # for LinModel + allECRs = ( + c_umin, c_umax, c_Δumin, c_Δumax, c_ymin, c_ymax, + C_umin, C_umax, C_Δumin, C_Δumax, C_ymin, C_ymax, c_x̂min, c_x̂max, + ) + if any(ECR -> !isnothing(ECR), allECRs) + nϵ == 1 || throw(ArgumentError("Slack variable weight Cwt must be finite to set softness parameters")) + notSolvedYet || error("Cannot set softness parameters after calling moveinput!") end - if !isnothing(c_x̂max) - size(c_x̂max) == (nx̂,) || throw(ArgumentError("c_x̂max size must be $((nx̂,))")) - any(c_x̂max .< 0) && error("c_x̂max weights should be non-negative") - con.c_x̂max .= c_x̂max - size(con.A_x̂max, 1) ≠ 0 && (con.A_x̂max[:, end] .= -con.c_x̂max) # for LinModel + if notSolvedYet + isnothing(C_umin) && !isnothing(c_umin) && (C_umin = repeat(c_umin, Hp)) + isnothing(C_umax) && !isnothing(c_umax) && (C_umax = repeat(c_umax, Hp)) + isnothing(C_Δumin) && !isnothing(c_Δumin) && (C_Δumin = repeat(c_Δumin, Hc)) + isnothing(C_Δumax) && !isnothing(c_Δumax) && (C_Δumax = repeat(c_Δumax, Hc)) + isnothing(C_ymin) && !isnothing(c_ymin) && (C_ymin = repeat(c_ymin, Hp)) + isnothing(C_ymax) && !isnothing(c_ymax) && (C_ymax = repeat(c_ymax, Hp)) + if !isnothing(C_umin) + size(C_umin) == (nu*Hp,) || throw(ArgumentError("C_umin size must be $((nu*Hp,))")) + any(C_umin .< 0) && error("C_umin weights should be non-negative") + con.A_Umin[:, end] .= -C_umin + end + if !isnothing(C_umax) + size(C_umax) == (nu*Hp,) || throw(ArgumentError("C_umax size must be $((nu*Hp,))")) + any(C_umax .< 0) && error("C_umax weights should be non-negative") + con.A_Umax[:, end] .= -C_umax + end + if !isnothing(C_Δumin) + size(C_Δumin) == (nu*Hc,) || throw(ArgumentError("C_Δumin size must be $((nu*Hc,))")) + any(C_Δumin .< 0) && error("C_Δumin weights should be non-negative") + con.A_ΔŨmin[1:end-1, end] .= -C_Δumin + end + if !isnothing(C_Δumax) + size(C_Δumax) == (nu*Hc,) || throw(ArgumentError("C_Δumax size must be $((nu*Hc,))")) + any(C_Δumax .< 0) && error("C_Δumax weights should be non-negative") + con.A_ΔŨmax[1:end-1, end] .= -C_Δumax + end + if !isnothing(C_ymin) + size(C_ymin) == (ny*Hp,) || throw(ArgumentError("C_ymin size must be $((ny*Hp,))")) + any(C_ymin .< 0) && error("C_ymin weights should be non-negative") + con.C_ymin .= C_ymin + size(con.A_Ymin, 1) ≠ 0 && (con.A_Ymin[:, end] .= -con.C_ymin) # for LinModel + end + if !isnothing(C_ymax) + size(C_ymax) == (ny*Hp,) || throw(ArgumentError("C_ymax size must be $((ny*Hp,))")) + any(C_ymax .< 0) && error("C_ymax weights should be non-negative") + con.C_ymax .= C_ymax + size(con.A_Ymax, 1) ≠ 0 && (con.A_Ymax[:, end] .= -con.C_ymax) # for LinModel + end + if !isnothing(c_x̂min) + size(c_x̂min) == (nx̂,) || throw(ArgumentError("c_x̂min size must be $((nx̂,))")) + any(c_x̂min .< 0) && error("c_x̂min weights should be non-negative") + con.c_x̂min .= c_x̂min + size(con.A_x̂min, 1) ≠ 0 && (con.A_x̂min[:, end] .= -con.c_x̂min) # for LinModel + end + if !isnothing(c_x̂max) + size(c_x̂max) == (nx̂,) || throw(ArgumentError("c_x̂max size must be $((nx̂,))")) + any(c_x̂max .< 0) && error("c_x̂max weights should be non-negative") + con.c_x̂max .= c_x̂max + size(con.A_x̂max, 1) ≠ 0 && (con.A_x̂max[:, end] .= -con.c_x̂max) # for LinModel + end end + # TODO: test setmodel! new arguments i_Umin, i_Umax = .!isinf.(con.U0min), .!isinf.(con.U0max) i_ΔŨmin, i_ΔŨmax = .!isinf.(con.ΔŨmin), .!isinf.(con.ΔŨmax) i_Ymin, i_Ymax = .!isinf.(con.Y0min), .!isinf.(con.Y0max) diff --git a/src/estimator/mhe/construct.jl b/src/estimator/mhe/construct.jl index d7fec674..3299afba 100644 --- a/src/estimator/mhe/construct.jl +++ b/src/estimator/mhe/construct.jl @@ -443,85 +443,117 @@ function setconstraint!( nX̂con = nx̂*(He+1) notSolvedYet = (JuMP.termination_status(optim) == JuMP.OPTIMIZE_NOT_CALLED) C = estim.C - isnothing(X̂min) && !isnothing(x̂min) && (X̂min = repeat(x̂min, He+1)) - isnothing(X̂max) && !isnothing(x̂max) && (X̂max = repeat(x̂max, He+1)) - isnothing(Ŵmin) && !isnothing(ŵmin) && (Ŵmin = repeat(ŵmin, He)) - isnothing(Ŵmax) && !isnothing(ŵmax) && (Ŵmax = repeat(ŵmax, He)) - isnothing(V̂min) && !isnothing(v̂min) && (V̂min = repeat(v̂min, He)) - isnothing(V̂max) && !isnothing(v̂max) && (V̂max = repeat(v̂max, He)) - isnothing(C_x̂min) && !isnothing(c_x̂min) && (C_x̂min = repeat(c_x̂min, He+1)) - isnothing(C_x̂max) && !isnothing(c_x̂max) && (C_x̂max = repeat(c_x̂max, He+1)) - isnothing(C_ŵmin) && !isnothing(c_ŵmin) && (C_ŵmin = repeat(c_ŵmin, He)) - isnothing(C_ŵmax) && !isnothing(c_ŵmax) && (C_ŵmax = repeat(c_ŵmax, He)) - isnothing(C_v̂min) && !isnothing(c_v̂min) && (C_v̂min = repeat(c_v̂min, He)) - isnothing(C_v̂max) && !isnothing(c_v̂max) && (C_v̂max = repeat(c_v̂max, He)) - if !all(isnothing.((C_x̂min, C_x̂max, C_ŵmin, C_ŵmax, C_v̂min, C_v̂max))) - !isinf(C) || throw(ArgumentError("Slack variable weight Cwt must be finite to set softness parameters")) - notSolvedYet || error("Cannot set softness parameters after calling updatestate!") - end - if !isnothing(X̂min) + if isnothing(X̂min) && !isnothing(x̂min) + size(x̂min) == (nx̂,) || throw(ArgumentError("x̂min size must be $((nx̂,))")) + con.x̃0min[end-nx̂+1:end] .= x̂min .- estim.x̂op # if C is finite : x̃ = [ϵ; x̂] + for i in 1:nx̂*He + con.X̂0min[i] = x̂min[(i-1) % nx̂ + 1] - estim.X̂op[i] + end + elseif !isnothing(X̂min) size(X̂min) == (nX̂con,) || throw(ArgumentError("X̂min size must be $((nX̂con,))")) - con.x̃0min[end-nx̂+1:end] .= X̂min[1:nx̂] .- estim.x̂op # if C is finite : x̃ = [ϵ; x̂] - con.X̂0min .= X̂min[nx̂+1:end] .- estim.X̂op + con.x̃0min[end-nx̂+1:end] .= X̂min[1:nx̂] .- estim.x̂op + con.X̂0min .= @views X̂min[nx̂+1:end] .- estim.X̂op end - if !isnothing(X̂max) + if isnothing(X̂max) && !isnothing(x̂max) + size(x̂max) == (nx̂,) || throw(ArgumentError("x̂max size must be $((nx̂,))")) + con.x̃0max[end-nx̂+1:end] .= x̂max .- estim.x̂op # if C is finite : x̃ = [ϵ; x̂] + for i in 1:nx̂*He + con.X̂0max[i] = x̂max[(i-1) % nx̂ + 1] - estim.X̂op[i] + end + elseif !isnothing(X̂max) size(X̂max) == (nX̂con,) || throw(ArgumentError("X̂max size must be $((nX̂con,))")) - con.x̃0max[end-nx̂+1:end] .= X̂max[1:nx̂] .- estim.x̂op # if C is finite : x̃ = [ϵ; x̂] - con.X̂0max .= X̂max[nx̂+1:end] .- estim.X̂op + con.x̃0max[end-nx̂+1:end] .= X̂max[1:nx̂] .- estim.x̂op + con.X̂0max .= @views X̂max[nx̂+1:end] .- estim.X̂op end - if !isnothing(Ŵmin) + if isnothing(Ŵmin) && !isnothing(ŵmin) + size(ŵmin) == (nŵ*He,) || throw(ArgumentError("ŵmin size must be $((nŵ*He,))")) + for i in 1:nŵ*He + con.Ŵmin[i] = ŵmin[(i-1) % nŵ + 1] + end + elseif !isnothing(Ŵmin) size(Ŵmin) == (nŵ*He,) || throw(ArgumentError("Ŵmin size must be $((nŵ*He,))")) con.Ŵmin .= Ŵmin end - if !isnothing(Ŵmax) + if isnothing(Ŵmax) && !isnothing(ŵmax) + size(ŵmax) == (nŵ*He,) || throw(ArgumentError("ŵmax size must be $((nŵ*He,))")) + for i in 1:nŵ*He + con.Ŵmax[i] = ŵmax[(i-1) % nŵ + 1] + end + elseif !isnothing(Ŵmax) size(Ŵmax) == (nŵ*He,) || throw(ArgumentError("Ŵmax size must be $((nŵ*He,))")) con.Ŵmax .= Ŵmax end - if !isnothing(V̂min) + if isnothing(V̂min) && !isnothing(v̂min) + size(v̂min) == (nym*He,) || throw(ArgumentError("v̂min size must be $((nym*He,))")) + for i in 1:nym*He + con.V̂min[i] = v̂min[(i-1) % nym + 1] + end + elseif !isnothing(V̂min) size(V̂min) == (nym*He,) || throw(ArgumentError("V̂min size must be $((nym*He,))")) con.V̂min .= V̂min end - if !isnothing(V̂max) + if isnothing(V̂max) && !isnothing(v̂max) + size(v̂max) == (nym*He,) || throw(ArgumentError("v̂max size must be $((nym*He,))")) + for i in 1:nym*He + con.V̂max[i] = v̂max[(i-1) % nym + 1] + end + elseif !isnothing(V̂max) size(V̂max) == (nym*He,) || throw(ArgumentError("V̂max size must be $((nym*He,))")) con.V̂max .= V̂max end - if !isnothing(C_x̂min) - size(C_x̂min) == (nX̂con,) || throw(ArgumentError("C_x̂min size must be $((nX̂con,))")) - any(C_x̂min .< 0) && error("C_x̂min weights should be non-negative") - # if C is finite : x̃ = [ϵ; x̂] - con.A_x̃min[end-nx̂+1:end, end] .= @views -C_x̂min[1:nx̂] - con.C_x̂min .= @views C_x̂min[nx̂+1:end] - size(con.A_X̂min, 1) ≠ 0 && (con.A_X̂min[:, end] = -con.C_x̂min) # for LinModel - end - if !isnothing(C_x̂max) - size(C_x̂max) == (nX̂con,) || throw(ArgumentError("C_x̂max size must be $((nX̂con,))")) - any(C_x̂max .< 0) && error("C_x̂max weights should be non-negative") - # if C is finite : x̃ = [ϵ; x̂] : - con.A_x̃max[end-nx̂+1:end, end] .= @views -C_x̂max[1:nx̂] - con.C_x̂max .= @views C_x̂max[nx̂+1:end] - size(con.A_X̂max, 1) ≠ 0 && (con.A_X̂max[:, end] = -con.C_x̂max) # for LinModel - end - if !isnothing(C_ŵmin) - size(C_ŵmin) == (nŵ*He,) || throw(ArgumentError("C_ŵmin size must be $((nŵ*He,))")) - any(C_ŵmin .< 0) && error("C_ŵmin weights should be non-negative") - con.A_Ŵmin[:, end] .= -C_ŵmin - end - if !isnothing(C_ŵmax) - size(C_ŵmax) == (nŵ*He,) || throw(ArgumentError("C_ŵmax size must be $((nŵ*He,))")) - any(C_ŵmax .< 0) && error("C_ŵmax weights should be non-negative") - con.A_Ŵmax[:, end] .= -C_ŵmax - end - if !isnothing(C_v̂min) - size(C_v̂min) == (nym*He,) || throw(ArgumentError("C_v̂min size must be $((nym*He,))")) - any(C_v̂min .< 0) && error("C_v̂min weights should be non-negative") - con.C_v̂min .= C_v̂min - size(con.A_V̂min, 1) ≠ 0 && (con.A_V̂min[:, end] = -con.C_v̂min) # for LinModel + allECRs = ( + c_x̂min, c_x̂max, c_ŵmin, c_ŵmax, c_v̂min, c_v̂max, + C_x̂min, C_x̂max, C_ŵmin, C_ŵmax, C_v̂min, C_v̂max, + ) + if any(ECR -> !isnothing(ECR), allECRs) + !isinf(C) || throw(ArgumentError("Slack variable weight Cwt must be finite to set softness parameters")) + notSolvedYet || error("Cannot set softness parameters after calling updatestate!") end - if !isnothing(C_v̂max) - size(C_v̂max) == (nym*He,) || throw(ArgumentError("C_v̂max size must be $((nym*He,))")) - any(C_v̂max .< 0) && error("C_v̂max weights should be non-negative") - con.C_v̂max .= C_v̂max - size(con.A_V̂max, 1) ≠ 0 && (con.A_V̂max[:, end] = -con.C_v̂max) # for LinModel + if notSolvedYet + isnothing(C_x̂min) && !isnothing(c_x̂min) && (C_x̂min = repeat(c_x̂min, He+1)) + isnothing(C_x̂max) && !isnothing(c_x̂max) && (C_x̂max = repeat(c_x̂max, He+1)) + isnothing(C_ŵmin) && !isnothing(c_ŵmin) && (C_ŵmin = repeat(c_ŵmin, He)) + isnothing(C_ŵmax) && !isnothing(c_ŵmax) && (C_ŵmax = repeat(c_ŵmax, He)) + isnothing(C_v̂min) && !isnothing(c_v̂min) && (C_v̂min = repeat(c_v̂min, He)) + isnothing(C_v̂max) && !isnothing(c_v̂max) && (C_v̂max = repeat(c_v̂max, He)) + if !isnothing(C_x̂min) + size(C_x̂min) == (nX̂con,) || throw(ArgumentError("C_x̂min size must be $((nX̂con,))")) + any(C_x̂min .< 0) && error("C_x̂min weights should be non-negative") + # if C is finite : x̃ = [ϵ; x̂] + con.A_x̃min[end-nx̂+1:end, end] .= @views -C_x̂min[1:nx̂] + con.C_x̂min .= @views C_x̂min[nx̂+1:end] + size(con.A_X̂min, 1) ≠ 0 && (con.A_X̂min[:, end] = -con.C_x̂min) # for LinModel + end + if !isnothing(C_x̂max) + size(C_x̂max) == (nX̂con,) || throw(ArgumentError("C_x̂max size must be $((nX̂con,))")) + any(C_x̂max .< 0) && error("C_x̂max weights should be non-negative") + # if C is finite : x̃ = [ϵ; x̂] : + con.A_x̃max[end-nx̂+1:end, end] .= @views -C_x̂max[1:nx̂] + con.C_x̂max .= @views C_x̂max[nx̂+1:end] + size(con.A_X̂max, 1) ≠ 0 && (con.A_X̂max[:, end] = -con.C_x̂max) # for LinModel + end + if !isnothing(C_ŵmin) + size(C_ŵmin) == (nŵ*He,) || throw(ArgumentError("C_ŵmin size must be $((nŵ*He,))")) + any(C_ŵmin .< 0) && error("C_ŵmin weights should be non-negative") + con.A_Ŵmin[:, end] .= -C_ŵmin + end + if !isnothing(C_ŵmax) + size(C_ŵmax) == (nŵ*He,) || throw(ArgumentError("C_ŵmax size must be $((nŵ*He,))")) + any(C_ŵmax .< 0) && error("C_ŵmax weights should be non-negative") + con.A_Ŵmax[:, end] .= -C_ŵmax + end + if !isnothing(C_v̂min) + size(C_v̂min) == (nym*He,) || throw(ArgumentError("C_v̂min size must be $((nym*He,))")) + any(C_v̂min .< 0) && error("C_v̂min weights should be non-negative") + con.C_v̂min .= C_v̂min + size(con.A_V̂min, 1) ≠ 0 && (con.A_V̂min[:, end] = -con.C_v̂min) # for LinModel + end + if !isnothing(C_v̂max) + size(C_v̂max) == (nym*He,) || throw(ArgumentError("C_v̂max size must be $((nym*He,))")) + any(C_v̂max .< 0) && error("C_v̂max weights should be non-negative") + con.C_v̂max .= C_v̂max + size(con.A_V̂max, 1) ≠ 0 && (con.A_V̂max[:, end] = -con.C_v̂max) # for LinModel + end end i_x̃min, i_x̃max = .!isinf.(con.x̃0min), .!isinf.(con.x̃0max) i_X̂min, i_X̂max = .!isinf.(con.X̂0min), .!isinf.(con.X̂0max) From 2a67c9affcf23b55b5c62aa05cf696c115332d93 Mon Sep 17 00:00:00 2001 From: franckgaga Date: Wed, 3 Jul 2024 14:30:40 -0400 Subject: [PATCH 2/7] added: `Mwt`, `Nwt` and `Lwt` kwargs in `setmodel!` --- src/controller/construct.jl | 1 - src/controller/execute.jl | 54 ++++++++++++++++++++++++++------- test/test_predictive_control.jl | 26 +++++++++++++--- 3 files changed, 64 insertions(+), 17 deletions(-) diff --git a/src/controller/construct.jl b/src/controller/construct.jl index 4589180a..12c93080 100644 --- a/src/controller/construct.jl +++ b/src/controller/construct.jl @@ -268,7 +268,6 @@ function setconstraint!( size(con.A_x̂max, 1) ≠ 0 && (con.A_x̂max[:, end] .= -con.c_x̂max) # for LinModel end end - # TODO: test setmodel! new arguments i_Umin, i_Umax = .!isinf.(con.U0min), .!isinf.(con.U0max) i_ΔŨmin, i_ΔŨmax = .!isinf.(con.ΔŨmin), .!isinf.(con.ΔŨmax) i_Ymin, i_Ymax = .!isinf.(con.Y0min), .!isinf.(con.Y0max) diff --git a/src/controller/execute.jl b/src/controller/execute.jl index 5f80bca4..6c43e1b5 100644 --- a/src/controller/execute.jl +++ b/src/controller/execute.jl @@ -543,11 +543,13 @@ prediction horizon ``H_p``. Keyword arguments with *`emphasis`* are non-Unicode alternatives. - `mpc::PredictiveController` : controller to set model and weights. -- `model=mpc.estim.model` : new plant model ([`NonLinModel`](@ref) not supported). -- `M_Hp=mpc.M_Hp` : new ``\mathbf{M}_{H_p}`` weight matrix. -- `Ñ_Hc=mpc.Ñ_Hc` or *`Ntilde_Hc`* : new ``\mathbf{Ñ}_{H_c}`` weight matrix (see definition - above). -- `L_Hp=mpc.L_Hp` : new ``\mathbf{L}_{H_p}`` weight matrix. +- `model=mpc.estim.model` : new plant model (not supported by [`NonLinModel`](@ref)). +- `Mwt=nothing` : new main diagonal in ``\mathbf{M}`` weight matrix (vector). +- `Nwt=nothing` : new main diagonal in ``\mathbf{N}`` weight matrix (vector). +- `Lwt=nothing` : new main diagonal in ``\mathbf{L}`` weight matrix (vector). +- `M_Hp=nothing` : new ``\mathbf{M}_{H_p}`` weight matrix. +- `Ñ_Hc=nothing` or *`Ntilde_Hc`* : new ``\mathbf{Ñ}_{H_c}`` weight matrix (see def. above). +- `L_Hp=nothing` : new ``\mathbf{L}_{H_p}`` weight matrix. - additional keyword arguments are passed to `setmodel!(mpc.estim)`. # Examples @@ -566,18 +568,48 @@ julia> mpc.estim.model.A[], mpc.estim.R̂[], mpc.M_Hp[] function setmodel!( mpc::PredictiveController, model = mpc.estim.model; - M_Hp = mpc.M_Hp, - Ntilde_Hc = mpc.Ñ_Hc, - L_Hp = mpc.L_Hp, + Mwt = nothing, + Nwt = nothing, + Lwt = nothing, + M_Hp = nothing, + Ntilde_Hc = nothing, + L_Hp = nothing, Ñ_Hc = Ntilde_Hc, kwargs... ) x̂op_old = copy(mpc.estim.x̂op) nu, ny, Hp, Hc, nϵ = model.nu, model.ny, mpc.Hp, mpc.Hc, mpc.nϵ setmodel!(mpc.estim, model; kwargs...) - mpc.M_Hp .= to_hermitian(M_Hp) - mpc.Ñ_Hc .= to_hermitian(Ñ_Hc) - mpc.L_Hp .= to_hermitian(L_Hp) + if isnothing(M_Hp) && !isnothing(Mwt) + size(Mwt) == (ny,) || throw(ArgumentError("Mwt should be a vector of length ny")) + any(x -> x < 0, Mwt) && throw(ArgumentError("Mwt values should be nonnegative")) + for i=1:ny*Hp + mpc.M_Hp[i, i] = Mwt[(i-1) % ny + 1] + end + elseif !isnothing(M_Hp) + size(M_Hp) == (ny*Hp, ny*Hp) || throw(ArgumentError("M_Hp size should be (ny*Hp, ny*Hp)")) + mpc.M_Hp .= to_hermitian(M_Hp) + end + if isnothing(Ñ_Hc) && !isnothing(Nwt) + size(Nwt) == (nu,) || throw(ArgumentError("Nwt should be a vector of length nu")) + any(x -> x < 0, Nwt) && throw(ArgumentError("Nwt values should be nonnegative")) + for i=1:nu*Hc + mpc.Ñ_Hc[i, i] = Nwt[(i-1) % nu + 1] + end + elseif !isnothing(Ñ_Hc) + size(Ñ_Hc) == (nu*Hc+nϵ, nu*Hc+nϵ) || throw(ArgumentError("Ñ_Hc size should be (nu*Hc+nϵ, nu*Hc+nϵ)")) + mpc.Ñ_Hc .= to_hermitian(Ñ_Hc) + end + if isnothing(L_Hp) && !isnothing(Lwt) + size(Lwt) == (nu,) || throw(ArgumentError("Lwt should be a vector of length nu")) + any(x -> x < 0, Lwt) && throw(ArgumentError("Lwt values should be nonnegative")) + for i=1:nu*Hp + mpc.L_Hp[i, i] = Lwt[(i-1) % nu + 1] + end + elseif !isnothing(L_Hp) + size(L_Hp) == (nu*Hp, nu*Hp) || throw(ArgumentError("L_Hp size should be (nu*Hp, nu*Hp)")) + mpc.L_Hp .= to_hermitian(L_Hp) + end setmodel_controller!(mpc, x̂op_old, M_Hp, Ñ_Hc, L_Hp) return mpc end diff --git a/test/test_predictive_control.jl b/test/test_predictive_control.jl index 84f86031..cb12b8b8 100644 --- a/test/test_predictive_control.jl +++ b/test/test_predictive_control.jl @@ -260,7 +260,7 @@ end @testset "LinMPC set model" begin estim = KalmanFilter(setop!(LinModel(tf(5, [2, 1]), 3), yop=[10], uop=[1])) - mpc = LinMPC(estim, Nwt=[0], Hp=1000, Hc=1) + mpc = LinMPC(estim, Nwt=[0], Cwt=1e4, Hp=1000, Hc=1) mpc = setconstraint!(mpc, umin=[-24], umax=[26]) mpc = setconstraint!(mpc, ymin=[-54], ymax=[56]) @test mpc.Yop ≈ fill(10.0, 1000) @@ -286,6 +286,10 @@ end r = [40] u = moveinput!(mpc, r) @test u ≈ [13] atol=1e-2 + setmodel!(mpc, Mwt=[100], Nwt=[200], Lwt=[300]) + @test mpc.M_Hp ≈ diagm(fill(100, 1000)) + @test mpc.Ñ_Hc ≈ diagm([200, 1e4]) + @test mpc.L_Hp ≈ diagm(fill(300, 1000)) setmodel!(mpc, M_Hp=diagm(1:1000), Ñ_Hc=diagm([0.1;1e6]), L_Hp=diagm(1.1:1000.1)) @test mpc.M_Hp ≈ diagm(1:1000) @test mpc.Ñ_Hc ≈ diagm([0.1;1e6]) @@ -417,6 +421,10 @@ end r = [40] u = moveinput!(mpc, r) @test u ≈ [13] atol=1e-2 + setmodel!(mpc, Mwt=[100], Nwt=[200], Lwt=[300]) + @test mpc.M_Hp ≈ diagm(fill(100, 1000)) + @test mpc.Ñ_Hc ≈ diagm([200]) + @test mpc.L_Hp ≈ diagm(fill(300, 1000)) setmodel!(mpc, M_Hp=diagm(1:1000), Ñ_Hc=[0.1], L_Hp=diagm(1.1:1000.1)) @test mpc.M_Hp ≈ diagm(1:1000) @test mpc.Ñ_Hc ≈ [0.1] @@ -694,7 +702,7 @@ end @testset "NonLinMPC set model" begin estim = KalmanFilter(setop!(LinModel(tf(5, [2, 1]), 3), yop=[10], uop=[1])) - mpc = NonLinMPC(estim, Nwt=[0], Hp=1000, Hc=1) + mpc = NonLinMPC(estim, Nwt=[0], Cwt=1e4, Hp=1000, Hc=1) mpc = setconstraint!(mpc, umin=[-24], umax=[26]) mpc = setconstraint!(mpc, ymin=[-54], ymax=[56]) @test mpc.Yop ≈ fill(10.0, 1000) @@ -720,6 +728,10 @@ end r = [40] u = moveinput!(mpc, r) @test u ≈ [13] atol=1e-2 + setmodel!(mpc, Mwt=[100], Nwt=[200], Lwt=[300]) + @test mpc.M_Hp ≈ diagm(fill(100, 1000)) + @test mpc.Ñ_Hc ≈ diagm([200, 1e4]) + @test mpc.L_Hp ≈ diagm(fill(300, 1000)) setmodel!(mpc, M_Hp=diagm(1:1000), Ñ_Hc=diagm([0.1;1e6]), L_Hp=diagm(1.1:1000.1)) @test mpc.M_Hp ≈ diagm(1:1000) @test mpc.Ñ_Hc ≈ diagm([0.1;1e6]) @@ -727,10 +739,14 @@ end f(x,u,d) = estim.model.A*x + estim.model.Bu*u + estim.model.Bd*d h(x,d) = estim.model.C*x + estim.model.Du*d nonlinmodel = NonLinModel(f, h, 10.0, 1, 1, 1) - nmpc = NonLinMPC(nonlinmodel, Hp=1000, Hc=1) - setmodel!(nmpc, M_Hp=diagm(1:1000), Ñ_Hc=diagm([0.1;1e6]), L_Hp=diagm(1.1:1000.1)) + nmpc = NonLinMPC(nonlinmodel, Nwt=[0], Cwt=1e4, Hp=1000, Hc=10) + setmodel!(nmpc, Mwt=[100], Nwt=[200], Lwt=[300]) + @test nmpc.M_Hp ≈ diagm(fill(100, 1000)) + @test nmpc.Ñ_Hc ≈ diagm([fill(200, 10); 1e4]) + @test nmpc.L_Hp ≈ diagm(fill(300, 1000)) + setmodel!(nmpc, M_Hp=diagm(1:1000), Ñ_Hc=diagm([fill(0.1, 10);1e6]), L_Hp=diagm(1.1:1000.1)) @test nmpc.M_Hp ≈ diagm(1:1000) - @test nmpc.Ñ_Hc ≈ diagm([0.1;1e6]) + @test nmpc.Ñ_Hc ≈ diagm([fill(0.1, 10);1e6]) @test nmpc.L_Hp ≈ diagm(1.1:1000.1) @test_throws ErrorException setmodel!(nmpc, deepcopy(nonlinmodel)) end From 0be344b5c53d14234ea5b74d2ebda8de224cf5a9 Mon Sep 17 00:00:00 2001 From: franckgaga Date: Wed, 3 Jul 2024 14:33:26 -0400 Subject: [PATCH 3/7] bump --- Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Project.toml b/Project.toml index 195f126e..30a1c853 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "ModelPredictiveControl" uuid = "61f9bdb8-6ae4-484a-811f-bbf86720c31c" authors = ["Francis Gagnon"] -version = "0.22.0" +version = "0.22.1" [deps] ControlSystemsBase = "aaaaaaaa-a6ca-5380-bf3e-84a91bcd477e" From de25b56c5c0c3ee00d3cc49f7720fe59425bceb5 Mon Sep 17 00:00:00 2001 From: franckgaga Date: Wed, 3 Jul 2024 14:53:02 -0400 Subject: [PATCH 4/7] debug MHE `setconstraint!` --- src/controller/execute.jl | 15 +++++++++------ src/estimator/mhe/construct.jl | 8 ++++---- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/src/controller/execute.jl b/src/controller/execute.jl index 6c43e1b5..b1e3413c 100644 --- a/src/controller/execute.jl +++ b/src/controller/execute.jl @@ -581,33 +581,36 @@ function setmodel!( nu, ny, Hp, Hc, nϵ = model.nu, model.ny, mpc.Hp, mpc.Hc, mpc.nϵ setmodel!(mpc.estim, model; kwargs...) if isnothing(M_Hp) && !isnothing(Mwt) - size(Mwt) == (ny,) || throw(ArgumentError("Mwt should be a vector of length ny")) + size(Mwt) == (ny,) || throw(ArgumentError("Mwt should be a vector of length $ny")) any(x -> x < 0, Mwt) && throw(ArgumentError("Mwt values should be nonnegative")) for i=1:ny*Hp mpc.M_Hp[i, i] = Mwt[(i-1) % ny + 1] end elseif !isnothing(M_Hp) - size(M_Hp) == (ny*Hp, ny*Hp) || throw(ArgumentError("M_Hp size should be (ny*Hp, ny*Hp)")) + nŶ = ny*Hp + size(M_Hp) == (nŶ, nŶ) || throw(ArgumentError("M_Hp size should be ($nŶ, $nŶ)")) mpc.M_Hp .= to_hermitian(M_Hp) end if isnothing(Ñ_Hc) && !isnothing(Nwt) - size(Nwt) == (nu,) || throw(ArgumentError("Nwt should be a vector of length nu")) + size(Nwt) == (nu,) || throw(ArgumentError("Nwt should be a vector of length $nu")) any(x -> x < 0, Nwt) && throw(ArgumentError("Nwt values should be nonnegative")) for i=1:nu*Hc mpc.Ñ_Hc[i, i] = Nwt[(i-1) % nu + 1] end elseif !isnothing(Ñ_Hc) - size(Ñ_Hc) == (nu*Hc+nϵ, nu*Hc+nϵ) || throw(ArgumentError("Ñ_Hc size should be (nu*Hc+nϵ, nu*Hc+nϵ)")) + nΔŨ = nu*Hc+nϵ + size(Ñ_Hc) == (nΔŨ, nΔŨ) || throw(ArgumentError("Ñ_Hc size should be ($nΔŨ, $nΔŨ)")) mpc.Ñ_Hc .= to_hermitian(Ñ_Hc) end if isnothing(L_Hp) && !isnothing(Lwt) - size(Lwt) == (nu,) || throw(ArgumentError("Lwt should be a vector of length nu")) + size(Lwt) == (nu,) || throw(ArgumentError("Lwt should be a vector of length $nu")) any(x -> x < 0, Lwt) && throw(ArgumentError("Lwt values should be nonnegative")) for i=1:nu*Hp mpc.L_Hp[i, i] = Lwt[(i-1) % nu + 1] end elseif !isnothing(L_Hp) - size(L_Hp) == (nu*Hp, nu*Hp) || throw(ArgumentError("L_Hp size should be (nu*Hp, nu*Hp)")) + nU = nu*Hp + size(L_Hp) == (nU, nU) || throw(ArgumentError("L_Hp size should be ($nU, $nU)")) mpc.L_Hp .= to_hermitian(L_Hp) end setmodel_controller!(mpc, x̂op_old, M_Hp, Ñ_Hc, L_Hp) diff --git a/src/estimator/mhe/construct.jl b/src/estimator/mhe/construct.jl index 3299afba..de912777 100644 --- a/src/estimator/mhe/construct.jl +++ b/src/estimator/mhe/construct.jl @@ -466,7 +466,7 @@ function setconstraint!( con.X̂0max .= @views X̂max[nx̂+1:end] .- estim.X̂op end if isnothing(Ŵmin) && !isnothing(ŵmin) - size(ŵmin) == (nŵ*He,) || throw(ArgumentError("ŵmin size must be $((nŵ*He,))")) + size(ŵmin) == (nŵ,) || throw(ArgumentError("ŵmin size must be $((nŵ,))")) for i in 1:nŵ*He con.Ŵmin[i] = ŵmin[(i-1) % nŵ + 1] end @@ -475,7 +475,7 @@ function setconstraint!( con.Ŵmin .= Ŵmin end if isnothing(Ŵmax) && !isnothing(ŵmax) - size(ŵmax) == (nŵ*He,) || throw(ArgumentError("ŵmax size must be $((nŵ*He,))")) + size(ŵmax) == (nŵ,) || throw(ArgumentError("ŵmax size must be $((nŵ,))")) for i in 1:nŵ*He con.Ŵmax[i] = ŵmax[(i-1) % nŵ + 1] end @@ -484,7 +484,7 @@ function setconstraint!( con.Ŵmax .= Ŵmax end if isnothing(V̂min) && !isnothing(v̂min) - size(v̂min) == (nym*He,) || throw(ArgumentError("v̂min size must be $((nym*He,))")) + size(v̂min) == (nym,) || throw(ArgumentError("v̂min size must be $((nym,))")) for i in 1:nym*He con.V̂min[i] = v̂min[(i-1) % nym + 1] end @@ -493,7 +493,7 @@ function setconstraint!( con.V̂min .= V̂min end if isnothing(V̂max) && !isnothing(v̂max) - size(v̂max) == (nym*He,) || throw(ArgumentError("v̂max size must be $((nym*He,))")) + size(v̂max) == (nym,) || throw(ArgumentError("v̂max size must be $((nym,))")) for i in 1:nym*He con.V̂max[i] = v̂max[(i-1) % nym + 1] end From 38cd87b2adce63c8b3e73aed8713b273a0742b50 Mon Sep 17 00:00:00 2001 From: franckgaga Date: Wed, 3 Jul 2024 15:11:31 -0400 Subject: [PATCH 5/7] debug `setmodel!` for MPCs --- src/controller/execute.jl | 19 +++++++++++-------- src/general.jl | 3 ++- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/src/controller/execute.jl b/src/controller/execute.jl index b1e3413c..8ef0f7ea 100644 --- a/src/controller/execute.jl +++ b/src/controller/execute.jl @@ -556,13 +556,13 @@ prediction horizon ``H_p``. ```jldoctest julia> mpc = LinMPC(KalmanFilter(LinModel(ss(0.1, 0.5, 1, 0, 4.0)), σR=[√25]), Hp=1, Hc=1); -julia> mpc.estim.model.A[], mpc.estim.R̂[], mpc.M_Hp[] -(0.1, 25.0, 1.0) +julia> mpc.estim.model.A[1], mpc.estim.R̂[1], mpc.M_Hp[1], mpc.Ñ_Hc[1] +(0.1, 25.0, 1.0, 0.1) -julia> setmodel!(mpc, LinModel(ss(0.42, 0.5, 1, 0, 4.0)); R̂=[9], M_Hp=[0]); +julia> setmodel!(mpc, LinModel(ss(0.42, 0.5, 1, 0, 4.0)); R̂=[9], M_Hp=[10], Nwt=[0.666]); -julia> mpc.estim.model.A[], mpc.estim.R̂[], mpc.M_Hp[] -(0.42, 9.0, 0.0) +julia> mpc.estim.model.A[1], mpc.estim.R̂[1], mpc.M_Hp[1], mpc.Ñ_Hc[1] +(0.42, 9.0, 10.0, 0.666) ``` """ function setmodel!( @@ -587,9 +587,10 @@ function setmodel!( mpc.M_Hp[i, i] = Mwt[(i-1) % ny + 1] end elseif !isnothing(M_Hp) + M_Hp = to_hermitian(M_Hp) nŶ = ny*Hp size(M_Hp) == (nŶ, nŶ) || throw(ArgumentError("M_Hp size should be ($nŶ, $nŶ)")) - mpc.M_Hp .= to_hermitian(M_Hp) + mpc.M_Hp .= M_Hp end if isnothing(Ñ_Hc) && !isnothing(Nwt) size(Nwt) == (nu,) || throw(ArgumentError("Nwt should be a vector of length $nu")) @@ -598,9 +599,10 @@ function setmodel!( mpc.Ñ_Hc[i, i] = Nwt[(i-1) % nu + 1] end elseif !isnothing(Ñ_Hc) + Ñ_Hc = to_hermitian(Ñ_Hc) nΔŨ = nu*Hc+nϵ size(Ñ_Hc) == (nΔŨ, nΔŨ) || throw(ArgumentError("Ñ_Hc size should be ($nΔŨ, $nΔŨ)")) - mpc.Ñ_Hc .= to_hermitian(Ñ_Hc) + mpc.Ñ_Hc .= Ñ_Hc end if isnothing(L_Hp) && !isnothing(Lwt) size(Lwt) == (nu,) || throw(ArgumentError("Lwt should be a vector of length $nu")) @@ -609,9 +611,10 @@ function setmodel!( mpc.L_Hp[i, i] = Lwt[(i-1) % nu + 1] end elseif !isnothing(L_Hp) + L_Hp = to_hermitian(L_Hp) nU = nu*Hp size(L_Hp) == (nU, nU) || throw(ArgumentError("L_Hp size should be ($nU, $nU)")) - mpc.L_Hp .= to_hermitian(L_Hp) + mpc.L_Hp .= L_Hp end setmodel_controller!(mpc, x̂op_old, M_Hp, Ñ_Hc, L_Hp) return mpc diff --git a/src/general.jl b/src/general.jl index b08232b1..e40bd448 100644 --- a/src/general.jl +++ b/src/general.jl @@ -47,4 +47,5 @@ repeatdiag(A, n::Int) = kron(I(n), A) "Convert 1-element vectors and normal matrices to Hermitians." to_hermitian(A::AbstractVector) = Hermitian(reshape(A, 1, 1), :L) to_hermitian(A::AbstractMatrix) = Hermitian(A, :L) -to_hermitian(A::Hermitian) = A \ No newline at end of file +to_hermitian(A::Hermitian) = A +to_hermitian(A) = A \ No newline at end of file From afa1474611b9b54ac6187d312f46fe7edb398a3d Mon Sep 17 00:00:00 2001 From: franckgaga Date: Wed, 3 Jul 2024 15:14:50 -0400 Subject: [PATCH 6/7] added: non-unicode kwargs for `setmodel!` on estimators --- src/estimator/execute.jl | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/estimator/execute.jl b/src/estimator/execute.jl index cc5c0548..93a70c6c 100644 --- a/src/estimator/execute.jl +++ b/src/estimator/execute.jl @@ -254,11 +254,13 @@ time must stay the same. Note that the observability and controllability of the augmented model is not verified (see Extended Help for more info). # Arguments +!!! info + Keyword arguments with *`emphasis`* are non-Unicode alternatives. - `estim::StateEstimator` : estimator to set model and covariances. - `model=estim.model` : new plant model ([`NonLinModel`](@ref) not supported). -- `Q̂=nothing` : new augmented model ``\mathbf{Q̂}`` covariance matrix. -- `R̂=nothing` : new augmented model ``\mathbf{R̂}`` covariance matrix. +- `Q̂=nothing` or *`Qhat`* : new augmented model ``\mathbf{Q̂}`` covariance matrix. +- `R̂=nothing` or *`Rhat`* : new augmented model ``\mathbf{R̂}`` covariance matrix. # Examples ```jldoctest @@ -283,8 +285,10 @@ julia> kf.model.A[], kf.Q̂[1, 1], kf.Q̂[2, 2] function setmodel!( estim::StateEstimator, model = estim.model; - Q̂ = nothing, - R̂ = nothing + Qhat = nothing, + Rhat = nothing, + Q̂ = Qhat, + R̂ = Rhat ) uop_old = copy(estim.model.uop) yop_old = copy(estim.model.yop) From 2065d2fb20239e922a7e96f663d99cb295264051 Mon Sep 17 00:00:00 2001 From: franckgaga Date: Wed, 3 Jul 2024 15:36:22 -0400 Subject: [PATCH 7/7] details in doc --- src/estimator/execute.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/estimator/execute.jl b/src/estimator/execute.jl index 93a70c6c..820efd7d 100644 --- a/src/estimator/execute.jl +++ b/src/estimator/execute.jl @@ -258,7 +258,7 @@ augmented model is not verified (see Extended Help for more info). Keyword arguments with *`emphasis`* are non-Unicode alternatives. - `estim::StateEstimator` : estimator to set model and covariances. -- `model=estim.model` : new plant model ([`NonLinModel`](@ref) not supported). +- `model=estim.model` : new plant model (not supported by [`NonLinModel`](@ref)). - `Q̂=nothing` or *`Qhat`* : new augmented model ``\mathbf{Q̂}`` covariance matrix. - `R̂=nothing` or *`Rhat`* : new augmented model ``\mathbf{R̂}`` covariance matrix.