diff --git a/dev/func_index/index.html b/dev/func_index/index.html index cc80aa2e7..ab70cfc29 100644 --- a/dev/func_index/index.html +++ b/dev/func_index/index.html @@ -1,2 +1,2 @@ -Index · ModelPredictiveControl.jl

Index

+Index · ModelPredictiveControl.jl

Index

diff --git a/dev/index.html b/dev/index.html index a175926a0..af3e67970 100644 --- a/dev/index.html +++ b/dev/index.html @@ -1,2 +1,2 @@ -Home · ModelPredictiveControl.jl

ModelPredictiveControl.jl

A model predictive control package for Julia.

The package depends on ControlSystemsBase.jl for the linear systems and JuMP.jl for the solving.

The objective is to provide a simple and clear framework to quickly design model predictive controllers (MPCs) in Julia, while preserving the flexibility for advanced real-time optimization. Modern MPCs based on closed-loop state estimators are the main focus of the package, but classical approaches that rely on internal models are also possible. The JuMP.jl interface allows to easily test different solvers if the performance of the default settings is not satisfactory.

The documentation is divided in two parts:

  • Manual — This section includes step-by-step guides to design predictive controllers on multiple case studies.
  • Functions — Documentation of methods and types exported by the package. The "Internals" section provides implementation details of functions that are not exported.

Manual

Functions: Public

Functions: Internals

+Home · ModelPredictiveControl.jl

ModelPredictiveControl.jl

A model predictive control package for Julia.

The package depends on ControlSystemsBase.jl for the linear systems and JuMP.jl for the solving.

The objective is to provide a simple and clear framework to quickly design model predictive controllers (MPCs) in Julia, while preserving the flexibility for advanced real-time optimization. Modern MPCs based on closed-loop state estimators are the main focus of the package, but classical approaches that rely on internal models are also possible. The JuMP.jl interface allows to easily test different solvers if the performance of the default settings is not satisfactory.

The documentation is divided in two parts:

  • Manual — This section includes step-by-step guides to design predictive controllers on multiple case studies.
  • Functions — Documentation of methods and types exported by the package. The "Internals" section provides implementation details of functions that are not exported.

Manual

Functions: Public

Functions: Internals

diff --git a/dev/internals/predictive_control/index.html b/dev/internals/predictive_control/index.html index e7b4f021a..df48acbc0 100644 --- a/dev/internals/predictive_control/index.html +++ b/dev/internals/predictive_control/index.html @@ -38,32 +38,32 @@ \vdots \\ \mathbf{W}_{H_p-1} \end{bmatrix} -\end{aligned}\]

Note

Stochastic predictions $\mathbf{Ŷ_s}$ are calculated separately (see init_stochpred) and added to the $\mathbf{F}$ matrix to support internal model structure and reduce NonLinMPC computational costs. That is also why the prediction matrices are built on $\mathbf{A, B_u, C, B_d, D_d}$ instead of the augmented model $\mathbf{Â, B̂_u, Ĉ, B̂_d, D̂_d}$.

source

Return empty matrices if model is not a LinModel

source
ModelPredictiveControl.init_ΔUtoUFunction
init_ΔUtoU(nu, Hp, Hc, C, c_Umin, c_Umax)

Init manipulated input increments to inputs conversion matrices.

The conversion from the input increments $\mathbf{ΔU}$ to manipulated inputs over $H_p$ and $H_c$ are calculated by:

\[\begin{aligned} +\end{aligned}\]

Note

Stochastic predictions $\mathbf{Ŷ_s}$ are calculated separately (see init_stochpred) and added to the $\mathbf{F}$ matrix to support internal model structure and reduce NonLinMPC computational costs. That is also why the prediction matrices are built on $\mathbf{A, B_u, C, B_d, D_d}$ instead of the augmented model $\mathbf{Â, B̂_u, Ĉ, B̂_d, D̂_d}$.

source

Return empty matrices if model is not a LinModel

source
ModelPredictiveControl.init_ΔUtoUFunction
init_ΔUtoU(nu, Hp, Hc, C, c_Umin, c_Umax)

Init manipulated input increments to inputs conversion matrices.

The conversion from the input increments $\mathbf{ΔU}$ to manipulated inputs over $H_p$ and $H_c$ are calculated by:

\[\begin{aligned} \mathbf{U} = \mathbf{U}_{H_p} &= \mathbf{S}_{H_p} \mathbf{ΔU} + \mathbf{T}_{H_p} \mathbf{u}(k-1) \\ \mathbf{U}_{H_c} &= \mathbf{S}_{H_c} \mathbf{ΔU} + \mathbf{T}_{H_c} \mathbf{u}(k-1) -\end{aligned}\]

source
ModelPredictiveControl.init_quadprogFunction
init_quadprog(model::LinModel, Ẽ, S_Hp, M_Hp, N_Hc, L_Hp)

Init the quadratic programming optimization matrix and .

The matrices appear in the quadratic general form :

\[ J = \min_{\mathbf{ΔŨ}} \frac{1}{2}\mathbf{(ΔŨ)'P̃(ΔŨ)} + \mathbf{q̃'(ΔŨ)} + p \]

$\mathbf{P̃}$ is constant if the model and weights are linear and time invariant (LTI). The vector $\mathbf{q̃}$ and scalar $p$ need recalculation each control period $k$ (see initpred! method). $p$ does not impact the minima position. It is thus useless at optimization but required to evaluate the minimal $J$ value.

source

Return empty matrices if model is not a LinModel.

source
ModelPredictiveControl.init_stochpredFunction
init_stochpred(estim::StateEstimator, Hp)

Init the stochastic prediction matrix Ks from estim estimator for predictive control.

$\mathbf{K_s}$ is the prediction matrix of the stochastic model (composed exclusively of integrators):

\[ \mathbf{Ŷ_s} = \mathbf{K_s x̂_s}(k)\]

The stochastic predictions $\mathbf{Ŷ_s}$ are the integrator outputs from $k+1$ to $k+H_p$. $\mathbf{x̂_s}(k)$ is extracted from current estimates $\mathbf{x̂}_{k-1}(k)$ with getestimates!. The method also returns an empty $\mathbf{P_s}$ matrix, since it is useless except for InternalModel estimators.

source
init_stochpred(estim::InternalModel, Hp)

Init the stochastic prediction matrices for InternalModel.

Ks and Ps matrices are defined as:

\[ \mathbf{Ŷ_s} = \mathbf{K_s x̂_s}(k) + \mathbf{P_s ŷ_s}(k)\]

Current stochastic outputs $\mathbf{ŷ_s}(k)$ comprises the measured outputs $\mathbf{ŷ_s^m}(k) = \mathbf{y^m}(k) - \mathbf{ŷ_d^m}(k)$ and unmeasured $\mathbf{ŷ_s^u(k) = 0}$. See [2].

source
ModelPredictiveControl.init_linconstraintFunction
init_linconstraint(model::LinModel, 
+\end{aligned}\]

source
ModelPredictiveControl.init_quadprogFunction
init_quadprog(model::LinModel, Ẽ, S_Hp, M_Hp, N_Hc, L_Hp)

Init the quadratic programming optimization matrix and .

The matrices appear in the quadratic general form :

\[ J = \min_{\mathbf{ΔŨ}} \frac{1}{2}\mathbf{(ΔŨ)'P̃(ΔŨ)} + \mathbf{q̃'(ΔŨ)} + p \]

$\mathbf{P̃}$ is constant if the model and weights are linear and time invariant (LTI). The vector $\mathbf{q̃}$ and scalar $p$ need recalculation each control period $k$ (see initpred! method). $p$ does not impact the minima position. It is thus useless at optimization but required to evaluate the minimal $J$ value.

source

Return empty matrices if model is not a LinModel.

source
ModelPredictiveControl.init_stochpredFunction
init_stochpred(estim::StateEstimator, Hp)

Init the stochastic prediction matrix Ks from estim estimator for predictive control.

$\mathbf{K_s}$ is the prediction matrix of the stochastic model (composed exclusively of integrators):

\[ \mathbf{Ŷ_s} = \mathbf{K_s x̂_s}(k)\]

The stochastic predictions $\mathbf{Ŷ_s}$ are the integrator outputs from $k+1$ to $k+H_p$. $\mathbf{x̂_s}(k)$ is extracted from current estimates $\mathbf{x̂}_{k-1}(k)$ with getestimates!. The method also returns an empty $\mathbf{P_s}$ matrix, since it is useless except for InternalModel estimators.

source
init_stochpred(estim::InternalModel, Hp)

Init the stochastic prediction matrices for InternalModel.

Ks and Ps matrices are defined as:

\[ \mathbf{Ŷ_s} = \mathbf{K_s x̂_s}(k) + \mathbf{P_s ŷ_s}(k)\]

Current stochastic outputs $\mathbf{ŷ_s}(k)$ comprises the measured outputs $\mathbf{ŷ_s^m}(k) = \mathbf{y^m}(k) - \mathbf{ŷ_d^m}(k)$ and unmeasured $\mathbf{ŷ_s^u(k) = 0}$. See [2].

source
ModelPredictiveControl.init_linconstraintFunction
init_linconstraint(model::LinModel, 
     A_Umin, A_Umax, A_ΔŨmin, A_ΔŨmax, A_Ŷmin, A_Ŷmax,
     i_Umin, i_Umax, i_ΔŨmin, i_ΔŨmax, i_Ŷmin, i_Ŷmax
-)

Init A, b and i_b for the linear inequality constraints ($\mathbf{A ΔŨ ≤ b}$).

i_b is a BitVector including the indices of $\mathbf{b}$ that are finite numbers.

source

Init values without predicted output constraints if model is not a LinModel.

source

Constraint Relaxation

ModelPredictiveControl.relaxUFunction
relaxU(C, c_Umin, c_Umax, S_Hp, S_Hc)

Augment manipulated inputs constraints with slack variable ϵ for softening.

Denoting the input increments augmented with the slack variable $\mathbf{ΔŨ} = [\begin{smallmatrix} \mathbf{ΔU} \\ ϵ \end{smallmatrix}]$, it returns the augmented conversion matrix $\mathbf{S̃}_{H_p}$, similar to the one described at init_ΔUtoU. It also returns the $\mathbf{A}$ matrices for the inequality constraints:

\[\begin{bmatrix} +)

Init A, b and i_b for the linear inequality constraints ($\mathbf{A ΔŨ ≤ b}$).

i_b is a BitVector including the indices of $\mathbf{b}$ that are finite numbers.

source

Init values without predicted output constraints if model is not a LinModel.

source

Constraint Relaxation

ModelPredictiveControl.relaxUFunction
relaxU(C, c_Umin, c_Umax, S_Hp, S_Hc)

Augment manipulated inputs constraints with slack variable ϵ for softening.

Denoting the input increments augmented with the slack variable $\mathbf{ΔŨ} = [\begin{smallmatrix} \mathbf{ΔU} \\ ϵ \end{smallmatrix}]$, it returns the augmented conversion matrix $\mathbf{S̃}_{H_p}$, similar to the one described at init_ΔUtoU. It also returns the $\mathbf{A}$ matrices for the inequality constraints:

\[\begin{bmatrix} \mathbf{A_{U_{min}}} \\ \mathbf{A_{U_{max}}} \end{bmatrix} \mathbf{ΔŨ} ≤ \begin{bmatrix} - \mathbf{U_{min}} + \mathbf{T}_{H_c} \mathbf{u}(k-1) \\ + \mathbf{U_{max}} - \mathbf{T}_{H_c} \mathbf{u}(k-1) -\end{bmatrix}\]

