nav2_bringup — 系统启动包深度解读

一句话:Nav2 的"总电源开关",自身零算法代码,只有 launch 文件和配置文件,负责把所有节点按正确顺序、正确配置拉起来。


1. 文件结构总览

nav2_bringup/
├── CMakeLists.txt               ← 只做安装,不编译任何代码
├── package.xml                  ← 依赖声明
├── launch/                      ← 11个launch文件(核心)
│   ├── bringup_launch.py        ← 总入口★
│   ├── navigation_launch.py     ← 导航10节点★
│   ├── localization_launch.py   ← 定位2节点★
│   ├── slam_launch.py           ← SLAM模式★
│   ├── rviz_launch.py           ← 可视化
│   ├── tb3_simulation_launch.py ← TurtleBot3 Gazebo仿真
│   ├── tb4_simulation_launch.py ← TurtleBot4 Gazebo仿真
│   ├── tb3_loopback_simulation.launch.py  ← TB3 轻量仿真
│   ├── tb4_loopback_simulation.launch.py  ← TB4 轻量仿真
│   ├── cloned_multi_tb3_simulation_launch.py  ← 多机器人(克隆)
│   └── unique_multi_tb3_simulation_launch.py  ← 多机器人(唯一命名空间)
├── params/                      ← 参数配置(核心)
│   ├── nav2_params.yaml         ← 全栈默认参数(470行)★
│   ├── nav2_multirobot_params_1.yaml  ← 多机器人实例1
│   ├── nav2_multirobot_params_2.yaml  ← 多机器人实例2
│   └── nav2_multirobot_params_all.yaml ← 多机器人共享参数
├── maps/                        ← 内置测试地图
│   ├── tb3_sandbox.pgm/.yaml    ← TurtleBot3 沙盒地图
│   ├── depot.pgm/.yaml          ← 仓库地图
│   └── warehouse.pgm/.yaml      ← 大型仓库地图
└── rviz/                        ← RViz配置文件
    ├── nav2_default_view.rviz   ← 单机默认视图
    └── nav2_namespaced_view.rviz ← 多机命名空间视图

2. CMakeLists.txt 解读

find_package(ament_cmake REQUIRED)
find_package(nav2_common REQUIRED)    ← 引入 nav2_package() 宏
find_package(navigation2 REQUIRED)   ← 确保 Nav2 全栈已安装

nav2_package()                        ← nav2_common 提供的宏,设置编译标准等

# 四个目录全部安装到 share/nav2_bringup/
install(DIRECTORY launch  DESTINATION share/${PROJECT_NAME})
install(DIRECTORY maps    DESTINATION share/${PROJECT_NAME})
install(DIRECTORY rviz    DESTINATION share/${PROJECT_NAME})
install(DIRECTORY params  DESTINATION share/${PROJECT_NAME})

关键点:没有 add_library / add_executable,纯粹只是把文件夹复制到安装目录。
安装后路径:/opt/ros/jazzy/share/nav2_bringup/launch/bringup_launch.py 等。


3. launch 文件体系

3.1 总入口:bringup_launch.py

这是用户最常用的入口,内部做三路分支:

ros2 launch nav2_bringup bringup_launch.py [参数...]
                │
                ▼
        ┌───────────────────────────────────────────────────┐
        │           bringup_launch.py                        │
        │                                                     │
        │  ① 启动 nav2_container(仅 use_composition=True)  │
        │                                                     │
        │  ② 定位分支(三选一,由 slam + use_localization 决定)│
        │     ├─ slam=True  → slam_launch.py                 │
        │     ├─ slam=False → localization_launch.py         │
        │     └─ use_localization=False → 跳过(纯导航)      │
        │                                                     │
        │  ③ 始终执行 navigation_launch.py                    │
        └───────────────────────────────────────────────────┘
所有可配置参数(带默认值)
参数名默认值含义
namespace''机器人命名空间(多机器人用)
use_namespacefalse是否启用命名空间
slamFalse是否使用 SLAM 建图(vs 已有地图定位)
map''地图文件路径(localization模式用)
use_localizationTrue是否启用定位子系统
use_sim_timefalse是否使用仿真时钟(Gazebo需设True)
params_filenav2_params.yaml参数文件路径
autostarttrue启动后自动执行生命周期 startup
use_compositionTrue是否用 Component Container(进程内通信)
use_respawnFalse节点崩溃后是否自动重启(非 composition 模式)
log_levelinfo日志级别(debug/info/warn/error)
多机器人命名空间替换机制
# 用户在 nav2_multirobot_params.yaml 里写占位符:
#   <robot_namespace>/amcl
#
# launch 时自动替换:
params_file = ReplaceString(
    source_file=params_file,
    replacements={'<robot_namespace>': ('/', namespace)},
    condition=IfCondition(use_namespace),
)
# 结果:/robot1/amcl(当 namespace='robot1' 时)

