Skip to content

Commit 5bdfd14

Browse files
authored
Merge pull request #93 from JuliaControl/doc_correction
added: doc correction and reduce allocations for all Kalman filters
2 parents d10a731 + e8b3784 commit 5bdfd14

File tree

12 files changed

+155
-107
lines changed

12 files changed

+155
-107
lines changed

Project.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
name = "ModelPredictiveControl"
22
uuid = "61f9bdb8-6ae4-484a-811f-bbf86720c31c"
33
authors = ["Francis Gagnon"]
4-
version = "0.23.0"
4+
version = "0.23.1"
55

66
[deps]
77
ControlSystemsBase = "aaaaaaaa-a6ca-5380-bf3e-84a91bcd477e"

README.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -126,9 +126,9 @@ for more detailed examples.
126126
- [x] manipulated inputs
127127
- [x] measured outputs
128128
- [x] bumpless manual to automatic transfer for control with a proper initial estimate
129-
- [ ] estimators in two possible forms:
129+
- [x] estimators in two possible forms:
130+
- [x] filter (or current) form to improve accuracy and robustness
130131
- [x] predictor (or delayed) form to reduce computational load
131-
- [ ] filter (or current) form to improve accuracy and robustness
132132
- [x] moving horizon estimator in two formulations:
133133
- [x] linear plant models (quadratic optimization)
134134
- [x] nonlinear plant models (nonlinear optimization)

docs/src/manual/nonlinmpc.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -378,7 +378,7 @@ nothing # hide
378378

379379
The [`setmodel!`](@ref) method must be called after solving the optimization problem with
380380
[`moveinput!`](@ref) and before updating the state estimate with [`updatestate!`](@ref),
381-
that is, when both ``\mathbf{u}(k)`` and ``\mathbf{x̂}_{k-1}(k)`` are available as the new
381+
that is, when both ``\mathbf{u}(k)`` and ``\mathbf{x̂}_{k}(k)`` are available as the new
382382
operating point. The [`SimResult`](@ref) object is for plotting purposes only. The adaptive
383383
[`LinMPC`](@ref) performances are similar to the nonlinear MPC, both for the 180° setpoint:
384384

src/controller/construct.jl

+4-4
Original file line numberDiff line numberDiff line change
@@ -94,10 +94,10 @@ LinMPC controller with a sample time Ts = 4.0 s, OSQP optimizer, SteadyKalmanFil
9494
Terminal constraints provide closed-loop stability guarantees on the nominal plant model.
9595
They can render an unfeasible problem however. In practice, a sufficiently large
9696
prediction horizon ``H_p`` without terminal constraints is typically enough for
97-
stability. If `mpc.estim.direct==true`, the state is estimated at ``i = k`` (the current
98-
time step), otherwise at ``i = k - 1``. Note that terminal constraints are applied on the
99-
augmented state vector ``\mathbf{x̂}`` (see [`SteadyKalmanFilter`](@ref) for details on
100-
augmentation).
97+
stability. If `mpc.estim.direct==true`, the estimator computes the states at ``i = k``
98+
(the current time step), otherwise at ``i = k - 1``. Note that terminal constraints are
99+
applied on the augmented state vector ``\mathbf{x̂}`` (see [`SteadyKalmanFilter`](@ref)
100+
for details on augmentation).
101101
102102
For variable constraints, the bounds can be modified after calling [`moveinput!`](@ref),
103103
that is, at runtime, but not the softness parameters ``\mathbf{c}``. It is not possible

src/estimator/construct.jl

+3-3
Original file line numberDiff line numberDiff line change
@@ -146,13 +146,13 @@ end
146146
Return empty matrices, and `x̂op` & `f̂op` vectors, if `model` is not a [`LinModel`](@ref).
147147
"""
148148
function augment_model(model::SimModel{NT}, As, args... ; verify_obsv=false) where NT<:Real
149-
nu, nx, nd = model.nu, model.nx, model.nd
149+
nu, nx, nd, ny = model.nu, model.nx, model.nd, model.ny
150150
nxs = size(As, 1)
151151
= zeros(NT, 0, nx+nxs)
152152
B̂u = zeros(NT, 0, nu)
153-
= zeros(NT, 0, nx+nxs)
153+
= zeros(NT, ny, 0)
154154
B̂d = zeros(NT, 0, nd)
155-
D̂d = zeros(NT, 0, nd)
155+
D̂d = zeros(NT, ny, 0)
156156
x̂op, f̂op = [model.xop; zeros(nxs)], [model.fop; zeros(nxs)]
157157
return Â, B̂u, Ĉ, B̂d, D̂d, x̂op, f̂op
158158
end

src/estimator/execute.jl

+4-2
Original file line numberDiff line numberDiff line change
@@ -153,8 +153,8 @@ in which ``\mathbf{Ĉ^m, D̂_d^m}`` are the rows of `estim.Ĉ, estim.D̂d` th
153153
measured outputs ``\mathbf{y^m}``.
154154
"""
155155
function init_estimate!(estim::StateEstimator, ::LinModel, y0m, d0, u0)
156-
Â, B̂u, Ĉ, B̂d, D̂d = estim.Â, estim.B̂u, estim.Ĉ, estim.B̂d, estim.D̂d
157-
Ĉm, D̂dm = @views Ĉ[estim.i_ym, :], D̂d[estim.i_ym, :] # measured outputs ym only
156+
Â, B̂u, B̂d = estim.Â, estim.B̂u, estim.B̂d
157+
Ĉm, D̂dm = estim.Ĉm, estim.D̂dm
158158
# TODO: use estim.buffer.x̂ to reduce allocations
159159
estim.x̂0 .= [I - Â; Ĉm]\[B̂u*u0 + B̂d*d0 + estim.f̂op - estim.x̂op; y0m - D̂dm*d0]
160160
return nothing
@@ -390,6 +390,8 @@ function setmodel_estimator!(estim::StateEstimator, model, _ , _ , _ , Q̂, R̂)
390390
estim.Ĉ .=
391391
estim.B̂d .= B̂d
392392
estim.D̂d .= D̂d
393+
estim.Ĉm .= @views Ĉ[estim.i_ym, :]
394+
estim.D̂dm .= @views D̂d[estim.i_ym, :]
393395
# --- update state estimate and its operating points ---
394396
estim.x̂0 .+= estim.x̂op # convert x̂0 to x̂ with the old operating point
395397
estim.x̂op .= x̂op

