zoukankan      html  css  js  c++  java
  • 2.A star

    2021-05-15 19:18:59

    A*就不赘述,比较关键的地方需要注意。

    下边内容参考自:

    • 高飞--深蓝学院
    • pathfinding.js
    • https://www.redblobgames.com/

    1.关于admisible

    一个一定要明白的概念,就是admissible。

    定义:h <= h*,则h就是admissible heuristic。其中h*到终点最小的真实cost。

    只要h是admissible,那A*结果一定是最优的,否则就是次优的(换来的是计算速度提升)。

    2.三种heuristic

    先介绍代码中会用到的eigen中的几种范数,老是记不住:

    • squaredNorm():  等价于vector自身点积,即所有元素平方和。
    • norm(): 返回squaredNorm()的开方根,注意不管是几维的vector,都是开平方根。
    • lpNorm< p >(): p取Infinity,就表示L∞范数,p取1就表示L1范数,p取2就表示L2范数

    范数的概念:

    • 1范数:即向量元素绝对值之和
    • 2范数:Euclid范数(欧几里得范数,常用计算向量长度),即向量元素绝对值的平方和再开方
    • ∞范数:即所有向量元素绝对值中的最大值

    2.1 Euclidean Distance

    double Astar::getEuclHeu(Eigen::Vector3d x1, Eigen::Vector3d x2)
    {
      return tie_breaker_ * (x2 - x1).norm(); //norm = sqrt(squaredNorm())
    }

    理想结果是(PathFinding.js) VS 实际结果,正确!

            

    2.2 Manhattan Distance

    引用

    在该网站的介绍中,有一个系数D,该如何理解。

    文中定义D:两个相邻栅格之间的最小距离。

    我的理解:这里之所以有D,是因为node是用的栅格索引,而不是物理上的位置,所以需要D,而我代码中,用的就是物理上的坐标,所以不需要D

    function heuristic(node) =
        dx = abs(node.x - goal.x)
        dy = abs(node.y - goal.y)
        return D * (dx + dy)
    double Astar::getManhHeu(Eigen::Vector3d x1, Eigen::Vector3d x2)
    {
      double dx = fabs(x1(0) - x2(0));
      double dy = fabs(x1(1) - x2(1));return tie_breaker_ * (dx + dy);
    }

    理想结果是(PathFinding.js) VS 实际结果,正确!

    2.3 Diagonal Distance

    引用

    如果曼哈顿需要上移4,右移4,共8*D,(D代表两个栅格的距离)

    那Diagonal需要斜着移动4*D2。(D2代表一个栅格的对角线距离)

    When D = 1 and D2 = 1, this is called the Chebyshev distance. When D = 1 and D2 = sqrt(2), this is called the octile distance.

    我这里采用octile distance。

    function heuristic(node) =
        dx = abs(node.x - goal.x)
        dy = abs(node.y - goal.y)
        return D * (dx + dy) + (D2 - 2 * D) * min(dx, dy)

    代码里是不是有问题,没起作用呢?确实有问题,代码中对应sqrt(2)是D2,2是2*D,很明显我把栅格间距认为是1了,

    但其实应该用自己的栅格地图的间距才行,我这里用的是0.05, 也就是说一个栅格的边长是0.05米。

    double Astar::getDiagHeu(Eigen::Vector3d x1, Eigen::Vector3d x2)
    {
      double dx = fabs(x1(0) - x2(0));
      double dy = fabs(x1(1) - x2(1));
      double h = (dx + dy) + 0.05 * (sqrt(2) - 2) * min(dx, dy);
      //double h = (dx + dy) + (sqrt(2) - 2) * min(dx, dy);
      return tie_breaker_ * h;
    }

          理想结果是(PathFinding.js) VS 实际结果,正确!                                                         

    2.4 其他

    下边这个启发值,可以使得路径尽量保持起点到终点连接的直线,对于洗地车来说,是比较合适的,但是代码里哪里有问题,没起作用。

    double Astar::getCrossHeu(Eigen::Vector3d s, Eigen::Vector3d c, Eigen::Vector3d e)
    {
      double dx1 = (c(0) - e(0));
      double dy1 = (c(1) - e(1));
      double dx2 = (s(0) - e(0));
      double dy2 = (s(1) - e(1));
      double cross = fabs(dx1*dy2 - dx2*dy1);
      double h = (c-e).norm();
      h = h + cross*0.001;
      return h; //norm = sqrt(squaredNorm())
    }
    dx1 = current.x - goal.x
    dy1 = current.y - goal.y
    dx2 = start.x - goal.x
    dy2 = start.y - goal.y
    cross = abs(dx1*dy2 - dx2*dy1)
    heuristic += cross*0.001
    理想效果是这样的:

    
    

    2.4 如何选用

    引用http://theory.stanford.edu/~amitp/GameProgramming/Heuristics.html#heuristics-for-grid-maps中的内容:

      四联通地图,用曼哈顿;

      八联通地图,用对角线距离;

      任意方向联通,用欧氏距离;

    • On a square grid that allows 4 directions of movement, use Manhattan distance (L1).
    • On a square grid that allows 8 directions of movement, use Diagonal distance (L∞).
    • On a square grid that allows any direction of movement, you might or might not want Euclidean distance (L2). If A* is finding paths on the grid but you are allowing movement not on the grid, you may want to consider other representations of the map.
    • On a hexagon grid that allows 6 directions of movement, use Manhattan distance adapted to hexagonal grids.

    3.tie break

    tie_break在代码里怎么不起作用呢??

    4. over-estimate heuristic

    如果将a*用于lattice中计算启发值,那速度绝对要非常快才行,所以感觉次有解是很有必要的;

    但是尝试过将h调大,有可能使得轨迹曲曲折折,这里应该需要cost function调整了。

  • 相关阅读:
    LeetCode:Symmetric Tree
    LeetCode:Construct Binary Tree from Inorder and Postorder Traversal,Construct Binary Tree from Preorder and Inorder Traversal
    LeetCode:Binary Tree Level Order Traversal I II
    LeetCode:Binary Tree Zigzag Level Order Traversal
    LeetCode:Convert Sorted Array to Binary Search Tree,Convert Sorted List to Binary Search Tree
    LeetCode:Balanced Binary Tree
    LeetCode:Minimum Depth of Binary Tree,Maximum Depth of Binary Tree
    LeetCode:Path Sum I II
    LeetCode:Flatten Binary Tree to Linked List
    LeetCode:Distinct Subsequences
  • 原文地址:https://www.cnblogs.com/gaowensheng/p/14772387.html
Copyright © 2011-2022 走看看