@@ -19,6 +19,8 @@ struct SteadyKalmanFilter{NT<:Real, SM<:LinModel} <: StateEstimator{NT}
1919 Ĉ :: Matrix{NT}
2020 B̂d :: Matrix{NT}
2121 D̂d :: Matrix{NT}
22+ Ĉm :: Matrix{NT}
23+ D̂dm :: Matrix{NT}
2224 Q̂:: Hermitian{NT, Matrix{NT}}
2325 R̂:: Hermitian{NT, Matrix{NT}}
2426 K̂:: Matrix{NT}
@@ -34,6 +36,7 @@ struct SteadyKalmanFilter{NT<:Real, SM<:LinModel} <: StateEstimator{NT}
3436 nxs = size (As, 1 )
3537 nx̂ = model. nx + nxs
3638 Â, B̂u, Ĉ, B̂d, D̂d, x̂op, f̂op = augment_model (model, As, Cs_u, Cs_y)
39+ Ĉm, D̂dm = Ĉ[i_ym, :], D̂d[i_ym, :]
3740 validate_kfcov (nym, nx̂, Q̂, R̂)
3841 K̂ = try
3942 Q̂_kalman = Matrix (Q̂) # Matrix() required for Julia 1.6
@@ -59,7 +62,7 @@ struct SteadyKalmanFilter{NT<:Real, SM<:LinModel} <: StateEstimator{NT}
5962 lastu0, x̂op, f̂op, x̂0,
6063 i_ym, nx̂, nym, nyu, nxs,
6164 As, Cs_u, Cs_y, nint_u, nint_ym,
62- Â, B̂u, Ĉ, B̂d, D̂d,
65+ Â, B̂u, Ĉ, B̂d, D̂d, Ĉm, D̂dm,
6366 Q̂, R̂,
6467 K̂,
6568 direct, corrected,
233236
234237" Allow code reuse for `SteadyKalmanFilter` and `Luenberger` (observers with constant gain)."
235238function correct_estimate_obsv! (estim:: StateEstimator , y0m, d0, K̂)
236- Ĉm, D̂dm = @views estim. Ĉ[estim . i_ym, :], estim. D̂d[estim . i_ym, :]
239+ Ĉm, D̂dm = estim. Ĉm, estim. D̂dm
237240 ŷ0m = @views estim. buffer. ŷ[estim. i_ym]
238241 # in-place operations to reduce allocations:
239242 mul! (ŷ0m, Ĉm, estim. x̂0)
@@ -281,6 +284,8 @@ struct KalmanFilter{NT<:Real, SM<:LinModel} <: StateEstimator{NT}
281284 Ĉ :: Matrix{NT}
282285 B̂d :: Matrix{NT}
283286 D̂d :: Matrix{NT}
287+ Ĉm :: Matrix{NT}
288+ D̂dm :: Matrix{NT}
284289 P̂_0:: Hermitian{NT, Matrix{NT}}
285290 Q̂:: Hermitian{NT, Matrix{NT}}
286291 R̂:: Hermitian{NT, Matrix{NT}}
@@ -297,6 +302,7 @@ struct KalmanFilter{NT<:Real, SM<:LinModel} <: StateEstimator{NT}
297302 nxs = size (As, 1 )
298303 nx̂ = model. nx + nxs
299304 Â, B̂u, Ĉ, B̂d, D̂d, x̂op, f̂op = augment_model (model, As, Cs_u, Cs_y)
305+ Ĉm, D̂dm = Ĉ[i_ym, :], D̂d[i_ym, :]
300306 validate_kfcov (nym, nx̂, Q̂, R̂, P̂_0)
301307 lastu0 = zeros (NT, nu)
302308 x̂0 = [zeros (NT, model. nx); zeros (NT, nxs)]
@@ -311,7 +317,7 @@ struct KalmanFilter{NT<:Real, SM<:LinModel} <: StateEstimator{NT}
311317 lastu0, x̂op, f̂op, x̂0, P̂,
312318 i_ym, nx̂, nym, nyu, nxs,
313319 As, Cs_u, Cs_y, nint_u, nint_ym,
314- Â, B̂u, Ĉ, B̂d, D̂d,
320+ Â, B̂u, Ĉ, B̂d, D̂d, Ĉm, D̂dm,
315321 P̂_0, Q̂, R̂,
316322 K̂,
317323 direct, corrected,
@@ -408,8 +414,7 @@ It computes the corrected state estimate ``\mathbf{x̂}_{k}(k)`` estimation cova
408414``\m athbf{P̂}_{k}(k)``.
409415"""
410416function correct_estimate! (estim:: KalmanFilter , y0m, d0)
411- Ĉm = @views estim. Ĉ[estim. i_ym, :]
412- return correct_estimate_kf! (estim, y0m, d0, Ĉm)
417+ return correct_estimate_kf! (estim, y0m, d0, estim. Ĉm)
413418end
414419
415420
@@ -447,11 +452,10 @@ provided below, see [^2] for details.
447452 <https://en.wikipedia.org/wiki/Kalman_filter>, Accessed 2024-08-08.
448453"""
449454function update_estimate! (estim:: KalmanFilter , y0m, d0, u0)
450- Ĉm = @views estim. Ĉ[estim. i_ym, :]
451455 if ! estim. direct
452- correct_estimate_kf! (estim, y0m, d0, Ĉm)
456+ correct_estimate_kf! (estim, y0m, d0, estim . Ĉm)
453457 end
454- return predict_estimate_kf! (estim, y0m, d0, u0, Ĉm , estim. Â)
458+ return predict_estimate_kf! (estim, u0, d0 , estim. Â)
455459end
456460
457461
@@ -472,11 +476,13 @@ struct UnscentedKalmanFilter{NT<:Real, SM<:SimModel} <: StateEstimator{NT}
472476 Cs_y:: Matrix{NT}
473477 nint_u :: Vector{Int}
474478 nint_ym:: Vector{Int}
475- Â :: Matrix{NT}
476- B̂u:: Matrix{NT}
477- Ĉ :: Matrix{NT}
478- B̂d:: Matrix{NT}
479- D̂d:: Matrix{NT}
479+ Â :: Matrix{NT}
480+ B̂u :: Matrix{NT}
481+ Ĉ :: Matrix{NT}
482+ B̂d :: Matrix{NT}
483+ D̂d :: Matrix{NT}
484+ Ĉm :: Matrix{NT}
485+ D̂dm :: Matrix{NT}
480486 P̂_0:: Hermitian{NT, Matrix{NT}}
481487 Q̂:: Hermitian{NT, Matrix{NT}}
482488 R̂:: Hermitian{NT, Matrix{NT}}
@@ -502,6 +508,7 @@ struct UnscentedKalmanFilter{NT<:Real, SM<:SimModel} <: StateEstimator{NT}
502508 nxs = size (As, 1 )
503509 nx̂ = model. nx + nxs
504510 Â, B̂u, Ĉ, B̂d, D̂d, x̂op, f̂op = augment_model (model, As, Cs_u, Cs_y)
511+ Ĉm, D̂dm = Ĉ[i_ym, :], D̂d[i_ym, :]
505512 validate_kfcov (nym, nx̂, Q̂, R̂, P̂_0)
506513 nσ, γ, m̂, Ŝ = init_ukf (model, nx̂, α, β, κ)
507514 lastu0 = zeros (NT, nu)
@@ -520,7 +527,7 @@ struct UnscentedKalmanFilter{NT<:Real, SM<:SimModel} <: StateEstimator{NT}
520527 lastu0, x̂op, f̂op, x̂0, P̂,
521528 i_ym, nx̂, nym, nyu, nxs,
522529 As, Cs_u, Cs_y, nint_u, nint_ym,
523- Â, B̂u, Ĉ, B̂d, D̂d,
530+ Â, B̂u, Ĉ, B̂d, D̂d, Ĉm, D̂dm,
524531 P̂_0, Q̂, R̂,
525532 K̂,
526533 M̂, X̂0, X̄0, Ŷ0m, Ȳ0m,
@@ -822,11 +829,13 @@ struct ExtendedKalmanFilter{NT<:Real, SM<:SimModel} <: StateEstimator{NT}
822829 Cs_y:: Matrix{NT}
823830 nint_u :: Vector{Int}
824831 nint_ym:: Vector{Int}
825- Â :: Matrix{NT}
826- B̂u:: Matrix{NT}
827- Ĉ :: Matrix{NT}
828- B̂d:: Matrix{NT}
829- D̂d:: Matrix{NT}
832+ Â :: Matrix{NT}
833+ B̂u :: Matrix{NT}
834+ Ĉ :: Matrix{NT}
835+ B̂d :: Matrix{NT}
836+ D̂d :: Matrix{NT}
837+ Ĉm :: Matrix{NT}
838+ D̂dm :: Matrix{NT}
830839 P̂_0:: Hermitian{NT, Matrix{NT}}
831840 Q̂:: Hermitian{NT, Matrix{NT}}
832841 R̂:: Hermitian{NT, Matrix{NT}}
@@ -845,6 +854,7 @@ struct ExtendedKalmanFilter{NT<:Real, SM<:SimModel} <: StateEstimator{NT}
845854 nxs = size (As, 1 )
846855 nx̂ = model. nx + nxs
847856 Â, B̂u, Ĉ, B̂d, D̂d, x̂op, f̂op = augment_model (model, As, Cs_u, Cs_y)
857+ Ĉm, D̂dm = Ĉ[i_ym, :], D̂d[i_ym, :]
848858 validate_kfcov (nym, nx̂, Q̂, R̂, P̂_0)
849859 lastu0 = zeros (NT, nu)
850860 x̂0 = [zeros (NT, model. nx); zeros (NT, nxs)]
@@ -861,7 +871,7 @@ struct ExtendedKalmanFilter{NT<:Real, SM<:SimModel} <: StateEstimator{NT}
861871 lastu0, x̂op, f̂op, x̂0, P̂,
862872 i_ym, nx̂, nym, nyu, nxs,
863873 As, Cs_u, Cs_y, nint_u, nint_ym,
864- Â, B̂u, Ĉ, B̂d, D̂d,
874+ Â, B̂u, Ĉ, B̂d, D̂d, Ĉm, D̂dm,
865875 P̂_0, Q̂, R̂,
866876 K̂,
867877 F̂_û, Ĥ,
@@ -1008,8 +1018,6 @@ function update_estimate!(estim::ExtendedKalmanFilter{NT}, y0m, d0, u0) where NT
10081018 ForwardDiff. jacobian! (Ĥ, ĥAD!, ŷ0, x̂0)
10091019 Ĥm = @views Ĥ[estim. i_ym, :]
10101020 correct_estimate_kf! (estim, y0m, d0, Ĥm)
1011- else
1012- Ĥm = @views Ĥ[estim. i_ym, :]
10131021 end
10141022 x̂0corr = estim. x̂0
10151023 # concatenate x̂0next and û0 vectors to allows û0 vector with dual numbers for AD:
@@ -1020,7 +1028,7 @@ function update_estimate!(estim::ExtendedKalmanFilter{NT}, y0m, d0, u0) where NT
10201028 )
10211029 ForwardDiff. jacobian! (estim. F̂_û, f̂AD!, x̂0nextû, x̂0corr)
10221030 F̂ = @views estim. F̂_û[1 : estim. nx̂, :]
1023- return predict_estimate_kf! (estim, y0m, d0, u0, Ĥm , F̂)
1031+ return predict_estimate_kf! (estim, u0, d0 , F̂)
10241032end
10251033
10261034" Set `estim.P̂` to `estim.P̂_0` for the time-varying Kalman Filters."
@@ -1079,30 +1087,32 @@ function correct_estimate_kf!(estim::Union{KalmanFilter, ExtendedKalmanFilter},
10791087 I_minus_K̂_Ĉm = estim. buffer. Q̂
10801088 mul! (I_minus_K̂_Ĉm, K̂, Ĉm)
10811089 lmul! (- 1 , I_minus_K̂_Ĉm)
1082- I_minus_K̂_Ĉm[diagind (I_minus_K̂_Ĉm)] .+ = 1 # compute I - K̂*Ĉm in-place
1090+ for i= diagind (I_minus_K̂_Ĉm)
1091+ I_minus_K̂_Ĉm[i] += 1 # compute I - K̂*Ĉm in-place
1092+ end
10831093 P̂corr = estim. buffer. P̂
10841094 mul! (P̂corr, I_minus_K̂_Ĉm, P̂)
10851095 estim. P̂ .= Hermitian (P̂corr, :L )
10861096 return nothing
10871097end
10881098
10891099"""
1090- predict_estimate_kf!(estim::Union{KalmanFilter, ExtendedKalmanFilter}, y0m, d0, u0, Ĉm , Â)
1100+ predict_estimate_kf!(estim::Union{KalmanFilter, ExtendedKalmanFilter}, u0, d0 , Â)
10911101
10921102Predict time-varying/extended Kalman Filter estimates with augmented `Ĉm` and `Â` matrices.
10931103
10941104Allows code reuse for [`KalmanFilter`](@ref), [`ExtendedKalmanFilterKalmanFilter`](@ref).
10951105They predict the state `x̂` and covariance `P̂` with the same equations. See
10961106[`update_estimate`](@ref) methods for the equations.
10971107"""
1098- function predict_estimate_kf! (estim:: Union{KalmanFilter, ExtendedKalmanFilter} , y0m, d0, u0, Ĉm , Â)
1108+ function predict_estimate_kf! (estim:: Union{KalmanFilter, ExtendedKalmanFilter} , u0, d0 , Â)
10991109 x̂0corr, P̂corr = estim. x̂0, estim. P̂
11001110 Q̂ = estim. Q̂
11011111 x̂0next, û0 = estim. buffer. x̂, estim. buffer. û
11021112 # in-place operations to reduce allocations:
11031113 f̂! (x̂0next, û0, estim, estim. model, x̂0corr, u0, d0)
11041114 P̂corr_Âᵀ = estim. buffer. P̂
1105- mul! (P̂corr_Âᵀ, P̂corr, Â' )
1115+ mul! (P̂corr_Âᵀ, P̂corr. data , Â' ) # the ".data" weirdly removes a type instability in mul!
11061116 Â_P̂corr_Âᵀ = estim. buffer. Q̂
11071117 mul! (Â_P̂corr_Âᵀ, Â, P̂corr_Âᵀ)
11081118 P̂next = estim. buffer. P̂
0 commit comments