你信任你的激光雷达吗?

声明:本文不是官方文档,亦不是某种形式的断言或结论,本文仅仅是技术讨论性质的文章,无论是否用了确定性的语气,作者都不保证内容的准确性和完整性,亦不明示或暗示此文章不是在胡说八道。(事实上,作者过去常常胡说八道并乐此不彼)。因此,所有因采用本文章涉及的方法、数据或其他任何信息,所造成的直接或间接损害,包括但不限于生命和财产损失,作者、撰写团队和平台概不负责。

大部分人使用激光雷达的时候,都会选择无条件相信激光雷达厂家,以及那个来路不明的 ROS 驱动。

多数情况下,雷达一通电,你就能在 Rviz 上看到漂亮的点云。

我猜,很多人(包括我)心底都有一个声音,「行了,这就可以了,不要没事找事了」。至于雷达驱动中的各项参数,那简直就是大象身上的虱子,不值一提。

确实,作为开发者,我们常常被教导要抓住事物的主要矛盾,雷达的质量和精度,交给供应商来保证好了。

可问题是,我真的可以毫无保留的信任厂家和 GitHub 上长篇大论的代码么?

你信任你的激光雷达吗?

更进一步,你或许不爽激光雷达的精度久已,你想自己动手进行校准。不管你动用哪种方法,有监督无监督,有标靶无标靶,各种暗黑科技。

提升雷达精度的头号问题是,你该动哪些参数呢?

很多论文都是假定激光雷达的 Raw Data 是从原点出发,基于「多余测量」的思想,用平差模型从外向内修正。

不过这次,我们不是要修正雷达,而是要从雷达本身,去理解雷达的校准和补偿,所以,我打算从内向外来讨论一下。

我们以 Velodyne 激光雷达 HDL-64E S3 的 ROS 驱动为例,来详细了解一下这些参数问题。

Velodyne HDL-64E S3 是一款非常经典和优秀的激光雷达,曾是无数无人车形象的标志性特征。

当然,它推出有一些年头了,不能说老态龙钟,但是产品生命周期已经步入晚年了,有时候你需要站在更高的角度重新审视这款雷达,来复盘一下,它所代表的这一类机械旋转式雷达,有哪些优缺点,基本校准参数是怎么组成和相互作用的?

更近一步,这些雷达的精度和性能,被完全挖掘了么?你所信赖的 ROS 驱动,都写对了么?

举个例子:

你信任你的激光雷达吗?

上图是目前使用最多的雷达 ROS 驱动程序,不管你信不信这个神秘的数学模型,反正我不信,这十分令人费解。

我们之后会详细分析,为什么说这里应该有问题。遗憾的是,用户很难发现这个问题,因为,它会引起部分激光 25 米以上时,10cm 左右的测距误差。

这原本没有什么,你的车上不会装一堆高精度测距设备相互交叉验证,但你如果有很多雷达和测距设备(大部分人没有),大家在一起工作的时候,你就会发现不对劲。更有甚者,线与线之间,表现都感觉不太一致。

这里就产生一个很奇怪的问题,激光雷达作为一个单纯的测距设备,为什么还要弄个内参文件,还定义那么多个校准参数?

64 线的激光雷达,校准参数有 576 个之多(当然,有些其他型号的雷达生产改进了,于是把一部分参数填 0 了,但这些参数本身仍然存在)。

即便是对每一束激光,都有多达 9 个校准参数,这不得不使人心生疑问,为什么要这么多校准参数?

你信任你的激光雷达吗?

当然,我们会一个个讲,这些参数是什么意思。

篇幅所限,我们先讲几个,余下的,我们之后的文章接着讲。

因为加工问题,激光雷达的自身的坐标系,很难从雷达中心点出发。

64 线激光雷达是一个收发异轴的光学系统(其实所有的机械雷达都是),也就是说,发射出去的激光光路,和返回的激光光路,并不重合。

这主要是因为激光发射器和接收器不能做在一起导致的。现在很多方案,都是向着共轴努力,此为后话。

我们还是以经典的机械式雷达为例:

你信任你的激光雷达吗?

打在墙上的光斑,一部分形成漫反射,有一小部分光会回到激光雷达,并被接收光学系统和接受器接收。

