3. ROS2服务通信实现
任务目标
本案例将创建一个ROS2服务通信的最小可运行示例:一个服务端节点提供两个整数相加的服务,一个客户端节点发起请求并接收响应。同时演示服务不可用时客户端的超时处理机制。
环境准备
需要已安装ROS2(Humble或更高版本),并完成环境source。本案例使用Python实现,无需额外依赖包。
实现代码
创建文件 add_two_ints_server.py:
#!/usr/bin/env python3
import rclpy
from rclpy.node import Node
from example_interfaces.srv import AddTwoInts
class AddTwoIntsServer(Node):
def __init__(self):
super().__init__('add_two_ints_server')
self.srv = self.create_service(AddTwoInts, 'add_two_ints', self.add_callback)
self.get_logger().info('服务端已启动,等待请求...')
def add_callback(self, request, response):
response.sum = request.a + request.b
self.get_logger().info(f'收到请求: {request.a} + {request.b} = {response.sum}')
return response
def main(args=None):
rclpy.init(args=args)
node = AddTwoIntsServer()
try:
rclpy.spin(node)
except KeyboardInterrupt:
pass
finally:
node.destroy_node()
rclpy.shutdown()
if __name__ == '__main__':
main()
创建文件 add_two_ints_client.py:
#!/usr/bin/env python3
import sys
import rclpy
from rclpy.node import Node
from example_interfaces.srv import AddTwoInts
class AddTwoIntsClient(Node):
def __init__(self):
super().__init__('add_two_ints_client')
self.cli = self.create_client(AddTwoInts, 'add_two_ints')
while not self.cli.wait_for_service(timeout_sec=1.0):
self.get_logger().warn('服务不可用,等待中...')
self.req = AddTwoInts.Request()
def send_request(self, a, b):
self.req.a = a
self.req.b = b
future = self.cli.call_async(self.req)
rclpy.spin_until_future_complete(self, future, timeout_sec=5.0)
if future.done() and future.result() is not None:
return future.result().sum
else:
raise TimeoutError('请求超时:服务端未在5秒内响应')
def main(args=None):
rclpy.init(args=args)
node = AddTwoIntsClient()
if len(sys.argv) != 3:
node.get_logger().error('用法: python3 add_two_ints_client.py <a> <b>')
rclpy.shutdown()
return
try:
a, b = int(sys.argv[1]), int(sys.argv[2])
result = node.send_request(a, b)
node.get_logger().info(f'调用结果: {a} + {b} = {result}')
except TimeoutError as e:
node.get_logger().error(str(e))
except Exception as e:
node.get_logger().error(f'发生异常: {e}')
finally:
node.destroy_node()
rclpy.shutdown()
if __name__ == '__main__':
main()
运行与验证
步骤1:打开终端,source ROS2环境后运行服务端:
source /opt/ros/humble/setup.bash
python3 add_two_ints_server.py
步骤2:另开终端,运行客户端发起请求:
source /opt/ros/humble/setup.bash
python3 add_two_ints_client.py 3 5
预期输出:客户端终端显示 调用结果: 3 + 5 = 8,服务端终端显示收到请求的日志。
异常验证:先不启动服务端,直接运行客户端。客户端会持续打印“服务不可用,等待中...”,此时启动服务端,客户端自动连接成功并完成请求。若服务端在请求发出后5秒内无响应(可先启动客户端再立即关闭服务端模拟),客户端会打印超时错误。
通过标准:正常场景下客户端能正确打印两数之和;异常场景下客户端能识别服务不可用并等待,或在超时后给出明确错误提示,不崩溃退出。