Skip to content

Concepts

This section documents the mathematical structure behind affine_mpc. It is shared between the C++ and Python interfaces.

Supported Optimization Problem

affine_mpc assumes a discrete-time affine, time-invariant model

\[ \bm{x}_{k+1} = A \bm{x}_k + B \bm{u}_k + \bm{w}, \]

and solves a finite-horizon tracking MPC problem in which the dense input trajectory is parameterized by control points through some mapping \(\bm{u}_k = g_k(\bm{c}_0, \dots, \bm{c}_{\eta-1})\). The same mathematical problem supports both library formulations, chosen with the Formulation argument of MPC: the condensed formulation (the default) optimizes only the control points, while the sparse formulation keeps the predicted states in the QP decision vector as well.

The library supports the following cost and constraint structure, with several optional terms controlled by Options (labeled in \(\textcolor{red}{\text{red}}\) below):

\[ \begin{align} \min &\quad J = \left\lVert \bm{x}_{\mathrm{ref},T} - \bm{x}_T \right\rVert^2_{Q_{\mathrm{f}}} % terminal cost + \sum_{k=1}^{T-1} \left\lVert \bm{x}_{\mathrm{ref},k} - \bm{x}_k \right\rVert^2_Q \\ % state stracking cost &\qquad\quad + \: \underbrace{ \sum_{i=0}^{\eta-1} \lVert \bm{c}_{\mathrm{ref},i} - \bm{c}_i \rVert^2_R }_{ \textcolor{red}{\text{control point cost}} } \quad \text{OR} \quad \underbrace{ \sum_{k=0}^{T-1} \lVert \bm{u}_{\mathrm{ref},k} - \bm{u}_k \rVert^2_R }_{ \textcolor{red}{\text{input trajectory cost}} } \\ &\qquad\quad + \: \underbrace{ \sum_{k=0}^{T-1} \lVert \bm{u}_k - \bm{u}_{k-1} \rVert^2_{R_\Delta} }_{ \textcolor{red}{\text{input rate cost}} } \\ &\qquad\quad + \: \underbrace{ \bm{\rho}_1^\T \bm{s} + \lVert \bm{s} \rVert^2_{\diag(\bm{\rho}_2)} }_{ \textcolor{red}{\text{soft state bounds}} } \\ \text{w.r.t.} &\quad \bm{c}_0, \dots ,\bm{c}_{\eta-1}, \quad \underbrace{ \bm{x}_1, \dots, \bm{x}_T }_{ \textcolor{magenta}{\text{sparse only}} }, \quad \underbrace{ \bm{s} }_{ \textcolor{red}{\text{soft state bounds}} } \\ \text{s.t.} &\quad \bm{x}_{k+1} = A \bm{x}_k + B \bm{u}_k + \bm{w} \\ &\quad \bm{u}_k = g_k(\bm{c}_0, \dots, \bm{c}_{\eta-1}) \\ &\quad \bm{u}_{\min} \leq \bm{c}_i \leq \bm{u}_{\max} \quad \text{OR} \quad \underbrace{ \bm{u}_{\min} \leq \Omega \bm{c} \leq \bm{u}_{\max} }_{ \textcolor{red}{\text{refined input bounds}} } \quad \text{OR} \quad \underbrace{ \bm{u}_{\min} \leq \bm{u}_k \leq \bm{u}_{\max} }_{ \textcolor{red}{\text{trajectory input bounds}} } \\ &\quad \underbrace{ \bm{x}_{\min} \leq \bm{x}_k \leq \bm{x}_{\max} }_{ \textcolor{red}{\text{hard state bounds}} } \quad \text{OR} \quad \underbrace{ \bm{x}_{\min} - \bm{s} \leq \bm{x}_k \leq \bm{x}_{\max} + \bm{s} }_{ \textcolor{red}{\text{soft state bounds}} } \\ &\quad \underbrace{ |\bm{u}_0 - \bm{u}_{{-}1}| \leq \bm{u}_{0,\mathrm{slew}} }_{ \textcolor{red}{\text{initial slew rate}} } \\ &\quad \underbrace{ |\bm{c}_i - \bm{c}_{i-1}| \leq \lambda_i \bm{u}_{\mathrm{slew}} }_{ \textcolor{red}{\text{control point slew bounds}} } \quad \text{OR} \quad \underbrace{ |\bm{u}_k - \bm{u}_{k-1}| \leq \bm{u}_{\mathrm{slew}} }_{ \textcolor{red}{\text{trajectory slew bounds}} } \\ &\quad \underbrace{ \bm{h}_{\min} \leq H_x \bm{x}_k + H_u \bm{u}_k \leq \bm{h}_{\max} }_{ \textcolor{red}{\text{general constraints}} } \\ &\quad \underbrace{ \bm{h}_{\mathrm{f},\min} \leq H_{\mathrm{f}} \bm{x}_T \leq \bm{h}_{\mathrm{f},\max} }_{ \textcolor{red}{\text{terminal constraints}} } \end{align} \]

