osqp-eigen使用记录

1. 环境配置

参考这两篇文章安装osqp和eigen3(都装在了/usr/local下):

18.04安装osqp-eigen_夜半__的博客-CSDN博客

ubuntu 安装使用eigen3 (两种方式)_樱桃木的博客-CSDN博客

其中osqp可以用build/out/osqp_demo进行测试。

osqp-eigen的安装也是参照第一篇参考文章。测试方式需要手动对example里给的MPCExample进行编译运行,最后是可以成功实现的。

osqp-eigen使用记录_第1张图片

2. 例子练习

用了这里面最后一个例子做了编程练习

OSQP使用说明 - 知乎

也可以参考这篇:使用OSQP解决二次凸优化(QP)问题_shoufei403的博客-CSDN博客

(1)QP问题的基本问题:

优化目标:\( \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写成一个数就行了。

(2)Eigen使用的问题

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可以看到。

输出结果:

osqp-eigen使用记录_第2张图片

 

(3) OSQP基本知识

Data,Setting,Solver三个部分去看:osqp-eigen

内部的设置和使用,还是去啃osqp官网比较好:The solver — OSQP documentation

你可能感兴趣的:(编程,c++)