主要内容

在3-D LIDAR点云中的车道检测

这个例子展示了如何在激光雷达点云中检测车道。您可以使用从激光雷达点云返回的强度值来检测自我车辆的车道。通过使用曲线拟合算法并跟踪曲线参数,可以进一步改进车道检测。激光雷达车道检测使您能够构建复杂的工作流程,如车道保持辅助、车道偏离预警和自适应巡航控制的自动驾驶。一辆测试车通过安装在车顶上的激光雷达传感器收集激光雷达数据。

介绍

激光雷达的车道检测涉及到相对于激光雷达传感器的左车道和右车道的检测,也称为自我车辆车道。它涉及以下步骤:

  • 兴趣区提取

  • 地平面分割

  • 峰值强度检测

  • 使用窗口搜索的车道检测

  • 抛物线多项式拟合

  • 平行车道配件

  • 车道跟踪

此流程图概述了本示例中提供的工作流程。

使用LINE检测的LIDAR数据的优点是:

  • LIDAR点云提供比图像数据更好的3-D表示路面,从而减少所需的校准参数以找到鸟瞰图。

  • LIDAR与基于图像的检测相比不利的气候条件更加稳健。

  • LIDAR数据具有厘米的准确度,导致道路定位准确。

下载并准备激光雷达数据集

本例中使用的激光雷达数据是使用Ouster OS1-64通道激光雷达传感器收集的,产生高分辨率点云。该数据集包含以单元阵列的形式存储的点云pointcloud.目的。每个3-D点云都包含XYZ位置以及强度信息。

注意:下载数据的时间取决于你的网络连接。在执行此代码块期间,MATLAB将暂时无响应。

%下载激光雷达数据Lidardata =螺杆植物;

选择数据集的第一帧进行进一步处理。

%选择第一帧ptcloud = lidardata {1};%可视化输入点云图pcshow (ptCloud)标题('输入激光乐点云')轴([0 50 -15 15 -5 5])视图([ -  42 35])

预处理

为了估计车道点,首先对激光雷达点云进行预处理。预处理包括以下步骤:

  • 兴趣区提取

  • 地平面分割

用仪表定义ROIxlim = [5 55];ylim = [-3 3];zlim = [-4 1];ROI = [XLIM ylim zlim];使用ROI%作物点云indices = findpointsinroi(ptcloud,Roi);croppedptcloud = select(ptcloud,索引);%拆除接地面maxdistance = 0.1;参考矢量= [0 0 1];[型号,inliers,异常值] = pcfitplane(crocpedptcloud,maxdistance,caperencedvector);地面= SELECT(CRACPEDPEPTCLOUD,INLIERS);图pcshow(地面)标题('地平面')视图(3)

弄点检测

通过使用滑动窗口搜索来检测车道点,其中使用基于强度的直方图进行滑动窗口的初始估计。

Lane Point检测主要由这两个步骤组成:

  • 峰值强度检测

  • 窗口搜索

峰值强度检测

激光雷达点云中的道点强度分布明显。通常,这些强度占据直方图分布的上部区域,并以高峰形式出现。从检测到的地平面沿自我车辆轴(正x轴)计算强度的直方图。这HelpercomputeHistograph帮助函数创建强度点的直方图。通过指定箱分辨率来控制直方图的箱数。

histbinresolution = 0.2;[Histval,Yvals] = HelpercomputeHistograph(地面,Histbinresolution);图绘图(Yvals,Histval,“——k”甘氨胆酸)组(,“XDir”'逆转')举行

在直方图中使用helperfindpeaks帮手功能。进一步使用通道宽度进一步过滤可能的车道点HelperinitialWindow.帮手功能。

(峰值、loc) = helperfindpeaks (histVal);startYs = yvals (loc);巷宽= 4;[startLanePoints, detectedPeaks] = helperInitialWindow (startYs、山峰、巷宽);情节(startYs,山峰,“* r”)绘图(STARTLANEPOINTS,DETTETINEDPEAKS,'og')传说('直方图''顶峰''检测到峰值'“位置”'北') 标题(峰值检测的)举行

