主要内容

基于ffh描述符的航空激光雷达SLAM

本例演示了如何使用三维特征实现用于空中测绘的同步定位和测绘(SLAM)算法。本例的目标是估计机器人的轨迹并创建其环境的点云地图。

本例中的SLAM算法通过查找下采样接受扫描之间的粗对齐来估计轨迹,使用在每个点提取的快速点特征直方图(FPFH)描述符,然后应用迭代最近点(ICP)算法来微调对齐。3-D姿态图优化,来自导航工具箱™,减少了估计轨迹中的漂移。

创建和可视化数据

从OpenTopography网站下载的航空数据块创建合成激光雷达扫描[1].加载一个mat文件,其中包含一系列航路点,这些航路点定义了机器人的轨迹。计算激光雷达扫描从数据在每个航路点使用helperCreateDataset功能。该功能将在每个航路点计算的激光雷达扫描输出为pointCloud物体、机器人覆盖的原始地图和地面真实航路点。

数据文件='航空地图.tar.gz';航路点文件=“gTruthWayPoints.mat”;%使用辅助功能在每个航路点生成激光雷达扫描[pClouds,orgMap,gTruthWayPts]=helperCreateDataset(数据文件,航路点文件);

在机器人覆盖的原始地图上可视化地面真实路径点。

%创建一个图形窗口来可视化地面真实地图和路径点hFigGT=图;axGT=轴(“家长”hFigGT,“颜色”,“黑”);%想象地面真相航路点pcshow(GTP、,“红色”,“MarkerSize”, 150,“家长”,axGT)保持可视化被机器人覆盖的原始地图pcshow (orgMap“MarkerSize”10“家长”,axGT)保持远离的%自定义轴标签xlabel(axGT,‘X(m)’) ylabel (axGT“Y (m)”) zlabel (axGT“Z (m)”)标题(axGT,“地面真实地图和机器人轨迹”)

可视化提取的激光雷达扫描,使用pcplayer反对。

%为玩家指定限制xlimits=[-9090];ylimits=[-9090];zlimits=[-625-587];%创建一个pcplayer对象来可视化激光雷达扫描lidarPlayer = pcplayer (xlimits ylimits zlimits);%自定义pcplayer轴标签xlabel(lidarPlayer.Axes,‘X(m)’)ylabel(lidarPlayer.Axes,“Y (m)”)zlabel(lidarPlayer.Axes,“Z (m)”)标题(lidarPlayer.Axes,“激光雷达扫描”)%循环并可视化数据对于l = 1:长度(pClouds)提取激光雷达扫描ptCloud=pClouds(l);%更新激光雷达显示视图(lidarPlayer ptCloud)暂停(0.05)结束

设置可调参数

指定轨迹和闭环估计的参数。针对特定的机器人和环境调整这些参数。

点云配准参数

指定在接受注册的每次扫描之间要跳过的激光雷达扫描数。由于连续扫描具有很高的重叠,跳过几帧可以提高算法速度而不影响精度。

skipFrames = 3;

下采样激光雷达扫描可以提高算法速度。长方体栅格过滤器通过将每个单元内的所有点平均为单个点来对点云进行下采样。指定长方体栅格过滤器各个单元的大小,单位为米。

gridStep=1.5;%在米

为下采样点云中的每个有效点提取FPFH描述符。指定用于计算描述符的k最近邻(KNN)搜索方法的邻域大小。

邻居= 60;

设置匹配FPFH描述符的阈值和比率,用于识别点对应。

匹配阈值=0.1;匹配比率=0.97;

设置连续扫描之间的相对姿态估计的最大距离和路径数。

maxDistance=1;maxNumTrails=3000;

指定微调相对姿态所需考虑的内偏百分比。

inlierRatio = 0.1;

指定长方体栅格过滤器每个单元的大小,用于通过对齐激光雷达扫描创建地图。

alignGridStep=1.2;

环路闭合估计的参数

指定当前机器人位置周围的半径,以搜索循环闭合候选对象。

loopClosureSearchRadius=7.9;

循环闭合算法基于三维子映射的创建和匹配。子映射由指定数量的可接受扫描组成nScansPerSubmap。循环闭合算法也会忽略指定数量的最近扫描潜伏期,同时搜索循环候选。指定均方根误差(RMSE)阈值循环关闭阈值,用于接受submap作为匹配。分数越低表示匹配越好,但分数会根据传感器数据和预处理而变化。