这个光斑的坐标,本来应该以激光雷达的底部中心点为坐标系原点。

然而,它做不到,它甚至不关心原点在哪里,理论上得到的粗略目标距离,是上图的 (D1+D2+D3+D4)/2,根据几何光学的一般规律,D1 和 D3 是同一条直线,D2 和 D4 可不一定(因为接收器雪崩二极管粘死在背板上,无法移动)。

这引来一个好问题:雷达中心原点 O 到目标光斑 P 的距离,怎么换算?

答案是,存在一个虚拟的逻辑点 M,我们认为激光是从 M 点发射,并在 M 点完成接收,很显然,M 点存在于 D3 和 D4 之间,我们经过粗校准后的距离值,也就是对激光雷达的 Distance 输出值,进行了固定补偿,或者线性补偿(两点修正)之后的值,要等于这个 PM。

那如何补偿呢?

激光雷达的测距精度,随着距离的变化而变化。有几个原因:

1. 我们这里说的激光雷达,是指 TOF 激光雷达,TOF 测距,靠的是 TDC 电路提供计时,用光速乘以时间再除以 2 得到距离,但限于成本,TDC 一般由 FPGA 的进位链实现,本质上是对一个低频的晶振信号做差值,实现高频的计数。所以,测距的精度,强烈依赖于这个晶振的精度。而晶振随着时间的推移,存在累计误差;

2. 距离越远,接收信号越弱,雷达自身的寻峰算法越难以定位到最佳接收时刻,这也造成了精度的劣化;

3. 万能的其他原因;

于是,我们可以假定一个最简单的情况,线性关系(实际上并不存在这样简单的线性关系,不过我们先这么假定),即:D = (1+A)*d + B。

其中,d 表示测量值,A 表示线性系数,B 表示固定补偿值,D 表示真值。

补偿之后的 M 点,将会落在 OM 垂直于 MP 处。

写到这里,我们就发现第一个问题,

64 线雷达(至少是说明书)偷了一个大懒,它对 25 米以上的目标,采用固定补偿,而对 25 米以下的目标,进行线性补偿。(也就是两点修正法 Two Point Calibration Methodology)

它为什么这么做,因为,它并不关心 25 米以上目标的精度,无人车嘛,要那么精确干嘛?

所以,合理地说,64 线雷达,25 米以上的精度,并不是特别高,至少不像说明书中描述的那样高,正负 3 厘米我个人是持保留意见的。

这个两点修正法也是个大瓜,简直是各显神通,我们之后再讲,我们先讨论 25 米以上的问题:

你信任你的激光雷达吗?

于是,这个固定补偿值 B,就是我们 xml 文件中的:distCorrection_,也是 ROS 驱动中的:corrections.dist_correction。

你信任你的激光雷达吗?

为什么是 25 米,确切的说是 25.04 米,这是因为雷达生产时,25.04 米外刚好设置了一个标靶,仅此而已。而且,这个 25 米的标靶,应该是他们最远的标靶。

正确的代码应该怎么写?

你信任你的激光雷达吗?

于是,更多的疑问会产生,他们为什么要在 xy 投影上加个尾巴:

vert_offset * sin_vert_angle?

有时候,代码会告诉你一段尘封的历史,就像在 shell 下输入 cal 9 1752 查看 1752 年的 9 月日历,你会惊奇的发现这个月只有 21 天,从 2 号起直接走到 14 号。

你信任你的激光雷达吗?

很奇怪吧。

1582 年 2 月,因为儒略历误差问题,罗马教皇格里高利十三世要求从 1582 年 10 月中减去 10 天,意大利、西班牙等天主教国家都谨尊圣谕。

但是英国因为亨利八世离婚问题跟罗马教廷反目,成了新教国家,所以就不愿意修改,直到近 200 年后的 1752 年 9 月,英国及其殖民地(包括美国)才被执行。

这样 1752 年 9 月 2 日后面跟着的就是 1752 年 9 月 14 日。这就是为什么 cal 会生成上面输出的原因了。

这个雷达也是一样,我们现在是这样认为的:

雷达的 raw data 输出的测量值 distance,在 25 米以上的距离,加上一个固定修正值 distCorrection_,即 distance += corrections.dist_correction 后,即 PM。

