Skip to content

Commit 27d5943

Browse files
committed
added: xbar and Vhat combined
1 parent a354030 commit 27d5943

File tree

2 files changed

+50
-44
lines changed

2 files changed

+50
-44
lines changed

src/estimator/mhe.jl

Lines changed: 48 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -276,7 +276,7 @@ function init_defaultcon_mhe(model::SimModel{NT}, He, nx̂) where {NT<:Real}
276276
con = EstimatorConstraint{NT}(X̂min, X̂max, x̂min, x̂max, A_x̂min, A_x̂max, A, b, i_b, i_g)
277277
end
278278

279-
279+
# TODO: MODIFIER L'EQ ET LA MÉTHODE POUR QUE E ET F CONTIENNE AUSSI LE STOCK DE XBAR
280280

281281
@doc raw"""
282282
init_predmat_mhe(model::LinModel{NT}, He, i_ym, Â, B̂u, Ĉ, B̂d, D̂d) -> E, F, G, J, ex̄, fx̄
@@ -288,9 +288,10 @@ Introducing the decision variables vector ``\mathbf{Z} =
288288
estimated sensor noise over the time window is given by:
289289
```math
290290
\begin{aligned}
291-
\mathbf{V̂} &= \mathbf{Y^m - Ŷ^m} \\
292-
&= \mathbf{Y^m - (E Z + G U + J D)} \\
293-
&= \mathbf{Y^m - (E Z + F)}
291+
[\begin{smallmatrix}\mathbf{x̄} \\ \mathbf{V̂} \end{smallmatrix}]
292+
&= \mathbf{Y^m - Ŷ^m} \\
293+
&= \mathbf{Y^m - (E Z + G U + J D)} \\
294+
&= \mathbf{Y^m - (E Z + F)}
294295
\end{aligned}
295296
in which ``Y^m``, ``U`` and ``D`` contains respectively the measured outputs, manipulated
296297
inputs and measured disturbances from time ``k-N_k+1`` to ``k``. The method also returns
@@ -386,7 +387,7 @@ function init_optimization!(
386387
estim::MovingHorizonEstimator, model::SimModel, optim::JuMP.GenericModel{JNT},
387388
) where JNT<:Real
388389
He, con = estim.He, estim.con
389-
nV̂, nX̂, ng = He*estim.nym, He*estim.nx̂, length(con.i_g)
390+
nx̄V̂, nX̂, ng = estim.nx̂ + He*estim.nym, He*estim.nx̂, length(con.i_g)
390391
# --- variables and linear constraints ---
391392
nvar = length(estim.Z̃)
392393
set_silent(optim)
@@ -397,42 +398,42 @@ function init_optimization!(
397398
@constraint(optim, linconstraint, A*Z̃var .≤ b)
398399
# --- nonlinear optimization init ---
399400
# see init_optimization!(mpc::NonLinMPC, optim) for details on the inspiration
400-
Jfunc, gfunc = let estim=estim, model=model, nvar=nvar , nV̂=nV̂, nX̂=nX̂, ng=ng
401+
Jfunc, gfunc = let estim=estim, model=model, nvar=nvar , nx̄V̂=nx̄V̂, nX̂=nX̂, ng=ng
401402
last_Z̃tup_float, last_Z̃tup_dual = nothing, nothing
402-
V̂_cache::DiffCache{Vector{JNT}, Vector{JNT}} = DiffCache(zeros(JNT, nV̂), nvar + 3)
403-
g_cache::DiffCache{Vector{JNT}, Vector{JNT}} = DiffCache(zeros(JNT, ng), nvar + 3)
404-
X̂_cache::DiffCache{Vector{JNT}, Vector{JNT}} = DiffCache(zeros(JNT, nX̂), nvar + 3)
403+
x̄V̂_cache::DiffCache{Vector{JNT}, Vector{JNT}} = DiffCache(zeros(JNT, nx̄V̂), nvar + 3)
404+
g_cache ::DiffCache{Vector{JNT}, Vector{JNT}} = DiffCache(zeros(JNT, ng), nvar + 3)
405+
X̂_cache ::DiffCache{Vector{JNT}, Vector{JNT}} = DiffCache(zeros(JNT, nX̂), nvar + 3)
405406
function Jfunc(Z̃tup::JNT...)
406-
= get_tmp(V̂_cache, Z̃tup[1])
407+
x̄V̂ = get_tmp(x̄V̂_cache, Z̃tup[1])
407408
= collect(Z̃tup)
408409
if Z̃tup !== last_Z̃tup_float
409410
g = get_tmp(g_cache, Z̃tup[1])
410411
= get_tmp(X̂_cache, Z̃tup[1])
411-
, X̂ = predict!(, X̂, estim, model, Z̃)
412+
x̄V̂, X̂ = predict!(x̄V̂, X̂, estim, model, Z̃)
412413
g = con_nonlinprog!(g, estim, model, X̂)
413414
last_Z̃tup_float = Z̃tup
414415
end
415-
return obj_nonlinprog(estim, model, , Z̃)
416+
return obj_nonlinprog(estim, model, x̄V̂, Z̃)
416417
end
417418
function Jfunc(Z̃tup::ForwardDiff.Dual...)
418-
= get_tmp(V̂_cache, Z̃tup[1])
419+
x̄V̂ = get_tmp(x̄V̂_cache, Z̃tup[1])
419420
= collect(Z̃tup)
420421
if Z̃tup !== last_Z̃tup_dual
421422
g = get_tmp(g_cache, Z̃tup[1])
422423
= get_tmp(X̂_cache, Z̃tup[1])
423-
, X̂ = predict!(, X̂, estim, model, Z̃)
424+
x̄V̂, X̂ = predict!(x̄V̂, X̂, estim, model, Z̃)
424425
g = con_nonlinprog!(g, estim, model, X̂)
425426
last_Z̃tup_dual = Z̃tup
426427
end
427-
return obj_nonlinprog(estim, model, , Z̃)
428+
return obj_nonlinprog(estim, model, x̄V̂, Z̃)
428429
end
429430
function gfunc_i(i, Z̃tup::NTuple{N, JNT}) where N
430431
g = get_tmp(g_cache, Z̃tup[1])
431432
if Z̃tup !== last_Z̃tup_float
432-
= get_tmp(V̂_cache, Z̃tup[1])
433-
= get_tmp(X̂_cache, Z̃tup[1])
434-
= collect(Z̃tup)
435-
, X̂ = predict!(, X̂, estim, model, Z̃)
433+
x̄V̂ = get_tmp(x̄V̂_cache, Z̃tup[1])
434+
= get_tmp(X̂_cache, Z̃tup[1])
435+
= collect(Z̃tup)
436+
x̄V̂, X̂ = predict!(x̄V̂, X̂, estim, model, Z̃)
436437
g = con_nonlinprog!(g, estim, model, X̂)
437438
last_Z̃tup_float = Z̃tup
438439
end
@@ -441,10 +442,10 @@ function init_optimization!(
441442
function gfunc_i(i, Z̃tup::NTuple{N, ForwardDiff.Dual}) where N
442443
g = get_tmp(g_cache, Z̃tup[1])
443444
if Z̃tup !== last_Z̃tup_dual
444-
= get_tmp(V̂_cache, Z̃tup[1])
445-
= get_tmp(X̂_cache, Z̃tup[1])
445+
x̄V̂ = get_tmp(x̄V̂_cache, Z̃tup[1])
446+
= get_tmp(X̂_cache, Z̃tup[1])
446447
= collect(Z̃tup)
447-
, X̂ = predict!(, X̂, estim, model, Z̃)
448+
x̄V̂, X̂ = predict!(x̄V̂, X̂, estim, model, Z̃)
448449
g = con_nonlinprog!(g, estim, model, X̂)
449450
last_Z̃tup_dual = Z̃tup
450451
end
@@ -514,6 +515,10 @@ function setconstraint!(
514515
estim::MovingHorizonEstimator;
515516
x̂min = nothing, x̂max = nothing,
516517
X̂min = nothing, X̂max = nothing,
518+
ŵmin = nothing, ŵmax = nothing,
519+
Ŵmin = nothing, Ŵmax = nothing,
520+
v̂min = nothing, v̂max = nothing,
521+
V̂min = nothing, V̂max = nothing,
517522
)
518523
model, optim, con = estim.model, estim.optim, estim.con
519524
nx̂, He = estim.nx̂, estim.He
@@ -644,11 +649,11 @@ function update_estimate!(estim::MovingHorizonEstimator{NT}, u, ym, d) where NT<
644649
Nk = estim.Nk[]
645650
nŴ, nYm, nX̂ = nx̂*Nk, nym*Nk, nx̂*Nk
646651
Z̃var::Vector{VariableRef} = optim[:Z̃var]
647-
Ŷm = Vector{NT}(undef, nYm)
652+
x̄V̂ = Vector{NT}(undef, nx̂ + nYm)
648653
= Vector{NT}(undef, nX̂)
649654
Z̃0 = [estim.x̂arr_old; estim.Ŵ]
650-
Ŷm, X̂ = predict!(Ŷm, X̂, estim, model, Z̃0)
651-
J0 = obj_nonlinprog(estim, model, Ŷm, Z̃0)
655+
x̄V̂, X̂ = predict!(x̄V̂, X̂, estim, model, Z̃0)
656+
J0 = obj_nonlinprog(estim, model, x̄V̂, Z̃0)
652657
# initial Z̃0 with Ŵ=0 if objective or constraint function not finite :
653658
isfinite(J0) || (Z̃0 = [estim.x̂arr_old; zeros(NT, nŴ)])
654659
set_start_value.(Z̃var, Z̃0)
@@ -683,7 +688,7 @@ function update_estimate!(estim::MovingHorizonEstimator{NT}, u, ym, d) where NT<
683688
estim.Z̃[:] = !isfatal(status) ? Z̃curr : Z̃last
684689
# --------- update estimate -----------------------
685690
estim.Ŵ[1:nŴ] = estim.Z̃[nx̂+1:nx̂+nŴ] # update Ŵ with optimum for next time step
686-
Ŷm, X̂ = predict!(Ŷm, X̂, estim, model, estim.Z̃)
691+
x̄V̂, X̂ = predict!(x̄V̂, X̂, estim, model, estim.Z̃)
687692
x̂[:] = X̂[(1 + nx̂*(Nk-1)):(nx̂*Nk)]
688693
if Nk == He
689694
uarr, ymarr, darr = estim.U[1:nu], estim.Ym[1:nym], estim.D[1:nd]
@@ -739,54 +744,55 @@ end
739744

740745

741746
function obj_nonlinprog(
742-
estim::MovingHorizonEstimator, ::LinModel, Ŷm, Z̃::Vector{T}
747+
estim::MovingHorizonEstimator, ::LinModel, x̄V̂, Z̃::Vector{T}
743748
) where {T<:Real}
744-
return obj_quadprog(Z̃, estim.H̃, estim.q̃)
749+
return obj_quadprog(Z̃, estim.H̃, estim.q̃) + estim.p[]
745750
end
746751

747752
"""
748-
obj_nonlinprog(estim::MovingHorizonEstimator, model::SimModel, , Z̃)
753+
obj_nonlinprog(estim::MovingHorizonEstimator, model::SimModel, x̄V̂, Z̃)
749754
750755
Objective function for the [`MovingHorizonEstimator`](@ref).
751756
752757
The function `dot(x, A, x)` is a performant way of calculating `x'*A*x`.
753758
"""
754759
function obj_nonlinprog(
755-
estim::MovingHorizonEstimator, ::SimModel, , Z̃::Vector{T}
760+
estim::MovingHorizonEstimator, ::SimModel, x̄V̂, Z̃::Vector{T}
756761
) where {T<:Real}
757762
Nk = estim.Nk[]
758763
nYm, nŴ, nx̂, invP̄ = Nk*estim.nym, Nk*estim.nx̂, estim.nx̂, estim.invP̄
759764
invQ̂_Nk, invR̂_Nk = @views estim.invQ̂_He[1:nŴ, 1:nŴ], estim.invR̂_He[1:nYm, 1:nYm]
760-
x̂arr = @views Z̃[1:nx̂]
761-
= estim.x̂arr_old - x̂arr
765+
= @views x̄V̂[1:nx̂]
762766
= @views Z̃[nx̂+1:nx̂+nŴ]
763-
= @views V̂[1:nYm]
767+
= @views x̄V̂[nx̂+1:nx̂+nYm]
764768
return dot(x̄, invP̄, x̄) + dot(Ŵ, invQ̂_Nk, Ŵ) + dot(V̂, invR̂_Nk, V̂)
765769
end
766770

767771
"""
768-
predict!(, X̂, estim::MovingHorizonEstimator, model::SimModel, Z̃) -> , X̂
772+
predict!(x̄V̂, X̂, estim::MovingHorizonEstimator, model::SimModel, Z̃) -> x̄V̂, X̂
769773
770-
Compute the estimated sensor noises `V̂` and states `X̂` for the `MovingHorizonEstimator`.
774+
Compute the `x̄V̂` vector and `X̂` vectors for the `MovingHorizonEstimator`.
771775
772-
The method mutates `V̂` and `X̂` vector arguments. Note that `V̂` goes from ``k-N_k+1`` to
773-
``k``, and `X̂`, from ``k-N_k+2`` to ``k+1``.
776+
The method mutates `x̄V̂` and `X̂` vector arguments. The vector `x̄V̂` is a concatenation of the
777+
estimated error at arrival `x̄` and the sensor noises `V̂` from ``k-N_k+1`` to ``k``. The `X̂`
778+
vector is estimated states from ``k-N_k+2`` to ``k+1``.
774779
"""
775780
function predict!(
776-
, X̂, estim::MovingHorizonEstimator, model::SimModel, Z̃::Vector{T}
781+
x̄V̂, X̂, estim::MovingHorizonEstimator, model::SimModel, Z̃::Vector{T}
777782
) where {T<:Real}
778783
nu, nd, nx̂, nym, Nk = model.nu, model.nd, estim.nx̂, estim.nym, estim.Nk[]
779-
= @views Z̃[1:nx̂] # Z̃ = [x̂(k-Nk+1|k); Ŵ]
784+
= @views Z̃[1:nx̂]
785+
x̄V̂[1:nx̂] = estim.x̂arr_old -
780786
for j=1:Nk
781787
u = @views estim.U[ (1 + nu* (j-1)):(nu*j)]
782788
ym = @views estim.Ym[(1 + nym*(j-1)):(nym*j)]
783789
d = @views estim.D[ (1 + nd* (j-1)):(nd*j)]
784790
= @views Z̃[(1 + nx̂*j):(nx̂*(j+1))]
785-
[(1 + nym*(j-1)):(nym*j)] = ym - (estim, model, x̂, d)[estim.i_ym]
786-
X̂[(1 + nx̂ *(j-1)):(nx̂ *j)] = (estim, model, x̂, u, d) +
791+
x̄V̂[(1 + nx̂ + nym*(j-1)):(nx̂ + nym*j)] = ym - (estim, model, x̂, d)[estim.i_ym]
792+
X̂[(1 + nx̂*(j-1)):(nx̂ *j)] = (estim, model, x̂, u, d) +
787793
= @views X̂[(1 + nx̂*(j-1)):(nx̂*j)]
788794
end
789-
return , X̂
795+
return x̄V̂, X̂
790796
end
791797

792798
"""