The weighted norm used above is defined as \(\: \left\lVert \bm{y} \right\rVert^2_M = \bm{y}^\T M \bm{y}\).

How to enable each labeled term in code

Unlabeled terms are always present; each labeled term is enabled at construction by a field of Options (values are enum members in both interfaces, e.g. InputCostMode::Trajectory in C++ and InputCostMode.Trajectory in Python).

Options field Type Choices
input_cost InputCostMode Off (default)
ControlPoints → \(\textcolor{red}{\text{control point cost}}\)
Trajectory → \(\textcolor{red}{\text{input trajectory cost}}\)
use_input_rate_cost bool false (default)
true → \(\textcolor{red}{\text{input rate cost}}\)
input_bounds InputBoundMode ControlPoints (default)
Refined → \(\textcolor{red}{\text{refined input bounds}}\)
Trajectory → \(\textcolor{red}{\text{trajectory input bounds}}\)
slew_initial_input bool false (default)
true → \(\textcolor{red}{\text{initial slew rate}}\)
slew_bounds SlewBoundMode Off (default)
ControlPoints → \(\textcolor{red}{\text{control point slew bounds}}\)
Trajectory → \(\textcolor{red}{\text{trajectory slew bounds}}\)
state_bounds StateBoundMode Off (default)
Hard → \(\textcolor{red}{\text{hard state bounds}}\)
Soft → \(\textcolor{red}{\text{soft state bounds}}\)
num_general_constraints int 0 (default)
> 0 → \(\textcolor{red}{\text{general constraints}}\)
num_terminal_constraints int 0 (default)
> 0 → \(\textcolor{red}{\text{terminal constraints}}\)
MPC Terms
Symbol Meaning
\(n\) state dimension
\(m\) input dimension
\(n_b\) number of bounded states (bounded_states; \(n_b = n\) by default)
\(T\) number of steps in the prediction horizon
\(\eta\) number of control points that parameterize the input trajectory
\(\bm{x}_k \in \R^n\) state vector at horizon step \(k\)
\(\bm{u}_k \in \R^m\) input vector applied at horizon step \(k\)
\(A \in \R^{n \times n}\) discrete-time state matrix
\(B \in \R^{n \times m}\) discrete-time input matrix
\(\bm{w} \in \R^n\) discrete-time model offset
\(\bm{u}_{-1} \in \R^m\) previous input, applied before the current horizon
\(\bm{c}_i \in \R^m\) control point vector at index \(i\)
\(\bm{x}_{\mathrm{ref},k} \in \R^n\) reference state at horizon step \(k\)
\(\bm{c}_{\mathrm{ref},i} \in \R^m\) reference control point at index \(i\)
\(\bm{u}_{\mathrm{ref},k} \in \R^m\) reference input at horizon step \(k\) (InputCostMode::Trajectory)
\(Q \in \R^{n \times n} \succeq 0\) diagonal state weights
\(Q_{\mathrm{f}} \in \R^{n \times n} \succeq 0\) diagonal terminal state weights
\(R \in \R^{m \times m} \succeq 0\) diagonal input weights, on the control points or the sampled inputs (input_cost)
\(R_\Delta \in \R^{m \times m} \succeq 0\) diagonal input rate weights
\(\bm{u}_{\min}, \bm{u}_{\max} \in \R^m\) input limits
\(\bm{x}_{\min}, \bm{x}_{\max} \in \R^{n_b}\) state limits of the bounded states
\(\bm{u}_{0,\mathrm{slew}} \in \R^m\) slew rate limit of the initial input
\(\bm{u}_{\mathrm{slew}} \in \R^m\) slew rate limit per sample step, on \(\bm{u}_k - \bm{u}_{k-1}\) for \(k \geq 1\)
\(\bm{s} \in \R^{n_b}\) slack of the soft state bounds, one per bounded state
\(\bm{\rho}_1, \bm{\rho}_2 \in \R^{n_b}\) L1 and L2 penalties of the slack
\(n_h\), \(n_{h,\mathrm{f}}\) number of general and terminal constraints
\(H_x \in \R^{n_h \times n}\), \(H_u \in \R^{n_h \times m}\) state and input matrices of the general constraints
\(\bm{h}_{\min}, \bm{h}_{\max} \in \R^{n_h}\) bounds of the general constraints
\(H_{\mathrm{f}} \in \R^{n_{h,\mathrm{f}} \times n}\) state matrix of the terminal constraints
\(\bm{h}_{\mathrm{f},\min}, \bm{h}_{\mathrm{f},\max} \in \R^{n_{h,\mathrm{f}}}\) bounds of the terminal constraints

Section Guide