Skip to content

Commit 8a56c4f

Browse files
committed
new default settings for Kalman filters
1 parent e96d75e commit 8a56c4f

File tree

5 files changed

+70
-68
lines changed

5 files changed

+70
-68
lines changed

Project.toml

Lines changed: 1 addition & 1 deletion
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.5.9"
4+
version = "0.5.10"
55

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

README.md

Lines changed: 40 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -72,49 +72,49 @@ for more detailed examples.
7272

7373
### Legend
7474

75-
implemented feature
76-
planned feature
75+
- [x] implemented feature
76+
- [ ] planned feature
7777

7878
### Model Predictive Control Features
7979

80-
- linear and nonlinear plant models exploiting multiple dispatch
81-
- supported objective function terms:
82-
- output setpoint tracking
83-
- move suppression
84-
- input setpoint tracking
85-
- economic costs (economic model predictive control)
86-
- terminal cost to ensure nominal stability
87-
- soft and hard constraints on:
88-
- output predictions
89-
- manipulated inputs
90-
- manipulated inputs increments
91-
- custom manipulated input constraints that are a function of the predictions
92-
- supported feedback strategy:
93-
- state estimator (see State Estimation features)
94-
- internal model structure with a custom stochastic model
95-
- offset-free tracking with a single or multiple integrators on measured outputs
96-
- support for unmeasured model outputs
97-
- feedforward action with measured disturbances that supports direct transmission
98-
- custom predictions for:
99-
- output setpoints
100-
- measured disturbances
101-
- easy integration with `Plots.jl`
102-
- optimization based on `JuMP.jl`:
103-
- quickly compare multiple optimizers
104-
- nonlinear solvers relying on automatic differentiation (exact derivative)
105-
- additional information about the optimum to ease troubleshooting
80+
- [x] linear and nonlinear plant models exploiting multiple dispatch
81+
- [x] supported objective function terms:
82+
- [x] output setpoint tracking
83+
- [x] move suppression
84+
- [x] input setpoint tracking
85+
- [x] economic costs (economic model predictive control)
86+
- [ ] terminal cost to ensure nominal stability
87+
- [x] soft and hard constraints on:
88+
- [x] output predictions
89+
- [x] manipulated inputs
90+
- [x] manipulated inputs increments
91+
- [ ] custom manipulated input constraints that are a function of the predictions
92+
- [x] supported feedback strategy:
93+
- [x] state estimator (see State Estimation features)
94+
- [x] internal model structure with a custom stochastic model
95+
- [x] offset-free tracking with a single or multiple integrators on measured outputs
96+
- [x] support for unmeasured model outputs
97+
- [x] feedforward action with measured disturbances that supports direct transmission
98+
- [x] custom predictions for:
99+
- [x] output setpoints
100+
- [x] measured disturbances
101+
- [x] easy integration with `Plots.jl`
102+
- [x] optimization based on `JuMP.jl`:
103+
- [x] quickly compare multiple optimizers
104+
- [x] nonlinear solvers relying on automatic differentiation (exact derivative)
105+
- [x] additional information about the optimum to ease troubleshooting
106106

107107
### State Estimation Features
108108

109-
- supported state estimators/observers:
110-
- steady-state Kalman filter
111-
- Kalman filter
112-
- Luenberger observer
113-
- internal model structure
114-
- extended Kalman filter
115-
- unscented Kalman filter
116-
- moving horizon estimator
117-
- observers in predictor form to ease control applications
118-
- moving horizon estimator that supports:
119-
- inequality state constraints
120-
- zero process noise equality constraint to reduce the problem size
109+
- [ ] supported state estimators/observers:
110+
- [x] steady-state Kalman filter
111+
- [x] Kalman filter
112+
- [x] Luenberger observer
113+
- [x] internal model structure
114+
- [ ] extended Kalman filter
115+
- [x] unscented Kalman filter
116+
- [ ] moving horizon estimator
117+
- [x] observers in predictor form to ease control applications
118+
- [ ] moving horizon estimator that supports:
119+
- [ ] inequality state constraints
120+
- [ ] zero process noise equality constraint to reduce the problem size

docs/src/manual/nonlinmpc.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ plot(sim!(model, 60, u), plotu=false)
5959
An [`UnscentedKalmanFilter`](@ref) estimates the plant state :
6060

6161
```@example 1
62-
estim = UnscentedKalmanFilter(model, σQ=[0.5, 2.5], σQ_int=[5.0], σR=[0.5])
62+
estim = UnscentedKalmanFilter(model, σQ=[0.1, 0.5], σQ_int=[5.0], σR=[0.5])
6363
```
6464

