JOVANA
Library Glossary Getting Started Three Levels Fields How it works Mission
Join the mission
All guides

位姿图、相机与激光雷达

现代 SLAM 把位姿组织成一张待理顺的图,并权衡用相机看世界与用激光看世界的优劣。

把后端看成一张图

到现在你已经知道,SLAM 要求机器人一边确定自己在哪里,一边绘制它赖以定位的那张地图。前面几节把这件事拆成两半:前端把原始传感器数据转成测量值,后端把所有信息融合成一个一致的估计——这就是前端/后端的分工。本节讲的是现代后端,而思考它最主流的方式非常直观:把它看成一张

位姿图 SLAM中,机器人停留过的每个位置都是一个节点,里面装着一个位姿——也就是位置加朝向的猜测。节点之间的边就是测量值:「从这里,我向前开了两米,再稍微左转。」每条边都是一个约束,规定了两个位姿之间应有的关系。关键在于,这些边彼此略有矛盾,因为每次测量都带着噪声。这张图被「过度约束」,还略微自相矛盾,而后端的任务,就是找出那唯一一种位姿排布,让所有这些带噪约束尽可能都得到满足。

藏在它背后、更一般的表述是因子图。在因子图里,我们想估计的量(位姿,有时还有路标位置)是一类节点;而每个测量都化作一个小函数——一个因子——用来打分:一组候选取值把这次观测解释得有多好。位姿图其实就是因子图的一个特例,只不过它的因子恰好全是位姿对位姿的约束。因子图是现代 SLAM 库真正使用的语言,因为它让你能把里程计、回环、GPS 与路标观测,全都整齐地装进同一个结构里。

把图拉紧

有一个画面能让位姿图 SLAM 一下子说得通。把每个节点想象成一颗珠子,每条边想象成一根小弹簧。每根弹簧都有一个「自然长度」——也就是那次测量,它认为两颗珠子之间应有的距离和转角。当珠子摆错了位置,弹簧就被拉长或压扁,从而储存了能量。所有弹簧储存的总能量,就是总误差。所谓优化,无非是松手放开这些珠子,让弹簧把一切拉扯到一个它们都能接受、能量最低的形状。

弹簧并非一样硬,这一点很重要。一个很有把握的测量——比如一次干净利落的激光扫描匹配——就是一根很硬的弹簧,强烈抗拒被拉伸;一个含糊的测量则是一根软弹簧,优化器几乎不付代价就能把它弯一弯。这种「软硬」恰恰就是测量的确定度(严格地说,是其协方差的逆)。当优化器把整张图安顿下来时,硬弹簧几乎不动,软弹簧吸收掉大部分误差——这正是我们希望「信任」流动的方式。

total_error = 0
for each edge (i, j) with measurement z and stiffness W:
    predicted = relative_pose(node[i], node[j])
    residual  = predicted - z          # how wrong this edge is
    total_error += residual^T * W * residual   # stiff W -> costly
# adjust all nodes to make total_error as small as possible
每条边都加一份罚分;硬边(W 较大)代价更高,所以求解器会先弯软边。

用相机看世界

无论用什么传感器去填那些边,图本身都是一样的——但传感器的选择,会彻底改变成本、鲁棒性,以及你最终得到的地图类型。第一大门类是视觉 SLAM,它用普通相机图像来建图。它的吸引力一目了然:相机便宜、轻、功耗低,而一张图像信息量惊人——纹理、颜色、标识、人脸,应有尽有。从一帧到下一帧,系统用特征描述子追踪那些可辨认的图像点,再反推相机必定如何移动,才会让这些点按观察到的方式偏移。

这种丰富恰恰也是视觉 SLAM 的软肋。相机看到的是光,而不是几何,因此它任由光照摆布。开进漆黑的隧道、对着一面空白的白墙、掠过一扇刺眼的窗户,或者面对一条没有纹理的走廊,可追踪的点就会消失——系统恰好在你最需要它的时候变成了瞎子。此外,单只普通相机无法从一张图像读出绝对尺度:它能看出有东西动了,却分不清眼前是一米外的玩具屋,还是远处一栋真房子。这正是视觉系统通常要再借一只眼睛或另一种感官的原因。

