自动驾驶规划中使用 OSQP 进行二次规划 代码原理详细解读

news2024/11/20 20:24:49

目录

1 问题描述

什么是稀疏矩阵 CSC 形式

QP Path Planning 问题

1. Cost function

1.1 The first term:

1.2 The second term:

1.3 The thrid term:

1.4 The forth term:

对 Qx''' 矩阵公式的验证

整体 Q 矩阵(就是 P 矩阵,二次项的权重矩阵)

整体 P 矩阵的形式如下:

目标函数中的线性项部分,即 q 矩阵的构建

计算 q 矩阵的代码块如下:

2. Constraints

2.1 不等式约束

2.2 连续性约束

Equality constraints

不等式约束的上下边界条件为:

上下边界条件是如何计算的?

二阶导边界极值的计算:

三阶导边界极值的计算

最后,A 矩阵为:

仿射矩阵 A


1 问题描述

典型的优化问题可以用以下的数学表达式来描述:

其中,P 是一个 n x n 的半正定矩阵, x 为 n 维向量,q 为 m x n 的矩阵。

需要注意的是,二次规划只在代价函数为凸函数的时候能够收敛到最优解,因此这需要 P 矩阵为半正定矩阵,这是非常重要的一个条件。这反映在 Apollo 中的规划算法则为需要进行求解的空间为凸空间,这样二次规划才能收敛到一条最优 Path。

上面的表述源自:Apollo 二次规划算法(piecewise jerk path optimizer)解析

什么是半正定矩阵?什么是正定矩阵?

设 A 为实对称矩阵,若对于每个非零实向量 X,都有 X'AX ≥ 0,则称 A 为半正定矩阵,称 X'AX 为半正定二次型。(其中,X'表示 X 的转置。)

注 :

在 OSQP 中,对上述的数据用结构体 OSQPData 进行封装,其定义如下:

// the location of file: /usr/local/include/osqp/types.h

typedef struct {

c_int n; ///< number of variables n

c_int m; ///< number of constraints m

csc *P; ///< the upper triangular part of the quadratic cost matrix P

csc *A; ///< linear constraints matrix A in csc format (size m x n)

c_float *q; ///< dense array for linear part of cost function (size n)

c_float *l; ///< dense array for lower bound (size m)

c_float *u; ///< dense array for upper bound (size m)

} OSQPData;

其中,P 和 A 都是以稀疏矩阵 CSC 的形式进行存储的。

什么是稀疏矩阵 CSC 形式

CSC - Compressed sparse column (CSC or CCS)

稀疏矩阵和稠密矩阵 - 看矩阵中非零元素占所有元素的比例

在矩阵中,若数值为 0 的元素数目远远多于非 0 元素的数目,并且非 0 元素分布没有规律时,则称该矩阵为稀疏矩阵;与之相反,若非 0 元素数目占大多数时,则称该矩阵为稠密矩阵。定义非零元素的总数比上矩阵所有元素的总数为矩阵的稠密度。

稀疏矩阵的常规方式

下面是最常见的一种,也很好理解,(row,col) 指向矩阵非零元素的索引,data 里为该元素的值。

稀疏矩阵的 CSC 形式 - csc_matrix

按列压缩 Compressed sparse column,顾名思义将每一列出现的非零元素的个数统计后放好。

如何保证规划算法求解的空间为凸空间?

QP Path Planning 问题

QP 问题的标准形式(下面是常见的两种表示方法):

1. Cost function

论文中的 cost 函数实际上是如下的形式:

优化变量的形式是:

Cost function 也可以写成下面这种形式:

我们注意到第一项和第二项的内容似乎相同,但其实是有所区别的。我们通过下图来解释。

可以看到,我们要规划的离散点曲线是在 SL 坐标系下进行的。所以第一项惩罚的横向偏移也就是偏移 s 的法向的距离,可以理解为关于车道中心线的偏移。而第四项关于参考线的偏移,则是考虑了静态和低速障碍物生成的一条参考线,第四项所计算的偏移其实是关于参考线的偏移。我们可以这样理解这两项:我们规划的最优轨迹要尽量贴合原来的车道中心线,同时还要尽量贴合能够避障的参考线。

1.1 The first term:

一共有 n 个点:

假如有四个点需要优化,为 x0, x1, ... x3,则矩阵为:

1.2 The second term:

1.3 The thrid term:

1.4 The forth term:

对 Qx''' 矩阵公式的验证

