Управление политиками качества обслуживания в ROS 2

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

Доступные политики качества обслуживания в ROS 2:

  • History - Режим очереди сообщений

  • Depth - Размер очереди сообщений

  • Reliability - Гарантия доставки сообщений

  • Durability - Постоянство сообщений

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

История и глубина

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

  • "keeplast" - Очередь обработки сообщений имеет максимальный размер, равный Depth значение. Если очередь заполнена, самые старые сообщения отбрасываются, чтобы освободить место для новых таковых.

  • "keepall" - очередь обработки сообщений пытается сохранить все полученные сообщения в очереди до обработки.

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

В ситуациях, когда важно обрабатывать все сообщения, увеличивая Depth значение или использование History,"keepall" рекомендуется.

В этом примере показано, как настроить издателя и подписчика для отправки и приема сообщений облака точек. Издатель Depth равен 20, и для истории абонентов задано значение "keepall". Абонент использует обратный вызов, чтобы построить график метки времени для каждого сообщения, чтобы показать время обработки каждого сообщения. Обработка начальных сообщений занимает больше времени, но все сообщения в конечном счете обрабатываются из очереди.

% Create a publisher to provide sensor data
robotNode = ros2node("/simple_robot");
lidarPub = ros2publisher(robotNode,"/laser_scan","sensor_msgs/PointCloud2",...
    "History","keeplast","Depth",20);

% Create a subscriber representing localization, requiring all scan data
hFig = figure;
hAxesLidar = axes("Parent",hFig);
title("Message Timeline (Keep All)")
localizationSub = ros2subscriber(robotNode,"/laser_scan",...
    @(msg)exampleHelperROS2PlotTimestamps(msg,hAxesLidar),...
    "History","keepall");

% Send messages, simulating an extremely fast sensor
load robotPoseLidarData.mat lidarScans
for iMsg = 1:numel(lidarScans)
    send(lidarPub,lidarScans(iMsg))
end

% Allow messages to arrive, then remove the localization subscriber
pause(3)

Figure contains an axes. The axes with title Message Timeline (Keep All) contains 40 objects of type line, text.

clear localizationSub

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

% Create a subscriber representing user interface display
hFig = figure;
hAxesLidar2 = axes("Parent",hFig);
title("Message Timeline (Keep Last 1)")
scanDisplaySub = ros2subscriber(robotNode,"/laser_scan",...
    @(msg)exampleHelperROS2PlotTimestamps(msg,hAxesLidar2),...
    "History","keeplast","Depth",1);
for iMsg = 1:numel(lidarScans)
    send(lidarPub,lidarScans(iMsg))
end

% Allow messages to arrive, then remove the subscriber and publisher
pause(3)

Figure contains an axes. The axes with title Message Timeline (Keep Last 1) contains 40 objects of type line, text.

clear lidarPub scanDisplaySub

Надежность

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

  • "reliable" - издатель постоянно отправляет сообщение абоненту до тех пор, пока абонент не подтвердит получение сообщения.

  • "besteffort" - Издатель отправляет сообщение только один раз и не подтверждает, что подписчик получает его.

Надежный

A "reliable" Подключение полезно, когда все данные должны быть обработаны, и любые сброшенные сообщения могут повлиять на результат. Этот пример публикует Odometry и использует обратный коллбэк абонента для построения графика положения. Потому что для "reliable" установка, все положения нанесены на рисунок.

% Create a publisher for odometry data
odomPub = ros2publisher(robotNode,"/odom","nav_msgs/Odometry",...
    "Reliability","reliable");

% Create a subscriber for localization
hFig = figure;
hAxesReliable = axes("Parent",hFig);
title("Robot Position (Reliable Connection)")
xlabel("X (m)")
ylabel("Y (m)")
odomPlotSub = ros2subscriber(robotNode,"/odom",...
    @(msg)exampleHelperROS2PlotOdom(msg,hAxesReliable,"ok"),...
    "Reliability","reliable");

% Send messages, simulating an extremely fast sensor
load robotPoseLidarData.mat odomData
for iMsg = 1:numel(odomData)
    send(odomPub,odomData(iMsg))
end

pause(5)    % Allow messages to arrive and be plotted

Figure contains an axes. The axes with title Robot Position (Reliable Connection) contains 40 objects of type line, text.

% Temporarily prevent reliable subscriber from reacting to new messages
odomPlotSub.NewMessageFcn = [];

Лучшие усилия

A "besteffort" Подключение полезно, чтобы избежать влияния на эффективность, если удаленные сообщения приемлемы. Если для издателя задано значение "reliable", и для абонента установлено значение "besteffort"издатель рассматривает это соединение только как требующее "besteffort", и не подтверждает доставку. Связи с "reliable" подписчикам на ту же тему гарантирована доставка от одного и того же издателя.

Этот пример использует "besteffort" абонент, но все равно получает все сообщения из-за низкого влияния на сеть.

