Space-time A*算法介绍
背景:
A搜索用于查找每个智能体到达目的地的最短路径,但是这种搜索忽略了其他智能体的存在,或者可能将它们视为固定障碍物。在运动过程中,如果智能体检测到碰撞即将发生,相关智能体将重新搜索并选择新路径。合作寻路(Cooperative pathfinding)试图让智能体了解彼此的意图,在合作寻路中,A搜索仍在使用,但增加了对其他智能体的移动的考量。
1. space-time A* -结合时间维度
为了解决协作寻路问题,搜索算法需要充分了解障碍物和智能体。当智能体四处移动时,无法在二维地图上表示智能体随时间变化的路线,为了克服这个问题,David Silver扩展地图的时间维度,称其为时空图。
时空图由三维单元网格组成:Cell(x, y, t)。在时空图中,假设执行单个动作的时间成本均为1,向上移动的动作相当于将一个智能体从 Cell(x, y, t) 移动到 Cell(x, y + 1, t + 1)。类似地,等待的动作将一个智能体从 Cell(x, y, t) 移动到 Cell(x, y, t + 1)。如果目标位置没有障碍物,并且没有其他智能体占用,则动作是可行的。现在在时空图上继续使用A*搜索,用到达目标位置所需的动作数量作为该条路径的成本,目标是找到智能体从当前点到其目标位置的最小成本路径。
2. space-time A* -预约表
一个智能体选择了一条路径后,需要确保其他智能体寻路时能避开其路径上的单元格,可以通过构造一个揭示每个单元格是否可用的预约表来满足这一约束。
预约表是一个简单的数据结构,包含时空图中每个单元格的一个条目,用来指定相应的单元格是可用的还是已经被预约了。时空图里的单元格数目通常很多,但在每个时间步上预约的条目数应该大致等于图中智能体的数量,很多单元格在大多数时间步上是未被占用的,如果直接存储每个单元格的状态(可用/已被占用)会造成大量的空间浪费。
为了优化空间使用,可以通过哈希表来存储已占用的时空单元格:使用 (x, y, t) 作为哈希表的键,表示一个具体的单元格在某个时刻的状态。如果一个单元格在特定时间步没有被占用,那么它就不需要在哈希表中记录。一旦一个单元格被预约了,任何其他智能体都不能移入该单元格。
智能体在时空图中使用A*搜索路径,寻路到目标位置后将该路径标记到预约表中,后续智能体寻路时将避开所有已经被预约的单元格,从而保证多智能体间不会发生同时占用同一个单元格的冲突(如图1所示)。
此外,还需要避免可能发生的边冲突,比如,如果一个智能体的路径预约了 Cell(x, y, t) 和 Cell(x + 1, y, t + 1),则需要阻止其他智能体在规划路径时预约 Cell(x + 1, y, t) 和 Cell(x, y, t + 1)。解决方案一是可以为动作中涉及的每个位置预约两个时间步,一个在时间 t,一个在时间 t+1;解决方案二是可以规划路径时明确地识别边冲突并将其标记为不可行的动作。
3. space-time A* -启发函数
A搜索的性能取决于启发式函数的选择,当启发式函数对距离的估算值小于等于从该点到目标位置的真实距离时,A搜索保证一定能找到最短路径,且启发式函数的估计距离与真实距离越接近时,搜索速度越快。
在时空A*中,随着搜索空间扩展一个额外的维度,启发式函数的选择变得更加重要。基于网格的地图通常使用曼哈顿距离作为启发式函数,它是到目标位置的 Δx 和 Δy 距离之和。如果到达目标位置的最短路径是迂回的,那么曼哈顿距离就是对真实距离糟糕的估计。当选择曼哈顿距离作为启发式函数时,时空图上许多位置的 f 值可能小于到目标位置的真实距离,启发式函数估计的值越小,算法就会遍历越多的单元格,导致搜索速度变慢。因此,需要选择一种更准确的启发式函数。
A搜索过程中,一旦将某个节点放入了close list中,从起点到该节点的最短距离就已知,这个距离为g。为了更有效地估计时空A中某个点到目标位置的真实距离,可以采用向后搜索的方法:以目标位置为起点,源头位置为终点,只考虑地图中的静态障碍物,使用A在二维地图中从目标位置向源头位置搜寻最短路,搜索完一遍后,对于加入到close list中的那些点,就已知了从目标位置到该位置的避开静态障碍物的最短距离。换句话说,close list中每个节点的g值正好为二维地图上该点到目标位置的真实距离。在一次向后搜索完成后,可能无法获得地图上所有点到目标位置的真实距离,此时如果有需要,可以继续使用A向后搜索,直至搜索完需要的点为止。
使用向后搜索得到的距离更接近时空图上到目标位置的真实距离,我们使用这个距离作为A搜索的h值,提高搜索效率。基于以上,在时空A中并列运行两个搜索,主搜索为时空A寻找从智能体的当前位置到目标位置最短路径的搜索过程,辅助搜索为A从智能体的目标位置向当前位置的向后搜索过程。主搜索在探索每个位置时都需要真实距离的启发式估计值,此时使用辅助搜索来得到这个估计值。如果主搜索探索的当前位置在辅助搜索的close list中,则立刻返回其g值;如果不在close list中,则继续向后搜索,直到将请求的位置放入到close list中,并返回其g值。*
4. 处理不同移动行为的智能体
到目前为止,我们假设每个智能体的移动速度都是相同的:在一个时间步长内可以执行一个动作——向左、右、上、下移动一个单元格,或是在当前的单元格等待。时空A*搜索的路径包含的单元格和预约表的条目之间存在一一对应的关系。然而,每个智能体都可以以最适合自己的方式搜索时空,比如一个以缓慢速度移动的智能体需要两个时间步长才能向四周移动一个单元格,则这个智能体需要具有更长时间步长的时空网格(如图5A所示);同理,以更快速度移动的智能体的时间步长更短(如图5B所示)。我们可以给不同智能体构建不同大小的时空网格,但预约表有固定的结构,预约表每个条目所对应的每个单元格都具有固定大小并在所有智能体之间共享(如图5C所示)。
智能体动作的足迹决定了需要在预约表中预约的条目集合。例如,对角线移动的足迹可能包括一个由八个单元格组成的立方体(如图6A所示)。大型智能体在每个时间步都会有更广泛的足迹(如图6B所示)。缓慢的移动将产生持续更多时间步长的足迹(如图5A所示)。曲线移动将占用该动作穿过的所有时空单元格(如图6C所示)。预约表的粒度可以被初始化为任何值,这取决于寻路要求。
参考
[1] Silver, “Cooperative Pathfinding,” AIIDE, vol. 1, no. 1, pp. 117–122, Sep. 2021, doi: 10.1609/aiide.v1i1.18726.
[2] Space-Time A*算法Python库网站:https://pypi.org/project/space-time-astar/
[3] 久章团队 久章智能.