четверг, 3 августа 2017 г.

ROS. Сервисы

Наряду с нодами, ROS предоставляет ещё один тип программ, называемый сервисами. Их главное отличие заключается в способе общения. Если нода посылает сообщение на топик и не заботится о том, получил ли его кто-нибудь, то при обращении к сервису нужно указать конкретно, к какому именно. Кроме того, сервис возвращает своему клиенту ответ, так что связь оказывается двусторонней и направленной. Как следует из названия, данный тип программ введён для выполнения вспомогательных действий и оказания услуг. Если провести аналогию с вокзалом, топик - это информационное табло отправления/прибытия поездов (оператор публикует актуальную информацию, пассажир идёт в нужное время на требуемый путь), а сервисом будет являться покупка билета или обращение в справочное окно.

Сервис подразумевает наличие клиента и сервера. Клиент отправляет запрос (request), а сервер возвращает ответ (response). Список доступных в данный момент сервисов можно получить по команде 

   rosservice list

Связанные с конкретным запущенным нодом сервисы отображаются в разделе "Services" по запросу

   rosnode info имя_нода

Можно также узнать, к чему относится конкретный сервис. Для этого служит команда 

   rosservice node имя_сервиса

Общение происходит с помощью специальных сообщений. Узнать тип данных конкретного сервиса можно с помощью запроса 

   rosservice info имя_сервиса

Для описания сообщения служит команда, аналогичная rosmsg:

   rossrv show тип_сообщения

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

   rosservice call имя_сервиса запрос

Например, 

   rosservice call /spawn 3 3 0 Mikey 

поместит черепаху Mikey в положение x=3, y=3 под углом theta=0.

Попробуем по примеру из официального руководства создать свой сервис, который складывает 2 целых числа. Прежде всего, нам понадобится новый тип сообщения, включающий оба слагаемых и их сумму, а также папка, где должны располагаться все сервисные сообщения (в ROS она должна называться srv). 

   roscd ros_test
   mkdir srv

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

   roscp rospy_tutorials AddTwoInts.srv srv/AddTwoInts.srv

При работе с rospy от пользователя в большинстве случаев не требуется каких-либо дополнительных действий, кроме создания исполняемых файлов, но сервисы являются исключением. Во-первых, в файле package.xml необходимо добавить строки 

   <build_depend>message_generation</build_depend>
   <run_depend>message_runtime</run_depend>

которые объявляют зависимости пакета на этапе сборки и выполнения. После этого необходимо отредактировать файл CMakeLists.txt. Во-первых, нужно дополнить find_rospackage:

   find_rospackage(catkin REQUIRED COMPONENTS
      rospy
      std_msgs
      message_generation
   )

Во-вторых, найти, раскомментировать add_service_files, и указать тип сообщения 

   add_service_files(
      FILES
      AddTwoInts.srv
   )

В третьих, раскомментировать строки 

   generate_messages(
      DEPENDENCIES
      std_msgs
   )

После сохранения изменений переходим в основную директорию и выполняем сборку

   cd ../..
   catkin_make install
   rosmake ros_test

В результате ROS подготовит файлы для работы с Python, C++, Lisp и, возможно, чем-то ещё. После этого можно переходить к коду.

Ниже приведён код сервера add_server.py. Используемые для обмена сообщения импортируются из ros_test.srv. При запуске программы функция add_two_ints_server() создаёт ноду, но помимо неё определяется сервис, для которого указываются тип сообщения и функция, которая вызывается при обращении. rospy.spin() обеспечивает возможность многократного обращения к сервису. В данном случае, при получении запроса функция handle_add_two_ints() вычисляет сумму переданных чисел, выводит результат на экран и возвращает его клиенту (AddTwoIntsRepsonse() была сгенерирована системой автоматически при выполнении предыдущих команд).


Работа клиента начинается с проверки корректности вызова. Если всё верно, запускается функция add_two_ints_client(), которая ожидает появление сервиса 'add_two_ints', после чего отправляет запрос на выполнение требуемой операции (сложения двух чисел), и при получении ответа возвращает результат, который затем печатается на экране.


Остаётся сделать файлы исполняемыми

   chmod +x scripts/add_server.py
   chmod +x scripts/add_client.py

и проверить их работу

   roscore
   rosrun ros_test add_server.py
   rosrun ros_test add_client.py 3 5

Комментариев нет:

Отправить комментарий