11const DEFAULT_LINMHE_OPTIMIZER = OSQP. MathOptInterfaceOSQP. Optimizer
22const DEFAULT_NONLINMHE_OPTIMIZER = optimizer_with_attributes (Ipopt. Optimizer," sb" => " yes" )
33
4- " Include all the data for the constraints of [`MovingHorizonEstimator`](@ref)"
4+ @doc raw """
5+ Include all the data for the constraints of [`MovingHorizonEstimator`](@ref).
6+
7+ The bounds on the estimated state at arrival ``\m athbf{x̂}_k(k-N_k+1)`` is separated from
8+ the other state constraints ``\m athbf{x̂}_k(k-N_k+2), \m athbf{x̂}_k(k-N_k+3), ...`` since
9+ the former is always a linear inequality constraint (it's a decision variable). The fields
10+ `x̂min` and `x̂max` refer to the bounds at the arrival, and `X̂min` and `X̂max`, the others.
11+ """
512struct EstimatorConstraint{NT<: Real }
613 Ẽx̂ :: Matrix{NT}
714 Fx̂ :: Vector{NT}
@@ -144,7 +151,7 @@ This estimator can handle constraints on the estimates, see [`setconstraint!`](@
144151Additionally, `model` is not linearized like the [`ExtendedKalmanFilter`](@ref), and the
145152probability distribution is not approximated like the [`UnscentedKalmanFilter`](@ref). The
146153computational costs are drastically higher, however, since it minimizes the following
147- nonlinear objective function at each discrete time ``k``:
154+ objective function at each discrete time ``k``:
148155```math
149156\m in_{\m athbf{x̂}_k(k-N_k+1), \m athbf{Ŵ}} \m athbf{x̄}' \m athbf{P̄}^{-1} \m athbf{x̄}
150157 + \m athbf{Ŵ}' \m athbf{Q̂}_{N_k}^{-1} \m athbf{Ŵ}
@@ -164,8 +171,11 @@ and the covariances are repeated ``N_k`` times:
164171 \m athbf{R̂}_{N_k} &= \t ext{diag}\m athbf{(R̂,R̂,...,R̂)}
165172\e nd{aligned}
166173```
167- The estimation horizon ``H_e`` limits the window length ``N_k = \m in(k+1, H_e)``. The
168- vectors ``\m athbf{Ŵ}`` and ``\m athbf{V̂}`` encompass the estimated process noise
174+ The estimation horizon ``H_e`` limits the window length:
175+ ```math
176+ N_k = \m in(k+1, H_e)
177+ ```
178+ The vectors ``\m athbf{Ŵ}`` and ``\m athbf{V̂}`` encompass the estimated process noise
169179``\m athbf{ŵ}(k-j)`` and sensor noise ``\m athbf{v̂}(k-j)`` from ``j=N_k-1`` to ``0``. The
170180Extended Help explicitly defines the two vectors. See [`SteadyKalmanFilter`](@ref) for
171181details on ``\m athbf{R̂}, \m athbf{Q̂}`` covariances and model augmentation. The process
@@ -179,7 +189,7 @@ model is identical to the one in [`UnscentedKalmanFilter`](@ref) documentation.
179189# Arguments
180190- `model::SimModel` : (deterministic) model for the estimations.
181191- `He=nothing`: estimation horizon ``H_e``, must be specified.
182- - `optim=default_mhe_optim (model)` : quadratic or nonlinear optimizer used in the moving
192+ - `optim=default_optim_mhe (model)` : quadratic or nonlinear optimizer used in the moving
183193 horizon estimator, provided as a [`JuMP.Model`](https://jump.dev/JuMP.jl/stable/api/JuMP/#JuMP.Model)
184194 (default to [`Ipopt.jl`](https://github.com/jump-dev/Ipopt.jl), or [`OSQP.jl`](https://osqp.org/docs/parsers/jump.html)
185195 if `model` is a [`LinModel`](@ref)).
@@ -191,7 +201,7 @@ model is identical to the one in [`UnscentedKalmanFilter`](@ref) documentation.
191201julia> model = NonLinModel((x,u,_)->0.1x+u, (x,_)->2x, 10.0, 1, 1, 1);
192202
193203julia> estim = MovingHorizonEstimator(model, He=5, σR=[1], σP0=[0.01])
194- MovingHorizonEstimator estimator with a sample time Ts = 10.0 s, NonLinModel and:
204+ MovingHorizonEstimator estimator with a sample time Ts = 10.0 s, Ipopt optimizer, NonLinModel and:
195205 5 estimation steps He
196206 1 manipulated inputs u (0 integrating states)
197207 2 states x̂
@@ -238,7 +248,7 @@ function MovingHorizonEstimator(
238248 nint_ym :: IntVectorOrInt = default_nint (model, i_ym, nint_u),
239249 σQint_ym :: Vector = fill (1 , max (sum (nint_ym), 0 )),
240250 σP0int_ym:: Vector = fill (1 , max (sum (nint_ym), 0 )),
241- optim:: JM = default_mhe_optim (model),
251+ optim:: JM = default_optim_mhe (model),
242252) where {NT<: Real , SM<: SimModel{NT} , JM<: JuMP.GenericModel }
243253 # estimated covariances matrices (variance = σ²) :
244254 P̂0 = Hermitian (diagm (NT[σP0; σP0int_u; σP0int_ym]. ^ 2 ), :L )
@@ -251,9 +261,9 @@ function MovingHorizonEstimator(
251261end
252262
253263" Return a `JuMP.Model` with OSQP optimizer if `model` is a [`LinModel`](@ref)."
254- default_mhe_optim (:: LinModel ) = JuMP. Model (DEFAULT_LINMHE_OPTIMIZER, add_bridges= false )
264+ default_optim_mhe (:: LinModel ) = JuMP. Model (DEFAULT_LINMHE_OPTIMIZER, add_bridges= false )
255265" Else, return it with Ipopt optimizer."
256- default_mhe_optim (:: SimModel ) = JuMP. Model (DEFAULT_NONLINMHE_OPTIMIZER, add_bridges= false )
266+ default_optim_mhe (:: SimModel ) = JuMP. Model (DEFAULT_NONLINMHE_OPTIMIZER, add_bridges= false )
257267
258268@doc raw """
259269 MovingHorizonEstimator(model, He, i_ym, nint_u, nint_ym, P̂0, Q̂, R̂, optim)
618628
619629Set the constraint parameters of `estim` [`MovingHorizonEstimator`](@ref).
620630
621- The moving horizon estimator supports constraints on the estimated states ``\m athbf{x̂}``,
631+ The moving horizon estimator supports constraints on the estimated state ``\m athbf{x̂}``,
622632process noise ``\m athbf{ŵ}`` and sensor noise ``\m athbf{v̂}``:
623633```math
624634\b egin{alignat*}{3}
@@ -627,9 +637,9 @@ process noise ``\mathbf{ŵ}`` and sensor noise ``\mathbf{v̂}``:
627637 \m athbf{v̂_{min}} ≤&&\ \m athbf{v̂}(k-j+1) &≤ \m athbf{v̂_{max}} &&\q quad j = N_k, N_k - 1, ... , 1
628638\e nd{alignat*}
629639```
630- Note that state and process noise constraints are applied on augmented model vectors (see
631- the extended help of [`SteadyKalmanFilter`](@ref) for details on augmentation). Also,
632- constraining the estimated sensor noises is equivalent to constraining the innovation term
640+ Note that the state and process noise constraints are applied on augmented model vectors
641+ (see the extended help of [`SteadyKalmanFilter`](@ref) for details on augmentation). Also,
642+ constraining the estimated sensor noises is equivalent to constraining the innovation term,
633643since ``\m athbf{v̂}(k) = \m athbf{y^m}(k) - \m athbf{ŷ^m}(k)`` in the MHE. See Extended Help
634644for time-varying constraints.
635645
@@ -653,7 +663,7 @@ for time-varying constraints.
653663julia> estim = MovingHorizonEstimator(LinModel(ss(0.5,1,1,0,1)), He=3);
654664
655665julia> estim = setconstraint!(estim, x̂min=[-50, -50], x̂max=[50, 50])
656- MovingHorizonEstimator estimator with a sample time Ts = 1.0 s, LinModel and:
666+ MovingHorizonEstimator estimator with a sample time Ts = 1.0 s, OSQP optimizer, LinModel and:
657667 3 estimation steps He
658668 1 manipulated inputs u (0 integrating states)
659669 2 states x̂
@@ -822,6 +832,16 @@ function setnonlincon!(estim::MovingHorizonEstimator, ::NonLinModel)
822832 return nothing
823833end
824834
835+ function Base. show (io:: IO , estim:: MovingHorizonEstimator )
836+ nu, nd = estim. model. nu, estim. model. nd
837+ nx̂, nym, nyu = estim. nx̂, estim. nym, estim. nyu
838+ n = maximum (ndigits .((nu, nx̂, nym, nyu, nd))) + 1
839+ println (io, " $(typeof (estim). name. name) estimator with a sample time " *
840+ " Ts = $(estim. model. Ts) s, $(solver_name (estim. optim)) optimizer, " *
841+ " $(typeof (estim. model). name. name) and:" )
842+ print_estim_dim (io, estim, n)
843+ end
844+
825845" Print the overall dimensions of the state estimator `estim` with left padding `n`."
826846function print_estim_dim (io:: IO , estim:: MovingHorizonEstimator , n)
827847 nu, nd = estim. model. nu, estim. model. nd
@@ -902,9 +922,6 @@ function update_estimate!(estim::MovingHorizonEstimator{NT}, u, ym, d) where NT<
902922 isfinite (J0) || (Z̃0 = [estim. x̂arr_old; zeros (NT, nŴ)])
903923 set_start_value .(Z̃var, Z̃0)
904924 # ------- solve optimization problem --------------
905- # at start, when time windows are not filled, some decision variables are fixed at 0:
906- # unfix.(Z̃var[is_fixed.(Z̃var)])
907- # fix.(Z̃var[(1 + nx̂*(Nk+1)):end], 0)
908925 try
909926 optimize! (optim)
910927 catch err
@@ -1043,14 +1060,22 @@ function obj_nonlinprog(
10431060end
10441061
10451062"""
1046- predict!(V̂, X̂, estim::MovingHorizonEstimator, model::SimModel , Z̃) -> V̂, X̂
1063+ predict!(V̂, X̂, estim::MovingHorizonEstimator, model::LinModel , Z̃) -> V̂, X̂
10471064
1048- Compute the `V̂` vector and `X̂` vectors for the `MovingHorizonEstimator`.
1065+ Compute the `V̂` vector and `X̂` vectors for the `MovingHorizonEstimator` and `LinModel` .
10491066
10501067The method mutates `V̂` and `X̂` vector arguments. The vector `V̂` is the estimated sensor
10511068noises `V̂` from ``k-N_k+1`` to ``k``. The `X̂` vector is estimated states from ``k-N_k+2`` to
10521069``k+1``.
10531070"""
1071+ function predict! (V̂, X̂, estim:: MovingHorizonEstimator , :: LinModel , Z̃)
1072+ nX̂, nYm = estim. nx̂* estim. Nk[], estim. nym* estim. Nk[]
1073+ V̂[1 : nYm] = estim. Ẽ* Z̃ + estim. F
1074+ X̂[1 : nX̂] = estim. con. Ẽx̂* Z̃ + estim. con. Fx̂
1075+ return V̂, X̂
1076+ end
1077+
1078+ " Compute the two vectors when `model` is not a `LinModel`."
10541079function predict! (
10551080 V̂, X̂, estim:: MovingHorizonEstimator , model:: SimModel , Z̃:: Vector{T}
10561081) where {T<: Real }
0 commit comments