6565
The standard deviation of the angular velocity ``ω`` is higher here (`σQ` second value)
@@ -80,15 +80,15 @@ sufficient for control. As the motor torque is limited to -1.5 to 1.5 N m, we in
8080
the input constraints in a [`NonLinMPC`](@ref):
8181

8282
```@example 1
83-
mpc = NonLinMPC(estim, Hp=20, Hc=4, Mwt=[0.1], Nwt=[1.0], Cwt=Inf)
83+
mpc = NonLinMPC(estim, Hp=20, Hc=4, Mwt=[0.05], Nwt=[2.5], Cwt=Inf)
8484
mpc = setconstraint!(mpc, umin=[-1.5], umax=[+1.5])
8585
```
8686

8787
We test `mpc` performance on `plant` by imposing an angular setpoint of 180° (inverted
8888
position):
8989

9090
```@example 1
91-
res = sim!(mpc, 65, [180.0], plant=plant, x0=zeros(plant.nx), x̂0=zeros(mpc.estim.nx̂))
91+
res = sim!(mpc, 60, [180.0], plant=plant, x0=zeros(plant.nx), x̂0=zeros(mpc.estim.nx̂))
9292
plot(res)
9393
```
9494

@@ -97,6 +97,6 @@ inverted position, the closed-loop response to a step disturbances of 10° is al
9797
satisfactory:
9898

9999
```@example 1
100-
res = sim!(mpc, 65, [180.0], plant=plant, x0=[π, 0], x̂0=[π, 0, 0], y_step=[10])
100+
res = sim!(mpc, 60, [180.0], plant=plant, x0=[π, 0], x̂0=[π, 0, 0], y_step=[10])
101101
plot(res)
102102
```

