Home Astar寻路算法
Post
Cancel

Astar寻路算法

曼哈顿距离

图形中只允许朝上下左右四个方向移动

  • manhadun.png

计算公式:设格子的单位长度为D

1
(|A.x-B.x|+|A.y-B.y|)*D

欧几里得距离

图形中允许朝任何方向移动

  • oujilide.png

计算公式:根据勾股定理求斜边。设格子的单位长度为D

1
2
3
dx=|A.x-B.x|
dy=|A.y-B.y|
Dsqrt(dxdx+dy*dy)

对角线距离

图形中允许朝八个方向移动

  • duijiaoxian.png

计算公式:设格子的单位长度为D,那么斜向移动一单位距离,根据勾股定理,求腰为D的等腰直角三角形的斜边,即√2D。

1
2
3
dx=|A.x-B.x|
dy=|A.y-B.y|
D*(dx+dy)+(2D-2D)*min(dx,dy)

计算机处理浮点数比较耗费资源,可以在损失一定精度的情况下进行优化。√2≈1.4,假设D=10,则√2D≈14,将浮点数转换成整数计算


A*算法

估算公式:

1
f(n)=g(n)+h(n)
  • g(n)是当前节点到起点的真实距离,g(n)的计算方法:前一个节点的g(n)值加上两节点之间的距离d
  • h(n)是当前节点到终点的“估算距离”(无视障碍物情况下的预测值,也可理解成该点到终点的直线距离的值)

待遍历的节点集合:open_list 节点的状态:open(待处理),close(已处理),unknown(初始) 前置节点指针:parent

算法步骤:

  • find_path_init:初始化open_list,并将起点加入open_list中
  • find_path_step:
    • 取出open_list中f值最小的节点node,设置状态为close
    • 获取并遍历节点node的邻居节点(4/8方向),邻居节点必须为可走
      • 若邻居节点状态为unknown,则计算邻居节点的g值和f值,并设置parent指针为node,将邻居节点加入到open_list中
      • 若邻居节点状态为open,根据node的g+d得到newg,当newg<邻居节点的g时,设置parent指针为node
    • 循环find_path_step的操作,直到open_list为空或者node等于终点。
  • find_path_finish:搜到终点后通过parent指针,便能从终点一步步回溯通过的路径点。

优化思路:

  • open_list需要频繁加入节点,并且每次都需要取出最小值,可以使用最小堆实现。

业务需求:

  • 业务只允许4方向移动,在寻找邻居节点的时候,只需要判定上下左右的节点。
  • 业务允许8方向移动,在寻找邻居节点的时候,除了需要判定上下左右节点,若当前节点往斜边节点的方向存在任意一个可走节点,则斜边节点也需要判定。
    • 下图中虽然斜边节点可走,但实际上是不可走的
    • diagonal1.png
    • 下图中这种斜边节点才可走
    • diagonal2.png
    • 估算公式需要换成对角线距离,估算公式会影响路线的最优解。寻路演算
    • 曼哈顿距离:
    • formula1.png
    • 欧几里得距离:
    • ba8674d7a7fa6f5ee33215e8fecd6e7b.png
This post is licensed under CC BY 4.0 by the author.