Skip to content

Commit 62006e4

Browse files
committed
weird bug: the simulations in my own test script are slightly different, to investigate
1 parent 9f1612e commit 62006e4

File tree

7 files changed

+61
-19
lines changed

7 files changed

+61
-19
lines changed

src/estimator/execute.jl

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,13 @@ Also store current inputs without operating points `u0` in `estim.lastu0`. This
77
used for [`PredictiveController`](@ref) computations.
88
"""
99
function remove_op!(estim::StateEstimator, u, ym, d)
10-
u0 = u - estim.model.uop
11-
ym0 = ym - estim.model.yop[estim.i_ym]
12-
d0 = d - estim.model.dop
13-
estim.lastu0[:] = u0
14-
return u0, ym0, d0
10+
u0, d0 = estim.model.buffer.u, estim.model.buffer.d
11+
y0m = estim.buffer.ym
12+
u0 .= u .- estim.model.uop
13+
y0m .= @views ym .- estim.model.yop[estim.i_ym]
14+
d0 .= d .- estim.model.dop
15+
estim.lastu0 .= u0
16+
return u0, y0m, d0
1517
end
1618

1719
@doc raw"""
@@ -150,6 +152,7 @@ measured outputs ``\mathbf{y^m}``.
150152
function init_estimate!(estim::StateEstimator, ::LinModel, u0, ym0, d0)
151153
Â, B̂u, Ĉ, B̂d, D̂d = estim.Â, estim.B̂u, estim.Ĉ, estim.B̂d, estim.D̂d
152154
Ĉm, D̂dm = @views Ĉ[estim.i_ym, :], D̂d[estim.i_ym, :] # measured outputs ym only
155+
# TODO: use estim.buffer.x̂ to reduce allocations
153156
estim.x̂0 .= [I - Â; Ĉm]\[B̂u*u0 + B̂d*d0 + estim.f̂op - estim.x̂op; ym0 - D̂dm*d0]
154157
return nothing
155158
end
@@ -178,11 +181,11 @@ julia> ŷ = evaloutput(kf)
178181
"""
179182
function evaloutput(estim::StateEstimator{NT}, d=estim.model.buffer.empty) where NT <: Real
180183
validate_args(estim.model, d)
181-
ŷ0 = Vector{NT}(undef, estim.model.ny)
182-
d0 = d - estim.model.dop
184+
ŷ0, d0 = estim.model.buffer.y, estim.model.buffer.d
185+
d0 .= d .- estim.model.dop
183186
ĥ!(ŷ0, estim, estim.model, estim.x̂0, d0)
184-
= ŷ0
185-
.+= estim.model.yop
187+
= estim.model.buffer.y
188+
ŷ .= ŷ0 .+ estim.model.yop
186189
return
187190
end
188191

@@ -207,7 +210,7 @@ julia> x̂ = updatestate!(kf, [1], [0]) # x̂[2] is the integrator state (nint_y
207210
0.0
208211
```
209212
"""
210-
function updatestate!(estim::StateEstimator, u, ym, d=[])
213+
function updatestate!(estim::StateEstimator, u, ym, d=estim.model.buffer.empty)
211214
validate_args(estim, u, ym, d)
212215
u0, ym0, d0 = remove_op!(estim, u, ym, d)
213216
x̂0next = update_estimate!(estim, u0, ym0, d0)

