Service. Пример сервера
Эта часть занятий будет сосредоточена в большей степени на практике. Прежде чем мы напишем первый сервис ROS, стоит еще раз посмотреть вводную часть о том, что такое Service в формулировках ROS.
В практической части мы даже сами запускали сервис сложения двух чисел и выполняли тестовые сложения при помощи утилиты rosservice.
Давайте напишем такой же сервис самостоятельно.
Service Server
Используемые типы сообщений
Для того, чтобы упростить нашу работу, мы будем использовать уже созданные сообщения из пакета с примерами rospy_tutorials. Создавать собсвенные сообщения для сервисов мы будем в разделе Администрование ROS.
Сервер - это программа, которая выполняет непосредственно полезную работу. В нашем случае складывает два числа.
Код программы (service_server.py)
import rospy
from rospy_tutorials.srv import AddTwoInts,AddTwoIntsResponse
def sum_function(req):
sum = req.a + req.b
print("Returning [%s + %s = %s]" % (req.a, req.b, sum))
return AddTwoIntsResponse(sum)
rospy.init_node("add_server_node")
s = rospy.Service('add_two_ints', AddTwoInts, sum_function)
rospy.spin()
Начало вполне стандартное - импортируем rospy.
Дальше, по аналогии с топиками, которые требуют импорта используемой в них структуры данных, сервисы тоже требуют импорта структуры данных используемых сообщений.
import rospy
from rospy_tutorials.srv import AddTwoInts,AddTwoIntsResponse
В данном случае это две структуры: AddTwoInts для определения используемых типов запросов выполнения сервиса и AddTwoIntsResponse для объекта ответа с результатом работы.
Давайте быстро посмотрим, из чего они состоят: используем команду rossrv с параметром show, чтобы посмотреть состав структуры. Напишем путь до нашей структуры
rossrv show rospy_tutorials/AddTwoInts
====
int64 a
int64 b
---
int64 sum
Сейчас мы не будем останавливаться подробно на том, почему и как именно записываются структуры данных, просто примем к сведению, что вот эта часть int64 a и int64 b, это запрос к сервису, а вот эта часть, после трех тире - int 64 sum ответ сервиса.
Далее мы реализуем собственно саму "рабочую" функцию сложения. Из листинга выше мы понимаем, что в запросе будут находиться две переменные a и b, которые мы должны сложить.
def sum_function(req):
sum = req.a + req.b
print("Returning [%s + %s = %s]" % (req.a, req.b, sum))
return AddTwoIntsResponse(sum)
Метод сервиса должен вернуть объект, который "понятен" ROS, поэтому мы возвращаем объект AddTwoIntsResponse, а не просто число.
Похожий код мы уже использовали, когда разбирали работу с топиками.
rospy.init_node("add_server_node")
s = rospy.Service('add_two_ints', AddTwoInts, sum_function)
rospy.spin()
Мы инициализируем ноду, создаем сервис с параметрами
- Имя созданного сервиса
add_two_ints - Тип используемых для работы сообщений
AddTwoInts - Функция для обработки полученных запросов
sum_function
И запускаем "вечный" цикл, для того чтобы программа не выходила.
Сохраним и запустим файл
python3 service_server.py
Убедимся, что сервис появился в списке сервисов
rosservice list
/add_two_ints/get_loggers
/add_two_ints/set_logger_level
/add_two_ints
/rosout/get_loggers
/rosout/set_logger_level
Вызовем сервис через терминал и убедимся, что результат суммирования верный.
rosservice call /add_two_ints "a: 2
b: 3"
sum: 5
Можем считать, что мы смогли написать и проверить наш первый сервис, далее мы научимся вызывать этот сервис из программы клиента.