Files
note_sync/ros/ros2/nav2/nav2_bringup_gps_demo.md
T

14 KiB
Raw Blame History

Navigation2 详解:nav2_bringup 与 nav2_gps_waypoint_follower_demo

1. Navigation2 整体介绍

Navigation2(简称Nav2)是ROS2生态中最成熟的开源导航框架,是ROS1 Navigation Stack的官方继任者,专为移动机器人自主导航设计。

1.1 核心功能

  • 定位:支持AMCL、SLAM(Cartographer、SLAM Toolbox等)、GPS/RTK等多源定位
  • 全局路径规划:支持A*、Dijkstra、NavFn等多种规划算法
  • 局部路径跟踪:支持DWA、TEB、MPPI、Pure Pursuit等跟踪算法
  • 避障与行为树:通过行为树实现复杂导航逻辑,支持动态障碍物规避
  • 重规划与恢复行为:导航失败时自动执行恢复策略(旋转、回退、清图等)
  • 多机器人支持:支持命名空间隔离的多机器人导航

1.2 整体架构

Nav2采用模块化插件式设计,核心模块包括:

├── 感知层
│   ├── 传感器数据处理(LiDAR、Camera、IMU、GPS等)
│   └── 障碍物检测/语义分割
├── 定位层
│   ├── AMCL(蒙特卡洛定位)
│   ├── SLAM 建图
│   └── 多传感器融合定位
├── 地图层
│   ├── 代价地图(全局/局部)
│   ├── 图层插件(静态层、障碍层、膨胀层、社会层等)
├── 规划层
│   ├── 全局路径规划器
│   └── 平滑器
├── 控制层
│   ├── 局部路径规划器
│   └── 轨迹跟踪控制器
├── 行为决策层
│   ├── 行为树执行器
│   └── 恢复行为管理器
└── 接口层
    ├── RViz 可视化
    ├── Action/Topic API
    └── 配置参数系统

2. nav2_bringup 包详解

nav2_bringup是Nav2的官方启动集成包,提供了开箱即用的启动文件、配置模板和参数集合,是快速部署Nav2系统的入口。

2.1 代码结构

nav2_bringup/
├── bringup/                      # 启动相关核心目录
│   ├── launch/                   # 启动文件集合
│   │   ├── bringup_launch.py     # 主启动文件,集成所有导航模块
│   │   ├── localization_launch.py # 单独启动定位模块(AMCL/SLAM)
│   │   ├── navigation_launch.py  # 单独启动导航模块(规划/控制/行为树)
│   │   ├── rviz_launch.py        # 启动RViz可视化
│   │   ├── slam_launch.py        # 启动SLAM建图
│   │   └── urdf_launch.py        # 加载机器人URDF模型
│   ├── params/                   # 参数配置文件目录
│   │   ├── nav2_params.yaml      # 导航全模块默认参数
│   │   ├── nav2_params_no_odom.yaml # 无里程计场景参数
│   │   ├── nav2_slam_params.yaml # SLAM模式参数
│   │   └── robot_localization/  # 传感器融合参数模板
│   └── rviz/                     # RViz配置文件
│       └── nav2_default_view.rviz # Nav2默认RViz配置
├── docker/                       # Docker部署相关文件
├── scripts/                      # 辅助脚本
├── CMakeLists.txt
├── package.xml
└── README.md

2.2 核心启动文件说明

2.2.1 bringup_launch.py

这是最常用的一站式启动文件,集成了完整的导航流程,支持参数配置:

# 关键参数
'namespace': '',                  # 多机器人命名空间
'use_sim_time': False,            # 是否使用仿真时间
'rviz_config_file': '',           # RViz配置文件路径
'params_file': '',                # 导航参数文件路径
'autostart': True,                # 启动后自动激活导航栈
'use_composition': True,          # 使用组件化节点(减少进程数,提高性能)
'use_respawn': False,             # 节点崩溃时自动重启
'map': '',                        # 静态地图文件路径(.yaml/.pgm)
'slam': False,                    # 是否启用SLAM模式
'localization_type': 'amcl'       # 定位方式:amcl/slam_toolbox等

启动示例:

# 仿真环境启动导航
ros2 launch nav2_bringup bringup_launch.py use_sim_time:=True map:=/path/to/map.yaml

# 真机环境启用SLAM建图
ros2 launch nav2_bringup bringup_launch.py slam:=True params_file:=/path/to/my_params.yaml

2.2.2 localization_launch.py

单独启动定位模块,适合只需要定位不需要完整导航的场景:

# 仅启动AMCL定位
ros2 launch nav2_bringup localization_launch.py map:=/path/to/map.yaml use_sim_time:=True

2.2.3 navigation_launch.py

单独启动导航模块(规划/控制/行为树),适合定位已由其他系统提供的场景:

# 仅启动导航模块,使用已有的定位信息
ros2 launch nav2_bringup navigation_launch.py params_file:=/path/to/my_params.yaml

