定位、导航与自主任务
2D Navigation:使用地图导航
Navigation 使用已经保存的地图进行定位、路径规划和底盘控制。它不会重新建图。启动 Navigation 后,系统会加载 map.pgm / map.yaml,启动定位模块、路径规划模块、控制器、代价地图和 RViz。Gmapping / Cartographer 负责生成地图;Navigation 负责使用地图。
Navigation / Localization 显示 active 只表示相关 Nav2 lifecycle 节点已经激活,不表示地图一定正确、AMCL 一定收敛、LaserScan 一定对齐,也不表示当前目标一定可达。发出目标前必须先确认地图、定位、雷达扫描和 costmap 状态。
Navigation 使用前面保存的 map.pgm 和 map.yaml 进行定位和路径规划。启动 Navigation 前,请先打开 map.pgm 检查地图轮廓是否清楚,并确认当前测试环境与建图时基本一致。
如果地图有明显重影、断墙、错位、大片未知区域,或当前场地已经发生较大变化,不要继续测试 Navigation。应先重新建图或重新保存地图。
前置条件
启动 Navigation 前,先完成以下检查:
- 已按 查看保存的地图文件 确认
map.pgm和map.yaml存在,并检查map.pgm轮廓质量; - 已按 检查并释放底盘串口 确认底盘串口没有被其它程序占用;
- 已停止 Gmapping、Cartographer、基础 bringup、键盘控制或其它会占用底盘、雷达的终端;
- 测试场地空旷,UGV 旁边没有人、宠物、线缆、桌脚或其它障碍;
- 已确认 停止 Navigation 的流程。
nav.launch.py 会包含底盘与雷达 bringup,不要同时单独启动另一个 bringup_lidar.launch.py。
Navigation 会发布速度指令并驱动实体底盘。关闭终端不应作为唯一停止手段,测试时始终保留物理停止方式。
启动 Navigation
cd /home/ws/ugv_ws
source /opt/ros/humble/setup.bash
source install/setup.bash
export UGV_MODEL=ugv_rover
ros2 launch ugv_nav nav.launch.py use_rviz:=true use_localization:=amcl use_localplan:=teb
该命令会启动 Navigation、定位、局部规划、底盘与雷达相关节点,并打开 RViz。启动后不要关闭该 Navigation 终端。
本节使用推荐组合 amcl + teb。其中 amcl 用来判断机器人在地图中的位置,teb 用来根据目标点和障碍物规划局部移动路线。首次导航时先不要修改 use_localization 和 use_localplan 参数,先完成地图加载、初始位姿设置、目标点发送和底盘移动测试。
开发者补充:Navigation 参数说明
nav.launch.py 中的两个参数分别决定:
use_localization:机器人使用哪种方式在地图中定位,也就是判断“我现在在地图哪里”;use_localplan:机器人使用哪种局部规划方式移动到目标点,也就是判断“我怎么绕开附近障碍物走过去”。
| 参数 | 可选值 | 作用 | 建议 |
|---|---|---|---|
use_localization | amcl | 常用 2D 定位方式。启动后需要在 RViz 中用 2D Pose Estimate 设置初始位姿 | 首次实车导航优先使用 |
use_localization | emcl | 另一种 2D 定位方式,也需要设置初始位姿 | 跑通 AMCL 后再测试 |
use_localization | cartographer | 使用 Cartographer 相关定位流程 | 前面使用 Cartographer 建图流程时再测试 |
use_localplan | teb | 局部规划方式之一,用于根据目标点、障碍物和机器人运动约束生成局部运动路径 | 当前主线使用 |
use_localplan | dwa | 另一种局部规划方式 | 跑通 TEB 后再对比测试 |
简单理解:
amcl/emcl/cartographer解决“机器人在哪里”;teb/dwa解决“机器人怎么走过去”;- 首次导航不要改参数,先使用
amcl + teb跑通地图加载、初始位姿、目标点和底盘移动流程。
确认 Navigation 实际加载的地图
启动 Navigation 后,另开 Docker ROS 2 终端确认 /map_server 实际加载的地图路径。
cd /home/ws/ugv_ws
source /opt/ros/humble/setup.bash
source install/setup.bash
ros2 param get /map_server yaml_filename
再检查源码目录和安装目录中的地图文件。
ls -lh src/ugv_main/ugv_nav/maps/map.pgm \
src/ugv_main/ugv_nav/maps/map.yaml
ls -lh install/ugv_nav/share/ugv_nav/maps/map.pgm \
install/ugv_nav/share/ugv_nav/maps/map.yaml
查看两个 map.yaml 的内容。
echo "===== src map.yaml ====="
cat src/ugv_main/ugv_nav/maps/map.yaml
echo "===== install map.yaml ====="
cat install/ugv_nav/share/ugv_nav/maps/map.yaml
Navigation 实际使用哪张地图,以 /map_server 的 yaml_filename 为准。如果 src 和 install 中的地图文件时间、大小或内容不一致,可能出现保存的是新地图、Navigation 加载的却是旧地图的情况。
地图不匹配时,LaserScan 与地图轮廓会错开,AMCL 定位和 costmap 会异常,近距离目标也可能无法到达。如果发现 Navigation 加载的不是预期地图,请先停止 Navigation,确认当前工作空间的地图保存脚本和 launch 加载路径,再重新启动 Navigation。
认识 Navigation RViz 界面
Navigation RViz 不是只看地图,而是把静态地图、实时雷达扫描、定位粒子、全局路径、局部控制和 costmap 叠加显示。颜色较多属于正常界面状态。
Navigation RViz 中常见显示项如下。
| 显示项 | 含义 |
|---|---|
Map | 保存后加载的 2D 占据栅格地图 |
RobotModel | 当前机器人模型和朝向 |
LaserScan | 实时雷达扫描,用来和地图边缘对齐 |
Amcl Particle Swarm | AMCL 定位粒子,用来估计机器人在地图中的位置 |
Global Planner | 全局规划路径 |
Controller | 局部控制器或局部代价相关显示 |
| costmap 红色 / 紫色 / 粉色 / 青色区域 | 导航认为靠近障碍物、有碰撞风险或需要避开的区域 |
Navigation / Localization | 显示 active 时,表示 Nav2 导航和定位模块已激活 |
需要区分:Map 是原始 2D 地图,LaserScan 是实时雷达扫描,costmap 是导航代价图。costmap 会把障碍物、安全距离和风险区域叠加显示,不等于原始地图。

