
服务通信也是ROS中一种极其常用的通信模式,服务通信是基于请求响应模式的,是一种应答机制。也即:一个节点A向另一个节点B发送请求,B接收处理请求并产生响应结果返回给A。比如如下场景:
机器人巡逻过程中,控制系统分析传感器数据发现可疑物体或人... 此时需要拍摄照片并留存。
在上述场景中,就使用到了服务通信。
数据分析节点A需要向相机相关节点B发送图片存储请求,节点B处理请求,并返回处理结果。
与上述应用类似的,服务通信更适用于对实时性有要求、具有一定逻辑处理的应用场景。
服务通信是以请求响应的方式实现不同节点之间数据传输的通信模式。发送请求数据的对象称为客户端,接收请求并发送响应的对象称之为服务端,同话题通信一样,客户端和服务端也通过话题相关联,不同的是服务通信的数据传输是双向交互式的。

服务通信中,服务端与客户端是一对多的关系,也即,同一服务话题下,存在多个客户端,每个客户端都可以向服务端发送请求。

用于偶然的、对实时性有要求、有一定逻辑处理需求的数据传输场景。
需求:编写服务通信,客户端可以提交两个整数到服务端,服务端接收请求并解析两个整数求和,然后将结果响应回客户端。

在上述案例中,需要关注的要素有三个:
客户端;
服务端;
消息载体。
案例实现前需要先自定义服务接口,接口准备完毕后,服务实现主要步骤如下:
编写服务端实现;
编写客户端实现;
编辑配置文件;
编译;
执行。
案例我们会采用C++和Python分别实现,二者都遵循上述实现流程。
终端下进入工作空间的src目录,调用如下两条命令分别创建C++功能包和Python功能包。
定义服务接口消息与定义话题接口消息流程类似,主要步骤如下:
创建并编辑 .srv文件;
编辑配置文件;
编译;
测试。
接下来,我们可以参考案例编写一个srv文件,该文件中包含请求数据(两个整型字段)与响应数据(一个整型字段)。
功能包base_interfaces_demo下新建srv文件夹,srv文件夹下新建AddInts.srv文件,文件中输入如下内容:
srv文件与msg文件的包依赖一致,如果你是新建的功能包添加srv文件,那么直接参考定义msg文件时package.xml 配置即可。由于我们使用的是base_interfaces_demo该包已经为msg文件配置过了依赖包,所以package.xml不需要做修改。
如果是新建的功能包,与之前定义msg文件同理,为了将文件转换成对应的C++和Python代码,还需要在CMakeLists.txt中添加如下配置:
不过,我们当前使用的base_interfaces_demo包,那么你只需要修改rosidl_generate_interfaces函数即可,修改后的内容如下:
终端中进入当前工作空间,编译功能包:
编译完成之后,在工作空间下的 install 目录下将生成文件对应的C++和Python文件,我们也可以在终端下进入工作空间,通过如下命令查看文件定义以及编译是否正常:
正常情况下,终端将会输出与文件一致的内容。
功能包cpp02_service的src目录下,新建C++文件demo01_server.cpp,并编辑文件,输入如下内容:
功能包cpp02_service的src目录下,新建C++文件demo02_client.cpp,并编辑文件,输入如下内容:

在创建功能包时,所依赖的功能包已经自动配置了,配置内容如下:
CMakeLists.txt 中服务端和客户端程序核心配置如下:
终端中进入当前工作空间,编译功能包:
当前工作空间下,启动两个终端,终端1执行服务端程序,终端2执行客户端程序。
终端1输入如下指令:
终端2输入如下指令:
最终运行结果与案例类似。
功能包py02_service的py02_service目录下,新建Python文件demo01_server_py.py,并编辑文件,输入如下内容:
功能包py02_service的py02_service目录下,新建Python文件demo02_client_py.py,并编辑文件,输入如下内容

在创建功能包时,所依赖的功能包已经自动配置了,配置内容如下:
字段的中添加如下内容:
终端中进入当前工作空间,编译功能包:
当前工作空间下,启动两个终端,终端1执行服务端程序,终端2执行客户端程序。
终端1输入如下指令:
终端2输入如下指令:
最终运行结果与案例类似。
B站有完整的ros系列教程视频,可以观看完整内容ros课程ROS2理论与实践
更多内容将在猛狮知识星球社区更新最新课程,后续将推出更多优质内容——详情可关注猛狮集训营公众号和猛狮集训营官方网站。