1.Apollo EM中path_assesment_task相关细节的源码讨论
2.终于把Apollo存储加密这件事搞定了 | 周末福利!
3.Apollo OSQP路径规划
4.Apollo6.0安装文档教程——环境搭建、分析安装、源码编译、分析测试
5.Apollo 8.0 配置参数读取源码解析:以 Planning 模块为例
6.自动驾驶笛卡尔坐标系和frenet坐标系相互转换
Apollo EM中path_assesment_task相关细节的源码讨论
网上已有关于本task流程的详细注释,本文主要探讨Apollo EM中path_assesment task的分析麦克指标源码内部算法细节。
首先,源码我们来看SetPathPointType函数。分析函数中,源码ego_center_shift_distance代表车体几何中心距离后轴中心的分析距离。初始化过程中,源码以车体后轴中心点为基准获取整个车体Box。分析ego_box所调用的源码Shift函数将后轴中心点前移至车体几何中心点并计算box四个角的位置。这样做的分析原因是,Control使用后轴中心点跟踪每一个pathpoint,源码而本车SLboundary依据其几何中心点在参考线上进行投影,因此这一步转化是必不可少的。
Shift函数内所调用的InitCorners()如上图所示,其中cos_heading,sin_heading_,half_length_,half_width_,center_,是在Box2d初始化时进行赋值。简单用图示介绍一下含义:X-Y用于表示地图坐标系,x-y用于表示将地图坐标系平移至车体几何中心点之后的坐标系,[公式] 用于表示heading。特别解释一下:此处的使用 [公式] 来表示长度half_width x[公式]。
获取到本车box的四个角的坐标之后,再将依靠参考线将box转化到SL坐标系下的boundary。之后遍历SL坐标系下每个pathpoint,计算自车位于每个pathpoint的时候所对应的车体的边界。将边界与车道线比较,判断每个pathpoint的类型(在lane_borrow/lane_change决策下是在旁车道还是本车道)。此处不粘贴源码,直接用图示进行说明各种情况。
需要注意:由于要在统一的坐标系下进行比较,所以,采用-right_width。所以对应上图的std chrono 源码情况,即处于车道边界之外还没换道的情况:start_l>lane_left_width || end_1<-lane_right_width此时type为IN_LANE。对应上图情况,即严格处于本车边界之内的车辆,需要考虑将车道边界添加buffer:所以本车实际处于虚线之内,此时的type为IN_LANE,表示已经换道完成。其它状态下为lane_change的过渡状态,type为OUT_ON_FORWARD_LANE。
需要注意的是:由于借道其实是拐入别的车道一点点之后再拐回来,所以需要添加动态的迟滞边界in_and_out_lane_hysteresis_buffer,来对pathpoint进行严格地区分。类似的做法在量产ADAS功能中也用到,主要用于对前方动态Target的识别,目的是为了防止障碍车辆沿车道线来回画龙或压线行驶的情况。扯远了~
如上述,因为借道只是占据旁车道一点点,所以判断条件与lane_change略有不同,此处的判断条件使用end_l与lane_left_width相比较,start_l与-lane_right_width相比较。
如上图所示,当前一个路径点在车道内(is_prev_point_out_lane = false),即绿点所在位置,则判断lane_borrow的条件:此时,in_and_out_lane_hysteresis_buffer = 0.2;当前一个路径点在车道内(is_prev_point_out_lane = true),即红点所在位置,此时,in_and_out_lane_hysteresis_buffer = 0;
接下来讨论path与静态障碍物collision的问题:具体流程图参见下图:IsCollidingWithStaticObstacles中流程概述:过滤掉虚拟障碍物,高速运动障碍物等,按照固定距离的pathpoint建立VehBox,所有点转化为Frenet坐标系,调用函数IsPointIn检验所有点是否处于障碍物的内部。
下面开始详细讲解IsPointIn函数:首先判断本车的Corner点是否在障碍物边界上,如果不在,则进行下一步取Corner点在与轴方向异侧的在线预定 源码两个点,分别于Corner点构成向量,之后做叉乘,叉乘结果若大于0,则比较两个点的y值,若y值结果小于0,则看向量正旋转到目标向量的实际角度是否小于度,若小于,则c由零变为1;若y值结果为大于,则看向量正旋转到目标的实际角度是否大于度,若大于,则c由零变为1。同理再构建另外两个向量,若与上述情况相同,则c由1变为2。最后判断C为奇数还是偶数,如果为奇数,则返回true,表示Corner点处于Obstacle内部。如果为偶数,则表示Corner点在Obstacle外部。
下面举个栗子:对于左图A点的这种情况,0点与3点在Y轴方向上位于A点异侧,0.y<3.y,side>0(即比较向量A-0正旋转到目标向量A-3是否小于度),实际大于度(蓝色箭头),结果为否,则c值仍为0;2点与1点在Y轴方向上位于A点异侧,side<0(即比较向量A-2正旋转到目标向量A-1是否大于度),实际大于度(红色箭头),结果为是,则c值变为1。最终c&1为奇数,表示A点在obstacle之内。
对于右图A点情况,c 日历 源码0点与3点在Y轴方向上位于A点异侧,0.y<3.y,side>0(即比较向量A-0正旋转到目标向量A-3是否小于度),实际小于度(红色箭头),结果为是,c值由0变为1;2点与1点在Y轴方向上位于A点异侧,side<0(即比较向量A-2正旋转到目标向量A-1是否大于度),实际大于度(蓝色箭头),结果为是,则c值变为2。最终c&1为偶数,表示A点在obstacle之外。
正旋转相关的知识:叉乘几何含义:须注意:本算法所有的坐标系为上图所示,所以正旋转方向为X轴沿绿三色箭头转到Y轴。
最后依旧借用M星云男神女神镇楼。。
终于把Apollo存储加密这件事搞定了 | 周末福利!
作者:尹吉欢 转自:微信公众号“程序员私房菜”
本文节选自《Spring Cloud微服务入门实战与进阶》
敏感配置,如密码等,我们期望进行加密存储,确保其安全性。然而,Apollo框架并未提供数据加密功能。若想实现此功能,有两种方法:一是修改Apollo源码,添加加解密逻辑;二是利用第三方框架进行数据加密。
jasypt-spring-boot是一款基于Spring Boot开发的框架,它可自动解密properties中加密的内容。在Apollo中,我们也可以利用jasypt-spring-boot实现数据的加解密操作。
jasypt-spring-boot的GitHub地址:github.com/ulisesbocchi...
使用jasypt-spring-boot提供的方法对需要加密的配置进行加密,然后将加密内容配置在Apollo中。项目启动时,jasypt-spring-boot会解密Apollo加密的锁瓶源码配置,让使用者获取解密后的内容。
创建一个新的Maven项目,并加入Apollo和jasypt的依赖。具体依赖信息如下:
创建一个加密的工具类,用于加密配置。执行main方法后,可以得到如下输出:
input就是hello加密后的内容,将input的值复制存储到Apollo中。存储格式需要遵循一定规则,即需要将加密内容用ENC包起来,这样jasypt才会解密这个值。
使用时可以直接根据名称注入配置,例如:
input的值就是解密后的值,使用者无需关心解密逻辑,jasypt框架在内部处理好了。
jasypt整合Apollo也存在一些不足之处。目前,我只发现了以下两个问题:
上述两个问题与jasypt实现方式有关,意味着这种加密方式可能仅适用于数据库密码等场景,启动时可以解密,且仅使用一次。对于需要加密的核心业务配置,jasypt无法支持实时更新。下章节我将讲解如何修改Apollo源码来解决这两个问题。
扩展Apollo支持存储加解密
前文介绍了如何使用jasypt为Apollo中的配置进行加解密操作,基本需求可实现。但仍存在一些不足之处。
jasypt仅在启动时解密带有ENC(xx)格式的配置,当配置发生修改时无法更新。由于Apollo框架本身不具备对配置加解密的功能,若想实现加解密并支持动态更新,就需要修改Apollo源码来满足需求。
修改源码需要重新打包。这里介绍一种简单实现方法:创建一个与Apollo框架中相同类名的类进行覆盖,这样无需替换已使用的客户端。
若配置中心存储的内容是加密的,意味着Apollo客户端从配置中心拉取下来的配置也是加密的。我们需要在配置拉取下来后对其进行解密,然后再执行后续流程,如绑定到Spring中。在业务点进行切入后,配置中心加密的内容可自动转换为解密后的明文,对使用者透明。
通过分析Apollo源码,我找到了一个最合适的切入点来完成这项任务,即com.ctrip.framework.apollo.internals.DefaultConfig类。DefaultConfig是Config接口的实现类,配置的初始化和获取都会经过DefaultConfig的处理。
在DefaultConfig内部有一个更新配置的方法updateConfig,可在该方法中对加密数据进行解密处理:
这里使用AES进行解密,意味着配置中心的加密内容也需要使用相同的加密算法进行加密。至于格式,仍使用ENC(xx)格式来标识加密配置内容。解密后将明文内容重新赋值到Properties中,其他流程保持不变。
创建一个加密测试类,加密配置内容,并将其复制存储到Apollo中。输出内容如下:
Ke4LIPGOp3jCwbIHtmhmBA==
存储到Apollo中时,需要用ENC将加密内容包起来,如下:
test.input = ENC(Ke4LIPGOp3jCwbIHtmhmBA==)
使用之前的代码进行测试,Config获取和Spring注入的方式可以成功获取到解密后的数据,并且在配置中心修改后也能实时推送到客户端并成功解密。
本文摘自于《Spring Cloud微服务入门实战与进阶》一书。这是朋友写的一本新书,豆瓣评分8.2。
Apollo OSQP路径规划
探索高效优化之路:OSQP在Apollo路径规划中的应用 在追求自动驾驶车辆动态控制的极致平滑性和安全性时,路径规划算法扮演了关键角色。其中,Piecewise Jerk Path Optimizer(PJP)方法通过优化成本函数,为我们提供了理想的轨迹设计。在这个过程中,OSQP作为一种高效且鲁棒的二次规划求解器,凭借其C语言实现和多语言接口,成为了一种不可或缺的工具。 理解矩阵世界:PD/PSD的数学基础 在优化领域,正定矩阵(PD,Positive Definite)在实数域内是关键概念,它要求对称且所有特征值均为正。这意味着它不仅主元和主子式皆为正,而且对于任何非零向量,其内积总是正的。在复数域中,我们关注的是厄米特矩阵(PSD,Positive Semidefinite),它允许非正特征值,但满足上述对称性和内积非负的条件。 Matlab中的强大工具:quadprog与OSQP对比 Matlab的quadprog函数专为处理有线性约束的二次优化问题,它支持'interior-point-convex'算法,提供了直观的问题描述和prob结构体的使用。然而,对于更高效和现代化的解决方案,OSQP以其C++接口的易用性和依赖于Eigen库的优势脱颖而出,osqp-eigen成为了推荐的首选。 深入实践:osqp-eigen的使用与实例 要开始使用osqp-eigen,首先需要从OSQP官网或GitHub下载源代码,并通过git clone --recurse-submodules或GitHub Desktop完成安装,别忘了安装TDM-GCC作为编译工具。在osqp-matlab/examples目录中,你可以找到丰富的实例来实践OSQP在路径规划中的应用。 扩展学习:走向更广阔的优化天地 为了深入理解OSQP在Apollo路径规划中的应用,掌握正定和半正定矩阵的特性至关重要。查阅OSQP官网和GitHub文档,同时参考知乎、CSDN博客和Apollo开发者社区的专业资源,将帮助你更好地理解和利用OSQP的强大功能。 在自动驾驶的征途上,每一步优化都关乎安全与效率。OSQP与PJP的结合,正在推动智能车辆在复杂道路上的稳健前行。Apollo6.0安装文档教程——环境搭建、安装、编译、测试
一、环境搭建 为了安装Apollo 6.0,您需要以下环境准备:Ubuntu .,安装教程参阅相关资源。
NVIDIA显卡驱动,根据官方指南进行安装。
Docker引擎,Apollo安装步骤中完成。
NVIDIA容器工具,Apollo安装步骤中完成。
安装过程中,请确保禁用nouveau驱动,操作步骤如下: 在终端中添加指定内容至文件末尾并保存,然后重启系统。重启后执行命令,检查禁用状态。 二、下载源码 前往Apollo下载地址,选择对应版本。 三、安装 安装Docker:进入Apollo 6.0的docker目录,执行安装命令。安装完成后,重启电脑。 安装NVIDIA容器工具:与Docker安装同步进行。 创建Apollo容器:下载所需image,此过程可能耗时较长。成功后,会显示“[OK], Enjoy!”。 进入容器:执行相关命令。 四、编译与测试 编译Apollo:根据容器中的GPU状态(有或无)进行编译。可能遇到的warning如“DimsNCHW”被标记为过时,这是正常现象,不会影响后续使用。 启动Dreamview:可能遇到权限问题,使用chmod进行授权。如果问题仍未解决,授权整个Scripts目录并执行。 Dreamview查看:在浏览器中输入ponents.config.config_file_path 指定配置文件路径,文件中的参数在组件初始化时被读入 ProtoBuf 对象。1.2 gflags 命令行参数
gflags 参数通过 module_config.components.config.flag_file_path 指定,文件中的命令行参数在初始化时由 gflags 解析。
2. 配置参数读取流程
主入口文件 (apollo/cyber/mainboard/mainboard.cc) 的 main 函数负责加载 DAG 文件并启动模块。解析命令行参数、读取 DAG 文件、执行模块加载逻辑。
2.1 加载 DAG 文件
解析命令行参数形成 ModuleArgument,用于存储参数信息。执行主流程时,ModuleController 负责加载所有模块,并处理模块组件的注册、实例化和初始化。
2.2 读取配置参数
ModuleController 通过 LoadModule 方法读取模块配置,具体步骤涉及读取 ProtoBuf 参数和 gflags 命令行参数。
3. 总结
本文通过分析 Planning 模块的配置读取过程,清晰展示了 Apollo 8.0 中配置参数的完整读取流程。通过理解这一过程,开发者能够更深入地掌握 Apollo 的模块启动和配置机制。
自动驾驶笛卡尔坐标系和frenet坐标系相互转换
自动驾驶中的车辆运动在笛卡尔坐标系和Frenet坐标系之间转换是关键。在笛卡尔系统中,车辆运动通过航向角[公式]和曲率[公式]描述,而在Frenet坐标(S-L坐标)下,车辆运动则用[公式]表示,其中下标[公式]和[公式]分别代表车辆和参考点,对时间求导用点表示,对自变量求导用撇表示。 Frenet坐标系常用于路径规划,通过先在S-L坐标系规划轨迹得到[公式]关系,再在S-T图规划速度得到[公式]。参考线通常用散点表示,包含位置[公式]、切线方向[公式]、曲率[公式]等信息。在Apollo源码中,涉及如下转换:从笛卡尔的[公式]和[公式]转换到S-L的[公式]和[公式]
从S-L的[公式]到笛卡尔的[公式]
例如,从笛卡尔到S-L,首先找到最近的参考点,通过向量关系推导出[公式],然后利用速度关系式[公式],结合向心力类比的Frenet公式推导出[公式]。整个过程涉及速度的定义、链式求导法则和Frenet公式的应用。 在S-L坐标到笛卡尔坐标转换时,通过参考点的几何位置和车辆与参考线的关系,可以计算速度、加速度等参数,从而完成坐标间的转换。这些转换公式确保了自动驾驶系统在不同坐标系间的运动描述和控制的灵活性和准确性。