查看地图时,先选择顶部 Move Camera。鼠标滚轮用于缩放,按住鼠标中键拖动可以平移地图视图。如果视图被左侧 Displays 面板挡住,可以拖动面板边界缩小左侧区域,或折叠暂时不需要查看的显示项。设置初始位姿或目标点前,可以先用 Move Camera 调整视角,再点击 2D Pose Estimate 或 Nav2 Goal。
如果路径、机器人模型或地图被过多显示项遮挡,可在左侧 Displays 面板中临时取消勾选部分 costmap、粒子或调试显示项,只保留查看路径需要的 Map、RobotModel、LaserScan、Global Planner 等显示项。该操作只改变 RViz 显示,不会修改导航参数,也不会停止 Navigation。

设置初始位姿
- 确认地图已经加载。
- 确认实时
LaserScan大致落在地图墙体或障碍物边缘附近。 - 点击顶部
2D Pose Estimate。 - 在地图上点击 UGV 实际位置,按住鼠标左键拖出车头方向箭头。
- 松开鼠标完成设置。
松开鼠标后,RViz 工具栏回到 Move Camera 时属于正常显示状态。判断初始位姿是否生效,不看工具栏当前按钮,而是看 Amcl Particle Swarm 是否收敛到机器人附近,以及实时 LaserScan 是否大致贴合地图中的墙体或障碍物边缘。
设置初始位姿后,先等待 10 ~ 20 秒,不要立即发送目标。观察 LaserScan 是否与地图轮廓对齐,观察 Amcl Particle Swarm 是否集中。如果粒子分散、机器人模型跳动、LaserScan 与墙体轮廓明显错开,需要重新设置 2D Pose Estimate。
判断 LaserScan、AMCL 和 costmap 是否正常
设置目标点前,必须完成四项检查:
- 地图是当前场地的地图;
LaserScan与地图墙体或障碍物轮廓大致对齐;Amcl Particle Swarm集中在机器人真实位置附近;- 机器人自身和目标点附近没有被 costmap 高风险区域覆盖。
如果以上任意一项不满足,不要点击 Nav2 Goal。
costmap 中出现红色、紫色、粉色或青色区域不一定是错误,它表示 Navigation 根据静态地图、实时雷达、障碍层和膨胀层计算出的风险区域。需要重点看机器人中心附近和目标点附近是否被高风险区域覆盖。
如果机器人中心附近被大面积高风险区域覆盖,或者目标点位于高风险区域内,或者 RViz 中无法生成路径、Feedback 显示 canceled、Recoveries 持续增加,不要继续发送目标。先回到地图、LaserScan、AMCL 和传感器状态检查。
清理 costmap
需要排查代价地图缓存时,先查看当前是否存在清理服务。
cd /home/ws/ugv_ws
source /opt/ros/humble/setup.bash
source install/setup.bash
ros2 service list | grep clear
如果存在以下服务,再执行清理命令。
ros2 service call /global_costmap/clear_entirely_global_costmap nav2_msgs/srv/ClearEntireCostmap {}
ros2 service call /local_costmap/clear_entirely_local_costmap nav2_msgs/srv/ClearEntireCostmap {}
清理 costmap 只清除当前代价地图缓存,不会修复错误地图、错误初始位姿或传感器异常。如果清理后机器人周围很快再次被大面积高风险区域覆盖,应回到地图、LaserScan、AMCL 和传感器状态检查。
设置极近距离 Nav2 Goal
第一次只设置 20 ~ 30 cm 的极近距离目标。目标点必须在白色可通行区域,且不靠墙、不靠障碍、不在线缆附近。极近目标可达后,再测试 0.5 ~ 1 m 目标。不要第一次就跨房间、穿过狭窄区域或贴近障碍物。
- 完成 判断 LaserScan、AMCL 和 costmap 是否正常 中的四项检查。
- 点击顶部
Nav2 Goal。 - 在地图上选择机器人附近
20 ~ 30 cm的白色可通行区域。 - 按住鼠标左键拖出目标点到达后的车头方向箭头。
- 松开鼠标后,观察 RViz 中是否生成路径,以及 Navigation 面板状态是否变化。
Nav2 Goal 会让导航系统发布速度指令并驱动底盘。拖出的箭头表示“到达目标点后的车头朝向”,不表示机器人一定会沿箭头方向直线行驶。实际路径由 Nav2 根据地图、定位、实时雷达扫描和 costmap 自动规划。
目标太近时,Navigation 面板可能很快显示 reached,机器人不会有明显移动;这不代表远距离目标已经可用。先用极近目标确认基础导航状态,再逐步增加距离。
执行目标后,可以在 RViz 左侧 Navigation 2 面板中查看状态:
Navigation: active:导航模块已激活;Localization: active:定位模块已激活;Feedback: active:Nav2 正在执行目标;Feedback: reached:Nav2 认为目标已经到达;ETA:预计剩余时间;Distance remaining:距离目标的剩余距离;Recoveries:恢复行为触发次数。
Recoveries 不是普通计时器。它表示导航过程中触发恢复行为的次数。如果该数值持续增加,通常说明目标点附近代价过高、路线被阻挡、定位不够准,或目标选择不合适。首次测试时可以取消当前目标,重新选择更近、更空旷的白色区域。