nScansPerSubmap = 3;subMapThresh = 15;loopClosureThreshold = 0.6;

指定最大可接受均方根误差(RMSE),用于估计候选回路之间的相对姿态rmseThreshold。选择较低的值可以获得更精确的回路闭合边,这对姿势图优化有很大影响,但分数会因传感器数据和预处理而异。

rmseThreshold=0.6;

初始化变量

创建一个姿势图,使用poseGraph3D(导航工具箱)对象,存储在接受的激光雷达扫描之间的估计相对姿态。

pGraph = poseGraph3D;%6乘6信息矩阵的默认序列化右上三角形infoMat = [1 0 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1];

预分配和初始化计算所需的变量。

%分配内存来存储子映射子映射=单元(地板(长度(pClouds)/(skipFrames*nScansPerSubmap)),1;%分配内存以存储每个子贴图姿势subMapPoses = 0(圆(长度(pClouds) / (skipFrames * nScansPerSubmap)), 3);初始化变量以存储接受的扫描及其转换submap创建百分比pcAccepted=pointCloud.empty(0);tformAccepted=rigid3d.empty(0);%初始化变量以存储基于特征方法的相对姿势%无姿势图形优化fpfhTform=rigid3d.empty(0);用于跟踪添加的扫描次数的计数器数= 1;

创建变量以可视化处理的激光雷达扫描和估计轨迹。

%设置为1可在构建过程中可视化已处理的激光雷达扫描viewPC=0;%创建pcplayer对象以查看激光雷达扫描,同时%顺序处理它们,如果viewPC是启用的如果viewPC==1 pplayer=pcplayer(xlimits、ylimits、zlimits);%自定义播放器轴标签包含(pplayer。轴,‘X(m)’) ylabel (pplayer。轴,“Y (m)”)zlabel(pplayer.Axes,“Z (m)”)标题(pplayer.Axes,“已处理扫描”)结束%创建一个体形窗口以可视化估计的轨迹hFigTrajUpdate=图形;axTrajUpdate=轴(“家长”hFigTrajUpdate,“颜色”,“黑”);标题(axTrajUpdate,“传感器姿态轨迹”)

轨迹估计与修正

机器人的轨迹是机器人在三维空间中的位置和姿态的集合。利用三维激光雷达SLAM算法从三维激光雷达扫描实例估计机器人的姿态。使用这些过程进行三维SLAM估计:

  1. 点云将采样

  2. 点云注册

  3. Submap创建

  4. 循环闭包查询

  5. 位姿图优化

迭代处理激光雷达扫描来估计机器人的轨迹。

rng (“默认”)%在pcmatchfeature中设置随机种子以保证一致的结果对于FrameIdx = 1: skipFrames:长度(pClouds)

点云将采样

点云下采样可以提高点云配准算法的速度。降采样应该根据您的具体需要进行调整。

%向下采样当前扫描curScan=pcdownsample(pClouds(FrameIdx)),“gridAverage”,gridStep);如果viewPC = = 1%可视化下采样点云视图(pplayer curScan)结束

点云注册

点云配准估计当前扫描和上一次扫描之间的相对姿势。该示例使用以下步骤进行配准:

  1. 提取FPFH描述符从每次扫描使用extractFPFHFeatures功能

  2. 通过使用pcmatchfeatures功能

  3. 使用估计几何变换3D功能

  4. 微调相对姿势使用pcregistericp功能

