二次规划(QP)与OSQP求解器

优化在很多领域都发挥着重要应用,其中自动驾驶的运动规划可以看做一个优化问题,根据实际情况进行合理简化和建模。

一个优化问题包含:优化目标和约束条件(包含等式约束、不等式约束)。

如果约束条件或目标函数包含非线性,则为非线性优化。二次规划是一种特殊的非线性规划,也是标准的凸优化问题,能够快速求解。

在路径/轨迹优化中经常建模为二次优化问题进行求解,很多MPC的求解过程也是转化为序列二次规划进行求解。

二次优化的标准形式为:

minimize\ \frac{1}{2} x^{T}Px + q^{T}x

subject \ to \ l\leq Ax \leq u

关于二次项系数的正定性,以及优化理论的剖析,此处暂不做探讨,可以阅读参考文献,待了解更加深入后再进行补充。

OSQP 求解器

OSQP官方无C++接口,有两个推荐的第三方维护的接口:google的osqp-cpp与Giulio Romualdi的osqp-eigen. 

以Apollo中的osqp-eigen为例(通常有固定的代码书写流程)

以下列问题的求解为例:

min \bigl(\begin{smallmatrix} x_{1} -1 \end{smallmatrix}\bigr)^{2} +\bigl(\begin{smallmatrix} x_{1} -2 \end{smallmatrix}\bigr)^{2}

s.t. \0 \leq x_{1} \leq 1.5, \0 \leq x_{2} \leq 1.5​​

// osqp-eigen
#include "OsqpEigen/OsqpEigen.h"

// eigen
#include 
#include 

int main()
{
    // allocate QP problem matrices and vectores
    Eigen::SparseMatrix hessian(2, 2);      //P: n*n正定矩阵,必须为稀疏矩阵SparseMatrix
    Eigen::VectorXd gradient(2);                    //Q: n*1向量
    Eigen::SparseMatrix linearMatrix(2, 2); //A: m*n矩阵,必须为稀疏矩阵SparseMatrix
    Eigen::VectorXd lowerBound(2);                  //L: m*1下限向量
    Eigen::VectorXd upperBound(2);                  //U: m*1上限向量

    hessian.insert(0, 0) = 2.0; //注意稀疏矩阵的初始化方式,无法使用<<初始化
    hessian.insert(1, 1) = 2.0;
    // std::cout << "hessian:" << std::endl
    //           << hessian << std::endl;
    gradient << -2, -2;
    linearMatrix.insert(0, 0) = 1.0; //注意稀疏矩阵的初始化方式,无法使用<<初始化
    linearMatrix.insert(1, 1) = 1.0;
    // std::cout << "linearMatrix:" << std::endl
    //           << linearMatrix << std::endl;
    lowerBound << 1, 1;
    upperBound << 1.5, 1.5;

    // instantiate the solver
    OsqpEigen::Solver solver;

    // settings
    solver.settings()->setVerbosity(false);
    solver.settings()->setWarmStart(true);

    // set the initial data of the QP solver
    solver.data()->setNumberOfVariables(2);   //变量数n
    solver.data()->setNumberOfConstraints(2); //约束数m
    if (!solver.data()->setHessianMatrix(hessian))
        return 1;
    if (!solver.data()->setGradient(gradient))
        return 1;
    if (!solver.data()->setLinearConstraintsMatrix(linearMatrix))
        return 1;
    if (!solver.data()->setLowerBound(lowerBound))
        return 1;
    if (!solver.data()->setUpperBound(upperBound))
        return 1;

    // instantiate the solver
    if (!solver.initSolver())
        return 1;

    Eigen::VectorXd QPSolution;

    // solve the QP problem
    if (!solver.solve())
    {
        return 1;
    }

    QPSolution = solver.getSolution();
    std::cout << "QPSolution" << std::endl
              << QPSolution << std::endl; //输出为m*1的向量
    return 0;
}

CMakeList文件内容:

cmake_minimum_required(VERSION 3.1)

set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

project(OSQP_test LANGUAGES CXX)

find_package(OsqpEigen)
find_package(Eigen3)

include_directories(SYSTEM ${EIGEN3_INCLUDE_DIR})

#MPCExample
add_executable(OSQP_test main.cpp)

target_link_libraries(OSQP_test OsqpEigen::OsqpEigen)

这篇文章只是简单介绍了二次规划的思想和OSQP的代码流程,希望后面能结合实际的路径/轨迹优化问题,进行实践验证。

除了QP问题,常见的凸优化问题还有其他标准形式:

二次规划(QP)与OSQP求解器_第1张图片

 这部分需要在理论的基础上,结合实际问题进行学习。

参考链接:

OSQP使用说明 - 知乎

使用OSQP解决二次凸优化(QP)问题_首飞爱玩机器人的博客-CSDN博客_osqp库

Apollo 6.0 QP(二次规划)算法解析 - 知乎

Apollo MPC OSQP Solver_cyytum的博客-CSDN博客_mpc osqp求解器

OSQP solver documentation — OSQP documentation

凸优化笔记(3)Quadratic Programming简介 - 知乎

二次规划 | 机器之心

osqp-eigen使用记录_Oxalate-c的博客-CSDN博客_osqp-eigen

利用OSQP库计算标准二次规划(QP)问题的实例 - Challenging-eXtraordinary

你可能感兴趣的:(决策规划,算法)