src/estimator/internal_model.jl

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ struct InternalModel{NT<:Real, SM<:SimModel} <: StateEstimator{NT}
2222
D̂d::Matrix{NT}
2323
Âs::Matrix{NT}
2424
B̂s::Matrix{NT}
25+
buffer::StateEstimatorBuffer{NT}
2526
function InternalModel{NT, SM}(
2627
model::SM, i_ym, Asm, Bsm, Csm, Dsm
2728
) where {NT<:Real, SM<:SimModel}
@@ -36,13 +37,15 @@ struct InternalModel{NT<:Real, SM<:SimModel} <: StateEstimator{NT}
3637
# x̂0 and x̂d are same object (updating x̂d will update x̂0):
3738
x̂d = x̂0 = zeros(NT, model.nx)
3839
x̂s = zeros(NT, nxs)
40+
buffer = StateEstimatorBuffer{NT}(nx̂, nym)
3941
return new{NT, SM}(
4042
model,
4143
lastu0, x̂op, f̂op, x̂0, x̂d, x̂s,
4244
i_ym, nx̂, nym, nyu, nxs,
4345
As, Bs, Cs, Ds,
4446
Â, B̂u, Ĉ, B̂d, D̂d,
45-
Âs, B̂s
47+
Âs, B̂s,
48+
buffer
4649
)
4750
end
4851
end

src/estimator/kalman.jl

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ struct SteadyKalmanFilter{NT<:Real, SM<:LinModel} <: StateEstimator{NT}
2222
::Hermitian{NT, Matrix{NT}}
2323
::Hermitian{NT, Matrix{NT}}
2424
::Matrix{NT}
25+
buffer::StateEstimatorBuffer{NT}
2526
function SteadyKalmanFilter{NT, SM}(
2627
model::SM, i_ym, nint_u, nint_ym, Q̂, R̂
2728
) where {NT<:Real, SM<:LinModel}
@@ -48,14 +49,16 @@ struct SteadyKalmanFilter{NT<:Real, SM<:LinModel} <: StateEstimator{NT}
4849
lastu0 = zeros(NT, model.nu)
4950
x̂0 = [zeros(NT, model.nx); zeros(NT, nxs)]
5051
Q̂, R̂ = Hermitian(Q̂, :L), Hermitian(R̂, :L)
52+
buffer = StateEstimatorBuffer{NT}(nx̂, nym)
5153
return new{NT, SM}(
5254
model,
5355
lastu0, x̂op, f̂op, x̂0,
5456
i_ym, nx̂, nym, nyu, nxs,
5557
As, Cs_u, Cs_y, nint_u, nint_ym,
5658
Â, B̂u, Ĉ, B̂d, D̂d,
5759
Q̂, R̂,
58-
60+
K̂,
61+
buffer
5962
)
6063
end
6164
end
@@ -234,6 +237,7 @@ struct KalmanFilter{NT<:Real, SM<:LinModel} <: StateEstimator{NT}
234237
::Hermitian{NT, Matrix{NT}}
235238
::Matrix{NT}
236239
::Matrix{NT}
240+
buffer::StateEstimatorBuffer{NT}
237241
function KalmanFilter{NT, SM}(
238242
model::SM, i_ym, nint_u, nint_ym, P̂_0, Q̂, R̂
239243
) where {NT<:Real, SM<:LinModel}
@@ -249,14 +253,16 @@ struct KalmanFilter{NT<:Real, SM<:LinModel} <: StateEstimator{NT}
249253
P̂_0 = Hermitian(P̂_0, :L)
250254
= copy(P̂_0)
251255
K̂, M̂ = zeros(NT, nx̂, nym), zeros(NT, nx̂, nym)
256+
buffer = StateEstimatorBuffer{NT}(nx̂, nym)
252257
return new{NT, SM}(
253258
model,
254259
lastu0, x̂op, f̂op, x̂0, P̂,
255260
i_ym, nx̂, nym, nyu, nxs,
256261
As, Cs_u, Cs_y, nint_u, nint_ym,
257262
Â, B̂u, Ĉ, B̂d, D̂d,
258263
P̂_0, Q̂, R̂,
259-
K̂, M̂
264+
K̂, M̂,
265+
buffer
260266
)
261267
end
262268
end
@@ -402,6 +408,7 @@ struct UnscentedKalmanFilter{NT<:Real, SM<:SimModel} <: StateEstimator{NT}
402408
γ::NT
403409
::Vector{NT}
404410
::Diagonal{NT, Vector{NT}}
411+
buffer::StateEstimatorBuffer{NT}
405412
function UnscentedKalmanFilter{NT, SM}(
406413
model::SM, i_ym, nint_u, nint_ym, P̂_0, Q̂, R̂, α, β, κ
407414
) where {NT<:Real, SM<:SimModel{NT}}
@@ -421,6 +428,7 @@ struct UnscentedKalmanFilter{NT<:Real, SM<:SimModel} <: StateEstimator{NT}
421428
= Hermitian(zeros(NT, nym, nym), :L)
422429
X̂0, Ŷ0m = zeros(NT, nx̂, nσ), zeros(NT, nym, nσ)
423430
sqrtP̂ = LowerTriangular(zeros(NT, nx̂, nx̂))
431+
buffer = StateEstimatorBuffer{NT}(nx̂, nym)
424432
return new{NT, SM}(
425433
model,
426434
lastu0, x̂op, f̂op, x̂0, P̂,
@@ -429,7 +437,8 @@ struct UnscentedKalmanFilter{NT<:Real, SM<:SimModel} <: StateEstimator{NT}
429437
Â, B̂u, Ĉ, B̂d, D̂d,
430438
P̂_0, Q̂, R̂,
431439
K̂, M̂, X̂0, Ŷ0m, sqrtP̂,
432-
nσ, γ, m̂, Ŝ
440+
nσ, γ, m̂, Ŝ,
441+
buffer
433442
)
434443
end
435444
end
@@ -698,6 +707,7 @@ struct ExtendedKalmanFilter{NT<:Real, SM<:SimModel} <: StateEstimator{NT}
698707
::Matrix{NT}
699708
F̂_û::Matrix{NT}
700709
::Matrix{NT}
710+
buffer::StateEstimatorBuffer{NT}
701711
function ExtendedKalmanFilter{NT, SM}(
702712
model::SM, i_ym, nint_u, nint_ym, P̂_0, Q̂, R̂
703713
) where {NT<:Real, SM<:SimModel}
@@ -715,6 +725,7 @@ struct ExtendedKalmanFilter{NT<:Real, SM<:SimModel} <: StateEstimator{NT}
715725
= copy(P̂_0)
716726
K̂, M̂ = zeros(NT, nx̂, nym), zeros(NT, nx̂, nym)
717727
F̂_û, Ĥ = zeros(NT, nx̂+model.nu, nx̂), zeros(NT, model.ny, nx̂)
728+
buffer = StateEstimatorBuffer{NT}(nx̂, nym)
718729
return new{NT, SM}(
719730
model,
720731
lastu0, x̂op, f̂op, x̂0, P̂,
@@ -723,7 +734,8 @@ struct ExtendedKalmanFilter{NT<:Real, SM<:SimModel} <: StateEstimator{NT}
723734
Â, B̂u, Ĉ, B̂d, D̂d,
724735
P̂_0, Q̂, R̂,
725736
K̂, M̂,
726-
F̂_û, Ĥ
737+
F̂_û, Ĥ,
738+
buffer
727739
)
728740
end
729741
end

