1. Nav2概述与核心架构
大家好,我是你们的讲师。今天咱们来聊聊Nav2——这个在ROS2生态里举足轻重的导航框架。
说实话,我第一次接触Nav2的时候,心里是有点犯怵的。毕竟从ROS1的Navigation Stack到ROS2的Nav2,变化确实不小。但用下来我发现,Nav2的设计思路其实更清晰,也更灵活。嗯,咱们慢慢聊。
1.1 Nav2是什么?
Nav2,全称Navigation2,是ROS2官方推荐的导航框架。说白了,它就是一套让机器人从A点走到B点的完整解决方案。
你想想看,一个机器人要自主导航,需要解决哪些问题?
- 定位:我在哪儿?
- 建图:周围环境长什么样?
- 规划:怎么走到目标点?
- 控制:怎么沿着规划路径走?
- 避障:遇到障碍物怎么办?
Nav2把这些功能都打包好了,而且是用插件化的方式组织的。我个人觉得,这是它最聪明的地方——每个模块都可以独立替换,就像乐高积木一样。
核心要点:Nav2不是一个单一的程序,而是一套工具链和框架的集合。它基于ROS2的节点通信机制,把导航任务拆解成多个可独立运行的组件。
1.2 Nav2与ROS1 Navigation Stack的区别
很多从ROS1转过来的朋友会问:Nav2和原来的Navigation Stack到底有啥区别?
我刚开始也困惑过。后来在实际项目中踩过坑,才真正理解了它们的差异。咱们用表格对比一下:
| 对比项 | ROS1 Navigation Stack | Nav2 (ROS2) |
|---|---|---|
| 底层通信 | 基于ROS1的Topic/Service | 基于ROS2的Topic/Service/Action |
| 行为树支持 | 不支持,逻辑硬编码 | 原生支持Behavior Tree |
| 生命周期管理 | 手动管理节点状态 | 内置生命周期节点管理 |
| 插件化程度 | 部分插件化 | 完全插件化架构 |
| 多机器人支持 | 不友好 | 原生支持多机器人命名空间 |
| 参数动态配置 | 需要重启节点 | 支持运行时动态参数调整 |
为什么会这样?其实核心原因在于ROS2本身的设计哲学变了。ROS2引入了DDS作为底层通信,带来了更好的实时性和可靠性。Nav2就是基于这个新底座重新设计的。
我的经验:如果你是从ROS1迁移过来的项目,别想着直接把原来的导航配置搬过来用。Nav2的参数结构和行为树逻辑完全不同。我曾经试过直接复制参数文件,结果机器人原地转圈……嗯,从那以后我都是重新配置的。
1.3 Nav2的核心组件
Nav2的架构可以拆成几个核心组件。咱们一个一个来看:
1.3.1 BT Navigator(行为树导航器)
这是Nav2的大脑。它用行为树(Behavior Tree)来组织导航逻辑。你想想看,传统的导航逻辑是写死在代码里的,想改个流程就得改代码重新编译。但行为树不一样,它把导航拆成一个个小节点,然后用树状结构组合起来。
我个人习惯把行为树理解成流程图。每个节点代表一个动作或条件判断,比如"规划路径"、"执行路径"、"检查是否到达"等等。这些节点通过树状结构组合,就形成了完整的导航逻辑。
# 一个简单的行为树示例(XML格式)
<root main_tree_to_execute="MainTree">
<BehaviorTree ID="MainTree">
<Sequence>
<ComputePathToPose goal="{goal}"/>
<FollowPath path="{path}"/>
</Sequence>
</BehaviorTree>
</root>
1.3.2 Planner(规划器)
规划器负责生成从起点到终点的全局路径。Nav2默认提供了多种规划器插件:
- NavFn:基于Dijkstra或A*算法,适合静态环境
- Smac Planner:支持Hybrid-A*,适合非完整约束的机器人
- Theta* Planner:支持任意角度的路径规划
我在项目中遇到过一个问题:用NavFn规划出来的路径总是贴着墙走,导致机器人容易卡住。后来换成Smac Planner,路径就平滑多了。所以选规划器要结合你的机器人运动模型来考虑。
1.3.3 Controller(控制器)
控制器负责执行规划器生成的路径。它把路径转换成具体的速度指令,让机器人动起来。
Nav2默认的控制器是DWB Controller(Dynamic Window Approach的改进版)。它会实时计算最优的速度组合,让机器人既能跟上路径,又能避开动态障碍物。
注意:控制器的参数调优是个细致活。我曾经因为加速度设得太大,导致机器人急转弯时差点翻车。建议先从保守的参数开始,慢慢调优。
1.3.4 Recovery(恢复行为)
机器人总会遇到意外情况,比如卡住了、迷路了、规划失败等等。Recovery模块就是处理这些异常情况的。
Nav2内置了几种恢复行为:
- Spin:原地旋转,重新获取环境信息
- Backup:后退一段距离,尝试重新规划
- Wait:等待一段时间,再尝试
这些恢复行为也是通过行为树组织的。你可以自定义恢复策略,比如先尝试Spin,不行再Backup,再不行就报错。
1.4 Nav2的架构图
说了这么多,咱们用一张图来总结Nav2的整体架构。这张图是我自己画的,把核心组件和它们之间的关系都标出来了。
从这张图可以看出,Nav2的架构是分层的:
- 顶层:BT Navigator负责整体的导航逻辑编排
- 中间层:Planner、Controller、Recovery各司其职
- 底层:传感器、里程计、执行器提供硬件接口
- 支撑层:地图和定位模块提供环境信息
这种分层设计的好处是:每个模块都可以独立开发和测试。我在实际项目中,经常只替换Planner插件来测试不同规划算法的效果,其他模块完全不用动。
总结一下:Nav2的核心思想就是"插件化 + 行为树"。插件化让每个模块可替换,行为树让导航逻辑可配置。这两点结合起来,让Nav2比ROS1的Navigation Stack灵活得多。
好了,这一章的内容就到这里。Nav2的架构其实不复杂,关键是要理解各个组件之间的协作关系。下一章咱们会深入行为树,看看它到底是怎么工作的。