%提取FPFH特征curFeature=extractFPFHFeatures(curScan,“纽曼尼斯堡”,邻居);如果FrameIdx==1%更新验收扫描及其形式pcAccepted(计数,1)= curScan;tformAccepted(计数,1)= rigid3d;%将初始姿态更新为地面真实值的第一个航路点%比较fpfhTform(count,1)=rigid3d(眼睛(3),gTruthWayPts(1,:);其他的%通过将当前扫描与上一次扫描相匹配来识别对应关系indexPairs=pcmatchfeatures(curFeature、prevFeature、curScan、prevScan、,...“MatchThreshold”matchThreshold,“不合格率”, matchRatio);matchedPrevPts =选择(prevScan indexPairs (:, 2));matchedCurPts =选择(curScan indexPairs (: 1));%估计当前扫描和上一次扫描之间的相对姿势%使用通信tform1 = estimateGeometricTransform3D (matchedCurPts。的位置,...matchedPrevPts。的位置,“刚性”,“最大距离”,最大距离,...“MaxNumTrials”,maxNumTrails);执行ICP注册以微调相对姿态tform = pcregistericp (curScan prevScan,“初始化转换”tform1,...“内部比率”,内插率);

将刚性变换转换为xyz-位置和四元数方向将其添加到姿势图中。

relPose = [tform2trvec(tform.T') tform2quat(tform.T')];%将相对姿势添加到姿势图添加相对位置(pGraph,relPose);

存储接受的扫描及其姿势以创建submap。

%更新计数器和存储接受扫描和他们的姿势计数=计数+1;pcAccepted(count,1)=curScan;accumPose=pGraph.nodes(高度(pGraph.nodes));tformAccepted(count,1)=rigid3d((trvec2tform)(累加(1:3))*...quat2tform (accumPose (4))));%更新估计姿势fpfhTform(数)= rigid3d (tform。T * fpfhTform(把1).T);结束

Submap创建

通过将连续的、可接受的扫描对齐到指定大小的组中来创建子映射nScansPerSubmap,使用pcalign函数。使用子映射可以导致更快的循环闭包查询。

CurrSubMap=楼层(计数/nScansPerSubmap);如果rem(计数,nScansPerSubmap)==0%对齐激光雷达扫描阵列以创建子贴图submap {currSubMapId} = pcalign (...pcAccepted((计数-nScansPerSubmap+1):计数,1),...tformAccepted((count - nScansPerSubmap + 1):count,1),...校准步骤);%将中心扫描姿势指定为子贴图的姿势submappose (currSubMapId,:) = tformAccepted(count -...地板(nScansPerSubmap / 2), 1) .Translation;结束

关闭循环查询

使用一个循环闭包查询标识以前访问过的位置。循环结束查询包括查找当前扫描和以前子映射之间的相似性。如果找到相似的扫描,则当前扫描是循环结束候选。循环结束候选估计包括以下步骤:

  1. 方法估计以前的子映射和当前扫描之间的匹配帮助评估候选人如果当前扫描和submap之间的RMSE小于指定的循环关闭阈值。前面由所有匹配的子映射表示的扫描是循环闭包候选。

  2. 使用ICP配准算法计算当前扫描和闭环候选之间的相对位姿。RMSE最低的闭环候选是当前扫描的最佳可能匹配。

只有当RMSE低于指定的阈值时,循环闭包候选者才被接受为有效的循环闭包。

