Skip to content

Commit aa9b8dd

Browse files
committed
reduce allocations KalmanFilter and ExtendedKalmanFilter
1 parent 2f81e2b commit aa9b8dd

File tree

1 file changed

+19
-8
lines changed

1 file changed

+19
-8
lines changed

src/estimator/kalman.jl

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -290,7 +290,8 @@ struct KalmanFilter{NT<:Real, SM<:LinModel} <: StateEstimator{NT}
290290
Q̂, R̂ = Hermitian(Q̂, :L), Hermitian(R̂, :L)
291291
P̂_0 = Hermitian(P̂_0, :L)
292292
= copy(P̂_0)
293-
K̂, M̂ = zeros(NT, nx̂, nym), zeros(NT, nx̂, nym)
293+
= zeros(NT, nx̂, nym)
294+
= Hermitian(zeros(NT, nym, nym), :L)
294295
corrected = [false]
295296
buffer = StateEstimatorBuffer{NT}(nu, nx̂, nym, ny, nd)
296297
return new{NT, SM}(
@@ -411,6 +412,9 @@ It implements the time-varying Kalman Filter in its predictor (observer) form :
411412
\mathbf{ŷ^m}(k) &= \mathbf{Ĉ^m x̂}_{k-1}(k) + \mathbf{D̂_d^m d}(k) \\
412413
\mathbf{x̂}_{k}(k+1) &= \mathbf{Â x̂}_{k-1}(k) + \mathbf{B̂_u u}(k) + \mathbf{B̂_d d}(k)
413414
+ \mathbf{K̂}(k)[\mathbf{y^m}(k) - \mathbf{ŷ^m}(k)] \\
415+
416+
417+
414418
\mathbf{P̂}_{k}(k+1) &= \mathbf{Â}[\mathbf{P̂}_{k-1}(k)
415419
- \mathbf{M̂}(k)\mathbf{Ĉ^m P̂}_{k-1}(k)]\mathbf{Â}' + \mathbf{Q̂}
416420
\end{aligned}
@@ -801,7 +805,8 @@ struct ExtendedKalmanFilter{NT<:Real, SM<:SimModel} <: StateEstimator{NT}
801805
= Hermitian(Q̂, :L)
802806
= Hermitian(R̂, :L)
803807
= copy(P̂_0)
804-
K̂, M̂ = zeros(NT, nx̂, nym), zeros(NT, nx̂, nym)
808+
= zeros(NT, nx̂, nym)
809+
= Hermitian(zeros(NT, nym, nym), :L)
805810
F̂_û, Ĥ = zeros(NT, nx̂+nu, nx̂), zeros(NT, ny, nx̂)
806811
corrected = [false]
807812
buffer = StateEstimatorBuffer{NT}(nu, nx̂, nym, ny, nd)
@@ -996,19 +1001,25 @@ See [`update_estimate_kf!`](@ref) for more information.
9961001
function correct_estimate_kf!(estim::StateEstimator, y0m, d0, Ĉm)
9971002
R̂, M̂, K̂ = estim.R̂, estim.M̂, estim.
9981003
x̂0, P̂ = estim.x̂0, estim.
999-
mul!(M̂, P̂.data, Ĉm') # the ".data" weirdly removes a type instability in mul!
1000-
rdiv!(M̂, cholesky!(Hermitian(Ĉm ** Ĉm' .+ R̂, :L)))
1001-
# TODO: use M̂ matrix for something else e.g. M̂ = Ĉm * P̂ * Ĉm' .+ R̂ (would be Hermitian)
1002-
K̂ .=
1004+
P̂_Ĉmᵀ =
1005+
mul!(P̂_Ĉmᵀ, P̂.data, Ĉm') # the ".data" weirdly removes a type instability in mul!
1006+
mul!(M̂, Ĉm, P̂_Ĉmᵀ)
1007+
.+=
1008+
= P̂_Ĉmᵀ
1009+
M̂_chol = cholesky!(Hermitian(M̂)) # also modifies M̂
1010+
rdiv!(K̂, M̂_chol)
10031011
ŷ0 = estim.buffer.
10041012
ĥ!(ŷ0, estim, estim.model, x̂0, d0)
10051013
ŷ0m = @views ŷ0[estim.i_ym]
10061014
= ŷ0m
10071015
v̂ .= y0m .- ŷ0m
10081016
x̂0corr, P̂corr = estim.x̂0, estim.
10091017
mul!(x̂0corr, K̂, v̂, 1, 1)
1010-
# TODO: use buffer.P̂ to reduce allocations
1011-
P̂corr .= Hermitian((I -*Ĉm) * P̂, :L)
1018+
I_minus_K̂_Ĉm = estim.buffer.
1019+
mul!(I_minus_K̂_Ĉm, K̂, Ĉm)
1020+
lmul!(-1, I_minus_K̂_Ĉm)
1021+
I_minus_K̂_Ĉm[diagind(I_minus_K̂_Ĉm)] .+= 1 # compute I - K̂*Ĉm
1022+
P̂corr .= Hermitian(I_minus_K̂_Ĉm * P̂) # TODO: remove this allocation
10121023
return nothing
10131024
end
10141025

0 commit comments

Comments
 (0)