连载文章,长期更新,欢迎关注:
前面已经学习了大量ROS的基础知识,到这里终于可以开始编写ROS代码了,并在实战中体验和理解ROS的真正面容。ROS代码的编写围绕节点通信过程中的消息机制和消息类型两个核心点展开,因此先详细阐述话题(topic)、服务(service)和动作(action)三种消息机制的原理,然后介绍这三种消息机制中使用的消息类型,最后利用C++编写分别使用这三种消息机制通信的代码实例。
话题通信方式是单向异步的,发布者只负责将消息发布到话题,订阅者只从话题订阅消息,发布者与订阅者之间并不需要事先确定对方的身份,话题充当消息存储容器的角色,这种机制很好地实现了发布者与订阅者程序之间的解耦。由于话题通信方式是单向的,即发布者并不能确定订阅者是否按时接收到消息,所以这种机制也是异步的。话题通信一般用在实时性要求不高的场景中,比如传感器广播其采集的数据。如图1-10所示,是一个通过话题消息机制传递hello消息内容的实例。
图1-10 话题消息机制的过程
服务通信方式是双向同步的,服务客户端向服务提供端发送请求,服务提供端在收到请求后立马进行处理并返回响应信息。如图1-11所示,是一个通过服务消息机制计算两个数之和的实例。服务通信一般用在实时性要求比较高且使用频次低的场景下,比如获取全局静态地图。
图1-11 服务消息机制的过程
动作通信方式是双向异步的,动作客户端向动作提供端发送目标后,要达到目标需要一个过程,在执行目标的过程中实时地反馈消息,并且在目标完成后返回结果。动作通信用在一个过程性的任务执行场景下,比如导航任务。如图1-12所示,是一个通过动作消息机制实现倒计时任务的实例。
图1-12 动作消息机制的过程
进一步探究消息机制的底层实现,能够帮助大家更深入地理解ROS的性能特点。ROS的消息机制基于XMLRPC(XML Remote Procedure Call,XML远程过程调用)协议,这是一种采用XML编码格式,传输方式既不保持连接状态、也不检测连接状态的请求/响应式的HTTP协议。ROS的主节点master采用XMLRPC协议对节点的注册和连接进行管理,一旦两个节点建立了连接,节点之间就可以利用TCP/UDP协议传输消息数据了。如图1-13所示,是XMLRPC通信模型。在话题通信中,节点需要借助XMLRPC完成注册和连接,然后订阅者发起订阅之后,发布者就开始持续发布消息;在服务通信中,节点借助XMLRPC完成注册,而不需要建立连接就可以直接发起请求,响应完成后就自动断开;在动作通信中,节点借助XMLRPC完成注册,跟服务通信类似也不需要建立连接就可以直接发起目标,只是在响应的基础上多了一个反馈过程,完成后就自动断开。
图1-13 XMLRPC通信模型
了解ROS消息机制的原理后,接下来讨论一下ROS中的消息类型。其实消息类型就是一种数据结构,最底层的数据结构还是C++/Python的基本数据类型,只是ROS利用这些基本数据类型做了自己的封装。ROS中的消息类型分两种:一种是ROS定义的标准消息类型,另一种是用户利用标准消息类型自己封装的非标准消息类型。可以说用户自定义的非标准消息类型是对标准消息类型的有效补充。不管是标准的消息类型还是自定义的消息类型,都需要在功能包中进行封装,因此使用消息类型的时候需要使用功能包名和子类型名同时进行标识。ROS标准消息类型主要封装在std_msgs、sensor_msgs、geometry_msgs、nav_msgs、actionlib_msgs这些功能包中,并且这些消息类型大部分用在话题通信中,如表1-5所示。
表1-5 ROS标准消息类型
封装 功能包 |
std_msgs |
sensor_msgs |
geometry_msgs |
nav_msgs |
actionlib_msgs |
话题 消息 类型 |