ROS2笔记4--服务通讯
ROS2中话题通讯可以实现多个ROS节点之间数据的单向传输,不过话题通讯是一种异步通信机制,发布者无法准确知道订阅者是否收到消息。而服务通信是一种基于请求响应的通信模型,在通信双方中客户端发送请求数据到服务端,服务端响应结果给客户端。

从服务实现机制看这种形式是CS模型,客户端需要数据时针对具体的服务发送请求信息,服务端收到请求后进行处理并返回应答信息。
以加法计算器为例
1、新建功能包
1 | ros2 pkg create pkg_service --build- type ament_python --dependencies rclpy --node-name server_demo |
2、服务端实现
编写服务端server_demo.py文件实现服务端功能
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | import rclpy from rclpy.node import Node from example_interfaces.srv import AddTwoInts class Service_Server(Node): def __init__( self , name): super ().__init__(name)<br> # 创建一个服务端,使用的是create_service函数<br> # 参数分别为:服务数据类型、服务名称、服务回调函数 self .src = self .create_service(AddTwoInts, "/add_two_ints" , self .AddTwoInts_callback) <br> # 定义服务回调函数 def AddTwoInts_callback( self , request, response): response. sum = request.a + request.b print ( "result.sum = " , response. sum ) return response def main(): rclpy.init() server_demo = Service_Server( "server_node" ) rclpy.spin(server_demo) server_demo.destroy_node() rclpy.shutdown() |
服务回调函数AddTwoInts_callback这里需要传入参数除了self,还有requesst和response,request是服务需要的参数,response是服务返回的结果。request.a和request.b是request部分的内容,response.sum是response部分的内容。
AddTwoInts是类型,可以通过如下命令查看类型
1 | ros2 interface show example_interfaces /srv/AddTwoInts |
其中“--”上面部分是request,下面部分是response。request包含两个变量a,b;response包含变量sum
3、客户端实现
在server_demo.py统计目录下创建文件client_demo.py,编写客户端功能代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | import rclpy from rclpy.node import Node from example_interfaces.srv import AddTwoInts class Service_Client(Node): def __init__( self , name): super ().__init__(name)<br> # 创建客户端,使用create_client函数<br> # 传入参数分别是:服务数据类型、服务名称 self .client = self .create_client(AddTwoInts, "/add_two_ints" )<br> # 循环等待服务端启动 while not self .client.wait_for_service(timeout_sec = 1.0 ): print ( "service not available, waiting..." )<br> # 创建服务请求数据对象 self .request = AddTwoInts.Request() def send_request( self ): self .request.a = 10 self .request.b = 20 <br> # 发送服务请求 self .future = self .client.call_async( self .request) def main(): rclpy.init() client_demo = Service_Client( "client_node" ) client_demo.send_request() # 发送服务请求 while rclpy.ok(): rclpy.spin_once(client_demo)<br> # 判断数据是否处理完成 if client_demo.future.done(): try :<br> # 获取服务返回结果 response = client_demo.future.result() print ( "request.a = " , client_demo.request.a) print ( "request.b = " , client_demo.request.b) print ( "response.sum = " , response. sum ) except Exception as e: print ( "Service call failed" ) break client_demo.destroy_node() rclpy.shutdown() |
4、编辑配置文件、编译工作空间
配置文件setup.py

编译工作空间
1 | cd ~ /ros_ws colcon build --package-selects pkg_service source install /setup . bash |
5、运行程序
分终端分别启动服务端节点和客户端节点
1 2 | ros2 run pkg_service server_demo ros2 run pkg_service client_demo |
服务端打印:

客户端打印:

【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· 字符编码:从基础到乱码解决
· SpringCloud带你走进微服务的世界