Skip to content

Commit e9ec616

Browse files
committed
reduce allocation MHE
1 parent d40c075 commit e9ec616

File tree

3 files changed

+26
-20
lines changed

3 files changed

+26
-20
lines changed

src/estimator/mhe/construct.jl

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -990,22 +990,25 @@ function init_optimization!(
990990
end
991991
He = estim.He
992992
nV̂, nX̂, ng = He*estim.nym, He*estim.nx̂, length(con.i_g)
993+
nx̂, nŷ = estim.nx̂, model.ny
993994
# see init_optimization!(mpc::NonLinMPC, optim) for details on the inspiration
994-
Jfunc, gfunc = let estim=estim, model=model, nZ̃=nZ̃ , nV̂=nV̂, nX̂=nX̂, ng=ng, nx̂=estim.nx̂
995+
Jfunc, gfunc = let estim=estim, model=model, nZ̃=nZ̃ , nV̂=nV̂, nX̂=nX̂, ng=ng, nx̂=nx̂, nŷ=nŷ
995996
Nc = nZ̃ + 3
996997
last_Z̃tup_float, last_Z̃tup_dual = nothing, nothing
997998
V̂_cache::DiffCache{Vector{JNT}, Vector{JNT}} = DiffCache(zeros(JNT, nV̂), Nc)
998999
g_cache::DiffCache{Vector{JNT}, Vector{JNT}} = DiffCache(zeros(JNT, ng), Nc)
9991000
X̂_cache::DiffCache{Vector{JNT}, Vector{JNT}} = DiffCache(zeros(JNT, nX̂), Nc)
10001001
x̄_cache::DiffCache{Vector{JNT}, Vector{JNT}} = DiffCache(zeros(JNT, nx̂), Nc)
1002+
ŷ_cache::DiffCache{Vector{JNT}, Vector{JNT}} = DiffCache(zeros(JNT, nŷ), Nc)
10011003
function Jfunc(Z̃tup::JNT...)
10021004
Z̃1 = Z̃tup[begin]
10031005
= get_tmp(V̂_cache, Z̃1)
10041006
= collect(Z̃tup)
10051007
if Z̃tup !== last_Z̃tup_float
10061008
g = get_tmp(g_cache, Z̃1)
10071009
= get_tmp(X̂_cache, Z̃1)
1008-
V̂, X̂ = predict!(V̂, X̂, estim, model, Z̃)
1010+
= get_tmp(ŷ_cache, Z̃1)
1011+
V̂, X̂ = predict!(V̂, X̂, ŷ, estim, model, Z̃)
10091012
g = con_nonlinprog!(g, estim, model, X̂, V̂, Z̃)
10101013
last_Z̃tup_float = Z̃tup
10111014
end
@@ -1019,7 +1022,8 @@ function init_optimization!(
10191022
if Z̃tup !== last_Z̃tup_dual
10201023
g = get_tmp(g_cache, Z̃1)
10211024
= get_tmp(X̂_cache, Z̃1)
1022-
V̂, X̂ = predict!(V̂, X̂, estim, model, Z̃)
1025+
= get_tmp(ŷ_cache, Z̃1)
1026+
V̂, X̂ = predict!(V̂, X̂, ŷ, estim, model, Z̃)
10231027
g = con_nonlinprog!(g, estim, model, X̂, V̂, Z̃)
10241028
last_Z̃tup_dual = Z̃tup
10251029
end
@@ -1030,10 +1034,11 @@ function init_optimization!(
10301034
Z̃1 = Z̃tup[begin]
10311035
g = get_tmp(g_cache, Z̃1)
10321036
if Z̃tup !== last_Z̃tup_float
1037+
= collect(Z̃tup)
10331038
= get_tmp(V̂_cache, Z̃1)
10341039
= get_tmp(X̂_cache, Z̃1)
1035-
= collect(Z̃tup)
1036-
V̂, X̂ = predict!(V̂, X̂, estim, model, Z̃)
1040+
= get_tmp(ŷ_cache, Z̃1)
1041+
V̂, X̂ = predict!(V̂, X̂, ŷ, estim, model, Z̃)
10371042
g = con_nonlinprog!(g, estim, model, X̂, V̂, Z̃)
10381043
last_Z̃tup_float = Z̃tup
10391044
end
@@ -1043,10 +1048,11 @@ function init_optimization!(
10431048
Z̃1 = Z̃tup[begin]
10441049
g = get_tmp(g_cache, Z̃1)
10451050
if Z̃tup !== last_Z̃tup_dual
1051+
= collect(Z̃tup)
10461052
= get_tmp(V̂_cache, Z̃1)
10471053
= get_tmp(X̂_cache, Z̃1)
1048-
= collect(Z̃tup)
1049-
V̂, X̂ = predict!(V̂, X̂, estim, model, Z̃)
1054+
= get_tmp(ŷ_cache, Z̃1)
1055+
V̂, X̂ = predict!(V̂, X̂, ŷ, estim, model, Z̃)
10501056
g = con_nonlinprog!(g, estim, model, X̂, V̂, Z̃)
10511057
last_Z̃tup_dual = Z̃tup
10521058
end

src/estimator/mhe/execute.jl

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -34,15 +34,16 @@ function update_estimate!(estim::MovingHorizonEstimator{NT}, u, ym, d) where NT<
3434
add_data_windows!(estim::MovingHorizonEstimator, u, d, ym)
3535
initpred!(estim, model)
3636
linconstraint!(estim, model)
37-
nx̂, nym, nŵ, Nk = estim.nx̂, estim.nym, estim.nx̂, estim.Nk[]
37+
nŷ, nx̂, nym, nŵ, Nk = model.ny, estim.nx̂, estim.nym, estim.nx̂, estim.Nk[]
3838
nx̃ = !isinf(estim.C) + nx̂
3939
Z̃var::Vector{VariableRef} = optim[:Z̃var]
4040
= Vector{NT}(undef, nym*Nk)
4141
= Vector{NT}(undef, nx̂*Nk)
42+
= Vector{NT}(undef, nŷ)
4243
= Vector{NT}(undef, nx̂)
4344
ϵ0 = isinf(estim.C) ? empty(estim.Z̃) : estim.Z̃[begin]
4445
Z̃0 = [ϵ0; estim.x̂arr_old; estim.Ŵ]
45-
V̂, X̂ = predict!(V̂, X̂, estim, model, Z̃0)
46+
V̂, X̂ = predict!(V̂, X̂, ŷ, estim, model, Z̃0)
4647
J0 = obj_nonlinprog!(x̄, estim, model, V̂, Z̃0)
4748
# initial Z̃0 with Ŵ=0 if objective or constraint function not finite :
4849
isfinite(J0) || (Z̃0 = [ϵ0; estim.x̂arr_old; zeros(NT, nŵ*estim.He)])
@@ -75,7 +76,7 @@ function update_estimate!(estim::MovingHorizonEstimator{NT}, u, ym, d) where NT<
7576
estim.Z̃ .= iserror(optim) ? Z̃last : Z̃curr
7677
# --------- update estimate -----------------------
7778
estim.Ŵ[1:nŵ*Nk] .= @views estim.Z̃[nx̃+1:nx̃+nŵ*Nk] # update Ŵ with optimum for warm-start
78-
V̂, X̂ = predict!(V̂, X̂, estim, model, estim.Z̃)
79+
V̂, X̂ = predict!(V̂, X̂, ŷ, estim, model, estim.Z̃)
7980
x̂ .= X̂[end-nx̂+1:end]
8081
if Nk == estim.He
8182
uarr, ymarr, darr = estim.U[1:model.nu], estim.Ym[1:nym], estim.D[1:model.nd]
@@ -129,7 +130,8 @@ function getinfo(estim::MovingHorizonEstimator{NT}) where NT<:Real
129130
MyTypes = Union{JuMP._SolutionSummary, Hermitian{NT, Matrix{NT}}, Vector{NT}, NT}
130131
info = Dict{Symbol, MyTypes}()
131132
V̂, X̂ = similar(estim.Ym[1:nym*Nk]), similar(estim.X̂[1:nx̂*Nk])
132-
V̂, X̂ = predict!(V̂, X̂, estim, model, estim.Z̃)
133+
= similar(model.yop)
134+
V̂, X̂ = predict!(V̂, X̂, ŷ, estim, model, estim.Z̃)
133135
x̂arr = estim.Z̃[nx̃-nx̂+1:nx̃]
134136
= estim.x̂arr_old - x̂arr
135137
= [x̂arr; X̂]
@@ -372,16 +374,16 @@ function obj_nonlinprog!(
372374
end
373375

374376
"""
375-
predict!(V̂, X̂, estim::MovingHorizonEstimator, model::LinModel, Z̃) -> V̂, X̂
377+
predict!(V̂, X̂, ŷ, estim::MovingHorizonEstimator, model::LinModel, Z̃) -> V̂, X̂
376378
377379
Compute the `V̂` vector and `X̂` vectors for the `MovingHorizonEstimator` and `LinModel`.
378380
379-
The method mutates `V̂` and `X̂` vector arguments. The vector `V̂` is the estimated sensor
381+
The function mutates `V̂`, `X̂` and ŷ vector arguments. The vector `V̂` is the estimated sensor
380382
noises `V̂` from ``k-N_k+1`` to ``k``. The `X̂` vector is estimated states from ``k-N_k+2`` to
381383
``k+1``.
382384
"""
383385
function predict!(
384-
V̂, X̂, estim::MovingHorizonEstimator, ::LinModel, Z̃::Vector{T}
386+
V̂, X̂, _ , estim::MovingHorizonEstimator, ::LinModel, Z̃::Vector{T}
385387
) where {T<:Real}
386388
Nk, nϵ = estim.Nk[], !isinf(estim.C)
387389
nX̂, nŴ, nYm = estim.nx̂*Nk, estim.nx̂*Nk, estim.nym*Nk
@@ -393,13 +395,11 @@ end
393395

394396
"Compute the two vectors when `model` is not a `LinModel`."
395397
function predict!(
396-
V̂, X̂, estim::MovingHorizonEstimator, model::SimModel, Z̃::Vector{T}
398+
V̂, X̂, ŷ, estim::MovingHorizonEstimator, model::SimModel, Z̃::Vector{T}
397399
) where {T<:Real}
398400
Nk = estim.Nk[]
399401
nu, nd, ny, nx̂, nŵ, nym = model.nu, model.nd, model.ny, estim.nx̂, estim.nx̂, estim.nym
400402
nx̃ = !isinf(estim.C) + nx̂
401-
# TODO: avoid these two allocations if possible:
402-
ŷ, x̂next = Vector{T}(undef, ny), Vector{T}(undef, nx̂)
403403
= @views Z̃[nx̃-nx̂+1:nx̃]
404404
for j=1:Nk
405405
u = @views estim.U[ (1 + nu * (j-1)):(nu*j)]
@@ -409,10 +409,10 @@ function predict!(
409409
ĥ!(ŷ, estim, model, x̂, d)
410410
ŷm = @views ŷ[estim.i_ym]
411411
V̂[(1 + nym*(j-1)):(nym*j)] .= ym .- ŷm
412+
x̂next = @views X̂[(1 + nx̂ *(j-1)):(nx̂ *j)]
412413
f̂!(x̂next, estim, model, x̂, u, d)
413414
x̂next .+=
414-
X̂[(1 + nx̂ *(j-1)):(nx̂ *j)] = x̂next
415-
= @views X̂[(1 + nx̂*(j-1)):(nx̂*j)]
415+
= x̂next
416416
end
417417
return V̂, X̂
418418
end

src/model/nonlinmodel.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ end
2626
NonLinModel{NT}(f::Function, h::Function, Ts, nu, nx, ny, nd=0)
2727
NonLinModel{NT}(f!::Function, h!::Function, Ts, nu, nx, ny, nd=0)
2828
29-
Construct a nonlinear model from discrete-time state-space functions `f` and `h`.
29+
Construct a nonlinear model from discrete-time state-space functions `f`/`f!` and `h`/`h!`.
3030
3131
The state update ``\mathbf{f}`` and output ``\mathbf{h}`` functions are defined as :
3232
```math

0 commit comments

Comments
 (0)