当前位置:网站首页>3D激光SLAM:LeGO-LOAM---两步优化的帧间里程计及代码分析
3D激光SLAM:LeGO-LOAM---两步优化的帧间里程计及代码分析
2022-08-03 10:35:00 【华为云】
前言
LeGO-LOAM的全称是 Lightweight and Ground-Optimized Lidar Odometry and Mapping on Variable Terrain
其中LeGO就是轻量级和利用地面优化,轻量级的实现就是通过两步的优化方式,利用地面优化的部分也在两步优化的第一步中。
和原始LOAM一样,通过前后两帧点云来估计两帧之间的运动,从而累加得到前端里程计的输出,和上述方法使用线面约束同时优化六自由度帧间位姿不同,LeGO-LOAM的前端分成两个步骤,每个步骤估计三自由度的变量。
通过这种方式进行帧间里程计的运算,可以提供运算效率,使得可以在嵌入式平台中运行
在里程计部分,LeGO-LOAM充分利用了前面存储的标签信息,在原本LOAM的里程计部分,其使用的思路更像是ICP,单纯寻找距离最近的点,而并没有考虑其合理性。在这里,LeGO-LOAM通过标签增加了一次筛选,标签相同的点才会用于优化,通过这种方法,能够大幅提高匹配的准确率。
此外,在优化部分,LOAM使用的是直接将所有参数放在一起,进行LM优化,而在LeGO-LOAM中,作者将LM优化分两步进行,每次优化三个参数,在确保准确性的前提下,减小了35%的计算开销。
利用地面点优化
地面点更符合面特征的性质,因此地面点的优化问题就使用点到面的约束来构建
地面点的约束对x,y,yaw这三个自由度是不能估测的。当这个三个自由度的值发生变化,点到面的残差不会发生显著变化,
地面点的优化,只对pitch、roll及z进行约束和优化