图中 Navigation 和 Localization 均为 active,Feedback 为 active,表示 Nav2 已接收目标并正在执行。Distance remaining 表示距离目标的剩余距离,Recoveries 表示恢复行为触发次数。若 Recoveries 持续增加,可取消当前目标,重新选择更近、更空旷的目标点。到达目标后,Feedback 会显示 reached。这些状态表示 Navigation 正在使用地图,不代表正在重新建图。
停止 Navigation
需要停止 Navigation 时,按下面顺序处理:
-
在 RViz 左侧
Navigation 2面板中点击Cancel或Pause。 -
另开 Docker ROS 2 终端发送一次
/cmd_vel零速度。cd /home/ws/ugv_wssource /opt/ros/humble/setup.bashsource install/setup.bashros2 topic pub --once /cmd_vel geometry_msgs/msg/Twist "{linear: {x: 0.0}, angular: {z: 0.0}}" -
回到 Navigation launch 终端,按
Ctrl + C停止nav.launch.py。 -
如果 UGV 仍在移动,立即断电。
发送一次零速度只能作为辅助停止动作。Navigation 控制器仍在运行时,可能继续发布新的 /cmd_vel,因此不要把该命令作为唯一停止方式。
常见异常排查
如果近距离 Nav2 Goal 也无法移动、Feedback 显示 canceled、costmap 大面积异常或 UGV 有碰撞风险,先停止 Navigation,再按下面顺序排查:
- Navigation 实际加载的
map.yaml是否是当前场地地图; src与install中地图文件是否不一致;LaserScan是否与地图轮廓对齐;- AMCL 粒子是否收敛;
- 机器人中心或目标点是否被 costmap 高风险区域覆盖;
/scan是否有稳定频率;/odom和/robot_pose是否持续输出;ugv_bringup、ugv_driver、base_node是否仍在运行;- Navigation launch 终端是否出现
process has died、multiple access、KeyError、TF extrapolation、Message Filter dropping message等日志; - 目标点是否太远、靠墙、靠障碍或在未知区域。
检查关键节点:
ros2 node list | grep -E "ugv_bringup|ugv_driver|base_node|amcl|map_server|planner_server|controller_server|bt_navigator"
检查关键数据:
timeout 8 ros2 topic hz /scan
timeout 8 ros2 topic echo /odom
timeout 8 ros2 topic echo /robot_pose
如果 /scan、/odom 或 /robot_pose 没有输出,先不要继续发目标。回到 bringup、定位和地图加载检查。
行为控制与导航点任务
行为控制是产品封装的任务接口,用来把常见底盘动作和导航点操作封装成 Action 任务。它不是 Nav2 标准功能,也不是建图功能。
前置知识
行为控制与Jupyter/Web JSON指令的区别
行为控制不是 Jupyter / Web JSON 指令的替代品。Jupyter / Web JSON 指令更接近下位机协议,用于验证硬件响应;ROS 2 行为控制运行在 ROS 2 层,用 /behavior Action 执行动作任务,例如后退一小段、原地旋转、保存导航点或发布已保存导航点。保存导航点不等于保存地图,前往导航点仍然依赖 Navigation。
| 对比项 | Jupyter / Web JSON 指令 | ROS 2 行为控制 /behavior |
|---|---|---|
| 所在层级 | 下位机 / 产品协议层 | ROS 2 应用层 |
| 控制入口 | Jupyter、Web 命令框或下位机 JSON 指令 | ROS 2 Action:/behavior |
| 控制方式 | 直接发送底盘、灯光、云台、OLED 等硬件指令 | 发送动作任务,由行为节点结合 /odom、/cmd_vel、/robot_pose、/goal_pose 执行 |
| 是否需要 ROS 2 | 不一定 | 需要 ROS 2 环境和相关节点 |
| 典型用途 | 验证下位机通信,测试底盘、LED、OLED、云台等硬件是否响应 | 封装短动作、查看 Action 状态、保存导航点、发布导航目标 |
开发者补充:behavior_ctrl 的 topic 和 Action
behavior_ctrl 创建 /behavior Action Server,订阅 /odom 和 /robot_pose,发布 /cmd_vel 和 /goal_pose。短距离动作通过 /cmd_vel 驱动底盘;导航点任务通过 /robot_pose 获取当前位置,并通过 /goal_pose 发布目标点。
短距离动作与停止
短距离动作适合先验证行为控制接口,例如让 UGV 前进一小段、后退一小段或原地旋转一定角度。它依赖 /odom 判断动作进度,并通过 /cmd_vel 驱动底盘,不依赖地图。
短距离动作、前往导航点和 Navigation 目标都会驱动实体底盘。测试前确认场地空旷,远离人、宠物、线缆和桌脚。测试时先使用低速、短距离任务。
- 确认 Docker ROS 2 终端 1 中的
bringup_lidar.launch.py正在运行。若该终端已经关闭,先回到 启动底盘与雷达 重新启动。
启动 behavior Action Server
-
另开新的 Docker ROS 2 终端启动行为控制。启动后保持该终端运行,不要关闭。
cd /home/ws/ugv_wssource /opt/ros/humble/setup.bashsource install/setup.bashros2 run ugv_tools behavior_ctrl -
另开 Docker ROS 2 终端发送短距离动作。新终端也先加载 ROS 2 环境。
cd /home/ws/ugv_wssource /opt/ros/humble/setup.bashsource install/setup.bash
前进一小段:
ros2 action send_goal /behavior ugv_interface/action/Behavior "{command: '[{\"T\": 1, \"type\": \"drive_on_heading\", \"data\": 0.1}]'}"
后退一小段:
ros2 action send_goal /behavior ugv_interface/action/Behavior "{command: '[{\"T\": 1, \"type\": \"back_up\", \"data\": 0.1}]'}"
原地旋转:
ros2 action send_goal /behavior ugv_interface/action/Behavior "{command: '[{\"T\": 1, \"type\": \"spin\", \"data\": -1}]'}"
停止当前行为:
ros2 action send_goal /behavior ugv_interface/action/Behavior "{command: '[{\"T\": 1, \"type\": \"stop\", \"data\": 0}]'}"
如果行为动作仍在执行,优先发送停止动作;如果仍无法停止,回到行为控制终端或底盘 bringup 终端按 Ctrl + C,必要时直接关闭机器人电源。
对比任务:同样后退一小段,对比 JSON 指令和 ROS 2 行为任务
这个任务用于理解“直接控制下位机”和“ROS 2 Action 任务”的区别。两种方式都会让 UGV 后退一小段,但观察重点不同:JSON 指令关注底层硬件是否响应;ROS 2 行为控制关注 Action 任务是否被接收、执行并返回结果。
目标: 分别使用 Web JSON 指令和 ROS 2 /behavior Action 让 UGV 后退一小段,对比两种控制层级的输出和状态。
完成标准: UGV 能完成短时间后退并停止;JSON 方式用于确认底盘响应,ROS 2 行为控制方式能看到 Action 任务接收和完成状态。 Web 命令输入框使用 在 Web 命令输入框发送后退短动作: 识别结果中会看到: 切换到 ROS 2 行为控制前,先按 实体 UGV Docker ROS 2 SSH Session 连接 Docker ROS 2 终端,再按 检查并释放底盘串口 释放底盘串口占用。随后启动 Docker ROS 2 终端 1,并按 启动 behavior Action Server 启动行为控制节点,保持两个终端运行。 再另开 Docker ROS 2 终端发送后退任务: ROS 2 行为控制方式运行后会看到: 同样是“后退一小段”,JSON 指令更像“直接告诉下位机怎么动”;ROS 2 行为控制更像“告诉 ROS 2 执行一个后退任务,并等待任务完成结果”。展开操作步骤和命令
base -c ... 转发 JSON 指令。Notebook 中可通过下位机教程的 send_cmd({...}) 发送同类 JSON。更多 JSON 控制入口见 下位机教程。base -c ... 只发送一次 JSON 指令。默认配置下,底盘约 1 ~ 2 秒没有收到新的运动指令后会自行停止,因此这里不需要再发送停止指令。
Goal accepted、SUCCEEDED 这类任务状态。
Waiting for an action server to become available...;Goal accepted;Goal finished with status: SUCCEEDED;Result: true 表示行为任务返回完成;
可选验证:保存并发布导航点
保存并发布导航点用于验证 /behavior、/robot_pose 和 /goal_pose 的接口链路。它不是完整的航点管理系统,也不替代基础 Navigation 检查。
save_map_point 会把当前 /robot_pose 记录为命名点。pub_nav_point 会把已保存点发布到 /goal_pose。这相当于把“手动点 Nav2 Goal”替换为“程序发布目标点”。真正路径规划和底盘运动仍由 Navigation / Nav2 完成。
能否实际到达,仍取决于 Navigation 的地图、AMCL、TF、costmap、底盘反馈和目标容差。如果 RViz 手动 Nav2 Goal 的极近距离目标都不能稳定到达,不要继续测试保存导航点后的实际移动。
| 方式 | 目标点来源 |
|---|---|
RViz Nav2 Goal | 在地图上手动点击目标 |
pub_nav_point | 程序把之前保存的导航点发布成目标 |
测试 A:接口链路验证。
-
先按 2D Navigation:使用地图导航 启动 Navigation,再按 启动 behavior Action Server 启动行为控制节点,并保持两个终端运行。
-
另开 Docker ROS 2 终端发送导航点任务命令。新终端也先加载 ROS 2 环境。
cd /home/ws/ugv_wssource /opt/ros/humble/setup.bashsource install/setup.bash -
先确认
/behaviorAction Server 已经可用。ros2 action list | grep behaviorros2 action info /behavior如果发送行为命令时一直停在
Waiting for an action server to become available...,说明当前没有找到/behaviorAction Server。先回到第 1 步的行为控制终端,确认ros2 run ugv_tools behavior_ctrl仍在运行;如果该终端已经退出,重新启动行为控制节点后再发送命令。 -
检查
/robot_pose。ros2 topic echo /robot_pose --once如果
/robot_pose有输出,表示系统已经能得到机器人在地图中的位姿。若没有输出,先检查 Navigation 是否启动、初始位姿是否设置、定位是否正常。 -
保存当前位置为 A 点。
ros2 action send_goal /behavior ugv_interface/action/Behavior "{command: '[{\"T\": 1, \"type\": \"save_map_point\", \"data\": \"a\"}]'}"该命令会把当前
/robot_pose记录为一个导航点。保存时 UGV 不会因为“保存点”这个动作而主动移动。 -
在另一个 Docker ROS 2 终端监听
/goal_pose。cd /home/ws/ugv_wssource /opt/ros/humble/setup.bashsource install/setup.bashros2 topic echo /goal_pose -
回到发送导航点任务命令的终端,发布 A 点为 Navigation 目标。
ros2 action send_goal /behavior ugv_interface/action/Behavior "{command: '[{\"T\": 1, \"type\": \"pub_nav_point\", \"data\": \"a\"}]'}"该命令会向
/goal_pose发布已保存的 A 点。后续是否能规划路径、是否移动、是否到达,取决于 Navigation 的定位、地图、costmap 和路径规划状态。
接口链路验证的观察点:
/behaviorAction Server 可用;/robot_pose有输出;save_map_point返回;pub_nav_point后/goal_pose有输出;/goal_pose的frame_id为map;- Navigation 面板是否收到目标。
测试 B:实际移动验证。
只有在基础 Navigation 已经通过 设置极近距离 Nav2 Goal 后,才继续测试实际移动。不要把精确回到物理 A 点作为通过标准。
- 保存当前位置为 A 点。
- 可以按 设置极近距离 Nav2 Goal 使用 RViz
Nav2 Goal设置一个近距离目标,也可以按 使用键盘低速移动 用键盘控制短距离移动。 - 移动后确认 UGV 已经离开 A 点,并保持 Navigation 正常运行。使用键盘控制时,不要同时保留其它会持续发布速度指令的程序。
- 发布 A 点为 Navigation 目标。
发布后只观察 Navigation 状态,不把到达某个物理点作为唯一判断:
- 是否生成路径;
- 是否开始执行;
- 是否
canceled; Recoveries是否增加;- 是否被 costmap 阻挡;
- 是否接近目标容差范围。
如果手动 Nav2 Goal 的近距离目标都不能稳定到达,先回到 常见异常排查,不要继续测试保存导航点的实际移动。
自动探索
自动探索是进阶功能,不作为首次导航。先完成 Gmapping 建图、查看保存的地图文件 和近距离 2D Navigation:使用地图导航,再测试自动探索。
-
先在当前 Docker ROS 2 终端加载 ROS 2 环境。
cd /home/ws/ugv_wssource /opt/ros/humble/setup.bashsource install/setup.bash -
启动建图导航。
ros2 launch ugv_nav slam_nav.launch.py use_rviz:=true
继续启动探索入口时,不要结束当前建图导航终端。
-
另开终端启动探索入口。新终端也先加载 ROS 2 环境。
cd /home/ws/ugv_wssource /opt/ros/humble/setup.bashsource install/setup.bash
ros2 launch explore_lite explore.launch.py
自动探索会让机器人自主选择目标点并移动。使用前确认场地封闭、规则、空旷,并全程准备 停止 Navigation 的方式。保存探索地图时,可按 Gmapping 建图 中的保存方式处理。停止时先停止探索节点,再按 停止 Navigation 中的方式停止底盘运动,最后停止 SLAM / Navigation 相关 launch。