source
ModelPredictiveControl.relaxΔUFunction
relaxΔU(C, c_ΔUmin, c_ΔUmax, ΔUmin, ΔUmax, N_Hc)

Augment input increments constraints with slack variable ϵ for softening.

Denoting the input increments augmented with the slack variable $\mathbf{ΔŨ} = [\begin{smallmatrix} \mathbf{ΔU} \\ ϵ \end{smallmatrix}]$, it returns the augmented input increment weights $\mathbf{Ñ}_{H_c}$ (that incorporate $C$). It also returns the augmented constraints $\mathbf{ΔŨ_{min}}$ and $\mathbf{ΔŨ_{max}}$ and the $\mathbf{A}$ matrices for the inequality constraints:

\[\begin{bmatrix} +\end{bmatrix}\]

source
ModelPredictiveControl.relaxΔUFunction
relaxΔU(C, c_ΔUmin, c_ΔUmax, ΔUmin, ΔUmax, N_Hc)

Augment input increments constraints with slack variable ϵ for softening.

Denoting the input increments augmented with the slack variable $\mathbf{ΔŨ} = [\begin{smallmatrix} \mathbf{ΔU} \\ ϵ \end{smallmatrix}]$, it returns the augmented input increment weights $\mathbf{Ñ}_{H_c}$ (that incorporate $C$). It also returns the augmented constraints $\mathbf{ΔŨ_{min}}$ and $\mathbf{ΔŨ_{max}}$ and the $\mathbf{A}$ matrices for the inequality constraints:

\[\begin{bmatrix} \mathbf{A_{ΔŨ_{min}}} \\ \mathbf{A_{ΔŨ_{max}}} \end{bmatrix} \mathbf{ΔŨ} ≤ \begin{bmatrix} - \mathbf{ΔŨ_{min}} \\ + \mathbf{ΔŨ_{max}} -\end{bmatrix}\]

source
ModelPredictiveControl.relaxŶFunction
relaxŶ(::LinModel, C, c_Ŷmin, c_Ŷmax, E)

Augment linear output prediction constraints with slack variable ϵ for softening.

Denoting the input increments augmented with the slack variable $\mathbf{ΔŨ} = [\begin{smallmatrix} \mathbf{ΔU} \\ ϵ \end{smallmatrix}]$, it returns the $\mathbf{Ẽ}$ matrix that appears in the linear model prediction equation $\mathbf{Ŷ = Ẽ ΔŨ + F}$, and the $\mathbf{A}$ matrices for the inequality constraints:

\[\begin{bmatrix} +\end{bmatrix}\]

source
ModelPredictiveControl.relaxŶFunction
relaxŶ(::LinModel, C, c_Ŷmin, c_Ŷmax, E)

Augment linear output prediction constraints with slack variable ϵ for softening.

Denoting the input increments augmented with the slack variable $\mathbf{ΔŨ} = [\begin{smallmatrix} \mathbf{ΔU} \\ ϵ \end{smallmatrix}]$, it returns the $\mathbf{Ẽ}$ matrix that appears in the linear model prediction equation $\mathbf{Ŷ = Ẽ ΔŨ + F}$, and the $\mathbf{A}$ matrices for the inequality constraints:

\[\begin{bmatrix} \mathbf{A_{Ŷ_{min}}} \\ \mathbf{A_{Ŷ_{max}}} \end{bmatrix} \mathbf{ΔŨ} ≤ \begin{bmatrix} - \mathbf{Ŷ_{min}} + \mathbf{F} \\ + \mathbf{Ŷ_{max}} - \mathbf{F} -\end{bmatrix}\]

source

Return empty matrices if model is not a LinModel

source

Get Estimates

ModelPredictiveControl.getestimates!Function
getestimates!(mpc::PredictiveController, estim::StateEstimator)

Get estimator output and split into the deterministic x̂d and stochastic x̂s states.

source
getestimates!(mpc::PredictiveController, estim::InternalModel)

Get the internal model deterministic estim.x̂d and stochastic estim.x̂s states.

source

Predictions

ModelPredictiveControl.initpred!Function
initpred!(mpc, model::LinModel, d, D̂, R̂y)

Init linear model prediction matrices F, and p.

See init_deterpred and init_quadprog for the definition of the matrices.

source
initpred!(mpc::PredictiveController, model::SimModel, d, D̂, R̂y)

Init d0 and D̂0 matrices when model is not a LinModel.

d0 and D̂0 are the measured disturbances and its predictions without the operating points $\mathbf{d_{op}}$.

source

Constraints

ModelPredictiveControl.linconstraint!Function
linconstraint!(mpc::PredictiveController, model::LinModel)

Set b vector for the linear model inequality constraints ($\mathbf{A ΔŨ ≤ b}$).

source

Set b excluding predicted output constraints when model is not a LinModel.

source
+\end{bmatrix}\]

source

Return empty matrices if model is not a LinModel

source

Get Estimates

ModelPredictiveControl.getestimates!Function
getestimates!(mpc::PredictiveController, estim::StateEstimator)

Get estimator output and split into the deterministic x̂d and stochastic x̂s states.

source
getestimates!(mpc::PredictiveController, estim::InternalModel)

Get the internal model deterministic estim.x̂d and stochastic estim.x̂s states.

source

Predictions

ModelPredictiveControl.initpred!Function
initpred!(mpc, model::LinModel, d, D̂, R̂y)

Init linear model prediction matrices F, and p.

See init_deterpred and init_quadprog for the definition of the matrices.

source
initpred!(mpc::PredictiveController, model::SimModel, d, D̂, R̂y)

Init d0 and D̂0 matrices when model is not a LinModel.

d0 and D̂0 are the measured disturbances and its predictions without the operating points $\mathbf{d_{op}}$.

source

Constraints

ModelPredictiveControl.linconstraint!Function
linconstraint!(mpc::PredictiveController, model::LinModel)

Set b vector for the linear model inequality constraints ($\mathbf{A ΔŨ ≤ b}$).

source

Set b excluding predicted output constraints when model is not a LinModel.

source
diff --git a/dev/internals/sim_model/index.html b/dev/internals/sim_model/index.html index d8a217dee..596bf0c2f 100644 --- a/dev/internals/sim_model/index.html +++ b/dev/internals/sim_model/index.html @@ -1,2 +1,2 @@ -Plant Models · ModelPredictiveControl.jl

Functions: SimModel Internals

ModelPredictiveControl.steadystateFunction
steadystate(model::LinModel, u, d=Float64[])

Evaluate the steady-state vector when model is a LinModel.

Omitting the operating points, the method evaluates the equilibrium $\mathbf{x}(∞)$ from:

\[ \mathbf{x}(∞) = \mathbf{(I - A)^{-1}(B_u u + B_d d)}\]

with the manipulated inputs held constant at $\mathbf{u}$ and, the measured disturbances, at $\mathbf{d}$. The Moore-Penrose pseudo-inverse computes $\mathbf{(I - A)^{-1}}$ to support integrating model (integrator states will be 0).

source
+Plant Models · ModelPredictiveControl.jl

Functions: SimModel Internals

ModelPredictiveControl.steadystateFunction
steadystate(model::LinModel, u, d=Float64[])

Evaluate the steady-state vector when model is a LinModel.

Omitting the operating points, the method evaluates the equilibrium $\mathbf{x}(∞)$ from:

\[ \mathbf{x}(∞) = \mathbf{(I - A)^{-1}(B_u u + B_d d)}\]

with the manipulated inputs held constant at $\mathbf{u}$ and, the measured disturbances, at $\mathbf{d}$. The Moore-Penrose pseudo-inverse computes $\mathbf{(I - A)^{-1}}$ to support integrating model (integrator states will be 0).

source
diff --git a/dev/internals/state_estim/index.html b/dev/internals/state_estim/index.html index dc5578055..56dd9eec8 100644 --- a/dev/internals/state_estim/index.html +++ b/dev/internals/state_estim/index.html @@ -2,24 +2,24 @@ State Estimators · ModelPredictiveControl.jl

Functions: StateEstimator Internals

Estimator Initialization

ModelPredictiveControl.init_estimstochFunction
init_estimstoch(i_ym, nint_ym::Vector{Int})

Calc stochastic model matrices from output integrators specifications for state estimation.

For closed-loop state estimators. nint_ym is a vector providing how many integrator should be added for each measured output $\mathbf{y^m}$. The argument generates the Asm and Csm matrices:

\[\begin{aligned} \mathbf{x_s}(k+1) &= \mathbf{A_s^m x_s}(k) + \mathbf{B_s^m e}(k) \\ \mathbf{y_s^m}(k) &= \mathbf{C_s^m x_s}(k) -\end{aligned}\]

where $\mathbf{e}(k)$ is a conceptual and unknown zero mean white noise. $\mathbf{B_s^m}$ is not used for closed-loop state estimators thus ignored.

source
ModelPredictiveControl.augment_modelFunction
augment_model(model::LinModel, As, Cs)

Augment LinModel state-space matrices with the stochastic ones As and Cs.

If $\mathbf{x}$ are model.x states, and $\mathbf{x_s}$, the states defined at init_estimstoch, we define an augmented state vector $\mathbf{x̂} = [ \begin{smallmatrix} \mathbf{x} \\ \mathbf{x_s} \end{smallmatrix} ]$. The method returns the augmented matrices , B̂u, , B̂d and D̂d:

\[\begin{aligned} +\end{aligned}\]

where $\mathbf{e}(k)$ is a conceptual and unknown zero mean white noise. $\mathbf{B_s^m}$ is not used for closed-loop state estimators thus ignored.

source
ModelPredictiveControl.augment_modelFunction
augment_model(model::LinModel, As, Cs)

Augment LinModel state-space matrices with the stochastic ones As and Cs.

If $\mathbf{x}$ are model.x states, and $\mathbf{x_s}$, the states defined at init_estimstoch, we define an augmented state vector $\mathbf{x̂} = [ \begin{smallmatrix} \mathbf{x} \\ \mathbf{x_s} \end{smallmatrix} ]$. The method returns the augmented matrices , B̂u, , B̂d and D̂d:

\[\begin{aligned} \mathbf{x̂}(k+1) &= \mathbf{Â x̂}(k) + \mathbf{B̂_u u}(k) + \mathbf{B̂_d d}(k) \\ \mathbf{ŷ}(k) &= \mathbf{Ĉ x̂}(k) + \mathbf{D̂_d d}(k) -\end{aligned}\]

source
ModelPredictiveControl.init_ukfFunction
init_ukf(nx̂, α, β, κ)

Compute the UnscentedKalmanFilter constants from $α, β$ and $κ$.

With $n_\mathbf{x̂}$ elements in the state vector $\mathbf{x̂}$ and $n_σ = 2 n_\mathbf{x̂} + 1$ sigma points, the scaling factor applied on standard deviation matrices $\sqrt{\mathbf{P̂}}$ is:

\[ γ = α \sqrt{ n_\mathbf{x̂} + κ }\]

The weight vector $(n_σ × 1)$ for the mean and the weight matrix $(n_σ × n_σ)$ for the covariance are respectively:

\[\begin{aligned} +\end{aligned}\]

source
ModelPredictiveControl.init_ukfFunction
init_ukf(nx̂, α, β, κ)

Compute the UnscentedKalmanFilter constants from $α, β$ and $κ$.

With $n_\mathbf{x̂}$ elements in the state vector $\mathbf{x̂}$ and $n_σ = 2 n_\mathbf{x̂} + 1$ sigma points, the scaling factor applied on standard deviation matrices $\sqrt{\mathbf{P̂}}$ is:

