1. ROS2动作通信基础概念
动作(Action)是ROS2中一种重要的通信机制,它结合了话题(Topic)和服务(Service)的优点,特别适合需要长时间执行并反馈进度的任务场景。想象一下你点了一份外卖:下单相当于服务调用,骑手实时位置更新相当于话题发布,而整个送餐过程就是一个典型的动作交互。
在机器人开发中,动作通信最常见的应用场景包括:
- 机械臂运动控制
- 导航任务执行
- 物体抓取操作
- 长时间运行的算法任务
与ROS1相比,ROS2的动作系统有了显著改进:
- 取消机制:支持随时中断正在执行的任务
- 反馈机制:实时返回任务执行进度
- 超时处理:内置完善的超时管理
- 多语言支持:Python和C++实现更加统一
RCLPY是ROS2的Python客户端库,它提供了简洁的API来实现动作通信。相比RCLCPP(C++库),RCLPY的代码更加简洁,特别适合快速原型开发和教育演示。不过要注意,Python在实时性要求高的场景下可能不如C++高效。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 环境准备与工程创建
2.1 开发环境配置
在开始之前,确保你已经完成以下准备工作:
- 安装Ubuntu 22.04(推荐)或20.04
- 安装ROS2 Humble或Foxy版本
- 配置Python 3.8+环境
- 安装必要的开发工具:
bash复制sudo apt install python3-pip python3-rosdep2
pip install setuptools==58.2.0
2.2 创建工作空间和功能包
让我们从创建一个全新的工作空间开始:
bash复制mkdir -p ~/action_ws/src
cd ~/action_ws/src
创建Python功能包时,我们需要指定正确的依赖项:
bash复制ros2 pkg create example_action_rclpy \
--build-type ament_python \
--dependencies rclpy robot_control_interfaces \
--node-name action_server \
--maintainer-name "your_name" \
--maintainer-email "your_email@example.com"
这个命令会自动生成包的基本结构,但我们需要手动添加一些关键文件:
bash复制touch ~/action_ws/src/example_action_rclpy/example_action_rclpy/action_server.py
touch ~/action_ws/src/example_action_rclpy/example_action_rclpy/action_client.py
touch ~/action_ws/src/example_action_rclpy/example_action_rclpy/robot_simulator.py
2.3 配置package.xml和setup.py
确保package.xml包含所有必要的依赖:
xml复制<depend>rclpy</depend>
<depend>robot_control_interfaces</depend>
<depend>action_msgs</depend>
在setup.py中正确配置入口点:
python复制entry_points={
'console_scripts': [
'action_server = example_action_rclpy.action_server:main',
'action_client = example_action_rclpy.action_client:main',
],
},
3. 动作服务端实现详解
3.1 机器人模拟器开发
我们先创建一个简单的机器人模拟器,用于演示动作通信:
python复制from robot_control_interfaces.action import MoveRobot
import math
class RobotSimulator:
"""模拟机器人移动的虚拟类"""
def __init__(self):
self.current_pose = 0.0
self.target_pose = 0.0
self.status = MoveRobot.Feedback.STATUS_READY
def move_step(self):
"""模拟机器人单步移动"""
step_size = 0.1 * (self.target_pose - self.current_pose)
self.current_pose += step_size
return self.current_pose
def set_goal(self, distance):
"""设置移动目标"""
self.target_pose = distance
self.status = MoveRobot.Feedback.STATUS_MOVING
return True
def get_status(self):
