Skip to content

Commit 8bb5543

Browse files
committed
debug: MHE update arrival cov with I/O at arr
1 parent 603812e commit 8bb5543

File tree

3 files changed

+41
-44
lines changed

3 files changed

+41
-44
lines changed

src/estimator/kalman.jl

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -733,10 +733,9 @@ automatically computes the Jacobians:
733733
The matrix ``\mathbf{Ĥ^m}`` is the rows of ``\mathbf{Ĥ}`` that are measured outputs.
734734
"""
735735
function update_estimate!(estim::ExtendedKalmanFilter, u, ym, d=empty(estim.x̂))
736-
= ForwardDiff.jacobian(x̂ -> (estim, estim.model, x̂, u, d), estim.x̂)
737-
= ForwardDiff.jacobian(x̂ -> (estim, estim.model, x̂, d), estim.x̂)
738-
Ĥm = Ĥ[estim.i_ym, :]
739-
return update_estimate_kf!(estim, u, ym, d, F̂, Ĥm, estim.P̂, estim.x̂)
736+
= ForwardDiff.jacobian(x̂ -> (estim, estim.model, x̂, u, d), estim.x̂)
737+
= ForwardDiff.jacobian(x̂ -> (estim, estim.model, x̂, d), estim.x̂)
738+
return update_estimate_kf!(estim, u, ym, d, F̂, Ĥ[estim.i_ym, :], estim.P̂, estim.x̂)
740739
end
741740

742741
"Set `estim.P̂` to `estim.P̂0` for the time-varying Kalman Filters."

src/estimator/mhe.jl

Lines changed: 35 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,8 @@ struct MovingHorizonEstimator{
4343
U ::Union{Vector{NT}, Missing}
4444
D ::Union{Vector{NT}, Missing}
4545
::Union{Vector{NT}, Missing}
46-
x̂0_past::Vector{NT}
47-
P̂0_past::Hermitian{NT, Matrix{NT}}
46+
x̂arr_old::Vector{NT}
47+
P̂arr_old::Hermitian{NT, Matrix{NT}}
4848
Nk::Vector{Int}
4949
function MovingHorizonEstimator{NT, SM, JM}(
5050
model::SM, He, i_ym, nint_u, nint_ym, P̂0, Q̂, R̂, optim::JM
@@ -66,14 +66,14 @@ struct MovingHorizonEstimator{
6666
invR̂_He = Hermitian(repeatdiag(inv(R̂), He), :L)
6767
= zeros(NT, nx̂, nym)
6868
nvar, nX̂ = nx̂*(He + 1), nx̂*(He + 1)
69-
X̂min , X̂max = fill(-Inf, nX̂), fill(+Inf, nX̂)
69+
X̂min, X̂max = fill(-Inf, nX̂), fill(+Inf, nX̂)
7070
i_X̂min, i_X̂max = .!isinf.(X̂min) , .!isinf.(X̂max)
7171
i_g = [i_X̂min; i_X̂max]
7272
= zeros(NT, nvar)
7373
X̂, Ym = zeros(NT, nx̂*He), zeros(NT, nym*He)
7474
U, D, Ŵ = zeros(NT, nu*He), zeros(NT, nd*He), zeros(NT, nx̂*He)
75-
x̂0_past = zeros(NT, nx̂)
76-
P̂0_past = copy(P̂0)
75+
x̂arr_old = zeros(NT, nx̂)
76+
P̂arr_old = copy(P̂0)
7777
Nk = [0]
7878
estim = new{NT, SM, JM}(
7979
model, optim, W̃,
@@ -85,7 +85,7 @@ struct MovingHorizonEstimator{
8585
M̂,
8686
X̂min, X̂max, i_g,
8787
X̂, Ym, U, D, Ŵ,
88-
x̂0_past, P̂0_past, Nk
88+
x̂arr_old, P̂arr_old, Nk
8989
)
9090
init_optimization!(estim, optim)
9191
return estim
@@ -386,18 +386,18 @@ function print_estim_dim(io::IO, estim::MovingHorizonEstimator, n)
386386
print(io, "$(lpad(nd, n)) measured disturbances d")
387387
end
388388

389-
"Reset `estim.`, `estim.invP̄` and the time windows for the moving horizon estimator."
389+
"Reset `estim.P̂arr_old`, `estim.invP̄` and the windows for the moving horizon estimator."
390390
function init_estimate_cov!(estim::MovingHorizonEstimator, _ , _ , _ )
391-
estim.invP̄.data[:] = Hermitian(inv(estim.P̂0), :L)
392-
estim.P̂0_past.data[:] = estim.P̂0
393-
estim.x̂0_past .= 0
394-
estim.W̃ .= 0
395-
estim.X̂ .= 0
396-
estim.Ym .= 0
397-
estim.U .= 0
398-
estim.D .= 0
399-
estim.Ŵ .= 0
400-
estim.Nk .= 0
391+
estim.invP̄.data[:] = Hermitian(inv(estim.P̂0), :L)
392+
estim.P̂arr_old.data[:] = estim.P̂0
393+
estim.x̂arr_old .= 0
394+
estim. .= 0
395+
estim. .= 0
396+
estim.Ym .= 0
397+
estim.U .= 0
398+
estim.D .= 0
399+
estim. .= 0
400+
estim.Nk .= 0
401401
return nothing
402402
end
403403

@@ -450,7 +450,7 @@ Once the problem solved, the next estimate ``\mathbf{x̂}_k(k+1)`` is computed b
450450
the optimal values of ``\mathbf{x̂}_k(k-N_k+1)`` and ``\mathbf{Ŵ}`` in the last equation from
451451
``j=N_k-1`` to ``0``, inclusively. Afterward, if ``k ≥ H_e``, the arrival covariance for the
452452
next time step ``\mathbf{P̂}_{k-N_k+1}(k-N_k+2)`` is estimated with the equations of
453-
[`update_estimate!(::ExtendedKalmanFilter)`](@ref) (or `KalmanFilter`, for [`LinModel`](@ref)).
453+
[`update_estimate!(::ExtendedKalmanFilter)`](@ref), or `KalmanFilter`, for [`LinModel`](@ref)).
454454
"""
455455
function update_estimate!(estim::MovingHorizonEstimator{NT}, u, ym, d) where NT<:Real
456456
model, optim, x̂ = estim.model, estim.optim, estim.
@@ -477,8 +477,8 @@ function update_estimate!(estim::MovingHorizonEstimator{NT}, u, ym, d) where NT<
477477
W̃var::Vector{VariableRef} = optim[:W̃var]
478478
Ŷm = Vector{NT}(undef, nYm)
479479
= Vector{NT}(undef, nX̂)
480-
estim.x̂0_past[:] = estim.X̂[1:nx̂]
481-
W̃0 = [estim.x̂0_past; estim.Ŵ]
480+
estim.x̂arr_old[:] = estim.X̂[1:nx̂]
481+
W̃0 = [estim.x̂arr_old; estim.Ŵ]
482482
Ŷm, X̂ = predict!(Ŷm, X̂, estim, model, W̃0)
483483
J0 = obj_nonlinprog(estim, model, Ŷm, W̃0)
484484
# initial W̃0 with Ŵ=0 if objective or constraint function not finite :
@@ -515,25 +515,23 @@ function update_estimate!(estim::MovingHorizonEstimator{NT}, u, ym, d) where NT<
515515
Ŷm, X̂ = predict!(Ŷm, X̂, estim, model, estim.W̃)
516516
x̂[:] = X̂[(1 + nx̂*Nk):(nx̂*(Nk+1))]
517517
if Nk == He
518-
P̂0_past = update_cov!(estim, model, u, ym, d)
519-
estim.invP̄.data[:] = Hermitian(inv(P̂0_past), :L)
518+
uarr, ymarr, darr = estim.U[1:nu], estim.Ym[1:nym], estim.D[1:nd]
519+
update_cov!(estim.P̂arr_old, estim, model, uarr, ymarr, darr)
520+
estim.invP̄.data[:] = Hermitian(inv(estim.P̂arr_old), :L)
520521
end
521522
return nothing
522523
end
523524

