当前位置: 首页 > news >正文

从静态到动态:D * 算法如何革新机器人路径规划

一、引入背景

传统A*算法在静态环境中表现优异,但面对动态环境(如障碍物移动、地图更新)时存在显著缺陷:

  • 需重新搜索:环境变化后需从头计算路径,效率低下。
  • 无法利用历史信息:忽略已搜索区域的代价变化,导致重复计算。

D*(Dynamic A*)由Anthony Stentz于1994年提出,核心目标是高效处理动态环境中的路径更新,通过反向搜索代价增量更新机制,显著减少重新规划的计算量。

二、算法原理

一、反向搜索机制
1. 核心思想

传统A算法从起点向目标正向搜索,而D采用反向搜索(目标→起点),原因如下:

  • 动态环境中目标固定:障碍物变化通常不影响目标点位置,反向搜索可避免起点频繁变化导致的全局重算。
  • 路径复用性:当局部环境变化时,仅需调整目标附近的路径段。
2. 反向代价定义
  • r h s ( n ) rhs(n) rhs(n):节点 n n n到目标的最优反向代价(实际代价)。
  • g ( n ) g(n) g(n):起点到节点 n n n的正向代价(估计值)。
  • 初始条件
    r h s ( goal ) = 0 , g ( goal ) = 0 rhs(\text{goal}) = 0, \quad g(\text{goal}) = 0 rhs(goal)=0,g(goal)=0
二、评估函数推导
1. 优先级函数

D*的优先级队列按以下公式排序:
k ( n ) = min ⁡ { g ( n ) + h ( n ) ,   r h s ( n ) + h ( n ) } k(n) = \min\{g(n) + h(n), \ rhs(n) + h(n)\} k(n)=min{g(n)+h(n), rhs(n)+h(n)}
推导逻辑

  • 正向路径评估 g ( n ) + h ( n ) g(n) + h(n) g(n)+h(n)(类似A*的 f ( n ) f(n) f(n))。
  • 反向路径评估 r h s ( n ) + h ( n ) rhs(n) + h(n) rhs(n)+h(n)(反向代价与启发式结合)。
  • 取最小值:确保优先处理路径中代价更高的节点,避免局部最优。
2. 启发式函数选择
  • 曼哈顿距离:适用于网格环境,公式为:
    h ( n ) = ∣ x n − x goal ∣ + ∣ y n − y goal ∣ h(n) = |x_n - x_{\text{goal}}| + |y_n - y_{\text{goal}}| h(n)=xnxgoal+ynygoal
  • 对角线距离:若允许对角线移动,公式为:
    h ( n ) = max ⁡ ( ∣ x n − x goal ∣ , ∣ y n − y goal ∣ ) h(n) = \max(|x_n - x_{\text{goal}}|, |y_n - y_{\text{goal}}|) h(n)=max(xnxgoal,ynygoal)
  • 可接受性要求 h ( n ) ≤ 实际代价 h(n) \leq \text{实际代价} h(n)实际代价,确保算法最优性。
三、代价更新规则
1. 节点状态转移

每个节点有三种状态,状态转移规则如下:

  • New → Open:节点首次被发现,加入队列。
  • Open → Closed:节点被扩展,生成后继节点。
  • Closed → Open:节点代价更新后需重新评估。
2. rhs(n)更新公式

对于节点 n n n的所有后继节点 s s s,其 r h s ( n ) rhs(n) rhs(n)由以下公式确定:
r h s ( n ) = min ⁡ s ∈ successors ( n ) { c ( n , s ) + g ( s ) } rhs(n) = \min_{s \in \text{successors}(n)} \left\{ c(n, s) + g(s) \right\} rhs(n)=ssuccessors(n)min{c(n,s)+g(s)}
其中 c ( n , s ) c(n, s) c(n,s)是从 n n n s s s的实际代价(如移动步数)。

3. 反向传播机制

当节点 u u u r h s ( u ) rhs(u) rhs(u)变化时,递归更新其父节点 v v v r h s ( v ) rhs(v) rhs(v)
r h s ( v ) = min ⁡ s ∈ successors ( v ) { c ( v , s ) + g ( s ) } rhs(v) = \min_{s \in \text{successors}(v)} \left\{ c(v, s) + g(s) \right\} rhs(v)=ssuccessors(v)min{c(v,s)+g(s)}
示例:若节点 u u u的代价增加,其父节点 v v v可能需要寻找其他更优路径。

四、收敛性证明
1. 算法终止条件

当以下条件满足时,算法终止:
g ( start ) = r h s ( start ) g(\text{start}) = rhs(\text{start}) g(start)=rhs(start)
此时起点到目标的路径已收敛到最优解。