窗口搜索

窗口搜索用于通过沿着车道曲率方向滑动窗口来检测车道点。窗口搜索包括两个步骤:

  • 窗口初始化

  • 滑动窗口

窗口初始化

检测到的峰值有助于初始化搜索窗口。将搜索Windows初始化为具有红色和右侧通道的红色和蓝色的多个箱子。

vBinRes = 1;hBinRes = 0.8;numverticalins = cell ((groundPts.XLimits(2) - groundPts.XLimits(1))/vBinRes);groundPts.XLimits laneStartX = linspace (groundPts.XLimits (1), (2), numVerticalBins);%显示宾窗图pcshow(地面)视图(2)Helperdisplaybins(LaneStartx,StartlanePoints(1),HBinres / 2,地面,'红色的');helperDisplayBins (laneStartX startLanePoints (2), hBinRes / 2, groundPts,'蓝色');标题('初始化滑动窗口'

滑动窗口

滑动仓从仓位初始化,并沿自我载具(正x轴)方向迭代移动。这helperDetectLanes辅助功能检测车道点并可视化滑块。连续箱基于前一个箱内的强度值沿着y轴滑动。

在缺少车道点的区域,该函数使用二次多项式预测滑动箱。当有移动物体穿越车道时,通常会出现这种情况。滑动的箱子是黄色的,用多项式预测的箱子是绿色的。

display = true;Lanes = Helperdetectlanes(地面,Hbinres,...numverticalbins,startlanepoints,显示);

%绘制最终车道点Lane1 =车道{1};Lane2 = Lanes {2};图pcshow(地面)标题('检测到车道点')举行P1 = Plot3(Lane1(:,1),Lane1(:,2),Lane1(:,3),'* y');P2 = Plot3(Lane2(:,1),Lane2(:,2),Lane2(:,3),“* r”);持有视图(2)LGND = legend([p1 p2],{)“左车道点”'右车道点'});集(lgnd,“颜色”“白色”“位置”“southoutside”

莱恩配件

车道拟合包括在检测到的车道点上估计一条多项式曲线。这些多项式与平行车道约束一起用于车道拟合。

抛物面多项式拟合

使用表示为的2度多项式拟合多项式在X-Y点上。 一种 X 2 + BX. + C , 在哪里一种B.,C是多项式参数。要执行曲线拟合,请使用helperFitPolynomial辅助功能,还使用随机样本共识(RANSAC)算法处理异常值。为了估计3-D泳道点,从预处理步骤期间从平面模型中提取参数。平面模型表示为 斧头 + 经过 + CZ. + D. = 0. ,其中z坐标未知。通过在平面方程中替换X和y坐标来估计z坐标。

[P1,Error1] = HelperFitPolynomial(Lane1(:,1:2),2,0.1);[P2,Error2] = HelperFitpolynomial(Lane2(:,1:2),2,0.1);xval = linspace(5,40,80);YVAL1 = Polyval(P1,XVAL);YVAL2 = Polyval(P2,XVAL);%z坐标估计modelParams = model.Parameters;zworld1 =(-modelparams(1)* xval  -  ModelParams(2)* YVAL1  -  ModelParams(4))/ ModelParams(3);zworld2 =(-modelparams(1)* xval  -  modelparams(2)* yval2  -  modelparams(4))/ modelparams(3);%可视化安装车道图pcshow (croppedPtCloud)标题(“多项式拟合巷”)举行p1 = plot3 (xval yval1 zWorld1,“y”'行宽', 0.2);p2 = plot3 (xval yval2 zWorld2,'r''行宽', 0.2);LGND = legend([p1 p2],{)“左车道点”'右车道点'});集(lgnd,“颜色”“白色”“位置”“southoutside”)查看(2)持有

平行车道配件

