Skip to content

Commit b42e6ab

Browse files
committed
wip: multiple shooting
1 parent b9a2056 commit b42e6ab

File tree

6 files changed

+81
-37
lines changed

6 files changed

+81
-37
lines changed

docs/src/internals/predictive_control.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ The prediction methodology of this module is mainly based on Maciejowski textboo
1212
## Controller Construction
1313

1414
```@docs
15+
ModelPredictiveControl.init_ZtoΔU
1516
ModelPredictiveControl.init_ZtoU
1617
ModelPredictiveControl.init_predmat
1718
ModelPredictiveControl.init_defectmat

src/controller/construct.jl

Lines changed: 31 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -499,20 +499,20 @@ end
499499
init_defaultcon_mpc(
500500
estim::StateEstimator,
501501
Hp, Hc, C,
502-
S, E,
502+
P, S, E,
503503
ex̂, fx̂, gx̂, jx̂, kx̂, vx̂, bx̂,
504504
Eŝ, Fŝ, Gŝ, Jŝ, Kŝ, Vŝ, Bŝ,
505505
gc!=nothing, nc=0
506506
) -> con, S̃, Ẽ, Ẽŝ
507507
508508
Init `ControllerConstraint` struct with default parameters based on estimator `estim`.
509509
510-
Also return `S̃`, `Ẽ` and `Ẽŝ` matrices for the the augmented decision vector `ΔŨ`.
510+
Also return `P̃`, `S̃`, `Ẽ` and `Ẽŝ` matrices for the the augmented decision vector ``.
511511
"""
512512
function init_defaultcon_mpc(
513513
estim::StateEstimator{NT},
514514
Hp, Hc, C,
515-
S, E,
515+
P, S, E,
516516
ex̂, fx̂, gx̂, jx̂, kx̂, vx̂, bx̂,
517517
Eŝ, Fŝ, Gŝ, Jŝ, Kŝ, Vŝ, Bŝ,
518518
gc!::GCfunc = nothing, nc = 0
@@ -533,7 +533,7 @@ function init_defaultcon_mpc(
533533
C_umin, C_umax, C_Δumin, C_Δumax, C_ymin, C_ymax =
534534
repeat_constraints(Hp, Hc, c_umin, c_umax, c_Δumin, c_Δumax, c_ymin, c_ymax)
535535
A_Umin, A_Umax, S̃ = relaxU(model, nϵ, C_umin, C_umax, S)
536-
A_ΔŨmin, A_ΔŨmax, ΔŨmin, ΔŨmax = relaxΔU(model, nϵ, C, C_Δumin, C_Δumax, ΔUmin, ΔUmax)
536+
A_ΔŨmin, A_ΔŨmax, ΔŨmin, ΔŨmax, P̃ = relaxΔU(model, nϵ, C_Δumin, C_Δumax, ΔUmin, ΔUmax, P)
537537
A_Ymin, A_Ymax, Ẽ = relaxŶ(model, nϵ, C_ymin, C_ymax, E)
538538
A_x̂min, A_x̂max, ẽx̂ = relaxterminal(model, nϵ, c_x̂min, c_x̂max, ex̂)
539539
A_ŝ, Ẽŝ = augmentdefect(model, nϵ, Eŝ)
@@ -558,7 +558,7 @@ function init_defaultcon_mpc(
558558
C_ymin , C_ymax , c_x̂min , c_x̂max , i_g,
559559
gc! , nc
560560
)
561-
return con, nϵ, S̃, Ẽ, Ẽŝ
561+
return con, nϵ, P̃, S̃, Ẽ, Ẽŝ
562562
end
563563

564564
"Repeat predictive controller constraints over prediction `Hp` and control `Hc` horizons."
@@ -579,70 +579,76 @@ end
579579
580580
Augment manipulated inputs constraints with slack variable ϵ for softening.
581581
582-
Denoting the input increments augmented with the slack variable
583-
``\mathbf{ΔŨ} = [\begin{smallmatrix} \mathbf{ΔU} \\ ϵ \end{smallmatrix}]``, it returns the
582+
Denoting the decision variables augmented with the slack variable
583+
``\mathbf{} = [\begin{smallmatrix} \mathbf{Z} \\ ϵ \end{smallmatrix}]``, it returns the
584584
augmented conversion matrix ``\mathbf{S̃}``, similar to the one described at
585585
[`init_ZtoU`](@ref). It also returns the ``\mathbf{A}`` matrices for the inequality
586586
constraints:
587587
```math
588588
\begin{bmatrix}
589589
\mathbf{A_{U_{min}}} \\
590590
\mathbf{A_{U_{max}}}
591-
\end{bmatrix} \mathbf{ΔŨ} ≤
591+
\end{bmatrix} \mathbf{} ≤
592592
\begin{bmatrix}
593-
- \mathbf{U_{min} + T} \mathbf{u}(k-1) \\
594-
+ \mathbf{U_{max} - T} \mathbf{u}(k-1)
593+
- \mathbf{U_{min} + T u}(k-1) \\
594+
+ \mathbf{U_{max} - T u}(k-1)
595595
\end{bmatrix}
596596
```
597597
in which ``\mathbf{U_{min}}`` and ``\mathbf{U_{max}}`` vectors respectively contains
598598
``\mathbf{u_{min}}`` and ``\mathbf{u_{max}}`` repeated ``H_p`` times.
599599
"""
600600
function relaxU(::SimModel{NT}, nϵ, C_umin, C_umax, S) where NT<:Real
601-
if== 1 # ΔŨ = [ΔU; ϵ]
602-
# ϵ impacts ΔU → U conversion for constraint calculations:
601+
if== 1 # = [Z; ϵ]
602+
# ϵ impacts Z → U conversion for constraint calculations:
603603
A_Umin, A_Umax = -[S C_umin], [S -C_umax]
604-
# ϵ has no impact on ΔU → U conversion for prediction calculations:
604+
# ϵ has no impact on Z → U conversion for prediction calculations:
605605
= [S zeros(NT, size(S, 1))]
606-
else # ΔŨ = ΔU (only hard constraints)
606+
else # = Z (only hard constraints)
607607
A_Umin, A_Umax = -S, S
608608
= S
609609
end
610610
return A_Umin, A_Umax, S̃
611611
end
612612

613613
@doc raw"""
614-
relaxΔU(model, nϵ, C, C_Δumin, C_Δumax, ΔUmin, ΔUmax) -> A_ΔŨmin, A_ΔŨmax, ΔŨmin, ΔŨmax
614+
relaxΔU(
615+
model, nϵ, C_Δumin, C_Δumax, ΔUmin, ΔUmax, P
616+
) -> A_ΔŨmin, A_ΔŨmax, ΔŨmin, ΔŨmax, P̃
615617
616618
Augment input increments constraints with slack variable ϵ for softening.
617619
618-
Denoting the input increments augmented with the slack variable
619-
``\mathbf{ΔŨ} = [\begin{smallmatrix} \mathbf{ΔU} \\ ϵ \end{smallmatrix}]``, it returns the
620-
augmented constraints ``\mathbf{ΔŨ_{min}}`` and ``\mathbf{ΔŨ_{max}}`` and the ``\mathbf{A}``
621-
matrices for the inequality constraints:
620+
Denoting the decision variables augmented with the slack variable
621+
``\mathbf{Z̃} = [\begin{smallmatrix} \mathbf{Z} \\ ϵ \end{smallmatrix}]``, it returns the
622+
augmented conversion matrix ``\mathbf{P̃}``, similar to the one described at
623+
[`init_ZtoΔU`](@ref). It also returns the augmented constraints ``\mathbf{ΔŨ_{min}}`` and
624+
``\mathbf{ΔŨ_{max}}`` and the ``\mathbf{A}`` matrices for the inequality constraints:
622625
```math
623626
\begin{bmatrix}
624627
\mathbf{A_{ΔŨ_{min}}} \\
625628
\mathbf{A_{ΔŨ_{max}}}
626-
\end{bmatrix} \mathbf{ΔŨ} ≤
629+
\end{bmatrix} \mathbf{} ≤
627630
\begin{bmatrix}
628631
- \mathbf{ΔŨ_{min}} \\
629632
+ \mathbf{ΔŨ_{max}}
630633
\end{bmatrix}
631634
```
632635
"""
633-
function relaxΔU(::SimModel{NT}, nϵ, C, C_Δumin, C_Δumax, ΔUmin, ΔUmax) where NT<:Real
636+
function relaxΔU(::SimModel{NT}, nϵ, C_Δumin, C_Δumax, ΔUmin, ΔUmax, P) where NT<:Real
634637
nΔU = length(ΔUmin)
635-
if== 1 # ΔŨ = [ΔU; ϵ]
636-
# 0 ≤ ϵ ≤ ∞
638+
nZ = size(P, 2)
639+
if== 1 # Z̃ = [Z; ϵ]
640+
# 0 ≤ ϵ ≤ ∞
637641
ΔŨmin, ΔŨmax = [ΔUmin; NT[0.0]], [ΔUmax; NT[Inf]]
638642
A_ϵ = [zeros(NT, 1, nΔU) NT[1.0]]
639643
A_ΔŨmin, A_ΔŨmax = -[I C_Δumin; A_ϵ], [I -C_Δumax; A_ϵ]
640-
else # ΔŨ = ΔU (only hard constraints)
644+
= [P zeros(NT, size(P, 1), 1)]
645+
else # Z̃ = Z (only hard constraints)
641646
ΔŨmin, ΔŨmax = ΔUmin, ΔUmax
642647
I_Hc = Matrix{NT}(I, nΔU, nΔU)
643648
A_ΔŨmin, A_ΔŨmax = -I_Hc, I_Hc
649+
= P
644650
end
645-
return A_ΔŨmin, A_ΔŨmax, ΔŨmin, ΔŨmax
651+
return A_ΔŨmin, A_ΔŨmax, ΔŨmin, ΔŨmax, P̃
646652
end
647653

648654
@doc raw"""

src/controller/explicitmpc.jl

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,11 +47,12 @@ struct ExplicitMPC{NT<:Real, SE<:StateEstimator} <: PredictiveController{NT}
4747
# dummy vals (updated just before optimization):
4848
R̂y, R̂u, T_lastu = zeros(NT, ny*Hp), zeros(NT, nu*Hp), zeros(NT, nu*Hp)
4949
transcription = SingleShooting() # explicit MPC only supports SingleShooting
50+
P = init_ZtoΔU(estim, transcription, Hp, Hc)
5051
S, T = init_ZtoU(estim, transcription, Hp, Hc)
5152
E, G, J, K, V, B = init_predmat(model, estim, transcription, Hp, Hc)
5253
# dummy val (updated just before optimization):
5354
F, fx̂ = zeros(NT, ny*Hp), zeros(NT, nx̂)
54-
S̃, Ñ_Hc, Ẽ = S, N_Hc, E # no slack variable ϵ for ExplicitMPC
55+
P̃, S̃, Ñ_Hc, Ẽ = P, S, N_Hc, E # no slack variable ϵ for ExplicitMPC
5556
= init_quadprog(model, weights ,Ẽ, S̃)
5657
# dummy vals (updated just before optimization):
5758
q̃, r = zeros(NT, size(H̃, 1)), zeros(NT, 1)
@@ -70,7 +71,7 @@ struct ExplicitMPC{NT<:Real, SE<:StateEstimator} <: PredictiveController{NT}
7071
Hp, Hc, nϵ,
7172
weights,
7273
R̂u, R̂y,
73-
S̃, T, T_lastu,
74+
P̃, S̃, T, T_lastu,
7475
Ẽ, F, G, J, K, V, B,
7576
H̃, q̃, r,
7677
H̃_chol,

src/controller/linmpc.jl

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,14 +53,15 @@ struct LinMPC{
5353
weights = ControllerWeights{NT}(model, Hp, Hc, M_Hp, N_Hc, L_Hp, Cwt)
5454
# dummy vals (updated just before optimization):
5555
R̂y, R̂u, T_lastu = zeros(NT, ny*Hp), zeros(NT, nu*Hp), zeros(NT, nu*Hp)
56+
P = init_ZtoΔU(estim, transcription, Hp, Hc)
5657
S, T = init_ZtoU(estim, transcription, Hp, Hc)
5758
E, G, J, K, V, B, ex̂, gx̂, jx̂, kx̂, vx̂, bx̂ = init_predmat(
5859
model, estim, transcription, Hp, Hc
5960
)
6061
# dummy vals (updated just before optimization):
6162
F, fx̂ = zeros(NT, ny*Hp), zeros(NT, nx̂)
62-
con, nϵ, S̃, Ẽ = init_defaultcon_mpc(
63-
estim, Hp, Hc, Cwt, S, E, ex̂, fx̂, gx̂, jx̂, kx̂, vx̂, bx̂
63+
con, nϵ, P̃, S̃, Ẽ, Ẽŝ = init_defaultcon_mpc(
64+
estim, Hp, Hc, Cwt, P, S, E, ex̂, fx̂, gx̂, jx̂, kx̂, vx̂, bx̂
6465
)
6566
= init_quadprog(model, weights, Ẽ, S̃)
6667
# dummy vals (updated just before optimization):
@@ -78,7 +79,7 @@ struct LinMPC{
7879
Hp, Hc, nϵ,
7980
weights,
8081
R̂u, R̂y,
81-
S̃, T, T_lastu,
82+
P̃, S̃, T, T_lastu,
8283
Ẽ, F, G, J, K, V, B,
8384
H̃, q̃, r,
8485
Ks, Ps,

src/controller/nonlinmpc.jl

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -67,14 +67,15 @@ struct NonLinMPC{
6767
weights = ControllerWeights{NT}(model, Hp, Hc, M_Hp, N_Hc, L_Hp, Cwt, Ewt)
6868
# dummy vals (updated just before optimization):
6969
R̂y, R̂u, T_lastu = zeros(NT, ny*Hp), zeros(NT, nu*Hp), zeros(NT, nu*Hp)
70+
P = init_ZtoΔU(estim, transcription, Hp, Hc)
7071
S, T = init_ZtoU(estim, transcription, Hp, Hc)
7172
E, G, J, K, V, B, ex̂, gx̂, jx̂, kx̂, vx̂, bx̂ = init_predmat(
7273
model, estim, transcription, Hp, Hc
7374
)
7475
# dummy vals (updated just before optimization):
7576
F, fx̂ = zeros(NT, ny*Hp), zeros(NT, nx̂)
76-
con, nϵ, S̃, Ẽ = init_defaultcon_mpc(
77-
estim, Hp, Hc, Cwt, S, E, ex̂, fx̂, gx̂, jx̂, kx̂, vx̂, bx̂, gc!, nc
77+
con, nϵ, P̃, S̃, Ẽ, Ẽŝ = init_defaultcon_mpc(
78+
estim, Hp, Hc, Cwt, P, S, E, ex̂, fx̂, gx̂, jx̂, kx̂, vx̂, bx̂
7879
)
7980
= init_quadprog(model, weights, Ẽ, S̃)
8081
# dummy vals (updated just before optimization):
@@ -94,7 +95,7 @@ struct NonLinMPC{
9495
weights,
9596
JE, p,
9697
R̂u, R̂y,
97-
S̃, T, T_lastu,
98+
P̃, S̃, T, T_lastu,
9899
Ẽ, F, G, J, K, V, B,
99100
H̃, q̃, r,
100101
Ks, Ps,

src/controller/transcription.jl

Lines changed: 38 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,8 @@ The decision variable in the optimization problem is (excluding the slack ``ϵ``
1818
\vdots \\
1919
\mathbf{Δu}(k+H_c-1) \end{bmatrix}
2020
```
21-
2221
This method generally more efficient for small control horizon ``H_c``, stable or mildly
23-
nonlinear plant model.
22+
nonlinear plant model/constraints.
2423
"""
2524
struct SingleShooting <: TranscriptionMethod end
2625

@@ -42,12 +41,47 @@ operating point ``\mathbf{x̂_{op}}`` (see [`augment_model`](@ref)):
4241
\vdots \\
4342
\mathbf{x̂}(k+H_p) - \mathbf{x̂_{op}} \end{bmatrix}
4443
```
45-
4644
This method is generally more efficient for large control horizon ``H_c``, unstable or
47-
highly nonlinear plant models.
45+
highly nonlinear plant models/constraints.
4846
"""
4947
struct MultipleShooting <: TranscriptionMethod end
5048

