Вызовите и предоставьте услуги ROS

ROS поддерживает два основных коммуникационных механизма: темы и сервисы. Темы имеют издателей и подписчиков и используются для отправки и получения сообщений (см., обмениваются Данными с Издателями ROS и Подписчиками). Сервисы, с другой стороны, реализуют более трудную связь путем разрешения коммуникации ответа запроса. Сервисный клиент отправляет сообщение запроса в сервисный сервер и ожидает ответа. Сервер будет использовать данные в просьбе создать сообщение ответа и передает его обратно клиенту. Каждый сервис имеет тип, который определяет структуру сообщений запроса и ответа. Сервисы также имеют имя, которое уникально в сети ROS.

Эта сервисная коммуникация имеет следующие характеристики:

  • Запрос на обслуживание (или сервисный вызов) используется для непосредственной коммуникации. Один узел будет инициировать запрос, и только один узел получит запрос и передаст ответ обратно.

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

Концепция сервисов проиллюстрирована в следующем изображении:

Этот пример показывает вам, как настроить сервисные серверы, чтобы рекламировать сервис к сети ROS. Кроме того, вы изучите, как использовать сервисные клиенты, чтобы вызвать сервер и получить ответ.

Необходимые условия: Начало работы с ROS, подключением к сети ROS, обмениваются данными с издателями ROS и подписчиками

Создайте сервисный сервер

Прежде, чем исследовать сервисные концепции, запустите ведущее устройство ROS в MATLAB® и демонстрационной сети ROS. exampleHelperROSCreateSampleNetwork создаст некоторые сервисные серверы, чтобы симулировать реалистическую сеть ROS.

rosinit
Launching ROS Core...
...Done in 3.16 seconds.
Initializing ROS master on http://192.168.178.1:55438.
Initializing global node /matlab_global_node_55791 with NodeURI http://ah-csalzber:51640/
exampleHelperROSCreateSampleNetwork

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

Для более быстрой эффективности используйте сервисы с сообщениями в формате структуры.

testserver = rossvcserver("/test","std_srvs/Empty",@exampleHelperROSEmptyCallback,"DataFormat","struct")
testserver = 
  ServiceServer with properties:

      ServiceType: 'std_srvs/Empty'
      ServiceName: '/test'
    NewRequestFcn: @exampleHelperROSEmptyCallback
       DataFormat: 'struct'

Вы видите свой новый сервис, /test, когда вы перечисляете все сервисы в сети ROS.

rosservice list
/add
/matlab_global_node_55791/get_loggers
/matlab_global_node_55791/set_logger_level
/node_1/get_loggers
/node_1/set_logger_level
/node_2/get_loggers
/node_2/set_logger_level
/node_3/get_loggers
/node_3/set_logger_level
/reply
/test

Можно получить больше информации о сервисном использовании rosservice info. Глобальный узел перечислен как узел, где сервисный сервер достижим, и вы также видите его std_srvs/Empty сервисный тип.

rosservice info /test
Node: /matlab_global_node_55791
URI: rosrpc://ah-csalzber:51639
Type: std_srvs/Empty
Args: MessageType

Создайте сервисный клиент

Используйте сервисные клиенты, чтобы запросить информацию у сервисного сервера ROS. Чтобы создать клиент, использовать rossvcclient с сервисом называют как аргумент.

Создайте сервисный клиент для /test сервис, который мы только создали.

testclient = rossvcclient("/test","DataFormat","struct")
testclient = 
  ServiceClient with properties:

    ServiceType: 'std_srvs/Empty'
    ServiceName: '/test'
     DataFormat: 'struct'

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

testreq = rosmessage(testclient)
testreq = struct with fields:
    MessageType: 'std_srvs/EmptyRequest'

Убедитесь, что сервис соединяется с клиентом, ожидающим их, чтобы соединиться при необходимости.

waitForServer(testclient,"Timeout",3)

