# 3.3 Topic
## 3.3.1 简介
ROS的通信方式是ROS最为核心的概念,ROS系统的精髓就在于它提供的通信架构。ROS的通信方式有以下四种:
* Topic 主题
* Service 服务
* Parameter Service 参数服务器
* Actionlib 动作库
## 3.3.2 Topic
ROS中的通信方式中,topic是常用的一种。对于实时性、周期性的消息,使用topic来传输是最佳的选择。topic是一种点对点的单向通信方式,这里的“点”指的是node,也就是说node之间可以通过topic方式来传递信息。topic要经历下面几步的初始化过程:首先,publisher节点和subscriber节点都要到节点管理器进行注册,然后publisher会发布topic,subscriber在master的指挥下会订阅该topic,从而建立起sub-pub之间的通信。注意整个过程是单向的。其结构示意图如下:
![](https://img.kancloud.cn/a3/3a/a33aeaa0bc6f9be4a11d7418debf9298_1042x705.jpg)
Subscriber接收消息会进行处理,一般这个过程叫做**回调(Callback)**。所谓回调就是提前定义好了一个处理函数(写在代码中),当有消息来就会触发这个处理函数,函数会对消息进行处理。
上图就是ROS的topic通信方式的流程示意图。topic通信属于一种异步的通信方式。下面我们通过一个示例来了解下如何使用topic通信。
## 3.3.3 通信示例
参考下图,我们以摄像头画面的发布、处理、显示为例讲讲topic通信的流程。在机器人上的摄像头拍摄程序是一个node(圆圈表示,我们记作node1),当node1运行启动之后,它作为一个Publisher就开始发布topic。比如它发布了一个topic(方框表示),叫做`/camera_rgb`,是rgb颜色信息,即采集到的彩色图像。同时,node2假如是图像处理程序,它订阅了`/camera_rgb`这个topic,经过节点管理器的介绍,它就能建立和摄像头节点(node1)的连接。
那么怎么样来理解**“异步”**这个概念呢?在node1每发布一次消息之后,就会继续执行下一个动作,至于消息是什么状态、被怎样处理,它不需要了解;而对于node2图像处理程序,它只管接收和处理`/camera_rgb`上的消息,至于是谁发来的,它不会关心。所以node1、node2两者都是各司其责,不存在协同工作,我们称这样的通信方式是异步的。
![](https://img.kancloud.cn/3e/ef/3eefe2749d521dec251915943dab6e8e_1317x1166.jpg)
ROS是一种分布式的架构,一个topic可以被多个节点同时发布,也可以同时被多个节点接收。比如在这个场景中用户可以再加入一个图像显示的节点,我们在想看看摄像头节点的画面,则可以用自己的笔记本连接到机器人上的节点管理器,然后在自己的电脑上启动图像显示节点。
这就体现了分布式系统通信的好处:扩展性好、软件复用率高。
**总结三点**:
1. topic通信方式是异步的,发送时调用publish()方法,发送完成立即返回,不用等待反馈。
2. subscriber通过回调函数的方式来处理消息。
3. topic可以同时有多个subscribers,也可以同时有多个publishers。ROS中这样的例子有:/rosout、/tf等等。
## 3.3.4 操作命令
在实际应用中,我们应该熟悉topic的几种使用命令,下表详细的列出了各自的命令及其作用。
| 命令 | 作用 |
| :------: | :------: |
| `rostopic list` | 列出当前所有的topic |
| `rostopic info topic_name` | 显示某个topic的属性信息 |
| `rostopic echo topic_name` | 显示某个topic的内容 |
| `rostopic pub topic_name ...` | 向某个topic发布内容|
| `rostopic bw topic_name` | 查看某个topic的带宽|
| `rostopic hz topic_name` | 查看某个topic的频率|
| `rostopic find topic_type` | 查找某个类型的topic|
| `rostopic type topic_name` | 查看某个topic的类型(msg)|
如果你一时忘记了命令的写法,可以通过`rostopic help`或`rostopic command -h`查看具体用法。
## 3.3.5 测试实例
1. 首先打开`ROS-Academy-for-Beginners`的模拟场景,输入`roslaunch robot_sim_demo robot_spawn_launch`,看到我们仿真的模拟环境。该`launch`文件启动了模拟场景、机器人。
2. 查看当前模拟器中存在的topic,输入命令`rostopic list`。可以看到许多topic,它们可以视为模拟器与外界交互的接口。
3. 查询topic`/camera/rgb/image_raw`的相关信息:`rostopic info /camera/rgb/image_raw`。则会显示类型信息type,发布者和订阅者的信息。
4. 上步我们在演示中可以得知,并没有订阅者订阅该主题,我们指定`image_view`来接收这个消息,运行命令`rosrun image_view image_view image:=<image topic> [transport]`。我们可以看到message,即是上一步中的type。
5. 同理我们可以查询摄像头的深度信息depth图像。
6. 在用键盘控制仿真机器人运动的时候,我们可以查看速度指令topic的内容`rostopic echo /cmd_vel` ,可以看到窗口显示的各种坐标参数在不断的变化。
通过这些实例的测试,帮助我们更快的掌握topic各种操作命令的使用,以及对topic通信的理解。
##小结
topic的通信方式是ROS中比较常见的单向异步通信方式,它在很多时候的通信是比较易用且高效的。但是有些需要交互的通信时该方式就显露出自己的不足之处了,后续我们会介绍双向同步的通信方式service。
- 前言
- 第一章 ROS简介
- 机器人时代的到来
- ROS发展历程
- 什么是ROS
- 安装ROS
- 安装ROS-Academy-for-Beginners教学包
- 二进制与源码包
- 安装RoboWare Studio
- 单元测试一
- 第二章 ROS文件系统
- Catkin编译系统
- Catkin工作空间
- Package软件包
- CMakeLists.txt
- package.xml
- Metapacakge软件元包
- 其他常见文件类型
- 单元测试二
- 第三章 ROS通信架构(一)
- Node & Master
- Launch文件
- Topic
- Msg
- 常见msg类型
- 单元测试三
- 第四章 ROS通信架构(二)
- Service
- Srv
- Parameter server
- Action
- 常见srv类型
- 常见action类型
- 单元测试四
- 第五章 常用工具
- Gazebo
- RViz
- Rqt
- Rosbag
- Rosbridge
- moveit!
- 单元测试五
- 第六章 roscpp
- Client Library与roscpp
- 节点初始、关闭与NodeHandle
- Topic in roscpp
- Service in roscpp
- Param in roscpp
- 时钟
- 日志与异常
- 第七章 rospy
- Rospy与主要接口
- Topic in rospy
- Service in rospy
- Param与Time
- 第八章 TF与URDF
- 认识TF
- TF消息
- tf in c++
- tf in python
- 统一机器人描述格式
- 附录:TF数学基础
- 三维空间刚体运动---旋转矩阵
- 三维空间刚体运动---欧拉角
- 三维空间刚体运动---四元数
- 第九章 SLAM
- 地图
- Gmapping
- Karto
- Hector
- 第十章 Navigation
- Navigation Stack
- move_base
- costmap
- Map_server & Amcl
- 附录:Navigation工具包说明
- amcl
- local_base_planner
- carrot_planner
- clear_costmap_recovery
- costmap_2d
- dwa_local_planner
- fake_localization
- global_planner
- map_server
- move_base_msg
- move_base
- move_slow_and_clear
- navfn
- nav_core
- robot_pose_ekf
- rotate_recovery