Skip to content

Commit 48c201f

Browse files
committed
added: SimModelBuffer object to reduce the allocations
default `d` argument is now `model.buffer.empty` (restore the error handling when no d is provided)
1 parent 3c225a0 commit 48c201f

File tree

7 files changed

+56
-30
lines changed

7 files changed

+56
-30
lines changed

src/controller/execute.jl

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,15 @@
11
@doc raw"""
2-
initstate!(mpc::PredictiveController, u, ym, d=mpc.estim.model.dop) -> x̂
2+
initstate!(mpc::PredictiveController, u, ym, d=[]) -> x̂
33
44
Init the states of `mpc.estim` [`StateEstimator`](@ref) and warm start `mpc.ΔŨ` at zero.
55
"""
6-
function initstate!(mpc::PredictiveController, u, ym, d=mpc.estim.model.dop)
6+
function initstate!(mpc::PredictiveController, u, ym, d=mpc.estim.model.buffer.empty)
77
mpc.ΔŨ .= 0
88
return initstate!(mpc.estim, u, ym, d)
99
end
1010

1111
@doc raw"""
12-
moveinput!(
13-
mpc::PredictiveController, ry=mpc.estim.model.yop, d=mpc.estim.model.dop;
14-
<keyword arguments>
15-
) -> u
12+
moveinput!(mpc::PredictiveController, ry=mpc.estim.model.yop, d=[]; <keyword args>) -> u
1613
1714
Compute the optimal manipulated input value `u` for the current control period.
1815
@@ -32,7 +29,7 @@ See also [`LinMPC`](@ref), [`ExplicitMPC`](@ref), [`NonLinMPC`](@ref).
3229
3330
- `mpc::PredictiveController` : solve optimization problem of `mpc`.
3431
- `ry=mpc.estim.model.yop` : current output setpoints ``\mathbf{r_y}(k)``.
35-
- `d=mpc.estim.model.dop` : current measured disturbances ``\mathbf{d}(k)``.
32+
- `d=[]` : current measured disturbances ``\mathbf{d}(k)``.
3633
- `D̂=repeat(d, mpc.Hp)` or *`Dhat`* : predicted measured disturbances ``\mathbf{D̂}``, constant
3734
in the future by default or ``\mathbf{d̂}(k+j)=\mathbf{d}(k)`` for ``j=1`` to ``H_p``.
3835
- `R̂y=repeat(ry, mpc.Hp)` or *`Rhaty`* : predicted output setpoints ``\mathbf{R̂_y}``, constant
@@ -54,7 +51,7 @@ julia> ry = [5]; u = moveinput!(mpc, ry); round.(u, digits=3)
5451
function moveinput!(
5552
mpc::PredictiveController,
5653
ry::Vector = mpc.estim.model.yop,
57-
d ::Vector = mpc.estim.model.dop;
54+
d ::Vector = mpc.estim.model.buffer.empty;
5855
Dhat ::Vector = repeat(d, mpc.Hp),
5956
Rhaty::Vector = repeat(ry, mpc.Hp),
6057
Rhatu::Vector = mpc.Uop,
@@ -508,11 +505,11 @@ end
508505
set_objective_linear_coef!(::PredictiveController, _ ) = nothing
509506

510507
"""
511-
updatestate!(mpc::PredictiveController, u, ym, d=mpc.estim.model.dop) -> x̂
508+
updatestate!(mpc::PredictiveController, u, ym, d=[]) -> x̂
512509
513510
Call [`updatestate!`](@ref) on `mpc.estim` [`StateEstimator`](@ref).
514511
"""
515-
function updatestate!(mpc::PredictiveController, u, ym, d=mpc.estim.model.dop)
512+
function updatestate!(mpc::PredictiveController, u, ym, d=mpc.estim.model.buffer.empty)
516513
return updatestate!(mpc.estim, u, ym, d)
517514
end
518515
updatestate!(::PredictiveController, _ ) = throw(ArgumentError("missing measured outputs ym"))

src/estimator/execute.jl

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ end
7979

8080

8181
@doc raw"""
82-
initstate!(estim::StateEstimator, u, ym, d=estim.model.dop) -> x̂
82+
initstate!(estim::StateEstimator, u, ym, d=[]) -> x̂
8383
8484
Init `estim.x̂0` states from current inputs `u`, measured outputs `ym` and disturbances `d`.
8585
@@ -111,7 +111,7 @@ julia> evaloutput(estim) ≈ y
111111
true
112112
```
113113
"""
114-
function initstate!(estim::StateEstimator, u, ym, d=estim.model.dop)
114+
function initstate!(estim::StateEstimator, u, ym, d=estim.model.buffer.empty)
115115
# --- validate arguments ---
116116
validate_args(estim, u, ym, d)
117117
# --- init state estimate ----
@@ -161,7 +161,7 @@ Left `estim.x̂0` estimate unchanged if `model` is not a [`LinModel`](@ref).
161161
init_estimate!(::StateEstimator, ::SimModel, _ , _ , _ ) = nothing
162162

163163
@doc raw"""
164-
evaloutput(estim::StateEstimator, d=estim.model.dop) -> ŷ
164+
evaloutput(estim::StateEstimator, d=[]) -> ŷ
165165
166166
Evaluate `StateEstimator` outputs `ŷ` from `estim.x̂0` states and disturbances `d`.
167167
@@ -176,7 +176,7 @@ julia> ŷ = evaloutput(kf)
176176
20.0
177177
```
178178
"""
179-
function evaloutput(estim::StateEstimator{NT}, d=estim.model.dop) where NT <: Real
179+
function evaloutput(estim::StateEstimator{NT}, d=estim.model.buffer.empty) where NT <: Real
180180
validate_args(estim.model, d)
181181
ŷ0 = Vector{NT}(undef, estim.model.ny)
182182
d0 = d - estim.model.dop
@@ -187,10 +187,10 @@ function evaloutput(estim::StateEstimator{NT}, d=estim.model.dop) where NT <: Re
187187
end
188188

189189
"Functor allowing callable `StateEstimator` object as an alias for `evaloutput`."
190-
(estim::StateEstimator)(d=estim.model.dop) = evaloutput(estim, d)
190+
(estim::StateEstimator)(d=estim.model.buffer.empty) = evaloutput(estim, d)
191191

192192
@doc raw"""
193-
updatestate!(estim::StateEstimator, u, ym, d=estim.model.dop) -> x̂
193+
updatestate!(estim::StateEstimator, u, ym, d=[]) -> x̂
194194
195195
Update `estim.x̂0` estimate with current inputs `u`, measured outputs `ym` and dist. `d`.
196196
@@ -207,7 +207,7 @@ julia> x̂ = updatestate!(kf, [1], [0]) # x̂[2] is the integrator state (nint_y
207207
0.0
208208
```
209209
"""
210-
function updatestate!(estim::StateEstimator, u, ym, d=estim.model.dop)
210+
function updatestate!(estim::StateEstimator, u, ym, d=[])
211211
validate_args(estim, u, ym, d)
212212
u0, ym0, d0 = remove_op!(estim, u, ym, d)
213213
x̂0next = update_estimate!(estim, u0, ym0, d0)

src/model/linmodel.jl

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ struct LinModel{NT<:Real} <: SimModel{NT}
1919
yname::Vector{String}
2020
dname::Vector{String}
2121
xname::Vector{String}
22+
buffer::SimModelBuffer{NT}
2223
function LinModel{NT}(A, Bu, C, Bd, Dd, Ts) where {NT<:Real}
2324
A, Bu = to_mat(A, 1, 1), to_mat(Bu, 1, 1)
2425
nu, nx = size(Bu, 2), size(A, 2)
@@ -44,13 +45,15 @@ struct LinModel{NT<:Real} <: SimModel{NT}
4445
dname = ["\$d_{$i}\$" for i in 1:nd]
4546
xname = ["\$x_{$i}\$" for i in 1:nx]
4647
x0 = zeros(NT, nx)
48+
buffer = SimModelBuffer{NT}(nx, nu, ny, nd)
4749
return new{NT}(
4850
A, Bu, C, Bd, Dd,
4951
x0,
5052
Ts,
5153
nu, nx, ny, nd,
5254
uop, yop, dop, xop, fop,
53-
uname, yname, dname, xname
55+
uname, yname, dname, xname,
56+
buffer
5457
)
5558
end
5659
end

src/model/nonlinmodel.jl

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ struct NonLinModel{NT<:Real, F<:Function, H<:Function, DS<:DiffSolver} <: SimMod
1717
yname::Vector{String}
1818
dname::Vector{String}
1919
xname::Vector{String}
20+
buffer::SimModelBuffer{NT}
2021
function NonLinModel{NT, F, H, DS}(
2122
f!::F, h!::H, solver::DS, Ts, nu, nx, ny, nd
2223
) where {NT<:Real, F<:Function, H<:Function, DS<:DiffSolver}
@@ -31,13 +32,15 @@ struct NonLinModel{NT<:Real, F<:Function, H<:Function, DS<:DiffSolver} <: SimMod
3132
dname = ["\$d_{$i}\$" for i in 1:nd]
3233
xname = ["\$x_{$i}\$" for i in 1:nx]
3334
x0 = zeros(NT, nx)
35+
buffer = SimModelBuffer{NT}(nx, nu, ny, nd)
3436
return new{NT, F, H, DS}(
3537
x0,
3638
f!, h!,
3739
solver, Ts,
3840
nu, nx, ny, nd,
3941
uop, yop, dop, xop, fop,
40-
uname, yname, dname, xname
42+
uname, yname, dname, xname,
43+
buffer
4144
)
4245
end
4346
end

src/predictive_control.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ Abstract supertype of all predictive controllers.
33
44
---
55
6-
(mpc::PredictiveController)(ry, d=mpc.estim.model.dop; kwargs...) -> u
6+
(mpc::PredictiveController)(ry, d=[]; kwargs...) -> u
77
88
Functor allowing callable `PredictiveController` object as an alias for [`moveinput!`](@ref).
99
@@ -42,7 +42,7 @@ end
4242
"Functor allowing callable `PredictiveController` object as an alias for `moveinput!`."
4343
function (mpc::PredictiveController)(
4444
ry::Vector = mpc.estim.model.yop,
45-
d ::Vector = mpc.estim.model.dop;
45+
d ::Vector = mpc.estim.model.buffer.empty;
4646
kwargs...
4747
)
4848
return moveinput!(mpc, ry, d; kwargs...)

src/sim_model.jl

Lines changed: 31 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ Abstract supertype of [`LinModel`](@ref) and [`NonLinModel`](@ref) types.
55
66
---
77
8-
(model::SimModel)(d=model.dop) -> y
8+
(model::SimModel)(d=[]) -> y
99
1010
Functor allowing callable `SimModel` object as an alias for [`evaloutput`](@ref).
1111
@@ -20,6 +20,29 @@ julia> y = model()
2020
"""
2121
abstract type SimModel{NT<:Real} end
2222

23+
struct SimModelBuffer{NT<:Real}
24+
u::Vector{NT}
25+
x::Vector{NT}
26+
y::Vector{NT}
27+
d::Vector{NT}
28+
empty::Vector{NT}
29+
end
30+
31+
@doc raw"""
32+
SimModelBuffer(nu, nx, ny, nd) -> SimModelBuffer{NT}
33+
34+
Create a buffer for `SimModel` objects for inputs, states, outputs, and disturbances.
35+
"""
36+
function SimModelBuffer{NT}(nu, nx, ny, nd) where NT <: Real
37+
u = Vector{NT}(undef, nu)
38+
x = Vector{NT}(undef, nx)
39+
y = Vector{NT}(undef, ny)
40+
d = Vector{NT}(undef, nd)
41+
empty = Vector{NT}(undef, 0)
42+
return SimModelBuffer{NT}(u, x, y, d, empty)
43+
end
44+
45+
2346
@doc raw"""
2447
setop!(model; uop=nothing, yop=nothing, dop=nothing, xop=nothing, fop=nothing) -> model
2548
@@ -160,7 +183,7 @@ end
160183
detailstr(model::SimModel) = ""
161184

162185
@doc raw"""
163-
initstate!(model::SimModel, u, d=model.dop) -> x
186+
initstate!(model::SimModel, u, d=[]) -> x
164187
165188
Init `model.x0` with manipulated inputs `u` and measured disturbances `d` steady-state.
166189
@@ -182,7 +205,7 @@ julia> x ≈ updatestate!(model, u)
182205
true
183206
```
184207
"""
185-
function initstate!(model::SimModel, u, d=model.dop)
208+
function initstate!(model::SimModel, u, d=model.buffer.empty)
186209
validate_args(model::SimModel, d, u)
187210
u0, d0 = u - model.uop, d - model.dop
188211
steadystate!(model, u0, d0)
@@ -191,7 +214,7 @@ function initstate!(model::SimModel, u, d=model.dop)
191214
end
192215

193216
"""
194-
updatestate!(model::SimModel, u, d=model.dop) -> x
217+
updatestate!(model::SimModel, u, d=[]) -> x
195218
196219
Update `model.x0` states with current inputs `u` and measured disturbances `d`.
197220
@@ -204,7 +227,7 @@ julia> x = updatestate!(model, [1])
204227
1.0
205228
```
206229
"""
207-
function updatestate!(model::SimModel{NT}, u, d=model.dop) where NT <: Real
230+
function updatestate!(model::SimModel{NT}, u, d=model.buffer.empty) where NT <: Real
208231
validate_args(model::SimModel, d, u)
209232
xnext0 = Vector{NT}(undef, model.nx)
210233
u0, d0 = u - model.uop, d - model.dop
@@ -217,7 +240,7 @@ function updatestate!(model::SimModel{NT}, u, d=model.dop) where NT <: Real
217240
end
218241

219242
"""
220-
evaloutput(model::SimModel, d=model.dop) -> y
243+
evaloutput(model::SimModel, d=[]) -> y
221244
222245
Evaluate `SimModel` outputs `y` from `model.x0` states and measured disturbances `d`.
223246
@@ -232,7 +255,7 @@ julia> y = evaloutput(model)
232255
20.0
233256
```
234257
"""
235-
function evaloutput(model::SimModel{NT}, d=model.dop) where NT <: Real
258+
function evaloutput(model::SimModel{NT}, d=model.buffer.empty) where NT <: Real
236259
validate_args(model, d)
237260
y0 = Vector{NT}(undef, model.ny)
238261
d0 = d - model.dop
@@ -262,7 +285,7 @@ to_mat(A::Real, dims...) = fill(A, dims)
262285

263286

264287
"Functor allowing callable `SimModel` object as an alias for `evaloutput`."
265-
(model::SimModel)(d=model.dop) = evaloutput(model::SimModel, d)
288+
(model::SimModel)(d=model.buffer.empty) = evaloutput(model::SimModel, d)
266289

267290
include("model/linmodel.jl")
268291
include("model/solver.jl")

src/state_estim.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ Abstract supertype of all state estimators.
33
44
---
55
6-
(estim::StateEstimator)(d=estim.model.dop) -> ŷ
6+
(estim::StateEstimator)(d=[]) -> ŷ
77
88
Functor allowing callable `StateEstimator` object as an alias for [`evaloutput`](@ref).
99

0 commit comments

Comments
 (0)