Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Создание сервисов (Python)

Что вы узнаете в этом разделе:

  • Как создать сервер сервиса на Python
  • Структуру программы-сервера в ROS2
  • Как обрабатывать запросы и формировать ответы
  • Как найти подходящие типы сообщений для сервисов
  • Как протестировать работу сервиса через консоль
  • Основные методы работы с сервисами в rclpy

Пример Сервиса (Service) на Python

Рассмотрим создание простого сервиса, который будет складывать два числа. Клиент отправляет два числа, которые необходимо сложить, в сервер производит сложение и возвращает результат сложения.

Такую программу, можно считать "каноничной" демонстрацией работы сервиса. Также данный пример нам удобно реализовать, так как сообщения для такой программы уже созданы, и нам не нужно их создавать.

Найдем подходящие нам сообщения для сервиса. Используем дополнительный ключ --only-srvs, для того, чтобы получить только сервисы

ros2 interface list --only-srvs
===
    action_msgs/srv/CancelGoal
....
    example_interfaces/srv/AddTwoInts
    example_interfaces/srv/SetBool
    example_interfaces/srv/Trigger
....    

Необходимое нам сообщение example_interfaces/srv/AddTwoInts рассмотрим его структуру.

ros2 interface show example_interfaces/srv/AddTwoInts
int64 a
int64 b
---
int64 sum

До символов --- мы видим описание Запроса (переменные a и b, тип int64), а после идет Ответ (int64 sum)

Создадим сервер (Service server)

Сервер должен "постоянно" работать, ожидая запрос. При получении запроса, необходимо сложить два числа, и вернуть результат операции.

Создадим файл chapter6/minimal-service.py

from example_interfaces.srv import AddTwoInts

import rclpy
from rclpy.node import Node


class MinimalService(Node):

    def __init__(self):
        super().__init__('minimal_service')
        self.srv = self.create_service(AddTwoInts, 'add_two_ints', self.add_two_ints_callback)
        self.get_logger().info("Service AddTwoInts is ready")

    def add_two_ints_callback(self, request, response):
        response.sum = request.a + request.b
        self.get_logger().info('Incoming request\na: %d b: %d' % (request.a, request.b))

        return response

def main(args=None):
    
    rclpy.init(args=args)
    minimal_service = MinimalService()
    
    try:
        rclpy.spin(minimal_service)
    except KeyboardInterrupt:
        pass

if __name__ == '__main__':
    main()

Скелет программы аналогичен тому, с которым мы работали с топиками.

В начале, мы импортируем библиотеки ROS и сообщение сервиса AddTwoInts

from example_interfaces.srv import AddTwoInts

import rclpy
from rclpy.node import Node

Блок "запуска" ноды, также аналогичен рассмотренным ранее, поменялось только имя созданного класса.

def main(args=None):
    
    rclpy.init(args=args)
    minimal_service = MinimalService()
    
    try:
        rclpy.spin(minimal_service)
    except KeyboardInterrupt:
        pass
    
if __name__ == '__main__':
    main()

Рассмотрим с комментариями тело самой программы. Методы инициализации __init__(self) и основной рабочий метод сервиса add_two_ints_callback

    def __init__(self):
        #Инициализируем ноду
        super().__init__('minimal_service')
        #Создаем сервис. Указав параметры
        # `AddTwoInts` Тип сервиса
        # `add_two_ints` Название сервиса
        # `add_two_ints_callback` Имя функции, которую необходимо запустить 
        # когда поступи Запрос от Клинта
        self.srv = self.create_service(AddTwoInts, 'add_two_ints', self.add_two_ints_callback)
    
    # Функция "реализатор" сервиса, выполняет сложение
    def add_two_ints_callback(self, request, response):
        #Операция сложения, где
        #request - объект из Запроса
        #response - объект Ответа
        response.sum = request.a + request.b
        
        self.get_logger().info(f'Incoming request a: {request.a} b: {request.b}')

        #Возврат ответа (суммы)
        return response

Запустим нашу программу

python3 ./minimal-service.py
[INFO] [1758020610.453802380] [minimal_service]: Service AddTwoInts is ready

Мы видим, что сервис запустился, и программа ожидает запросы.

Найдем наш сервис

ros2 service list | grep add
===
/add_two_ints

Наш сервис появился в списке. Используя CLI, создадим запрос к сервису.

ros2 service call /add_two_ints example_interfaces/srv/AddTwoInts '{"a": 1, "b": 5}'
===
waiting for service to become available...
requester: making request: example_interfaces.srv.AddTwoInts_Request(a=1, b=5)

response:
example_interfaces.srv.AddTwoInts_Response(sum=6)

Мы видим формирование запроса (a=1, b=5) и получения результата (sum=6)

В консоле, где работает программа сервер, мы видим вывод сообщение, что получен запрос с параметрами a: 1 b: 5

[INFO] [1758020904.243744414] [minimal_service]: Incoming request
a: 1 b: 5

Мы удостоверились, что программа работает верно, и мы можем использую CLI протестировать ее.