赞
踩
本文为我在浙江省北大信研院-智能计算中心-情感智能机器人实验室-科技委员会所做的一个分享汇报,现在我把它搬运到博客中。
由于参与分享汇报的同事有许多是做其他方向的机器人工程师(包括硬件、控制等各方面并不是专门做SLAM的工程师),加上汇报的内容较多,因此在分享中我尽量使用简介的口语,而不出现复杂的公式。所以本文面向的是3D-slam方向的初学者,不涉及到源码解析。内容在整理中参考了许多链接,将放在最后。
在文章结束后,我会把原PPT放在最后面,需要者自取。
另外打个广告,在slam方向或者强化学习导航方向有实习意愿的,请发送简历至zkyy828@163.com,谢谢。
内容比较多,放一个目录,感兴趣的朋友可以只看对应位置。
注:很荣幸能受到中山大学博士后戚玉华老师和阿木实验室邀请,于11月18日在B站直播间做了一期线上分享,并且加入了LIO-Mapping,LINS,FAST-LIO等内容。有兴趣的同学可以关注 直播回放 | 三维激光SLAM原理及开源方案对比
目录
从2D到3D——Cartographer (ICRA2016)
LOAM:Lidar Odometry and Mapping in Real-time
LeGO-LOAM: Lightweight and Ground-Optimized Lidar Odometry and Mapping on Variable Terrain .
LIO-SAM: Tightly-coupled Lidar Inertial Odometry via Smoothing and Mapping
LVI-SAM: Tightly-coupled Lidar-Visual-Inertial Odometry via Smoothing and Mapping
“明显不是搞科研的玩儿法,就是奔着产品去的。算法需要的计算资源少,而且因为依赖很少,因此几乎可以直接应用在一个产品级的嵌入式系统上。以前学术界出来的开源2D/3D SLAM算法不少,但能几乎直接拿来就用在产品上的,恕我孤陋寡闻还真想不出来。因此,我认为进入相关领域SLAM算法的门槛被显著降低了。” ——知乎 梅卡曼德机器人创始人 邵天兰
Cartographer支持2D和3D激光雷达的输入,实现机器人定位,并构建栅格地图。
2D-SLAM:基于2D栅格地图,可以直接用于导航。 使用方法: 1.直接使用Ros的Move_base等方式。 2. 导航代码中订阅/map消息, (data部分为一维数组,根据height和width可恢复地图图像。-1为未知,0~100依次增加表示被占据概率增大)
3D-SLAM:基于hybridGrid,译为混合概率地图,我理解为3D栅格地图。 明确:RViz 仅显示3D混合概率网格的2D 投影(以灰度形式)。该地图难以直接使用。
在介绍定位和建图思路之前,先介绍一下地图的更新方式:
以方格代表地图块,内部存储数据用来表示被占据的概率。 发出一束激光,打到一个障碍物点,被打到的称为hit点,中间连线上的空区域,称为miss点。 2d和3d都是存储的这样的地图。3d相当于是3维的栅格地图。
宏观上:多次观测到,提升其概率。 问题是,如何用公式表达这个“多次观测”来实现“概率提升”?
举例:
- scan-scan: 这个意味着利用两帧激光数据(每帧激光束的数目相同),计算二者之间的变换。典型方法:ICP。
- scan-map: 利用一帧激光数据和地图数据,找到激光数据在地图中的位置。
- map-map: 利用一个子地图数据,在一个更大的地图中找到它合适的位置。
不管是2D还是3D,首先要有一个初始的位姿,在此基础上进行优化:
可以看出,cartographer的多传感器融合是一个松耦合,主要依赖激光来定位。IMU和里程计数据并没有被构建到真正优化的目标函数中。
在得到了初始位姿以后,初始位姿要经过第一阶段解算:CSM(Correlation Scan Match 相关扫描匹配)——构建似然场。即对原先的地图map进行一个高斯模糊,让它膨胀一些,然后把激光scan在一个搜索窗口内暴力匹配,计算得分。
注意,这里有两个问题:
1.得分怎么算?
如果scan的点落在障碍物模糊区域内,落的越多,得分越高。
2.地图不是无限大的吗,你怎么保证在搜索窗口里就能找到位姿呢?
因为有初始位姿。误差肯定在一个范围内而不会马上发散到很远,所以可以在一个位姿的窗口内,对位姿进行暴力匹配搜索。(初始位姿估计中,里程计数据不会突然激增;imu的加速度信息会漂移,但是算法对于imu加速度数据选择直接丢弃不看;而根据之前位姿匀速假设也不会飘走)
这时候我们就要考虑,什么是位姿?位置+姿态。
对于2Dslam而言,有三个变量,x,y,yaw角。 对于3Dslam而言,有x,y,z,roll,pitch,yaw六个变量。
我们可以看出,第一阶段CSM解算中,位姿在其中是一个离散的变量,通过暴力枚举获得输出结果;
但是暴力枚举也是存在分辨率的,例如:如果角度步长设为1度,但如果刚好真正的角度是5.5度,那么CSM只能搜索到5或6度,而无法进一步细化,逐步累积将会造成误差。 因此,引入第二阶段位姿解算:非线性优化。
Si(T)表示把激光数据S用位姿T进行转换,M(x)表示得到坐标x的地图占用概率。思路:S代表了激光击中障碍物,将激光点在机器人坐标系下的位置,经过T转换到世界坐标系下以后,应该尽可能的落在已有地图的障碍物上。
第二阶段的位姿求解,显然位姿在其中是一个连续的变量,通过梯度下降的方法求解目标函数。由于地图是离散的,因此需要对地图进行插值处理,使地图也变成一个可以求导的连续变量,这样才能优化前述目标函数。
线性插值:已知数据 (x0, y0) 与 (x1, y1),要计算 [x0, x1] 区间内某一位置 x 在直线上的y值;
双线性插值本质上就是在两个方向上做线性插值。
双三次插值:更加复杂的插值方式,它能创造出比双线性插值更平滑的图像边缘。使用最近16个点插值。
Cartographer用的应该是这一种 并且采用Ceres自带的双三插值器。
阅读比较了代码,我判断2D和3D对于此部分内容基本相同。
Cartographer在后端主要寻找回环,并根据建立的约束对所有的sumap进行统一优化。
回环检测目的是:检测当前位置是否曾经来过,即采用当前scan在历史中搜索,确认是否匹配。
为什么要有回环检测呢?原因有二:1. 已有地图时位姿初始化,不知道当前帧初始位姿,也就不清楚在地图中哪个位置,无法做定位。 2.有累积误差,仅靠前端递推,不进行修正的话,地图很容易变形。
因此接下来我们探讨两个问题:1.如何检测回环。2.检测回环后该怎么做。
检测回环和前端的思路也比较相似,先通过穷举暴力匹配,再通过优化精细修正。
但是,前端的暴力穷举,是在有个初始位姿的基础上在一个小窗口内穷举。
后端重定位,没有初始位姿了,暴力匹配的范围变成了整个地图。 因此必须采用算法加速处理。:多分辨率地图+分枝定界操作。
假设有一帧激光:
蓝色代表障碍物:
在高分辨率的地图上,四个点命中3个;
在低分辨率的地图上,四个点全部命中。
激光在低分辨率的地图上匹配情况: 代表得分的上界 (再往精细展开,匹配得分只能更低,不能更高)
在高分辨率的地图上匹配情况: 代表得分的下界( 再往粗略缩放,匹配得分只能更高,不会更低)
分支定界:
- 先把整个地图中的一个区域展开到底(最高分辨率),得到一个匹配分数(得分下界);
- 然后把其他区域不展开,算匹配分数。(得分上界)
- 如果低分辨率区域的得分上界,还没有已展开到底的高分辨率区域的下界高,这个低分辨率区域就不再展开了,统统丢掉不要。
左图四个命中3个,得分75; 右图四个命中2个,得分50; 那么激光打在子区域A的可能性就要大于B,因此B就无需继续展开成更精细的地图了。
这块没有论文发表,是我个人的理解,可能在细节上不够准确,这段比较复杂,仅供参考。(欢迎纠错,有错误我将立即更正)
1.首先,在z轴方向对点云切成n个片; 2.对每个切片中的点,求解质心; 3.计算每个点,与质心连线,和x轴所成的角度,并依据角度排序。
之后: 1. A点作为参考点:计算AB和x轴的夹角,映射到直方图。 相当于:把点云分类,分成size个类, 分类标准为当前点B与参考点A连线AB和x轴的夹角。 2.再计算一下质心到AB的夹角OBA,作为直方图中这个点对应的权重。
B点被映射到某一个分类中,分类依据为AB和X的夹角;(AB代表“参考点与当前点”,当参考点B距离A很远时,参考点则会被重新选择) B在此分类中的权重,由角OBA的大小决定(变换至-90~90度,主要是想看垂直程度)。
我们可以知道,一圈360度激光,求质心实际就是激光发射器的位置, OB和AB的夹角越垂直,证明一束激光OB,更接近垂直的打到了AB构成的障碍物平面上,反射强度更高,更可信。越不垂直,说明激光OB以侧面的形式打到平面AB上,探测误差可能更大。
回到原先问题上: 刚刚准备在yaw,x,y,z四个维度对当前点云在地图中暴力搜索一个位置初值; 提取直方图的目的,相当于是对当前点云进行一个降维,提取特征。 根据直方图中提取的特征(根据切片上每个点与参考点的直线AB与x轴的夹角分成n个类,类的值是OBA的大小), 和历史数据进行匹配,筛选掉一批不够阈值的yaw角。
细节问题:
二维激光点云或者三维点云,拥有xy或xyz三个坐标。因此点云可以被旋转。但是一个抽象的特征怎么进行旋转?
答:直方图横坐标代表AB和机器人坐标系x轴的夹角,如果对点云进行旋转,也就代表了对这个夹角进行了旋转。旋转点云,对应其实也就是对整个直方图的横坐标向右平移。其实旋转的本质上仍然是点云。
因此整个流程为:
1.把当前时刻的点云直方图进行旋转,代表得到一系列的候选直方图;
2.候选直方图和地图中各个位置的点云直方图进行匹配,计算余弦距离。(直方图可以用一个向量表示,向量的余弦距离就是向量的夹角。)
3.筛掉未达阈值的候选直方图,其对应的yaw角直接丢掉,不进行x,y,z三个方向上的展开。
4.达到阈值的yaw角,进入深层循环:对点云进行xyz三个方向的平移,和三维栅格地图计算匹配得分,仍然遵循分支定界,计算上界和下界。(仅有高、低两个分辨率)
补充理解(仅供参考):
1.为什么yaw角上的特征不满足,这个候选位姿就可以丢掉,就不需要再展开x,y,z了?
因为特征的匹配方法对距离不敏感。 特征主要依赖角OBA,以及AB和X轴的夹角。 在BO的延长线上任意一点,对应的特征都完全相同。
2.在直方图匹配中,需要对当前时刻点云提取直方图特征,并和历史地图匹配。然而只有点云才能提取直方图,而Cartographer3D使用的是三维栅格地图。历史地图中的点云从哪里来?
- 根据源码我推测,程序在各个submap中的每个位姿节点里存放了特征直方图。
- Cartographer可以三维建图,但是是以rosbag的形式把传感器数据保存下来,再把地图以二进制文件pbstream保存以后,离线调用assets_writer_backpack_3d.launch文件,需要同时提供传感器数据bag和地图pbstream文件,才能离线三维建图。 (关于这点,详见SLAM学习笔记(十八)3D激光SLAM——Cartographer第一视角点云可视化配置与使用方法(最新) )
- 因此,我推测代码内部应该把历史点云丢掉了,因此离线点云建图除了需要已经建好栅格地图文件以外,还需要才需要提供原始传感器数据(包含每一时刻获取的点云)。 如果想要获取真正的三维栅格地图,应该需要定位并且修改源码,找到数据在代码中的存储位置,把submap中的三维栅格地图从protobuf数据流中修改并解析出来。
回顾:在Cartographer前端中,不断维护的是scan和submap之间的位姿。整个的map是由一个个submap组成的。
两个问题:
1. 前端后端均采用了暴力枚举的方式,这样做是否科学?(虽然各自以不同方式加速,但是感觉暴力搜索并不是一个聪明的做法)
2.导入一个已知地图,机器人出现在该地图的某个区域,初始位置未知,随后很快确定了自己的位置,在这个重定位的计算过程中,机器人的位姿变化,到底是离散的,还是连续的?
离散:从一个位置跳变到另一个位置; 连续:从一个位置,逐渐平滑的过渡到另一个位置。
假设现在有一个如下的曲线图:
我们可以构成三点共识:
1. 已有地图不是无限大的,所以位姿的解空间范围有限;
2.机器人真正的位置处,激光和地图匹配得分最高;
3.实际的曲线可能有着很多的局部最优值。然而,一个局部最优值所在位置,往往和机器人真正的位置天壤地别。
采用随机梯度上升,则大概率落入局部最优值。
因此,必须把整个解空间全都搜索完一遍,才能知道哪个区域上界最高,再从这个区域出发优化,找到真正的最优得分。——采用多分辨率地图,分区域枚举,确定最优解在绿色范围内,再从绿色范围内出发,非线性优化,梯度上升,找到真正的位置。
回答上面的问题:
1.暴力搜索是否科学?从传统求解角度来说,是的。否则会落入局部最优值。但是目前有人也用深度学习的方式去做,主要集中在视觉SLAM中,因为相对于只有距离特征的点云,图像有更多的特征。
2.在重定位过程中位姿变化,是先离散搜索区域,再连续精准确定。
1.Cartographer主要解决室内问题,LOAM室内外都可以,但是没有回环检测。
2.Cartographer的3D部分,更像是2D的扩展:即用2D的思路去做3D的事情。而LOAM则主要解决3D问题,其核心思路难以解决2D问题。
3.从代码风格来看,我认为它属于——学院派。根据其开源代码来看,和Cartographer令人望而生畏的代码量完全不是一个层次。当然这也解释了,为什么基于LOAM的衍生算法众多,但基于Cartographer的衍生算法却鲜有所闻。
那么,代码少,时间老,就证明它不行吗?作为一个7年前的算法,至今在自动驾驶数据集KITTI上的Odometry模块的激光SLAM排行榜上,仍然霸占榜一。
2011年,Andreas Geiger(KIT,德国卡尔斯鲁厄理工学院)、Philip Lenz(KIT)、Raquel Urtasun(TTIC,美国丰田工业大学芝加哥分校)三位年轻人发现,阻碍视觉感知系统在自动驾驶领域应用的主要原因之一,是缺乏合适的benchmark。而现有的数据集无论是在数据量,还是采集环境上都与实际需求相差甚远。于是他们利用自己的自动驾驶平台,建立起庞大的基于真实场景下的数据集,以此推动计算机视觉和机器人算法在自动驾驶领域的发展。这便是KITTI数据集的诞生背景。
KITTI数据采集平台:1个惯性导航系统,1个64线3D激光雷达, 2个灰度摄像机,2个彩色摄像机,以及4个光学镜头。
- KITTI数据集主要有以下Benchmark:road(用于道路分割),semantics(用于语义分割),object(2D、3D和鸟瞰三种视角,用于目标检测),depth(用于视觉深度评估),stereo(用于双目立体视觉和三维重建),flow(用于光流预测),tracking(用于目标跟踪),odometry(里程计)
- 里程计数据集地址:http://www.cvlibs.net/datasets/kitti/eval_odometry.php 数据集中包含了22个立体视觉序列以无损png的形式保存,
- 另外还提供了velodyne64线激光雷达数据。评估标准:平移误差(百分比),旋转度数(度每米)。
前三名:
1. SOFT2:萨格勒布大学电气工程与计算学院采用的方法,未发表论文,使用的是双目视觉;
2.V-LOAM:基于LOAM的改进版本,同时使用了激光-视觉数据进行融合,也是LOAM作者Zhang Ji于ICRA2015所发,但代码未开源。
3.LOAM:本节所述方法。
Point Cloud Registration:点云不是同一时刻获取的,每一个帧点云,其中的每一个点,都是不同时刻获取的,因此把它进行运动补偿: 获取每个点的时间戳,位姿插值,把点云先投影到同一时刻;提取特征点。
Lidar Odometry: 估计两帧点云之间的位姿变换,获得两个时刻之间的相对位姿,频率较高 10Hz
Lidar Mapping: 建图模块,把连续10帧的点云数据和整个地图匹配,获得世界坐标系下的位姿,频率较低 1Hz。
Transform Intergration:实时利用世界坐标系下的位姿和两个时刻之间的相对位姿,更新各个时刻世界坐标系下的位姿
回顾:Cartographer使用栅格地图,地图中存储着占据概率,通过把点云投影到栅格地图,计算匹配得分,找到最合适的投影,作为位姿变换。
但是,LOAM使用的是点云地图,那么点云投影后,进行匹配的就还是点云地图。 两堆点云,如何匹配?
传统方法,使用ICP方法,即默认两堆点云中最近的点是匹配点,构建矩阵进行奇异值分解,得到变换矩阵后投影点云,然后再次寻找匹配点,重新计算投影……直至收敛。
然而,对SLAM算法而言,要求同步定位和建图。这样随便根据距离选匹配点,计算太复杂,可能算来算去都不收敛,压根就不能实时,计算量实在是太大了。
LOAM作者决定对点云提取特征,然后根据稀疏的特征来计算位姿变换。 作者决定提取两种特征点:平面点和边缘点。
那么,如何区分这两种点?
作者引入了一种计算方法——曲率。
计算曲率听起来是一个很麻烦的事情,在高等数学中,一条曲线的曲率以如下公式进行计算:
但事实上作者并不是这样算的。他直接利用激光的每条扫瞄线中,一个点前后各五个点,计算平均值到该点的距离。
平面点:在三维空间中处于平滑平面上的点,其和周围点的大小差距不大,曲率较低,平滑度较低。
边缘点:在三维空间中处于尖锐边缘上的点,其和周围点的大小差距较大,曲率较高,平滑度较高。
作者对整个扫描进行分段,分四段,每段各取2个边缘点和4个平面点。在确定了边缘点和平面点后,两帧点云将根据这两种特征点进行运动估计。
边缘点匹配方法:
红、绿、蓝代表多线激光雷达的扫描线; 在第k+1帧中,边缘点i处在红色的扫瞄线上;
在第k帧中,红线上的边缘点j和i更近,在相邻绿线上再找到一个最近的边缘点l,那么l和j构成一个边缘。 因此,对边缘特征点来说,优化的目标就是,i到直线lj的距离最近。
向量叉乘的模长,代表平行四边形的面积; 除以底,代表平行四边形的高; 也就是点到直线的距离。
平面点匹配方法:
红、绿、蓝代表多线激光雷达的扫描线; 在第k+1帧中,平面点i处在红色的扫瞄线上; 在第k帧中,红线上的平面点j和i更近,在同线上再找到一个附近的平面点l,在相邻绿线上再找到一个最近的平面点m,那么lmj构成一个平面。 因此,对平面特征点来说,优化的目标就是,i到平面mlj的距离最近。
分子:三维物体的体积; 分母:地面构成的平行四边形的面积; 高=体积/面积 也就是点到平面的距离。
有趣却无用的细节:作者发表时的源代码,和目前流传的代码并不相同(源代码可能由于后续维护和其他商业原因下架)。其声称使用了LM算法,但实际上在代码中被人发现用的是比较简单的高斯牛顿法(也许重要内容没有开源,也许是这样论文看起来更复杂),使用的是OpenCV自带的solve函数迭代求解增量,轮子是自己造的。 目前流传的代码为ALOAM,代码简介,易于学习。主要是后人对其工程代码进行了改进,使用了和Cartographer一样的Ceres库,直接用求解器,省去了对雅可比矩阵的手工推导,因此代码简洁了不少。
到目前为止,根据特征点,计算了相邻两个时刻点云之间的位姿变换。然而,我们希望得到的是世界坐标系下的位姿。
是否可以直接从第1帧开始,逐步递推,得到每个时刻点云之间的位姿变换呢?
毫无疑问,这样会把误差越累积越大,就好比只用轮式里程计递推定位一样。
LOAM虽然没有回环检测(不能发现自己到了相同的位置),但这并不代表它仅靠前端递推。 LOAM在建图部分,采用map-map的匹配方法,用连续10帧的激光点云数据,和10立方米之内的地图做一个匹配。
也就是说,在第25帧的位姿,不是从0帧-1帧,1帧-2帧……一直递推到第25帧的。而是10~20帧之间构建的点云地图和全局地图匹配得到的第20帧位姿开始递推,从20~21,21~22……直到第25帧。
前端寻找边缘线和平面,使用的是最近临的方法。
后端则不同,使用的是特征点周围的点云簇,通过主成分分析(求解协方差矩阵的特征值和特征向量)确定边缘线和平面。
gif图像来自于robinvista的博客-LOAM论文和程序代码的解读
红色箭头代表特征值方向。
特征值两长一短,则是平面,短的那个作为平面的法向量。
特征值两短一长,则是边缘,长的那个作为边缘的方向向量。
三个向量相交于几何中心,由此确定边缘线和平面。
其他内容与前端相同。在确定了点和线、线和面以后,构建目标函数,非线性优化。
LOAM的优点是:
1.提出了新颖的特征提取方式。
2.根据时间戳,对旋转的雷达采集时间不一致进行运动补偿。
3.融合了scan to scan(里程计部分) map to map(建图部分)的思想。
LOAM的缺点也很明显:
1.没有回环检测。(发表时间较早,比谷歌Cartographer要早两年)
2.不能处理大规模的旋转变换。
作为一个14年提出的算法,为什么能一直占据Kitti的榜首呢?之后的算法就都不如它吗?
我的看法:
- 首先,kitti中odometry指的是里程计,里程计不等同于定位,里程计的评价指标为每100m误差多少米——LOAM在0.55%左右。
- 而有回环检测的算法,则发现回环时会修正全局轨迹,取得更高的结果。而Kitti中并非所有序列都有回环。
- 其次,Kitti数据集中累积的公里数大概为39km左右,由汽车采集,也没有大范围的旋转运动。有些算法在其他数据集上比它要好,有的算法比它更快,有的算法结合了更多的信息,例如GPS等,Kitti数据集中并未提供(是作为GT的,而不是传感器数据)。
Lego-LOAM是TiXiao Shan发表在IROS2018的文章,文章叫:可变地形下的轻量级和地面优化的雷达里程计与建图。
其是以LOAM为框架衍生出的新算法,主要在于两点提升:轻量级 和 地面优化。
使用的是加拿大clearpath公司的 Jackal小车(吐槽:这一款价格比较昂贵,很多paper里面都是用这种小车,国内价格约为15~19万,根据代理商不同价格不同。要是有人想读博或者读研还不确定的,看到实验室有这个样子的小车,就从了吧,愿意十几万买这样一个小车的,要么有钱,其他设备和学生补助充足,要么已经有很多的技术积累了,才舍得买)
没有回环检测(前述已经说过) ;
计算时间复杂度较高,基于三维空间中的位姿进行优化;
户外可能受到各种噪声影响,例如树上摇晃的树叶,地上的杂草。而这些点未必会重复出现在前后两帧激光中。而错误的特征点将会影响位姿精度。
LOAM需要提取平面点和边缘点,由于车体上下颠簸,竖直维度提取的平面点很容易造成误差。
因此Lego-LOAM的contribution:1.着重于解决一些非城市化道路或非平整道路上LOAM存在的问题。2.轻量化,改进算法,使其在TX2上也可以实时运行。
分割部分首先把点云投影到一张距离图像中:
以16线激光雷达为例,其竖直方向为16根,因此竖直方向的分辨率为16;其水平方向角度分辨率为0.2度,因此水平方向分辨率为360/0.2=1800,即构建一张1800*16的距离图像,其中每个像素的值为对应点云到传感器的欧几里得距离。
区分地面点和非地面点:
要求激光雷达安装平行于地面。(找到朝下的第一组雷达中的每个点,找到相邻组中同一水平索引的点。其俯仰角变化在一定范围内,则为同一平面。)
为什么要提取地面点?
就算车体颠簸,路面基本在相邻帧之间变化是不大的。
总体思路就是:先利用提取的地面平面点,调整z,roll,pitch;再利用地面上竖直的边缘点,调整x,y,yaw;不仅更准确了,还实际缩小了优化的规模。(类似于把一个O(n^6)的问题变成了两个O(n^3)的问题。)
在提取特征点之前,对点云进行一个聚类操作:低于30个数据点的类别就当成噪声处理,这样保存下来的点就是一些相对比较静态的物体了。
右图为聚类处理后的点云,红色部分被分割为地面点。
对前述形成的16*1800的距离图像,水平分成若干个子图像(sub-image),对每一个子图像都进行特征提取操作:
依旧是和LOAM中相同的边缘点和平面点评判标准,根据曲率c,区分边缘点和平面点。
之后,要划分两个大集合:
之后,再从F_me和F_mp中,划分两个小集合:
图片展示了大集合和小集合的区别。
雷达里程计部分,要根据两帧点云,确定相对的位姿变换:
构建了目标函数以后,仍然采用LOAM中的列文伯格-马尔夸特优化算法,但是分了两阶段,第一阶段计算竖直维度的z,roll,pitch。(根据地面的平面点来优化)
第二阶段计算水平维度的x,y,yaw,根据边缘点来优化。 两次LM优化得到相同的精度,实验计算时间减少35%。
放一张图:yaw角就是绕垂直于上方的转轴旋转的角。机器人里,一般让正前方是x,左侧是y,头顶上方是z轴。(和下面图示的不一致,但是yaw角都是绕头顶的轴旋转的角,也叫“航向角”)
与LOAM一致,Lego-LOAM同样也是采用了一快一慢两个部分,快的Lidar Odometry 10Hz来计算相对变换,慢的Lidar Mapping 2Hz来计算世界坐标系下的位姿。相当于10Hz在2Hz的基础上递推。
Lego-LOAM不再存储所有的传感器点云数据,而是只存储特征点集(前述的大集合)。
LOAM采取的是map-to-map的优化,最近的十帧点云与10立方米内的全局地图进行匹配,主成分分析,构建点到线、点到面的误差;
Lego-LOAM采取的是scan-to-map的优化,scan为当前帧点云中的特征点集;map有两种取法:第一种,和LOAM中一致,10立方米;第二种,选一组时间上相近的特征点云,构建图优化问题。当前时刻的特征点云作为观测数据,当前位姿作为优化节点。
使用的优化库:不再是谷歌公司的Ceres,而是因子图优化库gtstam。
回顾:Cartographer中的回环检测:激光点云投影到栅格地图,暴力搜索全局地图,分支定界加速,确定初值以后用非线性优化精修;
Lego-LOAM中加入了回环检测,是单独用一个线程运行的。
流程:
第一步,寻找历史位姿:1.与当前位姿的距离上最近。2.与当前位姿间隔时间较长。(这样才是回环)
第二步,把历史位姿作为候选,用ICP算法迭代,修正位姿。
我们可以看出:1.相比Cartographer,Lego-LOAM的回环检测就是一个简单的回环检测,其默认偏移较小。如果偏移较大,就不能修正了。2.不具备重定位功能。因为这种算法的前提是需要知道自己的大致位置,和历史中附近的位置进行匹配,修正位姿。
Lego-LOAM有一个显著的缺陷——依赖地面。
如果用无人机,那么就难以确定地面了。 当然论文作者提到,对于无人机,则不提取地面点,直接就像LOAM中那样正常提取边缘点和平面点。但是我认为这样算法的核心优势就丢掉了。
保存的点云地图是稀疏的特征点地图,这也是此类算法的通病,地图有什么用?——可以用来辅助定位,却不能用来辅助路径规划。
这个问题准确的来说,应该叫“点云地图应该怎么用来路径规划”。 由于在导航任务中,定位、决策往往分为了两个不同的模块。定位部分不用考虑“我该怎么走”,决策部分不用考虑“我走到了哪里”。 所以在三维重建(3D Rescontruction)中,“定位”用来辅助“建图”;在SLAM中,“建图”用来辅助“定位”。因此构建的点云地图,对于定位模块够用了,但对于决策模块则不能使用。
目前,业界基本是属于三种思路: 1.构建稠密点云地图,构建八叉树地图,滤除地面信息,取中间高度; 2.语义SLAM,构建物体级别的地图。(需要深度学习参与) 3.构建稀疏点云地图计算位姿,然后根据传感器数据,实时进行点云地图与栅格地图的更新,之后稀疏点云地图用来定位,栅格地图用来规划。
LIO-SAM是TixiaoShan在2020年IROS发表的Lego-LOAM续作。 实际上也是Lego-LOAM的扩展版本,添加了IMU预积分因子和GPS因子。
使用了三种设备进行实验。
这部分是VIO领域的内容。我一直没有时间总结,之后更新完,会放一个链接在这里。
简单说一下吧:
(2)~(3) :IMU可以测量自身的加速度和角速度,但一般认为其测量数据包括了两大噪声:随机游走噪声 b + 高斯白噪声n。B表示body坐标系,即imu坐标系;W表示世界坐标系,R^BW表示了从世界坐标系转换至IMU坐标系;
(4)~(6) 分别表示t + ∆t 时间内,IMU的速度、位移和旋转; 注意,并非直接用原始数据积分,而是减去了随机游走b和高斯白噪声n。 bias未知,该变量也参与优化;
(7)~(8)为i到j时刻的预积分,即把它作为两时刻位姿的一个约束,参与整体的图优化过程。
雷达里程计部分主要得到两帧之间的位姿变换; 方法基本与LOAM或Lego-LOAM的一致。
区别:仅用关键帧和之前n+1个关键帧中的特征集合构成地图,进行匹配,构建点到线、点到面的约束; (原先是使用帧到帧的匹配)
关于这点,该方法应该没有使用Lego-LOAM的提取地面特征的方式,因为在实验部分,采用手持建图、轮船水面建图,可能不适合Lego-LOAM该方式。
收到一个GPS测量,即将其转换到笛卡尔坐标系下,构建一个新的约束;
时间戳不同步问题: 插值解决;
当估计的位置的协方差大于GPS位置协方差时,才插入一个约束因子。
我们可以看到,红色框住的部分,GPS并不是一直插入进去的。
该方法使用的回环检测方法,应该和Lego-LOAM中的一致; 搜索当前位置15m内的最近历史位置,使用该历史位置的前后分别12个关键帧的特征,和当前匹配,构建约束。
视觉-惯性里程计的著名工作——Vins-mono(香港科技大学沈劭劼团队于2018年发表在IEEE Transactions on Robotics上的工作,可以利用单目的视觉和IMU实现融合)可以达到非常好的效果,但是其需要一个初始化过程来估计:相机到IMU的外参,IMU的bias,重力向量的方向和尺度,相机到世界坐标系下的外参等……(非线性系统需要基于初值来不断优化)
简单的说: 单目相机无法观测实际尺度,因此就无法和具有实际尺度的IMU数据进行融合,必须经过一个初始化过程让二者联系在一起。Vins-mono在初始静止或匀速运动时,IMU没有加速度,初始化会失败,进而导致后续其他问题——这也是单目视觉惯性里程计的通病。 前述的激光SLAM大多在回环检测上存在问题(除Cartographer的暴力搜索以外),也就是说:给定一个地图,在没有历史轨迹的基础上,回环检测并不能确定自己在哪里。
LVI-SAM使用了两个子系统,视觉惯性系统(VIS)和雷达惯性系统(LIS):
1.视觉惯性系统用雷达惯性系统来初始化;——用LIS计算的位姿,作为VIS的初始优化值;
2.VIS中需要根据图像计算特征的深度,可以利用雷达的测量数据来辅助优化;
3. LIS计算两个点云位姿变换的优化初值,同样也可以用VIS的视觉估计来计算;
4. 回环检测可以用视觉信息确定初值,再用雷达数据优化。
视觉-惯性框架(VIS)基本上采用Vins-mono的思路,但是区别有三:
1.初始化位姿和IMU的初始bias直接由雷达-惯性框架来估计(前述 vins-mono缺陷)
2.特征像素的深度,从雷达数据中获取;(vins-mono是通过三角测量计算,不够准确)
3.检测失效:
问题:特征像素的深度,如何从雷达中获取?
a) 把视觉特征点和雷达点云,投影到归一化相机球体坐标系下,找到像素点最近的三个雷达点云,从而确立关联深度。 b) 周围的三个点如果自身差距太大(超过2m),则丢弃不要。
我们对LIS和LIO-SAM的框架做个对比:
LVI所采用的回环检测,与大多数视觉SLAM所采取的回环检测方法相同,为词袋模型。 这一点我以前做过总结:SLAM14讲学习笔记(八)回环检测
最初被用在信息检索领域:一句话是由单词组成的;通过各个单词出现的次数,可以得到一句话的向量。比较各个文档的向量,就可以比较文档的相似程度。
视觉SLAM用图像作为“文档”,用图像的特征点的描述子作为“单词”,计算各个图像的向量,比较相似程度。 可以看出这种方式是一种简单朴素的方式,因此许多工作集中于用深度学习来比较相似程度。
但与Lego-LOAM,LIO-LOAM等工作相比,显然这种方式可以在地图数据库中找到回环,而无需当前运动的历史轨迹。
其实关于固态雷达的内容,本来我们目前的机器人——四足机器人萝卜是要用多线机械雷达的,固态雷达是另外一个组的仿人机器人叫爱瑟尔的在用。不过既然开始调研工作了,就一起看了。
Livox-loam为香港大学于2019年开源的工作,其主要由两篇论文组成:
机械雷达:通过机械方式改变扫描方向;类似于一个激光笔,放在电机上旋转;十六线雷达,就是依次改变扫描的角度和高度,进行旋转。
固态雷达:通过阵列干涉改变扫描方向。类似于一个激光笔自己不动,改变激光射出的方向和角度。
左图为固态雷达的扫描轨迹线,可以看出,它是很杂乱的。
右图为固态雷达和多线雷达的视野对比。其实多线雷达也不是一条线一条线挨个扫的,看看velodyne的说明书就知道,它是上下跳着扫的,可能因为一些工艺的原因吧。这点我不是专业人士,我就不乱讲了。
livox-loam依然采用和LOAM一样的方式,选取边缘点和平面点。但是它和LOAM最大区别就是,在选取候选的特征点时,变得更加“小心”了。
四大原则:
1.接近视角边缘的点不要。说白了就是射线和x轴夹角大于17度的就不选。
2.反射强度太大或者太小的点不要。
R是目标反射率,D是点云到光心的距离。
目标反射率可以由雷达直接获得。
3.和平面夹角很小的点不要
4.部分被遮挡的点不要
选取特征点(边缘点,平面点)的方式和LOAM中一致(根据曲率),
还另外多一种选取方式: 利用反射强度信息: 如果相邻点的反射强度区别很大,也认为是一个边缘点。
计算位姿的目标函数,与LOAM中的一致,为点到线的距离(从边缘点中选点),点到面的距离(从平面点中选点),也采用协方差矩阵特征值的方式,提取边缘线和平面。
值的注意的是,固态激光雷达虽然是不动的,但是绝对不意味着所有点都像相机一样是同时获取的。
因此,每个点都是基于不同时间戳的。如果本身雷达自身处于运动状态,就会导致运动畸变。 算法采取了两种方式:线性插值和分段处理。
实验结果发现线性插值效果不太好,会有重影,因为遵循的是一帧激光之间是匀速运动的这个假设。实际上在运动畸变的去除上,一般采用IMU或者里程计来确定激光雷达在旋转一周时的位姿变换(当然固态雷达这里对应的是一帧数据,因为固态雷达是不转的)。
算法采用一种比较朴素的方式过滤外点和动态点:
Livox-loam的回环检测部分被单独列为一篇文章。
其和上面提到的LVI-LOAM的回环检测方式类似,都是使用视觉SLAM中的“词袋模型”来进行匹配。 对所有的关键帧提取特征,然后在回环检测阶段,把当前的特征和关键帧的特征进行比对,确立对应关系。
问题是:LVI-LOAM中是利用图像来提取特征的,(比如提取图像的各种类型的特征点),但是在livox-LOAM中并没有用到相机,那么对点云是如何提取抽象的“特征”用以依次匹配的呢?
其提取的特征,是基于2D直方图。
回忆:Cartographer3D中也是提取了特征直方图,不过和此处的不一致。
接下来就是核心内容:计算一帧对应的直方图,把这个直方图当作关键帧的特征。 之后将基于所有帧的直方图,比较相似性,建立匹配关系,确定回环。
直方图如何确定呢?
这个公式叫归一化互相关(NCC)。基本就是视觉slam中的内容。利用此公式,建立阈值,确定回环。
确定回环之后,之后的优化内容则依旧是利用图优化方法,建立约束,优化各个位姿节点。 注意:用到的库为Ceres(和Cartographer、LOAM相同。LOAM的续作均为因子图优化库gtsam)
https://blog.csdn.net/robinvista/article/details/104379087
LOAM笔记及A-LOAM源码阅读 - WellP.C - 博客园
激光雷达SLAM算法大全 - 知乎
LeGO-LOAM:轻量级地面优化的建图_try_again_later的博客-CSDN博客
LeGO-LOAM论文翻译(内容精简)_wykxwyc的博客-CSDN博客
lego-loam 同步构建2d栅格导航地图 - it610.com
lego-loam代码分析(1)-地面提取和点云类聚_jiajiading的博客-CSDN博客
LeGO-LOAM回环检测_Zlp19970106的博客-CSDN博客
cartographer 3D scan matching 理解 - 达达MFZ - 博客园
Cartographer源码阅读3D-回环计算-分支定界_yeluohanchan的博客-CSDN博客
Cartographer-[2]-系统参数配置说明 | EpsilonJohn's Blog
视觉雷达imu的多传感器融合定位和建图系统LVI-SAM论文阅读 - 知乎
论文笔记_S2D.66_ICRA_2021_LVI-SAM: 紧耦合的激光视觉惯导SLAM系统_惊鸿一博-CSDN博客
激光SLAM | 基于固态雷达的里程计:Loam Livox - 知乎
【泡泡图灵智库】Loam livox:一种用于小视场角激光雷达的快速、鲁棒、高精度的激光雷达里程计和建图包_扫描
其他SLAM相关内容详见:微鉴道长SLAM学习笔记(目录)
本人目前在研究院从事基于强化学习的导航决策和基于SLAM的导航定位,有相关问题,欢迎留言探讨。
毕竟本人水平有限,如果内容有误,感谢指正!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。