2. 正确性证明
  • 最优性:若启发式函数 h ( n ) h(n) h(n)是admissible(不高估实际代价),则D*保证找到最优路径。
  • 有限性:每次环境变化后,算法在有限步内重新收敛。
3. 复杂度分析
  • 时间复杂度:每次环境变化的重新规划时间与受影响节点数成正比,而非全局节点数。
  • 空间复杂度:存储节点状态和优先级队列,与A*相当。
五、数学示例

假设网格环境中,目标点 G ( 0 , 0 ) G(0,0) G(0,0),当前节点 A ( 1 , 1 ) A(1,1) A(1,1),启发式函数为曼哈顿距离:

  1. 初始状态
    r h s ( G ) = 0 rhs(G) = 0 rhs(G)=0, g ( G ) = 0 g(G) = 0 g(G)=0
  2. 扩展节点 G G G的前驱
    节点 B ( 0 , 1 ) B(0,1) B(0,1),计算 r h s ( B ) = c ( B , G ) + g ( G ) = 1 + 0 = 1 rhs(B) = c(B,G) + g(G) = 1 + 0 = 1 rhs(B)=c(B,G)+g(G)=1+0=1
  3. 优先级队列排序
    k ( B ) = min ⁡ { g ( B ) + h ( B ) , r h s ( B ) + h ( B ) } = min ⁡ { ∞ + 1 , 1 + 1 } = 2 k(B) = \min\{g(B) + h(B), rhs(B) + h(B)\} = \min\{\infty + 1, 1 + 1\} = 2 k(B)=min{g(B)+h(B),rhs(B)+h(B)}=min{+1,1+1}=2
六、与A*的数学差异
特性A*D*
搜索方向正向(起点→目标)反向(目标→起点)
评估函数 f ( n ) = g ( n ) + h ( n ) f(n) = g(n) + h(n) f(n)=g(n)+h(n) k ( n ) = min ⁡ { g ( n ) + h ( n ) , r h s ( n ) + h ( n ) } k(n) = \min\{g(n)+h(n), rhs(n)+h(n)\} k(n)=min{g(n)+h(n),rhs(n)+h(n)}
路径更新全局重新搜索局部反向传播更新
动态适应性差(需重新计算)优(增量更新)

三、算法流程

以下是D*算法流程的详细分步解析,包含伪代码、状态转移逻辑和关键数据结构说明:

一、算法流程总览

D*算法分为三个核心阶段:初始化路径搜索动态更新。其流程通过优先队列(Priority Queue)和节点状态机(State Machine)驱动,确保高效处理动态环境。

二、初始化阶段
1. 数据结构初始化
  • 节点属性表:存储每个节点的 g ( n ) g(n) g(n) r h s ( n ) rhs(n) rhs(n)、状态(New/Open/Closed)。
  • 优先队列:按 k ( n ) = min ⁡ { g ( n ) + h ( n ) , r h s ( n ) + h ( n ) } k(n) = \min\{g(n)+h(n), rhs(n)+h(n)\} k(n)=min{g(n)+h(n),rhs(n)+h(n)}排序。
  • 邻接表:记录每个节点的前驱(Predecessors)和后继(Successors)。
2. 初始参数设置
def initialize():
    goal = (0, 0)  # 目标点坐标
    start = (5, 5)  # 起点坐标
    
    # 初始化目标点
    rhs[goal] = 0
    g[goal] = 0
    state[goal] = 'Closed'
    
    # 初始化所有节点的rhs和g值
    for all nodes n:
        if n != goal:
            rhs[n] = ∞
            g[n] = ∞
            state[n] = 'New'
    
    # 将目标点加入优先队列
    priority_queue.push(goal, k=0)
三、主循环阶段(路径搜索)
1. 主循环逻辑
while priority_queue not empty:
    u = priority_queue.pop_min()  # 取出优先级最高的节点
    if u == start and g[u] == rhs[u]:  # 路径已收敛
        break
    if g[u] > rhs[u]:  # 节点u的g值需更新
        g[u] = rhs[u]
        state[u] = 'Closed'
        # 更新所有前驱节点v的rhs值
        for v in predecessors[u]:
            update_rhs(v)
            if state[v] == 'Closed':
                add_to_queue(v)
    else:  # g[u] < rhs[u],节点u需重新计算
        g[u] = ∞
        state[u] = 'Open'
        # 更新所有前驱节点v的rhs值
        for v in predecessors[u]:
            update_rhs(v)
            if state[v] == 'Closed':
                add_to_queue(v)
