参考这两篇文章安装osqp和eigen3(都装在了/usr/local下):
18.04安装osqp-eigen_夜半__的博客-CSDN博客
ubuntu 安装使用eigen3 (两种方式)_樱桃木的博客-CSDN博客
其中osqp可以用build/out/osqp_demo进行测试。
osqp-eigen的安装也是参照第一篇参考文章。测试方式需要手动对example里给的MPCExample进行编译运行,最后是可以成功实现的。
用了这里面最后一个例子做了编程练习
OSQP使用说明 - 知乎
也可以参考这篇:使用OSQP解决二次凸优化(QP)问题_shoufei403的博客-CSDN博客
优化目标:\( \frac{1}{2}x^{T}Hx + f^{T}x\)
约束(OSQP中等式和不等式约束放在一起了):\( lb \leq Ax \leq ub\)
这里的\( H\)就是Hessian矩阵,\( f\)就是Gradient,\( A\)就是Linear Constrain Matrix,如果是等式约束,就把lb和up写成一个数就行了。
i. 有几个矩阵是SparseMatrix类型的,其不能使用<<流操作赋值,好像只能使用insert方法。
mat.insert(i, j) = val; 详见Eigen的手册如下:
Eigen: Sparse matrix manipulations
直接放代码了
#include
// osqp-eigen
#include "OsqpEigen/OsqpEigen.h"
// eigen
#include
using namespace std;
Eigen::SparseMatrix hessian;
Eigen::VectorXd gradient;
Eigen::SparseMatrix linearMatrix;
Eigen::VectorXd lowerBound;
Eigen::VectorXd upperBound;
int initMat(OsqpEigen::Solver& solver)
{
unsigned int numOfVar = 3;
unsigned int numOfCons = 4;
solver.data()->setNumberOfVariables(numOfVar);
solver.data()->setNumberOfConstraints(numOfCons);
hessian.resize(numOfVar, numOfVar);
gradient.resize(numOfVar);
linearMatrix.resize(numOfCons, numOfVar);
lowerBound.resize(numOfCons);
upperBound.resize(numOfCons);
hessian.insert(0, 0) = 1;
hessian.insert(0, 1) = -1;
hessian.insert(0, 2) = 1;
hessian.insert(1, 0) = -1;
hessian.insert(1, 1) = 2;
hessian.insert(1, 2) = -2;
hessian.insert(2, 0) = 1;
hessian.insert(2, 1) = -2;
hessian.insert(2, 2) = 4;
//cout << "hessian" << hessian << endl;
/* hessian << 1, -1, 1,
-1, 2, -2,
1, -2, 4;*/
gradient << 2, -3, 1;
linearMatrix.insert(0, 0) = 1;
linearMatrix.insert(1, 1) = 1;
linearMatrix.insert(2, 2) = 1;
linearMatrix.insert(3, 0) = 1;
linearMatrix.insert(3, 1) = 1;
linearMatrix.insert(3, 2) = 1;
/*linearMatrix << 1, 0, 0,
0, 1, 0,
0, 0, 1,
1, 1, 1;*/
lowerBound << 0, 0, 0, 0.5;
upperBound << 1, 1, 1, 0.5;
if (!solver.data()->setHessianMatrix(hessian)) return false;
if (!solver.data()->setGradient(gradient)) return false;
if (!solver.data()->setLinearConstraintsMatrix(linearMatrix)) return false;
if (!solver.data()->setLowerBound(lowerBound)) return false;
if (!solver.data()->setUpperBound(upperBound)) return false;
return true;
}
int main() {
OsqpEigen::Solver solver;
// set the solver
solver.settings()->setWarmStart(true);
// instantiate the solver
if (initMat(solver)) {
if (!solver.initSolver()) return 1;
}
else {
cout << "initilize QP solver failed" << endl;
return 1;
}
// solve
solver.solve();
Eigen::VectorXd QPSolution;
QPSolution = solver.getSolution();
cout << "x1 = " << QPSolution[0] << endl
<< "x2 = " << QPSolution[1] << endl
<< "x3 = " << QPSolution[2] << endl;
}
避坑1:
solver.data()->set这几个函数,底层是传递指针的方式,所以这几个函数的入参不能是局部变量,否则会被释放掉。从osqp里的type.h可以看到。
输出结果:
Data,Setting,Solver三个部分去看:osqp-eigen
内部的设置和使用,还是去啃osqp官网比较好:The solver — OSQP documentation