通道通常沿着道路彼此平行。要使车道拟合稳健,请使用此并行约束。适合多项式时,helperFitPolynomial辅助函数还计算,拟合误差。用新的多项式更新有错误点的车道。通过沿y轴移动来更新这个多项式。

lane3d1 = [xval ` yval1 ` zWorld1 `];lane3d2 = [xval ` yval2 ` zWorld2 `];%沿着y轴移动多项式的高分%分数低的多项式如果error1 > error2 lane多项式= P2;如果> 0 lane多项式(3)= lane3d2(1,2) + laneWidth;其他的lane多项式(3)= lane3d2(1,2) - laneWidth;结束Lane3d1(:,2)= Polyval(Lanepolynomial,Lane3d1(:,1));Lanepolynomials = [Lanepolynomial;P2];其他的lanePolynomial = P1;如果Lane3D2(1,2)> 0 Lanepolynomial(3)= Lane3D1(1,2)+ LaneWidth;其他的lane多项式(3)= lane3d1(1,2) - laneWidth;结束lane3d2 (:, 2) = polyval (lanePolynomial, lane3d2 (: 1));lanePolynomials = [P1;lanePolynomial]结束平行拟合后%可视化车道图pcshow(ptcloud)轴([0 50 -15 15-5 5])保持p1 = plot3 (lane3d1 (: 1), lane3d1 (:, 2), lane3d1 (:, 3),“y”'行宽', 0.2);p2 = plot3 (lane3d2 (: 1), lane3d2 (:, 2), lane3d2 (:, 3),'r''行宽', 0.2);查看([ -  90 90])标题('适合车道')LGND =图例([P1 P2],{“左车道点”'右车道点'});集(lgnd,“颜色”“白色”“位置”“Southoutside”)举行

车道跟踪

车道跟踪有助于稳定由突然的混蛋和漂移引起的车道曲率。由于缺失的车道点,移动在车道上的车辆以及错误的车道检测,这些变化可能发生。车道跟踪是一个两步的过程:

  • 跟踪车道多项式参数 一种 B. 控制多项式的曲率。

  • 跟踪峰值检测的起始点。此参数表示为 C 在多项式中。

这些参数被更新使用卡尔曼滤波器与一个恒定加速度运动模型。启动卡尔曼滤波,使用configureKalmanFilter

%初始值CurveinitialParameters = Lanepolynomials(1,1:2);DriveinitialParameters = Lanepolynomials(:,3)';initialEstimateError = [1 1 1] * 1E-1;MotionNoise = [1 1 1] * 1E-7;测量管理= 10;%配置卡尔曼滤波器curvefilter = configurekalmanfilter(“ConstantAcceleration”...curveInitialParameters、initialEstimateError motionNoise measurementNoise);driftFilter = configureKalmanFilter (“ConstantAcceleration”...DriveInitialParameters,IniStEstIniationError,MotionNoise,MeasurementNoise);

遍历数据

循环通过并通过使用循环数据来处理LIDAR数据helperLaneDetector助手类。这个helper类实现前面所有的步骤,并执行额外的预处理以从点云中删除车辆。这保证了被探测的接地点是平坦的,平面模型是准确的。这类方法探测器检测和提取左侧和右车道的车道点作为双元素单元阵列,其中第一元件对应于左车道和第二元件到右车道。

