Управляйте качеством обслуживаний в 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 object. The axes object 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 object. The axes object with title Message Timeline (Keep Last 1) contains 40 objects of type line, text.

clear lidarPub scanDisplaySub

Надежность

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

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

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

Надежный

"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 object. The axes object with title Robot Position (Reliable Connection) contains 40 objects of type line, text.

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

Максимальные усилия

"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 object. The axes object 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 object. The axes object 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 object. The axes object 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