2.3 配置文件详解

nav2_params.yaml是核心参数配置文件,采用分层结构,每个模块单独配置:

amcl:
  ros__parameters:
    base_frame_id: "base_footprint"  # 机器人基坐标系
    global_frame_id: "map"           # 全局坐标系
    odom_frame_id: "odom"            # 里程计坐标系
    max_particles: 2000              # 最大粒子数
    min_particles: 500               # 最小粒子数
    update_min_a: 0.2                # 角度变化超过0.2rad时更新
    update_min_d: 0.25               # 位移超过0.25m时更新

bt_navigator:
  ros__parameters:
    use_sim_time: False
    bt_xml_filename: "navigate_w_replanning_and_recovery.xml"  # 行为树文件

global_costmap:
  global_costmap:
    ros__parameters:
      update_frequency: 1.0
      publish_frequency: 1.0
      global_frame: map
      robot_base_frame: base_footprint
      resolution: 0.05
      plugins:
        - {name: static_layer, type: "costmap_2d::StaticLayer"}
        - {name: obstacle_layer, type: "costmap_2d::ObstacleLayer"}
        - {name: inflation_layer, type: "costmap_2d::InflationLayer"}

local_costmap:
  local_costmap:
    ros__parameters:
      update_frequency: 5.0
      publish_frequency: 2.0
      global_frame: odom
      robot_base_frame: base_footprint
      width: 3
      height: 3
      resolution: 0.05
      rolling_window: true  # 局部代价地图随机器人移动

planner_server:
  ros__parameters:
    expected_planner_frequency: 1.0
    planner_plugins: ["GridBased"]
    GridBased:
      plugin: "nav2_navfn_planner/NavfnPlanner"  # 默认使用NavFn规划器
      use_astar: true  # 启用A*算法

controller_server:
  ros__parameters:
    controller_frequency: 20.0
    min_x_velocity_threshold: 0.001
    min_y_velocity_threshold: 0.5
    controller_plugins: ["FollowPath"]
    FollowPath:
      plugin: "nav2_regulated_pure_pursuit_controller/RegulatedPurePursuitController"  # 默认使用Pure Pursuit控制器

2.4 最佳实践

  1. 不要直接修改默认参数文件:将nav2_params.yaml复制到自己的工作空间进行修改,通过params_file参数传入
  2. 组件化启动:默认启用use_composition:=True可以显著减少内存占用和通信开销
  3. 分层配置:将通用参数和机器人特定参数分开存放,便于维护
  4. 仿真与真机分离:使用use_sim_time参数区分仿真和真机环境,分别配置不同的参数值

3. nav2_gps_waypoint_follower_demo 详解

这是Nav2官方提供的室外导航示例,演示了如何结合GPS/RTK定位实现全局航点跟随功能,适用于无人车、巡检机器人等室外场景。

3.1 代码结构

该包位于navigation2_tutorials仓库中,结构如下:

nav2_gps_waypoint_follower_demo/
├── bringup/
│   ├── launch/
│   │   ├── gps_waypoint_follower_launch.py  # Demo主启动文件
│   │   ├── rviz.launch.py                   # RViz启动
│   │   └── dual_ekf.launch.py               # 双EKF传感器融合启动
│   ├── params/
│   │   ├── dual_ekf.yaml                    # 传感器融合参数
│   │   ├── nav2_params.yaml                 # 导航参数(适配GPS场景)
│   │   └── waypoint_follower_params.yaml    # 航点跟随器参数
│   ├── rviz/
│   │   └── gps_waypoint.rviz                # GPS导航专用RViz配置
│   └── worlds/
│       └── gps_world.world                  # 仿真世界文件(含GPS插件)
├── config/
│   └── sample_waypoints.yaml                # 示例航点配置文件
├── src/
│   └── gps_waypoint_logger.cpp              # 航点到达日志节点(可选)
├── CMakeLists.txt
├── package.xml
└── README.md

3.2 核心组件说明

GPS航点跟随系统主要由三个核心部分组成:

  1. 传感器融合模块(robot_localization):融合GPS、IMU、轮式里程计数据,输出全局定位
  2. 导航栈模块:基于全局定位进行路径规划和跟踪
  3. 航点跟随器:按照预设的GPS航点序列依次导航

3.2.1 双EKF传感器融合

demo使用两个扩展卡尔曼滤波器(EKF)实现多传感器融合:

# dual_ekf.yaml 核心配置
ekf_filter_node_odom:
  ros__parameters:
    frequency: 30.0
    sensor_timeout: 0.1
    two_d_mode: true
    publish_tf: true
    odom_frame: odom
    base_link_frame: base_link
    world_frame: odom
    # 融合IMU和轮式里程计,输出odom->base_link变换
    imu0: /imu/data
    odom0: /wheel/odometry

