Работа с базовыми сообщениями ROS 2

Сообщения ROS являются основным контейнером для обмена данными в ROS 2. Издатели и подписчики обмениваются данными с помощью сообщений по заданным темам для переноса данных между узлами. Для получения дополнительной информации об отправке и получении сообщений см. раздел Обмен данными с издателями и подписчиками ROS 2.

Для идентификации структуры данных каждое сообщение имеет тип сообщения. Для примера данные датчика от лазерного сканера обычно отправляются в сообщении типа sensor_msgs/LaserScan. Каждый тип сообщения определяет элементы данных, содержащиеся в сообщении. Каждое имя типа сообщения представляет собой комбинацию имени пакета, за которой следует косая черта/и имя типа:

MATLAB ® поддерживает многие типы сообщений ROS 2, которые обычно встречаются в приложениях робототехники. В этом примере рассматриваются некоторые способы создания, просмотра и заполнения сообщений ROS 2 в MATLAB.

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

Поиск типов сообщений

Использование exampleHelperROS2CreateSampleNetwork заполнение сети ROS 2 тремя узлами и настройка выборочных издателей и подписчиков по конкретным темам.

exampleHelperROS2CreateSampleNetwork

Использование ros2 topic list -t для поиска доступных тем и связанных с ними типов сообщений.

ros2 topic list -t
            Topic                       MessageType           
    _____________________    _________________________________

    {'/parameter_events'}    {'rcl_interfaces/ParameterEvent'}

Чтобы узнать больше о типе сообщения темы, используйте ros2message для создания пустого сообщения того же типа. ros2message поддерживает заполнение клавишей Tab для типа сообщения. Чтобы быстро заполнить имена типов сообщений, введите первые несколько символов имени, которое вы хотите заполнить, и нажмите клавишу Tab.

scanData = ros2message("sensor_msgs/LaserScan")
scanData = struct with fields:
        MessageType: 'sensor_msgs/LaserScan'
             header: [1x1 struct]
          angle_min: 0
          angle_max: 0
    angle_increment: 0
     time_increment: 0
          scan_time: 0
          range_min: 0
          range_max: 0
             ranges: 0
        intensities: 0

Созданное сообщение, scanData, имеет много полей, связанных с данными, которые вы обычно получали от лазерного сканера. Для примера минимальное расстояние измерения сохранено в range_min свойство и максимальное расстояние измерения в range_max свойство.

Теперь можно удалить созданное сообщение.

clear scanData

Чтобы просмотреть полный список всех типов сообщений, доступных для тем и служб, используйте ros2 msg list.

Исследуйте структуру сообщений и получите данные сообщений

Сообщения ROS 2 представлены в виде структур, и данные сообщения хранятся в полях. MATLAB предоставляет удобные способы поиска и исследования содержимого сообщений.

Использование ros2 msg show для просмотра определения типа сообщения.

ros2 msg show geometry_msgs/Twist
# This expresses velocity in free space broken into its linear and angular parts.

Vector3  linear
Vector3  angular

Если вы подписываетесь на /pose Вы можете получать и просматривать отправленные сообщения.

controlNode = ros2node("/base_station");
poseSub = ros2subscriber(controlNode,"/pose","geometry_msgs/Twist")
poseSub = 
  ros2subscriber with properties:

        TopicName: '/pose'
    LatestMessage: []
      MessageType: 'geometry_msgs/Twist'
    NewMessageFcn: []
          History: 'keeplast'
            Depth: 10
      Reliability: 'reliable'
       Durability: 'volatile'

Использование receive для получения данных от абонента. После получения нового сообщения функция возвращает его и сохраняет в posedata переменная. Задайте тайм-аут 10 секунд для приема сообщений.

poseData = receive(poseSub,10)
poseData = struct with fields:
    MessageType: 'geometry_msgs/Twist'
         linear: [1x1 struct]
        angular: [1x1 struct]

Сообщение имеет тип geometry_msgs/Twist. В сообщении есть два других поля: linear и angular. Значения этих полей сообщений можно просмотреть путем непосредственного доступа к ним.

poseData.linear
ans = struct with fields:
    MessageType: 'geometry_msgs/Vector3'
              x: 0.0457
              y: -0.0015
              z: 0.0300

