Skip to content

Commit 7b70bd6

Browse files
committed
added: support SteadyKalmanFilter for covestim argument in MovingHorizonEstimator
1 parent bc08d73 commit 7b70bd6

File tree

5 files changed

+30
-10
lines changed

5 files changed

+30
-10
lines changed

Project.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ SparseConnectivityTracer = "9f842d2f-2579-4b1d-911e-f412cf18a3f5"
2121
SparseMatrixColorings = "0a514795-09f3-496d-8182-132a7b665d35"
2222

2323
[compat]
24-
ControlSystemsBase = "1.9"
24+
ControlSystemsBase = "1.18.2"
2525
DAQP = "0.6, 0.7.1"
2626
DifferentiationInterface = "0.6.45, 0.7"
2727
Documenter = "1"

src/estimator/construct.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,9 +59,9 @@ struct KalmanCovariances{
5959
P̂_0 = zeros(NT, 0, 0)
6060
end
6161
P̂_0 = Hermitian(P̂_0, :L)
62-
= copy(P̂_0)
6362
= Hermitian(Q̂, :L)
6463
= Hermitian(R̂, :L)
64+
= copy(Q̂)
6565
# the following variables are only for the moving horizon estimator:
6666
invP̄, invQ̂, invR̂ = copy(P̂_0), copy(Q̂), copy(R̂)
6767
try

src/estimator/kalman.jl

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
1+
"Abstract supertype of all Kalman-type state estimators."
2+
abstract type KalmanEstimator{NT<:Real} <: StateEstimator{NT} end
3+
14
struct SteadyKalmanFilter{
25
NT<:Real,
36
SM<:LinModel,
47
KC<:KalmanCovariances
5-
} <: StateEstimator{NT}
8+
} <: KalmanEstimator{NT}
69
model::SM
710
cov ::KC
811
x̂op ::Vector{NT}
@@ -47,8 +50,8 @@ struct SteadyKalmanFilter{
4750
R̂_y[i_ym, i_ym] =
4851
R̂_y = Hermitian(R̂_y, :L)
4952
end
50-
= try
51-
ControlSystemsBase.kalman(Discrete, Â, Ĉ, Q̂, R̂_y; direct)[:, i_ym]
53+
K̂_y, P̂ = try
54+
ControlSystemsBase.kalman(Discrete, Â, Ĉ, Q̂, R̂_y; direct, extra=Val(true))
5255
catch my_error
5356
if isa(my_error, ErrorException)
5457
error("Cannot compute the optimal Kalman gain K̂ for the "*
@@ -58,6 +61,8 @@ struct SteadyKalmanFilter{
5861
rethrow()
5962
end
6063
end
64+
= (ny == nym) ? K̂_y : K̂_y[:, i_ym]
65+
cov.P̂ .= Hermitian(P̂, :L)
6166
x̂0 = [zeros(NT, model.nx); zeros(NT, nxs)]
6267
corrected = [false]
6368
buffer = StateEstimatorBuffer{NT}(nu, nx̂, nym, ny, nd, nk)
@@ -296,7 +301,7 @@ struct KalmanFilter{
296301
NT<:Real,
297302
SM<:LinModel,
298303
KC<:KalmanCovariances
299-
} <: StateEstimator{NT}
304+
} <: KalmanEstimator{NT}
300305
model::SM
301306
cov ::KC
302307
x̂op::Vector{NT}
@@ -508,7 +513,7 @@ struct UnscentedKalmanFilter{
508513
NT<:Real,
509514
SM<:SimModel,
510515
KC<:KalmanCovariances
511-
} <: StateEstimator{NT}
516+
} <: KalmanEstimator{NT}
512517
model::SM
513518
cov ::KC
514519
x̂op ::Vector{NT}
@@ -885,7 +890,7 @@ struct ExtendedKalmanFilter{
885890
JB<:AbstractADType,
886891
FF<:Function,
887892
HF<:Function
888-
} <: StateEstimator{NT}
893+
} <: KalmanEstimator{NT}
889894
model::SM
890895
cov ::KC
891896
x̂op ::Vector{NT}

src/estimator/mhe.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ include("mhe/execute.jl")
55
function print_details(io::IO, estim::MovingHorizonEstimator)
66
println(io, "├ optimizer: $(JuMP.solver_name(estim.optim)) ")
77
print_backends(io, estim, estim.model)
8+
println(io, "├ arrival covariance: $(nameof(typeof(estim.covestim))) ")
89
end
910

1011
"Print the differentiation backends for `SimModel`."

src/estimator/mhe/construct.jl

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ struct MovingHorizonEstimator{
5151
JM<:JuMP.GenericModel,
5252
GB<:AbstractADType,
5353
JB<:AbstractADType,
54-
CE<:StateEstimator,
54+
CE<:KalmanEstimator,
5555
} <: StateEstimator{NT}
5656
model::SM
5757
cov ::KC
@@ -121,7 +121,7 @@ struct MovingHorizonEstimator{
121121
JM<:JuMP.GenericModel,
122122
GB<:AbstractADType,
123123
JB<:AbstractADType,
124-
CE<:StateEstimator{NT}
124+
CE<:KalmanEstimator{NT}
125125
}
126126
nu, ny, nd, nk = model.nu, model.ny, model.nd, model.nk
127127
He < 1 && throw(ArgumentError("Estimation horizon He should be ≥ 1"))
@@ -436,6 +436,7 @@ function MovingHorizonEstimator(
436436
) where {NT<:Real, SM<:SimModel{NT}, JM<:JuMP.GenericModel, CE<:StateEstimator{NT}}
437437
P̂_0, Q̂, R̂ = to_mat(P̂_0), to_mat(Q̂), to_mat(R̂)
438438
cov = KalmanCovariances(model, i_ym, nint_u, nint_ym, Q̂, R̂, P̂_0, He)
439+
validate_covestim(cov, covestim)
439440
return MovingHorizonEstimator{NT}(
440441
model,
441442
He, i_ym, nint_u, nint_ym, cov, Cwt,
@@ -444,13 +445,26 @@ function MovingHorizonEstimator(
444445
)
445446
end
446447

448+
447449
function default_covestim_mhe(model::LinModel, i_ym, nint_u, nint_ym, P̂_0, Q̂, R̂; direct)
448450
return KalmanFilter(model, i_ym, nint_u, nint_ym, P̂_0, Q̂, R̂; direct)
449451
end
450452
function default_covestim_mhe(model::SimModel, i_ym, nint_u, nint_ym, P̂_0, Q̂, R̂; direct)
451453
return UnscentedKalmanFilter(model, i_ym, nint_u, nint_ym, P̂_0, Q̂, R̂; direct)
452454
end
453455

456+
"Validate covestim type and dimensions."
457+
function validate_covestim(cov::KalmanCovariances, covestim::KalmanEstimator)
458+
if size(cov.P̂) != size(covestim.cov.P̂)
459+
throw(ArgumentError("estimation covariance covestim.cov.P̂ size does not match the MHE"))
460+
end
461+
return nothing
462+
end
463+
function validate_covestim(::KalmanCovariances, ::StateEstimator)
464+
error( "covestim argument must be a SteadyKalmanFilter, KalmanFilter, "*
465+
"ExtendedKalmanFilter or UnscentedKalmanFilter")
466+
end
467+
454468
@doc raw"""
455469
setconstraint!(estim::MovingHorizonEstimator; <keyword arguments>) -> estim
456470

0 commit comments

Comments
 (0)