src/predictive_control.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -427,7 +427,7 @@ function getinfo(mpc::PredictiveController{NT}) where NT<:Real
427427
Ŷ, x̂end = predict!(Ŷ, x̂, mpc, mpc.estim.model, mpc.ΔŨ)
428428
info[:ΔU] = mpc.ΔŨ[1:mpc.Hc*mpc.estim.model.nu]
429429
info[] = isinf(mpc.C) ? NaN : mpc.ΔŨ[end]
430-
info[:J] = obj_nonlinprog(mpc, mpc.estim.model, Ŷ, mpc.ΔŨ) + mpc.p[]
430+
info[:J] = obj_nonlinprog(mpc, mpc.estim.model, Ŷ, mpc.ΔŨ)
431431
info[:U] = mpc.*mpc.ΔŨ + mpc.T*(mpc.estim.lastu0 + mpc.estim.model.uop)
432432
info[:u] = info[:U][1:mpc.estim.model.nu]
433433
info[:d] = mpc.d0 + mpc.estim.model.dop
@@ -947,7 +947,7 @@ at specific input increments `ΔŨ` and predictions `Ŷ` values.
947947
function obj_nonlinprog(
948948
mpc::PredictiveController, model::LinModel, Ŷ, ΔŨ::Vector{NT}
949949
) where {NT<:Real}
950-
J = obj_quadprog(ΔŨ, mpc.H̃, mpc.q̃)
950+
J = obj_quadprog(ΔŨ, mpc.H̃, mpc.q̃) + mpc.p[]
951951
if !iszero(mpc.E)
952952
U = mpc.*ΔŨ + mpc.T*(mpc.estim.lastu0 + model.uop)
953953
UE = [U; U[(end - model.nu + 1):end]]

0 commit comments

Comments
 (0)