跳到主要内容

Topics

Topic 用于节点之间的异步数据传输。

1. Topic 是什么?

ROS 2 中不同节点之间通常不会直接调用彼此函数,而是通过 Topic 通信。

例如:

摄像头节点 ---> /image_raw ---> 图像处理节点

或者:

键盘控制节点 ---> /cmd_vel ---> 小车底盘节点

其中:

/image_raw
/cmd_vel

就是 Topic。

2. 发布者和订阅者

Topic 通信中有两个核心角色:

Publisher 发布者

负责往某个话题发送数据。

例如:

摄像头节点发布图像数据

Subscriber 订阅者

负责从某个话题接收数据。

例如:

图像处理节点订阅图像数据

3. 基本模型

Publisher 节点
|
| 发布消息
v
Topic 话题
|
| 订阅消息
v
Subscriber 节点

例如:

/talker
|
| std_msgs/String
v
/chatter
|
v
/listener

4. Topic 的特点

1. 异步通信

发布者发消息后,不需要等待订阅者回复。

例如:

摄像头节点只管不断发布图像
图像处理节点有数据就处理

2. 多对多通信

一个 Topic 可以有:

  • 一个发布者,多个订阅者
  • 多个发布者,一个订阅者
  • 多个发布者,多个订阅者

例如:

/camera/image_raw

可以同时被:

图像显示节点
目标检测节点
录像节点

订阅。


3. 需要消息类型一致

发布者和订阅者必须使用同一种消息类型。

例如:

/cmd_vel

通常类型是:

geometry_msgs/msg/Twist

如果类型不匹配,就不能正常通信。


5. 常见 Topic 例子

Topic 名称常见消息类型含义
/cmd_velgeometry_msgs/msg/Twist控制机器人速度
/odomnav_msgs/msg/Odometry里程计信息
/scansensor_msgs/msg/LaserScan激光雷达数据
/camera/image_rawsensor_msgs/msg/Image摄像头图像
/imusensor_msgs/msg/ImuIMU 数据
/tftf2_msgs/msg/TFMessage动态坐标变换
/joint_statessensor_msgs/msg/JointState关节状态

6. 常用命令

查看所有话题

ros2 topic list

查看话题和类型

ros2 topic list -t

示例:

/cmd_vel [geometry_msgs/msg/Twist]
/odom [nav_msgs/msg/Odometry]

查看某个话题类型

ros2 topic type /话题名

例如:

ros2 topic type /cmd_vel

输出:

geometry_msgs/msg/Twist

查看话题内容

ros2 topic echo /话题名

例如:

ros2 topic echo /robot_news

查看话题频率

ros2 topic hz /话题名

例如:

ros2 topic hz /scan

查看话题带宽

ros2 topic bw /话题名

例如:

ros2 topic bw /camera/image_raw

手动发布一次消息

ros2 topic pub /话题名 消息类型 "消息内容"

例如发布速度控制:

ros2 topic pub /cmd_vel geometry_msgs/msg/Twist "{linear: {x: 0.2}, angular: {z: 0.0}}"

按频率发布消息

ros2 topic pub -r 10 /cmd_vel geometry_msgs/msg/Twist "{linear: {x: 0.2}, angular: {z: 0.0}}"

表示:

以 10 Hz 频率发布速度指令

7. Topic 通信适合什么?

适合连续数据流,例如:

  • 摄像头图像
  • 激光雷达
  • IMU
  • 里程计
  • 机器人速度命令
  • 关节状态
  • 传感器数据

8. Topic 不适合什么?

Topic 不适合需要明确请求和响应的场景。

例如:

打开/关闭电机
保存地图
查询当前模式
请求规划路径

这类更适合用:

Service

如果是长时间任务,比如:

导航到某个目标点
机械臂执行轨迹
无人机起飞降落

更适合用:

Action

9. Topic、Service、Action 简单区别

通信方式特点适合场景
Topic持续发布/订阅传感器、速度、状态
Service一问一答开关、查询、短任务
Action可反馈、可取消导航、机械臂运动、长任务

10. C++ 中创建发布者

简单示例:

publisher_ = this->create_publisher<std_msgs::msg::String>("chatter", 10);

发布消息:

auto msg = std_msgs::msg::String();
msg.data = "hello";
publisher_->publish(msg);

11. C++ 中创建订阅者

subscription_ = this->create_subscription<std_msgs::msg::String>(
"chatter",
10,
std::bind(&MyNode::callback, this, std::placeholders::_1)
);

回调函数:

void callback(const std_msgs::msg::String::SharedPtr msg)
{
RCLCPP_INFO(this->get_logger(), "I heard: %s", msg->data.c_str());
}

12. Python 中创建发布者

self.publisher_ = self.create_publisher(String, 'chatter', 10)

发布:

msg = String()
msg.data = 'hello'
self.publisher_.publish(msg)

13. Python 中创建订阅者

self.subscription = self.create_subscription(
String,
'chatter',
self.listener_callback,
10
)

回调:

def listener_callback(self, msg):
self.get_logger().info('I heard: "%s"' % msg.data)

14. 简单例子:小车速度控制

小车底盘节点订阅:

/cmd_vel

键盘控制节点发布:

/cmd_vel

结构:

/teleop_keyboard
|
| geometry_msgs/msg/Twist
v
/cmd_vel
|
v
/base_controller

消息内容大概是:

linear:
x: 0.2
y: 0.0
z: 0.0
angular:
x: 0.0
y: 0.0
z: 0.5

15.常用命令

ros2 topic list
ros2 topic echo /topic_name
ros2 topic info /topic_name
ros2 topic pub /topic_name 消息类型 "内容"