Обмен данными с ROS-издателями и подписчиками

Основным механизмом обмена данными между узлами ROS является отправка и прием сообщений. Сообщения передаются по теме, и каждая тема имеет уникальное имя в сети ROS. Если узел хочет поделиться информацией, он использует издателя для отправки данных в раздел. Узел, который хочет получить эту информацию, использует абонента в той же теме. Помимо своего уникального имени, каждая тема также имеет тип сообщения, который определяет типы сообщений, которые могут передаваться по этой теме.

Данная коммуникация издателя и абонента имеет следующие характеристики:

  • Темы используются для общения «многие ко многим». Многие издатели могут отправлять сообщения на ту же тему и многие подписчики могут их получать.

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

Концепция тем, издателей и подписчиков проиллюстрирована на рисунке:

В этом примере показано, как публиковать и подписываться на темы в сети ROS. Также показано, как:

  • Подождите получения нового сообщения

  • Используйте коллбэки для обработки новых сообщений в фоновом режиме

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

Подписка и ожидание сообщений

Запустите мастер ROS в MATLAB ® с помощью rosinit команда.

rosinit
Launching ROS Core...
Done in 0.84361 seconds.
Initializing ROS master on http://192.168.0.10:49966.
Initializing global node /matlab_global_node_39840 with NodeURI http://bat6315glnxa64:41167/

Создайте пример сети ROS с несколькими издателями и подписчиками, используя предоставленную функцию helper exampleHelperROSCreateSampleNetwork.

exampleHelperROSCreateSampleNetwork

Использовать rostopic list чтобы увидеть, какие темы доступны.

rostopic list
/pose  
/rosout
/scan  
/tf    

Использование rostopic info проверить, публикуются ли какие-либо узлы в /scan тема. Команда ниже показывает, что node_3 публикуется к нему.

rostopic info /scan
Type: sensor_msgs/LaserScan
 
Publishers:
* /node_3 (http://bat6315glnxa64:46535/)
 
Subscribers:
* /node_1 (http://bat6315glnxa64:39337/)
* /node_2 (http://bat6315glnxa64:35615/)

Использовать rossubscriber подписаться на /scan тема. Если тема уже существует в сети ROS (как это происходит здесь), rossubscriber определяет его тип сообщения автоматически, поэтому вам не нужно указывать его.

laser = rossubscriber('/scan');
pause(2)

Использовать receive чтобы дождаться нового сообщения. (Второй аргумент - тайм-аут в секундах.) Область выхода scandata содержит полученные данные сообщения.

scandata = receive(laser,10)
scandata = 
  ROS LaserScan message with properties:

       MessageType: 'sensor_msgs/LaserScan'
            Header: [1x1 Header]
          AngleMin: -0.5216
          AngleMax: 0.5243
    AngleIncrement: 0.0016
     TimeIncrement: 0
          ScanTime: 0.0330
          RangeMin: 0.4500
          RangeMax: 10
            Ranges: [640x1 single]
       Intensities: [0x1 single]

  Use showdetails to show the contents of the message

С некоторыми типами сообщений связаны визуализаторы. Для сообщения LaserScan, rosPlot строит графики данных скана. The MaximumRange Пара "имя-значение" задает максимальную область значений графика.

figure
plot(scandata,'MaximumRange',7)

Figure contains an axes. The axes with title Laser Scan contains an object of type line.

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

Вместо использования receive для получения данных можно задать функцию, которая будет вызываться при получении нового сообщения. Это позволяет выполнять другой код MATLAB во время ожидания абонентом новых сообщений. Коллбэки необходимы, если вы хотите использовать несколько абонентов.

Подпишитесь на /pose topic, использование функции обратного вызова exampleHelperROSPoseCallback.

robotpose = rossubscriber('/pose',@exampleHelperROSPoseCallback)
robotpose = 
  Subscriber with properties:

        TopicName: '/pose'
    LatestMessage: [0x1 Twist]
      MessageType: 'geometry_msgs/Twist'
       BufferSize: 1
    NewMessageFcn: @exampleHelperROSPoseCallback
       DataFormat: 'object'

Одним из способов обмена данными между вашей основной рабочей областью и функцией обратного вызова является использование глобальных переменных. Задайте две глобальные переменные pos и orient.

global pos
global orient

Глобальные переменные pos и orient назначаются в exampleHelperROSPoseCallback функция, когда новые данные сообщения получены на /pose тема.

Подождите несколько секунд, чтобы убедиться, что абонент может получать сообщения. Самые актуальные данные о положении и ориентации всегда будут храниться в pos и orient переменные.

pause(2) 
pos
pos = 1×3

   -0.1612   -0.2381    0.0105

orient
orient = 1×3

   -0.2323    0.2905    0.1572

Если вы вводите pos и orient несколько раз в командной строке можно увидеть, что значения постоянно обновляются.

Остановите абонента положения путем очистки переменной абонента

clear robotpose

Примечание: Существуют другие способы извлечения информации из функций обратного вызова, помимо использования globals. Для примера можно передать объект указателя в качестве дополнительного аргумента в функцию обратного вызова. Для получения дополнительной информации об определении функций обратного вызова см. документацию «Определение обратного вызова».

Публикация сообщений

Создайте издателя, который отправляет строковые сообщения ROS в /chatter тема (см. «Работа с базовыми сообщениями ROS»).

chatterpub = rospublisher('/chatter','std_msgs/String')
chatterpub = 
  Publisher with properties:

         TopicName: '/chatter'
    NumSubscribers: 0
        IsLatching: 1
       MessageType: 'std_msgs/String'
        DataFormat: 'object'

pause(2) % Wait to ensure publisher is registered

Создайте и заполните ROS-сообщение для отправки в /chatter тема.

chattermsg = rosmessage(chatterpub);
chattermsg.Data = 'hello world'
chattermsg = 
  ROS String message with properties:

    MessageType: 'std_msgs/String'
           Data: 'hello world'

  Use showdetails to show the contents of the message

Использование rostopic list чтобы проверить, что /chatter тема доступна в сети ROS.

rostopic list
/chatter
/pose   
/rosout 
/scan   
/tf     

Определите абонента для /chatter тема. exampleHelperROSChatterCallback вызывается при получении нового сообщения и отображает строку содержимое сообщения.

chattersub = rossubscriber('/chatter', @exampleHelperROSChatterCallback)
chattersub = 
  Subscriber with properties:

        TopicName: '/chatter'
    LatestMessage: [0x1 String]
      MessageType: 'std_msgs/String'
       BufferSize: 1
    NewMessageFcn: @exampleHelperROSChatterCallback
       DataFormat: 'object'

Опубликовать сообщение в /chatter тема. Строка отображается при коллбэк абонента.

send(chatterpub,chattermsg)
pause(2)
ans = 
'hello world'

The exampleHelperROSChatterCallback функция была вызвана сразу после публикации строкового сообщения.

Завершите работу сети ROS

Удалите примеры узлов, издателей и подписчиков из сети ROS. Очистите глобальные переменные pos и orient.

exampleHelperROSShutDownSampleNetwork
clear global pos orient

Завершите работу хозяина ROS и удалите глобальный узел.

rosshutdown
Shutting down global node /matlab_global_node_39840 with NodeURI http://bat6315glnxa64:41167/
Shutting down ROS master on http://192.168.0.10:49966.

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