如果currSubMapId > subMapThresh mostRecentScanCenter = pGraph.nodes(height(pGraph.nodes));通过匹配电流估计可能的环路闭合候选%用子贴图扫描[loopSubmapIds, ~] = helperEstimateLoopCandidates (curScan submap,...次级对手,最新世纪扫描中心,currSubMapId,subMapThresh,...loopClosureSearchRadius、LoopClosureStorhold);如果~isempty(loopSubmapIds) rmseMin = inf;%从匹配的子映射id估计当前扫描的最佳匹配对于k=1:长度(循环子磁盘)%检查submap中的每个扫描对于kf=1:nScansPerSubmap probableLoop候选者=...loopsubpids(k)*nScansPerSubmap-kf+1;[pose_-Tform,~,rmse]=pcregistericp(curScan,...PCA已接受(可能是候选);%更新最佳循环闭包候选者如果rmse < rmseMinmatchingNode = probableLoopCandidate;构成= [tform2trvec pose_Tform.T”)...tform2quat(pose_Tform.T');结束结束结束%检查循环闭包候选项是否有效如果rmseMin将候选环的相对位姿添加到位姿图addRelativePose (pGraph姿势,infoMat matchingNode,...珠心);结束结束结束%更新以前的点云和功能prevScan=curScan;prevFeature=curFeature;%可视化从接受的扫描估计的轨迹。显示(pGraph“id”,“关闭”,“家长”, axTrajUpdate);drawnow结束

位姿图优化

利用该方法减小估计轨迹中的漂移优化组合图(导航工具箱)功能。通常,姿势图中第一个节点的姿势表示原点。要将估计轨迹与地面真实航路点进行比较,请将第一个地面真实航路点指定为第一个节点的姿势。

pGraph = optimizePoseGraph (pGraph,“FirstNodePose”,[gTruthWayPts(1,:) 1 0 0 0]);

想象轨迹比较

利用未经过位姿图优化的特征、经过位姿图优化的特征和地面真实数据可视化估计轨迹。

从姿态图中得到估计的轨迹pGraphTraj = pGraph.nodes;从特征配准中得到估计的轨迹,而不需要姿态%图优化fpfhEstimatedTraj = 0(统计,3);对于i = 1:count fpfhEstimatedTraj(i,:) = fpfhTform(i).Translation;结束%创建一个图形窗口,以可视化地面真实情况和估计结果%轨迹hFigTraj=图形;axTraj=轴(“家长”,hFigTraj,“颜色”,“黑”)图3(FpfEstimatedTraj(:,1),FpfEstimatedTraj(:,2),FpfEstimatedTraj(:,3),...的r *,“家长”,axTraj)保持图3(pGraphTraj(:,1),pGraphTraj(:,2),pGraphTraj(:,3),“b.”,“家长”axTraj) plot3 (gTruthWayPts (: 1), gTruthWayPts (:, 2), gTruthWayPts (:, 3),“去”,“家长”,axTraj)保持远离的平等的视图(axTraj 2)包含(axTraj‘X(m)’) ylabel (axTraj“Y (m)”) zlabel (axTraj“Z (m)”)标题(axTraj,“轨迹比较”)传说(axTraj“无姿势图优化的估计轨迹”,...“姿态图优化的估计轨迹”,...“地面实况轨迹”,“位置”,“最佳户外”)

构建和可视化生成的地图

使用估计的姿势变换和合并激光雷达扫描,以创建累积点云地图。

%从姿势中获得估计的轨迹estimatedTraj = pGraphTraj (:, 1:3);将相对姿态转换为刚性转换EstimatedForms=rigid3d.empty(0);对于idx = 1: pGraph。NumNodes pose = pGraph.nodes(idx);rigidPose = rigid3d((trvec2tform(pose(1:3)) * quat2tform(pose(4:7)))');estimatedTforms (idx, 1) = rigidPose;结束%从处理过的点云及其相对姿势创建全局贴图globalMap = pcalign (pcAccepted estimatedTforms alignGridStep);%创建地物窗口以可视化估计的地图和轨迹hFigTrajMap =图;axTrajMap =轴(“家长”,hFigTrajMap,“颜色”,“黑”); pcshow(估计数),“红色”,“MarkerSize”, 150,“家长”,axTrajMap)保持pcshow(全球地图,“MarkerSize”10“家长”,axTrajMap)保持远离的%自定义轴标签包含(axTrajMap‘X(m)’) ylabel (axTrajMap“Y (m)”) zlabel (axTrajMap“Z (m)”)标题(axTrajMap,'估计的机器人轨迹和生成的地图')

可视化地面真实地图和估计地图。

%创建一个数字窗口来显示地面真实地图和估计地图hFigMap =图(“位置”,[0 0 700 400]);axMap1 =次要情节(1、2、1,“颜色”,“黑”,“家长”, hFigMap);axMap1。Position = [0.08 0.2 0.4 0.55];pcshow (orgMap“家长”axMap1)包含(axMap1‘X(m)’)ylabel(axMap1,“Y (m)”)zlabel(axMap1,“Z (m)”)标题(axMap1“地面实况图”) axMap2 = subplot(1,2,2,“颜色”,“黑”,“家长”, hFigMap);axMap2。Position = [0.56 0.2 0.4 0.55];pcshow(全球地图,“家长”,axMap2)xlabel(axMap2,‘X(m)’)ylabel(axMap2,“Y (m)”)zlabel(axMap2,“Z (m)”)标题(axMap2,“估计地图”)

另见

功能

readPointCloud|插入点云(导航工具箱)|rayIntersection(导航工具箱)|addRelativePose(导航工具箱)|优化组合图(导航工具箱)|显示(导航工具箱)|extractFPFHFeatures|pcmatchfeatures|估计几何变换3D|下采样|pctransform|pcregistericp|pcalign|tform2trvec(导航工具箱)|tform2quat(导航工具箱)

物体

lasFileReader|pointCloud|pcplayer|occupancyMap3D(导航工具箱)|poseGraph3D(导航工具箱)|rigid3d

参考文献

[1] 美国塔斯卡卢萨:季节性洪水动力学和无脊椎动物群落〉,国家航空激光测绘中心,2011年12月1日,开放地形图(https://doi.org/10.5069/G9SF2T3K).