2. 关键函数详解
  • update_rhs(v)
    r h s ( v ) = min ⁡ s ∈ successors ( v ) { c ( v , s ) + g ( s ) } rhs(v) = \min_{s \in \text{successors}(v)} \left\{ c(v,s) + g(s) \right\} rhs(v)=ssuccessors(v)min{c(v,s)+g(s)}

    • 重新计算节点 v v v的反向代价。
    • r h s ( v ) rhs(v) rhs(v)变化,需触发前驱节点的更新。
  • add_to_queue(v)

    • 计算 k ( v ) = min ⁡ { g ( v ) + h ( v ) , r h s ( v ) + h ( v ) } k(v) = \min\{g(v)+h(v), rhs(v)+h(v)\} k(v)=min{g(v)+h(v),rhs(v)+h(v)}
    • v v v不在队列中,插入队列;否则,若新 k ( v ) k(v) k(v)更小,更新优先级。
四、动态更新阶段(环境变化处理)
1. 环境变化检测
  • 触发条件:传感器检测到障碍物变化、地图更新等。
  • 处理步骤
    1. 标记受影响的节点(如障碍物周围的节点)。
    2. 更新受影响节点的代价(如将障碍物节点的移动代价设为无穷大)。
2. 局部重新规划
def handle_obstacle_change(obstacle_node):
    # 更新障碍物节点的代价
    for neighbor in get_neighbors(obstacle_node):
        c(neighbor, obstacle_node) =# 无法通行
    
    # 触发反向传播更新
    for v in predecessors[obstacle_node]:
        update_rhs(v)
        add_to_queue(v)
    
    # 重新运行主循环直到路径收敛
    while not is_converged(start):
        process_node()
五、状态转移图
发现节点
扩展节点
代价变化
重新评估
New
Open
Closed
六、算法收敛性条件

当满足以下条件时,算法终止:

  1. 起点条件 g ( start ) = r h s ( start ) g(\text{start}) = rhs(\text{start}) g(start)=rhs(start)
  2. 全局一致性:所有节点的 g ( n ) g(n) g(n) r h s ( n ) rhs(n) rhs(n)满足:
    g ( n ) = min ⁡ s ∈ successors ( n ) { c ( n , s ) + g ( s ) } g(n) = \min_{s \in \text{successors}(n)} \left\{ c(n,s) + g(s) \right\} g(n)=ssuccessors(n)min{c(n,s)+g(s)}
七、与A*算法的流程对比
步骤A*D*
搜索方向正向(起点→目标)反向(目标→起点)
队列管理仅插入新节点动态更新节点优先级
环境变化重新初始化搜索局部更新受影响节点
终止条件找到目标点起点的g和rhs收敛
八、示例:网格环境中的路径更新
  1. 初始状态:目标点 G ( 0 , 0 ) G(0,0) G(0,0),起点 S ( 5 , 5 ) S(5,5) S(5,5)
  2. 首次搜索:D*从 G G G出发,构建反向路径到 S S S
  3. 障碍物出现:在 ( 3 , 3 ) (3,3) (3,3)处出现障碍物。
  4. 更新处理
    • 标记 ( 3 , 3 ) (3,3) (3,3)及其邻域节点的代价为无穷大。
    • 反向传播更新 ( 3 , 3 ) (3,3) (3,3)的前驱节点的 r h s rhs rhs值。
    • 优先队列重新计算受影响节点的优先级,生成新路径。
九、优化策略
  1. 双向搜索:结合正向和反向搜索,减少搜索空间。
  2. 分层规划:将地图划分为子区域,优先处理高层路径。
  3. 增量式启发式:根据环境变化动态调整 h ( n ) h(n) h(n)的权重。

五、优势对比

一、对比维度总览
对比维度D*A*DijkstraLPA*DWA
适用场景动态环境静态环境静态环境动态环境实时避障
搜索方向反向(目标→起点)正向(起点→目标)正向双向局部规划
更新方式局部增量更新全局重新搜索无动态更新局部更新在线调整
时间复杂度O(k log n)O(m log n)O(n²)O(k log n)O(1)
空间复杂度O(n)O(n)O(n²)O(n)O(1)
实时性较高
路径质量最优最优最优次优次优
扩展性
历史信息利用完全复用部分复用部分复用
收敛性严格保证严格保证严格保证概率保证不保证
二、详细优势对比
1. 动态环境适应性
  • D*:

    • 局部更新:仅重新计算受环境变化影响的节点(如障碍物周围节点),避免全局搜索。
    • 反向传播:通过更新前驱节点的rhs值,高效传递环境变化的影响。
    • 案例:自动驾驶中突发障碍物,D*可在100ms内完成路径调整。
  • 对比算法

    • A*:环境变化后需重新初始化,计算时间与地图规模成正比。
    • DWA:仅处理局部避障,无法生成全局最优路径。
