Nav2 导航与任务原型
先完成开始前的准备、SLAM 建图与地图保存。本节先启动地图、定位和规划组件,再介绍自动任务需要接通的接口。配套任务节点尚不能直接完成“搜索黄油 → 导航抓取 → 返回起点”。
重要
启动自动任务前,需要补齐以下接口:视觉发布 /detections 的目标坐标;任务节点的 /amcl_pose 类型与 AMCL 的 PoseWithCovarianceStamped 对齐;将 /cmd_vel 转成 UART 的 MotorControl;为 /joint_commands 的 grasp 指令提供执行端并启用舵机。任务状态还需等待导航到达与抓取完成。未接通这些接口时,先进行地图、定位与规划检查,不启动自动抓取任务。
端侧安装依赖
在端侧(RK3588S)执行以下命令安装 Nav2 导航相关功能包:
sudo apt update sudo apt install -y \ ros-humble-navigation2 \ ros-humble-nav2-bringup \ ros-humble-nav2-simple-commander
重要
本章节依赖SLAM 建图与定位的功能包(slam-toolbox、robot-localization、laser-filters),若未安装请先完成 SLAM 配置。同时需要视觉检测系统、底盘通信功能包(uart)和里程计融合功能包(ekf_odom)正常运行。
前置条件检查
在开始 Nav2 部署前,请确认以下条件已满足:
✅ 已完成 SLAM 建图,将
src/hy_slam/map/中的地图复制到本节所需的安装目录✅ 已部署视觉检测系统(YOLOv8 + RKNN NPU)
✅ 底盘串口通信正常(UART 与 ESP32S3)
✅ 里程计融合节点正常运行(EKF)
✅ 雷达数据正常发布(
/scan话题)
系统架构设计
整体架构
导航系统采用分层设计,从上到下依次为:
┌─────────────────────────────────────────────────────────┐
│ 任务调度层 (Mission Layer) │
│ - 状态机管理 (搜索/导航/抓取/返回) │
│ - 目标点规划与发布 │
│ - 视觉检测结果订阅 │
└─────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────┐
│ 导航规划层 (Nav2 Stack) │
│ - 全局路径规划 (NavFn) │
│ - 局部轨迹规划 (DWB) │
│ - 行为协调 (Behavior Tree) │
└─────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────┐
│ 定位感知层 (Localization & Perception) │
│ - AMCL 粒子滤波定位 │
│ - 代价地图构建 (静态层+障碍层+膨胀层) │
│ - 雷达数据过滤 (laser_filters) │
└─────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────┐
│ 执行控制层 (Control Layer) │
│ - 速度指令发布 (/cmd_vel) │
│ - 底盘运动控制 (UART → ESP32S3) │
│ - 舵机控制 (抓取动作) │
└─────────────────────────────────────────────────────────┘
关键技术点
TF 坐标变换链:
map→odom→base_link→radar_Link视觉接口:现有视觉容器使用进程内图像传输;任务节点需要的检测坐标接口尚未接通
代价地图融合:静态地图 + 实时雷达障碍 + 安全膨胀区域
任务原型与当前状态切换
任务节点定义六个状态,当前行为如下:
| 状态 | 当前代码行为 | 尚缺的完成条件 |
|---|---|---|
IDLE |
首次收到位姿时保存起点 | /amcl_pose 消息类型需与 AMCL 对齐 |
GO_TO_CENTER |
发送搜索中心导航目标,立即切到搜索 | 等待导航成功或处理失败 |
SEARCHING |
持续发布角速度,发现目标时停止搜索 | 结构化检测结果、搜索范围与超时 |
NAVIGATE_TO_BUTTER |
把消息中的 x/y 直接作为 map 坐标发送,立即切到抓取 | 相机到地图转换、导航到达与距离检查 |
GRASPING |
发布字符串 grasp,立即切到返回 |
舵机桥接、动作完成反馈与等待 |
RETURN_HOME |
发送起点导航目标后切回空闲 | 等待返回成功、失败处理与状态复位 |
现有代码没有实现“距离小于 0.3 m 才抓取”或“等待 3 秒完成动作”。/cmd_vel 与 /joint_commands 也没有接到当前 UART 节点。这些是后续集成需要补齐的条件。
Nav2 核心组件
定位模块 (AMCL)
功能:基于粒子滤波的蒙特卡洛定位算法,融合雷达数据与里程计实现机器人在地图中的定位。
关键参数:
max_particles: 2000:粒子数量,影响定位精度和计算量laser_model_type: likelihood_field:激光模型类型update_min_d: 0.25:移动 0.25m 触发一次更新update_min_a: 0.2:旋转 0.2rad 触发一次更新
输出:发布 map → odom 的 TF 变换
全局规划器 (NavFn Planner)
功能:基于 Dijkstra 算法在静态地图上规划从起点到终点的最优路径。
特点:
考虑静态障碍物和膨胀区域
生成平滑的全局路径
expected_planner_frequency: 20.0是期望规划频率配置,不能作为实测更新频率保证
局部规划器 (DWB Controller)
功能:动态窗口法(Dynamic Window Approach)局部轨迹规划,实时避障。
工作原理:
在速度空间采样多条候选轨迹(vx, vy, vθ)
对每条轨迹评分(路径跟随、目标接近、障碍避让)
选择得分最高的轨迹执行
关键参数:
max_vel_x: 0.15:最大线速度 (m/s)max_vel_theta: 1.0:最大角速度 (rad/s)sim_time: 1.5:轨迹预测时间 (s)
代价地图 (Costmap 2D)
功能:构建机器人周围环境的代价地图,用于路径规划和避障。
三层结构:
静态层 (Static Layer):加载 SLAM 构建的静态地图
障碍层 (Obstacle Layer):实时雷达检测的动态障碍物
膨胀层 (Inflation Layer):障碍物周围膨胀安全区域
全局 vs 局部代价地图:
全局代价地图:覆盖整个地图,用于全局路径规划
局部代价地图:3m×3m 滚动窗口,用于局部避障
功能包结构
hy_nav2 功能包目录结构
hy_nav2/ ├── config/ │ └── nav2_params.yaml # Nav2 核心参数配置 ├── launch/ │ ├── nav2_bringup.launch.py # Nav2 导航栈启动 │ └── butter_mission.launch.py # 仅任务节点启动 ├── hy_nav2/ │ ├── __init__.py │ └── butter_mission_node.py # 任务调度节点 ├── package.xml └── setup.py
核心文件说明
nav2_params.yaml
包含 AMCL、控制器、规划器、代价地图等所有 Nav2 组件的参数
需根据机器人实际尺寸调整
robot_radius: 0.15速度限制需与底盘实际能力匹配
butter_mission_node.py
实现状态机逻辑
订阅
/detections话题获取目标检测结果发布
/cmd_vel搜索速度指令;到 UART 的控制桥接尚未实现调用 Nav2 的
NavigateToPoseAction 发送目标;当前不等待最终结果
nav2_bringup.launch.py
启动地图服务器(加载 SLAM 地图)
启动 AMCL 定位节点
启动 Nav2 导航栈(规划器、控制器、行为服务器)
配置与后续集成
配置文件编写
步骤 1:创建 Nav2 参数文件
在 config/nav2_params.yaml 中配置:
AMCL 定位参数(粒子数、更新阈值)
控制器参数(速度限制、加速度限制)
规划器参数(路径规划算法)
代价地图参数(分辨率、膨胀半径)
小技巧
可参考 Nav2 官方示例:/opt/ros/humble/share/nav2_bringup/params/nav2_params.yaml
步骤 2:适配机器人参数
根据黄油机器人实际情况调整:
robot_radius: 0.15(机器人半径,单位:米)max_vel_x: 0.15(最大线速度,与底盘能力匹配)inflation_radius: 0.35(障碍物膨胀半径,确保安全距离)
任务调度节点开发
当前实现与待接通项:
状态机管理:使用 Python Enum 定义状态,在定时器回调中切换状态
Action Client:调用 Nav2 的
NavigateToPoseAction 发送导航目标视觉融合:订阅
/detections话题,解析黄油位置信息坐标接口待实现:现有代码直接读取 x/y 并作为地图坐标,未完成坐标转换
关键接口:
订阅:
/detections(目标检测结果)、/amcl_pose(当前位姿)发布:
/cmd_vel(速度控制)、/joint_commands(舵机控制)Action:
/navigate_to_pose(导航目标)
启动文件编写
nav2_bringup.launch.py 职责:
启动 Map Server(加载
hy_slam保存的地图)启动 AMCL 定位节点
启动 Nav2 导航栈(通过
navigation_launch.py)启动 Lifecycle Manager 管理节点生命周期
butter_mission.launch.py 职责:
不包含
nav2_bringup.launch.py,导航栈需另行启动启动任务调度节点
butter_mission_node传递参数:中心点坐标、搜索速度等
编译与运行
编译功能包
cd /mnt/nfs/hy_ros colcon build --packages-up-to hy_nav2 hy_slam source install/setup.bash
启动系统
地图准备:nav2_bringup.launch.py 固定读取已安装 hy_slam 下的 map/my_map.yaml。在同一工作区先完成建图保存,再复制地图:
cd /mnt/nfs/hy_ros source install/setup.bash map_directory="$(ros2 pkg prefix hy_slam)/share/hy_slam/map" mkdir -p "$map_directory" cp src/hy_slam/map/my_map.yaml src/hy_slam/map/my_map.pgm "$map_directory/"
地图 YAML 中的 image 应指向可访问的 PGM,复制后确认地图加载目录中两个文件齐全。EKF 输出 /odometry/filtered,打开 src/hy_nav2/config/nav2_params.yaml,将 bt_navigator.ros__parameters.odom_topic 从 /odom 改为 /odometry/filtered,重新编译并加载工作区。以下命令在独立终端启动,每个终端先加载相同 ROS 和工作区环境。
# 终端 1:启动基础系统(雷达+底盘+里程计融合) ros2 launch ldlidar_driver_ros2 ldlidar_driver.launch.py & ros2 launch uart uart.launch.py & ros2 launch ekf_odom ekf_odom.launch.py & ros2 launch butter_robot_description butter_robot_description.launch.py & ros2 launch hy_slam laser_filter_only.launch.py # 终端 2:启动视觉检测(摄像头+YOLOv8+推流) ros2 launch rk_camera rk_camera.launch.py & ros2 launch rk_inference rk_inference.launch.py & ros2 launch rk_streamer rk_streamer.launch.py # 终端 3:启动 Nav2 导航栈 ros2 launch hy_nav2 nav2_bringup.launch.py # 终端 4:仅在接口断点补齐后调试任务节点 ros2 launch hy_nav2 butter_mission.launch.py
小技巧
可使用 tmux 或 screen 管理多个终端,或参考 all_launch 功能包编写统一的 launch 文件整合所有节点。
调试与验证
用 ros2 topic info -v 检查话题类型和订阅者。自动任务接口完成后,还要确认 /cmd_vel 能到达底盘、检测结果能到达任务节点,再进行运动测试。
检查系统状态
验证 TF 树完整性
# 生成 TF 树图 ros2 run tf2_tools view_frames # 检查关键坐标变换 ros2 run tf2_ros tf2_echo map base_link
应包含完整链路:map → odom → base_link → radar_Link
检查话题通信
# 查看导航相关话题 ros2 topic list | grep -E 'cmd_vel|odom|scan|map|amcl' # 查看目标检测结果 ros2 topic echo /detections # 查看机器人位姿 ros2 topic echo /amcl_pose
检查 Action 服务
# 查看可用 Action ros2 action list # 查看导航 Action 状态 ros2 action info /navigate_to_pose
常见问题排查
问题 1:机器人不移动
检查
/cmd_vel话题是否有数据:ros2 topic hz /cmd_vel检查 TF 树是否完整(特别是
map→odom变换)确认底盘串口通信正常
问题 2:定位漂移
增加 AMCL 粒子数:
max_particles: 2000 → 3000检查 EKF 输出:
ros2 topic echo /odometry/filtered,并核对与 Nav2/odom配置的对齐确认地图与实际环境一致
问题 3:路径规划失败
检查代价地图:
ros2 topic echo /global_costmap/costmap --once减小膨胀半径:
inflation_radius: 0.35 → 0.25确认目标点在可达区域内
问题 4:搜索时未检测到黄油
检查视觉检测节点是否运行:
ros2 node list | grep inference查看检测结果:
ros2 topic echo /detections调整搜索旋转速度:
search_angular_speed: 0.5 → 0.3
Foxglove 可视化
启动 Foxglove Bridge 进行实时监控:
ros2 run foxglove_bridge foxglove_bridge --ros-args -p port:=8765
在浏览器打开 Foxglove Studio,连接到 ws://<机器人IP>:8765
推荐查看的面板:
/map:静态地图/global_costmap/costmap:全局代价地图/local_costmap/costmap:局部代价地图(3m×3m 滚动窗口)/plan:全局路径/local_plan:局部轨迹/amcl_pose:定位位姿TF 树:坐标变换关系
参数调优建议
速度参数
根据实际测试调整机器人运动速度:
max_vel_x: 0.15:最大线速度,过大可能导致失控max_vel_theta: 1.0:最大角速度,影响转弯灵活性acc_lim_x: 0.5:线加速度限制,避免急加速acc_lim_theta: 1.5:角加速度限制
目标容差
调整到达目标的精度要求:
xy_goal_tolerance: 0.15:位置容差(米),过小可能无法到达yaw_goal_tolerance: 0.25:角度容差(弧度)
代价地图参数
robot_radius: 0.15:机器人半径,需实测确定inflation_radius: 0.35:膨胀半径,确保安全距离如需调整障碍物观测距离,根据雷达有效距离和实际场地设置,再检查代价地图覆盖范围。
完成后检查
地图服务器能加载
my_map.yaml,Foxglove 能显示/map和代价地图。雷达、滤波、里程计和 TF 连续输出;设置机器人初始位姿后,AMCL 能发布定位位姿。
ros2 action info /navigate_to_pose能找到导航 Action 服务。接入自动任务前,逐项完成本章开头的检测、消息类型、速度、舵机和动作反馈要求。
需要行走或抓取测试时,先完成控制接口适配,再从单个导航目标开始检查。