10#include <Eigen/Sparse>
15namespace smooth::feedback {
29template<
typename Problem>
36 Eigen::SparseMatrix<double, Eigen::ColMajor, c_int> P;
37 Eigen::SparseMatrix<double, Eigen::ColMajor, c_int> A;
38 if constexpr (std::is_base_of_v<Eigen::SparseMatrixBase<
decltype(pbm.A)>,
decltype(pbm.A)>) {
40 P = pbm.P.template triangularView<Eigen::Upper>();
42 A = pbm.A.sparseView();
43 Eigen::MatrixXd Pup = pbm.P.template triangularView<Eigen::Upper>();
51 OSQPSettings * settings = (OSQPSettings *)c_malloc(
sizeof(OSQPSettings));
52 osqp_set_default_settings(settings);
54 settings->verbose = prm.
verbose;
55 settings->sigma = prm.
sigma;
56 settings->alpha = prm.
alpha;
57 settings->rho = prm.
rho;
58 settings->eps_abs = prm.
eps_abs;
59 settings->eps_rel = prm.
eps_rel;
62 settings->scaling = prm.
scaling;
64 settings->polish = prm.
polish;
66 settings->delta = prm.
delta;
68 settings->adaptive_rho =
false;
69 settings->linsys_solver = QDLDL_SOLVER;
70 settings->scaled_termination =
false;
73 settings->max_iter = prm.
max_iter.value();
75 settings->max_iter = std::numeric_limits<c_int>::max();
78 settings->time_limit = duration_cast<std::chrono::duration<double>>(prm.
max_time.value()).count();
80 settings->time_limit = 0;
83 OSQPData * data = (OSQPData *)c_malloc(
sizeof(OSQPData));
86 data->A = csc_matrix(A.rows(), A.cols(), A.nonZeros(), A.valuePtr(), A.innerIndexPtr(), A.outerIndexPtr());
87 data->q =
const_cast<double *
>(pbm.q.data());
88 data->P = csc_matrix(P.rows(), P.cols(), P.nonZeros(), P.valuePtr(), P.innerIndexPtr(), P.outerIndexPtr());
89 data->l =
const_cast<double *
>(pbm.l.data());
90 data->u =
const_cast<double *
>(pbm.u.data());
94 QPSolution<-1, -1,
double> ret;
95 ret.code = QPSolutionStatus::Unknown;
97 c_int error = osqp_setup(&work, data, settings);
100 osqp_warm_start(work, warmstart.value().get().primal.data(), warmstart.value().get().dual.data());
101 settings->warm_start = 1;
103 settings->warm_start = 0;
106 if (!error) { error &= osqp_solve(work); }
109 switch (work->info->status_val) {
111 ret.code = QPSolutionStatus::Optimal;
114 case OSQP_PRIMAL_INFEASIBLE: {
115 ret.code = QPSolutionStatus::PrimalInfeasible;
118 case OSQP_DUAL_INFEASIBLE: {
119 ret.code = QPSolutionStatus::DualInfeasible;
122 case OSQP_MAX_ITER_REACHED: {
123 ret.code = QPSolutionStatus::MaxIterations;
126 case OSQP_TIME_LIMIT_REACHED: {
127 ret.code = QPSolutionStatus::MaxTime;
135 ret.iter = work->info->iter;
136 ret.primal = Eigen::Map<
const Eigen::Matrix<double, -1, 1>>(work->solution->x, data->n);
137 ret.dual = Eigen::Map<
const Eigen::Matrix<double, -1, 1>>(work->solution->y, data->m);
138 ret.objective = work->info->obj_val;
QPSolution<-1, -1, double > solve_qp_osqp(const Problem &pbm, const QPSolverParams &prm, std::optional< std::reference_wrapper< const QPSolution<-1, -1, double > > > warmstart={})
Solve a QuadraticProgram with the OSQP solver.
Quadratic Program solver.
float rho
first dual step size
uint32_t stop_check_iter
iterations between checking stopping criterion
std::optional< uint32_t > max_iter
max number of iterations (default no limit)
bool scaling
scale problem
float alpha
relaxation parameter
float eps_dual_inf
threshold for dual infeasibility
std::optional< std::chrono::nanoseconds > max_time
max solution time (default no limit)
float eps_rel
relative threshold for convergence
bool verbose
print solver info to stdout
bool polish
run solution polishing (uses dynamic memory)
float eps_primal_inf
threshold for primal infeasibility
float eps_abs
absolute threshold for convergence
uint32_t polish_iter
number of iterations to refine polish
float delta
regularization parameter for polishing
float sigma
second dual step length