改动: - 统一输出到 /cmd_vel_move (底盘订阅此话题) - PID 模式: 直接计算并发布到 /cmd_vel_move - NAV 模式: 订阅导航的 /cmd_vel 并转发到 /cmd_vel_move - 避免两种模式同时发布到 /cmd_vel 导致冲突 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6.5 KiB
6.5 KiB
rm_simple_move
一个用于 ROS2 的导航控制桥接节点,作为决策层和控制层的连接。支持两种控制模式:PID 直接控制和 Navigation 导航。
功能特性
双模式控制
- PID 模式 (mode=0): 直接根据当前位置和目标位置进行 PID 控制
- NAV 模式 (mode=1): 将目标转发给 Navigation 系统进行路径规划和导航
统一接口
- 单一输入话题:
/nav_goal(包含模式和目标点) - 标准输出:
/cmd_vel(标准 ROS2 速度控制) - 状态反馈:当前位置和导航状态
安装依赖
1. 克隆仓库
git clone https://github.com/goldenfishs/rm_simple_move.git
2. 安装 rm_msgs
git clone https://github.com/goldenfishs/rm_msgs.git
话题接口
输入话题
/nav_goal (rm_msgs/NavGoal)
导航目标 (合并了模式和目标点)
uint8 mode: 控制模式 (0=PID, 1=NAV)float32 target_x: 目标 x 坐标float32 target_y: 目标 y 坐标float32 target_angle: 目标角度 (-π ~ π)float32 max_speed: 最大速度 (仅 PID 模式使用)float32 tolerance: 到达容差 (仅 PID 模式使用)
输出话题
/cmd_vel_move (geometry_msgs/Twist)
统一的速度控制指令输出(底盘订阅此话题)
linear.x: x 方向线速度linear.y: y 方向线速度angular.z: z 轴角速度
/nav_status (rm_msgs/NavStatus)
导航状态
uint8 status: 状态码 (0=IDLE, 1=NAVIGATING, 2=REACHED, 3=FAILED)float32 distance: 距离目标点的距离string message: 状态描述
/current_pose (geometry_msgs/PoseStamped)
当前位置 (map 坐标系)
/goal_pose (geometry_msgs/PoseStamped)
导航目标 (NAV 模式下发布,供导航系统使用)
参数配置
| 参数名 | 类型 | 默认值 | 说明 |
|---|---|---|---|
pid_linear_kp |
double | 0.8 | 线性 PID 比例系数 |
pid_linear_ki |
double | 0.0 | 线性 PID 积分系数 |
pid_linear_kd |
double | 0.1 | 线性 PID 微分系数 |
pid_angular_kp |
double | 1.5 | 角度 PID 比例系数 |
pid_angular_ki |
double | 0.0 | 角度 PID 积分系数 |
pid_angular_kd |
double | 0.2 | 角度 PID 微分系数 |
使用方法
1. 编译
cd ~/MOVE_AI
colcon build --packages-select rm_msgs rm_simpal_move
2. 启动节点
source install/setup.bash
ros2 launch rm_simpal_move simple_move.launch.py
3. 测试
使用测试脚本
cd src/rm_nav/rm_simple_move/test
python3 move_test_new.py
测试命令:
# PID 模式导航
>>> pid 1.0 2.0 0.0
# PID 模式导航 (带速度和容差)
>>> pid 1.0 2.0 0.0 1.5 0.2
# NAV 模式导航
>>> nav 1.0 2.0 0.0
# 查看状态
>>> status
# 退出
>>> quit
使用命令行
PID 模式:
ros2 topic pub /nav_goal rm_msgs/msg/NavGoal "{
mode: 0,
target_x: 1.0,
target_y: 2.0,
target_angle: 0.0,
max_speed: 2.0,
tolerance: 0.1
}" --once
NAV 模式:
ros2 topic pub /nav_goal rm_msgs/msg/NavGoal "{
mode: 1,
target_x: 1.0,
target_y: 2.0,
target_angle: 0.0,
max_speed: 0.0,
tolerance: 0.0
}" --once
查看输出:
# 查看速度控制指令(底盘订阅此话题)
ros2 topic echo /cmd_vel_move
# 查看导航状态
ros2 topic echo /nav_status
# 查看当前位置
ros2 topic echo /current_pose
工作原理
PID 模式
- 接收目标点
/nav_goal(mode=0) - 通过 TF 获取当前位置 (map -> base_link)
- 计算目标点在 base_link 坐标系下的相对位置
- 使用 PID 控制器计算速度指令
- 发布到
/cmd_vel_move
NAV 模式
- 接收目标点
/nav_goal(mode=1) - 转换为
geometry_msgs/PoseStamped格式 - 发布到
/goal_pose给导航系统 - 导航系统输出
/cmd_vel rm_simple_move订阅/cmd_vel并转发到/cmd_vel_move
注意: 导航系统内部流程为:
/goal_pose → Nav2 → /cmd_vel_nav → velocity_smoother → /cmd_vel
状态发布
- 实时发布当前位置到
/current_pose - 实时发布导航状态到
/nav_status - 包含距离、状态码和描述信息
架构说明
决策层 (Decision Layer)
↓ /nav_goal (mode + target)
rm_simple_move (Bridge)
├─ PID 模式: 直接计算 → /cmd_vel_move
└─ NAV 模式: /goal_pose → Navigation Stack
↓
/cmd_vel_nav → velocity_smoother → /cmd_vel
↓
rm_simple_move 转发 → /cmd_vel_move
底盘驱动 (Chassis Driver)
← /cmd_vel_move (统一的速度指令)
话题流向:
- PID 模式:
rm_simple_move直接计算并发布到/cmd_vel_move - NAV 模式:
rm_simple_move发布/goal_pose→ Nav2 处理后输出/cmd_vel→rm_simple_move转发到/cmd_vel_move - 底盘驱动: 只订阅
/cmd_vel_move,避免冲突
Python 示例
import rclpy
from rclpy.node import Node
from rm_msgs.msg import NavGoal, NavStatus
class MyNode(Node):
def __init__(self):
super().__init__('my_node')
# 发布目标
self.goal_pub = self.create_publisher(NavGoal, '/nav_goal', 10)
# 订阅状态
self.status_sub = self.create_subscription(
NavStatus, '/nav_status', self.status_callback, 10)
def send_goal_pid(self, x, y, angle):
"""PID 模式"""
msg = NavGoal()
msg.mode = 0 # PID
msg.target_x = x
msg.target_y = y
msg.target_angle = angle
msg.max_speed = 2.0
msg.tolerance = 0.1
self.goal_pub.publish(msg)
def send_goal_nav(self, x, y, angle):
"""NAV 模式"""
msg = NavGoal()
msg.mode = 1 # NAV
msg.target_x = x
msg.target_y = y
msg.target_angle = angle
self.goal_pub.publish(msg)
def status_callback(self, msg):
if msg.status == 2: # REACHED
self.get_logger().info('目标已到达!')
完整示例见 test/decision_example.py
注意事项
- 坐标系要求: 需要正确配置
map -> base_link的 TF 变换 - PID 参数调优: 根据实际机器人调整 PID 参数
- 模式切换: 每次发送目标时可以切换模式
- 导航系统: NAV 模式需要配合 Nav2 或其他导航系统使用
- 标准接口: 输出使用标准
/cmd_vel,兼容所有 ROS2 底盘驱动
License
MIT License