初始化随机数生成器rng(2020) numFrames = nummel (lidarData);探测器= helperLaneDetector ('roi',[5 40 -3 3 -4 1]);%打开显示[0 0],[-15 15],[-5 5]);漂移= 0 (numFrames, 1);filteredDrift = 0 (numFrames, 1);curveSmoothness = 0 (numFrames, 1);filteredCurveSmoothness = 0 (numFrames, 1);为了i = 1:numframes ptcloud = lidardata {i};%检测通道探测器(探测器,Ptcloud);%从卡尔曼滤波器预测多项式预测(curveFilter);预测(driftFilter);使用卡尔曼滤波器%正确多项式Lanepolynomials =探测器.Lanepolynomial;漂移(i)=平均值(Lanepolynomials(:,3));Curveshoothness(i)=平均值(Lanepolynomials(:,1));updatedcurveparams =正确(曲线Filter,Lanepolynomials(1,1:2));UpdatedDriftParams =正确(Driftfilter,Lanepolynomials(:,3)');%更新车道多项式updatedlane多项式= [repmat(updatedCurveParams,[2 1]),updatedDriftParams'];%估计新车道点,更新多项式车道= updateLanePolynomial(检测器,updatedLanePolynomials);filteredDrift (i) =意味着(updatedLanePolynomials (:, 3));filteredCurveSmoothness (i) =意味着(updatedLanePolynomials (: 1));平行拟合后%可视化车道ptCloud。Color = uint8(repmat([0 0 255],ptCloud.Count,1)); / /用户名lane3dPc1 = pointCloud(车道{1});lane3dPc1。Color = uint8(repmat([255 0 0],lane3dPc1.Count,1));lanePc = pccat([ptCloud lane3dPc1]);lane3dPc2 = pointCloud(车道{2});lane3dPc2。Color = uint8(repmat([255 255 0],lane3dPc2.Count,1));lanePc = pccat([lanePc lane3dPc2]); view(player,lanePc)结束

结果

为了分析车道检测结果,通过在图中绘制它们来将它们与跟踪的车道多项式进行比较。每个绘图都将参数与卡尔曼滤波器进行比较。第一绘图比较沿Y轴的泳道漂移,第二曲线比较了车道多项式的平滑度。平滑度被定义为车道曲线的斜率的变化率。

图绘图(漂移)保持情节(filteredDrift)标题(“y轴车道漂移”)传说('漂移值'“过滤漂移值”

图绘制(curveSmoothness)绘图(过滤筛选)持有标题('曲线平滑度')传说('曲线平滑度'“曲线平滑过滤”

总结

这个例子已经向你展示了如何检测来自激光雷达传感器的点云的强度通道上的车道。您还学习了如何在检测到的车道点上拟合一个二维多项式,并利用地平面模型来估计三维车道点。您还使用了卡尔曼滤波跟踪来进一步改进车道检测。

金宝app支持功能

HelperLoadData.辅助功能将LIDAR数据设置为MATLAB工作区。

函数reflidarData = helperGetDataset() outputFolder = fullfile(tempdir,'wpi');URL =.“//www.tatmou.com/金宝appsupportfiles/lidar/data/WPI_LidarData.tar.gz”;lidardatatarfile = fullfile(outputfolder,“WPI_LidarData.tar.gz”);如果~存在(lidarDataTarFile“文件”mkdir (outputFolder);disp (“正在下载WPI激光雷达驱动数据(760 MB)……”);websave (lidarDataTarFile、url);解压(lidarDataTarFile outputFolder);结束%检查tar.gz文件是否已下载,但没有未压缩如果〜存在(FullFile(OutputFolder,'wpi_lidardata.mat'),“文件”)Untar(LidardataTarfile,Outputfolder);结束%加载LIDAR数据负载(fullfile (outputFolder'wpi_lidardata.mat'),'lidardata');%选择突出强度值的区域reflidarData =细胞(300 1);数= 1;ROI = [-50 50 -30 30 -inf inf];为了i = 81:380 pc = lidarData{i};印第安纳州= findPointsInROI (pc, roi);reflidarData{数}=选择(pc,印第安纳州);Count = Count + 1;结束结束

HelperinitialWindow.辅助功能使用检测到的直方图峰值计算搜索窗口的起点。

函数[yval,detedpeaks] = HelperinitialWindow(Yvals,Peaks,Lanewidth)LetlallaneDindes = Yvals> = 0;RightLaneSindices = YVALS <0;LeftLaneys = YVALS(左边林种);RightLaneys = YVALS(右润andices);Peaksleft =峰(左边alindices);peaksright =山峰(右润andices);diff = zeros(sum(leftlanesindices),sum(rightlaneindices));为了i = 1:sum(leftlanesindices)为了j = 1:sum(rightlaneindices)diff(i,j)= abs(lanewidth  - (liftlaneys(i) -  rightlaneys(j))));结束结束[~, minIndex] = min (diff (:));(行,坳)= ind2sub(大小(diff), minIndex);yval = [leftLaneYs(row) rightLaneYs(col)]; / /显示当前位置detectedPeaks = [peaksLeft(row) peaksRight(col)]; / /检测峰值estimatedLaneWidth = leftLaneYs(row) - rightLaneYs(col);%如果计算的车道宽度不在界限内,返回峰值最高的车道如果ABS(估计LaneWidth  -  LaneWidth)> 0.5如果max(peaksLeft) > max(peaksRight) yval = [leftLaneYs(maxLeftInd) NaN];detectedPeaks = [peaksLeft(maxLeftInd) NaN];其他的yval = [NaN rightLaneYs(maxRightInd)];detectedPeaks = [NaN rightLaneYs(maxRightInd)];结束结束结束

helperFitPolynomial辅助函数将基于ransac的多项式拟合到检测到的道点上,并计算拟合得分。

函数[P,score] = helperfit多项式(pts,degree,resolution) P = fitpolynomial (pts,degree,resolution);ptsSquare = (polyval(P,pts(: 1)) - pts(: 2)).^2;分数=√意味着(ptsSquare));结束

