Optimal Control Problems#
Problems are usually formulated using cyqlone::LinearOCPStorage.
To pass them to the Cyqlone solver, they need to be converted to cyqlone::CyqloneStorage
format, where the initial state is eliminated. For testing, it can be helpful to convert the
problem to a sparse QP format, which is supported by cyqlone::LinearOCPSparseQP.
-
struct LinearOCPStorage
Storage for a linear-quadratic OCP of the form.
ₙ₋₁ minimize ∑ [½ uᵢᵀ Rᵢ uᵢ + uᵢᵀ S xᵢ + ½ xᵢᵀ Qᵢ xᵢ + rᵢᵀuᵢ + qᵢᵀxᵢ] + ½ xₙᵀ Qₙ xₙ + qₙᵀ xₙ ⁱ⁼⁰ s.t. x₀ = b₀ xᵢ₊₁ = Aᵢ xᵢ + Bᵢ uᵢ + bᵢ₊₁ lᵢ ≤ Cᵢ xᵢ + Dᵢ uᵢ ≤ uᵢ lₙ ≤ Cₙ xₙ ≤ uₙPublic Functions
-
inline guanaqo::MatrixView<real_t, index_t> H(index_t i)
-
inline guanaqo::MatrixView<real_t, index_t> Q(index_t i)
-
inline guanaqo::MatrixView<real_t, index_t> R(index_t i)
-
inline guanaqo::MatrixView<real_t, index_t> S(index_t i)
-
inline guanaqo::MatrixView<real_t, index_t> S_trans(index_t i)
-
inline guanaqo::MatrixView<real_t, index_t> CD(index_t i)
-
inline guanaqo::MatrixView<real_t, index_t> C(index_t i)
-
inline guanaqo::MatrixView<real_t, index_t> D(index_t i)
-
inline guanaqo::MatrixView<real_t, index_t> AB(index_t i)
-
inline guanaqo::MatrixView<real_t, index_t> A(index_t i)
-
inline guanaqo::MatrixView<real_t, index_t> B(index_t i)
-
inline guanaqo::MatrixView<const real_t, index_t> H(index_t i) const
-
inline guanaqo::MatrixView<const real_t, index_t> Q(index_t i) const
-
inline guanaqo::MatrixView<const real_t, index_t> R(index_t i) const
-
inline guanaqo::MatrixView<const real_t, index_t> S(index_t i) const
-
inline guanaqo::MatrixView<const real_t, index_t> S_trans(index_t i) const
-
inline guanaqo::MatrixView<const real_t, index_t> CD(index_t i) const
-
inline guanaqo::MatrixView<const real_t, index_t> C(index_t i) const
-
inline guanaqo::MatrixView<const real_t, index_t> D(index_t i) const
-
inline guanaqo::MatrixView<const real_t, index_t> AB(index_t i) const
-
inline guanaqo::MatrixView<const real_t, index_t> A(index_t i) const
-
inline guanaqo::MatrixView<const real_t, index_t> B(index_t i) const
-
inline index_t num_variables() const
-
inline index_t num_constraints() const
-
inline index_t num_dynamics_constraints() const
-
inline guanaqo::MatrixView<real_t, index_t> qr()
-
inline guanaqo::MatrixView<real_t, index_t> qr(index_t i)
-
inline guanaqo::MatrixView<real_t, index_t> q(index_t i)
-
inline guanaqo::MatrixView<real_t, index_t> r(index_t i)
-
inline guanaqo::MatrixView<real_t, index_t> b()
-
inline guanaqo::MatrixView<real_t, index_t> b(index_t i)
-
inline guanaqo::MatrixView<real_t, index_t> b_min()
-
inline guanaqo::MatrixView<real_t, index_t> b_min(index_t i)
-
inline guanaqo::MatrixView<real_t, index_t> b_max()
-
inline guanaqo::MatrixView<real_t, index_t> b_max(index_t i)
-
inline guanaqo::MatrixView<const real_t, index_t> qr() const
-
inline guanaqo::MatrixView<const real_t, index_t> qr(index_t i) const
-
inline guanaqo::MatrixView<const real_t, index_t> q(index_t i) const
-
inline guanaqo::MatrixView<const real_t, index_t> r(index_t i) const
-
inline guanaqo::MatrixView<const real_t, index_t> b() const
-
inline guanaqo::MatrixView<const real_t, index_t> b(index_t i) const
-
inline guanaqo::MatrixView<const real_t, index_t> b_min() const
-
inline guanaqo::MatrixView<const real_t, index_t> b_min(index_t i) const
-
inline guanaqo::MatrixView<const real_t, index_t> b_max() const
-
inline guanaqo::MatrixView<const real_t, index_t> b_max(index_t i) const
Public Members
-
OCPDim dim = {}
-
std::vector<real_t> storage = create_storage(dim)
Create a single contiguous storage for all problem data.
Storage layout: size offset N × [ Q Sᵀ] = H (nx+nu)² 0 [ S R ] 1 × [ Q ] nx² N (nx+nu)² N × [ C D ] ny(nx+nu) N (nx+nu)² + nx² 1 × [ C ] ny_N nx N (nx+nu+ny)(nx+nu) + nx² N × [ A B ] nx(nx+nu) N (nx+nu+ny)(nx+nu) + (nx+ny_N)nx N × [ q r ] nx+nu N (2nx+nu+ny)(nx+nu) + (nx+ny_N)nx 1 × [ q ] nx N (2nx+nu+ny+1)(nx+nu) + (nx+ny_N)nx N+1 × [ b ] nx N (2nx+nu+ny+1)(nx+nu) + (nx+ny_N+1)nx N × [ l ] ny N (2nx+nu+ny+1)(nx+nu) + (nx+ny_N+2+N)nx 1 × [ l ] ny_N N (2nx+nu+ny+1)(nx+nu) + (nx+ny_N+2+N)nx + N ny N × [ u ] ny N (2nx+nu+ny+1)(nx+nu) + (nx+ny_N+2+N)nx + N ny + ny_N 1 × [ u ] ny_N N (2nx+nu+ny+1)(nx+nu) + (nx+ny_N+2+N)nx + N (2ny) + ny_N N (2nx+nu+ny+1)(nx+nu) + (nx+ny_N+2+N)nx + N (2ny) + 2ny_N
Public Static Functions
-
static inline std::vector<real_t> create_storage(OCPDim dim)
-
struct Solution
Public Functions
-
inline guanaqo::MatrixView<real_t, index_t> x(OCPDim dim)
-
inline guanaqo::MatrixView<const real_t, index_t> x(OCPDim dim) const
-
inline guanaqo::MatrixView<real_t, index_t> x(OCPDim dim, index_t i)
-
inline guanaqo::MatrixView<const real_t, index_t> x(OCPDim dim, index_t i) const
-
inline guanaqo::MatrixView<real_t, index_t> u(OCPDim dim)
-
inline guanaqo::MatrixView<const real_t, index_t> u(OCPDim dim) const
-
inline guanaqo::MatrixView<real_t, index_t> u(OCPDim dim, index_t i)
-
inline guanaqo::MatrixView<const real_t, index_t> u(OCPDim dim, index_t i) const
- inline guanaqo::MatrixView< real_t, index_t > λ (OCPDim dim)
- inline guanaqo::MatrixView< const real_t, index_t > λ (OCPDim dim) const
- inline guanaqo::MatrixView< real_t, index_t > λ (OCPDim dim, index_t i)
- inline guanaqo::MatrixView< const real_t, index_t > λ (OCPDim dim, index_t i) const
-
inline guanaqo::MatrixView<real_t, index_t> y(OCPDim dim, index_t i)
-
inline guanaqo::MatrixView<const real_t, index_t> y(OCPDim dim, index_t i) const
Public Members
-
std::vector<real_t> solution
-
std::vector<real_t> inequality_multipliers
-
std::vector<real_t> equality_multipliers
-
inline guanaqo::MatrixView<real_t, index_t> x(OCPDim dim)
-
struct KKTError
Public Members
-
real_t stationarity
-
real_t inequality_residual
-
real_t equality_residual
-
real_t complementarity
-
real_t stationarity
-
inline guanaqo::MatrixView<real_t, index_t> H(index_t i)
-
template<class T = real_t>
struct CyqloneStorage Storage for a linear-quadratic OCP with the initial states x₀ eliminated.
The matrices are combined per stage, with inputs ordered first. The first and last stage are special because of the lack of x₀ and uₙ.ₙ₋₁ minimize ∑ [½ uᵢᵀ Rᵢ uᵢ + uᵢᵀ Sᵢ xᵢ + ½ xᵢᵀ Qᵢ xᵢ + rᵢᵀuᵢ + qᵢᵀxᵢ] ⁱ⁼¹ + ½ u₀ᵀ R₀ u₀ + (r₀ + S₀ xᵢₙᵢₜ)ᵀ u₀ + ½ xₙᵀ Qₙ xₙ + qₙᵀ xₙ s.t. xᵢ₊₁ = Aᵢ xᵢ + Bᵢ uᵢ + cᵢ lᵢ ≤ Cᵢ xᵢ + Dᵢ uᵢ ≤ uᵢ l₀ - C₀ xᵢₙᵢₜ ≤ D₀ U₀ ≤ u₀ - C₀ xᵢₙᵢₜ lₙ ≤ Cₙ xₙ ≤ uₙDue to the elimination of x₀, there may be fewer constraints for the first stage, which is tracked by the Ju0 mask. When reconstructing the solution, the multipliers for eliminated constraints are set to zero (we assume that the initial state is feasible w.r.t. the state constraints).Hᵢ = [ Rᵢ Sᵢ ], H₀ = [ R₀ 0 ], Fᵢ = [ Bᵢ Aᵢ ], Gᵢ = [ Dᵢ Cᵢ ], G₀ = [ D₀ Cₙ ] [ Sᵢᵀ Qᵢ ] [ 0 Qₙ ]Public Types
-
using value_type = T
-
using matrix = batmat::matrix::Matrix<value_type, index_t>
-
using Solution = LinearOCPStorage::Solution
-
using KKTError = LinearOCPStorage::KKTError
Public Functions
-
void update_impl(const LinearOCPStorage &ocp)
-
void update(const LinearOCPStorage &ocp)
-
void reconstruct_ineq_multipliers(std::span<const value_type> y_compressed, std::span<value_type> y) const
-
std::vector<value_type> reconstruct_ineq_multipliers(std::span<const value_type> y_compressed) const
- Solution reconstruct_solution (const LinearOCPStorage &ocp, std::span< const value_type > ux_compressed, std::span< const value_type > y_compressed, std::span< const value_type > λ_compressed) const
- KKTError compute_kkt_error (const LinearOCPStorage &ocp, std::span< const value_type > ux_compressed, std::span< const value_type > y_compressed, std::span< const value_type > λ_compressed) const
Public Members
-
index_t N_horiz
-
index_t nx
-
index_t nu
-
index_t ny
-
index_t ny_0
-
index_t ny_N
-
std::vector<bool> Ju0
-
matrix data_H =
[this] {returnmatrix{{.depth = N_horiz, .rows = nu + nx, .cols = nu + nx}};}()
-
matrix data_F =
[this] { return matrix{{.depth = N_horiz, .rows = nx, .cols = nu + nx}}; }()
-
matrix data_G =
[this] {returnmatrix{{.depth = N_horiz - 1, .rows = ny, .cols = nu + nx}};}()
-
matrix data_G0N =
[this] {returnmatrix{{.depth = 1, .rows = ny_0 + ny_N, .cols = nu + nx}};}()
-
matrix data_rq =
[this] { return matrix{{.depth = N_horiz, .rows = nu + nx, .cols = 1}}; }()
-
matrix data_c =
[this] { return matrix{{.depth = N_horiz, .rows = nx, .cols = 1}}; }()
-
matrix data_lb =
[this] { return matrix{{.depth = N_horiz - 1, .rows = ny, .cols = 1}}; }()
-
matrix data_lb0N =
[this] { return matrix{{.depth = 1, .rows = ny_0 + ny_N, .cols = 1}}; }()
-
matrix data_ub =
[this] { return matrix{{.depth = N_horiz - 1, .rows = ny, .cols = 1}}; }()
-
matrix data_ub0N =
[this] { return matrix{{.depth = 1, .rows = ny_0 + ny_N, .cols = 1}}; }()
-
std::vector<index_t> indices_G0 = std::vector<index_t>(ny_0)
Public Static Functions
-
static CyqloneStorage build(const LinearOCPStorage &ocp, index_t ny_0 = -1)
-
static index_t count_constr_0(const LinearOCPStorage &ocp, std::vector<bool> &Ju0)
-
using value_type = T
-
struct LinearOCPSparseQP
Represents a sparse multiple shooting formulation of the standard optimal control problem.
Public Functions
- KKTMatrix build_kkt (real_t S, std::span< const real_t > Σ, std::span< const bool > J) const
Returns the lower part of the symmetric indefinite KKT matrix for the active set
Jand penalty factorsΣ.
Public Members
-
std::vector<index_t> Q_outer_ptr
-
std::vector<index_t> Q_inner_idx
-
std::vector<real_t> Q_values
-
SparseCSC<index_t, index_t> Q_sparsity
-
std::vector<index_t> A_outer_ptr
-
std::vector<index_t> A_inner_idx
-
std::vector<real_t> A_values
-
SparseCSC<index_t, index_t> A_sparsity
-
index_t n
-
index_t m_eq
-
index_t m_ineq
Public Static Functions
-
static LinearOCPSparseQP build(const LinearOCPStorage &ocp)
-
struct KKTMatrix
Public Members
-
std::vector<index_t> outer_ptr
-
std::vector<index_t> inner_idx
-
std::vector<real_t> values
-
SparseCSC<index_t, index_t> sparsity
-
std::vector<index_t> outer_ptr