假设有四个点,x1, x2... x3,则:

使用上面的 matrix form:

说明上述的 Qx''' 的公式是正确的。

整体 Q 矩阵(就是 P 矩阵,二次项的权重矩阵)

所以,cost function 的 Q 矩阵为:

整体 P 矩阵的形式如下:
 

注意:代码中 Apollo 中的 Q 矩阵(代码中是 P 矩阵)形式与上述推导有一定的差异:

Apollo 6.0 代码中的 P 矩阵形式如下:

参见这篇文章:

https://zhuanlan.zhihu.com/p/480298921

目标函数的形式如下:

下面就是代码中的 P 矩阵的实际形式:

构建 P 矩阵的函数:

void PiecewiseJerkPathProblem::CalculateKernel(std::vector<c_float>* P_data,

                                               std::vector<c_int>* P_indices,

                                               std::vector<c_int>* P_indptr)

P 矩阵的零阶导数(蓝色)部分对应的代码块:

// x(i)^2 * (w_x + w_x_ref[i]), w_x_ref might be a uniform value for all x(i)

  // or piecewise values for different x(i)

  // P 矩阵的零阶导数部分

  for (int i = 0; i < n - 1; ++i) {

    columns[i].emplace_back(i, (weight_x_ + weight_x_ref_vec_[i]) /

                                   (scale_factor_[0] * scale_factor_[0])); // scale_factor - 缩放系数

    ++value_index;

  }

  // x(n-1)^2 * (w_x + w_x_ref[n-1] + w_end_x) - 最后一个节点增加了一个末状态的权重 w_end_x

  columns[n - 1].emplace_back(

      n - 1, (weight_x_ + weight_x_ref_vec_[n - 1] + weight_end_state_[0]) /

                 (scale_factor_[0] * scale_factor_[0]));

  ++value_index;

P 矩阵的一阶导数(粉色)部分对应的代码块:

  // x(i)'^2 * w_dx - P 矩阵的一阶导数部分

  for (int i = 0; i < n - 1; ++i) {

    columns[n + i].emplace_back(

        n + i, weight_dx_ / (scale_factor_[1] * scale_factor_[1]));

    ++value_index;

  }

  // x(n-1)'^2 * (w_dx + w_end_dx)

  columns[2 * n - 1].emplace_back(2 * n - 1,

                                  (weight_dx_ + weight_end_state_[1]) /

                                      (scale_factor_[1] * scale_factor_[1]));

  ++value_index;

P 矩阵的二阶导数(绿色)部分对应的代码块:

 auto delta_s_square = delta_s_ * delta_s_;

  // P 矩阵的二阶导数部分的第一个对角线元素

  // x(i)''^2 * (w_ddx + 2 * w_dddx / delta_s^2)

  columns[2 * n].emplace_back(2 * n,

                              (weight_ddx_ + weight_dddx_ / delta_s_square) /

                                  (scale_factor_[2] * scale_factor_[2]));

  ++value_index;

  // P 矩阵的二阶导数部分的对角线元素(除了对角线上的第一个元素和最后一个元素)

  for (int i = 1; i < n - 1; ++i) {

    columns[2 * n + i].emplace_back(

        2 * n + i, (weight_ddx_ + 2.0 * weight_dddx_ / delta_s_square) /

                       (scale_factor_[2] * scale_factor_[2]));

    ++value_index;

  }

  // P 矩阵的二阶导数部分的最后一个对角线元素

  columns[3 * n - 1].emplace_back(

      3 * n - 1,

      (weight_ddx_ + weight_dddx_ / delta_s_square + weight_end_state_[2]) /

          (scale_factor_[2] * scale_factor_[2]));

  ++value_index;

  // P 矩阵的二阶导数部分的次对角线上的元素

  // -2 * w_dddx / delta_s^2 * x(i)'' * x(i + 1)''

  for (int i = 0; i < n - 1; ++i) {

    columns[2 * n + i].emplace_back(2 * n + i + 1,

                                    (-2.0 * weight_dddx_ / delta_s_square) /

                                        (scale_factor_[2] * scale_factor_[2]));

    ++value_index;

目标函数中的线性项部分,即 q 矩阵的构建

这部分代码在 PiecewiseJerkPathProblem::CalculateOffset 这个函数

void PiecewiseJerkPathProblem::CalculateOffset(std::vector<c_float>* q)

q 矩阵形式如下:

计算 q 矩阵的代码块如下:

  if (has_x_ref_) {

    for (int i = 0; i < n; ++i) {

      q->at(i) += -2.0 * weight_x_ref_vec_.at(i) * x_ref_[i] / scale_factor_[0];

    }

  }

  //

  if (has_end_state_ref_) {

    q->at(n - 1) +=

        -2.0 * weight_end_state_[0] * end_state_ref_[0] / scale_factor_[0];

    q->at(2 * n - 1) +=

        -2.0 * weight_end_state_[1] * end_state_ref_[1] / scale_factor_[1];

    q->at(3 * n - 1) +=

        -2.0 * weight_end_state_[2] * end_state_ref_[2] / scale_factor_[2];

  }

2. Constraints

2.1 不等式约束

2.2 连续性约束

用每个轨迹点处在 l 方向的 jerk 相等作为连续性约束。

上面的推导和下面的推导是一致的:

将 piecewise jerk 的条件带入:

得:

Now we generate constraints in matrix form.

For constrains a - lateral offset - 0 阶导数

For constrains b - lateral velocity - 一阶导数

For constrains c - lateral acceleration - 二阶导

For constraints d - lateral jerk - 三阶导数

这里有一些问题,对于 jerk 的不等式约束,应该是下面的形式:

For constraints e - 连续性约束

下图是有四个点的时候仿射矩阵的具体形式:

For Constraints f:

约束可以写成:

具体形式:

Equality constraints

不等式约束的上下边界条件为:

上下边界条件是如何计算的?

关于边界约束的详细介绍参见这篇文章:https://zhuanlan.zhihu.com/p/481835121

二阶导边界极值的计算:

对应代码如下:

const double lat_acc_bound =

std::tan(veh_param.max_steer_angle() / veh_param.steer_ratio()) /

veh_param.wheel_base();

std::vector<std::pair<double, double>> ddl_bounds;

for (size_t i = 0; i < path_boundary_size; ++i) {

double s = static_cast<double>(i) * path_boundary.delta_s() +

path_boundary.start_s();

double kappa = reference_line.GetNearestReferencePoint(s).kappa();

ddl_bounds.emplace_back(-lat_acc_bound - kappa, lat_acc_bound - kappa);

}

三阶导边界极值的计算

最后,A 矩阵为:

仿射矩阵 A

至此,P 矩阵,q 矩阵,A 矩阵,b 矩阵均可以表示出来,放入 OSQP 求解器中,可以进行迭代求解了。

The Principle of Apollo Path Planning using Quadratic Programming

这里是 Piecewise Jerk Path Optimizer 的代码讲解。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1855131.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Android开发:自定义TabLayout,神奇效果竟是如此简单

此时有的小伙伴可能会想&#xff0c;自定义view太麻烦&#xff0c;不如让UI直接把这个弧度切出来&#xff0c;不是一共就三个tab项嘛&#xff0c;Textview&#xff0c;ImageView… 这样横着排起来&#xff0c;然后做适当的显示和隐藏不就行啦。 是的&#xff0c;确实是可以&am…

人工智能在数字病理切片虚拟染色以及染色标准化领域的研究进展|顶刊速递·24-06-23

小罗碎碎念 本期推文主题&#xff1a;人工智能在数字病理切片虚拟染色以及染色标准化领域的研究进展 这一期的推文是我发自内心觉得为数不多&#xff0c;特别宝贵的一篇推文&#xff0c;原因很简单——可参考的文献相对较少&方向非常具有研究意义&现在不卷。 数字病理…

nginx服务器连接数告警

序言 只要系统之间有交互&#xff0c;那么就会有连接数&#xff0c;连接数的告警阈值一般设置个几万&#xff0c;当连接数开始告警之后&#xff0c;怎么来排查呢&#xff1f; 连接数过多&#xff0c;会消耗cpu&#xff0c;内存&#xff0c;文件句柄等资源&#xff0c;其实也还好…

《算法笔记》总结No.2——模拟

一.简单模拟 考察代码能力&#xff0c;不涉及算法&#xff1a;一类题目怎么说你就怎么做的类型~ 巴音布鲁克比赛&#xff0c;以车队为基准评选冠军。业务要求是&#xff1a;第一行输入正整数N&#xff0c;代表车手的总个数&#xff1b;接下来的N行每行键入两个数字&#xff1a…

【TOOL】ceres学习笔记(二) —— 自定义函数练习

文章目录 一、曲线方程1. 问题描述2. 实现方案 一、曲线方程 1. 问题描述 现有数学模型为 f ( x ) A e x B s i n ( x ) C x D f(x)Ae^xBsin(x)Cx^D f(x)AexBsin(x)CxD &#xff0c;但不知道 A A A 、 B B B 、 C C C 、 D D D 各参数系数&#xff0c;实验数据中含有噪声…

Windows程序设计课程作业-3(文件并发下载)

目录 目录 1.作业内容 2.作业要求 3.主要思路 1&#xff09;窗体和组件初始化 2&#xff09;下载管理器实例化 3&#xff09;按钮点击事件处理 4&#xff09;窗体加载事件处理 5&#xff09;下载消息处理 4.主要难点 1&#xff09;多线程管理&#xff1a; 2&#xff09…

智能优化算法改进策略之局部搜索算子(六)--进化梯度搜索

1、原理介绍 进化梯度搜索(Evolutionary Gradient Search, EGS)[1]是兼顾进化计算与梯度搜索的一种混合算法&#xff0c;具有较强的局部搜索能力。在每次迭代过程中&#xff0c;EGS方法首先用受进化启发的形式估计梯度方向&#xff0c;然后以最陡下降的方式执行实际的迭代步骤&…

【JavaSE ⑧】P219 ~ 225 Date类‘’DateFormat类转化Date和字符串;Calendar类获得日历中某值,修改日历,日历转日期

目录 日期时间类1 Date类概述常用方法 2DateFormat类构造方法格式规则常用方法parse方法format方法 3 Calendar类概念获取方式常用方法get/set方法add方法getTime方法 ● 练习1.判断Date不同参数构造的输出2. 用日期时间相关的API&#xff0c;计算一个人已经出生了多少天。3. 获…

【Java】已解决java.lang.NoSuchMethodException异常

文章目录 一、分析问题背景二、可能出错的原因三、错误代码示例四、正确代码示例五、注意事项 已解决java.lang.NoSuchMethodException异常 在Java编程中&#xff0c;java.lang.NoSuchMethodException是一个常见的运行时异常&#xff0c;它通常表示尝试通过反射调用一个不存在…

Ai调教写作技巧,不会还有人在到处找指令吧!一篇文章带你学会生成爆款文章写作指令

大家好&#xff0c;我是网创有方的站长&#xff0c;今天教大家一个重磅级的ai调价指令。 相信很多朋友们都去到处找过写作指令&#xff0c;包括我之前也是&#xff0c;但是随着运用ai写作的次数越来越多&#xff0c;我也是渐渐地熟悉了ai的调教。那么本文的目的是什么呢&#…

使用obdumper对oceanbase进行备份,指定2881端口

1.安装obdumper &#xff08;1&#xff09;下载软件 OceanBase分布式数据库-海量数据 笔笔算数https://www.oceanbase.com/softwarecenter &#xff08;2&#xff09;安装软件 参考&#xff1a;https://www.oceanbase.com/docs/common-oceanbase-dumper-loader-100000000062…

C语言标准库

目录 引言 一、C标准库概述 常用标准库函数 字符串处理 数学运算 动态内存分配 标准库的扩展与限制 扩展功能 使用限制 使用自定义库与第三方库 创建自定义库 使用第三方库 表格总结 标准库头文件及功能 常用标准库函数 总结 引言 C标准库是C编程语言的重要组成…

Android studio登录Google账号超时的解决方法

确保自己已经打开了代理&#xff08;科学上网&#xff09;在设置-外观与行为-系统设置-HTTP代理 中打开“自动检测代理设置”&#xff1a; 再次重新尝试登录Google账号&#xff0c;登陆成功&#xff01; 学术会议征稿 想要了解国内主办的覆盖学科最全最广的学术会议&#xff0c…

redis持久化操作【随记】

持久化 Redis它是将数据保存到内存当中,内存里的数据最大特点: 断电易失.保存在内存的数据就没有了.如果如果这些数据还有用,业务使用啥的,不能就让它这么没有了. redis当中提供持久化机制, 说白了,将内存的数据 —-> 写入到磁盘. –> 持久化. 1 rdb方式 redis database,…

帕金森患者饮食指南:科学调养,呵护健康

&#x1f33c;在医学的广阔领域中&#xff0c;帕金森病作为一种慢性神经系统疾病&#xff0c;除了需要专业的医疗治疗外&#xff0c;日常饮食的调养也显得尤为重要。 今天&#xff0c;就为大家带来一份专为帕金森患者打造的饮食建议&#xff0c;希望能为大家的健康调养提供一些…

泛微E9与金蝶云星空ERP的无缝集成案例详解(包括接口与字段)

业务系统现状 背景介绍 泛微E9和金蝶云星空ERP是两款广泛应用与企业管理的信息系统&#xff0c;分别在移动办公自动化和企业资源计划管理领域占据重要地位。然而企业在使用这些系统时往往面临着信息孤岛和系统孤立的问题&#xff0c;导致数据无法在不系统之间高效流转共享。 当…

微服务——服务治理

目录 1 什么是服务治理&#xff1f;2 为什么需要服务治理&#xff1f;3 服务治理的关键点3.1 服务注册与发现3.2 负载均衡3.3 容错与熔断3.4 服务监控与告警3.5 服务配置管理 4 示例说明5 总结 1 什么是服务治理&#xff1f; 简单来说&#xff0c;服务治理就是对微服务架构中的…

Java:113-Spring Data JPA详解

Spring Data JPA详解 Spring Data Jpa 是应用于Dao层的⼀个框架&#xff0c;简化数据库开发的&#xff0c;作用和Mybatis框架⼀样&#xff0c;但是在使用方式和底层机制是有所不同的&#xff0c;最明显的⼀个特点&#xff0c;Spring Data Jpa 开发Dao的时候&#xff0c;很多场景…

气膜建筑:持久耐用的建筑选择—轻空间

随着科技的发展&#xff0c;气膜建筑以其快速施工、节能环保和灵活多用的特点&#xff0c;正在各个领域获得越来越多的应用。然而&#xff0c;许多人对气膜建筑的耐用程度仍存有疑虑。本文将从气膜建筑的材料、结构设计和维护等方面&#xff0c;深入探讨气膜建筑的耐用性&#…

【Android WebView】WebView基础

一、简介 WebView是一个基于webkit引擎、展现web页面的控件。Android的Webview在低版本和高版本采用了不同的webkit版本内核&#xff0c;4.4后直接使用了Chrome。 二、重要类 以WebView类为基础&#xff0c;WebSettings、WebViewClient、WebChromeClient为辅助共同完成安卓段加…