524-
"Update the covariance `estim.P̂0_past` with the `KalmanFilter` if `model` is a `LinModel`."
525-
function update_cov!(estim::MovingHorizonEstimator, ::LinModel, u, ym, d)
526-
update_estimate_kf!(estim, u, ym, d, estim.Â, estim.Ĉ[estim.i_ym, :], estim.P̂0_past)
527-
return estim.P̂0_past
525+
"Update the covariance `P̂` with the `KalmanFilter` if `model` is a `LinModel`."
526+
function update_cov!(P̂, estim::MovingHorizonEstimator, ::LinModel, u, ym, d)
527+
return update_estimate_kf!(estim, u, ym, d, estim.Â, estim.Ĉ[estim.i_ym, :], P̂)
528528
end
529529
"Update it with the `ExtendedKalmanFilter` if model is not a `LinModel`."
530-
function update_cov!(estim::MovingHorizonEstimator, ::SimModel, u, ym, d)
530+
function update_cov!(P̂, estim::MovingHorizonEstimator, ::SimModel, u, ym, d)
531531
# TODO: also support UnscentedKalmanFilter
532-
= ForwardDiff.jacobian(x̂ -> (estim, estim.model, x̂, u, d), estim.x̂)
533-
= ForwardDiff.jacobian(x̂ -> (estim, estim.model, x̂, d), estim.x̂)
534-
Ĥm = Ĥ[estim.i_ym, :]
535-
update_estimate_kf!(estim, u, ym, d, F̂, Ĥm, estim.P̂0_past)
536-
return estim.P̂0_past
532+
= ForwardDiff.jacobian(x̂ -> (estim, estim.model, x̂, u, d), estim.x̂)
533+
= ForwardDiff.jacobian(x̂ -> (estim, estim.model, x̂, d), estim.x̂)
534+
return update_estimate_kf!(estim, u, ym, d, F̂, Ĥ[estim.i_ym, :], P̂)
537535
end
538536

