第2章:Nav2核心架构解析
好,咱们直接切入正题。Nav2这个框架,说白了就是一套让机器人能自己找路、自己走的完整解决方案。我刚开始接触它的时候,第一反应是「这玩意儿怎么这么复杂?」后来拆开一看,其实核心逻辑非常清晰。
今天我就带你把它拆开揉碎,看看里面到底装了些什么。
2.1 Nav2整体框架:一个「大脑」和四个「器官」
Nav2的架构,我习惯把它比作一个机器人导航的「大脑」。这个大脑接收外部指令(比如「去厨房」),然后协调各个器官协同工作。
整体来看,它由以下几个核心部分组成:
- 行为树导航器(BT Navigator):这是大脑的「决策中枢」。它不直接干活,但它决定什么时候该让谁干活。
- 规划器(Planner):负责「想」——从A点到B点,全局路径怎么走。
- 控制器(Controller):负责「做」——沿着规划好的路径,控制机器人实际移动。
- 恢复器(Recovery):负责「救场」——出问题了怎么办?比如卡住了、迷路了。
这四个模块通过ROS2的通信机制(话题、服务、动作)紧密配合。嗯,这里要注意,它们不是各自为战,而是有严格的执行顺序。
核心要点:Nav2不是一个大而全的「单体」程序,而是一组可插拔的模块。你可以替换任何一个模块,只要它遵循相同的接口。我在项目中就曾把默认的DWB控制器换成纯PID控制器,效果还不错。
下面这张图,是我自己画的Nav2核心数据流。你看一眼,心里就有谱了。
2.2 BT Navigator:导航的「总指挥」
BT Navigator是Nav2里最容易被忽视、但最重要的模块。它不直接做路径规划,也不直接控制电机。它的工作是什么?是「决策」。
举个例子:你让机器人去厨房。BT Navigator会先问Planner:「路规划好了吗?」Planner说好了。然后它告诉Controller:「沿着这条路走。」Controller走了一半,发现前面有椅子挡住了。BT Navigator就会触发Recovery:「尝试原地旋转,看看能不能绕过去。」
你看,它就像一个项目经理,协调各个组员干活。
我的经验:很多人觉得BT Navigator只是个「调度器」,随便配配就行。我曾经也这么想,直到有一次机器人在走廊里反复横跳——后来发现是行为树里「重规划」的条件设置得太敏感了。调整一下阈值,问题就解决了。
BT Navigator的核心是行为树(Behavior Tree)。它用XML文件描述导航逻辑。比如:
<root main_tree_to_execute="MainTree">
<BehaviorTree ID="MainTree">
<Sequence>
<ComputePathToPose goal="{goal}" path="{path}" />
<FollowPath path="{path}" controller_id="FollowPath" />
</Sequence>
</BehaviorTree>
</root>
这段代码的意思是:先规划路径,再沿着路径走。简单明了。
2.3 Planner:全局路径的「设计师」
Planner负责生成从起点到终点的全局路径。它用的是全局代价地图(Global Costmap),这张地图包含了障碍物信息。
常见的Planner算法有:
| 算法 | 特点 | 适用场景 |
|---|---|---|
| NavFn | 基于Dijkstra,稳定可靠 | 大多数室内场景 |
| Theta* | 路径更平滑,拐角少 | 需要美观路径的场景 |
| Smac Planner | 支持混合A*,可处理非完整约束 | 差速/阿克曼底盘 |
我个人习惯用NavFn做默认,因为它最稳定。如果你需要更平滑的路径,可以试试Theta*。但要注意,平滑往往意味着计算量更大。
2.4 Controller:局部路径的「执行者」
Planner画好了大方向,Controller负责具体怎么走。它用的是局部代价地图(Local Costmap),实时感知周围环境。
Controller的核心任务是:在跟随全局路径的同时,避开动态障碍物。
常用的Controller有:
- DWB Controller:Nav2默认的控制器,基于动态窗口法(DWA)的改进版。它会在每个控制周期内采样多组速度,选最优的一组。
- MPPI Controller:基于模型预测控制(MPC),效果更好,但计算量也更大。
- Regulated Pure Pursuit:纯追踪算法的改进版,适合低速场景。
注意:Controller的参数调优是Nav2里最磨人的环节。我曾经在一个项目里,为了调好DWB的「最大线速度」和「最大角速度」,整整花了两天。建议你从保守的参数开始,慢慢放开。
2.5 Recovery:导航的「救火队」
Recovery模块负责处理异常情况。导航不可能永远一帆风顺,总会有意外。
常见的恢复行为包括:
- 原地旋转:清除局部代价地图中的「假障碍物」(比如传感器噪声导致的误检测)。
- 后退:如果前方被堵死,尝试后退一段距离。
- 重规划:放弃当前路径,重新规划一条新路径。
- 等待:如果障碍物是动态的(比如行人),等它离开。
这些恢复行为也是通过行为树组织的。你可以自定义恢复策略,比如「先旋转三次,不行就后退,再不行就原地等待并报警」。
2.6 数据流与通信机制
Nav2各模块之间怎么通信?全靠ROS2的三大件:话题(Topic)、服务(Service)、动作(Action)。
我简单梳理一下:
- 话题(Topic):用于持续的数据流。比如传感器数据(/scan)、里程计(/odom)、速度指令(/cmd_vel)。
- 服务(Service):用于一次性的请求-响应。比如加载地图、获取代价地图信息。
- 动作(Action):用于需要持续反馈的任务。比如导航到某个点(/navigate_to_pose),它会返回当前状态、反馈和最终结果。
举个例子,当你通过RVIZ点击「导航到某点」时,流程是这样的:
- RVIZ通过动作客户端发送
/navigate_to_pose请求给BT Navigator。 - BT Navigator收到后,通过动作调用Planner的
/compute_path_to_pose服务。 - Planner返回路径后,BT Navigator再通过动作调用Controller的
/follow_path服务。 - Controller开始控制机器人移动,同时通过话题发布
/cmd_vel速度指令。 - 如果Controller遇到问题,BT Navigator会触发Recovery模块。
你看,整个流程清晰得像流水线一样。
避坑指南:我曾经遇到过一个问题:机器人导航到一半突然停了,没有任何报错。排查了半天,发现是动作超时时间设置得太短。Planner计算路径稍微慢了一点,BT Navigator就认为它「死掉了」。所以,记得检查动作的超时参数。
好了,这一章的内容就到这里。Nav2的核心架构其实不复杂,关键是要理解各个模块的职责和它们之间的协作关系。下一章我们会深入行为树,看看怎么自定义导航逻辑。