ROS2 入门应用 引用自定义服务(Python)

  • 1. 查看自定义消息
  • 2. 修改服务应答
  • 3. 修改服务请求
  • 4. 修改依赖关系
  • 5. 编译和运行



1. 查看自定义消息

引用在《ROS2 入门应用 创建自定义接口》中自定义的
服务AddThreeInts.srv

ros2 interface show tutorial_interfaces/srv/AddThreeInts

# int64 a
# int64 b
# int64 c
# ---
# int64 sum

需要对《ROS2 入门应用 请求和应答(Python)》中创建的服务端/客户端功能包稍作修改

cd ~/ros2_ws/src/py_srvcli/py_srvcli

将把数值的字符串更改为球体半径


2. 修改服务应答

修改service_member_function.py服务端源文件,涉及服务类型变更和应用变化

from tutorial_interfaces.srv import AddThreeInts  # CHANGE

import rclpy
from rclpy.node import Node


class MinimalService(Node):
    '''
    服务端节点类
    '''
    def __init__(self):
        # 初始化节点
        super().__init__('minimal_service')

        # 初始化服务端,服务类型AddThreeInts,服务add_three_ints,回调函数add_three_ints_callback
        self.srv = self.create_service(AddThreeInts, 'add_three_ints', self.add_three_ints_callback)  # CHANGE

    def add_three_ints_callback(self, request, response):                                                  # CHANGE
        '''
        服务端回调函数
        '''
        # 从请求request中添加两个整数,并将总和提供给响应response
        response.sum = request.a + request.b + request.c                                                   # CHANGE
        self.get_logger().info('Incoming request\na: %d b: %d c: %d' % (request.a, request.b, request.c))  # CHANGE
        return response


def main():
    # 初始化ROS2
    rclpy.init()

    # 创建服务端节点
    minimal_service = MinimalService()

    # 运行服务端节点
    rclpy.spin(minimal_service)

    # 退出ROS2
    rclpy.shutdown()


if __name__ == '__main__':
    main()

3. 修改服务请求

修改client_member_function.py客户端源文件,涉及服务类型变更和应用变化
和修改等待应答的方式

import sys

from tutorial_interfaces.srv import AddThreeInts  # CHANGE
import rclpy
from rclpy.node import Node


class MinimalClientAsync(Node):
    '''
    客户端节点类
    '''
    def __init__(self):
        # 初始化节点
        super().__init__('minimal_client_async')

        # 初始化客户端,服务类型AddThreeInts,服务add_three_ints
        self.cli = self.create_client(AddThreeInts, 'add_three_ints')  # CHANGE

        # 搜索服务节点,间隔1s
        while not self.cli.wait_for_service(timeout_sec=1.0):
            self.get_logger().info('service not available, waiting again...')

        # 定义请求
        self.req = AddThreeInts.Request()  # CHANGE

    def send_request(self, a, b, c):
        '''
        请求发送函数
        '''
        self.req.a = a
        self.req.b = b
        self.req.c = c  # CHANGE
        # 发送请求
        self.future = self.cli.call_async(self.req)

        # CHANGE
        # 等待至发送请求得到应答
        # rclpy.spin_until_future_complete(self, self.future)
        # 返回应答结果
        # return self.future.result()


def main():
    # 初始化ROS2
    rclpy.init()

    # 创建客户端节点
    minimal_client = MinimalClientAsync()

    # 请求发送
    minimal_client.send_request(int(sys.argv[1]), int(sys.argv[2]), int(sys.argv[3]))  # CHANGE

    # CHANGE
    # 循环等待应答
    while rclpy.ok():
        # 非阻塞处理回调函数
        rclpy.spin_once(minimal_client)

        # 检测是否收到应答完成服务
        if minimal_client.future.done():
            try:
                # 应答结果
                response = minimal_client.future.result()
            except Exception as e:
                # 显示异常
                minimal_client.get_logger().info('Service call failed %r' % (e,))
            else:
                # 显示请求-应答状态
                minimal_client.get_logger().info(
                    'Result of add_three_ints: for %d + %d + %d = %d' %                                # CHANGE
                    (minimal_client.req.a, minimal_client.req.b, minimal_client.req.c, response.sum))  # CHANGE
            break

    # 销毁节点,退出ROS2
    minimal_client.destroy_node()
    rclpy.shutdown()


if __name__ == '__main__':
    main()

4. 修改依赖关系

package.xml清单文件中,添加对自定义服务的依赖项的声明

<exec_depend>tutorial_interfaces</exec_depend>

Python源文件应用不涉及到CMake编译信息,因此不用修改CMakeLists.txt编译文件

setup.py安装软件包说明的程序入口点entry_points字段在之前已经设置完成

entry_points={
    'console_scripts': [
        'service = py_srvcli.service_member_function:main',
        'client = py_srvcli.client_member_function:main',
    ],
},

5. 编译和运行

进入工作空间根目录

cd ~/ros2_ws

编译:

colcon build --packages-select py_srvcli

打开一个新终端,运行服务端节点准备应答:

ros2 run py_srvcli service

打开一个新终端,运行客户端节点发送请求:

ros2 run py_srvcli client 1 2 3

# [INFO] [minimal_client_async]: Result of add_three_ints: for 1 + 2 + 3 = 6

谢谢