3. ROS2服务通信实现
任务目标
在ROS2中创建自定义服务类型(AddTwoInts.srv),实现一个服务端节点接收两个整数请求并返回求和结果,同时实现一个客户端节点发送请求并接收响应,完整掌握ROS2服务通信的同步请求-响应模式。
环境准备
本案例基于ROS2 Humble版本,需要预先安装ros-humble-desktop。创建工作空间并编译自定义服务接口包:
mkdir -p ~/ros2_ws/src && cd ~/ros2_ws/src
ros2 pkg create --build-type ament_cmake tutorial_interfaces
mkdir -p tutorial_interfaces/srv
自定义服务类型
在tutorial_interfaces/srv/AddTwoInts.srv中定义请求与响应结构:
int64 a
int64 b
---
int64 sum
编辑tutorial_interfaces/CMakeLists.txt,添加服务生成规则:
rosidl_generate_interfaces(${PROJECT_NAME}
"srv/AddTwoInts.srv"
)
编译并source环境:
cd ~/ros2_ws && colcon build --packages-select tutorial_interfaces
source install/setup.bash
服务端节点实现
创建service_server.py,注册服务并处理请求:
import rclpy
from rclpy.node import Node
from tutorial_interfaces.srv import AddTwoInts
class ServiceServer(Node):
def __init__(self):
super().__init__('service_server')
self.srv = self.create_service(AddTwoInts, 'add_two_ints', self.callback)
def 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 = ServiceServer()
rclpy.spin(node)
node.destroy_node()
rclpy.shutdown()
if __name__ == '__main__':
main()
客户端节点实现
创建service_client.py,发送请求并等待响应:
import sys
import rclpy
from rclpy.node import Node
from tutorial_interfaces.srv import AddTwoInts
class ServiceClient(Node):
def __init__(self):
super().__init__('service_client')
self.cli = self.create_client(AddTwoInts, 'add_two_ints')
while not self.cli.wait_for_service(timeout_sec=1.0):
self.get_logger().info('等待服务端上线...')
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)
return future.result()
def main(args=None):
rclpy.init(args=args)
client = ServiceClient()
a, b = int(sys.argv[1]), int(sys.argv[2])
response = client.send_request(a, b)
client.get_logger().info(f'服务端返回: {a} + {b} = {response.sum}')
client.destroy_node()
rclpy.shutdown()
if __name__ == '__main__':
main()
运行与验证
将两个Python文件放入~/ros2_ws/src/tutorial_pkg/(需先创建包并配置setup.py入口点),编译后分别运行:
# 终端1 - 启动服务端
ros2 run tutorial_pkg service_server
# 终端2 - 启动客户端(传入两个整数)
ros2 run tutorial_pkg service_client 3 5
验证判定标准:
- 服务端终端输出
收到请求: 3 + 5 = 8; - 客户端终端输出
服务端返回: 3 + 5 = 8; - 另开终端执行
ros2 service list能看到/add_two_ints服务,执行ros2 service type /add_two_ints返回tutorial_interfaces/srv/AddTwoInts。
以上三条同时满足即表示服务通信闭环成功。若客户端先于服务端启动,客户端会每1秒重试连接直到服务端就绪,无需重启客户端。