1. 基本概念
-
发布-订阅模型:节点间通过话题(Topic)异步通信,发布者(Publisher)发送消息,订阅者(Subscriber)接收消息。
-
话题(Topic):数据的传输通道,由名称唯一标识(如
/cmd_vel
)。 -
消息(Message):话题中传输的数据结构,支持标准类型(如
std_msgs/String
)或自定义类型。
2. 核心组件
-
发布者(Publisher):向指定话题发送消息。
-
订阅者(Subscriber):监听话题并接收消息。
-
消息接口(Interface):定义数据的格式(如
.msg
文件)。
3. 实现示例(以 Python 为例)
(1) 创建发布者节点
import rclpy
from rclpy.node import Node
from std_msgs.msg import String
class PublisherNode(Node):
def __init__(self):
super().__init__('my_publisher')
self.publisher = self.create_publisher(String, 'chatter', 10)
timer_period = 1.0 # 每秒发布一次
self.timer = self.create_timer(timer_period, self.timer_callback)
def timer_callback(self):
msg = String()
msg.data = 'Hello, ROS2!'
self.publisher.publish(msg)
self.get_logger().info(f'Publishing: "{msg.data}"')
def main(args=None):
rclpy.init(args=args)
node = PublisherNode()
rclpy.spin(node)
node.destroy_node()
rclpy.shutdown()
if __name__ == '__main__':
main()
(2) 创建订阅者节点
import rclpy
from rclpy.node import Node
from std_msgs.msg import String
class SubscriberNode(Node):
def __init__(self):
super().__init__('my_subscriber')
self.subscription = self.create_subscription(String,'chatter',self.listener_callback,10)
def listener_callback(self, msg):
self.get_logger().info(f'Received: "{msg.data}"')
def main(args=None):
rclpy.init(args=args)
node = SubscriberNode()
rclpy.spin(node)
node.destroy_node()
rclpy.shutdown()
if __name__ == '__main__':
main()
(3) 配置依赖和编译
package.xml
:添加rclpy
和std_msgs
依赖。
<depend>rclpy</depend>
<depend>std_msgs</depend>
setup.py
:确保入口点已注册。
entry_points={
'console_scripts': [
'publisher = my_package.publisher:main',
'subscriber = my_package.subscriber:main',
],
}
(4) 编译
colcon build --packages-select my_package
source install/setup.bash
(5) 运行与测试
-
启动发布者:
ros2 run my_package publisher
-
启动订阅者:
ros2 run my_package subscriber
-
查看话题列表:
ros2 topic list
-
手动发布消息:
ros2 topic pub /chatter std_msgs/String "{data: 'Manual message'}"
4. 服务质量(QoS)配置
ROS2 通过 QoS 策略控制通信行为,常用配置:
-
可靠性(Reliability):
-
Reliable
:确保消息不丢失(适用于关键数据)。 -
BestEffort
:允许丢包(适用于高频低优先级数据)。
-
-
持久性(Durability):
TransientLocal
:订阅者可接收发布者历史消息。
-
示例:
from rclpy.qos import QoSProfile, QoSReliabilityPolicy, QoSDurabilityPolicy
qos_profile = QoSProfile(
depth=10,#队列的深度,也就是发布者或订阅者能保存的消息数量
reliability=QoSReliabilityPolicy.RELIABLE,
durability=QoSDurabilityPolicy.TRANSIENT_LOCAL
)
self.publisher = self.create_publisher(String, 'chatter', qos_profile)
QoSDurabilityPolicy参数
- 可选值:
- TRANSIENT_LOCAL:发布者保留历史消息
- VOLATILE:不保留历史消息
5. 高级特性
-
自定义消息:
-
在
msg
目录下创建.msg
文件(如MyMessage.msg
)。 -
在
CMakeLists.txt
和package.xml
中声明消息生成依赖。
-
-
多话题通信:一个节点可同时作为多个话题的发布者/订阅者。
-
同步与异步通信:默认异步,可通过
wait_for_message()
实现同步接收。
6. 话题通信常用命令
$ ros2 topic list # 查看话题列表
$ ros2 topic info <topic_name> # 查看话题信息
$ ros2 topic hz <topic_name> # 查看话题发布频率
$ ros2 topic bw <topic_name> # 查看话题传输带宽
$ ros2 topic echo <topic_name> # 查看话题数据
$ ros2 topic pub <topic_name> <msg_type> <msg_data> # 发布话题消息
7.实际应用
话题命名:使用/namespace/topic_name结构
消息设计:避免超过1MB的大消息
频率控制:合理设置发布频率(建议≤100Hz)
-
话题无数据:
-
检查话题名称是否一致:
ros2 topic list | grep <topic_name>
。 -
确认消息类型匹配:
ros2 topic info <topic_name>
。 -
检查 QoS 配置是否兼容(如发布者使用
BestEffort
,订阅者需相同)。
-
-
消息延迟:
-
增大 QoS 的
depth
参数以缓冲更多消息。 -
优化节点性能,减少回调函数处理时间。
-
补充:
1.与 ROS1 的主要区别
-
底层协议:ROS2 使用 DDS(数据分发服务),支持更灵活的通信配置。
-
节点生命周期:ROS2 节点需显式初始化和销毁。
-
命令行工具:ROS2 使用
ros2
替代roscore
,无需主节点(Master)。
ros2 topic pub命令
ros2 topic pub [选项] <话题名称> <消息类型> "<消息内容>"
一、命令参数详解
ros2 topic pub
/chatter # 目标话题名称
std_msgs/String # 消息类型(包名/消息名)
"{data: 'Manual message'}" # YAML格式的消息内容
二、各部分功能说明
-
话题名称:
- 必须是已存在的活跃话题
- 查看所有话题:
ros2 topic list
-
消息类型:
- 标准消息:如
std_msgs/String
,geometry_msgs/Twist
- 自定义消息:
package_name/msg/MyMessage
- 标准消息:如
-
消息内容:
- YAML格式或Python字典格式
- 必须严格匹配消息结构
三、自定义消息步骤
-
查看消息结构:
ros2 interface show std_msgs/msg/String # 输出:string data
-
复杂消息示例:
# 发布geometry_msgs/Twist ros2 topic pub /cmd_vel geometry_msgs/Twist " linear: x: 0.5 y: 0.0 z: 0.0 angular: x: 0.0 y: 0.0 z: 0.3"
-
常用选项参数:
-1 # 发布一次后退出 -r 10 # 以10Hz频率持续发布 -w 2 # 等待2秒后发布
四、实用技巧
-
自动补全:
ros2 topic pub /chatter std_msgs/String <按Tab键补全>
-
调试建议:
# 先使用echo验证话题 ros2 topic echo /chatter # 再发布测试消息
五、常见错误处理
-
格式错误:
- 错误:缺少缩进或冒号
- 解决:使用YAML校验工具检查
-
类型不匹配:
# 错误示例:字符串赋给数值字段 "{data: 'hello'}" # 用于std_msgs/Int32会报错
-
字段缺失:
- 必须完整填写所有required字段
即使最高的山,也不比最低的山谷更靠近天空。任何地方都不比另一个地方拥有更多的天空。 —辛波斯卡