Когда это необходимо, чтобы получить ответ от сервера, используйте call функция, которая вызывает сервисный сервер и возвращает ответ. Сервисный сервер, который вы создали прежде, возвратит пустой ответ. Кроме того, это вызовет exampleHelperROSEmptyCallback функционируйте и отображается, строка "Сервисный клиент вызывает". Можно также задать Timeout параметр, который указывает, сколько времени клиент должен ожидать ответа.

testresp = call(testclient,testreq,"Timeout",3);

Если вызов будет функционировать выше сбоев, он будет ошибка. Вместо ошибки, если вы предпочли бы реагировать на отказ вызова с помощью условных выражений, возвращают status и statustext выходные параметры от функции вызова. status выведите указывает если вызов, за которым следуют, в то время как statustext предоставляет дополнительную информацию. Подобные выходные параметры могут быть возвращены waitForServer.

numCallFailures = 0;
[testresp,status,statustext] = call(testclient,testreq,"Timeout",3);
if ~status
    numCallFailures = numCallFailues + 1;
    fprintf("Call failure number %d. Error cause: %s\n",numCallFailures,statustext)
else
    disp(testresp)
end
    MessageType: 'std_srvs/EmptyResponse'

Создайте сервис для добавления двух чисел

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

Существует существующий сервисный тип, roscpp_tutorials/TwoInts, то, что мы можем использовать для этой задачи. Можно смотреть структуру сообщений запроса и ответа путем вызова rosmsg show. Запрос содержит два целых числа, A и B, и ответ содержит их сложение в Sum.

rosmsg show roscpp_tutorials/TwoIntsRequest
int64 A
int64 B
rosmsg show roscpp_tutorials/TwoIntsResponse
int64 Sum

Создайте сервисный сервер с этим типом сообщения и функцией обратного вызова, которая вычисляет сложение. Для вашего удобства, exampleHelperROSSumCallback функционируйте уже реализует это вычисление. Задайте функцию как коллбэк.

sumserver = rossvcserver("/sum","roscpp_tutorials/TwoInts",@exampleHelperROSSumCallback,"DataFormat","struct")
sumserver = 
  ServiceServer with properties:

      ServiceType: 'roscpp_tutorials/TwoInts'
      ServiceName: '/sum'
    NewRequestFcn: @exampleHelperROSSumCallback
       DataFormat: 'struct'

Чтобы вызвать сервисный сервер, необходимо создать сервисный клиент. Обратите внимание на то, что этот клиент может быть создан где угодно в сети ROS. В целях этого примера мы создадим клиент для /sum сервис в MATLAB.

sumclient = rossvcclient("/sum","DataFormat","struct")
sumclient = 
  ServiceClient with properties:

    ServiceType: 'roscpp_tutorials/TwoInts'
    ServiceName: '/sum'
     DataFormat: 'struct'

Создайте сообщение запроса. Можно задать эти два целых числа, A и B, которые добавляются вместе, когда вы используете call команда.

sumreq = rosmessage(sumclient);
sumreq.A = int64(2);
sumreq.B = int64(1)
sumreq = struct with fields:
    MessageType: 'roscpp_tutorials/TwoIntsRequest'
              A: 2
              B: 1

Ожидание состоит в том, что сумма этих двух чисел будет 3. Чтобы вызвать сервис, используйте следующую команду. Сервисное сообщение ответа будет содержать Sum свойство, которое хранит сложение A и B. Убедитесь, что сервисный сервер доступен перед звонком, и реагируйте соответственно, если это не.

if isServerAvailable(sumclient)
    sumresp = call(sumclient,sumreq,"Timeout",3)
else
    error("Service server not available on network")
end
sumresp = struct with fields:
    MessageType: 'roscpp_tutorials/TwoIntsResponse'
            Sum: 3

Закройте сеть ROS

Удалите демонстрационные узлы и сервисные серверы от сети ROS.

exampleHelperROSShutDownSampleNetwork

Закройте ведущее устройство ROS и удалите глобальный узел.

rosshutdown
Shutting down global node /matlab_global_node_55791 with NodeURI http://ah-csalzber:51640/
Shutting down ROS master on http://192.168.178.1:55438.

Следующие шаги