ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

ROS2服务端和客户端通信

ROS2服务端和客户端通信 文章目录编写服务端节点编写客户端节点在ROS2中Topic 适用于持续的数据流如传感器数据而 Service 适用于同步的、一问一答的请求-响应模型类似于 RPC 远程过程调用。Service的核心特征是阻塞与同步客户端Client发送请求后会等待服务端Server处理完毕并返回结果。在此期间客户端的执行流通常会被挂起或通过异步回调处理。Service 常用于触发某个动作、查询系统状态或进行数学计算。下面使用ROS2内置的 AddTwoInts 服务接口进行实战。该接口定义了两个输入参数a 和 b和一个输出参数sum。在具体实现Topic通信的功能之前先创建工作空间具体可参考节点通信-创建工作空间。编写服务端节点服务端的作用是监听特定的服务名称当收到请求时执行计算逻辑并将结果返回给客户端。在内层restaurant_robot目录下新建service_server.py代码如下importrclpyfromrclpy.nodeimportNode# 导入 ROS2 示例接口中的 AddTwoInts 服务类型fromexample_interfaces.srvimportAddTwoIntsclassAddTwoIntsServer(Node):def__init__(self):super().__init__(add_two_ints_server)# 创建服务端# 参数服务类型(AddTwoInts), 服务名称(add_two_ints), 回调函数self.srvself.create_service(AddTwoInts,add_two_ints,self.callback)self.get_logger().info(service start...)defcallback(self,request,response):# request 包含客户端发来的数据 (request.a, request.b)# response 是需要返回给客户端的数据对象response.sumrequest.arequest.b self.get_logger().info(frecived: a{request.a}, b{request.b}, result:{response.sum})# 必须返回 response 对象returnresponsedefmain(argsNone):rclpy.init(argsargs)nodeAddTwoIntsServer()try:rclpy.spin(node)exceptKeyboardInterrupt:passfinally:node.destroy_node()rclpy.shutdown()if__name____main__:main()退回上一级目录打开 setup.py在 console_scripts 列表中添加run_service_server restaurant_robot.service_server:main,接下来在工作空间最上层文件夹编译并运行colcon build source install/setup.bash ros2 run restaurant_robot run_service_server此时打开另一个终端输入ros2 service list就会在服务列表中查看到【add_two_ints】。通过命令行service call指令可以直接调用这个服务# 格式ros2 service call 服务名 服务类型 请求参数(JSON格式)ros2servicecall /add_two_ints example_interfaces/srv/AddTwoInts{a: 15, b: 25}其中的json参数即为上述代码回调函数的request。此时服务端命令行会输出【request: a15, b25, result40】客户端命令行会输出requester: making request: example_interfaces.srv.AddTwoInts_Request(a15, b25) response: example_interfaces.srv.AddTwoInts_Response(sum40)编写客户端节点接下来手写一个客户端同样在内层restaurant_robot中新建文件文件名【service_client.py】内容如下importrclpyfromrclpy.nodeimportNodefromexample_interfaces.srvimportAddTwoIntsclassAddTwoIntsClient(Node):def__init__(self):super().__init__(add_two_ints_client)# 创建客户端# 参数服务类型(AddTwoInts), 服务名称(add_two_ints)self.clientself.create_client(AddTwoInts,add_two_ints)# 等待服务端上线。如果服务端未启动客户端会每秒检查一次并打印警告whilenotself.client.wait_for_service(timeout_sec1.0):self.get_logger().warn(wait server)# 实例化请求对象self.requestAddTwoInts.Request()defsend_request(self,a,b):self.request.aa self.request.bb self.get_logger().info(f发送请求: a{a}, b{b})# 异步发送请求。call_async 会立即返回一个 Future 对象self.futureself.client.call_async(self.request)returnself.futuredefmain(argsNone):rclpy.init(argsargs)nodeAddTwoIntsClient()# 1. 发送请求 (例如计算 50 60)futurenode.send_request(50,60)# 2. 阻塞当前线程直到 Future 对象返回结果即服务端处理完毕rclpy.spin_until_future_complete(node,future)# 3. 处理返回的结果iffuture.result()isnotNone:node.get_logger().info(f收到服务端响应: 结果 {future.result().sum})else:node.get_logger().error(服务调用异常未获取到结果)node.destroy_node()rclpy.shutdown()if__name____main__:main()同样在setup.py的console_scripyts列表中添加run_service_client restaurant_robot.service_client:main,至此在两个终端里分别运行服务端和客户端colcon build source install/setup.bash ros2 run restaurant_robot run_service_client客户端输出为[INFO] [1785116627.910747071] [add_two_ints_client]: send request: a50, b60 [INFO] [1785116628.828596147] [add_two_ints_client]: receive the response: result110
返回列表