Skip to content

Commit 3353368

Browse files
committed
added: setmodel! for StateEstimator
1 parent ab6f03f commit 3353368

9 files changed

+82
-20
lines changed

docs/src/public/generic_func.md

+6
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,12 @@ initstate!
3737
setstate!
3838
```
3939

40+
## Set Plant Model
41+
42+
```@docs
43+
setmodel!
44+
```
45+
4046
## Quick Simulation
4147

4248
### Simulate

src/ModelPredictiveControl.jl

+1-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ import OSQP, Ipopt
2323

2424
export SimModel, LinModel, NonLinModel
2525
export DiffSolver, RungeKutta
26-
export setop!, setstate!, updatestate!, evaloutput, linearize
26+
export setop!, setstate!, setmodel!, updatestate!, evaloutput, linearize
2727
export StateEstimator, InternalModel, Luenberger
2828
export SteadyKalmanFilter, KalmanFilter, UnscentedKalmanFilter, ExtendedKalmanFilter
2929
export MovingHorizonEstimator

src/controller/execute.jl

+7
Original file line numberDiff line numberDiff line change
@@ -474,3 +474,10 @@ Call [`updatestate!`](@ref) on `mpc.estim` [`StateEstimator`](@ref).
474474
"""
475475
updatestate!(mpc::PredictiveController, u, ym, d=empty(mpc.estim.x̂)) = updatestate!(mpc.estim,u,ym,d)
476476
updatestate!(::PredictiveController, _ ) = throw(ArgumentError("missing measured outputs ym"))
477+
478+
"""
479+
setstate!(mpc::PredictiveController, x̂)
480+
481+
Set the estimate at `mpc.estim.x̂`.
482+
"""
483+
setstate!(mpc::PredictiveController, x̂) = (setstate!(mpc.estim, x̂); return mpc)

src/estimator/execute.jl

+57
Original file line numberDiff line numberDiff line change
@@ -221,3 +221,60 @@ function validate_args(estim::StateEstimator, u, ym, d)
221221
nym = estim.nym
222222
size(ym) (nym,) && throw(DimensionMismatch("ym size $(size(ym)) ≠ meas. output size ($nym,)"))
223223
end
224+
225+
"""
226+
setstate!(estim::StateEstimator, x̂)
227+
228+
Set `estim.x̂` states to values specified by `x̂`.
229+
"""
230+
function setstate!(estim::StateEstimator, x̂)
231+
size(x̂) == (estim.nx̂,) || error("x̂ size must be $((estim.nx̂,))")
232+
estim.x̂[:] =
233+
return estim
234+
end
235+
236+
"""
237+
setmodel!(estim::StateEstimator, model::LinModel) -> estim
238+
239+
Set `estim.model` state-space matrices and operating points to `model` values.
240+
241+
Not supported by [`Luenberger`](@ref) and [`SteadyKalmanFilter`](@ref) estimators, use the
242+
time-varying [`KalmanFilter`](@ref) instead. The matrix dimensions and sample time must stay
243+
the same. The observability and controllability of the new augmented model is not verified.
244+
"""
245+
function setmodel!(estim::StateEstimator, model::LinModel)
246+
validate_model(estim, model)
247+
estim.model.A .= model.A
248+
estim.model.Bu .= model.Bu
249+
estim.model.C .= model.C
250+
estim.model.Bd .= model.Bd
251+
estim.model.Dd .= model.Dd
252+
estim.model.uop .= model.uop
253+
estim.model.yop .= model.yop
254+
estim.model.dop .= model.dop
255+
setmodel_estimator!(estim, model)
256+
return estim
257+
end
258+
259+
"Validate the dimensions and sample time of `model` against `estim.model`."
260+
function validate_model(estim::StateEstimator, model::LinModel)
261+
model.Ts == estim.model.Ts || throw(ArgumentError("model.Ts must be $(estim.model.Ts) s"))
262+
model.nu == estim.model.nu || throw(ArgumentError("model.nu must be $(estim.model.nu)"))
263+
model.nx == estim.model.nx || throw(ArgumentError("model.nx must be $(estim.model.nx)"))
264+
model.ny == estim.model.ny || throw(ArgumentError("model.ny must be $(estim.model.ny)"))
265+
model.nd == estim.model.nd || throw(ArgumentError("model.nd must be $(estim.model.nd)"))
266+
end
267+
268+
"Update the augmented model matrices of `estim` by default."
269+
function setmodel_estimator!(estim::StateEstimator, model::LinModel)
270+
As, Cs_u, Cs_y = estim.As, estim.Cs_u, estim.Cs_y
271+
Â, B̂u, Ĉ, B̂d, D̂d = augment_model(model, As, Cs_u, Cs_y, verify_obsv=false)
272+
estim. .=
273+
estim.B̂u .= B̂u
274+
estim.Ĉ .=
275+
estim.B̂d .= B̂d
276+
estim.D̂d .= D̂d
277+
estim.Ĉm .= @views Ĉ[estim.i_ym, :]
278+
estim.D̂dm .= @views D̂d[estim.i_ym, :]
279+
return nothing
280+
end

src/estimator/internal_model.jl

+3
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,9 @@ function init_internalmodel(As, Bs, Cs, Ds)
197197
return Âs, B̂s
198198
end
199199

200+
"Do nothing else for `InternalModel` estimator."
201+
setmodel_estimator!(estim::InternalModel, ::LinModel) = nothing
202+
200203
@doc raw"""
201204
update_estimate!(estim::InternalModel, u, ym, d=empty(estim.x̂)) -> x̂d
202205

src/estimator/kalman.jl

+4
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,10 @@ function SteadyKalmanFilter(model::SM, i_ym, nint_u, nint_ym, Q̂, R̂) where {N
166166
return SteadyKalmanFilter{NT, SM}(model, i_ym, nint_u, nint_ym, Q̂, R̂)
167167
end
168168

169+
"Throw an error if `setmodel!` is called on a SteadyKalmanFilter"
170+
function setmodel_estimator!(estim::SteadyKalmanFilter, _ )
171+
error("SteadyKalmanFilter does not support setmodel! (use KalmanFilter instead)")
172+
end
169173

170174

171175
@doc raw"""

src/estimator/luenberger.jl

+4-1
Original file line numberDiff line numberDiff line change
@@ -120,4 +120,7 @@ function update_estimate!(estim::Luenberger, u, ym, d=empty(estim.x̂))
120120
mul!(x̂next, K̂, v̂, 1, 1)
121121
estim.x̂ .= x̂next
122122
return nothing
123-
end
123+
end
124+
125+
"Throw an error if `setmodel!` is called on `Luenberger` observer."
126+
setmodel_estimator!(estim::Luenberger, ::LinModel) = error("Luenberger does not support setmodel!")

src/predictive_control.jl

-7
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,6 @@ include("controller/explicitmpc.jl")
2525
include("controller/linmpc.jl")
2626
include("controller/nonlinmpc.jl")
2727

28-
"""
29-
setstate!(mpc::PredictiveController, x̂)
30-
31-
Set the estimate at `mpc.estim.x̂`.
32-
"""
33-
setstate!(mpc::PredictiveController, x̂) = (setstate!(mpc.estim, x̂); return mpc)
34-
3528
function Base.show(io::IO, mpc::PredictiveController)
3629
Hp, Hc = mpc.Hp, mpc.Hc
3730
= isinf(mpc.C) ? 0 : 1

src/state_estim.jl

-11
Original file line numberDiff line numberDiff line change
@@ -20,17 +20,6 @@ abstract type StateEstimator{NT<:Real} end
2020

2121
const IntVectorOrInt = Union{Int, Vector{Int}}
2222

23-
"""
24-
setstate!(estim::StateEstimator, x̂)
25-
26-
Set `estim.x̂` states to values specified by `x̂`.
27-
"""
28-
function setstate!(estim::StateEstimator, x̂)
29-
size(x̂) == (estim.nx̂,) || error("x̂ size must be $((estim.nx̂,))")
30-
estim.x̂[:] =
31-
return estim
32-
end
33-
3423
function Base.show(io::IO, estim::StateEstimator)
3524
nu, nd = estim.model.nu, estim.model.nd
3625
nx̂, nym, nyu = estim.nx̂, estim.nym, estim.nyu

0 commit comments

Comments
 (0)