ROS2话题:节点间传递数据的桥梁

一、什么是话题(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

相关推荐
星辰徐哥2 小时前
异步定时任务系统的设计与Rust实战集成
开发语言·后端·rust
海兰2 小时前
【springboot】gradle快速镜像配置
spring boot·笔记·后端
武超杰2 小时前
SpringBoot 整合 Spring Security 实现权限控制
spring boot·后端·spring
XMYX-03 小时前
06 - Go 的切片、字典与遍历:从原理到实战
后端·golang
架构师专栏3 小时前
比 MQ 更轻的异步方案:Spring 内置的这个隐藏功能,很多人还不知道
后端
林木883 小时前
Druid Kafka 数据源消费到 Segment 生成全链路深度分析
后端
摇曳的精灵3 小时前
Spring boot注解实现信息脱敏
java·spring boot·后端·注解脱敏·信息脱敏
程序猿大帅3 小时前
记一次线上翻车:加了Redisson分布式锁,数据还是被并发打穿了
后端
weixin_704266053 小时前
项目总结一
java·前端·spring boot·后端·spring