主要内容

使用二维激光雷达进行碰撞预警

这个例子展示了如何使用2-D激光雷达数据检测障碍物并警告可能的碰撞。

概述

物流仓库越来越多地在自动制导车辆(AGV)上安装二维激光雷达,用于导航目的,这是由于传感器的经济实惠、远程和高分辨率。碰撞检测是agv在复杂环境下安全航行的一项重要任务。这个例子展示了如何表示一个充满障碍物的机器人工作空间,生成2-D激光雷达数据,检测障碍物,并在即将发生碰撞之前提供警告。

创建仓库地图

为了表示机器人工作空间的环境,定义binaryOccupancyMap(导航工具箱)对象,该对象包含仓库的平面图。占用网格中的每个单元格都有一个逻辑值。已占用的位置表示为1,空闲位置表示为0。您可以使用占用信息生成合成的2-D激光雷达数据。

在地图上靠近AGV指定路线的地方添加障碍物。

创建一个二进制仓库地图,并在定义的位置放置障碍物。map = helpercreatebinaryoccuancymap;%可视化地图与障碍和AGV图显示(地图)标题(“带障碍物和AGV的仓库平面图”将AGV添加到地图姿态= [5 40 0];甘氨胆酸helperPlotRobot(构成);

图中包含一个轴对象。轴对象标题仓库平面图与障碍和AGV包含2个对象类型的图像,补丁。

模拟二维激光雷达传感器

模拟二维激光雷达传感器rangeSensor对象为生成的地图收集激光雷达读数。将包含AGV预定义路径点的mat文件加载到工作区中。使用模拟激光雷达传感器返回AGV姿态的距离和角度读数,然后使用距离和角度生成一个lidarScan包含二维激光雷达扫描的对象

%模拟激光雷达传感器,设置探测角度为[-pi/2 pi/2]激光雷达=测距传感器;激光雷达。HorizontalAngle = [-pi/2 pi/2];设置传感器检测范围的最小和最大值,单位为米激光雷达。Range = [0 5];装载AGV移动的路径点负载waypoints.mattraj = waypointsMap;选择一个路径点以可视化扫描数据。Vehiclepose = traj(350,:);生成激光雷达读数[范围,角度]=激光雷达(车辆姿态,地图);存储和可视化2-D激光雷达扫描扫描= lidarScan(范围,角度);情节(扫描)标题(“自我观”) helperPlotRobot(gca,[0 0 Vehiclepose(3)]);

图中包含一个轴对象。标题为Ego View的axes对象包含2个类型为line、patch的对象。

设置可视化

设置一个图形窗口,显示AGV在仓库中的运动,相关的激光雷达扫描环境,在鸟瞰视图中将障碍物显示为填充圆圈,并使用颜色编码碰撞警告信息。用于每个警告的颜色表示碰撞的可能性,其基础是障碍物在该航路点所占的探测区域。

%设置显示display = helpvisualizer;在显示窗口中绘制仓库地图hRobot = plotBinaryMap(显示,映射,姿态);

基于区域的碰撞预警

只有当障碍物落在AGV的检测区域内时,才会出现碰撞警告。

定义检测区域

创建一个自定义的可检测区域,具有不同的颜色,形状,并在图形GUI上修改颜色区域的面积。运行下面的代码并修改多边形句柄以适应检测区域的要求。下面的代码创建了3个半圆形区域的多边形手柄,半径为5,2,1米,AGV位于[0 0]。修改半径或更改多边形对象以创建自定义检测区域。

数字detAxes = gca;标题(两家,定义检测区域xlabel(detAxes, [-2 10 -2 4])“X”) ylabel(两家,“Y”)轴(两家,“平等”)网格(两家,“小”) t = linspace(-pi/2,pi/2,30)';指定颜色值-白色,黄色,橙色,红色颜色= [1 1 1;11 10;1 0.5 0;10 0 0];以米为单位指定半径半径= [5 2 1];创建一个多边形类型的3x1矩阵detAreaHandles = repmat(images.roi。多边形,[3]);Pos = [cos(t) sin(t)]*半径(1);Pos = [0 -2;pos(真理:);0 2];detAreaHandles(1) = drawpolygon(...“父”两家,...“InteractionsAllowed”“重塑”...“位置”、pos、...“StripeColor”“黑”...“颜色”颜色(:));Pos = [cos(t) sin(t)]*半径(2);Pos = [0 -1.5;: pos (19);0 1.5);detAreaHandles(2) = drawpolygon(...“父”两家,...“InteractionsAllowed”“重塑”...“位置”、pos、...“StripeColor”“黑”...“颜色”颜色(:));Pos = [cos(t) sin(t)]*半径(3);Pos = [0 -1;: pos (21);0 1];detAreaHandles(3) = drawpolygon(...“父”两家,...“InteractionsAllowed”“重塑”...“位置”、pos、...“StripeColor”“黑”...“颜色”、颜色(4:));%暂停以便加载检测区域窗口暂停(2)

如果需要保存已创建的检测区域,执行helperSaveDetectionArea函数。使用具有检测区域多边形和相关多边形的图形的轴句柄detAreaHandles变量作为输入参数。该函数以数据类型矩阵的形式输出检测区域uint8,和一个包围框。检测区域周围的蓝色矩形表示包围框。

包含多边形句柄的图形窗口的轴axesDet = gca;[detArea,bbox] = helperSaveDetectionArea(axesDet,detAreaHandles);

图中包含一个轴对象。标题为Define Detection Area的axis对象包含4个image .roi类型的对象。多边形,形象。

通过缩放颜色使检测区域透明% alphadata = double(detArea ~= 0)*0.5;ax3 = getDetectionAreaAxes(显示);H = imagesc(ax3, [bbox(1) (bbox(1)+bbox(3))],...- - - - - - [bbox (2) (bbox (2) + bbox (4))),...detArea);colormap (ax3、颜色);%地块检测面积plotObstacleDisplay(显示)

运行仿真

检测区域分为红色、橙色、黄色三个等级。每个地区都与特定的危险程度有关:

  • 红色-碰撞迫在眉睫

  • 橙色-高碰撞几率

  • 黄色-采取谨慎措施

不在探测范围内的障碍物与AGV保持安全距离。以下是碰撞警告的主要步骤:

  • 模拟二维激光雷达,提取点云数据。

  • 将点云数据分割成障碍簇。

  • 在每个障碍物上循环检查可能的碰撞。

  • 根据障碍物的危险程度发出警告。

  • 显示AGV附近的障碍物。

移动AGV通过路径点ij = 27:size(traj,1) currentPose = traj(ij,:);

模拟二维激光雷达,提取点云数据

使用模拟传感器收集地图的激光雷达读数。从路径点文件中加载AGV的当前姿态。使用rangeSensor用于获取范围和角度测量的对象。

检索激光雷达扫描[range,angles] = lidar(currentPose,map);扫描= lidarScan(范围,角度);将二维扫描存储为点云cart = scan.笛卡尔;Cart (:,3) = 0;pc = pointCloud(购物车);

将点云数据分割成障碍簇

使用pcsegdist函数将扫描到的点云分割成簇,以点间的最小欧氏距离作为分割准则。

根据欧几里得距离将点云分割成簇minDistance = 0.9;[labels,numClusters] = pcsegdist(pc,minDistance);

用地图和扫描数据更新可视化窗口

%更新显示地图updateMapDisplay(显示、hRobot currentPose);绘制二维激光雷达扫描图plotLidarScan(显示、扫描、currentPose (3));删除上次扫描到绘制下一条扫描线的障碍物如果存在(“sc”“var”) delete(sc) clear(清除sc结束

循环检查每个障碍物,找出碰撞的可能性

根据它们的标签循环遍历群集,以提取位于其中的点。

nearxy = 0 (numClusters,2);Maxlevel = -inf;遍历pc中的所有集群i = 1:numClusters c = find(labels == i);% XY坐标提取障碍物xy = pc.Location(c,1:2);

将每个障碍物的世界位置转换为摄像机坐标系。

%转换为归一化坐标系(0->最小检测位置)%面积,1->检测区域最大位置)= (xy (: 1) xy(:, 2)]——repmat (bbox[1 - 2],[大小(xy, 1) 1]);B = repmat(bbox([3 4]),[size(xy,1) 1]);Xy_org = a./b;%坐标系(0,0)->(0,0),(1,1)->(宽度,高度)的detAreaidx = floor(xy_org.*repmat([size(detArea,2) size(detArea,1)],[size(xy_org,1) 1]));

提取检测区域内障碍点的指标。

只提取detArea中的坐标作为索引validIdx = 1 <= idx(:,1) & 1 <= idx(:,2) &...idx(: 1) < =大小(detArea, 2) & idx(:, 2) < =大小(detArea, 1);

对于每个有效的障碍点,在检测矩阵中找到相关的值。检测矩阵中所有相关点的最大值决定了该障碍物所代表的危险级别。中根据障碍物的危险程度显示一个彩色圆圈警告的颜色可视化窗口的窗格。

%舍入索引,并从detArea中获得每个障碍的级别cols = idx(validIdx,1);rows = idx(valididdx,2);level = double(detArea(sub2ind(size(detArea),rows,cols)));如果~isempty(levels) level = max(levels);Maxlevel = max(Maxlevel,level);xyInds = find(valididdx);xyInds = xyInds(级别==级别);获得检测区域内障碍物最近的坐标nearxy(i,:) = helpnearobstacle (xy(xyInds,:));其他的获得集群中障碍物最近的坐标nearxy(i,:) = helpnearobstacle (xy);结束结束%显示代表危险级别的警告颜色。如果%障碍物不落在检测区域,不显示颜色。开关maxlevel%红色区域情况下3 circleDisplay(显示、颜色(4:))%橙色区域情况下2 circleDisplay(显示、颜色(3,:))%黄色区域情况下1 circleDisplay(显示、颜色(2:))%默认情况否则circleDisplay(显示、[])结束

显示离AGV最近的障碍物点

由于仓库中的大多数障碍物都是线性的,所以只显示每个障碍物簇中最靠近AGV的点。控件中的障碍物显示为填充的圆圈鸟瞰的情节可视化窗口的窗格。

i = 1:numClusters%显示障碍,如果存在上述范围的斧头3sc(i,:) = displaybarriers (display,nearxy(i,:));结束updateDisplay(显示)暂停(0.01)结束

{

{

金宝app支持文件

helperCreateBinaryOccupancyMap创建机器人工作空间的仓库映射

函数map = helpercreatebinaryoccuancymap ()创建一个特定的仓库映射% resolution作为参数传递给binaryoccuancymapmap = binaryoccuancymap (100,80,1);Occ = 0 (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;%设置位置的占用率setOccupancy(地图,occ);在地图的特定位置添加障碍物。输入% helperaddoobstacle分别是obstacleWidth, obstacleHeight和obstacleLocation。helperAddObstacle(地图,5、5、(10、30));helperAddObstacle(地图,5 5[20日17]);helperAddObstacle(地图,5 5 [40,17]);结束在占用地图上添加障碍函数helperaddoobstacle (map,obstacleWidth,obstacleHeight,obstacleLocation) values = ones(obstacleHeight,obstacleWidth);setOccupancy(地图,obstacleLocation,值)结束

另请参阅

binaryOccupancyMap(导航工具箱)|lidarScan|rangeSensor|pcsegdist