exponenta event banner

Предупреждение о столкновении с помощью 2-D Lidar

Этот пример показывает, как обнаружить препятствия и предупредить о возможных столкновениях, используя 2-е данные о лидаре.

Обзор

Логистические склады все чаще монтируют 2-D лидары на автоматических управляемых автомобилях (AGV) в навигационных целях из-за доступности, большой дальности и высокой разрешающей способности датчика. Датчики помогают обнаруживать столкновения, что является важной задачей для безопасной навигации AGV в сложных средах. Этот пример шоу, как представлять рабочее пространство робота, населенное с препятствиями, произведите 2-е данные о лидаре, обнаружьте препятствия и обеспечьте предупреждение перед нависшим столкновением.

Создание карты склада

Чтобы представить среду рабочего пространства робота, определите binaryOccupancyMap(Панель инструментов навигации), содержащий план этажа склада. Каждая ячейка в сетке занятости имеет логическое значение. Занятое место представлено как 1, а свободное - как 0. Вы можете использовать информацию о занятии, чтобы произвести синтетические 2-е данные о лидаре.

Добавьте препятствия на карте рядом с определенным маршрутом AGV.

% Create a binary warehouse map and place obstacles at defined locations
map = helperCreateBinaryOccupancyMap;

% Visualize map with obstacles and AGV
figure
show(map)
title('Warehouse Floor Plan With Obstacles and AGV')

% Add AGV to the map
pose = [5 40 0];
helperPlotRobot(gca, pose);

Figure contains an axes. The axes with title Warehouse Floor Plan With Obstacles and AGV contains 2 objects of type image, patch.

Моделируйте 2-й датчик лидара

Моделируйте 2-й датчик лидара, используя a rangeSensor объект для сбора показаний лидара для создаваемой карты. Загрузите MAT-файл, содержащий предопределенные ППМ AGV, в рабочее пространство. Используйте моделируемый лидарный датчик для возврата показаний диапазона и угла для позы AGV, а затем используйте диапазоны и углы для генерации lidarScan объект, содержащий 2-D lidar scan.

% Simulate lidar sensor and set the detection angles to [-pi/2 pi/2]
lidar = rangeSensor;
lidar.HorizontalAngle = [-pi/2 pi/2];
% Set min and max values of the detectable range of the sensor in meters
lidar.Range = [0 5];

% Load waypoints through which AGV moves
load waypoints.mat
traj = waypointsMap;

% Select a waypoint to visualize scan data
Vehiclepose = traj(350, :);

% Generate lidar readings
[ranges, angles] = lidar(Vehiclepose, map);

% Store and visualize 2-D lidar scan
scan = lidarScan(ranges, angles);
plot(scan)
title('Ego View')
helperPlotRobot(gca, [0 0 Vehiclepose(3)]);

Figure contains an axes. The axes with title Ego View contains 2 objects of type line, patch.

Настройка визуализации

Настройте окно рисунка, в котором отображается движение AGV на складе, связанные с ним лидарные сканирования среды, отображаются препятствия в виде закрашенных окружностей на виде птичьего глаза и цветные предупреждения о столкновениях. Цвет, используемый для каждого предупреждения, означает вероятность столкновения на основе зоны зоны обнаружения, которую препятствие занимает в этом ППМ.

% Set up display
display = helperVisualizer;

% Plot warehouse map in the display window
hRobot = plotBinaryMap(display, map, pose);

Предупреждение о столкновении на основе зон

Предупреждения о столкновении появляются только в том случае, если препятствие попадает в область обнаружения AGV.

Определение области обнаружения

Создайте настраиваемую обнаруживаемую область с различными цветами, формами и измените область цветовых областей графического интерфейса фигуры. Выполните приведенную ниже часть кода и измените маркеры перемещения многоугольников в соответствии с требованиями области обнаружения. Код ниже создает 3 полигональных ручки полукруглых областей радиусом 5, 2, 1 в метрах и AGV располагается в [0 0]. Измените радиус или полигональные объекты, чтобы создать пользовательскую область обнаружения.

figure
detAxes = gca;
title(detAxes,'Define Detection Area')
axis(detAxes, [-2 10 -2 4])
xlabel(detAxes, 'X')
ylabel(detAxes, 'Y')
axis(detAxes, 'equal')
grid(detAxes, 'minor')
t = linspace(-pi/2, pi/2, 30)';
% Specify color values - white, yellow, orange, red
colors = [1 1 1; 1 1 0; 1 0.5 0; 1 0 0];

% Specify radius in meters
radius = [5 2 1];

% Create a 3x1 matrix of type Polygon
detAreaHandles = repmat(images.roi.Polygon, [3 1]);

pos = [cos(t) sin(t)] * radius(1);
pos = [0 -2; pos(14:17, :); 0 2];
detAreaHandles(1) = drawpolygon(...
	'Parent', detAxes, ...
	'InteractionsAllowed', 'reshape', ...
	'Position', pos, ...
	'StripeColor', 'black', ...
	'Color', colors(2, :));