3.2 navigation_launch.py — 导航10节点

启动整个导航核心,有两种部署模式

模式A:独立进程模式(use_composition=False)
每个节点 = 独立的 Linux 进程
节点间通信 = 走 DDS 网络(序列化/反序列化)
优点:隔离性好,一个崩溃不影响其他
缺点:通信有序列化开销,数据需要拷贝

启动的10个节点:

节点名                   包                        功能
─────────────────────────────────────────────────────────────────
controller_server        nav2_controller           局部控制服务器
smoother_server          nav2_smoother             路径平滑服务器
planner_server           nav2_planner              全局规划服务器
route_server             nav2_route                拓扑路网路由服务器
behavior_server          nav2_behaviors            恢复行为服务器
bt_navigator             nav2_bt_navigator         行为树导航调度器
waypoint_follower        nav2_waypoint_follower    多航点导航
velocity_smoother        nav2_velocity_smoother    速度指令平滑
collision_monitor        nav2_collision_monitor    安全守护
docking_server           opennav_docking           自动对接充电桩
──────────────────────────────────────────────────────────────────
lifecycle_manager_navigation  nav2_lifecycle_manager  管理以上10个节点
模式B:组合节点模式(use_composition=True)
所有节点 = 加载到同一个 component_container_isolated 进程
节点间通信 = 直接函数调用(零拷贝)
优点:性能更高,延迟更低(对实时控制有意义)
缺点:一个崩溃可能带崩整个容器

启动流程:
  bringup_launch.py 先创建容器节点 nav2_container
              ↓
  navigation_launch.py 用 LoadComposableNodes 把10个节点加载进去

ComposableNode 写法示例:

ComposableNode(
    package='nav2_controller',
    plugin='nav2_controller::ControllerServer',  # ← C++类名
    name='controller_server',
    parameters=[configured_params],
)
# vs 独立进程写法:
Node(
    package='nav2_controller',
    executable='controller_server',              # ← 可执行文件名
    name='controller_server',
)
cmd_vel 重映射
remappings=remappings + [('cmd_vel', 'cmd_vel_nav')]

controller_serverbehavior_servervelocity_smoother 都把 cmd_vel 重映射到 cmd_vel_nav,原因:

cmd_vel_nav  ← controller/behavior 输出的"原始"速度
     ↓
velocity_smoother  (加速度限幅)
     ↓
cmd_vel_smoothed
     ↓
collision_monitor  (最后防线,必要时减速/急停)
     ↓
cmd_vel            ← 机器人实际执行

3.3 localization_launch.py — 定位2节点

启动节点:
  map_server   ← 加载静态地图
  amcl         ← 粒子滤波定位,广播 map→odom TF
  lifecycle_manager_localization  ← 管理以上2个节点

map_server 的条件启动:
  map 参数为空 → 用 yaml 里配置的地图路径
  map 参数非空 → 用命令行传入的地图路径(覆盖 yaml)

为什么定位单独一个 lifecycle_manager?

lifecycle_manager_localization  管理:map_server + amcl
lifecycle_manager_navigation    管理:controller + planner + ... (10个)

独立的好处:
  AMCL 崩了 → 只重启定位子系统,不影响导航节点
  导航节点崩了 → 不影响 AMCL 继续定位
  可以单独 pause/resume 定位(换地图时)

3.4 slam_launch.py — SLAM建图模式

启动节点:
  slam_toolbox (online_sync_launch.py)  ← 外部包,实时同步SLAM
  map_saver_server                       ← 随时保存当前地图
  lifecycle_manager_slam                 ← 管理 map_saver

特殊逻辑:
  检测 params_file 里是否有 slam_toolbox 段落(HasNodeParams)
  有 → 把 params_file 传给 slam_toolbox
  没有 → slam_toolbox 用自己的默认参数(避免传空yaml报错)

4. nav2_params.yaml 解读(470行默认参数)

这是整个 Nav2 的"出厂设置",每个节点的参数都在这里集中配置。

4.1 文件结构

amcl:                    ← AMCL定位参数
  ros__parameters:
    ...

bt_navigator:            ← 行为树导航参数
  ros__parameters:
    ...

controller_server:       ← 控制服务器 + MPPI参数
  ros__parameters:
    controller_frequency: 20.0
    FollowPath:
      plugin: "nav2_mppi_controller::MPPIController"
      ...