src/estimator/kalman.jl

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -85,13 +85,13 @@ ones, for ``\mathbf{Ĉ^u, D̂_d^u}``).
8585
- `model::LinModel` : (deterministic) model for the estimations.
8686
- `i_ym=1:model.ny` : `model` output indices that are measured ``\mathbf{y^m}``, the rest
8787
are unmeasured ``\mathbf{y^u}``.
88-
- `σQ=fill(0.1,model.nx)` : main diagonal of the process noise covariance ``\mathbf{Q}`` of
89-
`model`, specified as a standard deviation vector.
90-
- `σR=fill(0.1,length(i_ym))` : main diagonal of the sensor noise covariance ``\mathbf{R}``
88+
- `σQ=fill(1/model.nx,model.nx)` : main diagonal of the process noise covariance
89+
``\mathbf{Q}`` of `model`, specified as a standard deviation vector.
90+
- `σR=fill(1,length(i_ym))` : main diagonal of the sensor noise covariance ``\mathbf{R}``
9191
of `model` measured outputs, specified as a standard deviation vector.
9292
- `nint_ym=fill(1,length(i_ym))` : integrator quantity per measured outputs (vector) for the
9393
stochastic model, use `nint_ym=0` for no integrator at all.
94-
- `σQ_int=fill(0.1,sum(nint_ym))` : same than `σQ` but for the stochastic model covariance
94+
- `σQ_int=fill(1,sum(nint_ym))` : same than `σQ` but for the stochastic model covariance
9595
``\mathbf{Q_{int}}`` (composed of output integrators).
9696
9797
# Examples
@@ -124,10 +124,10 @@ you can use 0 integrator on `model` integrating outputs, or the alternative time
124124
function SteadyKalmanFilter(
125125
model::LinModel;
126126
i_ym::IntRangeOrVector = 1:model.ny,
127-
σQ::Vector = fill(0.1, model.nx),
128-
σR::Vector = fill(0.1, length(i_ym)),
127+
σQ::Vector = fill(1/model.nx, model.nx),
128+
σR::Vector = fill(1, length(i_ym)),
129129
nint_ym::IntVectorOrInt = fill(1, length(i_ym)),
130-
σQ_int::Vector = fill(0.1, max(sum(nint_ym), 0))
130+
σQ_int::Vector = fill(1, max(sum(nint_ym), 0))
131131
)
132132
# estimated covariances matrices (variance = σ²) :
133133
= Diagonal{Float64}([σQ ; σQ_int ].^2);
@@ -158,11 +158,11 @@ The [`SteadyKalmanFilter`](@ref) updates it with the precomputed Kalman gain ``\
158158
159159
# Examples
160160
```jldoctest
161-
julia> kf = SteadyKalmanFilter(LinModel(ss(1, 1, 1, 0, 1.0)));
161+
julia> kf = SteadyKalmanFilter(LinModel(ss(0.1, 0.5, 1, 0, 4.0)));
162162
163163
julia> x̂ = updatestate!(kf, [1], [0]) # x̂[2] is the integrator state (nint_ym argument)
164164
2-element Vector{Float64}:
165-
1.0
165+
0.5
166166
0.0
167167
```
168168
"""
@@ -239,9 +239,9 @@ with ``\mathbf{P̂}_{-1}(0) = \mathrm{diag}\{ \mathbf{P}(0), \mathbf{P_{int}}(0)
239239
240240
# Arguments
241241
- `model::LinModel` : (deterministic) model for the estimations.
242-
- `σP0=fill(10,model.nx)` : main diagonal of the initial estimate covariance
242+
- `σP0=fill(1/model.nx,model.nx)` : main diagonal of the initial estimate covariance
243243
``\mathbf{P}(0)``, specified as a standard deviation vector.
244-
- `σP0_int=fill(10,sum(nint_ym))` : same than `σP0` but for the stochastic model
244+
- `σP0_int=fill(1,sum(nint_ym))` : same than `σP0` but for the stochastic model
245245
covariance ``\mathbf{P_{int}}(0)`` (composed of output integrators).
246246
- `<keyword arguments>` of [`SteadyKalmanFilter`](@ref) constructor.
247247
@@ -261,12 +261,12 @@ KalmanFilter estimator with a sample time Ts = 0.5 s, LinModel and:
261261
function KalmanFilter(
262262
model::LinModel;
263263
i_ym::IntRangeOrVector = 1:model.ny,
264-
σP0::Vector = fill(10, model.nx),
265-
σQ::Vector = fill(0.1, model.nx),
266-
σR::Vector = fill(0.1, length(i_ym)),
264+
σP0::Vector = fill(1/model.nx, model.nx),
265+
σQ::Vector = fill(1/model.nx, model.nx),
266+
σR::Vector = fill(1, length(i_ym)),
267267
nint_ym::IntVectorOrInt = fill(1, length(i_ym)),
268-
σP0_int::Vector = fill(10, max(sum(nint_ym), 0)),
269-
σQ_int::Vector = fill(0.1, max(sum(nint_ym), 0))
268+
σP0_int::Vector = fill(1, max(sum(nint_ym), 0)),
269+
σQ_int::Vector = fill(1, max(sum(nint_ym), 0))
270270
)
271271
# estimated covariances matrices (variance = σ²) :
272272
P̂0 = Diagonal{Float64}([σP0 ; σP0_int ].^2);
@@ -429,12 +429,12 @@ UnscentedKalmanFilter estimator with a sample time Ts = 10.0 s, NonLinModel and:
429429
function UnscentedKalmanFilter(
430430
model::M;
431431
i_ym::IntRangeOrVector = 1:model.ny,
432-
σP0::Vector = fill(10, model.nx),
433-
σQ::Vector = fill(0.1, model.nx),
434-
σR::Vector = fill(0.1, length(i_ym)),
432+
σP0::Vector = fill(1/model.nx, model.nx),
433+
σQ::Vector = fill(1/model.nx, model.nx),
434+
σR::Vector = fill(1, length(i_ym)),
435435
nint_ym::IntVectorOrInt = fill(1, length(i_ym)),
436-
σP0_int::Vector = fill(10, max(sum(nint_ym), 0)),
437-
σQ_int::Vector = fill(0.1, max(sum(nint_ym), 0)),
436+
σP0_int::Vector = fill(1, max(sum(nint_ym), 0)),
437+
σQ_int::Vector = fill(1, max(sum(nint_ym), 0)),
438438
α::Real = 1e-3,
439439
β::Real = 2,
440440
κ::Real = 0

test/test_state_estim.jl

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,10 @@ sys = [ tf(1.90,[18.0,1]) tf(1.90,[18.0,1]) tf(1.90,[18.0,1]);
3333
@test_throws ErrorException SteadyKalmanFilter(linmodel1, nint_ym=[-1,0])
3434
@test_throws ErrorException SteadyKalmanFilter(linmodel1, nint_ym=0, σQ=[1])
3535
@test_throws ErrorException SteadyKalmanFilter(linmodel1, nint_ym=0, σR=[1,1,1])
36-
@test_throws ErrorException SteadyKalmanFilter(LinModel(tf(1,[1,0]),1),nint_ym=[10])
37-
end
36+
@test_throws ErrorException SteadyKalmanFilter( # test error compute Kalman gain K
37+
LinModel(tf(1,[10,1]),1), nint_ym=[2], σQ_int=[0,0]
38+
)
39+
end
3840

3941
@testset "SteadyKalmanFilter estimator methods" begin
4042
linmodel1 = setop!(LinModel(sys,Ts,i_u=[1,2]), uop=[10,50], yop=[50,30])

0 commit comments

Comments
 (0)