Skip to content

Path Planning - 路径规划

路径规划是机器人导航的核心技术,它使机器人能够从起点找到一条到达终点的安全路径。

什么是路径规划?

┌─────────────────────────────────────────────────────────────┐
│                    路径规划问题                               │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  输入:                                                     │
│    - 起点位置                                               │
│    - 终点位置                                               │
│    - 环境地图                                               │
│    - 机器人模型                                             │
│                                                             │
│  输出:                                                     │
│    - 路径点序列                                             │
│    - 路径长度                                               │
│    - 路径安全性                                             │
│                                                             │
│  约束:                                                     │
│    - 避障                                                   │
│    - 运动学约束                                             │
│    - 动力学约束                                             │
│    - 时间约束                                               │
│                                                             │
└─────────────────────────────────────────────────────────────┘

路径规划算法

1. 搜索算法

算法 特点 适用场景
Dijkstra 最短路径,无启发式 任意图
A* 最短路径,有启发式 已知地图
D* 动态规划 动态环境
Lattice 离散化搜索 网格地图

2. 采样算法

算法 特点 适用场景
RRT 快速随机探索 高维空间
RRT* 渐近最优 需要最优路径
PRM 概率路线图 多查询
Informed RRT* 启发式采样 高效搜索

3. 优化算法

算法 特点 适用场景
TrajOpt 轨迹优化 平滑路径
CHOMP 协作优化 避障优化
STOMP 随机优化 非梯度优化

ROS Navigation Stack

ROS Navigation Stack 是 ROS 中最常用的导航框架。

架构

┌─────────────────────────────────────────────────────────────┐
│                ROS Navigation Stack                          │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  ┌─────────────────────────────────────────────────────┐   │
│  │              Global Planner                          │   │
│  │  (全局路径规划)                                      │   │
│  └─────────────────────┬───────────────────────────────┘   │
│                        │                                   │
│                        ▼                                   │
│  ┌─────────────────────────────────────────────────────┐   │
│  │              Local Planner                           │   │
│  │  (局部路径规划)                                      │   │
│  └─────────────────────┬───────────────────────────────┘   │
│                        │                                   │
│                        ▼                                   │
│  ┌─────────────────────────────────────────────────────┐   │
│  │              Controller                              │   │
│  │  (控制器)                                            │   │
│  └─────────────────────────────────────────────────────┘   │
│                                                             │
│  输入:                                                     │
│    - 地图 (map_server)                                      │
│    - 传感器数据 (激光雷达、深度相机)                        │
│    - 里程计 (odom)                                          │
│    - 目标点 (move_base)                                     │
│                                                             │
│  输出:                                                     │
│    - 速度命令 (cmd_vel)                                     │
│                                                             │
└─────────────────────────────────────────────────────────────┘

核心组件

1. move_base

move_base 是导航栈的核心节点,负责协调全局和局部规划。

# 启动 move_base
roslaunch move_base move_base.launch

2. 地图服务器

# 启动地图服务器
roslaunch map_server map_server.launch map_file:=/path/to/map.yaml

3. 定位

# 使用 AMCL 定位
roslaunch amcl amcl.launch

配置文件

costmap_common_params.yaml

# 通用代价地图参数
obstacle_range: 2.5
raytrace_range: 3.0
footprint: [[-0.2, -0.2], [-0.2, 0.2], [0.2, 0.2], [0.2, -0.2]]
inflation_radius: 0.55

observation_sources: laser_scan_sensor

laser_scan_sensor: {
  sensor_frame: laser,
  data_type: LaserScan,
  topic: /scan,
  marking: true,
  clearing: true
}

global_costmap_params.yaml

# 全局代价地图参数
global_costmap:
  global_frame: map
  robot_base_frame: base_link
  update_frequency: 5.0
  static_map: true
  rolling_window: false
  resolution: 0.05
  inflation_radius: 0.55

local_costmap_params.yaml

# 局部代价地图参数
local_costmap:
  global_frame: odom
  robot_base_frame: base_link
  update_frequency: 5.0
  static_map: false
  rolling_window: true
  width: 4.0
  height: 4.0
  resolution: 0.05
  inflation_radius: 0.3

base_local_planner_params.yaml

# 局部规划器参数
TrajectoryPlannerROS:
  max_vel_x: 0.5
  min_vel_x: 0.1
  max_vel_theta: 1.0
  min_vel_theta: -1.0
  min_in_place_vel_theta: 0.4
  escape_vel: -0.1
  acc_lim_x: 2.5
  acc_lim_theta: 3.2
  holonomic_robot: false
  meter_scoring: true
  pdist_scale: 0.6
  gdist_scale: 0.8
  occdist_scale: 0.1
  heading_lookahead: 0.325
  dwa: true

步骤 1:启动导航