白色的为当前帧,绿色的为上一帧,可以看到当前帧发生yaw的旋转,和发生x、y的平移的时候,当前帧的面点到上一帧的距离都没有变,所有不能把这三个自由度的优化放到面点特征上来。
当z轴发生移动,或者发生pitch和roll角的变化,当前帧的面特征点,到上一帧的面特征点的距离即发生变化。
利用角点优化
第一步优化完pitch、roll和z之后,剩下还有三个自由度的变量需要进行估计,
需要提取角点进行优化,由于多线激光雷达提取的角点通常是垂直的边缘特征,因此对,x、y及yaw有着比较好的能观性,通过角点的优化结合上地面点的结果可以得到六自由度的帧间优化结果。
将上一步分优化的z、pitch和roll的三自由度量,和剩下没有估计的三个自由度进行角点的约束优化。
代码部分
LeGO-LOAM的帧间里程计部分在FeatureAssociation.cpp中 。
可以直接找到runFeatureAssociation的函数
adjustDistortion();//去除畸变 calculateSmoothness();//计算曲率 markOccludedPoints();//剔除离散点 extractFeatures();//提取特征 publishCloud(); // cloud for visualization /** 2. Feature Association */ if (!systemInitedLM) { checkSystemInitialization(); return; } updateInitialGuess(); updateTransformation();//帧间里程计核心部分 integrateTransformation(); publishOdometry(); publishCloudsLast(); // cloud to mapOptimization在这个函数中进行了
- 去除畸变
- 计算曲率
- 剔除离散点
- 提取特征
- 帧间里程计核心部分
- 发布里程计
- 发布点云
其中帧间里程计核心部分在 updateTransformation() 函数中
void updateTransformation(){ if (laserCloudCornerLastNum < 10 || laserCloudSurfLastNum < 100) return; //地面点帧间里程计估计优化 for (int iterCount1 = 0; iterCount1 < 25; iterCount1++) { laserCloudOri->clear(); coeffSel->clear(); findCorrespondingSurfFeatures(iterCount1);//通过kdtree 寻找对应的点 if (laserCloudOri->points.size() < 10) continue; if (calculateTransformationSurf(iterCount1) == false)//进行优化估计 break; } //角点帧间里程计估计优化 for (int iterCount2 = 0; iterCount2 < 25; iterCount2++) { laserCloudOri->clear(); coeffSel->clear(); findCorrespondingCornerFeatures(iterCount2);//通过kdtree 寻找对应的点 if (laserCloudOri->points.size() < 10) continue; if (calculateTransformationCorner(iterCount2) == false)//进行优化估计 break; } }从这个函数中可以明显看出分成了两部分
- 第一个for循环是 地面点帧间里程计估计优化
- 第二个for循环是 角点帧间里程计估计优化

从这里可以看出surfPointsFlat中的点都是地面点
然后在findCorrespondingSurfFeatures的函数中,进行当前帧的地面点与上一帧中的地面点进行匹配。
其过程和ALOAM中的原理一致。
在findCorrespondingCornerFeatures的函数中,进行当前帧的角点与上一帧中的角点进行匹配。
其过程和ALOAM中的原理一致。
当前帧角点i,映射到上一帧点云中,并找到距离最近的点j,在与j相同的scan中,寻找次近邻点m。
利用映射后的点i到j和m的距离,进行约束
通过两步优化的位姿变换通过里程计数据的方式发送出来可以进行可视化的操作
具体代码在 publishOdometry() 函数中
当前帧角点i,映射到上一帧点云中,并找到距离最近的点j,并在相同scan中找到次近邻点l,在相邻的scan中再找到近邻点m。
利用映射后的点i到j、l、m平面的距离,进行约束。
//发布前端里程计 void publishOdometry(){ geometry_msgs::Quaternion geoQuat = tf::createQuaternionMsgFromRollPitchYaw(transformSum[2], -transformSum[0], -transformSum[1]); laserOdometry.header.stamp = cloudHeader.stamp; laserOdometry.pose.pose.orientation.x = -geoQuat.y; laserOdometry.pose.pose.orientation.y = -geoQuat.z; laserOdometry.pose.pose.orientation.z = geoQuat.x; laserOdometry.pose.pose.orientation.w = geoQuat.w; laserOdometry.pose.pose.position.x = transformSum[3]; laserOdometry.pose.pose.position.y = transformSum[4]; laserOdometry.pose.pose.position.z = transformSum[5]; pubLaserOdometry.publish(laserOdometry); laserOdometryTrans.stamp_ = cloudHeader.stamp; laserOdometryTrans.setRotation(tf::Quaternion(-geoQuat.y, -geoQuat.z, geoQuat.x, geoQuat.w)); laserOdometryTrans.setOrigin(tf::Vector3(transformSum[3], transformSum[4], transformSum[5])); tfBroadcaster.sendTransform(laserOdometryTrans); }其topic的名称为:
gazebo测试

前端的里程计在Z轴方向已经发生了漂移。
但是地图没有飘,这个是后端进行优化的结果,将前端漂移的部分优化了回来
边栏推荐
猜你喜欢

混合型界面:对话式UI的未来

以网强算,中国移动算网建设激发澎湃能量

三大产品力赋能欧萌达OMODA5

2022年山东省安全员C证复习题模拟考试平台操作

4 g acquisition ModbusTCP turn JSON MQTT cloud platform

Regulation action for one hundred days during the summer, more than 700 traffic safety hidden dangers were thrown out

DOM0, DOM2, DOM3 events

Mysql OCP 28题

Mysql OCP 27题

8 月数据库排行榜:Oracle 分数大跌,MySQL 上涨最多
随机推荐
流水线设计的方法和作用「建议收藏」
Mysql OCP 30题
error C2872: “flann”: 不明确的符号 解决方法
cass9.1快捷键怎么设置_cass9.1格式刷快捷键命令
MySQL binlog的这种时间怎么处理呢??
Mysql OCP 72 questions
混动产品谁更吃香,看技术还是看市场?
Mysql OCP 74 questions
VL53L0X V2 laser ranging sensor collects distance data serial output
DOM对象能干什么?
Guys, I have a problem: My source mysql has a table that has been writing to, I use mysql cdc connec
Matplotlib
机器学习(公式推导与代码实现)--sklearn机器学习库
QSplitter(分离部件)
免费的mysql数据库管理工具_易语言快速导入MySQL数据库
type="module" you know, but type="importmap" you know
月薪没到35K的程序员必须要背的面试八股,我先啃为敬!
浪潮—英伟达打造元宇宙新方案,虚拟人的故事将再破你的认知
金先生谈长效生长激素出海与产品力
C# Color颜色RGB对照表、颜色选择器