\[ γ = α \sqrt{ n_\mathbf{x̂} + κ }\]

The weight vector $(n_σ × 1)$ for the mean and the weight matrix $(n_σ × n_σ)$ for the covariance are respectively:

\[\begin{aligned} \mathbf{m̂} &= \begin{bmatrix} 1 - \tfrac{n_\mathbf{x̂}}{γ^2} & \tfrac{1}{2γ^2} & \tfrac{1}{2γ^2} & \cdots & \tfrac{1}{2γ^2} \end{bmatrix}' \\ \mathbf{Ŝ} &= \mathrm{diag}\big( 2 - α^2 + β - \tfrac{n_\mathbf{x̂}}{γ^2} \:,\; \tfrac{1}{2γ^2} \:,\; \tfrac{1}{2γ^2} \:,\; \cdots \:,\; \tfrac{1}{2γ^2} \big) -\end{aligned}\]

See update_estimate!(::UnscentedKalmanFilter) for other details.

source
ModelPredictiveControl.init_internalmodelFunction
init_internalmodel(As, Bs, Cs, Ds)

Calc stochastic model update matrices Âs and B̂s for InternalModel estimator.

As, Bs, Cs and Ds are the stochastic model matrices :

\[\begin{aligned} \mathbf{x_s}(k+1) &= \mathbf{A_s x_s}(k) + \mathbf{B_s e}(k) \\ \mathbf{y_s}(k) &= \mathbf{C_s x_s}(k) + \mathbf{D_s e}(k) \end{aligned}\]

where $\mathbf{e}(k)$ is conceptual and unknown zero mean white noise. Its optimal estimation is $\mathbf{ê=0}$, the expected value. Thus, the Âs and B̂s matrices that optimally update the stochastic estimate $\mathbf{x̂_s}$ are:

\[\begin{aligned} \mathbf{x̂_s}(k+1) &= \mathbf{(A_s - B_s D_s^{-1} C_s) x̂_s}(k) + \mathbf{(B_s D_s^{-1}) ŷ_s}(k) \\ &= \mathbf{Â_s x̂_s}(k) + \mathbf{B̂_s ŷ_s}(k) -\end{aligned}\]

with current stochastic outputs estimation $\mathbf{ŷ_s}(k)$, composed of the measured $\mathbf{ŷ_s^m}(k) = \mathbf{y^m}(k) - \mathbf{ŷ_d^m}(k)$ and unmeasured $\mathbf{ŷ_s^u = 0}$ outputs. See [1].

source

Augmented Model

ModelPredictiveControl.f̂Function
f̂(estim::StateEstimator, x̂, u, d)

State function $\mathbf{f̂}$ of the augmented model.

By introducing an augmented state vector $\mathbf{x̂}$ like in augment_model, the function returns the next state of the augmented model, defined as:

\[\begin{aligned} +\end{aligned}\]

with current stochastic outputs estimation $\mathbf{ŷ_s}(k)$, composed of the measured $\mathbf{ŷ_s^m}(k) = \mathbf{y^m}(k) - \mathbf{ŷ_d^m}(k)$ and unmeasured $\mathbf{ŷ_s^u = 0}$ outputs. See [1].

source

Augmented Model

ModelPredictiveControl.f̂Function
f̂(estim::StateEstimator, x̂, u, d)

State function $\mathbf{f̂}$ of the augmented model.

By introducing an augmented state vector $\mathbf{x̂}$ like in augment_model, the function returns the next state of the augmented model, defined as:

\[\begin{aligned} \mathbf{x̂}(k+1) &= \mathbf{f̂}\Big(\mathbf{x̂}(k), \mathbf{u}(k), \mathbf{d}(k)\Big) \\ \mathbf{ŷ}(k) &= \mathbf{ĥ}\Big(\mathbf{x̂}(k), \mathbf{d}(k)\Big) -\end{aligned}\]

source

Remove Operating Points

ModelPredictiveControl.remove_op!Function
remove_op!(estim::StateEstimator, u, d, ym)

Remove operating points on inputs u, measured outputs ym and disturbances d.

Also store current inputs without operating points u0 in estim.lastu0. This field is used for PredictiveController computations.

source

Update Estimate

Info

All these methods assume that the operating points are already removed in u, ym and d arguments. Strickly speaking, the arguments should be called u0, ym0 and d0, following setop! notation. The 0 is dropped to simplify the notation.

ModelPredictiveControl.update_estimate!Function
update_estimate!(estim::SteadyKalmanFilter, u, ym, d)

Update estim.x̂ estimate with current inputs u, measured outputs ym and dist. d.

The SteadyKalmanFilter updates it with the precomputed Kalman gain $\mathbf{K}$:

\[\mathbf{x̂}_{k}(k+1) = \mathbf{Â x̂}_{k-1}(k) + \mathbf{B̂_u u}(k) + \mathbf{B̂_d d}(k) - + \mathbf{K}[\mathbf{y^m}(k) - \mathbf{Ĉ^m x̂}_{k-1}(k) - \mathbf{D̂_d^m d}(k)]\]

source
update_estimate!(estim::KalmanFilter, u, ym, d)

Update KalmanFilter state estim.x̂ and estimation error covariance estim.P̂.

It implements the time-varying Kalman Filter in its predictor (observer) form :

\[\begin{aligned} +\end{aligned}\]

source

Remove Operating Points

ModelPredictiveControl.remove_op!Function
remove_op!(estim::StateEstimator, u, d, ym)

Remove operating points on inputs u, measured outputs ym and disturbances d.

Also store current inputs without operating points u0 in estim.lastu0. This field is used for PredictiveController computations.

source

Update Estimate

Info

All these methods assume that the operating points are already removed in u, ym and d arguments. Strickly speaking, the arguments should be called u0, ym0 and d0, following setop! notation. The 0 is dropped to simplify the notation.

ModelPredictiveControl.update_estimate!Function
update_estimate!(estim::SteadyKalmanFilter, u, ym, d)

Update estim.x̂ estimate with current inputs u, measured outputs ym and dist. d.

The SteadyKalmanFilter updates it with the precomputed Kalman gain $\mathbf{K}$:

\[\mathbf{x̂}_{k}(k+1) = \mathbf{Â x̂}_{k-1}(k) + \mathbf{B̂_u u}(k) + \mathbf{B̂_d d}(k) + + \mathbf{K}[\mathbf{y^m}(k) - \mathbf{Ĉ^m x̂}_{k-1}(k) - \mathbf{D̂_d^m d}(k)]\]

source
update_estimate!(estim::KalmanFilter, u, ym, d)

Update KalmanFilter state estim.x̂ and estimation error covariance estim.P̂.

It implements the time-varying Kalman Filter in its predictor (observer) form :

\[\begin{aligned} \mathbf{M}(k) &= \mathbf{P̂}_{k-1}(k)\mathbf{Ĉ^m}' [\mathbf{Ĉ^m P̂}_{k-1}(k)\mathbf{Ĉ^m + R̂}]^{-1} \\ \mathbf{K}(k) &= \mathbf{Â M(k)} \\ @@ -28,7 +28,7 @@ + \mathbf{K}(k)[\mathbf{y^m}(k) - \mathbf{ŷ^m}(k)] \\ \mathbf{P̂}_{k}(k+1) &= \mathbf{Â}[\mathbf{P̂}_{k-1}(k) - \mathbf{M}(k)\mathbf{Ĉ^m P̂}_{k-1}(k)]\mathbf{Â}' + \mathbf{Q̂} -\end{aligned}\]

based on the process model described in SteadyKalmanFilter. The notation $\mathbf{x̂}_{k-1}(k)$ refers to the state for the current time $k$ estimated at the last control period $k-1$. See [2] for details.

source
update_estimate!(estim::UnscentedKalmanFilter, u, ym, d)

Update UnscentedKalmanFilter state estim.x̂ and covariance estimate estim.P̂.

It implements the unscented Kalman Filter in its predictor (observer) form, based on the generalized unscented transform[3]. See init_ukf for the definition of the constants $\mathbf{m̂, Ŝ}$ and $γ$.

Denoting $\mathbf{x̂}_{k-1}(k)$ as the state for the current time $k$ estimated at the last period $k-1$, $\mathbf{0}$, a null vector, $n_σ = 2 n_\mathbf{x̂} + 1$, the number of sigma points, and $\mathbf{X̂}_{k-1}^j(k)$, the vector at the $j$th column of $\mathbf{X̂}_{k-1}(k)$, the estimator updates the states with:

\[\begin{aligned} +\end{aligned}\]

based on the process model described in SteadyKalmanFilter. The notation $\mathbf{x̂}_{k-1}(k)$ refers to the state for the current time $k$ estimated at the last control period $k-1$. See [2] for details.

source
update_estimate!(estim::UnscentedKalmanFilter, u, ym, d)

Update UnscentedKalmanFilter state estim.x̂ and covariance estimate estim.P̂.

It implements the unscented Kalman Filter in its predictor (observer) form, based on the generalized unscented transform[3]. See init_ukf for the definition of the constants $\mathbf{m̂, Ŝ}$ and $γ$.

Denoting $\mathbf{x̂}_{k-1}(k)$ as the state for the current time $k$ estimated at the last period $k-1$, $\mathbf{0}$, a null vector, $n_σ = 2 n_\mathbf{x̂} + 1$, the number of sigma points, and $\mathbf{X̂}_{k-1}^j(k)$, the vector at the $j$th column of $\mathbf{X̂}_{k-1}(k)$, the estimator updates the states with:

\[\begin{aligned} \mathbf{X̂}_{k-1}(k) &= \bigg[\begin{matrix} \mathbf{x̂}_{k-1}(k) & \mathbf{x̂}_{k-1}(k) & \cdots & \mathbf{x̂}_{k-1}(k) \end{matrix}\bigg] + \bigg[\begin{matrix} \mathbf{0} & γ \sqrt{\mathbf{P̂}_{k-1}(k)} & -γ \sqrt{\mathbf{P̂}_{k-1}(k)} \end{matrix}\bigg] \\ \mathbf{Ŷ^m}(k) &= \bigg[\begin{matrix} \mathbf{ĥ^m}\Big( \mathbf{X̂}_{k-1}^{1}(k) \Big) & \mathbf{ĥ^m}\Big( \mathbf{X̂}_{k-1}^{2}(k) \Big) & \cdots & \mathbf{ĥ^m}\Big( \mathbf{X̂}_{k-1}^{n_σ}(k) \Big) \end{matrix}\bigg] \\ \mathbf{ŷ^m}(k) &= \mathbf{Ŷ^m}(k) \mathbf{m̂} \\ @@ -43,7 +43,7 @@ \mathbf{x̂}_{k}(k+1) &= \mathbf{X̂}_{k}(k+1)\mathbf{m̂} \\ \mathbf{X̄}_k(k+1) &= \begin{bmatrix} \mathbf{X̂}_{k}^{1}(k+1) - \mathbf{x̂}_{k}(k+1) & \mathbf{X̂}_{k}^{2}(k+1) - \mathbf{x̂}_{k}(k+1) & \cdots &\, \mathbf{X̂}_{k}^{n_σ}(k+1) - \mathbf{x̂}_{k}(k+1) \end{bmatrix} \\ \mathbf{P̂}_k(k+1) &= \mathbf{X̄}_k(k+1) \mathbf{Ŝ} \mathbf{X̄}_k'(k+1) + \mathbf{Q̂} -\end{aligned} \]

by using the lower triangular factor of cholesky to compute $\sqrt{\mathbf{P̂}_{k-1}(k)}$ and $\sqrt{\mathbf{P̂}_{k}(k)}$. The matrices $\mathbf{P̂, Q̂, R̂}$ are the covariance of the estimation error, process noise and sensor noise, respectively.

source
update_estimate!(estim::ExtendedKalmanFilter, u, ym, d=Float64[])

Update ExtendedKalmanFilter state estim.x̂ and covariance estim.P̂.

The equations are similar to update_estimate!(::KalmanFilter) but with the substitutions $\mathbf{Â = F̂}(k)$ and $\mathbf{Ĉ^m = Ĥ^m}(k)$:

\[\begin{aligned} +\end{aligned} \]

by using the lower triangular factor of cholesky to compute $\sqrt{\mathbf{P̂}_{k-1}(k)}$ and $\sqrt{\mathbf{P̂}_{k}(k)}$. The matrices $\mathbf{P̂, Q̂, R̂}$ are the covariance of the estimation error, process noise and sensor noise, respectively.

source
update_estimate!(estim::ExtendedKalmanFilter, u, ym, d=Float64[])

Update ExtendedKalmanFilter state estim.x̂ and covariance estim.P̂.

The equations are similar to update_estimate!(::KalmanFilter) but with the substitutions $\mathbf{Â = F̂}(k)$ and $\mathbf{Ĉ^m = Ĥ^m}(k)$:

\[\begin{aligned} \mathbf{M}(k) &= \mathbf{P̂}_{k-1}(k)\mathbf{Ĥ^m}'(k) [\mathbf{Ĥ^m}(k)\mathbf{P̂}_{k-1}(k)\mathbf{Ĥ^m}(k) + \mathbf{R̂}]^{-1} \\ \mathbf{K}(k) &= \mathbf{F̂}(k) \mathbf{M}(k) \\ @@ -56,7 +56,7 @@ \end{aligned}\]

ForwardDiff.jacobian automatically computes the Jacobians:

\[\begin{aligned} \mathbf{F̂}(k) &= \left. \frac{∂\mathbf{f̂}(\mathbf{x̂}, \mathbf{u}, \mathbf{d})}{∂\mathbf{x̂}} \right|_{\mathbf{x̂ = x̂}_{k-1}(k),\, \mathbf{u = u}(k),\, \mathbf{d = d}(k)} \\ \mathbf{Ĥ}(k) &= \left. \frac{∂\mathbf{ĥ}(\mathbf{x̂}, \mathbf{d})}{∂\mathbf{x̂}} \right|_{\mathbf{x = x̂}_{k-1}(k),\, \mathbf{d = d}(k)} -\end{aligned}\]

The matrix $\mathbf{Ĥ^m}$ is the rows of $\mathbf{Ĥ}$ that are measured outputs.

source
update_estimate!(estim::Luenberger, u, ym, d=Float64[])

Same than update_estimate!(::SteadyKalmanFilter) but using Luenberger.

source
update_estimate!(estim::InternalModel, u, ym, d=Float64[])

Update estim.x̂ \ x̂d \ x̂s with current inputs u, measured outputs ym and dist. d.

The InternalModel updates the deterministic x̂d and stochastic x̂s estimates with:

\[\begin{aligned} +\end{aligned}\]

The matrix $\mathbf{Ĥ^m}$ is the rows of $\mathbf{Ĥ}$ that are measured outputs.

source
update_estimate!(estim::Luenberger, u, ym, d=Float64[])

Same than update_estimate!(::SteadyKalmanFilter) but using Luenberger.

source
update_estimate!(estim::InternalModel, u, ym, d=Float64[])

Update estim.x̂ \ x̂d \ x̂s with current inputs u, measured outputs ym and dist. d.

The InternalModel updates the deterministic x̂d and stochastic x̂s estimates with:

\[\begin{aligned} \mathbf{x̂_d}(k+1) &= \mathbf{f}\Big( \mathbf{x̂_d}(k), \mathbf{u}(k), \mathbf{d}(k) \Big) \\ \mathbf{x̂_s}(k+1) &= \mathbf{Â_s x̂_s}(k) + \mathbf{B̂_s ŷ_s}(k) -\end{aligned}\]

This estimator does not augment the state vector, thus $\mathbf{x̂ = x̂_d}$. See init_internalmodel for details.

source
  • 1Desbiens, A., D. Hodouin & É. Plamondon. 2000, "Global predictive control : a unified control structure for decoupling setpoint tracking, feedforward compensation and disturbance rejection dynamics", IEE Proceedings - Control Theory and Applications, vol. 147, no 4, https://doi.org/10.1049/ip-cta:20000443, p. 465–475, ISSN 1350-2379.
  • 2Boyd S., "Lecture 8 : The Kalman Filter" (Winter 2008-09) [course slides], EE363: Linear Dynamical Systems, https://web.stanford.edu/class/ee363/lectures/kf.pdf.
  • 3Simon, D. 2006, "Chapter 14: The unscented Kalman filter" in "Optimal State Estimation: Kalman, H∞, and Nonlinear Approaches", John Wiley & Sons, p. 433–459, https://doi.org/10.1002/0470045345.ch14, ISBN9780470045343.
+\end{aligned}\]

This estimator does not augment the state vector, thus $\mathbf{x̂ = x̂_d}$. See init_internalmodel for details.

source
diff --git a/dev/manual/installation/index.html b/dev/manual/installation/index.html index c05e2bab5..bf8b033f5 100644 --- a/dev/manual/installation/index.html +++ b/dev/manual/installation/index.html @@ -1,2 +1,2 @@ -Installation · ModelPredictiveControl.jl

Manual: Installation

To install the ModelPredictiveControl package, run this command in the Julia REPL:

using Pkg; Pkg.add("ModelPredictiveControl")

It will also automatically install all the dependencies, including JuMP.jl and ControlSystemsBase.jl. Note that that the construction of linear models typically requires ss or tf functions, it is thus recommended to load the package with:

using ModelPredictiveControl, ControlSystemsBase
+Installation · ModelPredictiveControl.jl

Manual: Installation

To install the ModelPredictiveControl package, run this command in the Julia REPL:

using Pkg; Pkg.add("ModelPredictiveControl")

It will also automatically install all the dependencies, including JuMP.jl and ControlSystemsBase.jl. Note that that the construction of linear models typically requires ss or tf functions, it is thus recommended to load the package with:

using ModelPredictiveControl, ControlSystemsBase
diff --git a/dev/manual/linmpc/index.html b/dev/manual/linmpc/index.html index 2d8b8bc8e..b029bf44d 100644 --- a/dev/manual/linmpc/index.html +++ b/dev/manual/linmpc/index.html @@ -63,117 +63,117 @@ p = plot(p1, p2, p3, layout=(3,1), fmt=:svg) - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dev/manual/nonlinmpc/index.html b/dev/manual/nonlinmpc/index.html index 64cf11cc8..19074244a 100644 --- a/dev/manual/nonlinmpc/index.html +++ b/dev/manual/nonlinmpc/index.html @@ -28,49 +28,49 @@ plot(sim!(model, 60, u), plotu=false) - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + +

Nonlinear Predictive Controller

An UnscentedKalmanFilter estimates the plant state :

estim = UnscentedKalmanFilter(model, σQ=[0.1, 0.5], σQ_int=[5.0], σR=[0.5])
UnscentedKalmanFilter estimator with a sample time Ts = 0.1 s, NonLinModel and:
  1 manipulated inputs u
@@ -84,165 +84,165 @@ 

- + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + +

The estimate $x̂_3$ is the integrator state that compensates for static errors (nint_ym and σQ_int parameters of UnscentedKalmanFilter). The Kalman filter performance seems sufficient for control. As the motor torque is limited to -1.5 to 1.5 N m, we incorporate the input constraints in a NonLinMPC:

mpc = NonLinMPC(estim, Hp=20, Hc=4, Mwt=[0.5], Nwt=[2.5], Cwt=Inf)
 mpc = setconstraint!(mpc, umin=[-1.5], umax=[+1.5])
NonLinMPC controller with a sample time Ts = 0.1 s, UnscentedKalmanFilter estimator and:
@@ -256,194 +256,194 @@ 

- + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

The controller seems robust enough to variations on $K$ coefficient. Starting from this inverted position, the closed-loop response to a step disturbances of 10° is also satisfactory:

res = sim!(mpc, 60, [180.0], plant=plant, x0=[π, 0], x̂0=[π, 0, 0], y_step=[10])
 plot(res)
- + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dev/public/generic_func/index.html b/dev/public/generic_func/index.html index 7b9eae65c..d38ec78c6 100644 --- a/dev/public/generic_func/index.html +++ b/dev/public/generic_func/index.html @@ -3,31 +3,31 @@ julia> y = evaloutput(model) 1-element Vector{Float64}: - 20.0

source
evaloutput(estim::StateEstimator, d=Float64[])

Evaluate StateEstimator outputs from estim.x̂ states and disturbances d.

Calling a StateEstimator object calls this evaloutput method.

Examples

julia> kf = SteadyKalmanFilter(setop!(LinModel(tf(2, [10, 1]), 5), yop=[20]));
+ 20.0
source
evaloutput(estim::StateEstimator, d=Float64[])

Evaluate StateEstimator outputs from estim.x̂ states and disturbances d.

Calling a StateEstimator object calls this evaloutput method.

Examples

julia> kf = SteadyKalmanFilter(setop!(LinModel(tf(2, [10, 1]), 5), yop=[20]));
 
 julia> ŷ = evaloutput(kf)
 1-element Vector{Float64}:
- 20.0
source
evaloutput(estim::InternalModel, ym, d=Float64[])

Evaluate InternalModel outputs from estim.x̂d states and measured outputs ym.

InternalModel estimator needs current measured outputs $\mathbf{y^m}(k)$ to estimate its outputs $\mathbf{ŷ}(k)$, since the strategy imposes that $\mathbf{ŷ^m}(k) = \mathbf{y^m}(k)$ is always true.

source

Update State x

ModelPredictiveControl.updatestate!Function
updatestate!(model::SimModel, u, d=Float64[])

Update model.x states with current inputs u and measured disturbances d.

Examples

julia> model = LinModel(ss(1, 1, 1, 0, 1.0));
+ 20.0
source
evaloutput(estim::InternalModel, ym, d=Float64[])

Evaluate InternalModel outputs from estim.x̂d states and measured outputs ym.

InternalModel estimator needs current measured outputs $\mathbf{y^m}(k)$ to estimate its outputs $\mathbf{ŷ}(k)$, since the strategy imposes that $\mathbf{ŷ^m}(k) = \mathbf{y^m}(k)$ is always true.

source

Update State x

ModelPredictiveControl.updatestate!Function
updatestate!(model::SimModel, u, d=Float64[])

Update model.x states with current inputs u and measured disturbances d.

Examples

julia> model = LinModel(ss(1, 1, 1, 0, 1.0));
 
 julia> x = updatestate!(model, [1])
 1-element Vector{Float64}:
- 1.0
source
updatestate!(estim::StateEstimator, u, ym, d=Float64[])

Update estim.x̂ estimate with current inputs u, measured outputs ym and dist. d.

The method removes the operating points with remove_op! and call update_estimate!.

Examples

julia> kf = SteadyKalmanFilter(LinModel(ss(0.1, 0.5, 1, 0, 4.0)));
+ 1.0
source
updatestate!(estim::StateEstimator, u, ym, d=Float64[])

Update estim.x̂ estimate with current inputs u, measured outputs ym and dist. d.

The method removes the operating points with remove_op! and call update_estimate!.

Examples

julia> kf = SteadyKalmanFilter(LinModel(ss(0.1, 0.5, 1, 0, 4.0)));
 
 julia> x̂ = updatestate!(kf, [1], [0]) # x̂[2] is the integrator state (nint_ym argument)
 2-element Vector{Float64}:
  0.5
- 0.0
source
updatestate!(mpc::PredictiveController, u, ym, d=Float64[])

Call updatestate! on mpc.estim StateEstimator.

source

Init State x

ModelPredictiveControl.initstate!Function
initstate!(estim::StateEstimator, u, ym, d=Float64[])

Init estim.x̂ states from current inputs u, measured outputs ym and disturbances d.

The method tries to find a good steady-state to initialize estim.x̂ estimate :

  • If estim.model is a LinModel, it evaluates estim.model steady-state (using steadystate) with current inputs u and measured disturbances d, and saves the result to estim.x̂[1:nx].
  • Else, the current deterministic states estim.x̂[1:nx] are left unchanged (use setstate! to manually modify them).

It then estimates the measured outputs ŷm from these states, and the residual offset with current measured outputs (ym - ŷm) initializes the integrators of the stochastic model. This approach ensures that $\mathbf{ŷ^m}(0) = \mathbf{y^m}(0)$. For LinModel, it also ensures that the estimator starts at steady-state, resulting in a bumpless manual to automatic transfer for control applications.

Examples

julia> estim = SteadyKalmanFilter(LinModel(tf(3, [10, 1]), 0.5), nint_ym=[2]);
+ 0.0
source
updatestate!(mpc::PredictiveController, u, ym, d=Float64[])

Call updatestate! on mpc.estim StateEstimator.

source

Init State x

ModelPredictiveControl.initstate!Function
initstate!(estim::StateEstimator, u, ym, d=Float64[])

Init estim.x̂ states from current inputs u, measured outputs ym and disturbances d.

The method tries to find a good steady-state to initialize estim.x̂ estimate :

  • If estim.model is a LinModel, it evaluates estim.model steady-state (using steadystate) with current inputs u and measured disturbances d, and saves the result to estim.x̂[1:nx].
  • Else, the current deterministic states estim.x̂[1:nx] are left unchanged (use setstate! to manually modify them).

It then estimates the measured outputs ŷm from these states, and the residual offset with current measured outputs (ym - ŷm) initializes the integrators of the stochastic model. This approach ensures that $\mathbf{ŷ^m}(0) = \mathbf{y^m}(0)$. For LinModel, it also ensures that the estimator starts at steady-state, resulting in a bumpless manual to automatic transfer for control applications.

Examples

julia> estim = SteadyKalmanFilter(LinModel(tf(3, [10, 1]), 0.5), nint_ym=[2]);
 
 julia> x̂ = initstate!(estim, [1], [3 - 0.1])
 3-element Vector{Float64}:
   5.0000000000000115
   0.0
- -0.10000000000000675
source
initstate!(estim::InternalModel, u, ym, d=Float64[])

Init estim.x̂d / x̂s states from current inputs u, meas. outputs ym and disturb. d.

The deterministic state estim.x̂d initialization method is identical to initstate!(::StateEstimator). The stochastic states estim.x̂s are init at 0.

source
initstate!(mpc::PredictiveController, u, ym, d=Float64[])

Init mpc.ΔŨ for warm-starting and the states of mpc.estim StateEstimator.

source

Set State x

ModelPredictiveControl.setstate!Function
setstate!(model::SimModel, x)

Set model.x states to values specified by x.

source
setstate!(estim::StateEstimator, x̂)

Set estim.x̂ states to values specified by .

source
setstate!(mpc::PredictiveController, x̂)

Set the estimate at mpc.estim.x̂.

source

Quick Simulation

ModelPredictiveControl.sim!Function
sim!(plant::SimModel, N::Int, u=plant.uop.+1, d=plant.dop; x0=zeros(plant.nx))

Open-loop simulation of plant for N time steps, default to unit bump test on all inputs.

The manipulated inputs $\mathbf{u}$ and measured disturbances $\mathbf{d}$ are held constant at u and d values, respectively. The plant initial state $\mathbf{x}(0)$ is specified by x0 keyword arguments. The function returns SimResult instances that can be visualized by calling plot from Plots.jl on them (see Examples below).

Examples

julia> plant = NonLinModel((x,u,d)->0.1x+u+d, (x,_)->2x, 10.0, 1, 1, 1, 1);
+ -0.10000000000000675
source
initstate!(estim::InternalModel, u, ym, d=Float64[])

Init estim.x̂d / x̂s states from current inputs u, meas. outputs ym and disturb. d.

The deterministic state estim.x̂d initialization method is identical to initstate!(::StateEstimator). The stochastic states estim.x̂s are init at 0.

source
initstate!(mpc::PredictiveController, u, ym, d=Float64[])

Init mpc.ΔŨ for warm-starting and the states of mpc.estim StateEstimator.

source

Set State x

ModelPredictiveControl.setstate!Function
setstate!(model::SimModel, x)

Set model.x states to values specified by x.

source
setstate!(estim::StateEstimator, x̂)

Set estim.x̂ states to values specified by .

source
setstate!(mpc::PredictiveController, x̂)

Set the estimate at mpc.estim.x̂.

source

Quick Simulation

ModelPredictiveControl.sim!Function
sim!(plant::SimModel, N::Int, u=plant.uop.+1, d=plant.dop; x0=zeros(plant.nx))

Open-loop simulation of plant for N time steps, default to unit bump test on all inputs.

The manipulated inputs $\mathbf{u}$ and measured disturbances $\mathbf{d}$ are held constant at u and d values, respectively. The plant initial state $\mathbf{x}(0)$ is specified by x0 keyword arguments. The function returns SimResult instances that can be visualized by calling plot from Plots.jl on them (see Examples below).

Examples

julia> plant = NonLinModel((x,u,d)->0.1x+u+d, (x,_)->2x, 10.0, 1, 1, 1, 1);
 
 julia> res = sim!(plant, 15, [0], [0], x0=[1]);
 
 julia> using Plots; plot(res, plotu=false, plotd=false, plotx=true)
-
source
sim!(
+
source
sim!(
     estim::StateEstimator,
     N::Int,
     u = estim.model.uop .+ 1,
@@ -40,7 +40,7 @@
 julia> res = sim!(estim, 50, [0], y_noise=[0.5], x_noise=[0.25], x0=[-10], x̂0=[0, 0]);
 
 julia> using Plots; plot(res, plotŷ=true, plotu=false, plotxwithx̂=true)
-
source
sim!(
+
source
sim!(
     mpc::PredictiveController, 
     N::Int,
     ry = mpc.estim.model.yop .+ 1, 
@@ -53,4 +53,4 @@
 julia> res = sim!(mpc, 25, [0, 0], y_noise=[0.1], y_step=[-10, 0]);
 
 julia> using Plots; plot(res, plotry=true, plotŷ=true, plotŷmin=true, plotu=true)
-
source
+
source diff --git a/dev/public/predictive_control/index.html b/dev/public/predictive_control/index.html index 50a071a48..b63e95ca3 100644 --- a/dev/public/predictive_control/index.html +++ b/dev/public/predictive_control/index.html @@ -3,7 +3,7 @@ julia> u = mpc([5]); round.(u, digits=3) 1-element Vector{Float64}: - 1.0source

LinMPC

ModelPredictiveControl.LinMPCType
LinMPC(model::LinModel; <keyword arguments>)

Construct a linear predictive controller based on LinModel model.

The controller minimizes the following objective function at each discrete time $k$:

\[\min_{\mathbf{ΔU}, ϵ} \mathbf{(R̂_y - Ŷ)}' \mathbf{M}_{H_p} \mathbf{(R̂_y - Ŷ)} + 1.0

source

LinMPC

ModelPredictiveControl.LinMPCType
LinMPC(model::LinModel; <keyword arguments>)

Construct a linear predictive controller based on LinModel model.

The controller minimizes the following objective function at each discrete time $k$:

\[\min_{\mathbf{ΔU}, ϵ} \mathbf{(R̂_y - Ŷ)}' \mathbf{M}_{H_p} \mathbf{(R̂_y - Ŷ)} + \mathbf{(ΔU)}' \mathbf{N}_{H_c} \mathbf{(ΔU)} + \mathbf{(R̂_u - U)}' \mathbf{L}_{H_p} \mathbf{(R̂_u - U)} + C ϵ^2\]

in which the weight matrices are repeated $H_p$ or $H_c$ times:

\[\begin{aligned} @@ -20,7 +20,7 @@ 4 states x̂ 2 measured outputs ym 0 unmeasured outputs yu - 0 measured disturbances d

Extended Help

Manipulated inputs setpoints $\mathbf{r_u}$ are not common but they can be interesting for over-actuated systems, when nu > ny (e.g. prioritize solutions with lower economical costs). The default Lwt value implies that this feature is disabled by default.

source
LinMPC(estim::StateEstimator; <keyword arguments>)

Use custom state estimator estim to construct LinMPC.

estim.model must be a LinModel. Else, a NonLinMPC is required.

Examples

julia> estim = KalmanFilter(LinModel([tf(3, [30, 1]); tf(-2, [5, 1])], 4), i_ym=[2]);
+  0 measured disturbances d

Extended Help

Manipulated inputs setpoints $\mathbf{r_u}$ are not common but they can be interesting for over-actuated systems, when nu > ny (e.g. prioritize solutions with lower economical costs). The default Lwt value implies that this feature is disabled by default.

source
LinMPC(estim::StateEstimator; <keyword arguments>)

Use custom state estimator estim to construct LinMPC.

estim.model must be a LinModel. Else, a NonLinMPC is required.

Examples

julia> estim = KalmanFilter(LinModel([tf(3, [30, 1]); tf(-2, [5, 1])], 4), i_ym=[2]);
 
 julia> mpc = LinMPC(estim, Mwt=[0, 1], Nwt=[0.5], Hp=30, Hc=1)
 LinMPC controller with a sample time Ts = 4.0 s, KalmanFilter estimator and:
@@ -30,7 +30,7 @@
   3 states x̂
   1 measured outputs ym
   1 unmeasured outputs yu
-  0 measured disturbances d
source

NonLinMPC

ModelPredictiveControl.NonLinMPCType
NonLinMPC(model::SimModel; <keyword arguments>)

Construct a nonlinear predictive controller based on SimModel model.

Both NonLinModel and LinModel are supported (see Extended Help). The controller minimizes the following objective function at each discrete time $k$:

\[\min_{\mathbf{ΔU}, ϵ} \mathbf{(R̂_y - Ŷ)}' \mathbf{M}_{H_p} \mathbf{(R̂_y - Ŷ)} + 0 measured disturbances d

source

NonLinMPC

ModelPredictiveControl.NonLinMPCType
NonLinMPC(model::SimModel; <keyword arguments>)

Construct a nonlinear predictive controller based on SimModel model.

Both NonLinModel and LinModel are supported (see Extended Help). The controller minimizes the following objective function at each discrete time $k$:

\[\min_{\mathbf{ΔU}, ϵ} \mathbf{(R̂_y - Ŷ)}' \mathbf{M}_{H_p} \mathbf{(R̂_y - Ŷ)} + \mathbf{(ΔU)}' \mathbf{N}_{H_c} \mathbf{(ΔU)} + \mathbf{(R̂_u - U)}' \mathbf{L}_{H_p} \mathbf{(R̂_u - U)} + C ϵ^2 + E J_E(\mathbf{U}_E, \mathbf{Ŷ}_E, \mathbf{D̂}_E)\]

See LinMPC for the variable definitions. The custom economic function $J_E$ can penalizes solutions with high economic costs. Setting all the weights to 0 except $E$ creates a pure economic model predictive controller (EMPC). The arguments of $J_E$ are the manipulated inputs, the predicted outputs and measured disturbances from $k$ to $k+H_p$ inclusively:

\[ \mathbf{U}_E = \begin{bmatrix} \mathbf{U} \\ \mathbf{u}(k+H_p-1) \end{bmatrix} \text{,} \qquad @@ -45,7 +45,7 @@ 2 states x̂ 1 measured outputs ym 0 unmeasured outputs yu - 0 measured disturbances d

Extended Help

NonLinMPC controllers based on LinModel compute the predictions with matrix algebra instead of a for loop. This feature can accelerate the optimization and is not available in any other package, to my knowledge.

The optimizations rely on JuMP.jl automatic differentiation (AD) to compute the objective and constraint derivatives. Optimizers generally benefit from exact derivatives like AD. However, the NonLinModel f and h functions must be compatible with this feature. See Automatic differentiation for common mistakes when writing these functions.

source
NonLinMPC(estim::StateEstimator; <keyword arguments>)

Use custom state estimator estim to construct NonLinMPC.

Examples

julia> model = NonLinModel((x,u,_)->0.5x+u, (x,_)->2x, 10.0, 1, 1, 1);
+  0 measured disturbances d

Extended Help

NonLinMPC controllers based on LinModel compute the predictions with matrix algebra instead of a for loop. This feature can accelerate the optimization and is not available in any other package, to my knowledge.

The optimizations rely on JuMP.jl automatic differentiation (AD) to compute the objective and constraint derivatives. Optimizers generally benefit from exact derivatives like AD. However, the NonLinModel f and h functions must be compatible with this feature. See Automatic differentiation for common mistakes when writing these functions.

source
NonLinMPC(estim::StateEstimator; <keyword arguments>)

Use custom state estimator estim to construct NonLinMPC.

Examples

julia> model = NonLinModel((x,u,_)->0.5x+u, (x,_)->2x, 10.0, 1, 1, 1);
 
 julia> estim = UnscentedKalmanFilter(model, σQ_int=[0.05]);
 
@@ -57,11 +57,11 @@
   2 states x̂
   1 measured outputs ym
   0 unmeasured outputs yu
-  0 measured disturbances d
source

Set Constraint

ModelPredictiveControl.setconstraint!Function
setconstraint!(mpc::PredictiveController; <keyword arguments>)

Set the constraint parameters of mpc predictive controller.

The predictive controllers support both soft and hard constraints, defined by:

\[\begin{alignat*}{3} + 0 measured disturbances d

source

Set Constraint

ModelPredictiveControl.setconstraint!Function
setconstraint!(mpc::PredictiveController; <keyword arguments>)

Set the constraint parameters of mpc predictive controller.

The predictive controllers support both soft and hard constraints, defined by:

\[\begin{alignat*}{3} \mathbf{u_{min} - c_{u_{min}}} ϵ &≤ \mathbf{u}(k+j) &&≤ \mathbf{u_{max} + c_{u_{max}}} ϵ &&\qquad j = 0, 1 ,..., H_c - 1 \\ \mathbf{Δu_{min} - c_{Δu_{min}}} ϵ &≤ \mathbf{Δu}(k+j) &&≤ \mathbf{Δu_{max} + c_{Δu_{max}}} ϵ &&\qquad j = 0, 1 ,..., H_c - 1 \\ \mathbf{ŷ_{min} - c_{ŷ_{min}}} ϵ &≤ \mathbf{ŷ}(k+j) &&≤ \mathbf{ŷ_{max} + c_{ŷ_{max}}} ϵ &&\qquad j = 1, 2 ,..., H_p \\ -\end{alignat*}\]

and also $ϵ ≥ 0$. All the constraint parameters are vector. Use ±Inf values when there is no bound. The constraint softness parameters $\mathbf{c}$, also called equal concern for relaxation, are non-negative values that specify the softness of the associated bound. Use 0.0 values for hard constraints. The predicted output constraints $\mathbf{ŷ_{min}}$ and $\mathbf{ŷ_{max}}$ are soft by default.

Arguments

Info

The default constraints are mentioned here for clarity but omitting a keyword argument will not re-assign to its default value (defaults are set at construction only).

  • umin=fill(-Inf,nu) : manipulated input lower bounds $\mathbf{u_{min}}$
  • umax=fill(+Inf,nu) : manipulated input upper bounds $\mathbf{u_{max}}$
  • Δumin=fill(-Inf,nu) : manipulated input increment lower bounds $\mathbf{Δu_{min}}$
  • Δumax=fill(+Inf,nu) : manipulated input increment upper bounds $\mathbf{Δu_{max}}$
  • ŷmin=fill(-Inf,ny) : predicted output lower bounds $\mathbf{ŷ_{min}}$
  • ŷmax=fill(+Inf,ny) : predicted output upper bounds $\mathbf{ŷ_{max}}$
  • c_umin=fill(0.0,nu) : umin softness weights $\mathbf{c_{u_{min}}}$
  • c_umax=fill(0.0,nu) : umax softness weights $\mathbf{c_{u_{max}}}$
  • c_Δumin=fill(0.0,nu) : Δumin softness weights $\mathbf{c_{Δu_{min}}}$
  • c_Δumax=fill(0.0,nu) : Δumax softness weights $\mathbf{c_{Δu_{max}}}$
  • c_ŷmin=fill(1.0,ny) : ŷmin softness weights $\mathbf{c_{ŷ_{min}}}$
  • c_ŷmax=fill(1.0,ny) : ŷmax softness weights $\mathbf{c_{ŷ_{max}}}$
source

Move Manipulated Input

ModelPredictiveControl.moveinput!Function
moveinput!(
+\end{alignat*}\]

and also $ϵ ≥ 0$. All the constraint parameters are vector. Use ±Inf values when there is no bound. The constraint softness parameters $\mathbf{c}$, also called equal concern for relaxation, are non-negative values that specify the softness of the associated bound. Use 0.0 values for hard constraints. The predicted output constraints $\mathbf{ŷ_{min}}$ and $\mathbf{ŷ_{max}}$ are soft by default.

Arguments

Info

The default constraints are mentioned here for clarity but omitting a keyword argument will not re-assign to its default value (defaults are set at construction only).

  • umin=fill(-Inf,nu) : manipulated input lower bounds $\mathbf{u_{min}}$
  • umax=fill(+Inf,nu) : manipulated input upper bounds $\mathbf{u_{max}}$
  • Δumin=fill(-Inf,nu) : manipulated input increment lower bounds $\mathbf{Δu_{min}}$
  • Δumax=fill(+Inf,nu) : manipulated input increment upper bounds $\mathbf{Δu_{max}}$
  • ŷmin=fill(-Inf,ny) : predicted output lower bounds $\mathbf{ŷ_{min}}$
  • ŷmax=fill(+Inf,ny) : predicted output upper bounds $\mathbf{ŷ_{max}}$
  • c_umin=fill(0.0,nu) : umin softness weights $\mathbf{c_{u_{min}}}$
  • c_umax=fill(0.0,nu) : umax softness weights $\mathbf{c_{u_{max}}}$
  • c_Δumin=fill(0.0,nu) : Δumin softness weights $\mathbf{c_{Δu_{min}}}$
  • c_Δumax=fill(0.0,nu) : Δumax softness weights $\mathbf{c_{Δu_{max}}}$
  • c_ŷmin=fill(1.0,ny) : ŷmin softness weights $\mathbf{c_{ŷ_{min}}}$
  • c_ŷmax=fill(1.0,ny) : ŷmax softness weights $\mathbf{c_{ŷ_{max}}}$
source

Move Manipulated Input

ModelPredictiveControl.moveinput!Function
moveinput!(
     mpc::PredictiveController, 
     ry = mpc.estim.model.yop, 
     d  = Float64[];
@@ -83,10 +83,10 @@
 
 julia> u = moveinput!(mpc, [5]); round.(u, digits=3)
 1-element Vector{Float64}:
- 1.0
source

Get Additional Information

ModelPredictiveControl.getinfoFunction
getinfo(mpc::PredictiveController)

Get additional information about mpc controller optimum to ease troubleshooting.

Return the optimizer solution summary that can be printed, sol_summary, and the dictionary info with the following fields:

  • :ΔU : optimal manipulated input increments over Hc $(\mathbf{ΔU})$
  • : optimal slack variable $(ϵ)$
  • :J : objective value optimum $(J)$
  • :U : optimal manipulated inputs over Hp $(\mathbf{U})$
  • :u : current optimal manipulated input $(\mathbf{u})$
  • :d : current measured disturbance $(\mathbf{d})$
  • :D̂ : predicted measured disturbances over Hp $(\mathbf{D̂})$
  • :ŷ : current estimated output $(\mathbf{ŷ})$
  • :Ŷ : optimal predicted outputs over Hp $(\mathbf{Ŷ = Ŷ_d + Ŷ_s})$
  • :Ŷd : optimal predicted deterministic output over Hp $(\mathbf{Ŷ_d})$
  • :Ŷs : predicted stochastic output over Hp $(\mathbf{Ŷ_s})$
  • :R̂y : predicted output setpoint over Hp $(\mathbf{R̂_y})$
  • :R̂u : predicted manipulated input setpoint over Hp $(\mathbf{R̂_u})$

Examples

julia> mpc = LinMPC(LinModel(tf(5, [2, 1]), 3), Nwt=[0], Hp=1, Hc=1);
+ 1.0
source

Get Additional Information

ModelPredictiveControl.getinfoFunction
getinfo(mpc::PredictiveController)

Get additional information about mpc controller optimum to ease troubleshooting.

Return the optimizer solution summary that can be printed, sol_summary, and the dictionary info with the following fields:

  • :ΔU : optimal manipulated input increments over Hc $(\mathbf{ΔU})$
  • : optimal slack variable $(ϵ)$
  • :J : objective value optimum $(J)$
  • :U : optimal manipulated inputs over Hp $(\mathbf{U})$
  • :u : current optimal manipulated input $(\mathbf{u})$
  • :d : current measured disturbance $(\mathbf{d})$
  • :D̂ : predicted measured disturbances over Hp $(\mathbf{D̂})$
  • :ŷ : current estimated output $(\mathbf{ŷ})$
  • :Ŷ : optimal predicted outputs over Hp $(\mathbf{Ŷ = Ŷ_d + Ŷ_s})$
  • :Ŷd : optimal predicted deterministic output over Hp $(\mathbf{Ŷ_d})$
  • :Ŷs : predicted stochastic output over Hp $(\mathbf{Ŷ_s})$
  • :R̂y : predicted output setpoint over Hp $(\mathbf{R̂_y})$
  • :R̂u : predicted manipulated input setpoint over Hp $(\mathbf{R̂_u})$

Examples

julia> mpc = LinMPC(LinModel(tf(5, [2, 1]), 3), Nwt=[0], Hp=1, Hc=1);
 
 julia> u = moveinput!(mpc, [10]);
 
 julia> sol_summary, info = getinfo(mpc); round.(info[:Ŷ], digits=3)
 1-element Vector{Float64}:
- 10.0
source
getinfo(mpc::NonLinMPC)

Invoke getinfo(::PredictiveController) and add :JE the economic optimum $J_E$.

source
+ 10.0source
getinfo(mpc::NonLinMPC)

Invoke getinfo(::PredictiveController) and add :JE the economic optimum $J_E$.

source
diff --git a/dev/public/sim_model/index.html b/dev/public/sim_model/index.html index a797b4c74..994830fbb 100644 --- a/dev/public/sim_model/index.html +++ b/dev/public/sim_model/index.html @@ -3,7 +3,7 @@ julia> y = model() 1-element Vector{Float64}: - 20.0source

LinModel

ModelPredictiveControl.LinModelType
LinModel(sys::StateSpace[, Ts]; i_u=1:size(sys,2), i_d=Int[])

Construct a linear model from state-space model sys with sampling time Ts in second.

Ts can be omitted when sys is discrete-time. Its state-space matrices are:

\[\begin{aligned} + 20.0

source

LinModel

ModelPredictiveControl.LinModelType
LinModel(sys::StateSpace[, Ts]; i_u=1:size(sys,2), i_d=Int[])

Construct a linear model from state-space model sys with sampling time Ts in second.

Ts can be omitted when sys is discrete-time. Its state-space matrices are:

\[\begin{aligned} \mathbf{x}(k+1) &= \mathbf{A x}(k) + \mathbf{B z}(k) \\ \mathbf{y}(k) &= \mathbf{C x}(k) + \mathbf{D z}(k) \end{aligned}\]

with the state $\mathbf{x}$ and output $\mathbf{y}$ vectors. The $\mathbf{z}$ vector comprises the manipulated inputs $\mathbf{u}$ and measured disturbances $\mathbf{d}$, in any order. i_u provides the indices of $\mathbf{z}$ that are manipulated, and i_d, the measured disturbances. See Extended Help if sys is continuous-time, or discrete-time with Ts ≠ sys.Ts.

See also ss, tf.

Examples

julia> model = LinModel(ss(0.4, 0.2, 0.3, 0, 0.1))
@@ -14,17 +14,17 @@
  0 measured disturbances d

Extended Help

State-space matrices are similar if sys is continuous (replace $\mathbf{x}(k+1)$ with $\mathbf{ẋ}(t)$ and $k$ with $t$ on the LHS). In such a case, it's discretized with c2d and :zoh for manipulated inputs, and :tustin, for measured disturbances. Lastly, if sys is discrete and the provided argument Ts ≠ sys.Ts, the system is resampled by using the aforementioned discretization methods.

The constructor transforms the system to a more practical form ($\mathbf{D_u=0}$ because of the zero-order hold):

\[\begin{aligned} \mathbf{x}(k+1) &= \mathbf{A x}(k) + \mathbf{B_u u}(k) + \mathbf{B_d d}(k) \\ \mathbf{y}(k) &= \mathbf{C x}(k) + \mathbf{D_d d}(k) -\end{aligned}\]

source
LinModel(sys::TransferFunction[, Ts]; i_u=1:size(sys,2), i_d=Int[])

Convert to minimal realization state-space when sys is a transfer function.

sys is equal to $\frac{\mathbf{y}(s)}{\mathbf{z}(s)}$ for continuous-time, and $\frac{\mathbf{y}(z)}{\mathbf{z}(z)}$, for discrete-time.

Examples

julia> model = LinModel([tf(3, [30, 1]) tf(-2, [5, 1])], 0.5, i_d=[2])
+\end{aligned}\]

source
LinModel(sys::TransferFunction[, Ts]; i_u=1:size(sys,2), i_d=Int[])

Convert to minimal realization state-space when sys is a transfer function.

sys is equal to $\frac{\mathbf{y}(s)}{\mathbf{z}(s)}$ for continuous-time, and $\frac{\mathbf{y}(z)}{\mathbf{z}(z)}$, for discrete-time.

Examples

julia> model = LinModel([tf(3, [30, 1]) tf(-2, [5, 1])], 0.5, i_d=[2])
 Discrete-time linear model with a sample time Ts = 0.5 s and:
  1 manipulated inputs u
  2 states x
  1 outputs y
- 1 measured disturbances d
source
LinModel(sys::DelayLtiSystem, Ts; i_u=1:size(sys,2), i_d=Int[])

Discretize with zero-order hold when sys is a continuous system with delays.

The delays must be multiples of the sample time Ts.

Examples

julia> model = LinModel(tf(4, [10, 1])*delay(2), 0.5)
+ 1 measured disturbances d
source
LinModel(sys::DelayLtiSystem, Ts; i_u=1:size(sys,2), i_d=Int[])

Discretize with zero-order hold when sys is a continuous system with delays.

The delays must be multiples of the sample time Ts.

Examples

julia> model = LinModel(tf(4, [10, 1])*delay(2), 0.5)
 Discrete-time linear model with a sample time Ts = 0.5 s and:
  1 manipulated inputs u
  5 states x
  1 outputs y
- 0 measured disturbances d
source

NonLinModel

ModelPredictiveControl.NonLinModelType
NonLinModel(f::Function, h::Function, Ts, nu, nx, ny, nd=0)

Construct a nonlinear model from discrete-time state-space functions f and h.

The state update $\mathbf{f}$ and output $\mathbf{h}$ functions are defined as :

\[ \begin{aligned} + 0 measured disturbances d

source

NonLinModel

ModelPredictiveControl.NonLinModelType
NonLinModel(f::Function, h::Function, Ts, nu, nx, ny, nd=0)

Construct a nonlinear model from discrete-time state-space functions f and h.

The state update $\mathbf{f}$ and output $\mathbf{h}$ functions are defined as :

\[ \begin{aligned} \mathbf{x}(k+1) &= \mathbf{f}\Big( \mathbf{x}(k), \mathbf{u}(k), \mathbf{d}(k) \Big) \\ \mathbf{y}(k) &= \mathbf{h}\Big( \mathbf{x}(k), \mathbf{d}(k) \Big) \end{aligned}\]

Ts is the sampling time in second. nu, nx, ny and nd are the respective number of manipulated inputs, states, outputs and measured disturbances.

Tip

Replace the d argument with _ if nd = 0 (see Examples below).

Nonlinear continuous-time state-space functions are not supported for now. In such a case, manually call a differential equation solver in f (see Manual).

Warning

f and h must be pure Julia functions to use the model in NonLinMPC, ExtendedKalmanFilter and MovingHorizonEstimator.

See also LinModel.

Examples

julia> model = NonLinModel((x,u,_)->0.1x+u, (x,_)->2x, 10.0, 1, 1, 1)
@@ -32,7 +32,7 @@
  1 manipulated inputs u
  1 states x
  1 outputs y
- 0 measured disturbances d
source

Set Operating Points

ModelPredictiveControl.setop!Function
setop!(model::SimModel; uop=nothing, yop=nothing, dop=nothing)

Set model inputs uop, outputs yop and measured disturbances dop operating points.

The state-space model with operating points (a.k.a. nominal values) is:

\[\begin{aligned} + 0 measured disturbances d

source

Set Operating Points

ModelPredictiveControl.setop!Function
setop!(model::SimModel; uop=nothing, yop=nothing, dop=nothing)

Set model inputs uop, outputs yop and measured disturbances dop operating points.

The state-space model with operating points (a.k.a. nominal values) is:

\[\begin{aligned} \mathbf{x}(k+1) &= \mathbf{A x}(k) + \mathbf{B_u u_0}(k) + \mathbf{B_d d_0}(k) \\ \mathbf{y_0}(k) &= \mathbf{C x}(k) + \mathbf{D_d d_0}(k) \end{aligned}\]

in which the uop, yop and dop vectors evaluate:

\[\begin{aligned} @@ -47,4 +47,4 @@ 1 manipulated inputs u 1 states x 1 outputs y - 0 measured disturbances d

source
+ 0 measured disturbances dsource diff --git a/dev/public/state_estim/index.html b/dev/public/state_estim/index.html index c5e5f9b5c..a5d5daaa6 100644 --- a/dev/public/state_estim/index.html +++ b/dev/public/state_estim/index.html @@ -3,7 +3,7 @@ julia> ŷ = kf() 1-element Vector{Float64}: - 20.0source

SteadyKalmanFilter

ModelPredictiveControl.SteadyKalmanFilterType
SteadyKalmanFilter(model::LinModel; <keyword arguments>)

Construct a steady-state Kalman Filter with the LinModel model.

The steady-state (or asymptotic) Kalman filter is based on the process model :

\[\begin{aligned} + 20.0

source

SteadyKalmanFilter

ModelPredictiveControl.SteadyKalmanFilterType
SteadyKalmanFilter(model::LinModel; <keyword arguments>)

Construct a steady-state Kalman Filter with the LinModel model.

The steady-state (or asymptotic) Kalman filter is based on the process model :

\[\begin{aligned} \mathbf{x}(k+1) &= \mathbf{Â x}(k) + \mathbf{B̂_u u}(k) + \mathbf{B̂_d d}(k) + \mathbf{w}(k) \\ \mathbf{y^m}(k) &= \mathbf{Ĉ^m x}(k) + \mathbf{D̂_d^m d}(k) + \mathbf{v}(k) \\ @@ -16,7 +16,7 @@ 3 states x̂ 1 measured outputs ym 1 unmeasured outputs yu - 0 measured disturbances d

Extended Help

The model augmentation with nint_ym vector produces the integral action when the estimator is used in a controller as state feedback. The default is 1 integrator per measured outputs, resulting in an offset-free tracking for "step-like" unmeasured output disturbances. Use 2 integrators for "ramp-like" disturbances. See init_estimstoch.

Tip

Increasing σQ_int values increases the integral action "gain".

The constructor pre-compute the steady-state Kalman gain K with the kalman function. It can sometimes fail, for example when model is integrating. In such a case, you can use 0 integrator on model integrating outputs, or the alternative time-varying KalmanFilter.

source
SteadyKalmanFilter(model, i_ym, nint_ym, Q̂, R̂)

Construct the estimator from the augmented covariance matrices and .

This syntax allows nonzero off-diagonal elements in $\mathbf{Q̂, R̂}$.

source

KalmanFilter

ModelPredictiveControl.KalmanFilterType
KalmanFilter(model::LinModel; <keyword arguments>)

Construct a time-varying Kalman Filter with the LinModel model.

The process model is identical to SteadyKalmanFilter. The matrix $\mathbf{P̂}_k(k+1)$ is the estimation error covariance of model states augmented with the stochastic ones (specified by nint_ym). Two keyword arguments modify its initial value with $\mathbf{P̂}_{-1}(0) = \mathrm{diag}\{ \mathbf{P}(0), \mathbf{P_{int}}(0) \}$.

Arguments

  • model::LinModel : (deterministic) model for the estimations.
  • σP0=fill(1/model.nx,model.nx) : main diagonal of the initial estimate covariance $\mathbf{P}(0)$, specified as a standard deviation vector.
  • σP0_int=fill(1,sum(nint_ym)) : same than σP0 but for the stochastic model covariance $\mathbf{P_{int}}(0)$ (composed of output integrators).
  • <keyword arguments> of SteadyKalmanFilter constructor.

Examples

julia> model = LinModel([tf(3, [30, 1]); tf(-2, [5, 1])], 0.5);
+ 0 measured disturbances d

Extended Help

The model augmentation with nint_ym vector produces the integral action when the estimator is used in a controller as state feedback. The default is 1 integrator per measured outputs, resulting in an offset-free tracking for "step-like" unmeasured output disturbances. Use 2 integrators for "ramp-like" disturbances. See init_estimstoch.

Tip

Increasing σQ_int values increases the integral action "gain".

The constructor pre-compute the steady-state Kalman gain K with the kalman function. It can sometimes fail, for example when model is integrating. In such a case, you can use 0 integrator on model integrating outputs, or the alternative time-varying KalmanFilter.

source
SteadyKalmanFilter(model, i_ym, nint_ym, Q̂, R̂)

Construct the estimator from the augmented covariance matrices and .

This syntax allows nonzero off-diagonal elements in $\mathbf{Q̂, R̂}$.

source

KalmanFilter

ModelPredictiveControl.KalmanFilterType
KalmanFilter(model::LinModel; <keyword arguments>)

Construct a time-varying Kalman Filter with the LinModel model.

The process model is identical to SteadyKalmanFilter. The matrix $\mathbf{P̂}_k(k+1)$ is the estimation error covariance of model states augmented with the stochastic ones (specified by nint_ym). Two keyword arguments modify its initial value with $\mathbf{P̂}_{-1}(0) = \mathrm{diag}\{ \mathbf{P}(0), \mathbf{P_{int}}(0) \}$.

Arguments

  • model::LinModel : (deterministic) model for the estimations.
  • σP0=fill(1/model.nx,model.nx) : main diagonal of the initial estimate covariance $\mathbf{P}(0)$, specified as a standard deviation vector.
  • σP0_int=fill(1,sum(nint_ym)) : same than σP0 but for the stochastic model covariance $\mathbf{P_{int}}(0)$ (composed of output integrators).
  • <keyword arguments> of SteadyKalmanFilter constructor.

Examples

julia> model = LinModel([tf(3, [30, 1]); tf(-2, [5, 1])], 0.5);
 
 julia> estim = KalmanFilter(model, i_ym=[2], σR=[1], σP0=[100, 100], σQ_int=[0.01])
 KalmanFilter estimator with a sample time Ts = 0.5 s, LinModel and:
@@ -24,7 +24,7 @@
  3 states x̂
  1 measured outputs ym
  1 unmeasured outputs yu
- 0 measured disturbances d
source
KalmanFilter(model, i_ym, nint_ym, P̂0, Q̂, R̂)

Construct the estimator from the augmented covariance matrices P̂0, and .

This syntax allows nonzero off-diagonal elements in $\mathbf{P̂}_{-1}(0), \mathbf{Q̂, R̂}$.

source

Luenberger

ModelPredictiveControl.LuenbergerType
Luenberger(
+ 0 measured disturbances d
source
KalmanFilter(model, i_ym, nint_ym, P̂0, Q̂, R̂)

Construct the estimator from the augmented covariance matrices P̂0, and .

This syntax allows nonzero off-diagonal elements in $\mathbf{P̂}_{-1}(0), \mathbf{Q̂, R̂}$.

source

Luenberger

ModelPredictiveControl.LuenbergerType
Luenberger(
     model::LinModel; 
     i_ym = 1:model.ny, 
     nint_ym = fill(1, length(i_ym)),
@@ -37,7 +37,7 @@
  4 states x̂
  2 measured outputs ym
  0 unmeasured outputs yu
- 0 measured disturbances d
source

UnscentedKalmanFilter

UnscentedKalmanFilter

ModelPredictiveControl.UnscentedKalmanFilterType
UnscentedKalmanFilter(model::SimModel; <keyword arguments>)

Construct an unscented Kalman Filter with the SimModel model.

Both LinModel and NonLinModel are supported. The unscented Kalman filter is based on the process model :

\[\begin{aligned} \mathbf{x}(k+1) &= \mathbf{f̂}\Big(\mathbf{x}(k), \mathbf{u}(k), \mathbf{d}(k)\Big) + \mathbf{w}(k) \\ \mathbf{y^m}(k) &= \mathbf{ĥ^m}\Big(\mathbf{x}(k), \mathbf{d}(k)\Big) + \mathbf{v}(k) \\ @@ -50,7 +50,7 @@ 3 states x̂ 1 measured outputs ym 0 unmeasured outputs yu - 0 measured disturbances d

source
UnscentedKalmanFilter{M<:SimModel}(model::M, i_ym, nint_ym, P̂0, Q̂, R̂, α, β, κ)

Construct the estimator from the augmented covariance matrices P̂0, and .

This syntax allows nonzero off-diagonal elements in $\mathbf{P̂}_{-1}(0), \mathbf{Q̂, R̂}$.

source

ExtendedKalmanFilter

ModelPredictiveControl.ExtendedKalmanFilterType
ExtendedKalmanFilter(model::SimModel; <keyword arguments>)

Construct an extended Kalman Filter with the SimModel model.

Both LinModel and NonLinModel are supported. The process model is identical to UnscentedKalmanFilter. The Jacobians of the augmented model $\mathbf{f̂, ĥ}$ are computed with ForwardDiff.jl automatic differentiation.

Warning

See Extended Help if you get an error like: MethodError: no method matching (::var"##")(::Vector{ForwardDiff.Dual}).

Arguments

  • model::SimModel : (deterministic) model for the estimations.
  • <keyword arguments> of SteadyKalmanFilter constructor.
  • <keyword arguments> of KalmanFilter constructor.

Examples

julia> model = NonLinModel((x,u,_)->0.2x+u, (x,_)->-3x, 5.0, 1, 1, 1);
+ 0 measured disturbances d
source
UnscentedKalmanFilter{M<:SimModel}(model::M, i_ym, nint_ym, P̂0, Q̂, R̂, α, β, κ)

Construct the estimator from the augmented covariance matrices P̂0, and .

This syntax allows nonzero off-diagonal elements in $\mathbf{P̂}_{-1}(0), \mathbf{Q̂, R̂}$.

source

ExtendedKalmanFilter

ModelPredictiveControl.ExtendedKalmanFilterType
ExtendedKalmanFilter(model::SimModel; <keyword arguments>)

Construct an extended Kalman Filter with the SimModel model.

Both LinModel and NonLinModel are supported. The process model is identical to UnscentedKalmanFilter. The Jacobians of the augmented model $\mathbf{f̂, ĥ}$ are computed with ForwardDiff.jl automatic differentiation.

Warning

See Extended Help if you get an error like: MethodError: no method matching (::var"##")(::Vector{ForwardDiff.Dual}).

Arguments

  • model::SimModel : (deterministic) model for the estimations.
  • <keyword arguments> of SteadyKalmanFilter constructor.
  • <keyword arguments> of KalmanFilter constructor.

Examples

julia> model = NonLinModel((x,u,_)->0.2x+u, (x,_)->-3x, 5.0, 1, 1, 1);
 
 julia> estim = ExtendedKalmanFilter(model, σQ=[2], σQ_int=[2], σP0=[0.1], σP0_int=[0.1])
 ExtendedKalmanFilter estimator with a sample time Ts = 5.0 s, NonLinModel and:
@@ -58,10 +58,10 @@
  2 states x̂
  1 measured outputs ym
  0 unmeasured outputs yu
- 0 measured disturbances d

Extended Help

Automatic differentiation (AD) allows exact Jacobians. The NonLinModel f and h functions must be compatible with this feature though. See Automatic differentiation for common mistakes when writing these functions.

source
ExtendedKalmanFilter{M<:SimModel}(model::M, i_ym, nint_ym, P̂0, Q̂, R̂)

Construct the estimator from the augmented covariance matrices P̂0, and .

This syntax allows nonzero off-diagonal elements in $\mathbf{P̂}_{-1}(0), \mathbf{Q̂, R̂}$.

source

InternalModel

ModelPredictiveControl.InternalModelType
InternalModel(model::SimModel; i_ym=1:model.ny, stoch_ym=ss(1,1,1,1,model.Ts).*I)

Construct an internal model estimator based on model (LinModel or NonLinModel).

i_ym provides the model output indices that are measured $\mathbf{y^m}$, the rest are unmeasured $\mathbf{y^u}$. model evaluates the deterministic predictions $\mathbf{ŷ_d}$, and stoch_ym, the stochastic predictions of the measured outputs $\mathbf{ŷ_s^m}$ (the unmeasured ones being $\mathbf{ŷ_s^u=0}$). The predicted outputs sum both values : $\mathbf{ŷ = ŷ_d + ŷ_s}$.

Warning

InternalModel estimator does not work if model is integrating or unstable. The constructor verifies these aspects for LinModel but not for NonLinModel. Uses any other state estimator in such cases.

Examples

julia> estim = InternalModel(LinModel([tf(3, [30, 1]); tf(-2, [5, 1])], 0.5), i_ym=[2])
+ 0 measured disturbances d

Extended Help

Automatic differentiation (AD) allows exact Jacobians. The NonLinModel f and h functions must be compatible with this feature though. See Automatic differentiation for common mistakes when writing these functions.

source
ExtendedKalmanFilter{M<:SimModel}(model::M, i_ym, nint_ym, P̂0, Q̂, R̂)

Construct the estimator from the augmented covariance matrices P̂0, and .

This syntax allows nonzero off-diagonal elements in $\mathbf{P̂}_{-1}(0), \mathbf{Q̂, R̂}$.

source

InternalModel

ModelPredictiveControl.InternalModelType
InternalModel(model::SimModel; i_ym=1:model.ny, stoch_ym=ss(1,1,1,1,model.Ts).*I)

Construct an internal model estimator based on model (LinModel or NonLinModel).

i_ym provides the model output indices that are measured $\mathbf{y^m}$, the rest are unmeasured $\mathbf{y^u}$. model evaluates the deterministic predictions $\mathbf{ŷ_d}$, and stoch_ym, the stochastic predictions of the measured outputs $\mathbf{ŷ_s^m}$ (the unmeasured ones being $\mathbf{ŷ_s^u=0}$). The predicted outputs sum both values : $\mathbf{ŷ = ŷ_d + ŷ_s}$.

Warning

InternalModel estimator does not work if model is integrating or unstable. The constructor verifies these aspects for LinModel but not for NonLinModel. Uses any other state estimator in such cases.

Examples

julia> estim = InternalModel(LinModel([tf(3, [30, 1]); tf(-2, [5, 1])], 0.5), i_ym=[2])
 InternalModel estimator with a sample time Ts = 0.5 s, LinModel and:
  1 manipulated inputs u
  2 states x̂
  1 measured outputs ym
  1 unmeasured outputs yu
- 0 measured disturbances d

Extended Help

stoch_ym is a TransferFunction or StateSpace object that models disturbances on $\mathbf{y^m}$. Its input is a hypothetical zero mean white noise vector. stoch_ym supposes 1 integrator per measured outputs by default, assuming that the current stochastic estimate $\mathbf{ŷ_s^m}(k) = \mathbf{y^m}(k) - \mathbf{ŷ_d^m}(k)$ is constant in the future. This is the dynamic matrix control (DMC) strategy, which is simple but sometimes too aggressive. Additional poles and zeros in stoch_ym can mitigate this.

source
+ 0 measured disturbances d

Extended Help

stoch_ym is a TransferFunction or StateSpace object that models disturbances on $\mathbf{y^m}$. Its input is a hypothetical zero mean white noise vector. stoch_ym supposes 1 integrator per measured outputs by default, assuming that the current stochastic estimate $\mathbf{ŷ_s^m}(k) = \mathbf{y^m}(k) - \mathbf{ŷ_d^m}(k)$ is constant in the future. This is the dynamic matrix control (DMC) strategy, which is simple but sometimes too aggressive. Additional poles and zeros in stoch_ym can mitigate this.

source diff --git a/dev/search/index.html b/dev/search/index.html index d8999c695..0dc7d070a 100644 --- a/dev/search/index.html +++ b/dev/search/index.html @@ -1,2 +1,2 @@ -Search · ModelPredictiveControl.jl

Loading search...

    +Search · ModelPredictiveControl.jl

    Loading search...