Skip to content

Commit 4d7ab12

Browse files
committed
Merge branch 'main' into new_jump_nlp_syntax
2 parents 21b5fb6 + 2ea9ad1 commit 4d7ab12

30 files changed

+697
-519
lines changed

Project.toml

Lines changed: 2 additions & 2 deletions
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.17.0"
4+
version = "0.20.1"
55

66
[deps]
77
ControlSystemsBase = "aaaaaaaa-a6ca-5380-bf3e-84a91bcd477e"
@@ -19,7 +19,7 @@ RecipesBase = "3cdcf5f2-1ef4-517c-9805-6587b60abb01"
1919
ControlSystemsBase = "1.9"
2020
ForwardDiff = "0.10"
2121
Ipopt = "1"
22-
JuMP = "1"
22+
JuMP = "1.21"
2323
LinearAlgebra = "1.6"
2424
OSQP = "0.8"
2525
PreallocationTools = "0.4"

README.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,4 +130,3 @@ for more detailed examples.
130130
- [x] state estimates
131131
- [x] process noise estimates
132132
- [x] sensor noise estimates
133-
- [ ] moving horizon estimator with no process noise to reduce the problem size

docs/src/manual/nonlinmpc.md

Lines changed: 17 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,9 @@ The plant model is nonlinear:
3535

3636
in which ``g`` is the gravitational acceleration in m/s², ``L``, the pendulum length in m,
3737
``K``, the friction coefficient at the pivot point in kg/s, and ``m``, the mass attached at
38-
the end of the pendulum in kg. Here, the explicit Euler method discretizes the system to
39-
construct a [`NonLinModel`](@ref):
38+
the end of the pendulum in kg. The [`NonLinModel`](@ref) constructor assumes by default
39+
that the state function `f` is continuous in time, that is, an ordinary differential
40+
equation system (like here):
4041

4142
```@example 1
4243
using ModelPredictiveControl
@@ -49,17 +50,17 @@ function pendulum(par, x, u)
4950
return [dθ, dω]
5051
end
5152
# declared constants, to avoid type-instability in the f function, for speed:
52-
const par, Ts = (9.8, 0.4, 1.2, 0.3), 0.1
53-
f(x, u, _ ) = x + Ts*pendulum(par, x, u) # Euler method
53+
const par = (9.8, 0.4, 1.2, 0.3)
54+
f(x, u, _ ) = pendulum(par, x, u)
5455
h(x, _ ) = [180/π*x[1]] # [°]
55-
nu, nx, ny = 1, 2, 1
56+
Ts, nu, nx, ny = 0.1, 1, 2, 1
5657
model = NonLinModel(f, h, Ts, nu, nx, ny)
5758
```
5859