poseData.angular
ans = struct with fields:
    MessageType: 'geometry_msgs/Vector3'
              x: -0.0358
              y: -0.0078
              z: 0.0416

Можно увидеть, что каждое из значений этих полей сообщения фактически само по себе является сообщением. geometry_msgs/Twist является составным сообщением, состоящим из двух geometry_msgs/Vector3 сообщений.

Доступ к данным для этих вложенных сообщений работает в точности так же, как и доступ к данным в других сообщениях. Доступ к x компонент linear сообщение с помощью этой команды:

xPose = poseData.linear.x
xPose = 0.0457

Установка данных сообщений

Можно также задать значения свойств сообщения. Создайте сообщение с типом geometry_msgs/Twist.

twist = ros2message("geometry_msgs/Twist")
twist = struct with fields:
    MessageType: 'geometry_msgs/Twist'
         linear: [1x1 struct]
        angular: [1x1 struct]

Числовые свойства этого сообщения инициализируются в 0 по умолчанию. Можно изменить любые свойства этого сообщения. Установите inear.y l поле до 5.

twist.linear.y = 5;

Можно просмотреть данные сообщения, чтобы убедиться, что ваше изменение вступило в эффект.

twist.linear
ans = struct with fields:
    MessageType: 'geometry_msgs/Vector3'
              x: 0
              y: 5
              z: 0

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

Копирование сообщений

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

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

tempMsgBlank = ros2message("sensor_msgs/Temperature");
tempMsgCopy = tempMsgBlank
tempMsgCopy = struct with fields:
    MessageType: 'sensor_msgs/Temperature'
         header: [1x1 struct]
    temperature: 0
       variance: 0

Измените temperature свойство tempMsg и заметьте, что содержимое tempMsgBlank оставить без изменений.

tempMsgCopy.temperature = 100
tempMsgCopy = struct with fields:
    MessageType: 'sensor_msgs/Temperature'
         header: [1x1 struct]
    temperature: 100
       variance: 0

tempMsgBlank
tempMsgBlank = struct with fields:
    MessageType: 'sensor_msgs/Temperature'
         header: [1x1 struct]
    temperature: 0
       variance: 0

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

thermometerNode = ros2node("/thermometer");
tempPub = ros2publisher(thermometerNode,"/temperature","sensor_msgs/Temperature");
tempMsgs(10) = tempMsgBlank;    % Pre-allocate message structure array
for iMeasure = 1:10
    % Copy blank message fields
    tempMsgs(iMeasure) = tempMsgBlank;
    
    % Record sample temperature
    tempMsgs(iMeasure).temperature = 20+randn*3;
    
    % Only calculate the variation once sufficient data observed
    if iMeasure >= 5
        tempMsgs(iMeasure).variance = var([tempMsgs(1:iMeasure).temperature]);
    end
    
    % Pass the data to subscribers
    send(tempPub,tempMsgs(iMeasure))
end
errorbar([tempMsgs.temperature],[tempMsgs.variance])

Figure contains an axes. The axes contains an object of type errorbar.

Сохранение и загрузка сообщений

Можно сохранять сообщения и хранить содержимое для дальнейшего использования.

Получите новое сообщение от абонента.

poseData = receive(poseSub,10)
poseData = struct with fields:
    MessageType: 'geometry_msgs/Twist'
         linear: [1x1 struct]
        angular: [1x1 struct]

Сохраните данные положения в файл MAT с помощью save функция.

save("poseFile.mat","poseData")

Перед загрузкой файла обратно в рабочую область очистите poseData переменная.

clear poseData

Теперь вы можете загрузить данные сообщения, позвонив load функция. Это загружает poseData сверху в messageData структура. poseData - поле данных struct.

messageData = load("poseFile.mat")
messageData = struct with fields:
    poseData: [1x1 struct]

Исследуйте messageData.poseData для просмотра содержимого сообщения.

messageData.poseData
ans = struct with fields:
    MessageType: 'geometry_msgs/Twist'
         linear: [1x1 struct]
        angular: [1x1 struct]

Теперь можно удалить файл MAT.

delete("poseFile.mat")

Отсоединение от сети ROS 2

Удалите примеры узлов, издателей и подписчиков из сети ROS 2.

exampleHelperROS2ShutDownSampleNetwork

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