HelpercomputeHistograph帮助函数计算点云的强度值的直方图。

函数[histval,yvals] = HelpercomputeHutehistograph(Ptcloud,直方图中)Numbins = CeIl((Ptcloud.ylimits(2) -  ptcloud.ylimits(1))/直方图);histval =零(1,numbins-1);binstarty = linspace(ptcloud.ylimits(1),ptcloud.ylimits(2),numbins);YVALS =零(1,NUMBINS-1);为了i = 1: numbin -1 roi = [-inf 15 binStartY(i) binStartY(i+1) -inf inf];印第安纳州= findPointsInROI (ptCloud roi);subPc =选择(ptCloud,印第安纳州);如果subPc。Count histVal(i) = sum(subPc.Intensity);yvals(i) = (binStartY(i) + binStartY(i+1))/2;结束结束结束

helperfindpeaks辅助功能从直方图值中提取峰值。

函数[pkHistVal,pkIdx] = helperfindpeaks(histVal) pkIdxTemp = (1:size(histVal,2))';histValTemp =[南;histVal ';南);tempIdx =(1:长度(histValTemp)。';%只保留任何相等值的第一个(包括NaN)yfinite =〜isnan(histvaltemp);Ineq = [1;1 + find((histvaltemp(1:end-1)〜= histvaltemp(2:端))&...(yfinite(1:end-1)| yfinite(2:端)))];tempidx = tempidx(Ineq);取第一阶导数的符号s =符号(diff(histvaltemp(tempidx)));%找到本地最大值maxIdx = 1 + find(diff(s)<0);% Index到原始索引向量中,不带NaN书端pkidx = tempidx(maxidx) -  1;%提取峰值的坐标pkHistVal = histVal (pkIdx);pkIdx = pkIdxTemp (pkIdx)”;结束

参考文献

[1] Ghallabi, Farouk, Fawzi Nashashibi, Ghayath el - haj - shade和Marie-Anne Mittet。“基于激光雷达的车道标记检测在高清地图中的车辆定位。”2018第21届智能交通系统国际会议(ITSC), 2209-14。毛伊岛:IEEE 2018。https://doi.org/10.1109/ITSC.2018.8569951。

[2] Thuy,Michael和FernandoLeón。“基于LIDAR数据的车道检测和跟踪。”计量和测量系统17,不。3(2010):311-322。https://doi.org/10.2478/v10178-010-0027-3。