Skip to content

Commit 3f02ec3

Browse files
committed
doc: add info on custom covariance estimator for MHE
1 parent a965c12 commit 3f02ec3

File tree

3 files changed

+33
-48
lines changed

3 files changed

+33
-48
lines changed

docs/src/manual/nonlinmpc.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ savefig(ans, "plot1_NonLinMPC.svg"); nothing # hide
7979
An [`UnscentedKalmanFilter`](@ref) estimates the plant state :
8080

8181
```@example 1
82-
α=0.1; σQ=[0.1, 0.5]; σR=[0.5]; nint_u=[1]; σQint_u=[0.1]
82+
α=0.01; σQ=[0.1, 0.5]; σR=[0.5]; nint_u=[1]; σQint_u=[0.1]
8383
estim = UnscentedKalmanFilter(model; α, σQ, σR, nint_u, σQint_u)
8484
```
8585

src/estimator/kalman.jl

Lines changed: 15 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -428,7 +428,7 @@ represents the measured outputs of ``\mathbf{ĥ}`` function (and unmeasured one
428428
429429
# Arguments
430430
- `model::SimModel` : (deterministic) model for the estimations.
431-
- `α=1e-3` : alpha parameter, spread of the state distribution ``(0 α ≤ 1)``.
431+
- `α=1e-3` : alpha parameter, spread of the state distribution ``(0 < α ≤ 1)``.
432432
- `β=2` : beta parameter, skewness and kurtosis of the states distribution ``(β ≥ 0)``.
433433
- `κ=0` : kappa parameter, another spread parameter ``(0 ≤ κ ≤ 3)``.
434434
- `<keyword arguments>` of [`SteadyKalmanFilter`](@ref) constructor.
@@ -565,22 +565,7 @@ noise, respectively.
565565
ISBN9780470045343.
566566
"""
567567
function update_estimate!(estim::UnscentedKalmanFilter{NT}, u, ym, d) where NT<:Real
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.
568+
x̂, P̂, Q̂, R̂, K̂ = estim.x̂, estim.P̂, estim.Q̂, estim.R̂, estim.
584569
nym, nx̂, nσ = estim.nym, estim.nx̂, estim.
585570
γ, m̂, Ŝ = estim.γ, estim.m̂, estim.
586571
# --- initialize matrices ---
@@ -815,34 +800,29 @@ function validate_kfcov(nym, nx̂, Q̂, R̂, P̂0=nothing)
815800
end
816801

817802
"""
818-
update_estimate_kf!(estim::StateEstimator, u, ym, d, Â, Ĉm, P̂, x̂=nothing)
803+
update_estimate_kf!(estim::StateEstimator, u, ym, d, Â, Ĉm, P̂, x̂)
819804
820805
Update time-varying/extended Kalman Filter estimates with augmented `Â` and `Ĉm` matrices.
821806
822807
Allows code reuse for [`KalmanFilter`](@ref), [`ExtendedKalmanFilterKalmanFilter`](@ref).
823808
They update the state `x̂` and covariance `P̂` with the same equations. The extended filter
824809
substitutes the augmented model matrices with its Jacobians (`Â = F̂` and `Ĉm = Ĥm`).
825810
The implementation uses in-place operations and explicit factorization to reduce
826-
allocations. See e.g. [`KalmanFilter`](@ref) docstring for the equations. If `isnothing(x̂)`,
827-
only the covariance `P̂` is updated.
811+
allocations. See e.g. [`KalmanFilter`](@ref) docstring for the equations.
828812
"""
829-
function update_estimate_kf!(
830-
estim::StateEstimator{NT}, u, ym, d, Â, Ĉm, P̂, x̂=nothing
831-
) where NT<:Real
832-
Q̂, R̂, M̂ = estim.Q̂, estim.R̂, estim.
813+
function update_estimate_kf!(estim::StateEstimator{NT}, u, ym, d, Â, Ĉm, P̂, x̂) where NT<:Real
814+
Q̂, R̂, M̂, K̂ = estim.Q̂, estim.R̂, estim.M̂, estim.
833815
mul!(M̂, P̂, Ĉm')
834816
rdiv!(M̂, cholesky!(Hermitian(Ĉm ** Ĉm' .+ R̂)))
835-
if !isnothing(x̂)
836-
mul!(estim.K̂, Â, M̂)
837-
x̂next, ŷ = Vector{NT}(undef, estim.nx̂), Vector{NT}(undef, estim.model.ny)
838-
ĥ!(ŷ, estim, estim.model, x̂, d)
839-
ŷm = @views ŷ[estim.i_ym]
840-
= ŷm
841-
v̂ .= ym .- ŷm
842-
f̂!(x̂next, estim, estim.model, x̂, u, d)
843-
mul!(x̂next, estim.K̂, v̂, 1, 1)
844-
estim.x̂ .= x̂next
845-
end
817+
mul!(K̂, Â, M̂)
818+
x̂next, ŷ = Vector{NT}(undef, estim.nx̂), Vector{NT}(undef, estim.model.ny)
819+
ĥ!(ŷ, estim, estim.model, x̂, d)
820+
ŷm = @views ŷ[estim.i_ym]
821+
= ŷm
822+
v̂ .= ym .- ŷm
823+
f̂!(x̂next, estim, estim.model, x̂, u, d)
824+
mul!(x̂next, K̂, v̂, 1, 1)
825+
estim.x̂ .= x̂next
846826
.data .=* (P̂ .-* Ĉm * P̂) *' .+# .data is necessary for Hermitians
847827
return nothing
848828
end

src/estimator/mhe/construct.jl

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -187,9 +187,9 @@ N_k = \begin{cases}
187187
```
188188
The vectors ``\mathbf{Ŵ}`` and ``\mathbf{V̂}`` encompass the estimated process noise
189189
``\mathbf{ŵ}(k-j)`` and sensor noise ``\mathbf{v̂}(k-j)`` from ``j=N_k-1`` to ``0``. The
190-
Extended Help defines the two vectors and the scalar ``ϵ``. See [`UnscentedKalmanFilter`](@ref)
191-
for details on the augmented process model and ``\mathbf{R̂}, \mathbf{Q̂}`` covariances. The
192-
covariance ``\mathbf{P̂}_{k-N_k}(k-N_k+1)`` is estimated with an [`ExtendedKalmanFilter`](@ref).
190+
Extended Help defines the two vectors, the slack variable ``ϵ``, and the estimation of the
191+
covariance at arrival ``\mathbf{P̂}_{k-N_k}(k-N_k+1)``. See [`UnscentedKalmanFilter`](@ref)
192+
for details on the augmented process model and ``\mathbf{R̂}, \mathbf{Q̂}`` covariances.
193193
194194
!!! warning
195195
See the Extended Help if you get an error like:
@@ -248,18 +248,23 @@ MovingHorizonEstimator estimator with a sample time Ts = 10.0 s, Ipopt optimizer
248248
The slack variable ``ϵ`` relaxes the constraints if enabled, see [`setconstraint!`](@ref).
249249
It is disabled by default for the MHE (from `Cwt=Inf`) but it should be activated for
250250
problems with two or more types of bounds, to ensure feasibility (e.g. on the estimated
251-
state and sensor noise).
252-
253-
For [`LinModel`](@ref), the optimization is treated as a quadratic program with a
254-
time-varying Hessian, which is generally cheaper than nonlinear programming.
251+
state and sensor noise).
255252
256-
For [`NonLinModel`](@ref), the optimization relies on automatic differentiation (AD).
257-
Optimizers generally benefit from exact derivatives like AD. However, the `f` and `h`
258-
functions must be compatible with this feature. See [Automatic differentiation](https://jump.dev/JuMP.jl/stable/manual/nlp/#Automatic-differentiation)
259-
for common mistakes when writing these functions.
253+
The optimization and the estimation of the covariance at arrival
254+
``\mathbf{P̂}_{k-N_k}(k-N_k+1)`` depend on `model`:
255+
256+
- If `model` is a [`LinModel`](@ref), the optimization is treated as a quadratic program
257+
with a time-varying Hessian, which is generally cheaper than nonlinear programming. By
258+
default, a [`KalmanFilter`](@ref) estimates the arrival covariance (customizable).
259+
- Else, a nonlinear program with automatic differentiation (AD) solves the optimization.
260+
Optimizers generally benefit from exact derivatives like AD. However, the `f` and `h`
261+
functions must be compatible with this feature. See [Automatic differentiation](https://jump.dev/JuMP.jl/stable/manual/nlp/#Automatic-differentiation)
262+
for common mistakes when writing these functions. An [`UnscentedKalmanFilter`](@ref)
263+
estimates the arrival covariance by default.
260264
261265
Note that if `Cwt≠Inf`, the attribute `nlp_scaling_max_gradient` of `Ipopt` is set to
262-
`10/Cwt` (if not already set), to scale the small values of ``ϵ``.
266+
`10/Cwt` (if not already set), to scale the small values of ``ϵ``. Use the second
267+
constructor to specify the covariance estimation method.
263268
"""
264269
function MovingHorizonEstimator(
265270
model::SM;

0 commit comments

Comments
 (0)