49+
50+
@doc raw"""
51+
init_ZtoΔU(estim::StateEstimator, transcription::TranscriptionMethod, Hp, Hc) -> P
52+
53+
Init decision variables to input increments over ``H_c`` conversion matrix `P`.
54+
55+
The conversion from the decision variables ``\mathbf{Z}`` to ``\mathbf{ΔU}``, the input
56+
increments over ``H_c``, is computed by:
57+
```math
58+
\mathbf{ΔU} = \mathbf{P} \mathbf{Z}
59+
```
60+
in which ``\mathbf{P} is defined in the Extended Help section.
61+
62+
# Extended Help
63+
!!! details "Extended Help"
64+
Following the decision variable definition of the [`TranscriptionMethod`](@ref), the
65+
conversion matrix ``\mathbf{P}``, we have:
66+
- ``\mathbf{P} = \mathbf{I}`` if `transcription isa SingleShooting`
67+
- ``\mathbf{P} = [\begin{smallmatrix}\mathbf{I} \mathbf{0} \end{smallmatrix}]`` if
68+
`transcription isa MultipleShooting`
69+
"""
70+
function init_ZtoU end
71+
72+
function init_ZtoΔU(
73+
estim::StateEstimator{NT}, transcription::SingleShooting, _ , Hc
74+
) where {NT<:Real}
75+
return Matrix{NT}(I, estim.model.nu*Hc, estim.model.nu*Hc)
76+
end
77+
78+
function init_ZtoΔU(
79+
estim::StateEstimator{NT}, transcription::MultipleShooting, Hp, Hc
80+
) where {NT<:Real}
81+
I_nu_Hc = Matrix{NT}(I, estim.model.nu*Hc, estim.model.nu*Hc)
82+
return [I_nu_Hc zeros(NT, estim.model.nu*Hc, estim.nx̂*Hp)]
83+
end
84+
5185
@doc raw"""
5286
init_ZtoU(estim, transcription, Hp, Hc) -> S, T
5387

0 commit comments

Comments
 (0)