ekf_filter_node_map:
  ros__parameters:
    frequency: 30.0
    sensor_timeout: 0.1
    two_d_mode: true
    publish_tf: true
    odom_frame: odom
    base_link_frame: base_link
    world_frame: map
    # 融合GPS数据,输出map->odom变换
    odom1: /gps/fix
    odom1_differential: false
    odom1_relative: false
  • 第一个EKF(odom系):融合IMU和轮式里程计,提供短时间内高精度的局部定位,无漂移
  • 第二个EKF(map系):融合GPS数据,提供全局绝对定位,修正长期漂移

3.2.2 导航参数适配(nav2_params.yaml)

GPS导航场景需要对默认导航参数进行调整:

amcl:
  ros__parameters:
    # GPS导航场景下禁用AMCL,使用EKF融合提供定位
    use_sim_time: False
    # AMCL相关参数全部注释或删除

global_costmap:
  global_costmap:
    ros__parameters:
      # GPS模式下不使用静态地图,使用动态生成的代价地图
      plugins:
        - {name: obstacle_layer, type: "costmap_2d::ObstacleLayer"}
        - {name: inflation_layer, type: "costmap_2d::InflationLayer"}
      # 代价地图大小足够覆盖所有航点范围
      width: 1000
      height: 1000
      resolution: 0.1
      rolling_window: false  # 全局代价地图固定,不随机器人移动
      origin_x: -500
      origin_y: -500

planner_server:
  ros__parameters:
    # 使用适合长距离规划的算法
    GridBased:
      plugin: "nav2_navfn_planner/NavfnPlanner"
      use_astar: true
      allow_unknown: true  # 允许在未知区域规划路径

controller_server:
  ros__parameters:
    # 使用适合高速行驶的控制器
    FollowPath:
      plugin: "nav2_mppi_controller/MPPIController"  # 或者TEB控制器
      max_vel_x: 5.0  # 室外场景允许更高速度

3.2.3 航点跟随器配置

# waypoint_follower_params.yaml
waypoint_follower:
  ros__parameters:
    loop: False  # 航点是否循环执行
    waypoint_timeout: 300.0  # 单个航点导航超时时间(秒)
    stop_on_failure: True  # 某个航点导航失败时停止
    action_server_name: "follow_waypoints"
    # 航点到达阈值
    goal_tolerance_x: 0.5
    goal_tolerance_y: 0.5
    goal_tolerance_yaw: 0.25

3.3 航点配置

sample_waypoints.yaml是预设的GPS航点文件,格式如下:

waypoints:
  - latitude: 37.7749
    longitude: -122.4194
    yaw: 0.0  # 到达后的朝向(弧度)
    frame_id: "wgs84"  # GPS坐标系
  - latitude: 37.7750
    longitude: -122.4195
    yaw: 1.57
    frame_id: "wgs84"
  - latitude: 37.7751
    longitude: -122.4196
    yaw: 3.14
    frame_id: "wgs84"

航点使用WGS84坐标系(标准GPS坐标),也可以配置为UTM坐标系。

3.4 运行流程

  1. 启动仿真/真机驱动:加载机器人模型、传感器驱动、GPS插件
  2. 启动传感器融合:ros2 launch nav2_gps_waypoint_follower_demo dual_ekf.launch.py
  3. 启动导航栈:ros2 launch nav2_gps_waypoint_follower_demo gps_waypoint_follower_launch.py
  4. 加载航点:ros2 run nav2_waypoint_follower waypoint_follower --ros-args -p waypoint_file:=/path/to/sample_waypoints.yaml
  5. 启动航点跟随:通过RViz发送FollowWaypoints action请求,或者用命令行启动:
    ros2 action send_goal /follow_waypoints nav2_msgs/action/FollowWaypoints "{waypoints: []}"
    

3.5 关键注意事项

  1. GPS信号质量:室外场景下需要确保GPS信号良好,RTK定位能达到厘米级精度,普通GPS只有米级精度,可能影响导航效果
  2. 坐标系转换:需要正确配置WGS84到UTM再到机器人本地坐标系的转换参数
  3. 航点规划:航点之间需要有可行路径,避免有障碍物阻挡
  4. 动态障碍物:室外场景需要配置合适的障碍物检测和避障参数
  5. TF树检查:确保map->odom->base_link的TF变换正确发布,这是GPS导航的基础

4. 常用调试技巧

  1. 查看TF树:ros2 run tf2_tools view_frames,检查坐标系变换是否正确
  2. 检查定位质量:ros2 topic echo /gps/fix 查看GPS信号质量,ros2 topic echo /odometry/filtered 查看融合后的定位输出
  3. 可视化调试:在RViz中显示全局/局部代价地图、规划路径、当前目标点等信息
  4. 参数动态调整:使用ros2 param命令动态修改参数,无需重启导航栈
  5. 日志分析:查看/tf, /cmd_vel, /plan等话题的输出,排查导航失败原因

参考资料