Skip to content

Commit 2511b08

Browse files
committed
Cleaner InternalModel implementation by storing ŷs only
1 parent aa9b8dd commit 2511b08

File tree

2 files changed

+29
-35
lines changed

2 files changed

+29
-35
lines changed

src/controller/execute.jl

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -240,14 +240,9 @@ end
240240
Init `mpc.F` vector with ``\mathbf{F = Ŷ_s}`` when `estim` is an [`InternalModel`](@ref).
241241
"""
242242
function predictstoch!(mpc::PredictiveController{NT}, estim::InternalModel) where {NT<:Real}
243-
F, ny = mpc.F, estim.model.ny
244-
ŷ0d = similar(estim.model.yop)
245-
h!(ŷ0d, estim.model, estim.x̂d, estim.d0)
246-
ŷs = zeros(NT, ny)
247-
ŷs[estim.i_ym] .= @views estim.y0m .- ŷ0d[estim.i_ym] # ŷs=0 for unmeasured outputs
248-
Ŷs = F
243+
Ŷs = mpc.F
249244
mul!(Ŷs, mpc.Ks, estim.x̂s)
250-
mul!(Ŷs, mpc.Ps, ŷs, 1, 1)
245+
mul!(Ŷs, mpc.Ps, estim.ŷs, 1, 1)
251246
return nothing
252247
end
253248
"Separate stochastic predictions are not needed if `estim` is not [`InternalModel`](@ref)."

src/estimator/internal_model.jl

Lines changed: 27 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,7 @@ struct InternalModel{NT<:Real, SM<:SimModel} <: StateEstimator{NT}
66
x̂0 ::Vector{NT}
77
x̂d::Vector{NT}
88
x̂s::Vector{NT}
9-
y0m::Vector{NT}
10-
d0 ::Vector{NT}
9+
ŷs::Vector{NT}
1110
i_ym::Vector{Int}
1211
nx̂::Int
1312
nym::Int
@@ -42,14 +41,13 @@ struct InternalModel{NT<:Real, SM<:SimModel} <: StateEstimator{NT}
4241
# x̂0 and x̂d are same object (updating x̂d will update x̂0):
4342
x̂d = x̂0 = zeros(NT, model.nx)
4443
x̂s = zeros(NT, nxs)
45-
y0m, d0 = zeros(NT, nym), zeros(NT, model.nd)
44+
ŷs = zeros(NT, ny)
4645
direct = true # InternalModel always uses direct transmission from ym
4746
corrected = [false]
4847
buffer = StateEstimatorBuffer{NT}(nu, nx̂, nym, ny, nd)
4948
return new{NT, SM}(
5049
model,
51-
lastu0, x̂op, f̂op, x̂0, x̂d, x̂s,
52-
y0m, d0,
50+
lastu0, x̂op, f̂op, x̂0, x̂d, x̂s, ŷs,
5351
i_ym, nx̂, nym, nyu, nxs,
5452
As, Bs, Cs, Ds,
5553
Â, B̂u, Ĉ, B̂d, D̂d,
@@ -238,16 +236,20 @@ end
238236
"""
239237
correct_estimate!(estim::InternalModel, y0m, d0)
240238
241-
Save current meas. output `y0m` and disturbance `d0` inside `estim` for stoch. predictions.
239+
Compute the current stochastic output estimation `ŷs` for [`InternalModel`](@ref).
242240
"""
243241
function correct_estimate!(estim::InternalModel, y0m, d0)
244-
estim.y0m .= y0m
245-
estim.d0 .= d0
242+
ŷ0d = estim.buffer.
243+
h!(ŷ0d, estim.model, estim.x̂d, d0)
244+
ŷs = estim.ŷs
245+
ŷs[estim.i_ym] .= @views y0m .- ŷ0d[estim.i_ym]
246+
# ŷs=0 for unmeasured outputs :
247+
map(i -> ŷs[i] = (i in estim.i_ym) ? ŷs[i] : 0, eachindex(ŷs))
246248
return nothing
247249
end
248250

249251
@doc raw"""
250-
update_estimate!(estim::InternalModel, y0m, d0, u0)
252+
update_estimate!(estim::InternalModel, _ , d0, u0)
251253
252254
Update `estim.x̂0`/`x̂d`/`x̂s` with current inputs `u0`, measured outputs `y0m` and dist. `d0`.
253255
@@ -261,19 +263,14 @@ The [`InternalModel`](@ref) updates the deterministic `x̂d` and stochastic `x̂
261263
This estimator does not augment the state vector, thus ``\mathbf{x̂ = x̂_d}``. See
262264
[`init_internalmodel`](@ref) for details.
263265
"""
264-
function update_estimate!(estim::InternalModel, y0m, d0, u0)
266+
function update_estimate!(estim::InternalModel, _ , d0, u0)
265267
model = estim.model
266-
x̂d, x̂s = estim.x̂d, estim.x̂s
268+
x̂d, x̂s, ŷs = estim.x̂d, estim.x̂s, estim.ŷs
267269
# -------------- deterministic model ---------------------
268-
ŷ0d, x̂dnext = estim.buffer.ŷ, estim.buffer.
269-
h!(ŷ0d, model, x̂d, d0)
270+
x̂dnext = estim.buffer.
270271
f!(x̂dnext, model, x̂d, u0, d0)
271272
x̂d .= x̂dnext # this also updates estim.x̂0 (they are the same object)
272273
# --------------- stochastic model -----------------------
273-
ŷs = ŷ0d
274-
ŷs[estim.i_ym] .= @views y0m .- ŷ0d[estim.i_ym]
275-
# ŷs=0 for unmeasured outputs :
276-
map(i -> ŷs[i] = (i in estim.i_ym) ? ŷs[i] : 0, eachindex(ŷs))
277274
x̂snext = similar(x̂s) # TODO: remove this allocation with a new buffer?
278275
mul!(x̂snext, estim.Âs, x̂s)
279276
mul!(x̂snext, estim.B̂s, ŷs, 1, 1)
@@ -319,21 +316,23 @@ function init_estimate!(estim::InternalModel, model::LinModel{NT}, y0m, d0, u0)
319316
end
320317

321318
@doc raw"""
322-
evalŷ(estim::InternalModel, _ ) -> ŷ
319+
evalŷ(estim::InternalModel, d) -> ŷ
323320
324321
Get [`InternalModel`](@ref) estimated output `ŷ`.
325322
326-
[`InternalModel`](@ref) estimator needs current measured outputs ``\mathbf{y^m}(k)`` to
327-
estimate its outputs ``\mathbf{ŷ}(k)``, since the strategy imposes that
328-
``\mathbf{ŷ^m}(k) = \mathbf{y^m}(k)`` is always true. The method [`preparestate!`](@ref)
329-
store the current measured outputs and disturbances inside `estim` object, it should be thus
330-
called before `evalŷ`.
323+
[`InternalModel`](@ref) estimator needs current stochastic output ``\mathbf{ŷ_s}(k)`` to
324+
estimate its outputs ``\mathbf{ŷ}(k)``. The method [`preparestate!`](@ref) store this value
325+
inside `estim` object, it should be thus called before `evalŷ`.
331326
"""
332-
function evalŷ(estim::InternalModel, _ )
333-
= estim.buffer.
334-
h!(ŷ, estim.model, estim.x̂d, estim.d0)
335-
.+= estim.model.yop
336-
ŷ[estim.i_ym] = @views estim.y0m .+ estim.model.yop[estim.i_ym]
327+
function evalŷ(estim::InternalModel, d)
328+
if !estim.corrected[]
329+
error("InternalModel: preparestate! must be called before evalŷ")
330+
end
331+
ŷ0d, d0 = estim.buffer.ŷ, estim.buffer.d
332+
d0 .= d .- estim.model.dop
333+
h!(ŷ0d, estim.model, estim.x̂d, d0)
334+
= ŷ0d
335+
.+= estim.model.yop .+ estim.ŷs
337336
return
338337
end
339338

0 commit comments

Comments
 (0)