Skip to content

Commit 6e2fc12

Browse files
committed
added : field in MHE
1 parent f349e19 commit 6e2fc12

File tree

3 files changed

+45
-43
lines changed

3 files changed

+45
-43
lines changed

src/estimator/mhe.jl

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,7 @@ end
1515
function print_estim_dim(io::IO, estim::MovingHorizonEstimator, n)
1616
nu, nd = estim.model.nu, estim.model.nd
1717
nx̂, nym, nyu = estim.nx̂, estim.nym, estim.nyu
18-
He = estim.He
19-
= isinf(estim.C) ? 0 : 1
18+
He, nϵ = estim.He, estim.
2019
println(io, "$(lpad(He, n)) estimation steps He")
2120
println(io, "$(lpad(nϵ, n)) slack variable ϵ (estimation constraints)")
2221
println(io, "$(lpad(nu, n)) manipulated inputs u ($(sum(estim.nint_u)) integrating states)")

src/estimator/mhe/construct.jl

Lines changed: 27 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ struct MovingHorizonEstimator{
6060
f̂op::Vector{NT}
6161
x̂0 ::Vector{NT}
6262
He::Int
63+
::Int
6364
i_ym::Vector{Int}
6465
nx̂ ::Int
6566
nym::Int
@@ -125,7 +126,9 @@ struct MovingHorizonEstimator{
125126
)
126127
# dummy values (updated just before optimization):
127128
F, fx̄, Fx̂ = zeros(NT, nym*He), zeros(NT, nx̂), zeros(NT, nx̂*He)
128-
con, Ẽ, ẽx̄ = init_defaultcon_mhe(model, He, Cwt, nx̂, nym, E, ex̄, Ex̂, Fx̂, Gx̂, Jx̂, Bx̂)
129+
con, nϵ, Ẽ, ẽx̄ = init_defaultcon_mhe(
130+
model, He, Cwt, nx̂, nym, E, ex̄, Ex̂, Fx̂, Gx̂, Jx̂, Bx̂
131+
)
129132
nZ̃ = size(Ẽ, 2)
130133
# dummy values, updated before optimization:
131134
H̃, q̃, p = Hermitian(zeros(NT, nZ̃, nZ̃), :L), zeros(NT, nZ̃), zeros(NT, 1)
@@ -140,7 +143,7 @@ struct MovingHorizonEstimator{
140143
estim = new{NT, SM, JM, CE}(
141144
model, optim, con, covestim,
142145
Z̃, lastu0, x̂op, f̂op, x̂0,
143-
He,
146+
He, nϵ,
144147
i_ym, nx̂, nym, nyu, nxs,
145148
As, Cs_u, Cs_y, nint_u, nint_ym,
146149
Â, B̂u, Ĉ, B̂d, D̂d,
@@ -641,6 +644,7 @@ function init_defaultcon_mhe(
641644
) where {NT<:Real}
642645
nŵ = nx̂
643646
nZ̃, nX̂, nŴ, nYm = nx̂+nŵ*He, nx̂*He, nŵ*He, nym*He
647+
= isinf(C) ? 0 : 1
644648
x̂min, x̂max = fill(convert(NT,-Inf), nx̂), fill(convert(NT,+Inf), nx̂)
645649
X̂min, X̂max = fill(convert(NT,-Inf), nX̂), fill(convert(NT,+Inf), nX̂)
646650
Ŵmin, Ŵmax = fill(convert(NT,-Inf), nŴ), fill(convert(NT,+Inf), nŴ)
@@ -649,10 +653,10 @@ function init_defaultcon_mhe(
649653
C_x̂min, C_x̂max = fill(0.0, nX̂), fill(0.0, nX̂)
650654
C_ŵmin, C_ŵmax = fill(0.0, nŴ), fill(0.0, nŴ)
651655
C_v̂min, C_v̂max = fill(0.0, nYm), fill(0.0, nYm)
652-
A_x̃min, A_x̃max, x̃min, x̃max, ẽx̄ = relaxarrival(model, C, c_x̂min, c_x̂max, x̂min, x̂max, ex̄)
653-
A_X̂min, A_X̂max, Ẽx̂ = relaxX̂(model, C, C_x̂min, C_x̂max, Ex̂)
654-
A_Ŵmin, A_Ŵmax = relaxŴ(model, C, C_ŵmin, C_ŵmax, nx̂)
655-
A_V̂min, A_V̂max, Ẽ = relaxV̂(model, C, C_v̂min, C_v̂max, E)
656+
A_x̃min, A_x̃max, x̃min, x̃max, ẽx̄ = relaxarrival(model, , c_x̂min, c_x̂max, x̂min, x̂max, ex̄)
657+
A_X̂min, A_X̂max, Ẽx̂ = relaxX̂(model, , C_x̂min, C_x̂max, Ex̂)
658+
A_Ŵmin, A_Ŵmax = relaxŴ(model, , C_ŵmin, C_ŵmax, nx̂)
659+
A_V̂min, A_V̂max, Ẽ = relaxV̂(model, , C_v̂min, C_v̂max, E)
656660
i_x̃min, i_x̃max = .!isinf.(x̃min), .!isinf.(x̃max)
657661
i_X̂min, i_X̂max = .!isinf.(X̂min), .!isinf.(X̂max)
658662
i_Ŵmin, i_Ŵmax = .!isinf.(Ŵmin), .!isinf.(Ŵmax)
@@ -670,12 +674,12 @@ function init_defaultcon_mhe(
670674
C_x̂min, C_x̂max, C_v̂min, C_v̂max,
671675
i_b, i_g
672676
)
673-
return con, Ẽ, ẽx̄
677+
return con, nϵ, Ẽ, ẽx̄
674678
end
675679

676680
@doc raw"""
677681
relaxarrival(
678-
model::SimModel, C, c_x̂min, c_x̂max, x̂min, x̂max, ex̄
682+
model::SimModel, , c_x̂min, c_x̂max, x̂min, x̂max, ex̄
679683
) -> A_x̃min, A_x̃max, x̃min, x̃max, ẽx̄
680684
681685
Augment arrival state constraints with slack variable ϵ for softening the MHE.
@@ -700,9 +704,9 @@ in which
700704
``\mathbf{x̃_{max}} = [\begin{smallmatrix} ∞ \\ \mathbf{x̂_{max}} \end{smallmatrix}]`` and
701705
``\mathbf{x̃_{op}} = [\begin{smallmatrix} 0 \\ \mathbf{x̂_{op}} \end{smallmatrix}]``
702706
"""
703-
function relaxarrival(::SimModel{NT}, C, c_x̂min, c_x̂max, x̂min, x̂max, ex̄) where {NT<:Real}
707+
function relaxarrival(::SimModel{NT}, , c_x̂min, c_x̂max, x̂min, x̂max, ex̄) where {NT<:Real}
704708
ex̂ = -ex̄
705-
if !isinf(C) # Z̃ = [ϵ; Z]
709+
if 0 # Z̃ = [ϵ; Z]
706710
x̃min, x̃max = [NT[0.0]; x̂min], [NT[Inf]; x̂max]
707711
A_ϵ = [NT[1.0] zeros(NT, 1, size(ex̂, 2))]
708712
# ϵ impacts arrival state constraint calculations:
@@ -718,7 +722,7 @@ function relaxarrival(::SimModel{NT}, C, c_x̂min, c_x̂max, x̂min, x̂max, ex
718722
end
719723

720724
@doc raw"""
721-
relaxX̂(model::SimModel, C, C_x̂min, C_x̂max, Ex̂) -> A_X̂min, A_X̂max, Ẽx̂
725+
relaxX̂(model::SimModel, , C_x̂min, C_x̂max, Ex̂) -> A_X̂min, A_X̂max, Ẽx̂
722726
723727
Augment estimated state constraints with slack variable ϵ for softening the MHE.
724728
@@ -739,8 +743,8 @@ also returns the ``\mathbf{A}`` matrices for the inequality constraints:
739743
in which ``\mathbf{X̂_{min}, X̂_{max}}`` and ``\mathbf{X̂_{op}}`` vectors respectively contains
740744
``\mathbf{x̂_{min}, x̂_{max}}`` and ``\mathbf{x̂_{op}}`` repeated ``H_e`` times.
741745
"""
742-
function relaxX̂(::LinModel{NT}, C, C_x̂min, C_x̂max, Ex̂) where {NT<:Real}
743-
if !isinf(C) # Z̃ = [ϵ; Z]
746+
function relaxX̂(::LinModel{NT}, , C_x̂min, C_x̂max, Ex̂) where {NT<:Real}
747+
if 0 # Z̃ = [ϵ; Z]
744748
# ϵ impacts estimated process noise constraint calculations:
745749
A_X̂min, A_X̂max = -[C_x̂min Ex̂], [-C_x̂max Ex̂]
746750
# ϵ has no impact on estimated process noises:
@@ -753,14 +757,14 @@ function relaxX̂(::LinModel{NT}, C, C_x̂min, C_x̂max, Ex̂) where {NT<:Real}
753757
end
754758

755759
"Return empty matrices if model is not a [`LinModel`](@ref)"
756-
function relaxX̂(::SimModel{NT}, C, C_x̂min, C_x̂max, Ex̂) where {NT<:Real}
757-
Ẽx̂ = !isinf(C) ? [zeros(NT, 0, 1) Ex̂] : Ex̂
760+
function relaxX̂(::SimModel{NT}, , C_x̂min, C_x̂max, Ex̂) where {NT<:Real}
761+
Ẽx̂ = [zeros(NT, 0, ) Ex̂]
758762
A_X̂min, A_X̂max = -Ẽx̂, Ẽx̂
759763
return A_X̂min, A_X̂max, Ẽx̂
760764
end
761765

762766
@doc raw"""
763-
relaxŴ(model::SimModel, C, C_ŵmin, C_ŵmax, nx̂) -> A_Ŵmin, A_Ŵmax
767+
relaxŴ(model::SimModel, , C_ŵmin, C_ŵmax, nx̂) -> A_Ŵmin, A_Ŵmax
764768
765769
Augment estimated process noise constraints with slack variable ϵ for softening the MHE.
766770
@@ -778,9 +782,9 @@ matrices for the inequality constraints:
778782
\end{bmatrix}
779783
```
780784
"""
781-
function relaxŴ(::SimModel{NT}, C, C_ŵmin, C_ŵmax, nx̂) where {NT<:Real}
785+
function relaxŴ(::SimModel{NT}, , C_ŵmin, C_ŵmax, nx̂) where {NT<:Real}
782786
A = [zeros(NT, length(C_ŵmin), nx̂) I]
783-
if !isinf(C) # Z̃ = [ϵ; Z]
787+
if 0 # Z̃ = [ϵ; Z]
784788
A_Ŵmin, A_Ŵmax = -[C_ŵmin A], [-C_ŵmax A]
785789
else # Z̃ = Z (only hard constraints)
786790
A_Ŵmin, A_Ŵmax = -A, A
@@ -789,7 +793,7 @@ function relaxŴ(::SimModel{NT}, C, C_ŵmin, C_ŵmax, nx̂) where {NT<:Real}
789793
end
790794

791795
@doc raw"""
792-
relaxV̂(model::SimModel, C, C_v̂min, C_v̂max, E) -> A_V̂min, A_V̂max, Ẽ
796+
relaxV̂(model::SimModel, , C_v̂min, C_v̂max, E) -> A_V̂min, A_V̂max, Ẽ
793797
794798
Augment estimated sensor noise constraints with slack variable ϵ for softening the MHE.
795799
@@ -808,8 +812,8 @@ also returns the ``\mathbf{A}`` matrices for the inequality constraints:
808812
\end{bmatrix}
809813
```
810814
"""
811-
function relaxV̂(::LinModel{NT}, C, C_v̂min, C_v̂max, E) where {NT<:Real}
812-
if !isinf(C) # Z̃ = [ϵ; Z]
815+
function relaxV̂(::LinModel{NT}, , C_v̂min, C_v̂max, E) where {NT<:Real}
816+
if 0 # Z̃ = [ϵ; Z]
813817
# ϵ impacts estimated sensor noise constraint calculations:
814818
A_V̂min, A_V̂max = -[C_v̂min E], [-C_v̂max E]
815819
# ϵ has no impact on estimated sensor noises:
@@ -822,8 +826,8 @@ function relaxV̂(::LinModel{NT}, C, C_v̂min, C_v̂max, E) where {NT<:Real}
822826
end
823827

824828
"Return empty matrices if model is not a [`LinModel`](@ref)"
825-
function relaxV̂(::SimModel{NT}, C, C_v̂min, C_v̂max, E) where {NT<:Real}
826-
= !isinf(C) ? [zeros(NT, 0, 1) E] : E
829+
function relaxV̂(::SimModel{NT}, , C_v̂min, C_v̂max, E) where {NT<:Real}
830+
= [zeros(NT, 0, ) E]
827831
A_V̂min, A_V̂max = -Ẽ, Ẽ
828832
return A_V̂min, A_V̂max, Ẽ
829833
end

src/estimator/mhe/execute.jl

Lines changed: 17 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -33,15 +33,16 @@ function update_estimate!(estim::MovingHorizonEstimator{NT}, u0, y0m, d0) where
3333
add_data_windows!(estim::MovingHorizonEstimator, u0, d0, y0m)
3434
initpred!(estim, model)
3535
linconstraint!(estim, model)
36-
nu, ny, nx̂, nym, nŵ, Nk = model.nu, model.ny, estim.nx̂, estim.nym, estim.nx̂, estim.Nk[]
37-
nx̃ = !isinf(estim.C) + nx̂
36+
nu, ny = model.nu, model.ny
37+
nx̂, nym, nŵ, nϵ, Nk = estim.nx̂, estim.nym, estim.nx̂, estim.nϵ, estim.Nk[]
38+
nx̃ =+ nx̂
3839
Z̃var::Vector{JuMP.VariableRef} = optim[:Z̃var]
3940
= Vector{NT}(undef, nym*Nk)
4041
X̂0 = Vector{NT}(undef, nx̂*Nk)
4142
û0 = Vector{NT}(undef, nu)
4243
ŷ0 = Vector{NT}(undef, ny)
4344
= Vector{NT}(undef, nx̂)
44-
ϵ_0 = isinf(estim.C) ? empty(estim.) : estim.[begin]
45+
ϵ_0 = estim. 0 ? estim.[begin] : empty(estim.)
4546
Z̃_0 = [ϵ_0; estim.x̂0arr_old; estim.Ŵ]
4647
V̂, X̂0 = predict!(V̂, X̂0, û0, ŷ0, estim, model, Z̃_0)
4748
J_0 = obj_nonlinprog!(x̄, estim, model, V̂, Z̃_0)
@@ -128,8 +129,8 @@ julia> round.(getinfo(estim)[:Ŷ], digits=3)
128129
function getinfo(estim::MovingHorizonEstimator{NT}) where NT<:Real
129130
model, Nk = estim.model, estim.Nk[]
130131
nu, ny, nd = model.nu, model.ny, model.nd
131-
nx̂, nym, nŵ = estim.nx̂, estim.nym, estim.nx̂
132-
nx̃ = !isinf(estim.C) + nx̂
132+
nx̂, nym, nŵ, nϵ = estim.nx̂, estim.nym, estim.nx̂, estim.
133+
nx̃ = + nx̂
133134
MyTypes = Union{JuMP._SolutionSummary, Hermitian{NT, Matrix{NT}}, Vector{NT}, NT}
134135
info = Dict{Symbol, MyTypes}()
135136
V̂, X̂0 = similar(estim.Y0m[1:nym*Nk]), similar(estim.X̂0[1:nx̂*Nk])
@@ -156,7 +157,7 @@ function getinfo(estim::MovingHorizonEstimator{NT}) where NT<:Real
156157
end
157158
info[:Ŵ] = estim.Ŵ[1:Nk*nŵ]
158159
info[:x̂arr] = x̂0arr + estim.x̂op
159-
info[] = isinf(estim.C) ? NaN : estim.Z̃[begin]
160+
info[] = 0 ? estim.Z̃[begin] : NaN
160161
info[:J] = obj_nonlinprog!(x̄, estim, estim.model, V̂, estim.Z̃)
161162
info[:X̂] = X̂0 .+ @views [estim.x̂op; estim.X̂op[1:nx̂*Nk]]
162163
info[:x̂] = estim.x̂0 .+ estim.x̂op
@@ -243,8 +244,7 @@ of the time-varying ``\mathbf{P̄}`` covariance . The computed variables are:
243244
"""
244245
function initpred!(estim::MovingHorizonEstimator, model::LinModel)
245246
F, C, optim = estim.F, estim.C, estim.optim
246-
= isinf(C) ? 0 : 1
247-
nx̂, nŵ, nym, Nk = estim.nx̂, estim.nx̂, estim.nym, estim.Nk[]
247+
nx̂, nŵ, nym, nϵ, Nk = estim.nx̂, estim.nx̂, estim.nym, estim.nϵ, estim.Nk[]
248248
nYm, nŴ = nym*Nk, nŵ*Nk
249249
nZ̃ =+ nx̂ + nŴ
250250
# --- update F and fx̄ vectors for MHE predictions ---
@@ -388,13 +388,13 @@ The function `dot(x, A, x)` is a performant way of calculating `x'*A*x`. This me
388388
`x̄` vector arguments.
389389
"""
390390
function obj_nonlinprog!(x̄, estim::MovingHorizonEstimator, ::SimModel, V̂, Z̃)
391-
Nk, nϵ = estim.Nk[], !isinf(estim.C)
391+
nϵ, Nk = estim.nϵ, estim.Nk[]
392392
nYm, nŴ, nx̂, invP̄ = Nk*estim.nym, Nk*estim.nx̂, estim.nx̂, estim.invP̄
393393
nx̃ =+ nx̂
394394
invQ̂_Nk, invR̂_Nk = @views estim.invQ̂_He[1:nŴ, 1:nŴ], estim.invR̂_He[1:nYm, 1:nYm]
395395
x̂0arr, Ŵ, V̂ = @views Z̃[nx̃-nx̂+1:nx̃], Z̃[nx̃+1:nx̃+nŴ], V̂[1:nYm]
396396
x̄ .= estim.x̂0arr_old .- x̂0arr
397-
=? estim.C*Z̃[begin]^2 : 0
397+
= 0 ? estim.C*Z̃[begin]^2 : 0
398398
return dot(x̄, invP̄, x̄) + dot(Ŵ, invQ̂_Nk, Ŵ) + dot(V̂, invR̂_Nk, V̂) +
399399
end
400400

@@ -408,7 +408,7 @@ estimated sensor noises from ``k-N_k+1`` to ``k``. The `X̂0` vector is estimate
408408
``k-N_k+2`` to ``k+1``.
409409
"""
410410
function predict!(V̂, X̂0, _ , _ , estim::MovingHorizonEstimator, ::LinModel, Z̃)
411-
Nk, nϵ = estim.Nk[], !isinf(estim.C)
411+
nϵ, Nk = estim.nϵ, estim.Nk[]
412412
nX̂, nŴ, nYm = estim.nx̂*Nk, estim.nx̂*Nk, estim.nym*Nk
413413
nZ̃ =+ estim.nx̂ + nŴ
414414
V̂[1:nYm] .= @views estim.Ẽ[1:nYm, 1:nZ̃]*Z̃[1:nZ̃] + estim.F[1:nYm]
@@ -418,9 +418,9 @@ end
418418

419419
"Compute the two vectors when `model` is not a `LinModel`."
420420
function predict!(V̂, X̂0, û0, ŷ0, estim::MovingHorizonEstimator, model::SimModel, Z̃)
421-
Nk = estim.Nk[]
421+
nϵ, Nk = estim.nϵ, estim.Nk[]
422422
nu, nd, nx̂, nŵ, nym = model.nu, model.nd, estim.nx̂, estim.nx̂, estim.nym
423-
nx̃ = !isinf(estim.C) + nx̂
423+
nx̃ = + nx̂
424424
x̂0 = @views Z̃[nx̃-nx̂+1:nx̃]
425425
for j=1:Nk
426426
u0 = @views estim.U0[ (1 + nu * (j-1)):(nu*j)]
@@ -446,7 +446,7 @@ Nonlinear constrains for [`MovingHorizonEstimator`](@ref).
446446
function con_nonlinprog!(g, estim::MovingHorizonEstimator, ::SimModel, X̂0, V̂, Z̃)
447447
nX̂con, nX̂ = length(estim.con.X̂0min), estim.nx̂ *estim.Nk[]
448448
nV̂con, nV̂ = length(estim.con.V̂min), estim.nym*estim.Nk[]
449-
ϵ = isinf(estim.C) ? 0 : Z̃[begin] # ϵ = 0 if Cwt=Inf (meaning: no relaxation)
449+
ϵ = estim. 0 ? Z̃[begin] : 0 # ϵ = 0 if Cwt=Inf (meaning: no relaxation)
450450
for i in eachindex(g)
451451
estim.con.i_g[i] || continue
452452
if i nX̂con
@@ -476,8 +476,7 @@ function setmodel_estimator!(
476476
estim::MovingHorizonEstimator, model, uop_old, yop_old, dop_old, Q̂, R̂
477477
)
478478
con = estim.con
479-
nx̂, nym, nu, nd, He = estim.nx̂, estim.nym, model.nu, model.nd, estim.He
480-
= isinf(estim.C) ? 0 : 1
479+
nx̂, nym, nu, nd, He, nϵ = estim.nx̂, estim.nym, model.nu, model.nd, estim.He, estim.
481480
As, Cs_u, Cs_y = estim.As, estim.Cs_u, estim.Cs_y
482481
Â, B̂u, Ĉ, B̂d, D̂d, x̂op, f̂op = augment_model(model, As, Cs_u, Cs_y, verify_obsv=false)
483482
# --- update augmented state-space matrices ---
@@ -496,8 +495,8 @@ function setmodel_estimator!(
496495
E, G, J, B, _ , Ex̂, Gx̂, Jx̂, Bx̂ = init_predmat_mhe(
497496
model, He, estim.i_ym, Â, B̂u, Ĉ, B̂d, D̂d, x̂op, f̂op
498497
)
499-
A_X̂min, A_X̂max, Ẽx̂ = relaxX̂(model, estim.C, con.C_x̂min, con.C_x̂max, Ex̂)
500-
A_V̂min, A_V̂max, Ẽ = relaxV̂(model, estim.C, con.C_v̂min, con.C_v̂max, E)
498+
A_X̂min, A_X̂max, Ẽx̂ = relaxX̂(model, , con.C_x̂min, con.C_x̂max, Ex̂)
499+
A_V̂min, A_V̂max, Ẽ = relaxV̂(model, , con.C_v̂min, con.C_v̂max, E)
501500
estim.Ẽ .=
502501
estim.G .= G
503502
estim.J .= J

0 commit comments

Comments
 (0)