Skip to content

Commit 234d84d

Browse files
committed
added : full covariance matrix Kalman filter constructors
1 parent bfc1891 commit 234d84d

File tree

4 files changed

+55
-27
lines changed

4 files changed

+55
-27
lines changed

example/juMPC.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ set_preferences!(ModelPredictiveControl, "precompile_workload" => false; force=t
1414
#using JuMP, HiGHS
1515
using JuMP, Ipopt
1616
using LinearAlgebra
17-
using ControlSystemsBase
17+
using ControlSystemsBase
1818
using MAT
1919

2020
vars_ml = matread("example/matlab.mat")

src/estimator/kalman.jl

Lines changed: 46 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,10 @@ struct SteadyKalmanFilter <: StateEstimator
2020
::Hermitian{Float64, Matrix{Float64}}
2121
::Hermitian{Float64, Matrix{Float64}}
2222
K::Matrix{Float64}
23-
function SteadyKalmanFilter(model, i_ym, nint_ym, Asm, Csm, Q̂, R̂)
23+
function SteadyKalmanFilter(model, i_ym, nint_ym, Q̂, R̂)
2424
nu, nx, ny = model.nu, model.nx, model.ny
2525
nym, nyu = length(i_ym), ny - length(i_ym)
26+
Asm, Csm, nint_ym = init_estimstoch(i_ym, nint_ym)
2627
nxs = size(Asm,1)
2728
nx̂ = nx + nxs
2829
validate_kfcov(nym, nx̂, Q̂, R̂)
@@ -128,16 +129,22 @@ function SteadyKalmanFilter(
128129
nint_ym::IntVectorOrInt = fill(1, length(i_ym)),
129130
σQ_int::Vector = fill(0.1, max(sum(nint_ym), 0))
130131
)
131-
if nint_ym == 0 # alias for no output integrator at all :
132-
nint_ym = fill(0, length(i_ym));
133-
end
134-
Asm, Csm = init_estimstoch(i_ym, nint_ym)
135132
# estimated covariances matrices (variance = σ²) :
136133
= Diagonal{Float64}([σQ ; σQ_int ].^2);
137134
= Diagonal{Float64}(σR.^2);
138-
return SteadyKalmanFilter(model, i_ym, nint_ym, Asm, Csm, Q̂ , R̂)
135+
return SteadyKalmanFilter(model, i_ym, nint_ym, Q̂ , R̂)
139136
end
140137

138+
@doc raw"""
139+
SteadyKalmanFilter(model, i_ym, nint_ym, Q̂, R̂)
140+
141+
Construct the estimator from the augmented covariance matrices `Q̂` and `R̂`.
142+
143+
This syntax allows nonzero off-diagonal elements in ``\mathbf{Q̂, R̂}``.
144+
"""
145+
SteadyKalmanFilter(model::LinModel, i_ym, nint_ym, Q̂, R̂)
146+
147+
141148
@doc raw"""
142149
updatestate!(estim::SteadyKalmanFilter, u, ym, d=Float64[])
143150
@@ -191,9 +198,17 @@ struct KalmanFilter <: StateEstimator
191198
P̂0::Hermitian{Float64, Matrix{Float64}}
192199
::Hermitian{Float64, Matrix{Float64}}
193200
::Hermitian{Float64, Matrix{Float64}}
194-
function KalmanFilter(model, i_ym, nint_ym, Asm, Csm, P̂0, Q̂, R̂)
201+
@doc raw"""
202+
KalmanFilter(model, i_ym, nint_ym, P̂0 ,Q̂, R̂)
203+
204+
Construct the estimator from the augmented covariance matrices `P̂0`, `Q̂` and `R̂`.
205+
206+
This syntax allows nonzero off-diagonal elements in ``\mathbf{P̂}_{-1}(0)\mathbf{, Q̂, R̂}``.
207+
"""
208+
function KalmanFilter(model, i_ym, nint_ym, P̂0, Q̂, R̂)
195209
nu, nx, ny = model.nu, model.nx, model.ny
196210
nym, nyu = length(i_ym), ny - length(i_ym)
211+
Asm, Csm, nint_ym = init_estimstoch(i_ym, nint_ym)
197212
nxs = size(Asm,1)
198213
nx̂ = nx + nxs
199214
validate_kfcov(nym, nx̂, Q̂, R̂, P̂0)
@@ -260,17 +275,23 @@ function KalmanFilter(
260275
σP0_int::Vector = fill(10, max(sum(nint_ym), 0)),
261276
σQ_int::Vector = fill(0.1, max(sum(nint_ym), 0))
262277
)
263-
if nint_ym == 0 # alias for no output integrator at all :
264-
nint_ym = fill(0, length(i_ym));
265-
end
266-
Asm, Csm = init_estimstoch(i_ym, nint_ym)
267278
# estimated covariances matrices (variance = σ²) :
268279
P̂0 = Diagonal{Float64}([σP0 ; σP0_int ].^2);
269280
= Diagonal{Float64}([σQ ; σQ_int ].^2);
270281
= Diagonal{Float64}(σR.^2);
271-
return KalmanFilter(model, i_ym, nint_ym, Asm, Csm, P̂0, Q̂ , R̂)
282+
return KalmanFilter(model, i_ym, nint_ym, P̂0, Q̂ , R̂)
272283
end
273284

285+
@doc raw"""
286+
KalmanFilter(model, i_ym, nint_ym, P̂0, Q̂, R̂)
287+
288+
Construct the estimator from the augmented covariance matrices `P̂0`, `Q̂` and `R̂`.
289+
290+
This syntax allows nonzero off-diagonal elements in ``\mathbf{P̂}_{-1}(0), \mathbf{Q̂, R̂}``.
291+
"""
292+
KalmanFilter(model::LinModel, i_ym, nint_ym, P̂0 ,Q̂, R̂)
293+
294+
274295
@doc raw"""
275296
updatestate!(estim::KalmanFilter, u, ym, d=Float64[])
276297
@@ -341,10 +362,11 @@ struct UnscentedKalmanFilter{M<:SimModel} <: StateEstimator
341362
::Vector{Float64}
342363
::Diagonal{Float64, Vector{Float64}}
343364
function UnscentedKalmanFilter{M}(
344-
model::M, i_ym, nint_ym, Asm, Csm, P̂0, Q̂, R̂, α, β, κ
365+
model::M, i_ym, nint_ym, P̂0, Q̂, R̂, α, β, κ
345366
) where {M<:SimModel}
346367
nu, nx, ny = model.nu, model.nx, model.ny
347368
nym, nyu = length(i_ym), ny - length(i_ym)
369+
Asm, Csm, nint_ym = init_estimstoch(i_ym, nint_ym)
348370
nxs = size(Asm,1)
349371
nx̂ = nx + nxs
350372
validate_kfcov(nym, nx̂, Q̂, R̂, P̂0)
@@ -424,17 +446,23 @@ function UnscentedKalmanFilter(
424446
β::Real = 2,
425447
κ::Real = 0
426448
) where {M<:SimModel}
427-
if nint_ym == 0 # alias for no output integrator at all :
428-
nint_ym = fill(0, length(i_ym));
429-
end
430-
Asm, Csm = init_estimstoch(i_ym, nint_ym)
431449
# estimated covariances matrices (variance = σ²) :
432450
P̂0 = Diagonal{Float64}([σP0 ; σP0_int ].^2);
433451
= Diagonal{Float64}([σQ ; σQ_int ].^2);
434452
= Diagonal{Float64}(σR.^2);
435-
return UnscentedKalmanFilter{M}(model, i_ym, nint_ym, Asm, Csm, P̂0, Q̂ , R̂, α, β, κ)
453+
return UnscentedKalmanFilter{M}(model, i_ym, nint_ym, P̂0, Q̂ , R̂, α, β, κ)
436454
end
437455

456+
@doc raw"""
457+
UnscentedKalmanFilter(model, i_ym, nint_ym, P̂0, Q̂, R̂, α, β, κ)
458+
459+
Construct the estimator from the augmented covariance matrices `P̂0`, `Q̂` and `R̂`.
460+
461+
This syntax allows nonzero off-diagonal elements in ``\mathbf{P̂}_{-1}(0), \mathbf{Q̂, R̂}``.
462+
"""
463+
UnscentedKalmanFilter{M}(model::SimModel, i_ym, nint_ym, P̂0, Q̂, R̂, α, β, κ) where {M}
464+
465+
438466
@doc raw"""
439467
init_ukf(nx̂, α, β, κ)
440468

src/estimator/luenberger.jl

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,10 @@ struct Luenberger <: StateEstimator
1818
Ĉm ::Matrix{Float64}
1919
D̂dm ::Matrix{Float64}
2020
K::Matrix{Float64}
21-
function Luenberger(model, i_ym, nint_ym, Asm, Csm, p̂)
21+
function Luenberger(model, i_ym, nint_ym, p̂)
2222
nu, nx, ny = model.nu, model.nx, model.ny
2323
nym, nyu = length(i_ym), ny - length(i_ym)
24+
Asm, Csm, nint_ym = init_estimstoch(i_ym, nint_ym)
2425
nxs = size(Asm,1)
2526
nx̂ = nx + nxs
2627
As, _ , Cs, _ = stoch_ym2y(model, i_ym, Asm, [], Csm, [])
@@ -82,16 +83,12 @@ function Luenberger(
8283
nint_ym::IntVectorOrInt = fill(1, length(i_ym)),
8384
= 1e-3*(0:(model.nx + sum(nint_ym)-1)) .+ 0.5
8485
)
85-
if nint_ym == 0 # alias for no output integrator at all :
86-
nint_ym = fill(0, length(i_ym));
87-
end
88-
Asm, Csm = init_estimstoch(i_ym, nint_ym)
8986
nx = model.nx
9087
if length(p̂) model.nx + sum(nint_ym)
9188
error("p̂ length ($(length(p̂))) ≠ nx ($nx) + integrator quantity ($(sum(nint_ym)))")
9289
end
9390
any(abs.(p̂) .≥ 1) && error("Observer poles p̂ should be inside the unit circles.")
94-
return Luenberger(model, i_ym, nint_ym, Asm, Csm, p̂)
91+
return Luenberger(model, i_ym, nint_ym, p̂)
9592
end
9693

9794

src/state_estim.jl

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,10 @@ be added for each measured output ``\mathbf{y^m}``. The argument generates the `
100100
where ``\mathbf{e}(k)`` is a conceptual and unknown zero mean white noise.
101101
``\mathbf{B_s^m}`` is not used for closed-loop state estimators thus ignored.
102102
"""
103-
function init_estimstoch(i_ym, nint_ym::Vector{Int})
103+
function init_estimstoch(i_ym, nint_ym)
104+
if nint_ym == 0 # alias for no output integrator at all
105+
nint_ym = fill(0, length(i_ym))
106+
end
104107
nym = length(i_ym);
105108
if length(nint_ym) nym
106109
error("nint_ym size ($(length(nint_ym))) ≠ measured output quantity nym ($nym)")
@@ -128,7 +131,7 @@ function init_estimstoch(i_ym, nint_ym::Vector{Int})
128131
else # no stochastic model :
129132
Asm, Csm = zeros(0, 0), zeros(nym, 0)
130133
end
131-
return Asm, Csm
134+
return Asm, Csm, nint_ym
132135
end
133136

134137
@doc raw"""

0 commit comments

Comments
 (0)