[规划算法]目标边界(Goal Bounding)
1. 简介
目标边界(Goal Bounding)不是一种搜索算法,而是一种对搜索空间进行修减的方法,主要的原理是通过离线预处理搜索空间,实时运行搜索算法时,利用预先计算的数据来减少寻找目标所需要考虑的节点数量。Goal Bounding常用于A*,JPS的加速。
2.前提条件
运用Goal Bounding有三个前提条件:
1)地图约束:地图必须是静态的(预处理时和运行时的地图是一样的,不能添加或删除节点和边,节点与节点之间的cost也不能改变);
2)内存:对应地图中的每个节点,运行时需要每个节点的边存储四个值,对内存空间要求较大;
3 ) 预计算: 需要对地图进行预处理(O(N2))。
3.应用场景
1)Goal Bounding用于任何图搜索空间,如栅格,路点图(waypoint),四叉树,八叉树和导航网格;
2)Goal Bounding可结合 A*,JPS+等搜索算法;
3)地图中的节点与节点之间可以有不同的cost。
4.算法的本质
对于与节点相邻的每条边,Goal Bounding预计算出一个边界框(4个值),它包含通过探索这条边可以达到的最边界目标。在运行时,只有当搜索的目标位于边界框中时,我们才探索这个节点的边缘。
例如,下图中,对于实体圆圈的节点来说,a)中灰色的节点都可以通过探索它的左侧边界达到,于是定义了 b)中的灰色边界框代表了探索左侧边能达到的极限范围(需要定义4个值:上下左右)。预计算时,这四个边界值存储在圆节点的左边缘;运行时,当搜索到该圆节点,并考虑它的左边缘时,会先检查目标点是否在边界框中。如果目标不在边界框,则不考虑这条边;如果目标在边界框中,会像普通搜索算法一样,考虑这条边。
5.结合Goal Bounding的A*算法
procedure AStarSearch(start, goal) { Push (start, openlist) while (openlist is not empty) { n = PopLowestCost(openlist) if (n is goal) return success foreach (neighbor d in n) { if (WithinBoundingBox(n, d, goal)) //与普通A*的区别,修剪了大量的边 { // Process d in the standard A* manner } } Push (n, closedlist) } return failure }
6. 预计算
为了计算单个节点所有边的边界框,一般使用稍微改进的Dijkstra搜索算法:从单个节点开始Dijkstra搜索,并且不给它任何目的地,导致它搜索地图中的所有节点。
使用Dijkstra进行洪水填充,地图具有用最佳“下一步”标记每个节点的效果,以最佳方式回到起始节点。下一步就是在搜索过程中记录的父指针。然而,对于给定的节点,我们真正想知道的关键信息不是下一步要做什么,而是最终到达该节点需要哪个起始节点边缘。将地图中的每个节点都标记为起始节点的边,该边位于返回起始节点的最佳路径上。
图2 .从黑色节点开始的 Dijkstra 洪水填充的结果。 Dijkstra 搜索期间的每个节点都标有返回起始节点的最佳路径上的起始边。
图3. 预计算得到的Bounding Box
参考文献:
[1] Rabin S, Sturtevant N R. Faster A* with Goal Bounding[M]//Game AI Pro 360. CRC Press, 2019: 283-290.
[2] https://github.com/SteveRabin/JPSPlusWithGoalBounding