Работа с основными сообщениями 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:
             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:
     linear: [1x1 struct]
    angular: [1x1 struct]

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

poseData.linear
ans = struct with fields:
    x: 0.0457
    y: -0.0015
    z: 0.0300

poseData.angular
ans = struct with fields:
    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:
     linear: [1x1 struct]
    angular: [1x1 struct]

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

twist.linear.y = 5;

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

twist.linear
ans = struct with fields:
    x: 0
    y: 5
    z: 0

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

Скопируйте сообщения

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

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

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

Измените the temperature свойство tempMsg и уведомления, что содержимое tempMsgBlank останьтесь неизменными.

tempMsgCopy.temperature = 100
tempMsgCopy = struct with fields:
         header: [1x1 struct]
    temperature: 100
       variance: 0

tempMsgBlank
tempMsgBlank = struct with fields:
         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])

Сохраните и загрузите сообщения

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

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

poseData = receive(poseSub,10)
poseData = struct with fields:
     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:
     linear: [1x1 struct]
    angular: [1x1 struct]

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

delete("poseFile.mat")

Отключитесь от сети ROS 2

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

exampleHelperROS2ShutDownSampleNetwork

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