539537
"""
@@ -549,11 +547,11 @@ function obj_nonlinprog(
549547
Nk = estim.Nk[]
550548
nYm, nŴ, nx̂, invP̄ = Nk*estim.nym, Nk*estim.nx̂, estim.nx̂, estim.invP̄
551549
invQ̂_Nk, invR̂_Nk = @views estim.invQ̂_He[1:nŴ, 1:nŴ], estim.invR̂_He[1:nYm, 1:nYm]
552-
x̂0 = @views W̃[1:nx̂] # W̃ = [x̂(k-Nk+1|k); Ŵ]
553-
x̄0 = x̂0 - estim.x̂0_past
554-
= @views estim.Ym[1:nYm] - Ŷm[1:nYm]
555-
= @views W̃[nx̂+1:nx̂+nŴ]
556-
return dot(x̄0, invP̄, x̄0) + dot(Ŵ, invQ̂_Nk, Ŵ) + dot(V̂, invR̂_Nk, V̂)
550+
x̂arr = @views W̃[1:nx̂] # W̃ = [x̂(k-Nk+1|k); Ŵ]
551+
= x̂arr - estim.x̂arr_old
552+
= @views estim.Ym[1:nYm] - Ŷm[1:nYm]
553+
= @views W̃[nx̂+1:nx̂+nŴ]
554+
return dot(, invP̄, ) + dot(Ŵ, invQ̂_Nk, Ŵ) + dot(V̂, invR̂_Nk, V̂)
557555
end
558556

559557
"""

test/test_state_estim.jl

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -583,9 +583,9 @@ end
583583
@test mhe5.nx̂ == 8
584584

585585
mhe6 = MovingHorizonEstimator(nonlinmodel, He=5, σP0=[1,2,3,4], σP0int_ym=[5,6])
586-
@test mhe6.P̂0 Hermitian(diagm(Float64[1, 4, 9 ,16, 25, 36]))
587-
@test mhe6.P̂0_past Hermitian(diagm(Float64[1, 4, 9 ,16, 25, 36]))
588-
@test mhe6.P̂0 !== mhe6.P̂0_past
586+
@test mhe6.P̂0 Hermitian(diagm(Float64[1, 4, 9 ,16, 25, 36]))
587+
@test mhe6.P̂arr_old Hermitian(diagm(Float64[1, 4, 9 ,16, 25, 36]))
588+
@test mhe6.P̂0 !== mhe6.P̂arr_old
589589

590590
mhe7 = MovingHorizonEstimator(nonlinmodel, He=10)
591591
@test mhe7.He == 10

0 commit comments

Comments
 (0)