2. 计算效率
  • D*:

    • **O(k log n)**时间复杂度(k为受影响节点数)。
    • 优先级队列优化:动态调整节点优先级,减少重复评估。
    • 反向搜索:从目标点出发,优先扩展高价值节点(如靠近起点的节点)。
  • 对比算法

    • Dijkstra:每次搜索需遍历所有节点,时间复杂度为O(n²)。
    • LPA*:需维护双向搜索,空间复杂度较高。
3. 路径质量保证
  • D*:

    • 严格最优性:通过g(n)rhs(n)的一致性检查,确保路径始终最优。
    • 启发式函数:使用可接受的启发式(如曼哈顿距离),避免陷入局部最优。
  • 对比算法

    • DWA:仅生成次优路径,依赖参数调优。
    • LPA*:在极端情况下可能出现路径震荡。
4. 资源消耗
  • D*:

    • 线性空间复杂度:仅需存储节点属性表和邻接关系。
    • 内存优化:通过状态机(New/Open/Closed)减少冗余数据。
  • 对比算法

    • Dijkstra:需存储所有节点的最短路径树,空间占用大。
    • A*:在大规模地图中优先队列可能爆炸。
5. 实时性与扩展性
  • D*:

    • 分层规划:支持将地图划分为子区域,逐层优化(如先规划主干道再细化局部)。
    • 增量式更新:适用于连续传感器输入(如激光雷达每100ms更新一次)。
  • 对比算法

    • A*:扩展性差,地图扩大10倍计算时间可能增加100倍。
    • DWA:无法处理全局路径规划。
三、典型应用场景匹配
场景D优势*其他算法局限性
无人机动态避障实时局部更新,适应突发障碍物A*需重新搜索,DWA无法生成全局路径
自动驾驶结合高精度地图与实时传感器,保持路径最优性Dijkstra无法处理动态变化,LPA*存在路径震荡风险
服务机器人导航内存占用低,支持多层环境(如商场楼层切换)DWA仅适用于局部避障,A*在多楼层场景扩展性差
军事侦察严格最优路径,避免暴露于敌方监测区域LPA*的次优路径可能增加风险,DWA无法规划全局路线

D*算法在动态环境适应性计算效率上显著优于传统算法,尤其适合实时性要求高、环境变化频繁的场景。其反向搜索局部更新机制是突破传统路径规划局限性的核心创新点,使其成为移动机器人、自动驾驶等领域的标杆算法。

http://www.dtcms.com/a/108296.html

相关文章:

  • 图形渲染: tinyrenderer 实现笔记(Lesson 1 - 4)
  • ATEngin开发记录_1_在Vsiual Studio2022中使用ReShaper创建类模板
  • 理解激活函数,多个网络层之间如何连接
  • 红宝书第二十七讲:详解WebAssembly与asm.js如何实现高效执行
  • 七种分布式ID生成方式详细介绍--Redis、雪花算法、号段模式以及美团Leaf 等
  • 二分查找与二分答案入门c++
  • 如何对后端API进行负载测试
  • vue将组件中template转为js
  • codeforces C. Creating Keys for StORages Has Become My Main Skill
  • systemd服务开机启动(code=exited, status=203/EXEC)错误,由于SELinux 开启安全模式
  • AI知识补全(十五):AI可解释性与透明度是什么?
  • 详细说明一下C++中的static关键字
  • 火山引擎coze用户市场
  • 使用PyTorch实现GoogleNet(Inception)并训练Fashion-MNIST
  • 【华为OD技术面试真题 - 技术面】- Java面试题(17)
  • 移动端六大语言速记:第1部分 - 基础语法与控制结构
  • 网络安全协议知识点总结
  • 网络空间安全(49)Python基础语法
  • 三.微服务架构中的精妙设计:服务注册/服务发现-Eureka
  • JavaScript reduce 方法详解
  • 视图函数的应用
  • 数据仓库项目启动与管理
  • App与Page构造器
  • vim的操作
  • Java面试31-MySQL如何解决幻读问题?
  • 【HTB】Linux-Shocker靶机渗透
  • 人工智能基础知识笔记七:随机变量的几种分布
  • Font Awesome 音/视频图标
  • 程序代码篇---Arm汇编语言
  • Laravel 中使用 JWT 作用户登录,身份认证