pos = [cos(t) sin(t)] * radius(2);
pos = [0 -1.5; pos(12:19, :); 0 1.5];
detAreaHandles(2) = drawpolygon(...
	'Parent', detAxes, ...
	'InteractionsAllowed', 'reshape', ...
	'Position', pos, ...
	'StripeColor', 'black', ...
	'Color', colors(3, :));

pos = [cos(t) sin(t)] * radius(3);
pos = [0 -1; pos(10:21, :); 0 1];
detAreaHandles(3) = drawpolygon(...
	'Parent', detAxes, ...
	'InteractionsAllowed', 'reshape', ...
	'Position', pos, ...
	'StripeColor', 'black', ...
	'Color', colors(4, :));

pause(2) % Pausing for the detection area window to load

Чтобы сохранить созданную область обнаружения, выполните команду helperSaveDetectionArea функция. Используйте маркер перемещения осей фигуры с многоугольниками области обнаружения и связанными с ними detAreaHandles переменная в качестве входных аргументов. Функция выводит область обнаружения в виде матрицы типа данных uint8и ограничивающую рамку. Синий прямоугольник вокруг области обнаружения представляет ограничительную рамку.

axesDet = gca; % Axes of the figure window containing the polygon handles
[detArea,bbox] = helperSaveDetectionArea(axesDet, detAreaHandles);

Figure contains an axes. The axes with title Define Detection Area contains 4 objects of type images.roi.polygon, image.

% Make detection area transparent by scaling colors
%alphadata = double(detArea ~= 0) * 0.5;
ax3 = getDetectionAreaAxes(display);
h = imagesc(ax3, [bbox(1) (bbox(1) + bbox(3))], ...
    -[bbox(2) (bbox(2) + bbox(4))], ...
    detArea);

colormap(ax3, colors);

% Plot detection area
plotObstacleDisplay(display)

Запустить моделирование

Область обнаружения разделена на три уровня: красный, оранжевый и желтый. Каждый регион связан с определенной степенью опасности:

  • Красный - столкновение неизбежно

  • Оранжевый - высокая вероятность столкновения

  • Желтый - применение мер предосторожности

Препятствия, не попадающие в зону обнаружения, находятся на безопасном расстоянии от АРМ. Ниже перечислены основные шаги, связанные с предупреждением о столкновении:

  • Моделирование 2-D лидара и извлечение данных облака точек.

  • Сегментировать данные облака точек в кластеры препятствий.

  • Закольцовывайте каждое препятствие, чтобы проверить возможные столкновения.

  • Выдайте предупреждение, исходя из уровня опасности препятствий.

  • Отображение препятствий рядом с AGV.

% Move AGV through waypoints
for ij = 27:size(traj, 1)
    currentPose = traj(ij, :);

Моделирование 2-D Lidar и извлечение данных облака точек

Соберите показания лидара на карте с помощью смоделированного датчика. Загрузите текущую позу AGV из файла ППМ. Используйте rangeSensor созданный для измерения дальности и угла.

    % Retrieve lidar scans
    [ranges, angles] = lidar(currentPose, map);
    scan = lidarScan(ranges, angles);
    
    % Store 2-D scan as point cloud
    cart = scan.Cartesian;
    cart(:, 3) = 0;
    pc = pointCloud(cart);

Сегментирование данных облака точек в кластеры препятствий

Используйте pcsegdist функция для сегментирования сканированного облака точек на кластеры с использованием минимального евклидового расстояния между точками в качестве критерия сегментации.

    % Segment point cloud into clusters based on euclidean distance
    minDistance = 0.9;
    [labels, numClusters] = pcsegdist(pc, minDistance);

Обновление окна визуализации с помощью карт и данных сканирования

    % Update display map
    updateMapDisplay(display, hRobot, currentPose);
    
    % Plot 2-D lidar scans
    plotLidarScan(display, scan, currentPose(3));
    
    % Delete obstacles from last scan to plot next scan line
    if exist('sc', 'var')
        delete(sc)
        clear sc
    end

Закольцевать каждое препятствие, чтобы найти вероятность столкновений

Проведите цикл по кластерам на основе их меток, чтобы извлечь точки, расположенные внутри них.

    nearxy = zeros(numClusters, 2);
    maxlevel = -inf;
    % Loop through all the clusters in pc
    for i = 1:numClusters
        c = find(labels == i);
        % XY coordinate extraction of obstacle
        xy = pc.Location(c, 1:2);