# 启动机器人
roslaunch my_robot bringup.launch

# 启动导航
roslaunch my_robot navigation.launch

# 启动 RViz
roslaunch my_robot rviz_navigation.launch

步骤 2:设置初始位置

在 RViz 中使用 "2D Pose Estimate" 设置机器人初始位置。

步骤 3:设置目标位置

在 RViz 中使用 "2D Nav Goal" 设置目标位置。

步骤 4:监控导航

# 查看路径规划
rostopic echo /move_base/NavfnROS/plan

# 查看速度命令
rostopic echo /cmd_vel

# 查看导航状态
rostopic echo /move_base/status

路径规划算法实现

1. A* 算法

import heapq

def astar(grid, start, goal):
    """A* 路径规划算法"""

    # 启发式函数(曼哈顿距离)
    def heuristic(a, b):
        return abs(a[0] - b[0]) + abs(a[1] - b[1])

    # 初始化
    open_set = []
    heapq.heappush(open_set, (0, start))
    came_from = {}
    g_score = {start: 0}
    f_score = {start: heuristic(start, goal)}

    while open_set:
        current = heapq.heappop(open_set)[1]

        if current == goal:
            # 重建路径
            path = []
            while current in came_from:
                path.append(current)
                current = came_from[current]
            path.append(start)
            return path[::-1]

        # 探索邻居
        for dx, dy in [(0, 1), (0, -1), (1, 0), (-1, 0)]:
            neighbor = (current[0] + dx, current[1] + dy)

            # 检查边界和障碍物
            if (0 <= neighbor[0] < len(grid) and 
                0 <= neighbor[1] < len(grid[0]) and 
                grid[neighbor[0]][neighbor[1]] == 0):

                tentative_g = g_score[current] + 1

                if neighbor not in g_score or tentative_g < g_score[neighbor]:
                    came_from[neighbor] = current
                    g_score[neighbor] = tentative_g
                    f_score[neighbor] = tentative_g + heuristic(neighbor, goal)
                    heapq.heappush(open_set, (f_score[neighbor], neighbor))

    return None  # 没有找到路径

2. RRT 算法

import random
import math

def rrt(start, goal, obstacles, max_iter=1000, step_size=0.5):
    """RRT 路径规划算法"""

    # 初始化树
    tree = {start: None}

    for _ in range(max_iter):
        # 随机采样
        if random.random() < 0.1:
            q_rand = goal
        else:
            q_rand = (random.uniform(0, 10), random.uniform(0, 10))

        # 找到最近节点
        q_near = min(tree.keys(), key=lambda q: distance(q, q_rand))

        # 扩展树
        q_new = steer(q_near, q_rand, step_size)

        # 检查碰撞
        if not collision_free(q_near, q_new, obstacles):
            continue

        # 添加到树
        tree[q_new] = q_near

        # 检查是否到达目标
        if distance(q_new, goal) < step_size:
            # 重建路径
            path = [goal]
            current = q_new
            while current is not None:
                path.append(current)
                current = tree[current]
            return path[::-1]

    return None  # 没有找到路径

避障策略

1. 静态避障

使用代价地图(Costmap)进行避障。

# costmap 参数
obstacle_range: 2.5
raytrace_range: 3.0
inflation_radius: 0.55

2. 动态避障

使用局部规划器(DWA、TEB)进行动态避障。

# DWA 参数
max_vel_x: 0.5
min_vel_x: 0.1
max_vel_theta: 1.0
min_vel_theta: -1.0
acc_lim_x: 2.5
acc_lim_theta: 3.2

3. 人群避障

使用社会力模型或深度学习进行人群避障。

导航调试

1. 参数调优

# 查看当前参数
rosparam get /move_base

# 动态调参
rosrun rqt_reconfigure rqt_reconfigure

2. 可视化

在 RViz 中添加: - 全局代价地图 - 局部代价地图 - 全局路径 - 局部路径 - 机器人模型

3. 日志分析

# 查看导航日志
rostopic echo /move_base/status

# 查看错误
rosnode info /move_base

常见问题

1. 路径规划失败

原因:目标点在障碍物内或代价地图配置错误

解决方案: - 检查目标点是否有效 - 调整代价地图参数 - 增加探索范围

2. 机器人抖动

原因:局部规划器参数不当

解决方案: - 调整速度限制 - 增加平滑参数 - 使用更好的规划器(TEB)

3. 避障失败

原因:传感器数据不准确或代价地图配置错误

解决方案: - 校准传感器 - 调整障碍物检测范围 - 增加安全距离

实验

Lab 3-1: 路径规划

  1. 启动导航栈
  2. 设置初始位置
  3. 设置目标位置
  4. 观察路径规划过程
  5. 测试避障功能

下一步

参考资源