local_costmap:           ← 局部代价地图(3m×3m滚动窗口)
  ...

global_costmap:          ← 全局代价地图(整张地图)
  ...

planner_server:          ← 规划服务器(默认用 NavFn,不是 Hybrid-A*!)
  ...

smoother_server:         ← 平滑服务器
behavior_server:         ← 恢复行为
waypoint_follower:       ← 多航点导航
route_server:            ← 拓扑路网
velocity_smoother:       ← 速度平滑
collision_monitor:       ← 碰撞监控
docking_server:          ← 对接充电桩
loopback_simulator:      ← 轻量仿真器

4.2 重要默认值速查

参数默认值注意
控制器MPPIController20Hz
规划器NavfnPlanner(Dijkstra)不是 Hybrid-A*,需手动换
平滑器SimpleSmoother不是 ConstrainedSmoother
机器人半径0.22mTurtleBot3 的半径,实际使用要改
膨胀半径0.7mlocal/global costmap 都是 0.7m
MPPI batch_size2000(比之前分析的1000更多)
MPPI time_steps56 步 × 0.05s = 2.8s预测时域
AMCL 粒子数500~2000KLD 自适应
目标容差xy=0.25m, yaw=0.25rad判断"到达目标"

4.3 cmd_vel 完整流水线(从参数看)

collision_monitor:
  cmd_vel_in_topic:  "cmd_vel_smoothed"   ← 从 velocity_smoother 接收
  cmd_vel_out_topic: "cmd_vel"            ← 输出给机器人底盘

完整链路:

controller_server → cmd_vel_nav
behavior_server   → cmd_vel_nav
                        ↓
              velocity_smoother(订阅 cmd_vel_nav,发布 cmd_vel_smoothed)
                        ↓
              collision_monitor(订阅 cmd_vel_smoothed,发布 cmd_vel)
                        ↓
                    机器人底盘

5. 地图文件格式解读

tb3_sandbox.yaml 为例:

image: tb3_sandbox.pgm     ← 对应的图像文件(灰度图)
resolution: 0.050000       ← 每像素=0.05m,即5cm分辨率
origin: [-10.0, -10.0, 0.0] ← 地图左下角在世界坐标系中的位置
negate: 0                  ← 0=白色是自由空间(正常),1=反转
occupied_thresh: 0.65      ← 像素值换算的占用概率>0.65 → 障碍
free_thresh: 0.196         ← 占用概率<0.196 → 自由空间
                           ← 0.196~0.65之间 → 未知

pgm 图像编码规则:

像素值 255(白)→ 占用概率 ≈ 0   → 自由空间(FREE)
像素值 0  (黑)→ 占用概率 ≈ 1   → 障碍(LETHAL)
像素值 205(灰)→ 占用概率 ≈ 0.2 → 未知(UNKNOWN)

6. package.xml 关键依赖

<build_depend>nav2_common</build_depend>    ← 提供 nav2_package() CMake宏
<build_depend>navigation2</build_depend>    ← 编译时确保全栈可用
<exec_depend>slam_toolbox</exec_depend>     ← SLAM模式需要
<exec_depend>ros_gz_sim</exec_depend>       ← Gazebo仿真需要
<exec_depend>nav2_minimal_tb3_sim</exec_depend>  ← TB3仿真模型
<exec_depend>nav2_minimal_tb4_sim</exec_depend>  ← TB4仿真模型

注意:nav2_bringup少数几个依赖 navigation2(meta包) 的包之一,因为它需要在编译时确认整个 Nav2 栈都存在。


7. 一图总结 nav2_bringup 的作用

用户输入:ros2 launch nav2_bringup bringup_launch.py map:=my_map.yaml
                              │
                  bringup_launch.py(总调度)
                  │           │            │
                  ▼           ▼            ▼
         slam=False       (条件)      navigation_launch.py
         use_loc=True      不启动            │
                  │         SLAM            │ 启动10个导航节点
                  ▼                         │ + lifecycle_manager
         localization_launch.py             │
              │                             │
              ├── map_server                ▼
              ├── amcl            controller_server(MPPI)
              └── lifecycle_manager_localization   planner_server(NavFn)
                                   bt_navigator
                                   behavior_server
                                   velocity_smoother
                                   collision_monitor
                                   ...

         全部读取 nav2_params.yaml 作为参数来源
         全部输出日志到 screen

8. 一句话总结

nav2_bringup 是 Nav2 的"一键启动脚本包":11个 launch 文件按不同场景组合启动节点,1个 470 行的 nav2_params.yaml 集中管理所有默认参数,3张测试地图开箱即用。自身零算法代码,全是"胶水"。

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