你信任你的激光雷达吗?

然而,以前并不是这样的。我们先放一放,上文中,激光收发平面是指什么?

我们详细解释一下,雷达从前向后看:

你信任你的激光雷达吗?

我们对比一下照片:

你信任你的激光雷达吗?

(有透镜的一侧,我们称之为「前面」)

下图反过来,是从后向前看,我们把激光编号和接收器编号标上,

你信任你的激光雷达吗?

激光编号和接收器编号的一一对应关系:

你信任你的激光雷达吗?

这里,我们回答了上文的问题:「每对激光收发器中,收和发的装置,都在同一个平面上」。

换句话说,激光发射路径的俯仰角(vertical angle)是-10.15 度,那么,激光反射路径的竖直角,也是-10.15 度。这在工厂加工时,就被如此排列。

我们接着讲校准参数,先从最好理解的 vertCorrection 开始:

你信任你的激光雷达吗?

激光光斑在最后需要呈现笛卡尔坐标系的坐标,要基于底部中心点,在下图中:θ1 和θ2 是激光俯仰角,这个数据,就是 XML 文件中的「vertCorrection_」。

另外:雷达内部设计尺寸如下:

你信任你的激光雷达吗?

所以,除了 vertCorrection_,还有一个 vertOffsetCorrection_:

你信任你的激光雷达吗?

它是可以被计算出来的,以上图 UpperBlock 为例:

vertOffsetCorrection_ =7.1905 x tan(- θ1) + 20.6573 cm

(θ1 为啥是负的呢,因为θ1 是个负角度,当然这个公式对θ1 是正角度时,同样适用)

Lower Block 中,是这样:

vertOffsetCorrection_ = 6.2139x tan(- θ2) + 13.415 cm

这样的话,我们就把 xml 文件中的两个量,联系起来了:

你信任你的激光雷达吗?

我们可以用一个 xml 文件中的数据验证下:

21.734091 = 7.1905 x tan(8.5167751)+ 20.6573

发现奥秘了吧。

现在回过头来,讲一讲,他们为什么要在 ROS 驱动的 xy 投影上加个尾巴?

float xy_distance = distance * cos_vert_angle - vert_offset * sin_vert_angle;

vert_offset * sin_vert_angle 的几何意义,是下图中的 O’N,其中 PN 垂直于 O’N。

你信任你的激光雷达吗?

以前他们认为:经过固定值修正的 distance,更接近这个 NP,所以在 XY 平面的投影,需要增加一点数值,vert_offset * sin_vert_angle 只是一个估计的距离值,并不是严格的几何关系,严格的几何关系应该是:

float xy_distance = distance * cos_vert_angle - vert_offset * sin_vert_angle* cos_vert_angle

但是,很快,他们就意识到这是有问题的,因为 vert_offset * sin_vert_angle 也几乎等于一个固定值,这样表达是没有任何意义的。

所以,在说明书上,还留下了这个痕迹:

你信任你的激光雷达吗?

作为对比,我们看一下 Velodyne 官方的 Veloview 是怎么写的,显然 Veloview 就没有加这个尾巴:

你信任你的激光雷达吗?

很可惜,ROS 驱动的作者没有改过来,所以,全世界但凡使用 ROS 驱动 Velodyne 64 线的用户,大家一直就这么沿用了这个疑似有问题的代码。

单单是这个地方,就会引来全量程最大 10cm 左右的测距误差。不可思议吧!

不过,这个雷达好像进入生命周期的末尾了,驱动也稳定很久了,所以也没有必要再建议他们动 master 分支,本文主要的目的不在于批判这款雷达,而在于和大家一起探讨校准参数的问题,所以为这点小事耽误大神们的宝贵时间是完全不值得的。

(未完待续。下一篇,我们会接着讲解其他的校准参数,不要走开哦!)

P.S.汽车之心开始招募专栏作者了,只要你乐于分享,是智能网联、自动驾驶、智能座舱、动力电池等领域的从业者或观察者,欢迎扫描上方二维码或添加微信 autobitxyz 了解详情。在这里,我们一起鼓捣些智能汽车领域的烧脑知识。


分享到:


相關文章: