Skip to content

Commit a5bdab5

Browse files
committed
doc: cleanup transcription method documentation
1 parent 6d9b296 commit a5bdab5

File tree

4 files changed

+60
-61
lines changed

4 files changed

+60
-61
lines changed

docs/src/public/predictive_control.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,9 +89,9 @@ NonLinMPC
8989
moveinput!
9090
```
9191

92-
## Transcription Methods
92+
## Direct Transcription Methods
9393

94-
### Transcription Method
94+
### TranscriptionMethod
9595

9696
```@docs
9797
ModelPredictiveControl.TranscriptionMethod

src/controller/execute.jl

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -113,22 +113,25 @@ julia> round.(getinfo(mpc)[:Ŷ], digits=3)
113113
```
114114
"""
115115
function getinfo(mpc::PredictiveController{NT}) where NT<:Real
116-
model = mpc.estim.model
116+
model, transcription = mpc.estim.model, mpc.transcription
117+
nΔŨ = mpc.Hc*model.nu + mpc.
117118
nŶe, nUe = (mpc.Hp+1)*model.ny, (mpc.Hp+1)*model.nu
119+
= mpc.
118120
info = Dict{Symbol, Any}()
119121
Ŷ0, u0, û0 = similar(mpc.Yop), similar(model.uop), similar(model.uop)
120122
Ŷs = similar(mpc.Yop)
121123
x̂0, x̂0next = similar(mpc.estim.x̂0), similar(mpc.estim.x̂0)
122124
Ȳ, Ū = similar(mpc.Yop), similar(mpc.Uop)
125+
ΔŨ = Vector{NT}(undef, nΔŨ)
123126
Ŷe, Ue = Vector{NT}(undef, nŶe), Vector{NT}(undef, nUe)
124-
Ŷ0, x̂0end = predict!(Ŷ0, x̂0, x̂0next, u0, û0, mpc, model, mpc.Z̃)
125-
Ŷe, Ue = extended_predictions!(Ŷe, Ue, Ū, mpc, model, Ŷ0, mpc.Z̃)
126-
J = obj_nonlinprog!(Ȳ, Ū, mpc, model, Ue, Ŷe, mpc.Z̃)
127+
Ŷ0, x̂0end = predict!(, x̂0, x̂0next, u0, û0, mpc, model, transcription, Z̃)
128+
ΔŨ, Ŷe, Ue = nonlinprog_vectors!(ΔŨ, Ŷe, Ue, Ū, mpc, Ŷ0, Z̃)
129+
J = obj_nonlinprog!(Ȳ, Ū, mpc, model, Ue, Ŷe, ΔŨ, Z̃)
127130
U, Ŷ = Ū, Ȳ
128131
U .= mul!(U, mpc.S̃, mpc.Z̃) .+ mpc.T_lastu
129132
Ŷ .= Ŷ0 .+ mpc.Yop
130133
predictstoch!(Ŷs, mpc, mpc.estim)
131-
info[:ΔU] = mpc.Z̃[1:mpc.Hc*model.nu]
134+
info[:ΔU] = Z̃[1:mpc.Hc*model.nu]
132135
info[] = mpc.== 1 ? mpc.Z̃[end] : zero(NT)
133136
info[:J] = J
134137
info[:U] = U
@@ -395,7 +398,7 @@ function `dot(x, A, x)` is a performant way of calculating `x'*A*x`. This method
395398
`Ŷe` and `Ue` arguments).
396399
"""
397400
function obj_nonlinprog!(
398-
Ȳ, Ū, mpc::PredictiveController, model::SimModel, Ue, Ŷe, ΔŨ, ::AbstractVector{NT}
401+
Ȳ, Ū, mpc::PredictiveController, model::SimModel, Ue, Ŷe, ΔŨ, ::AbstractVector{NT}
399402
) where NT<:Real
400403
nu, ny = model.nu, model.ny
401404
# --- output setpoint tracking term ---
@@ -716,7 +719,7 @@ function setmodel_controller!(mpc::PredictiveController, x̂op_old)
716719
JuMP.unregister(optim, :linconstrainteq)
717720
@constraint(optim, linconstrainteq, Aeq*Z̃var .== beq)
718721
# --- quadratic programming Hessian matrix ---
719-
= init_quadprog(model, mpc.weights, mpc.. mpc.P̃, mpc.S̃)
722+
= init_quadprog(model, mpc.weights, mpc., mpc.P̃, mpc.S̃)
720723
mpc.H̃ .=
721724
set_objective_hessian!(mpc, Z̃var)
722725
return nothing

src/controller/linmpc.jl

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -121,10 +121,10 @@ subject to [`setconstraint!`](@ref) bounds, and in which the weight matrices are
121121
\end{aligned}
122122
```
123123
Time-varying and non-diagonal weights are also supported. Modify the last block in
124-
``\mathbf{M}_{H_p}`` to specify a terminal weight. The content of the decision variable
125-
vector ``\mathbf{Z}`` depends on the chosen [`TranscriptionMethod`](@ref) (default to
126-
[`SingleShooting`](@ref)). The ``\mathbf{ΔU}`` includes the input increments
127-
``\mathbf{Δu}(k+j) = \mathbf{u}(k+j) - \mathbf{u}(k+j-1)`` from ``j=0`` to
124+
``\mathbf{M}_{H_p}`` to specify a terminal weight. The content of the decision vector
125+
``\mathbf{Z}`` depends on the chosen [`TranscriptionMethod`](@ref) (default to
126+
[`SingleShooting`](@ref), hence ``\mathbf{Z = ΔU}``). The ``\mathbf{ΔU}`` includes the input
127+
increments ``\mathbf{Δu}(k+j) = \mathbf{u}(k+j) - \mathbf{u}(k+j-1)`` from ``j=0`` to
128128
``H_c-1``, the ``\mathbf{Ŷ}`` vector, the output predictions ``\mathbf{ŷ}(k+j)`` from
129129
``j=1`` to ``H_p``, and the ``\mathbf{U}`` vector, the manipulated inputs ``\mathbf{u}(k+j)``
130130
from ``j=0`` to ``H_p-1``. The slack variable ``ϵ`` relaxes the constraints, as described

src/controller/transcription.jl

Lines changed: 44 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ The decision variable in the optimization problem is (excluding the slack ``ϵ``
1818
\vdots \\
1919
\mathbf{Δu}(k+H_c-1) \end{bmatrix}
2020
```
21-
This method generally more efficient for small control horizon ``H_c``, stable or mildly
21+
This method is generally more efficient for small control horizon ``H_c``, stable or mildly
2222
nonlinear plant model/constraints.
2323
"""
2424
struct SingleShooting <: TranscriptionMethod end
@@ -35,15 +35,17 @@ The decision variable is (excluding ``ϵ``):
3535
thus it also includes the predicted states, expressed as deviation vectors from the
3636
operating point ``\mathbf{x̂_{op}}`` (see [`augment_model`](@ref)):
3737
```math
38-
\mathbf{X̂_0} = \begin{bmatrix}
39-
\mathbf{x̂}(k+1) - \mathbf{x̂_{op}} \\
40-
\mathbf{x̂}(k+2) - \mathbf{x̂_{op}} \\
38+
\mathbf{X̂_0} = \mathbf{X̂ - X̂_{op}} \begin{bmatrix}
39+
\mathbf{x̂}_i(k+1) - \mathbf{x̂_{op}} \\
40+
\mathbf{x̂}_i(k+2) - \mathbf{x̂_{op}} \\
4141
\vdots \\
42-
\mathbf{x̂}(k+H_p) - \mathbf{x̂_{op}} \end{bmatrix}
42+
\mathbf{x̂}_i(k+H_p) - \mathbf{x̂_{op}} \end{bmatrix}
4343
```
44-
This method is generally more efficient for large control horizon ``H_c``, unstable or
45-
highly nonlinear plant models/constraints. Sparse optimizers like `OSQP.jl` or `Ipopt.jl`
46-
are recommended for large-scale problems.
44+
where ``\mathbf{x̂}_i(k+j)`` is the state prediction for time ``k+j``, estimated by the
45+
observer at time ``i=k`` or ``i=k-1`` depending on the `direct` flag. This transcription
46+
method is generally more efficient for large control horizon ``H_c``, unstable or highly
47+
nonlinear plant models/constraints. Sparse optimizers like `OSQP.jl` or `Ipopt.jl` are
48+
recommended for large-scale problems.
4749
"""
4850
struct MultipleShooting <: TranscriptionMethod end
4951

@@ -65,15 +67,15 @@ increments over ``H_c``, is computed by:
6567
```math
6668
\mathbf{ΔU} = \mathbf{P} \mathbf{Z}
6769
```
68-
in which ``\mathbf{P} is defined in the Extended Help section.
70+
in which ``\mathbf{P}`` is defined in the Extended Help section.
6971
7072
# Extended Help
7173
!!! details "Extended Help"
7274
Following the decision variable definition of the [`TranscriptionMethod`](@ref), the
7375
conversion matrix ``\mathbf{P}``, we have:
74-
- ``\mathbf{P} = \mathbf{I}`` if `transcription isa SingleShooting`
75-
- ``\mathbf{P} = [\begin{smallmatrix}\mathbf{I} \mathbf{0} \end{smallmatrix}]`` if
76-
`transcription isa MultipleShooting`
76+
- ``\mathbf{P} = \mathbf{I}`` if `transcription` is a [`SingleShooting`](@ref)
77+
- ``\mathbf{P} = [\begin{smallmatrix}\mathbf{I} & \mathbf{0} \end{smallmatrix}]`` if
78+
`transcription` is a [`MultipleShooting`](@ref)
7779
"""
7880
function init_ZtoΔU end
7981

@@ -92,21 +94,6 @@ function init_ZtoΔU(
9294
return P
9395
end
9496

95-
#=
96-
function init_Z̃toΔŨ(
97-
estim::StateEstimator{NT}, transcription::SingleShooting, Hp, Hc
98-
) where {NT<:Real}
99-
return Matrix{NT}(I, model.nu*Hc, model.nu*Hc)
100-
end
101-
102-
function init_Z̃toΔŨ(
103-
estim::StateEstimator{NT}, transcription::MultipleShooting, Hp, Hc
104-
) where {NT<:Real}
105-
I_nu_Hc = Matrix{NT}(I, model.nu*Hc, model.nu*Hc)
106-
return [I_nu_Hc zeros(NT, model.nu*Hc, model.nx̂*Hp)]
107-
end
108-
=#
109-
11097
@doc raw"""
11198
init_ZtoU(estim, transcription, Hp, Hc) -> S, T
11299
@@ -146,9 +133,9 @@ The ``\mathbf{S}`` and ``\mathbf{T}`` matrices are defined in the Extended Help
146133
\mathbf{I} \end{bmatrix}
147134
```
148135
and, depending on the transcription method, we have:
149-
- ``\mathbf{S} = \mathbf{S^†}`` if `transcription isa SingleShooting`
150-
- ``\mathbf{S} = [\begin{smallmatrix}\mathbf{S^†} \mathbf{0} \end{smallmatrix}]`` if
151-
`transcription isa MultipleShooting`
136+
- ``\mathbf{S} = \mathbf{S^†}`` if `transcription` is a [`SingleShooting`](@ref)
137+
- ``\mathbf{S} = [\begin{smallmatrix}\mathbf{S^†} & \mathbf{0} \end{smallmatrix}]`` if
138+
`transcription` is a [`MultipleShooting`](@ref)
152139
"""
153140
function init_ZtoU(
154141
estim::StateEstimator{NT}, transcription::TranscriptionMethod, Hp, Hc
@@ -343,7 +330,15 @@ end
343330
model::LinModel, estim, transcription::MultipleShooting, Hp, Hc
344331
) -> E, G, J, K, V, B, ex̂, gx̂, jx̂, kx̂, vx̂, bx̂
345332
346-
Construct the prediction matrices for [`LinModel`](@ref) and [`MultipleShooting`](@ref).
333+
Construct the prediction matrices for [`LinModel`](@ref) and [`MultipleShooting`](@ref).
334+
335+
They are defined in the Extended Help section.
336+
337+
# TODO: fill the next section
338+
339+
# Extended Help
340+
!!! details "Extended Help"
341+
The matrices are computed by:
347342
"""
348343
function init_predmat(
349344
model::LinModel, estim::StateEstimator{NT}, transcription::MultipleShooting, Hp, Hc
@@ -390,10 +385,12 @@ function init_predmat(
390385
return E, G, J, K, V, B, ex̂, gx̂, jx̂, kx̂, vx̂, bx̂
391386
end
392387

393-
"""
388+
@doc raw"""
394389
init_predmat(model::SimModel, estim, transcription::MultipleShooting, Hp, Hc)
395390
396391
Return empty matrices except `ex̂` for [`SimModel`](@ref) and [`MultipleShooting`](@ref).
392+
393+
The matrix is ``\mathbf{ex̂} = [\begin{smallmatrix}\mathbf{0} & \mathbf{I}\end{smallmatrix}]``.
397394
"""
398395
function init_predmat(
399396
model::SimModel, estim::StateEstimator{NT}, transcription::MultipleShooting, Hp, Hc
@@ -456,7 +453,6 @@ matrices ``\mathbf{E_ŝ, G_ŝ, J_ŝ, K_ŝ, V_ŝ, B_ŝ}`` are defined in th
456453
\mathbf{E_ŝ} &= \begin{bmatrix}
457454
\mathbf{B̂_u} & \mathbf{0} & \cdots & \mathbf{0} & -\mathbf{I} & \mathbf{0} & \cdots & \mathbf{0} \\
458455
\mathbf{B̂_u} & \mathbf{B̂_u} & \cdots & \mathbf{0} & \mathbf{Â} & -\mathbf{I} & \cdots & \mathbf{0} \\
459-
\mathbf{B̂_u} & \mathbf{B̂_u} & \cdots & \mathbf{0} & \mathbf{0} & \mathbf{Â} & \cdots & \mathbf{0} \\
460456
\vdots & \vdots & \ddots & \vdots & \vdots & \vdots & \ddots & \vdots \\
461457
\mathbf{B̂_u} & \mathbf{B̂_u} & \cdots & \mathbf{B̂_u} & \mathbf{0} & \mathbf{0} & \cdots & -\mathbf{I} \end{bmatrix} \\
462458
\mathbf{G_ŝ} &= \begin{bmatrix}
@@ -556,16 +552,16 @@ If supported by `mpc.optim`, it warm-starts the solver at:
556552
```math
557553
\mathbf{ΔŨ} =
558554
\begin{bmatrix}
559-
\mathbf{Δu}_{k-1}(k+0) \\
560-
\mathbf{Δu}_{k-1}(k+1) \\
555+
\mathbf{Δu}(k+0|k-1) \\
556+
\mathbf{Δu}(k+1|k-1) \\
561557
\vdots \\
562-
\mathbf{Δu}_{k-1}(k+H_c-2) \\
558+
\mathbf{Δu}(k+H_c-2|k-1) \\
563559
\mathbf{0} \\
564-
ϵ_{k-1}
560+
ϵ(k-1)
565561
\end{bmatrix}
566562
```
567-
where ``\mathbf{Δu}_{k-1}(k+j)`` is the input increment for time ``k+j`` computed at the
568-
last control period ``k-1``, and ``ϵ_{k-1}``, the slack variable of the last control period.
563+
where ``\mathbf{Δu}(k+j|k-1)`` is the input increment for time ``k+j`` computed at the
564+
last control period ``k-1``, and ``ϵ(k-1)``, the slack variable of the last control period.
569565
"""
570566
function set_warmstart!(mpc::PredictiveController, transcription::SingleShooting, Z̃var)
571567
nu, Hc, Z̃0 = mpc.estim.model.nu, mpc.Hc, mpc.buffer.
@@ -587,20 +583,20 @@ It warm-starts the solver at:
587583
```math
588584
\mathbf{ΔŨ} =
589585
\begin{bmatrix}
590-
\mathbf{Δu}_{k-1}(k+0) \\
591-
\mathbf{Δu}_{k-1}(k+1) \\
586+
\mathbf{Δu}(k+0|k-1) \\
587+
\mathbf{Δu}(k+1|k-1) \\
592588
\vdots \\
593-
\mathbf{Δu}_{k-1}(k+H_c-1) \\
589+
\mathbf{Δu}(k+H_c-2|k-1) \\
594590
\mathbf{0} \\
595-
\mathbf{x̂_0}_{k-1}(k+1) \\
596-
\mathbf{x̂_0}_{k-1}(k+2) \\
591+
\mathbf{x̂_0}(k+1|k-1) \\
592+
\mathbf{x̂_0}(k+2|k-1) \\
597593
\vdots \\
598-
\mathbf{x̂_0}_{k-1}(k+H_p-1) \\
599-
\mathbf{x̂_0}_{k-1}(k+H_p-1) \\
600-
ϵ_{k-1}
594+
\mathbf{x̂_0}(k+H_p-1|k-1) \\
595+
\mathbf{x̂_0}(k+H_p-1|k-1) \\
596+
ϵ(k-1)
601597
\end{bmatrix}
602598
```
603-
where ``\mathbf{x̂_0}_{k-1}(k+j)`` is the predicted state for time ``k+j`` computed at the
599+
where ``\mathbf{x̂_0}(k+j|k-1)`` is the predicted state for time ``k+j`` computed at the
604600
last control period ``k-1``, expressed as a deviation from the operating point ``x̂_{op}``.
605601
"""
606602
function set_warmstart!(mpc::PredictiveController, transcription::MultipleShooting, Z̃var)

0 commit comments

Comments
 (0)