一、什么是话题(Topic)?
1.1 话题的定义
在ROS2中,话题(Topic)是一种发布/订阅(Publish/Subscribe)模式的通信机制:
- 发布者(Publisher):生产数据并发送到话题
- 订阅者(Subscriber):从话题接收数据
- 话题(Topic):数据传输的命名通道
bash
发布者节点 话题 订阅者节点
┌────────┐ ┌─────────┐ ┌────────┐
│Publisher├─────────→│ /topic ├─────────→│Subscriber│
│ │ │ (消息队列)│ │ │
└────────┘ └─────────┘ └────────┘
数据源 数据通道 数据消费者
1.2 话题的本质特征
| 特性 | 说明 |
|---|---|
| 异步通信 | 发布者不等待订阅者响应 |
| 单向传输 | 数据单向流动 |
| 多对多 | 一个话题可有多个发布/订阅者 |
| 松耦合 | 发布者不知道订阅者存在 |
| 强类型 | 消息必须符合定义的类型 |
2、消息类型
2.1 消息类型定义
话题传输的数据必须符合预定义的消息类型(也被称为消息接口),消息类型其实就是一种数据类型,消息类型可以自定义。
消息类型例子:
msg
# std_msgs/msg/String.msg
string data
# geometry_msgs/msg/Twist.msg
Vector3 linear # 线速度
Vector3 angular # 角速度
# sensor_msgs/msg/LaserScan.msg
std_msgs/Header header
float32 angle_min
float32 angle_max
float32[] ranges
消息文件格式
- 文件扩展名:.msg
- 每个字段格式:类型 名称
2.2 常用消息类型
| 消息类型 | 用途 | 典型话题 |
|---|---|---|
std_msgs/String |
文本数据 | /diagnostics |
geometry_msgs/Twist |
速度指令 | /cmd_vel |
sensor_msgs/Image |
图像数据 | /camera/image |
sensor_msgs/LaserScan |
激光数据 | /scan |
nav_msgs/Odometry |
里程计数据 | /odom |
sensor_msgs/JointState |
关节状态 | /joint_states |
3.话题通信编程示例
3.1 创建发布者(Python)
1.创建发布者功能包:
css
#在ROS2工作空间的src目录下执行
ros2 pkg create --build-type ament_python topic_pub_pkg --license Apache-2.0
2.在topic_pub_pkg/topic_pub_pkg目录下创建topic_pub_node.py:
python
import rclpy
from rclpy.node import Node
from std_msgs.msg import String
from geometry_msgs.msg import Twist
class VelocityPublisher(Node):
"""
速度发布者节点
功能:定期发布机器人速度指令
"""
def __init__(self):
super().__init__('velocity_publisher')
# 创建发布者
# 参数:消息类型、话题名称、QoS深度
self.publisher = self.create_publisher(
Twist,
'/cmd_vel',
10
)
# 创建定时器,周期性发布
timer_period = 0.1 # 10Hz
self.timer = self.create_timer(
timer_period,
self.timer_callback
)
self.linear_speed = 0.2 # 线速度 m/s
self.angular_speed = 0.1 # 角速度 rad/s
self.get_logger().info('速度发布者已启动')
def timer_callback(self):
"""定时器回调函数"""
msg = Twist()
msg.linear.x = self.linear_speed
msg.linear.y = 0.0
msg.linear.z = 0.0
msg.angular.x = 0.0
msg.angular.y = 0.0
msg.angular.z = self.angular_speed
self.publisher.publish(msg)
self.get_logger().info(
f'发布速度: linear={msg.linear.x:.2f}, angular={msg.angular.z:.2f}'
)
def main(args=None):
rclpy.init(args=args)
node = VelocityPublisher()
rclpy.spin(node)
node.destroy_node()
rclpy.shutdown()
3.在setup.py中添加入口点
ini
entry_points={
'console_scripts': [
'topic_pub_node=topic_pub_pkg.topic_pub_node:main',
],
},
3.2 创建订阅者(Python)
1.创建订阅者功能包:
css
#在ROS2工作空间的src目录下执行
ros2 pkg create --build-type ament_python topic_sub_pkg --license Apache-2.0
2.在topic_sub_pkg/topic_sub_pkg目录下创建topic_sub_node.py:
python
import rclpy
from rclpy.node import Node
from geometry_msgs.msg import Twist
class VelocitySubscriber(Node):
"""
速度订阅者节点
功能:接收并处理速度指令
"""
def __init__(self):
super().__init__('velocity_subscriber')
# 创建订阅者
# 参数:消息类型、话题名称、回调函数、QoS深度
self.subscription = self.create_subscription(
Twist,
'/cmd_vel',
self.velocity_callback,
10
)
self.get_logger().info('速度订阅者已启动')
def velocity_callback(self, msg):
"""接收到消息时的回调函数"""
self.get_logger().info(
f'收到速度指令: linear.x={msg.linear.x:.2f}, '
f'angular.z={msg.angular.z:.2f}'
)
def main(args=None):
rclpy.init(args=args)
node = VelocitySubscriber()
try:
rclpy.spin(node)
except KeyboardInterrupt:
pass
finally:
node.destroy_node()
rclpy.shutdown()
3.在setup.py中添加入口点
ini
entry_points={
'console_scripts': [
'topic_sub_node=topic_sub_pkg.topic_sub_node:main',
],
},
3.3 构建和运行
3.3.1 构建发布者和订阅者节点
csharp
#构建发布者功能包
colcon build --packages-select topic_pub_pkg
#构建订阅者功能包
colcon build --packages-select topic_sub_pkg
3.3.2运行发布者和订阅者节点
bash
#运行发布者节点
source install/setup.bash
ros2 run topic_pub_pkg topic_pub_node
#运行订阅者节点
source install/setup.bash
ros2 run topic_sub_pkg topic_sub_node
3.4 输出示例
发布者节点:

