BotOf TechAI / IoT / Full-Stack / 植物养护
返回首页ROS 2 导航系统 Nav2 实战:从定位、代价地图到规划控制

ROS 2 导航系统 Nav2 实战:从定位、代价地图到规划控制

·6 分钟阅读·

Nav2 最容易被误解成“ROS 2 里的路径规划器”。实际上,它更像一个移动机器人导航操作系统:接收目标、管理行为树、调用全局规划、局部控制、代价地图、定位、恢复行为、速度平滑和任务服务器。

如果只把 Nav2 当成一个 A* + DWA 插件,很快会在真实机器人上遇到这些问题:

  • 地图有了,但机器人不知道自己在哪;
  • 路径能生成,但底盘不跟;
  • 局部避障不断触发恢复;
  • RViz 里 TF 树飘来飘去;
  • 仿真正常,实物在门口抖动;
  • 一换发行版,cmd_vel 消息类型和参数默认值变了。

这篇文章按工程落地的顺序拆 Nav2,而不是按文档目录逐项解释。

一、Nav2 的本质:行为树调度的导航系统

Nav2 的官方介绍里,它提供 perception、planning、control、localization、visualization、behaviors 等能力,并用 Behavior Tree 执行复杂机器人行为。官方 Concepts 文档也把它拆成 Behavior Trees、Navigation Servers、State Estimation、Environmental Representation 等部分。 [¹]

一条典型数据流如下:

可以把 Nav2 分成 6 层:

关键模块作用
任务层bt_navigator、waypoint follower、route server决定如何完成导航任务
全局规划planner_server从当前位置到目标点生成全局路径
路径处理smoother_server让全局路径更平滑、更可执行
局部控制controller_server根据局部代价地图和路径输出速度
环境表示global/local costmap把地图、传感器、禁行区、膨胀层变成可规划代价
状态估计AMCL / SLAM / robot_localization / TF提供机器人位姿和速度

如果一个机器人“看起来 Nav2 不工作”,先问它坏在哪一层,而不是盲目调 planner 参数。

二、先把 TF 和状态估计做对

Nav2 依赖一条稳定 TF 链:

map -> odom -> base_link -> sensor frames

这三个 frame 的职责不同:

frame谁发布含义
mapAMCL / SLAM / 全局定位全局地图坐标
odom里程计 / EKF连续但会漂移的局部坐标
base_linkrobot_state_publisher / 控制器机器人本体

常见做法:

  • 已有静态地图map_server + AMCL,用激光匹配地图;
  • 边建图边导航slam_toolbox 或其它 SLAM;
  • 户外/GPSrobot_localization 融合 wheel odom、IMU、GPS;
  • 视觉/深度方案:VIO / VSLAM 补充轮速里程计。

真实机器人最常见的失败不是算法差,而是 TF 时间、坐标轴、传感器外参错:

ros2 run tf2_tools view_frames
ros2 topic hz /tf
ros2 topic echo /odom
ros2 topic echo /scan
ros2 run tf2_ros tf2_echo map base_link

调 Nav2 前先确认:

  • /scan 或点云在 RViz 里和机器人方向一致;
  • 机器人前进时 /odom 的 x 正方向增加;
  • 机器人转动时 yaw 符号符合右手系;
  • base_link 到激光雷达的 static transform 准确;
  • 所有节点使用同一时间源,仿真时 /clock 一致。

三、Costmap 是 Nav2 的工程核心

Nav2 的 planner 和 controller 不是直接看传感器,而是看 costmap。costmap 把环境分成可走、障碍、膨胀、未知、禁行、限速等代价。

典型配置:

global_costmap:
  global_costmap:
    ros__parameters:
      global_frame: map
      robot_base_frame: base_link
      resolution: 0.05
      track_unknown_space: true
      plugins: ["static_layer", "obstacle_layer", "inflation_layer"]

local_costmap:
  local_costmap:
    ros__parameters:
      global_frame: odom
      robot_base_frame: base_link
      rolling_window: true
      width: 4.0
      height: 4.0
      resolution: 0.05
      plugins: ["obstacle_layer", "inflation_layer"]