5960
The output function ``\mathbf{h}`` converts the ``θ`` angle to degrees. Note that special
6061
characters like ``θ`` can be typed in the Julia REPL or VS Code by typing `\theta` and
61-
pressing the `<TAB>` key. The tuple `par` and `Ts` are declared as constants here to improve
62-
the [performance](https://docs.julialang.org/en/v1/manual/performance-tips/#Avoid-untyped-global-variables).
62+
pressing the `<TAB>` key. The tuple `par` is constant here to improve the [performance](https://docs.julialang.org/en/v1/manual/performance-tips/#Avoid-untyped-global-variables).
63+
Note that a 4th order [`RungeKutta`](@ref) differential equation solver is used by default.
6364
It is good practice to first simulate `model` using [`sim!`](@ref) as a quick sanity check:
6465

6566
```@example 1
@@ -78,20 +79,20 @@ savefig(ans, "plot1_NonLinMPC.svg"); nothing # hide
7879
An [`UnscentedKalmanFilter`](@ref) estimates the plant state :
7980

8081
```@example 1
81-
α=0.1; σQ=[0.1, 0.5]; σR=[0.5]; nint_u=[1]; σQint_u=[0.1]
82+
α=0.01; σQ=[0.1, 0.5]; σR=[0.5]; nint_u=[1]; σQint_u=[0.1]
8283
estim = UnscentedKalmanFilter(model; α, σQ, σR, nint_u, σQint_u)
8384
```
8485

8586
The vectors `σQ` and σR `σR` are the standard deviations of the process and sensor noises,
8687
respectively. The value for the velocity ``ω`` is higher here (`σQ` second value) since
8788
``\dot{ω}(t)`` equation includes an uncertain parameter: the friction coefficient ``K``.
8889
Also, the argument `nint_u` explicitly adds one integrating state at the model input, the
89-
motor torque ``τ`` , with an associated standard deviation `σQint_u` of 0.1 N m. The
90+
motor torque ``τ``, with an associated standard deviation `σQint_u` of 0.1 N m. The
9091
estimator tuning is tested on a plant with a 25 % larger friction coefficient ``K``:
9192

9293
```@example 1
9394
const par_plant = (par[1], par[2], 1.25*par[3], par[4])
94-
f_plant(x, u, _) = x + Ts*pendulum(par_plant, x, u)
95+
f_plant(x, u, _ ) = pendulum(par_plant, x, u)
9596
plant = NonLinModel(f_plant, h, Ts, nu, nx, ny)
9697
res = sim!(estim, N, [0.5], plant=plant, y_noise=[0.5])
9798
plot(res, plotu=false, plotxwithx̂=true)
@@ -107,12 +108,11 @@ As the motor torque is limited to -1.5 to 1.5 N m, we incorporate the input cons
107108
a [`NonLinMPC`](@ref):
108109

109110
```@example 1
110-
nmpc = NonLinMPC(estim, Hp=20, Hc=2, Mwt=[0.5], Nwt=[2.5])
111+
nmpc = NonLinMPC(estim, Hp=20, Hc=2, Mwt=[0.5], Nwt=[2.5], Cwt=Inf)
111112
nmpc = setconstraint!(nmpc, umin=[-1.5], umax=[+1.5])
112113
```
113114

114-
We test `mpc` performance on `plant` by imposing an angular setpoint of 180° (inverted
115-
position):
115+
The option `Cwt=Inf` disables the slack variable `ϵ` for constraint softening. We test `mpc` performance on `plant` by imposing an angular setpoint of 180° (inverted position):
116116

117117
```@example 1
118118
using Logging; disable_logging(Warn) # hide
@@ -184,7 +184,7 @@ function JE(UE, ŶE, _ )
184184
τ, ω = UE[1:end-1], ŶE[2:2:end-1]
185185
return Ts*sum(τ.*ω)
186186
end
187-
empc = NonLinMPC(estim2, Hp=20, Hc=2, Mwt=[0.5, 0], Nwt=[2.5], Ewt=4.5e3, JE=JE)
187+
empc = NonLinMPC(estim2, Hp=20, Hc=2, Mwt=[0.5, 0], Nwt=[2.5], Cwt=Inf, Ewt=3.5e3, JE=JE)
188188
empc = setconstraint!(empc, umin=[-1.5], umax=[+1.5])
189189
```
190190

@@ -245,13 +245,11 @@ We first linearize `model` at the point ``θ = π`` rad and ``ω = τ = 0`` (inv
245245
linmodel = linearize(model, x=[π, 0], u=[0])
246246
```
247247

248-
It is worth mentioning that the Euler method in `model` object is not the best choice for
249-
linearization since its accuracy is low (approximation of a poor approximation). A
250-
[`SteadyKalmanFilter`](@ref) and a [`LinMPC`](@ref) are designed from `linmodel`:
248+
A [`SteadyKalmanFilter`](@ref) and a [`LinMPC`](@ref) are designed from `linmodel`:
251249

252250
```@example 1
253251
kf = SteadyKalmanFilter(linmodel; σQ, σR, nint_u, σQint_u)
254-
mpc = LinMPC(kf, Hp=20, Hc=2, Mwt=[0.5], Nwt=[2.5])
252+
mpc = LinMPC(kf, Hp=20, Hc=2, Mwt=[0.5], Nwt=[2.5], Cwt=Inf)
255253
mpc = setconstraint!(mpc, umin=[-1.5], umax=[+1.5])
256254
```
257255

@@ -289,7 +287,7 @@ Constructing a [`LinMPC`](@ref) with `DAQP`:
289287
```@example 1
290288
using JuMP, DAQP
291289
daqp = Model(DAQP.Optimizer, add_bridges=false)
292-
mpc2 = LinMPC(kf, Hp=20, Hc=2, Mwt=[0.5], Nwt=[2.5], optim=daqp)
290+
mpc2 = LinMPC(kf, Hp=20, Hc=2, Mwt=[0.5], Nwt=[2.5], Cwt=Inf, optim=daqp)
293291
mpc2 = setconstraint!(mpc2, umin=[-1.5], umax=[+1.5])
294292
```
295293

docs/src/public/sim_model.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,20 @@ LinModel
2929
NonLinModel
3030
```
3131

32+
## Differential Equation Solvers
33+
34+
### DiffSolver
35+
36+
```@docs
37+
ModelPredictiveControl.DiffSolver
38+
```
39+
40+
### RungeKutta
41+
42+
```@docs
43+
RungeKutta
44+
```
45+
3246
## Set Operating Points
3347

3448
```@docs

src/ModelPredictiveControl.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import OSQP, Ipopt
1212

1313

1414
export SimModel, LinModel, NonLinModel
15+
export DiffSolver, RungeKutta
1516
export setop!, setstate!, updatestate!, evaloutput, linearize
1617
export StateEstimator, InternalModel, Luenberger
1718
export SteadyKalmanFilter, KalmanFilter, UnscentedKalmanFilter, ExtendedKalmanFilter

src/controller/construct.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ julia> mpc = setconstraint!(mpc, umin=[0], umax=[100], Δumin=[-10], Δumax=[+10
7272
LinMPC controller with a sample time Ts = 4.0 s, OSQP optimizer, SteadyKalmanFilter estimator and:
7373
10 prediction steps Hp
7474
2 control steps Hc
75+
1 slack variable ϵ (control constraints)
7576
1 manipulated inputs u (0 integrating states)
7677
2 estimated states x̂
7778
1 measured outputs ym (1 integrating states)

0 commit comments

Comments
 (0)