src/estimator/luenberger.jl

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ struct Luenberger{NT<:Real, SM<:LinModel} <: StateEstimator{NT}
2020
B̂d ::Matrix{NT}
2121
D̂d ::Matrix{NT}
2222
::Matrix{NT}
23+
buffer::StateEstimatorBuffer{NT}
2324
function Luenberger{NT, SM}(
2425
model, i_ym, nint_u, nint_ym, poles
2526
) where {NT<:Real, SM<:LinModel}
@@ -36,13 +37,15 @@ struct Luenberger{NT<:Real, SM<:LinModel} <: StateEstimator{NT}
3637
end
3738
lastu0 = zeros(NT, model.nu)
3839
x̂0 = [zeros(NT, model.nx); zeros(NT, nxs)]
40+
buffer = StateEstimatorBuffer{NT}(nx̂, nym)
3941
return new{NT, SM}(
4042
model,
4143
lastu0, x̂op, f̂op, x̂0,
4244
i_ym, nx̂, nym, nyu, nxs,
4345
As, Cs_u, Cs_y, nint_u, nint_ym,
4446
Â, B̂u, Ĉ, B̂d, D̂d,
45-
47+
K̂,
48+
buffer
4649
)
4750
end
4851
end

src/estimator/mhe/construct.jl

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@ struct MovingHorizonEstimator{
102102
x̂0arr_old::Vector{NT}
103103
P̂arr_old ::Hermitian{NT, Matrix{NT}}
104104
Nk::Vector{Int}
105+
buffer::StateEstimatorBuffer{NT}
105106
function MovingHorizonEstimator{NT, SM, JM, CE}(
106107
model::SM, He, i_ym, nint_u, nint_ym, P̂_0, Q̂, R̂, Cwt, optim::JM, covestim::CE
107108
) where {NT<:Real, SM<:SimModel{NT}, JM<:JuMP.GenericModel, CE<:StateEstimator{NT}}
@@ -140,6 +141,7 @@ struct MovingHorizonEstimator{
140141
x̂0arr_old = zeros(NT, nx̂)
141142
P̂arr_old = copy(P̂_0)
142143
Nk = [0]
144+
buffer = StateEstimatorBuffer{NT}(nx̂, nym)
143145
estim = new{NT, SM, JM, CE}(
144146
model, optim, con, covestim,
145147
Z̃, lastu0, x̂op, f̂op, x̂0,
@@ -151,7 +153,8 @@ struct MovingHorizonEstimator{
151153
H̃, q̃, p,
152154
P̂_0, Q̂, R̂, invP̄, invQ̂_He, invR̂_He, Cwt,
153155
X̂op, X̂0, Y0m, U0, D0, Ŵ,
154-
x̂0arr_old, P̂arr_old, Nk
156+
x̂0arr_old, P̂arr_old, Nk,
157+
buffer
155158
)
156159
init_optimization!(estim, model, optim)
157160
return estim

src/sim_model.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,13 @@ struct SimModelBuffer{NT<:Real}
2929
end
3030

3131
@doc raw"""
32-
SimModelBuffer(nu, nx, ny, nd) -> SimModelBuffer{NT}
32+
SimModelBuffer(nu::Int, nx::Int, ny::Int, nd::Int) -> SimModelBuffer{NT}
3333
3434
Create a buffer for `SimModel` objects for inputs, states, outputs, and disturbances.
3535
3636
The buffer is used to store intermediate results during simulation without allocating.
3737
"""
38-
function SimModelBuffer{NT}(nu, nx, ny, nd) where NT <: Real
38+
function SimModelBuffer{NT}(nu::Int, nx::Int, ny::Int, nd::Int) where NT <: Real
3939
u = Vector{NT}(undef, nu)
4040
x = Vector{NT}(undef, nx)
4141
y = Vector{NT}(undef, ny)

src/state_estim.jl

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,24 @@ julia> ŷ = kf()
1818
"""
1919
abstract type StateEstimator{NT<:Real} end
2020

21+
struct StateEstimatorBuffer{NT<:Real}
22+
::Vector{NT}
23+
ym::Vector{NT}
24+
end
25+
26+
@doc raw"""
27+
StateEstimatorBuffer(nx̂::Int, nym::Int) -> StateEstimatorBuffer{NT}
28+
29+
Create a buffer for `StateEstimator` objects for estimated states and measured outputs.
30+
31+
The buffer is used to store intermediate results during simulation without allocating.
32+
"""
33+
function StateEstimatorBuffer{NT}(nx̂::Int, nym::Int) where NT <: Real
34+
= Vector{NT}(undef, nx̂)
35+
ym = Vector{NT}(undef, nym)
36+
return StateEstimatorBuffer{NT}(x̂, ym)
37+
end
38+
2139
const IntVectorOrInt = Union{Int, Vector{Int}}
2240

2341
function Base.show(io::IO, estim::StateEstimator)

0 commit comments

Comments
 (0)