Skip to content

Commit 7e64174

Browse files
authored
Merge pull request #40 from JuliaControl/debug_mhe
Debug: MHE with `NonLinModel` update covariance with the correct state estimate
2 parents 383ce4b + d89ed9a commit 7e64174

File tree

5 files changed

+26
-12
lines changed

5 files changed

+26
-12
lines changed

Diff for: Project.toml

+1-1
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 = "0.19.1"
4+
version = "0.19.2"
55

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

Diff for: README.md

-1
Original file line numberDiff line numberDiff line change
@@ -130,4 +130,3 @@ for more detailed examples.
130130
- [x] state estimates
131131
- [x] process noise estimates
132132
- [x] sensor noise estimates
133-
- [ ] moving horizon estimator with no process noise to reduce the problem size

Diff for: src/estimator/kalman.jl

+17-2
Original file line numberDiff line numberDiff line change
@@ -565,7 +565,22 @@ noise, respectively.
565565
ISBN9780470045343.
566566
"""
567567
function update_estimate!(estim::UnscentedKalmanFilter{NT}, u, ym, d) where NT<:Real
568-
x̂, P̂, Q̂, R̂, K̂ = estim.x̂, estim.P̂, estim.Q̂, estim.R̂, estim.
568+
return update_estimate_ukf!(estim, u, ym, d, estim.P̂, estim.x̂)
569+
end
570+
571+
"""
572+
update_estimate_ukf!(estim::StateEstimator, u, ym, d, P̂, x̂=nothing)
573+
574+
Update Unscented Kalman Filter estimates and covariance matrices.
575+
576+
Allows code reuse for [`UnscentedKalmanFilter`](@ref) and [`MovingHorizonEstimator`](@ref).
577+
See [`update_estimate!(::UnscentedKalmanFilter, ::Any, ::Any, ::Any)`(@ref) docstring
578+
for the equations. If `isnothing(x̂)`, only the covariance `P̂` is updated.
579+
"""
580+
function update_estimate_ukf!(
581+
estim::StateEstimator{NT}, u, ym, d, P̂, x̂=nothing
582+
) where NT<:Real
583+
Q̂, R̂, K̂ = estim.Q̂, estim.R̂, estim.
569584
nym, nx̂, nσ = estim.nym, estim.nx̂, estim.
570585
γ, m̂, Ŝ = estim.γ, estim.m̂, estim.
571586
# --- initialize matrices ---
@@ -802,7 +817,7 @@ end
802817
803818
Update time-varying/extended Kalman Filter estimates with augmented `Â` and `Ĉm` matrices.
804819
805-
Allows code reuse for [`KalmanFilter`](@ref) and [`ExtendedKalmanFilterKalmanFilter`](@ref).
820+
Allows code reuse for [`KalmanFilter`](@ref), [`ExtendedKalmanFilterKalmanFilter`](@ref).
806821
They update the state `x̂` and covariance `P̂` with the same equations. The extended filter
807822
substitutes the augmented model matrices with its Jacobians (`Â = F̂` and `Ĉm = Ĥm`).
808823
The implementation uses in-place operations and explicit factorization to reduce

Diff for: src/estimator/mhe/execute.jl

+6-6
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ function update_estimate!(estim::MovingHorizonEstimator{NT}, u, ym, d) where NT<
8080
x̂ .= X̂[end-nx̂+1:end]
8181
if Nk == estim.He
8282
uarr, ymarr, darr = estim.U[1:model.nu], estim.Ym[1:nym], estim.D[1:model.nd]
83-
update_cov!(estim.P̂arr_old, estim, model, uarr, ymarr, darr)
83+
update_cov!(estim, model, estim.x̂arr_old, estim.P̂arr_old, uarr, ymarr, darr)
8484
estim.invP̄.data .= Hermitian(inv(estim.P̂arr_old), :L)
8585
end
8686
return nothing
@@ -324,16 +324,16 @@ function trunc_bounds(estim::MovingHorizonEstimator{NT}, Bmin, Bmax, n) where NT
324324
end
325325

326326
"Update the covariance `P̂` with the `KalmanFilter` if `model` is a `LinModel`."
327-
function update_cov!(P̂, estim::MovingHorizonEstimator, ::LinModel, u, ym, d)
327+
function update_cov!(estim::MovingHorizonEstimator, ::LinModel, _ , P̂, u, ym, d)
328328
return update_estimate_kf!(estim, u, ym, d, estim.Â, estim.Ĉ[estim.i_ym, :], P̂)
329329
end
330330
"Update it with the `ExtendedKalmanFilter` if model is not a `LinModel`."
331-
function update_cov!(P̂, estim::MovingHorizonEstimator, model::SimModel, u, ym, d)
331+
function update_cov!(estim::MovingHorizonEstimator, model::SimModel, x̂, P̂, u, ym, d)
332332
# TODO: also support UnscentedKalmanFilter
333333
x̂next, ŷ = similar(estim.x̂), similar(model.yop)
334-
= ForwardDiff.jacobian((x̂next, x̂) -> f̂!(x̂next, estim, estim.model, x̂, u, d), x̂next, estim.x̂)
335-
= ForwardDiff.jacobian((ŷ, x̂) -> ĥ!(ŷ, estim, estim.model, x̂, d), ŷ, estim.x̂)
336-
return update_estimate_kf!(estim, u, ym, d, F̂, Ĥ[estim.i_ym, :], P̂)
334+
= ForwardDiff.jacobian((x̂next, x̂) -> f̂!(x̂next, estim, estim.model, x̂, u, d), x̂next, x̂)
335+
= ForwardDiff.jacobian((ŷ, x̂) -> ĥ!(ŷ, estim, estim.model, x̂, d), ŷ, x̂)
336+
return update_estimate_kf!(estim, u, ym, d, F̂, Ĥ[estim.i_ym, :], P̂)
337337
end
338338

339339

Diff for: src/model/linmodel.jl

+2-2
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,8 @@ with the state ``\mathbf{x}`` and output ``\mathbf{y}`` vectors. The ``\mathbf{z
4747
comprises the manipulated inputs ``\mathbf{u}`` and measured disturbances ``\mathbf{d}``,
4848
in any order. `i_u` provides the indices of ``\mathbf{z}`` that are manipulated, and `i_d`,
4949
the measured disturbances. The constructor automatically discretizes continuous systems,
50-
resamples discrete ones if `Ts ≠ sys.Ts`, compute a new realization if not minimal, and
51-
separate the ``\mathbf{z}`` terms in two parts (details in Extended Help). The rest of the
50+
resamples discrete ones if `Ts ≠ sys.Ts`, computes a new realization if not minimal, and
51+
separates the ``\mathbf{z}`` terms in two parts (details in Extended Help). The rest of the
5252
documentation assumes discrete dynamics since all systems end up in this form.
5353
5454
See also [`ss`](https://juliacontrol.github.io/ControlSystems.jl/stable/lib/constructors/#ControlSystemsBase.ss)

0 commit comments

Comments
 (0)