跳转至

六、服务(service)与接口(interface)

📌服务是指由一个服务端提供服务,由客户端去请求,与话题的不同之处在于:服务只在需要时去请求即可,并且可以传递参数

📌接口可以用来定义服务传递的数据的结构

1.动手实现一个加法计算服务

(1)创建接口

cd ~/dev_ws/src

ros2 pkg create --build-type ament_cmake learning_interface

cd learning_interface

rm -rf include src # 可选

mkdir srv && cd srv

touch Add.srv

Add.srv代码

int64 a        # 第一个加数
int64 b        # 第二个加数
---
int64 sum      # 求和结果

在package.xml中添加:

<build_depend>rosidl_default_generators</build_depend>
<exec_depend>rosidl_default_runtime</exec_depend>
<member_of_group>rosidl_interface_packages</member_of_group>

在CMakeLists.txt中添加:

find_package(rosidl_default_generators REQUIRED)

rosidl_generate_interfaces(${PROJECT_NAME}
  "srv/Add.srv"
 )

构建软件包

cd ~/dev_ws

colcon build

source install/local_setup.bash

(2)服务端

cd ~/dev_ws/src

ros2 pkg create --build-type ament_python learning_service

add_server.py

import rclpy
from rclpy.node import Node
from learning_interface.srv import Add

class AddServer(Node):

    def __init__(self, node_name):
        super().__init__(node_name)
        self.srv = self.create_service(Add, "add", self.callback)

    def callback(self, request, response):
        response.sum = request.a + request.b
        self.get_logger().info('request: a: %d b: %d' % (request.a, request.b))
        return response

def main(args=None):
    rclpy.init(args=args)
    node = AddServer("add_server")
    rclpy.spin(node)
    node.destroy_node()
    rclpy.shutdown()

(3)客户端

add_client.py

import sys
import rclpy
from rclpy.node import Node
from learning_interface.srv import Add

class AddClient(Node):

    def __init__(self, name):
        super().__init__(name)
        self.client = self.create_client(Add, 'add')
        while not self.client.wait_for_service(timeout_sec=1.0):
            self.get_logger().info('waiting service...') 
        self.request = Add.Request()

    def send_request(self):
        self.request.a = int(sys.argv[1])
        self.request.b = int(sys.argv[2])
        self.future = self.client.call_async(self.request)

def main(args=None):
    rclpy.init(args=args)
    node = AddClient("add_client")
    node.send_request()

    while rclpy.ok():
        rclpy.spin_once(node)
        if node.future.done():
            try:
                response = node.future.result()
            except Exception as e:
                node.get_logger().info('service failed %r' % (e,))
            else:
                node.get_logger().info(
                    'result: %d + %d = %d' %
                    (node.request.a, node.request.b, response.sum))
            break

    node.destroy_node()
    rclpy.shutdown()

(4)配置节点并运行

ros2 run learning_service add_server

ros2 run learning_service add_client 33 44