作者 | 果冻啤
知圈 | 进“ISO26262社群”,请加微信15221054164,备注ISO
以下是本人在学习路径规划过程中的一些总结,借着机会写了一下,有不妥之处欢迎批评指正,谢谢。 路径规划部分在无人车架构体系当中分属控制或决策部分,如图1,是实现无人化驾驶的关键技术之一。路径规划模块性能的高低直接关系车辆行驶路径选择的优劣和行驶的流畅度,而路径规划算法的性能优劣很大程度上取决于规划算法的优劣,如何在各种场景下迅速、准确的规划出一条高效路径且使其具备应对场景动态变化的能力是路径规划算法应当解决的问题图 0.1
根据对环境信息的把握程度可把路径规划划分为基于先验完全信息的全局路径规划和基于传感器信息的局部路径规划。其中,从获取障碍物信息是静态或是动态的角度看,全局路径规划属于静态规划,局部路径规划属于动态规划。全局路径规划需要掌握所有的环境信息,根据环境地图的所有信息进行路径规划;局部路径规划只需要由传感器实时采集环境信息,了解环境地图信息,然后确定出所在地图的位置及其局部的障碍物分布情况,从而可以选出从当前结点到某一子目标结点的最优路径。 在全局路径规划算法中,大致可分为三类:传统算法(Dijkstra算法、A*算法等)、智能算法(PSO算法、遗传算法、强化学习等)、传统与智能相结合的算法。智能算法种类繁多,但传统算法更为基础,故本着由浅入深的原则,首先对传统算法展开学习。1 算法综述
在传统路径规划算法中,各种算法的实现原理和应用范围差异很大,但可以将以下五种算法看作一类(Dijkstra、A*、D*、LPA*、D* lite),以下对各算法的基本原理进行阐述,并在搜索原理和应用场景等方面进行了对比区分。1.1 算法简述
1.1.1 Dijkstra算法
Dijkstra算法是由E.W.Dijkstra于1959年提出,又叫迪杰斯特拉算法。该算法采用了一种贪心模式,其解决的是有向图中单个节点到另一节点的最短路径问题,其主要特点是每次迭代时选择的下一个节点是当前节点最近的子节点,也就是说每一次迭代行进的路程是最短的。而为了保证最终搜寻到的路径最短,在每一次迭代过程中,都要对起始节点到所有遍历到的点之间的 最短路径 进行更新,具体看一下过程 图 1.1 节点有向图 初始化: 建立distance[](起点到其他所有点的距离信息)、Top_node[](最短路径信息)两个列表存放信息。其中,distance[]的维度为节点的个数,每一个数值为到达对应索引节点的最短路径距离,比如distance[2]的值代表当前迭代时刻到达3号节点的最短距离。初始状态distance[0 inf 10 inf 30 100],其中0代表自身,inf代表无法到达;Top_node[num1],其中num1代表一号节点并以此类推。 搜索最小点: 找到当前节点到下一点的最小值,即从num1开始搜索到1->5/1->3/1->6三条路,并找到距离最小的路1->3。则此时到达num3点的最短路径确定为10,将num3存入Top_node[]。 松弛: 确定num3找到最短路径,然后num3开始搜寻其弧尾,找到3->4路径,此时1->3->4路径距离为10+50=60,小于inf,故将列表更新为distance[0 inf 10 60 30 100]。注意这里通过3->4这条路径缩短1->4这条路径的过程叫做“松弛”,该算法证实通过这样的方法进行路径寻优。 重复迭代: 除去num1和num3,从剩余点搜寻距离最小,找到num5,故将num5加入Top_node[]。找到弧尾路径5->4/5->6,进行松弛,其中1->5->4距离为30+20=50<60,1->5->6距离为30+60=90<100,所以列表更新为distance[0 inf 10 50 30 90]。 重复迭代: 除去num1、num3和num5,其余点寻最小,找到num4,将其加入Top_node[]。然后找到弧尾4->6,进行松弛,1->5->4->6距离30+20+10=60<90,1->3->4->6距离10+50+10=70>60,进行列表更新distance[0 inf 10 50 30 60]。 重复迭代: 除去num1、num3、num4和num5,其余点寻最小,找到num6,将其加入Top_node[],然后没有找到弧尾,则此时到达num6的最优路径找到。 以上就是Dijkstra算法的简单实例,可见其主要是通过贪心原则逐个遍历最小子节点,然后利用松弛方法去优化路径选择,最终将最优路径存放到可读列表当中,以此来解决最优路径规划问题。1.1.2 A*算法
A*算法是启发式搜索算法,启发式搜索即在搜索过程中建立启发式搜索规则,以此来衡量实时搜索位置和目标位置的距离关系,使搜索方向优先朝向目标点所处位置的方向,最终达到提高搜索效率的效果。 A*算法的基本思想如下:引入当前节点x的估计函数f(x),当前节点x的估计函数定义为: f (x)= g(x)+h(x) 其中g(x)是从起点到当前节点x的实际距离量度(代码中可以用两点之间距离代替);h(x)是从节点x到终点的最小距离估计, h (x) 的形式 可以 从欧几里得距离或者曼哈顿距离
算法基本实现过程为:从起始点开始计算其每一个子节点的f值,从中选择f值最小的子节点作为搜索的下一点,往复迭代,直到下一子节点为目标点。1.1.3 D*算法
基于A*算法,Anthony Stentz在1994年提出了Dynamic A*算法,也就是D*算法。D*算法是一种反向增量式搜索算法,反向即算法从目标点开始向起点逐步搜索;增量式搜索,即算法在搜索过程中会计算每一个节点的距离度量信息H(x),在动态环境中若出现障碍物无法继续沿预先路径搜索,算法会根据原先已经得到的每个点的距离度量信息在当前状态点进行路径再规划,无需从目标点进行重新规划。
其中,距离度量信息H(x)=H(y)+C(y, x),H(y)代表x点到目标点的距离度量,C(y,x)代表y点到x点的距离度量,在算法中均可用两点间实际距离代替。1.1.4 LPA*算法
2001年,由斯文·柯尼格(Sven Koenig)和马克西姆·利卡切夫(Maxim Likhachev)共同提出的Life Planning A*算法是一种基于A*算法的增量启发式搜索算法。 LPA*算法实现原理: 搜索起始点为所设起点(正向搜索),按照Key值的大小作为搜索前进的原则,迭代到目标点为下一搜索点时完成规划;Key值中包含启发式函数h项作为启发原则来影响搜索方向;处于动态环境时,LPA*可以适应环境中障碍物的变化而无需重新计算整个环境,方法是在当前搜索期间二次利用先前搜索得到的g值,以便重新规划路径。 其中,Key[]为一个二维数组: g(n)代表起点到当前点的距离度量。rhs(n)为min(g(n’)+c(n’, n)),n’为n的父节点,h(n, goal)为启发项;搜索原则为:优先判断k1大小,若k1小则优先遍历,若k1=k2,则选择k2较小的点。1.1.5 D* lite算法
D* lite算法是Koenig S和Likhachev M基于LPA_star 算法基础上提出的路径规划算法。D* lite与LPA*的主要区别在于搜索方向的不同,这就将Key[]定义中涉及到的目标点goal替换为起始点start的相应信息。 D*_lite算法是先在给定的地图集中逆向搜索并找到一条最优路径。在其接近目标点的过程中,通过在局部范围的搜索去应对动态障碍点的出现。增量式算法的优势在于,各个点的路径搜索已经完成,在遇到障碍点无法继续按照原路径进行逼近时,通过增量搜索的数据再利用直接在受阻碍的当前位置重新规划出一条最优路径,然后继续前进。1.2 算法对比
1.2.1 性能和应用对比
搜索方向 | 启发式 | 增量式 | 适用范围 | 现实应用 | |
Dijkstra | 正向搜索 | 否 | 否 | 全局信息已知,静态规划 | 网络通信中的最短路由选择 |
A* | 正向搜索 | 是 | 否 | 全局信息已知,静态规划 | Apollo、游戏、无人机路径规划 |
D* | 反向搜索 | 否 | 是 | 部分信息已知,动态规划 | 机器人探路、火星探测车路径规划 |
LPA* | 正向搜索 | 否 | 是 | 部分信息已知,假设其余为自由通路,动态规划 | 机器人路径规划 |
D* lite | 反向搜索 | 是 | 是 | 部分信息已知,假设其余为自由通路,动态规划 | 机器人路径规划 |