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

相关推荐
GetcharZp10 小时前
抛弃低效SSH!这套Ansible+Web可视化神器,让你天天准点下班!
后端
weixin_4462608513 小时前
HACO:面向动态部署环境的对冲式智能计算可靠多智能体调度框架
后端·python·flask
ttwuai15 小时前
Cursor 生成 CRUD 后,Go 后台接口别只测 200:JWT、RBAC 和 tenant_id 怎么验
开发语言·后端·golang
用户83562907805115 小时前
Python 实现 Excel 页面布局与打印设置自动化
后端·python
用户99314415798415 小时前
微服务框架中获取用户信息
后端
xuanWb15 小时前
手写一个 LLM API 网关:Anthropic 与 OpenAI 协议转换的完整实现
后端
苍何15 小时前
给 Codex 换皮肤这门生意,被我开源了
后端
用户83562907805115 小时前
Python 实现 Excel 命名范围(Named Range)的创建与管理
后端·python
程序员David15 小时前
我让 Claude 从架构文档一路干到代码,踩了三个坑才摸清边界
后端