Skip to content

Commit 51737c4

Browse files
committed
changed: computing inv with cholesky in MovingHorizonEstimator
1 parent 7aaabfe commit 51737c4

File tree

4 files changed

+27
-10
lines changed

4 files changed

+27
-10
lines changed

Project.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
name = "ModelPredictiveControl"
22
uuid = "61f9bdb8-6ae4-484a-811f-bbf86720c31c"
33
authors = ["Francis Gagnon"]
4-
version = "1.2.1"
4+
version = "1.3.0"
55

66
[deps]
77
ControlSystemsBase = "aaaaaaaa-a6ca-5380-bf3e-84a91bcd477e"

src/estimator/mhe/construct.jl

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -123,11 +123,6 @@ struct MovingHorizonEstimator{
123123
validate_kfcov(nym, nx̂, Q̂, R̂, P̂_0)
124124
lastu0 = zeros(NT, nu)
125125
x̂0 = [zeros(NT, model.nx); zeros(NT, nxs)]
126-
P̂_0 = Hermitian(P̂_0, :L)
127-
Q̂, R̂ = Hermitian(Q̂, :L), Hermitian(R̂, :L)
128-
invP̄ = Hermitian(inv(P̂_0), :L)
129-
invQ̂_He = Hermitian(repeatdiag(inv(Q̂), He), :L)
130-
invR̂_He = Hermitian(repeatdiag(inv(R̂), He), :L)
131126
r = direct ? 0 : 1
132127
E, G, J, B, ex̄, Ex̂, Gx̂, Jx̂, Bx̂ = init_predmat_mhe(
133128
model, He, i_ym, Â, B̂u, Ĉm, B̂d, D̂dm, x̂op, f̂op, r
@@ -146,10 +141,18 @@ struct MovingHorizonEstimator{
146141
nD0 = direct ? nd*(He+1) : nd*He
147142
U0, D0 = zeros(NT, nu*He), zeros(NT, nD0)
148143
= zeros(NT, nx̂*He)
144+
buffer = StateEstimatorBuffer{NT}(nu, nx̂, nym, ny, nd)
145+
P̂_0 = Hermitian(P̂_0, :L)
146+
Q̂, R̂ = Hermitian(Q̂, :L), Hermitian(R̂, :L)
147+
P̂_0 = Hermitian(P̂_0, :L)
148+
invP̄ = inv_cholesky!(buffer.P̂, P̂_0)
149+
invQ̂ = inv_cholesky!(buffer.Q̂, Q̂)
150+
invR̂ = inv_cholesky!(buffer.R̂, R̂)
151+
invQ̂_He = Hermitian(repeatdiag(invQ̂, He), :L)
152+
invR̂_He = Hermitian(repeatdiag(invR̂, He), :L)
149153
x̂0arr_old = zeros(NT, nx̂)
150154
P̂arr_old = copy(P̂_0)
151155
Nk = [0]
152-
buffer = StateEstimatorBuffer{NT}(nu, nx̂, nym, ny, nd)
153156
corrected = [false]
154157
estim = new{NT, SM, JM, CE}(
155158
model, optim, con, covestim,

src/estimator/mhe/execute.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -479,9 +479,9 @@ end
479479
"Invert the covariance estimate at arrival `P̄`."
480480
function invert_cov!(estim::MovingHorizonEstimator, P̄)
481481
try
482-
estim.invP̄ .= inv(P̄)
482+
estim.invP̄ .= inv_cholesky!(estim.buffer.P̂, P̄)
483483
catch err
484-
if err isa SingularException || err isa LAPACKException
484+
if err isa PosDefException
485485
@warn("Arrival covariance is not invertible: keeping the old one")
486486
else
487487
rethrow()

src/general.jl

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,4 +59,18 @@ end
5959
to_hermitian(A::AbstractVector) = Hermitian(reshape(A, 1, 1), :L)
6060
to_hermitian(A::AbstractMatrix) = Hermitian(A, :L)
6161
to_hermitian(A::Hermitian) = A
62-
to_hermitian(A) = A
62+
to_hermitian(A) = A
63+
64+
"""
65+
Compute the inverse of a the Hermitian positive definite matrix `A` using `cholesky`.
66+
67+
Builtin `inv` function uses LU factorization which is not the best choice for Hermitian
68+
positive definite matrices. The function will mutate `buffer` to reduce memory allocations.
69+
"""
70+
function inv_cholesky!(buffer::Matrix, A::Hermitian)
71+
Achol = Hermitian(buffer, :L)
72+
Achol .= A
73+
chol_obj = cholesky!(Achol)
74+
invA = Hermitian(inv(chol_obj), :L)
75+
return invA
76+
end

0 commit comments

Comments
 (0)