路径规划算法
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
[选取日期] NUAA未知环境的动态路径规划
[键入文档副标题] | 刘绍翰
度量距离
灰度化
四连通和8连通。
第一章、静态搜索与A*算法
很多时候,我们需要在一个图中寻找一条从源点到目标节点的最短路径,我们称之为路径规划。搜索算法主要分为,盲目搜索和启发式搜索,它们的一个作用是能够从解空间中需找一条从源点到目标节点的最短路径。启发式搜索是在搜索的过程中,参考一定的指标函数来决定搜索的策略。
迪杰斯特拉算法,类似于广度优先遍历,利用源点到当前节点的代价值作为指标,其一定可以获得从原点到目标节点的最短路,但是其访问的节点数很多。
而最好优先搜索,采用离标节点的距离作为搜索的代价参考值,贪心选择最小的扩展节点,也可以获得最短路径,而且其搜索的节点数目大大减少。
图1 迪杰斯特拉算法图2 最好优先搜索算法当地图中包含障碍物时,迪杰斯特拉算法,仍然可以获得最短路径的路径,最好优先搜索的节点尽管少,但是其不能获得最优解。
图3 迪杰斯特拉算法图4 最好优先搜索算法而A*算法,参考了从原点到当前节点的代价值和当前节点到目标节点启发值,综合了迪杰斯特拉算法和做好优先搜索算法优点,在有障碍物和无障碍物的地图上,可以像迪杰斯特拉算法一样求得最短路径同时,同时能够像最好优先搜索一样减少搜索范围,减少搜索节点的数目。
图5 无障碍物时A*路径规划图6 有障碍物时A*路径规划算法
经典的迪杰斯特拉算法可以求得最短的路径,而启发式搜索A* 算法,不但可以求得最短路,而且可以使得搜索的范围大大减少,上述算法是传统的静态路径规划算法,其规划的前提条件是已经知地图的结构。A*算法属于离线事先规划,在规划完毕之后,可以沿着最优路径移动,不是在线规划,不能一边规划一边移动。
A*算法的基本理论
A*算法又叫做启发式搜索算法,具有悠久的历史,其启发函数f=g+h。其中g表示从原点到当前节点已经付出的代价,好表示从当前节点到目标节点的启发值。
1)A*算法必须满足h(x)<=h*(x),其中h*(x)是实际的启发值,h*(x)在实际中通常是无
法事先得知的,但是这个条件是很容易满足,只要满足该条件,一定能够获得最
优解。
2)如果最短路径长度为C*, 则在算法结束前,open表中至少有一个节点n, 满足f(n)
<= C*. 这个性质可以这样理解,因为最短路径存在,我们不妨设它为: source->a->b->c->...->n->.....->goal. 且在当前时刻,路径中在节点n前的节点都在
closed表中,即已经扩展了,而节点n自己在open表中(注意:算法结束前任
意时刻都有这样的节点n存在)。则由于该条路劲是最短路径,我们可以知道此
时在open表中的n的g(n)值已经是准确值, 即最小值了。而f(n) = g(n) + h(n) = g*(n) + h(n) <= g*(n) + h*(n) = C* . (最后一个式子取等号是由于n在最短路径上) 有了这个性质,我们就知道,当A*算法扩展到目标节点时,必有f(goal) = g(goal) <= C* (即= C*)。否则, 如果f(goal) > C*,由于目标节点是被扩展节点, 则open表
中其他任意其他节点t, 都有f(t) >= f(goal) > C*, 和性质1 矛盾。
3)扩展新节点时很容易出现重复节点的问题,从上面的伪代码可以看出,如果新
扩展节点已经存在于closed表中,且f值比表中节点的f值还要小的话,则除了
更新该节点f值,还需要重新扩展该节点,这简直就是把人从棺材里拖出来。但
是如果h函数满足相容性,这一步就可以省掉了。所谓相容性就是指对任意节点
s1,都满足:
h(s1) <= h(s2) + c(s1,s2)
(其中c(s1,s2)是指从s1转移到s2的代价)有这个性质我们在不等号两边加上g(s1), 则有g(s1) + h(s1) <= h(s2) + g(s1) + c(s1,s2)。如果我们此时扩展s1, 而s2又是能
被s1扩展的节点,则由这个式子我们得到f(s1) <= f'(s2). (若s2之前就已经被扩
展出了,则当前的f(s2)可能比f'(s2)小) 这个式子的意义在于由当前节点进行扩
展这个方案下得到的节点的f值总比当前扩展节点的f值大(子节点总比父节点
费用高),而我们每次又是选择一个具有最小f值的节点进行扩展,然后让其进
入closed表,这就使得,进入closed表的每个节点的f值是递增的,并且之后不
可能出现比closed表中最大f值。还要小的节点被扩展出来(感觉有点问题),
因此扩展出的新节点不必再拿到closed表中检查更新了。
4)可以得知有如下条件成立:f(y)=g(y)+h(y)=g(x)+C(x,y)+h(y)>= g(x)+h(x)即代价函数f
的值是非递减的。
5)下面我们来讨论一下h函数的相容性,由于C(x,y)为从x到y的实际代价,因为
h的估计小于实际的代价值,h(x)
h(x)- h(y)。??
6)f的满足三角不等式:h(s,s’’’)<=h(s,s’’)+h(s’’,s’’’)<=h(s,s’)+h(s’,s’’) +h(s’’,s’’’)<=….可以
一直展开下去。
7)
A*算法的实现
众所周知,对图的表示可以采用数组或链表,而且这些表示法也各也优缺点,数组可以方便地实现对其中某个元素的存取,但插入和删除操作却很困难,而链表则利于插入和删除,但对某个特定元素的定位却需借助于搜索。而A*算法则需要快速插入和删除所求得的最优值以及可以对当前结点以下结点的操作,因而数组或链表都显得太通用了,用来实现A*算法会使速度有所降低。要实现这些,可以通过二分树、跳转表等数据结构来实现,我采用的是简单而高效的带优先权的堆栈,经实验表明,一个1000个结点的图,插入而且移动一个排序的链表平均需500次比较和2次移动;未排序的链表平均需1000次比较和2次移动;而堆仅需10次比较和10次移动。需要指出的是,当结点数n大于10,000时,堆将不再是正确的选择,但这足已满足我们一般的要求。
还有一种更好的方法是Hot Queues,而且这种方法还可应用于Dijkstra算法以降低其复杂度。当我们移动估价函数值为f的结点时,我们插入值为f+δ(δ<=C)(若δ>=0将意味着估价函数是有效的,反之亦然),常量C为从一个结点到相邻结点的权的最大改变。同时我们用一些“容器”来保存估价函数值的子集(这正如o(n)的排序算法的思想),例如,当有10个“容器”时,堆将平均只包含1/10的估价值。因而这将比用堆更为有效。
A*算法的变形
a. Beam Search
在A*算法中需要保留所有的结点,这将使得时间和空间的消耗都很大,而Beam Search方法对结点数作出限期,当结点数过多时,它会将一些不(大)可能为最优的点排除,从而降低时间和空间的要求,但需要说明的是,由于在排除结点后需对结点排序,当排序的工作量大于排除点后所节省的工作量,则该方法无意义。
b. Iterative deepening
这是一种在人工智能中常使用的方法,它首先产生一定值作为搜索的深度,当未能搜索到解的时候,对搜索的深度增加,继续搜索。
c. Dynamic weighting