global costmap 更多用于全局规划,local costmap 更多用于局部避障。两者可以共用传感器,也可以分层配置。

调 costmap 的关键变量:

参数影响经验
robot_radius / footprint机器人是否能过窄门真实尺寸加安全余量
inflation_radius离障碍多远开始变贵过大绕远,过小贴边
cost_scaling_factor障碍代价衰减影响贴边程度
observation_sources哪些传感器进障碍层先少后多,逐个验证
clearing / marking障碍清除和标记动态障碍场景必调
update_frequency更新频率低了避障慢,高了吃 CPU

典型调试方法:

  1. RViz 只看 local costmap;
  2. 推机器人走一圈,看障碍是否稳定;
  3. 用纸箱/人腿做动态障碍,看是否及时 mark/clear;
  4. 关闭 planner,只让 controller 跟简单路径;
  5. 最后再加 keepout zone、speed filter、语义层。

四、Planner Server:选对全局规划器

Nav2 的 Planner Server 托管一个或多个 planner 插件。不同机器人运动模型不同,规划器不应该乱选。

机器人推荐起步说明
差速/全向,室内 AMRNavFn / Smac 2D简单稳定,先跑通
Ackermann / 车式底盘Smac Hybrid-A*考虑最小转弯半径
大车、需要倒车/曲率约束Smac State Lattice / Hybrid-A*路径更可执行
走图网络/园区道路Route Server基于导航图,不是纯 freespace

官方 Smac Planner 文档说明,nav2_smac_planner 包提供优化过的 A* 框架,包括 2D A*、Hybrid-A* 和 State Lattice 三类规划器,面向不同机器人平台。 [²]

如果你的机器人是差速小车,先不要上复杂规划器。先用 2D planner 跑通,再根据路径质量和运动约束升级。复杂规划器会带来更多参数:转弯半径、角度离散、解析扩展、启发函数、平滑策略。

五、Controller Server:局部跟踪才是“能不能走好”

Controller Server 是 Nav2 里最靠近底盘的一层。官方文档说明它接收路径和插件名称,调用 controller、progress checker、goal checker,并持有 local costmap。 [³]

常见 controller:

Controller适合特点
DWB差速/全向小车ROS1 DWA 思路延续,参数多,可解释
Regulated Pure Pursuit差速、Ackermann、小车简洁、稳定、适合多数室内机器人
MPPI高动态/复杂约束采样优化,算力需求更高
Rotation Shim + primary controller需要先转向再跟踪对差速机器人很实用

局部控制常见症状:

症状多半原因
机器人原地抖速度阈值、角速度采样、goal checker 太紧
贴障碍太近inflation 半径/代价衰减不合适
路径看着对但不走controller 没收到有效 path 或 TF 超时
一直 recoveryprogress checker 判定失败
到点后转来转去yaw tolerance 太小或定位抖动

调 controller 的顺序:

  1. 降低最大速度;
  2. 放宽 goal tolerance;
  3. 确认 local costmap 稳定;
  4. 确认 odom 没明显延迟;
  5. 再调 planner 和 smoother。

不要一上来改 50 个参数。每次只改一类参数,并保存 rosbag。

六、Smoother 和 Velocity Smoother:不要混在一起

Nav2 里有两个“平滑”概念:

模块平滑对象位置
Smoother Server全局路径planner 之后、controller 之前
Velocity Smoother速度命令controller 之后、底盘控制器之前

路径平滑让全局路径更适合机器人执行。Nav2 Simple Smoother / Constrained Smoother 是这里的典型插件。

速度平滑处理的是 cmd_vel。官方 velocity smoother 文档强调,它用于降低加速度和 jerk,减少对电机和硬件控制器的冲击,也能插值到更高频率发布速度命令。 [⁴]

真实机器人推荐打开 velocity smoother,特别是:

  • 电机速度环比较硬;
  • 轮子打滑;
  • 局部控制器输出跳变;
  • 低速时有 deadband;
  • 底盘控制器频率高于 Nav2 controller server。

七、行为树:Nav2 的任务编排层

Nav2 默认不是简单的“规划一次、跟随一次”。它用 Behavior Tree 做编排:

行为树让你能插入:

  • 重规划频率;
  • 路径截断;
  • planner/controller 切换;
  • costmap 清理;
  • dock / undock;
  • keepout / speed zone;
  • 任务级失败策略。

但初期不要急着改 BT XML。先用默认树跑通,再把恢复行为、重规划周期、路径平滑节点按需求加入。

八、真实机器人上线顺序

1. 单独验证底盘

先确认 ros2_control 能手动控制底盘:

ros2 topic pub /cmd_vel geometry_msgs/msg/TwistStamped ...
ros2 topic echo /odom
ros2 run tf2_tools view_frames

底盘不能稳定响应时,不要调 Nav2。

2. 单独验证定位

静止时:

  • map -> base_link 不应明显跳动;
  • 激光和地图重合;
  • AMCL 粒子云收敛。

移动时:

  • odom -> base_link 连续;
  • map -> odom 可以缓慢校正,但不应剧烈跳;
  • 轮速里程计和激光/视觉定位差距可解释。

3. 单独验证 costmap

目标:

  • 障碍能进入 local costmap;
  • 障碍移开后能清除;
  • 机器人 footprint 不穿墙;
  • 未知区域策略符合场景。

4. 跑短距离目标

先在 1–2 米内低速测试:

  • 直线到点;
  • 原地转向;
  • 绕小障碍;
  • 窄门;
  • 人突然走近;
  • 目标取消。

5. 长距离、多目标、异常恢复

最后再测:

  • waypoint following;
  • 自动重规划;
  • 电梯口/窄通道;
  • 低电量回充;
  • 网络延迟;
  • 传感器丢帧;
  • 急停恢复。

九、一个可执行的参数基线

室内差速 AMR 起步可以保守一点:

controller_server:
  ros__parameters:
    controller_frequency: 20.0
    min_x_velocity_threshold: 0.001
    min_theta_velocity_threshold: 0.001
    progress_checker_plugins: ["progress_checker"]
    goal_checker_plugins: ["goal_checker"]
    controller_plugins: ["FollowPath"]

    progress_checker:
      plugin: "nav2_controller::SimpleProgressChecker"
      required_movement_radius: 0.3
      movement_time_allowance: 10.0

    goal_checker:
      plugin: "nav2_controller::SimpleGoalChecker"
      xy_goal_tolerance: 0.20
      yaw_goal_tolerance: 0.30
      stateful: True

velocity_smoother:
  ros__parameters:
    smoothing_frequency: 40.0
    max_velocity: [0.35, 0.0, 0.8]
    min_velocity: [-0.10, 0.0, -0.8]
    max_accel: [0.5, 0.0, 1.2]
    max_decel: [-0.6, 0.0, -1.4]
    velocity_timeout: 1.0

这不是最优值,只是安全起点。上线前必须按机器人质量、轮径、地面摩擦、传感器延迟重新标定。

十、排障清单

问题先看什么
点目标没反应bt_navigator、action server、lifecycle 状态
有全局路径但不动controller server、local costmap、cmd_vel
cmd_vel 有但底盘不动velocity smoother、ros2_control、硬件接口
机器人走偏odom、轮径、轮距、IMU yaw
遇障碍不避让local costmap observation source
一直清 costmaprecovery 条件、progress checker
定位突然跳AMCL 参数、地图质量、TF 时间戳
窄门过不去footprint、inflation、controller 速度
到目标前停住goal checker、minimum velocity、deadband
仿真正常实物失败传感器延迟、底盘限幅、地面摩擦

结论:Nav2 的难点不在“能不能跑 demo”,而在系统边界。定位、costmap、planner、controller、velocity smoother、ros2_control 每层都要能单独验证。只有这样,机器人在真实环境里出问题时,你才知道该改算法、改参数、改硬件,还是改 TF。

参考资料

[¹] Nav2 Concepts: https://docs.nav2.org/concepts/index.html
[²] Nav2 Smac Planner: https://docs.nav2.org/configuration/packages/configuring-smac-planner.html
[³] Nav2 Controller Server: https://docs.nav2.org/configuration/packages/configuring-controller-server.html
[⁴] Nav2 Velocity Smoother: https://docs.nav2.org/configuration/packages/configuring-velocity-smoother.html