订阅者节点:

4.话题的命令行操作
4.1 列出所有活动话题
ros2 topic list
新开一个终端,输入上述指令,显示结果:
bash
/cmd_vel
/parameter_events
/rosout
/cmd_vel就是发布者节点发布的话题。
/parameter_events是ROS 2 系统中一个内置的全局标准话题,用于实时监控和通知网络中所有节点的参数变化。
/rosout是 ROS2 中一个特殊的、全局内置的话题,承担着整个系统的日志收集与分发功能。
4.2 查看话题信息
css
ros2 topic info [话题名称]
输入:
bash
ros2 topic info /cmd_vel
显示结果:
yaml
Type: geometry_msgs/msg/Twist
Publisher count: 1
Subscription count: 1
4.3 查看话题消息类型
bash
ros2 topic type [话题名称]
输入:
bash
ros2 topic type /cmd_vel
显示结果:
bash
geometry_msgs/msg/Twist
4.4 查看话题发布频率
css
ros2 topic hz [话题名称]
输入:
bash
ros2 topic hz /cmd_vel
显示结果:
yaml
average rate: 10.001
min: 0.100s max: 0.100s std dev: 0.00017s window: 12
average rate: 10.001
min: 0.100s max: 0.100s std dev: 0.00015s window: 23
average rate: 10.000
min: 0.100s max: 0.100s std dev: 0.00015s window: 33
average rate: 10.000
4.5 查看话题带宽
css
ros2 topic bw [话题名称]
输入:
bash
ros2 topic bw /cmd_vel
显示结果:
less
Subscribed to [/cmd_vel]
537 B/s from 10 messages
Message size mean: 52 B min: 52 B max: 52 B
528 B/s from 20 messages
Message size mean: 52 B min: 52 B max: 52 B
525 B/s from 30 messages
Message size mean: 52 B min: 52 B max: 52 B
4.6 打印话题内容
bash
ros2 topic echo [话题名称]
输入:
bash
ros2 topic echo /cmd_vel
显示结果:
yaml
linear:
x: 0.2
y: 0.0
z: 0.0
angular:
x: 0.0
y: 0.0
z: 0.1
4.7 发布话题消息
css
ros2 topic pub [topic_name] [msg_type] [msg_data]
输入:
css
ros2 topic pub /cmd_vel geometry_msgs/msg/Twist "{linear: {x: 0.5}, angular: {z: 0.5}}"
topic_sub_node显示结果:
ini
INFO] [1775720799.149135035] [velocity_subscriber]: 收到速度指令: linear.x=0.50, angular.z=0.50
[INFO] [1775720800.149104853] [velocity_subscriber]: 收到速度指令: linear.x=0.50, angular.z=0.50
[INFO] [1775720801.148919754] [velocity_subscriber]: 收到速度指令: linear.x=0.50, angular.z=0.50