【问题标题】:A* orientation discretizationA* 方向离散化
【发布时间】:2016-02-07 23:58:48
【问题描述】:

我有一个有障碍物的空间,我想找到一条路径。我能做的就是将空间离散化成一个网格并使用 A*(或 D* 或其他)来找到通过它的路径。我现在希望为算法添加方向。所以节点位置现在变成了一个 3d 向量 (x, y, phi)。只有当它们属于弧线时,您才能从一个节点转到另一个节点(两个位置都在一个圆上并且沿切线定向)。我如何离散空间,以便角度不会在某种意义上爆炸,通过遍历图形,可能的角度集变得有限? 谢谢。

【问题讨论】:

    标签: graph shortest-path path-finding a-star


    【解决方案1】:

    可以通过确保 phi 被认为是模 2pi 来防止角度爆炸,即对于 k 的任何整数值,phi = phi + 2pi*k。

    在类似 C 的语法中,您最终可能会使用 fmod 更新 phi。

    phi = fmod(phi + deltaphi, 2*pi)
    

    其中 deltaphi 是您引入的角度变化(以弧度为单位)。

    执行此操作的最常见方法是将角度 phi 的值限制为采用 n 离散角度之一,这也具有避免精度/舍入问题的优势。鉴于您知道 phi 只能采用 n 值之一,您可以将其视为整数,并在必要时将值映射为实数。

    i = (i + deltai) % n
    phi = (2*i*pi)/n)  
    

    角度 delta 的变化是 (2*deltai*pi)/n 弧度。

    但是,找到一个好的离散化只是解决方案的一部分 - 它定义了您的配置空间的表示,但正如您所指出的,您还需要考虑什么是有效的转换。

    将角度整合到规划中的最简单方法是要求旋转和平移是不同的(在任何时候你可以做一个或另一个,但不能同时做),或者是可组合的(总是平移,然后立即到达旋转)。

    在您转弯时同时向前和/或向后移动更复杂,并且往往不适用于离散格子 - 它往往需要您正在使用的车辆的某些模型。最常见的是简单的非完整模型-仅前进的汽车(杜宾斯的汽车)或具有前进/后退功能的汽车(里德谢普汽车)-您提到圆的切线,我猜这就是您的意思后。 Dubins-Curves 或类似的库可用于构建可与 A*(或 D*)规划器组合的可能路径库。

    Differentially Constrained Mobile Robot Motion Planning in State Lattices 由 Mihail Pivtoraiko、Ross A. Knepper 和 Alonzo Kelly 撰写,展示了一些惊人的可能性。

    【讨论】:

    • 感谢您的回答,但我认为您错过了我的主要问题。首先,我说机器人只能跟随弧线(它是非完整的车辆)。因此,如果它转换到一侧,它也必须改变航向。如果我们采用 3x3 网格邻域,它将仅生成 4 个可能的航向(k*90 度)。但是,如果我们采用 5x5 网格邻域,一些点会产生不合理的航向(atan(2)、atan(1/2) 等)。算法识别它已经访问过一个节点是很重要的。我很容易离散化位置(整数坐标)。如何离散化标题?
    • 我读过你提到的那篇论文,但对我来说还是有点模糊。谢谢。
    【解决方案2】:

    据我了解,您的挑战不是离散坐标,而是离散标题。我必须在允许在八个方向(即水平、垂直和对角线)移动的网格世界中做同样的事情。 你的离散空间应该与问题域相匹配。供您参考:

    • 4 方向:使用可跨边移动的方形网格
    • 8 方向 使用方形网格,并在边缘 和 顶点之间移动
    • 6 个方向使用六边形网格,可跨边移动
    • 12 方向使用六边形网格,可跨边和点移动
    • ... 等等。

    为了真正获得离散化的标题,我声明了一个名为 Direction 的 enum:

    public enum Direction {
        North,
        NorthEast,
        East,
        SouthEast,
        South,
        SouthWest,
        West,
        NorthWest;
    
    //additional code below...
    } 
    

    您可以通过首先计算当前位置和目标位置之间的 XY 偏移量来查找正确的航向:

    int dx = currentPosition.x - goalPosition.x;
    int dy = currentPosition.y - goalPosition.y;
    

    这些被传递给getInstance(int,int) 方法(如下)以获得正确的Direction:

    public static Direction getInstance(int dx, int dy) {
        int count = Direction.values().length;
        double rad = Math.atan2(dy, dx); // In radians
        double degree = rad * (180 / Math.PI) + 450;
    
        return getInstance(((int) Math.round(((degree % 360) / (360 / count)))) % count);
    }
    
    public static Direction getInstance(int i) {
        return Direction.values()[i % Direction.count];
    }
    

    实际上,这些方法以度为单位计算航向并四舍五入到最接近的Direction。然后,您可以实现一个方法来移动/转动 Direction 标题中的代理,例如agent.turnToward(Direction d) 或 agent.move(Direction d)。

    其他资源:

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-04-02
      • 1970-01-01
      • 2013-11-01
      • 2012-06-03
      • 2017-04-05
      • 2020-08-20
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多