src/estimator/internal_model.jl

+13-8
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,13 @@ struct InternalModel{NT<:Real, SM<:SimModel} <: StateEstimator{NT}
1616
Bs::Matrix{NT}
1717
Cs::Matrix{NT}
1818
Ds::Matrix{NT}
19-
::Matrix{NT}
20-
B̂u::Matrix{NT}
21-
::Matrix{NT}
22-
B̂d::Matrix{NT}
23-
D̂d::Matrix{NT}
19+
::Matrix{NT}
20+
B̂u ::Matrix{NT}
21+
::Matrix{NT}
22+
B̂d ::Matrix{NT}
23+
D̂d ::Matrix{NT}
24+
Ĉm ::Matrix{NT}
25+
D̂dm ::Matrix{NT}
2426
Âs::Matrix{NT}
2527
B̂s::Matrix{NT}
2628
direct::Bool
@@ -36,6 +38,7 @@ struct InternalModel{NT<:Real, SM<:SimModel} <: StateEstimator{NT}
3638
nxs = size(As,1)
3739
nx̂ = model.nx
3840
Â, B̂u, Ĉ, B̂d, D̂d, x̂op, f̂op = matrices_internalmodel(model)
41+
Ĉm, D̂dm = Ĉ[i_ym,:], D̂d[i_ym,:]
3942
Âs, B̂s = init_internalmodel(As, Bs, Cs, Ds)
4043
lastu0 = zeros(NT, nu)
4144
# x̂0 and x̂d are same object (updating x̂d will update x̂0):
@@ -50,7 +53,7 @@ struct InternalModel{NT<:Real, SM<:SimModel} <: StateEstimator{NT}
5053
lastu0, x̂op, f̂op, x̂0, x̂d, x̂s, ŷs,
5154
i_ym, nx̂, nym, nyu, nxs,
5255
As, Bs, Cs, Ds,
53-
Â, B̂u, Ĉ, B̂d, D̂d,
56+
Â, B̂u, Ĉ, B̂d, D̂d, Ĉm, D̂dm,
5457
Âs, B̂s,
5558
direct, corrected,
5659
buffer
@@ -156,8 +159,8 @@ function matrices_internalmodel(model::LinModel)
156159
end
157160
"Return empty matrices, and `x̂op` & `f̂op` vectors, if `model` is not a [`LinModel`](@ref)."
158161
function matrices_internalmodel(model::SimModel{NT}) where NT<:Real
159-
nu, nx, nd = model.nu, model.nx, model.nd
160-
Â, B̂u, Ĉ, B̂d, D̂d = zeros(NT,0,nx), zeros(NT,0,nu), zeros(NT,0,nx), zeros(NT,0,nd), zeros(NT,0,nd)
162+
nu, nx, nd, ny = model.nu, model.nx, model.nd, model.ny
163+
Â, B̂u, Ĉ, B̂d, D̂d = zeros(NT,0,nx), zeros(NT,0,nu), zeros(NT,ny,0), zeros(NT,0,nd), zeros(NT,ny,0)
161164
x̂op, f̂op = copy(model.xop), copy(model.fop)
162165
return Â, B̂u, Ĉ, B̂d, D̂d, x̂op, f̂op
163166
end
@@ -225,6 +228,8 @@ function setmodel_estimator!(estim::InternalModel, model, _ , _ , _ , _ , _ )
225228
estim.Ĉ .=
226229
estim.B̂d .= B̂d
227230
estim.D̂d .= D̂d
231+
estim.Ĉm .= @views Ĉ[estim.i_ym,:]
232+
estim.D̂dm .= @views D̂d[estim.i_ym,:]
228233
# --- update state estimate and its operating points ---
229234
estim.x̂0 .+= estim.x̂op # convert x̂0 to x̂ with the old operating point
230235
estim.x̂op .= x̂op

0 commit comments

Comments
 (0)