DWA算法与RRT*融合算法,。 还有单独dwa,单独A*,RRT,RRT*(2/3d地图)等路径规划算法,可自定义地图。 运行效果如图所示

在机器人运动规划领域,路径规划算法一直是核心话题。今天咱们就唠唠 DWA 算法、A算法、RRT 算法以及 RRT算法,还有它们之间的融合,以及如何自定义地图来测试这些算法。

DWA 算法

DWA(Dynamic Window Approach)算法主要用于动态环境下的局部路径规划。它通过考虑机器人当前的速度和加速度限制,在一个动态窗口内搜索最优的速度和转向角。

以下是简化的 DWA 代码示例(Python 伪代码):

def dwa_algorithm(robot_state, obstacles, goal):
    # 获取机器人的速度限制和加速度限制
    min_vel, max_vel, min_omega, max_omega = get_robot_limits(robot_state)
    # 定义动态窗口
    dynamic_window = [(v, omega) for v in np.arange(min_vel, max_vel, 0.1) for omega in np.arange(min_omega, max_omega, 0.1)]
    best_score = -np.inf
    best_vel = None
    for vel, omega in dynamic_window:
        # 预测下一时刻的状态
        predicted_state = predict_state(robot_state, vel, omega)
        # 计算代价函数,这里简单以到目标点的距离为例
        score = -distance_to_goal(predicted_state, goal) - collision_cost(predicted_state, obstacles)
        if score > best_score:
            best_score = score
            best_vel = (vel, omega)
    return best_vel

这段代码首先确定机器人的速度和转向角范围,形成动态窗口。然后对窗口内每个可能的速度和转向角组合进行状态预测,并根据到目标点的距离和碰撞代价计算得分,最终选择得分最高的组合作为下一时刻的控制指令。

A* 算法

A*算法是经典的全局路径规划算法,它结合了 Dijkstra 算法的广度优先搜索和贪心算法的最佳优先搜索思想。通过一个启发函数(比如曼哈顿距离或欧几里得距离)来引导搜索朝着目标前进。

import heapq

def a_star(start, goal, map):
    open_set = []
    heapq.heappush(open_set, (0, start))
    came_from = {}
    g_score = {node: float('inf') for node in map.nodes()}
    g_score[start] = 0
    f_score = {node: float('inf') for node in map.nodes()}
    f_score[start] = heuristic(start, goal)

    while open_set:
        _, current = heapq.heappop(open_set)
        if current == goal:
            path = []
            while current in came_from:
                path.append(current)
                current = came_from[current]
            path.append(start)
            path.reverse()
            return path

        for neighbor in map.neighbors(current):
            tentative_g_score = g_score[current] + cost(current, neighbor)
            if tentative_g_score < g_score[neighbor]:
                came_from[neighbor] = current
                g_score[neighbor] = tentative_g_score
                f_score[neighbor] = tentative_g_score + heuristic(neighbor, goal)
                if neighbor not in [i[1] for i in open_set]:
                    heapq.heappush(open_set, (f_score[neighbor], neighbor))
    return None

这里通过优先队列 openset 来存储待扩展节点,根据 fscoregscore 加上启发函数值)来排序。gscore 表示从起点到当前节点的实际代价,heuristic 函数估计从当前节点到目标节点的代价。不断扩展节点,直到找到目标节点或者队列为空。

RRT 与 RRT* 算法

RRT(Rapidly - exploring Random Tree)算法是一种基于采样的路径规划算法,通过随机采样空间中的点,并逐步扩展搜索树,找到从起点到目标点的路径。

import random

class Node:
    def __init__(self, state):
        self.state = state
        self.parent = None

def rrt(start, goal, map, max_iter):
    root = Node(start)
    tree = [root]
    for i in range(max_iter):
        sample = sample_free(map)
        nearest = nearest_neighbor(tree, sample)
        new_state = steer(nearest.state, sample)
        if not collision(new_state, map):
            new_node = Node(new_state)
            new_node.parent = nearest
            tree.append(new_node)
            if distance(new_state, goal) < goal_threshold:
                goal_node = Node(goal)
                goal_node.parent = new_node
                tree.append(goal_node)
                path = []
                current = goal_node
                while current.parent:
                    path.append(current.state)
                    current = current.parent
                path.append(start)
                path.reverse()
                return path
    return None

上述代码中,rrt 函数不断在地图的自由空间采样点 sample,找到树中距离采样点最近的节点 nearest,向采样点方向前进得到新节点 new_node,如果新节点不与障碍物碰撞则加入树中,直到找到接近目标点的路径。

RRT* 是 RRT 的改进版本,它在扩展树的过程中,通过重新布线(rewiring)操作来优化路径,使得生成的路径更优。

def rrt_star(start, goal, map, max_iter):
    root = Node(start)
    tree = [root]
    for i in range(max_iter):
        sample = sample_free(map)
        nearest = nearest_neighbor(tree, sample)
        new_state = steer(nearest.state, sample)
        if not collision(new_state, map):
            new_node = Node(new_state)
            new_node.parent = nearest
            nearby = nearby_nodes(tree, new_state)
            best_parent = select_best_parent(new_node, nearby)
            new_node.parent = best_parent
            tree.append(new_node)
            rewire(new_node, nearby)
            if distance(new_state, goal) < goal_threshold:
                goal_node = Node(goal)
                goal_node.parent = new_node
                tree.append(goal_node)
                path = []
                current = goal_node
                while current.parent:
                    path.append(current.state)
                    current = current.parent
                path.append(start)
                path.reverse()
                return path
    return None

rrtstar 函数里,selectbest_parent 函数从附近节点中选择一个使新节点代价最小的节点作为父节点,rewire 函数则尝试优化附近节点的父节点,以降低整个树的代价。

DWA 与 RRT* 融合算法

融合 DWA 和 RRT 算法可以结合全局路径规划和局部动态规划的优势。先使用 RRT 算法生成全局路径,然后在机器人沿着全局路径行进时,使用 DWA 算法进行局部路径调整,以应对动态障碍物。

def dwa_rrt_star(start, goal, map):
    global_path = rrt_star(start, goal, map, max_iter=1000)
    if not global_path:
        return None
    robot_state = start
    for i in range(len(global_path) - 1):
        sub_goal = global_path[i + 1]
        while distance(robot_state, sub_goal) > sub_goal_threshold:
            vel, omega = dwa_algorithm(robot_state, get_obstacles(map), sub_goal)
            robot_state = update_state(robot_state, vel, omega)
    return global_path

这段代码先用 rrtstar 生成全局路径,然后机器人沿着全局路径分段前进,每段使用 dwaalgorithm 调整路径,以适应动态环境。

自定义地图

为了测试这些算法,我们可以自定义地图。以简单的二维地图为例,地图可以用二维数组表示,0 表示自由空间,1 表示障碍物。

map = [
    [0, 0, 0, 0, 0],
    [0, 1, 0, 1, 0],
    [0, 0, 0, 0, 0],
    [0, 1, 1, 1, 0],
    [0, 0, 0, 1, 0]
]

在实际应用中,地图可以从文件读取或者通过传感器实时生成。

以上这些算法各有优劣,在实际项目中,我们可以根据具体场景选择合适的算法或者算法融合方案。希望这篇博文能帮助你对路径规划算法有更深入的了解。运行效果就像我们看到的图示那样,不同算法在自定义地图上各展神通,为机器人规划出一条条或全局最优、或适应动态环境的路径。

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