@@ -193,7 +193,7 @@ model is identical to the one in [`UnscentedKalmanFilter`](@ref) documentation.
193193- `He=nothing`: estimation horizon ``H_e``, must be specified.
194194- `optim=default_optim_mhe(model)` : quadratic or nonlinear optimizer used in the moving
195195 horizon estimator, provided as a [`JuMP.Model`](https://jump.dev/JuMP.jl/stable/api/JuMP/#JuMP.Model)
196- (default to [`Ipopt.jl `](https://github.com/jump-dev/Ipopt.jl), or [`OSQP.jl `](https://osqp.org/docs/parsers/jump.html)
196+ (default to [`Ipopt`](https://github.com/jump-dev/Ipopt.jl), or [`OSQP`](https://osqp.org/docs/parsers/jump.html)
197197 if `model` is a [`LinModel`](@ref)).
198198- `<keyword arguments>` of [`SteadyKalmanFilter`](@ref) constructor.
199199- `<keyword arguments>` of [`KalmanFilter`](@ref) constructor.
@@ -562,7 +562,7 @@ function init_optimization!(
562562 g = get_tmp (g_cache, Z̃tup[1 ])
563563 X̂ = get_tmp (X̂_cache, Z̃tup[1 ])
564564 V̂, X̂ = predict! (V̂, X̂, estim, model, Z̃)
565- g = con_nonlinprog! (g, estim, model, X̂)
565+ g = con_nonlinprog! (g, estim, model, X̂, V̂ )
566566 last_Z̃tup_float = Z̃tup
567567 end
568568 return obj_nonlinprog (estim, model, V̂, Z̃)
@@ -574,7 +574,7 @@ function init_optimization!(
574574 g = get_tmp (g_cache, Z̃tup[1 ])
575575 X̂ = get_tmp (X̂_cache, Z̃tup[1 ])
576576 V̂, X̂ = predict! (V̂, X̂, estim, model, Z̃)
577- g = con_nonlinprog! (g, estim, model, X̂)
577+ g = con_nonlinprog! (g, estim, model, X̂, V̂ )
578578 last_Z̃tup_dual = Z̃tup
579579 end
580580 return obj_nonlinprog (estim, model, V̂, Z̃)
@@ -586,7 +586,7 @@ function init_optimization!(
586586 X̂ = get_tmp (X̂_cache, Z̃tup[1 ])
587587 Z̃ = collect (Z̃tup)
588588 V̂, X̂ = predict! (V̂, X̂, estim, model, Z̃)
589- g = con_nonlinprog! (g, estim, model, X̂)
589+ g = con_nonlinprog! (g, estim, model, X̂, V̂ )
590590 last_Z̃tup_float = Z̃tup
591591 end
592592 return g[i]
@@ -598,7 +598,7 @@ function init_optimization!(
598598 X̂ = get_tmp (X̂_cache, Z̃tup[1 ])
599599 Z̃ = collect (Z̃tup)
600600 V̂, X̂ = predict! (V̂, X̂, estim, model, Z̃)
601- g = con_nonlinprog! (g, estim, model, X̂)
601+ g = con_nonlinprog! (g, estim, model, X̂, V̂ )
602602 last_Z̃tup_dual = Z̃tup
603603 end
604604 return g[i]
@@ -715,8 +715,8 @@ function setconstraint!(
715715 isnothing (X̂max) && ! isnothing (x̂max) && (X̂max = repeat (x̂max, He+ 1 ))
716716 isnothing (Ŵmin) && ! isnothing (ŵmin) && (Ŵmin = repeat (ŵmin, He))
717717 isnothing (Ŵmax) && ! isnothing (ŵmax) && (Ŵmax = repeat (ŵmax, He))
718- isnothing (V̂min) && ! isnothing (V̂min ) && (X̂min = repeat (v̂min, He))
719- isnothing (V̂max) && ! isnothing (V̂max ) && (X̂max = repeat (v̂max, He))
718+ isnothing (V̂min) && ! isnothing (v̂min ) && (V̂min = repeat (v̂min, He))
719+ isnothing (V̂max) && ! isnothing (v̂max ) && (V̂max = repeat (v̂max, He))
720720 if ! isnothing (X̂min)
721721 size (X̂min) == (nX̂con,) || throw (ArgumentError (" X̂min size must be $((nX̂con,)) " ))
722722 con. x̂min[:] = X̂min[1 : nx̂]
@@ -838,6 +838,14 @@ function setnonlincon!(estim::MovingHorizonEstimator, ::NonLinModel)
838838 f_sym = Symbol (" g_X̂max_$(i) " )
839839 add_nonlinear_constraint (optim, :($ (f_sym)($ (Z̃var... )) <= 0 ))
840840 end
841+ for i in findall (.! isinf .(con. V̂min))
842+ f_sym = Symbol (" g_V̂min_$(i) " )
843+ add_nonlinear_constraint (optim, :($ (f_sym)($ (Z̃var... )) <= 0 ))
844+ end
845+ for i in findall (.! isinf .(con. V̂max))
846+ f_sym = Symbol (" g_V̂max_$(i) " )
847+ add_nonlinear_constraint (optim, :($ (f_sym)($ (Z̃var... )) <= 0 ))
848+ end
841849 return nothing
842850end
843851
@@ -922,11 +930,11 @@ function update_estimate!(estim::MovingHorizonEstimator{NT}, u, ym, d) where NT<
922930 Nk = estim. Nk[]
923931 nŴ, nYm, nX̂ = nx̂* Nk, nym* Nk, nx̂* Nk
924932 Z̃var:: Vector{VariableRef} = optim[:Z̃var ]
925- x̄V̂ = Vector {NT} (undef, nx̂ + nYm)
933+ V̂ = Vector {NT} (undef, nYm)
926934 X̂ = Vector {NT} (undef, nX̂)
927935 Z̃0 = [estim. x̂arr_old; estim. Ŵ]
928- x̄V̂ , X̂ = predict! (x̄V̂ , X̂, estim, model, Z̃0)
929- J0 = obj_nonlinprog (estim, model, x̄V̂ , Z̃0)
936+ V̂ , X̂ = predict! (V̂ , X̂, estim, model, Z̃0)
937+ J0 = obj_nonlinprog (estim, model, V̂ , Z̃0)
930938 # initial Z̃0 with Ŵ=0 if objective or constraint function not finite :
931939 isfinite (J0) || (Z̃0 = [estim. x̂arr_old; zeros (NT, nŴ)])
932940 set_start_value .(Z̃var, Z̃0)
@@ -958,7 +966,7 @@ function update_estimate!(estim::MovingHorizonEstimator{NT}, u, ym, d) where NT<
958966 estim. Z̃[:] = ! isfatal (status) ? Z̃curr : Z̃last
959967 # --------- update estimate -----------------------
960968 estim. Ŵ[1 : nŴ] = estim. Z̃[nx̂+ 1 : nx̂+ nŴ] # update Ŵ with optimum for next time step
961- x̄V̂ , X̂ = predict! (x̄V̂ , X̂, estim, model, estim. Z̃)
969+ V̂ , X̂ = predict! (V̂ , X̂, estim, model, estim. Z̃)
962970 x̂[:] = X̂[(1 + nx̂* (Nk- 1 )): (nx̂* Nk)]
963971 if Nk == He
964972 uarr, ymarr, darr = estim. U[1 : nu], estim. Ym[1 : nym], estim. D[1 : nd]
@@ -1006,31 +1014,49 @@ function linconstraint!(estim::MovingHorizonEstimator, model::LinModel)
10061014 if model. nd ≠ 0
10071015 estim. con. Fx̂[:] = estim. con. Fx̂ + estim. con. Jx̂* estim. D
10081016 end
1017+ X̂min, X̂max = trunc_bounds (estim, estim. con. X̂min, estim. con. X̂max, estim. nx̂)
1018+ Ŵmin, Ŵmax = trunc_bounds (estim, estim. con. Ŵmin, estim. con. Ŵmax, estim. nx̂)
1019+ V̂min, V̂max = trunc_bounds (estim, estim. con. V̂min, estim. con. V̂max, estim. nym)
10091020 estim. con. b[:] = [
10101021 - estim. con. x̂min
10111022 + estim. con. x̂max
1012- - estim . con . X̂min + estim. con. Fx̂
1013- + estim . con . X̂max - estim. con. Fx̂
1014- - estim . con . Ŵmin
1015- + estim . con . Ŵmax
1016- - estim . con . V̂min + estim. F
1017- + estim . con . V̂max - estim. F
1023+ - X̂min + estim. con. Fx̂
1024+ + X̂max - estim. con. Fx̂
1025+ - Ŵmin
1026+ + Ŵmax
1027+ - V̂min + estim. F
1028+ + V̂max - estim. F
10181029 ]
10191030 lincon = estim. optim[:linconstraint ]
10201031 set_normalized_rhs .(lincon, estim. con. b[estim. con. i_b])
10211032end
10221033
10231034function linconstraint! (estim:: MovingHorizonEstimator , :: SimModel )
1035+ Ŵmin, Ŵmax = trunc_bounds (estim, estim. con. Ŵmin, estim. con. Ŵmax, estim. nx̂)
10241036 estim. con. b[:] = [
10251037 - estim. con. x̂min
10261038 + estim. con. x̂max
1027- - estim . con . Ŵmin
1028- + estim . con . Ŵmax
1039+ - Ŵmin
1040+ + Ŵmax
10291041 ]
10301042 lincon = estim. optim[:linconstraint ]
10311043 set_normalized_rhs .(lincon, estim. con. b[estim. con. i_b])
10321044end
10331045
1046+ " Truncate the bounds `Bmin` and `Bmax` to the window size `Nk` if `Nk < He`."
1047+ function trunc_bounds (estim:: MovingHorizonEstimator , Bmin, Bmax, n)
1048+ He, Nk = estim. He, estim. Nk[]
1049+ if Nk < He
1050+ nB = n* Nk
1051+ Bmin_t = @views [Bmin[end - nB+ 1 : end ]; fill (- Inf , He* n- nB)]
1052+ Bmax_t = @views [Bmax[end - nB+ 1 : end ]; fill (+ Inf , He* n- nB)]
1053+ else
1054+ Bmin_t = Bmin
1055+ Bmax_t = Bmax
1056+ end
1057+ return Bmin_t, Bmax_t
1058+ end
1059+
10341060" Update the covariance `P̂` with the `KalmanFilter` if `model` is a `LinModel`."
10351061function update_cov! (P̂, estim:: MovingHorizonEstimator , :: LinModel , u, ym, d)
10361062 return update_estimate_kf! (estim, u, ym, d, estim. Â, estim. Ĉ[estim. i_ym, :], P̂)
@@ -1105,27 +1131,27 @@ function predict!(
11051131end
11061132
11071133"""
1108- con_nonlinprog!(g, estim::MovingHorizonEstimator, model::SimModel, X̂)
1134+ con_nonlinprog!(g, estim::MovingHorizonEstimator, model::SimModel, X̂, V̂ )
11091135
11101136Nonlinear constrains for [`MovingHorizonEstimator`](@ref).
11111137"""
1112- function con_nonlinprog! (g, estim:: MovingHorizonEstimator , :: SimModel , X̂)
1138+ function con_nonlinprog! (g, estim:: MovingHorizonEstimator , :: SimModel , X̂, V̂ )
11131139 nX̂con, nX̂ = length (estim. con. X̂min), estim. nx̂ * estim. Nk[]
11141140 nV̂con, nV̂ = length (estim. con. V̂min), estim. nym* estim. Nk[]
11151141 for i in eachindex (g)
11161142 estim. con. i_g[i] || continue
11171143 if i ≤ nX̂con
11181144 j = i
1119- (j ≤ nX̂) && (g[i] = estim. con. X̂min[j] - X̂[j])
1145+ g[i] = j > nX̂ ? 0 : estim. con. X̂min[nX̂con - nX̂ + j] - X̂[j]
11201146 elseif i ≤ 2 nX̂con
11211147 j = i - nX̂con
1122- (j ≤ nX̂) && (g[i] = X̂[j] - estim. con. X̂max[j])
1148+ g[i] = j > nX̂ ? 0 : X̂[j] - estim. con. X̂max[nX̂con - nX̂ + j]
11231149 elseif i ≤ 2 nX̂con + nV̂con
11241150 j = i - 2 nX̂con
1125- (j ≤ nV̂) && (g[i] = estim. con. V̂min[j] - V̂[j])
1151+ g[i] = j > nV̂ ? 0 : estim. con. V̂min[nV̂con - nV̂ + j] - V̂[j]
11261152 else
11271153 j = i - 2 nX̂con - nV̂con
1128- (j ≤ nV̂) && (g[i] = V̂[j] - estim. con. V̂max[j])
1154+ g[i] = j > nV̂ ? 0 : V̂[j] - estim. con. V̂max[nV̂con - nV̂ + j]
11291155 end
11301156 end
11311157 return g
0 commit comments