侧边栏壁纸
  • 累计撰写 18 篇文章
  • 累计创建 9 个标签
  • 累计收到 3 条评论

目 录CONTENT

文章目录

ROS2_Nav2导航栈解析

王富贵
2026-04-21 / 0 评论 / 0 点赞 / 15 阅读 / 0 字

ROS2 移动机器人导航架构深度指南:SLAM 与 Nav2 协作详解

1. 核心概念澄清:谁负责什么?

在 ROS2 导航体系中,必须将“感知(Perception)”与“决策(Decision)”彻底解耦。

模块层级核心问题代表组件职责描述
感知层 (Perception)“我在哪?周围有什么?”SLAM Engine
(Cartographer / slam_toolbox)
1. 建图:将激光雷达数据转化为栅格地图。
2. 定位:计算机器人在地图中的精确坐标 $(x, y, \theta)$。
3. 输出:发布 /map 话题和 map->odom 的 TF 变换。
决策层 (Planning)“怎么去?怎么避障?”Nav2 Stack
(Global/Local Planner)
1. 全局规划:基于地图计算起点到终点的最优路径。
2. 局部规划:实时控制速度并避开动态障碍物。
3. 输出:发布 /cmd_vel 速度指令给底盘。

关键点:SLAM 引擎不包含任何路径规划算法。它只是 Nav2 的“眼睛”和“GPS”。无论底层使用哪种 SLAM,上层的 Nav2 规划器(A*, DWA, TEB 等)都是通用的。


2. 通用数据流向图 (Mermaid - 终极修复版)

以下流程图展示了数据如何在各个节点间流动。此图已针对 Mermaid 11+ 版本进行了极致优化

  • 全中文描述:节点内清晰标注了“输入”、“输出”及“核心职责”。
  • 无 Emoji/无 HTML:彻底移除了导致渲染失败的 Emoji 和 <br/> 标签。
  • 稳健语法:使用纯英文 ID 配合双引号中文标签,确保在任何编辑器中都能完美渲染。