Преобразование мирового положения каждого препятствия в систему координат камеры.

        % Convert to normalized coordinate system (0-> minimum location of detection
        % area, 1->maximum position of detection area)
        a = [xy(:, 1) xy(:, 2)] - repmat(bbox([1 2]), [size(xy, 1) 1]);
        b = repmat(bbox([3 4]), [size(xy, 1) 1]);
        xy_org = a./b;
        % Coordinate system (0, 0)->(0, 0), (1, 1)->(width, height) of detArea
        idx = floor(xy_org.*repmat([size(detArea, 2) size(detArea, 1)],[size(xy_org, 1), 1]));

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

        % Extracts as an index only the coordinates in detArea
        validIdx = 1 <= idx(:, 1) & 1 <= idx(:, 2) & ...
            idx(:, 1) <= size(detArea, 2) & idx(:, 2) <= size(detArea, 1);

Для каждой допустимой точки препятствия найдите соответствующее значение в матрице обнаружения. Максимальное значение всех связанных точек в матрице обнаружения определяет уровень опасности, представленный этим препятствием. Отображение цветного круга в зависимости от уровня опасности препятствия на панели «Цвет предупреждения» окна визуализации.

        % Round the index and get the level of each obstacle from detArea
        cols = idx(validIdx, 1);
        rows = idx(validIdx, 2);
        levels = double(detArea(sub2ind(size(detArea), rows, cols)));

        if ~isempty(levels)
            level = max(levels);
            maxlevel = max(maxlevel, level);
            xyInds = find(validIdx);
            xyInds = xyInds(levels == level);
            % Get the nearest coordinates of obstacle in detection area
            nearxy(i, :) = helperNearObstacles(xy(xyInds, :));
        else
            % Get the nearest coordinates of obstacle in the cluster
            nearxy(i, :) = helperNearObstacles(xy);
        end
    end
    % Display a warning color representing the danger level. If the
    % obstacle does not fall in the detection area, do not display a color.
    switch maxlevel
        % Red region
        case 3
            circleDisplay(display, colors(4, :))
        % Orange region
        case 2
            circleDisplay(display, colors(3, :))
        % Yellow region
        case 1
            circleDisplay(display, colors(2, :))
        % Default case
        otherwise
            circleDisplay(display, [])
    end

Отображение точек препятствий, ближайших к AGV

Поскольку большинство препятствий на складе являются линейными и длинными, отображается только точка каждого кластера препятствий, ближайшая к AGV. Препятствия отображаются в виде закрашенных кругов на панели «График птичьего глаза» окна визуализации.

    for i = 1:numClusters
        % Display obstacles if exist in the mentioned range of axes3
        sc(i, :) = displayObstacles(display, nearxy(i, :));
    end
    updateDisplay(display)
    pause(0.01)
end

Figure Collision warning display contains 4 axes and other objects of type uipanel. Axes 1 with title Warehouse Floor Plan contains 4 objects of type image, patch, line. Axes 2 with title 2-D lidar scan contains 2 objects of type line, patch. Axes 3 with title Display obstacles contains 3 objects of type image, scatter. These objects represent AGV, Obstacle. Axes 4 contains an object of type scatter.

Figure Collision warning display contains 4 axes and other objects of type uipanel. Axes 1 with title Warehouse Floor Plan contains 686 objects of type image, patch, line. Axes 2 with title 2-D lidar scan contains 2 objects of type line, patch. Axes 3 with title Display obstacles contains 3 objects of type image, scatter. These objects represent AGV, Obstacle. Axes 4 contains an object of type scatter.

Вспомогательные файлы

helperCreateBineyOccupancyMap создает карту склада рабочего пространства робота

function map = helperCreateBinaryOccupancyMap()
% helperCreateBinaryOccupancyMap Creates a warehouse map with specific
% resolution passed as arguments to binaryOccupancyMap

map = binaryOccupancyMap(100, 80, 1);
occ = zeros(80, 100);
occ(1, :) = 1;
occ(end, :) = 1;
occ([1:30, 51:80], 1) = 1;
occ([1:30, 51:80], end) = 1;
occ(40, 20:80) = 1;
occ(28:52, [20:21 32:33 44:45 56:57 68:69 80:81]) = 1;
occ(1:12, [20:21 32:33 44:45 56:57 68:69 80:81]) = 1;
occ(end-12:end, [20:21 32:33 44:45 56:57 68:69 80:81]) = 1;
% Set occupancy value of locations
setOccupancy(map, occ);

% Add obstacles to the map at specific locations. Inputs to
% helperAddObstacle are obstacleWidth, obstacleHeight and obstacleLocation.
helperAddObstacle(map, 5, 5, [10, 30]);
helperAddObstacle(map, 5, 5, [20, 17]);
helperAddObstacle(map, 5, 5, [40, 17]);
end

%helperAddObstacle Adds obstacles to the occupancy map
function helperAddObstacle(map, obstacleWidth, obstacleHeight, obstacleLocation)
values = ones(obstacleHeight, obstacleWidth);
setOccupancy(map, obstacleLocation, values)
end

См. также

binaryOccupancyMap(Панель инструментов навигации) | lidarScan | rangeSensor | pcsegdist