hFig = figure;
hAxesBestEffort = axes("Parent",hFig);
title("Message Timeline (Best Effort Connection)")
odomTimingSub = ros2subscriber(robotNode,"/odom",...
    @(msg)exampleHelperROS2PlotTimestamps(msg,hAxesBestEffort),...
    "Reliability","besteffort");
for iMsg = 1:numel(odomData)
    send(odomPub,odomData(iMsg))
end

pause(3)    % Allow messages to arrive and be plotted

Figure contains an axes. The axes with title Message Timeline (Best Effort Connection) contains 40 objects of type line, text.

Совместимость

Обеспечение совместимости является важным фактором при настройке надежности. Абонент с "reliable" для набора опций требуется издатель, соответствующий этому стандарту. Любой "besteffort" издатели не подключаются к "reliable" абонент, поскольку сообщения не гарантируются. В противоположной ситуации "reliable" издатель и "besteffort" абонент действительно подключается, но соединение ведет себя следующим "besteffort" без подтверждения при получении сообщений. Этот пример показывает "besteffort" издатель отправляет сообщения в "besteffort" абонент уже настроен. Опять же, из-за низкого влияния на сеть, "besteffort" соединения достаточно для обработки всех сообщений.

% Reactivate reliable subscriber to show no messages received
odomPlotSub.NewMessageFcn = @(msg)exampleHelperROS2PlotOdom(msg,hAxesReliable,"*r");

% Send messages from a best-effort publisher
bestEffortOdomPub = ros2publisher(robotNode,"/odom","nav_msgs/Odometry",...
    "Reliability","besteffort");
for iMsg = 1:numel(odomData)
    send(bestEffortOdomPub,odomData(iMsg))
end

% Allow messages to arrive, then remove odometry publishers and subscribers
pause(3)    % Allow messages to arrive and be plotted

Figure contains an axes. The axes with title Message Timeline (Best Effort Connection) contains 80 objects of type line, text.

clear odomPub bestEffortOdomPub odomPlotSub odomTimingSub

Долговечность и глубина

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

  • "transientlocal" - Для издателя поддерживаются сообщения, которые уже были отправлены. Если абонент присоединяется к сети с "transientlocal" после этого издатель отправляет постоянные сообщения подписчику.

  • "volatile" - Издатели не сохраняют сообщения после их отправки, и подписчики не запрашивают постоянные сообщения от издателей.

Количество сообщений, сохраненных издателями с "transientlocal" долговечность также контролируется Depth вход. Абоненты запрашивают только количество последних сообщений на основе их индивидуальных Depth настройки. Издатели по-прежнему могут хранить больше сообщений для других подписчиков, чтобы получить больше. Для примера полный список положения робота может быть полезен для визуализации его пути, но алгоритм локализации может быть заинтересован только в последнем известном месте. Этот пример иллюстрирует, что при помощи абонента локализации для отображения текущей позиции и абонента построения графика для отображения всех позиций в очереди.

% Publish robot location information
posePub = ros2publisher(robotNode,"/bot_position","geometry_msgs/Pose2D",...
    "Durability","transientlocal","Depth",100);
load robotPoseLidarData.mat robotPositions
for iMsg = 1:numel(robotPositions)
    send(posePub,robotPositions(iMsg))
    pause(0.2)     % Allow for processing time
end

% Create a localization update subscriber that only needs current position
localUpdateSub = ros2subscriber(robotNode,"/bot_position",@disp,...
    "Durability","transientlocal","Depth",1);
pause(1)    % Allow message to arrive
        x: 0.1047
        y: -2.3168
    theta: -8.5194
% Create a visualization subscriber to show where the robot has been
hFig = figure;
hAxesMoreMsgs = axes("Parent",hFig);
title("Robot Position (Transient Local Connection)")
xlabel("X (m)")
ylabel("Y (m)")
hold on
posePlotSub = ros2subscriber(robotNode,"/bot_position",...
    @(msg)plot(hAxesMoreMsgs,msg.x,msg.y,"ok"),...
    "Durability","transientlocal","Depth",20);
pause(3)    % Allow messages to arrive and be plotted

Figure contains an axes. The axes with title Robot Position (Transient Local Connection) contains 20 objects of type line.

Совместимость

Подобно надежности, несовместимые настройки долговечности могут помешать общению между издателями и подписчиками. Абонент с "transientlocal" для долговечности требуется издатель с "transientlocal" долговечность. Если издатель "volatile", связь не установлена с "transientlocal" абонентов. Если издатель "transientlocal" и абонента "volatile", затем это соединение создается, не отправляя постоянные сообщения абоненту.

% Reset plotting behavior
posePlotSub.NewMessageFcn = @(msg)plot(hAxesMoreMsgs,msg.x,msg.y,"xr");

% Send messages from volatile publisher
volatilePosePub = ros2publisher(robotNode,"/bot_position",...
    "Durability","volatile");
for iMsg = 1:numel(robotPositions)
    send(volatilePosePub,robotPositions(iMsg))
    pause(0.2)     % Allow for processing time
end

Ни одно из сообщений не получено "transientlocal" абонент.

% Remove pose publishers and subscribers
clear posePub volatilePosePub localUpdateSub posePlotSub robotNode