graph TD
    %% 定义样式类
    classDef sensor fill:#e1f5fe,stroke:#01579b,stroke-width:2px;
    classDef slam fill:#fff9c4,stroke:#fbc02d,stroke-width:2px;
    classDef nav2 fill:#e8f5e9,stroke:#2e7d32,stroke-width:2px;
    classDef base fill:#fce4ec,stroke:#880e4f,stroke-width:2px;
    classDef note fill:#ffffff,stroke:#666,stroke-dasharray: 5 5,stroke-width:1px;

    subgraph Hardware_Layer ["硬件层: 数据采集"]
        direction TB
        Lidar["激光雷达 LiDAR"]:::sensor
        Odom["里程计/IMU"]:::sensor
        Base["电机底盘 Base"]:::base
        
        Note_Lidar["职责: 探测障碍物距离与角度
输出: LaserScan 点云数据"]:::note --- Lidar
        Note_Odom["职责: 估算机器人短时位移
输出: Odometry 里程计信息"]:::note --- Odom
    end

    subgraph Perception_Layer ["感知层: SLAM 引擎"]
        direction TB
        SLAM_Node{"SLAM 核心节点
(Cartographer 或 slam_toolbox)"}:::slam
        
        Lidar -->|"LaserScan 话题"| SLAM_Node
        Odom -->|"Odometry 话题"| SLAM_Node
        
        SLAM_Node -->|"OccupancyGrid 话题"| Map_Publisher["地图发布器
(实时栅格地图)"]:::slam
        SLAM_Node -->|"TF: map->odom"| TF_Broadcaster["TF 坐标变换广播器
(机器人全局位姿)"]:::slam
        
        Note_SLAM["核心职责:
1. 匹配激光帧构建地图
2. 闭环检测消除累积误差
3. 输出机器人全局位姿"]:::note --- SLAM_Node
    end

    subgraph Decision_Layer ["决策层: Nav2 导航栈"]
        direction TB
        Nav2_Core["Nav2 核心控制器
(Behavior Tree)"]:::nav2
        
        Map_Publisher -->|"/map 静态或动态地图"| Nav2_Core
        TF_Broadcaster -->|"TF Tree 坐标树"| Nav2_Core
        
        subgraph Planners ["规划器集群"]
            Global_Planner["全局规划器
(A* / Dijkstra / Theta*)"]:::nav2
            Local_Planner["局部规划器
(DWA / TEB / MPPI)"]:::nav2
        end
        
        Nav2_Core -->|"请求路径"| Global_Planner
        Global_Planner -->|"返回全局路径 Path"| Local_Planner
        Local_Planner -->|"返回速度指令 cmd_vel"| Base
        
        Note_Nav2["核心职责:
1. 订阅地图与位姿
2. 计算无碰撞最优路径
3. 控制底盘运动"]:::note --- Nav2_Core
    end

    %% 跨层连接:激光雷达数据也直接用于局部避障
    Lidar -.->|"用于实时避障"| Local_Planner

3. 细致工作流程对比

虽然架构图相同,但 Cartographerslam_toolbox 在实际运行时的“工作流”有显著差异。

方案 A:Cartographer (经典离线建图模式)

这是工业界最常用的“高精度静态地图”方案。流程分为两个独立阶段:建图期导航期

阶段 1:建图期 (Mapping Phase)

  1. 启动:运行 cartographer_node + cartographer_occupancy_grid_node
  2. 数据采集:机器人被遥控或自动行走,SLAM 实时构建子图(Submaps)。
  3. 闭环检测:当机器人回到已探索区域,Cartographer 执行后端优化,消除累积误差。
  4. 保存:调用服务 /finish_trajectory,将地图保存为 .pbstream 文件。
  5. 转换:使用工具将 .pbstream 转换为标准的 .pgm (图片) 和 .yaml (配置) 文件。
  6. 退出关闭 Cartographer 节点。此时建图完成。

阶段 2:导航期 (Navigation Phase)

  1. 启动地图服务:运行 nav2_map_server,加载上一步生成的 .pgm/.yaml 静态地图。
  2. 启动定位:运行 amcl (Adaptive Monte Carlo Localization)。AMCL 通过粒子滤波,根据激光雷达匹配静态地图,估算机器人位置。
  3. 启动 Nav2:运行 Nav2 栈,订阅 /map 和 AMCL 发布的 TF。
  4. 执行导航:Nav2 规划路径,发送速度指令。
  5. 注意:在此阶段,Cartographer 不参与工作。如果环境发生变化(如多了个箱子),AMCL 可能会定位失败,因为地图是静态的。

方案 B:slam_toolbox (在线终身建图模式)

这是 ROS2 社区推荐的“动态适应”方案。建图和导航同时进行,没有明显的阶段划分。

持续运行期 (Continuous Operation)

  1. 启动:运行 sync_slam_toolbox_node (或 async 版本)。
  2. 初始化
    • 如果是第一次:创建新地图。
    • 如果是后续启动:加载之前的 .posegraph 文件(包含历史地图和关键帧记忆)。
  3. 实时建图与定位
    • SLAM 节点每收到一帧激光雷达数据,就进行一次扫描匹配(Scan Matching)。
    • 更新地图:如果发现新障碍物,直接更新 /map 话题。
    • 修正定位:如果检测到闭环(Loop Closure),后台线程会优化整个轨迹,并修正 map->odom 的 TF。
  4. 启动 Nav2:Nav2 订阅由 slam_toolbox 实时发布的 /map 和 TF。
  5. 执行导航
    • Nav2 的全局规划器会根据实时更新的地图重新规划路径。
    • 例如:如果 slam_toolbox 发现前方多了一堵墙,它会立即更新地图,Nav2 随即重新计算绕路路径。
  6. 保存记忆:关机前,调用服务 /save_map,将最新的地图和轨迹保存为 .posegraph.yaml。下次启动时直接加载,实现“终身学习”。

4. 为什么你会觉得 “slam_toolbox 集成了导航”?

这是一个非常直观的错觉,原因如下:

  1. 一站式启动

    • Cartographer 方案:你需要分别启动 map_serveramclnav2_bringup。配置文件分散,逻辑割裂。
    • slam_toolbox 方案:你只需要启动 slam_toolboxnav2_bringup。slam_toolbox 一人包办了“地图服务器”和“定位器”的工作。
  2. 动态适应性

    • 在 Cartographer+AMCL 模式下,如果环境变了,你必须重新建图,否则导航会失败。
    • 在 slam_toolbox 模式下,环境变了,它自己会改地图,导航继续正常工作。这种“无感”的体验让你觉得它更像是一个完整的导航系统。
  3. 官方背书

    • Nav2 官方文档中,slam_toolbox 是作为“标准 SLAM 插件”推荐的,提供了现成的 Launch 文件(navigation_launch.py + slam_toolbox_launch.py),几乎零配置即可运行。

5. 总结与建议

维度Cartographer (离线+AMCL)slam_toolbox (在线)
工作流建图 -> 保存 -> 关闭 -> 加载静态地图 -> 导航启动 -> 边建图/定位边导航 -> 保存记忆
环境变化不支持(需重新建图)✅ 支持(实时更新地图)
配置难度⭐⭐ (高,需调优多个节点)⭐ (低,官方集成好)
资源占用导航时极低 (仅跑 AMCL)导航时较高 (SLAM 持续运行)
适用场景大型仓库、结构固定、算力有限家庭、办公室、环境动态变化、快速原型

🚀 最终建议

对于大多数现代移动机器人项目,尤其是基于 ROS2 Humble/Jazzy 的开发,强烈推荐使用 slam_toolbox + Nav2 的组合

  • 理由:它的“终身学习”能力(适应环境变化)比静态地图更有价值,且配置极其简单,能让你把精力集中在业务逻辑而非底层调试上。
  • 何时选 Cartographer:只有当你的环境极大(如超过 1000 平米)、结构极度规则(如长走廊仓库),且对定位精度有毫米级要求时,才考虑 Cartographer 的离线建图方案。

附录:常用命令速查

  • 启动 slam_toolbox 在线建图
    ros2 launch slam_toolbox online_async_launch.py
    
  • 保存 slam_toolbox 地图
    ros2 service call /slam_toolbox/save_map slam_toolbox/srv/SaveMap "{name: {data: '/path/to/map'}}"
    
  • 启动 Nav2 (带 slam_toolbox)
    ros2 launch nav2_bringup navigation_launch.py use_slam:=True
    
0

评论区