常见的补救都很实际。用双目相机或 RGB-D 相机能恢复真实距离,直接解决尺度问题。更好的做法,是把相机与惯性传感器配对——即视觉惯性里程计——让二者互补彼此的盲区:在相机短暂致盲的瞬间,由惯性传感器撑住估计;而相机又反过来约束惯性传感器那种缓慢的漂移。便宜、丰富、却怕光:一句话,这就是用相机的「划算账」。

用激光看世界

另一大门类是激光雷达 SLAM。激光雷达发出激光脉冲并对回波计时,所以它不是「推断」距离——而是直接测量距离,每秒数十万到数百万个点,从而生成点云:一团密集的三维点喷雾,勾勒出机器人周围每一个表面。因为它自带光源,激光雷达在漆黑中工作得和白天一样好,也根本不在乎墙面是有花纹还是一片空白。视觉要去「猜」几何,激光雷达却直接把几何递到你手里。

那么,激光又是怎样给出图的边的呢?靠扫描匹配:拿来刚才采到的那团点云和现在采到的这团点云,找出一组旋转和平移,让其中一团最严丝合缝地滑到另一团上。能让两次扫描对齐的那个运动,恰好就是机器人在这之间的移动。这里的主力算法是ICP——迭代最近点——它的循环简单得近乎让人不好意思,而这正是它历经数十年仍屹立不倒的原因之一。

  1. 对新扫描中的每个点,在旧扫描里找出离它最近的点,暂且把它们当作同一处表面——一次猜测的对应关系。
  2. 计算出唯一的一组旋转和平移,使这些配对点平均而言被拉得最近。
  3. 把这个运动施加到新扫描上,让它朝旧扫描挪过去。
  4. 重复:最近点的猜测越来越准,贴合越来越紧,几轮之后两团点云便严丝合缝地咬合在一起。累积下来的运动,就是你要的那条边。

激光雷达的取舍恰与视觉相对。它的几何精确、且不怕光照,但传感器更重、更贵、更耗电;而一团裸点云虽几何上完美,语义上却是「哑」的——它知道那里有个表面,却不知道那是一扇门还是一个人。ICP 在几何重复的地方也容易被骗:一条又长又没特征的走廊,无论你是否向前滑了一米,看上去都一个样,于是扫描可以沿着它自由滑动,估计随之漂移。实践中,这正是为什么稳健的系统会把两个世界融合在一起——用激光提供坚实的结构,用相机赋予含义。

前沿:更丰富、更聪明、能终身运行

经典 SLAM 满足于一副稀疏的骨架——只要有足够多的路标可供定位就行。而前沿想要的更多。稠密建图重建出完整连续的表面,于是机器人拿到的不再是一团散点,而是一个滴水不漏的模型,可以在其中规划路径,甚至直接渲染。语义建图更进一步,借助语义分割之类的工具给几何赋予含义:这一块是地板,那是一把椅子,那是一道门。一张知道「东西是什么」的地图,机器人就能对它进行推理,而不只是绕开它。

在前端,手工设计的特征检测器正越来越多地与「学习得到的特征」并肩工作——这些神经网络经过训练,专挑那些在严苛光照、天气和视角变化下依然可辨认的点。这类学习描述子尤其擅长为回环做地点识别,能看出两张看起来天差地别的图像,其实是同一个房间角落。底下的图和优化器几乎纹丝不动;悄然飞跃的,是喂给它们的那些边的质量。

最棘手的开放难题是终身 SLAM:在一个拒绝静止的世界里,让一张地图维持数月仍然可用。家具会挪动,季节会更替,店铺会重新粉刷,停着的车来来去去。一张定格在初见那一刻的地图,会慢慢变成一个谎言。终身系统必须判断:什么该当作永久的来信任,什么该当作短暂的来遗忘,以及如何更新这张图而不让它无止境地膨胀下去——一个长住某地的机器人,应该随着时间越来越会在那里穿行,而不是越来越糊涂。