3、点云地图构建:激光雷达点云原理、点云滤波与去噪、点云配准
各位同学,今天我们来聊聊点云地图构建。说实话,这是整个高精地图管线里最「硬核」的部分之一。我当年刚入行时,觉得点云就是一堆密密麻麻的坐标点,没什么技术含量。直到第一次自己动手建图,发现地图里全是噪点、重影,车跑上去定位直接飘飞——嗯,从那以后我再也不敢小看这一步了。
点云地图构建,说白了就是三个核心环节:理解点云怎么来的、把脏数据洗干净、把多帧点云拼成一张完整地图。我们一个一个来拆解。
3.1 激光雷达点云原理
先说说点云是怎么产生的。激光雷达发射激光束,打到物体表面反射回来,通过测量飞行时间(ToF)或者相位差,算出距离。再结合激光雷达自身的旋转角度,就能得到每个点的三维坐标 (x, y, z)。
我习惯把激光雷达分成两类:机械式和固态式。机械式就是大家常见的16线、32线、64线那种,里面有个旋转电机,一圈一圈地扫。固态式则用光学相控阵或者MEMS微镜,没有旋转部件,寿命更长,但视场角通常小一些。
这里有个关键点:点云是稀疏的。你想想看,一个64线激光雷达,每秒也就出几十万个点。跟相机动辄几百万像素比,差了一个数量级。所以点云处理的核心思路,就是用有限的数据去还原环境的结构。
3.2 点云滤波与去噪
原始点云里什么妖魔鬼怪都有:空气中的灰尘、雨滴、镜面反射的假点、雷达自身的噪声……如果不处理,后面配准和建图全是坑。
常用的滤波方法,我重点讲两个:体素滤波和统计滤波。
3.2.1 体素滤波(Voxel Filter)
体素滤波的思路很简单:把空间划分成一个个小立方体(体素),每个体素内只保留一个点(通常是重心点)。这样既能降采样,又能保持点云的几何结构。
体素大小是关键参数。设得太小,降采样效果不明显;设得太大,细节全丢了。我个人习惯在城区场景用 0.2m 的体素,高速场景可以放宽到 0.5m。
// 伪代码示例:体素滤波
VoxelGrid voxel;
voxel.setInputCloud(cloud_in);
voxel.setLeafSize(0.2f, 0.2f, 0.2f); // 体素边长0.2米
voxel.filter(cloud_out);
3.2.2 统计滤波(Statistical Outlier Removal)
统计滤波用来去除离群点。它的原理是:计算每个点到其k个近邻的平均距离,如果这个距离超过全局均值的一定标准差,就认为是离群点。
说白了,就是「大家都聚在一起,你一个人跑那么远,肯定有问题」。
| 参数 | 含义 | 推荐值 |
|---|---|---|
| k(近邻数) | 计算平均距离时考虑的邻居数量 | 50 ~ 100 |
| std_dev(标准差倍数) | 判定离群点的阈值 | 1.0 ~ 2.0 |
为什么推荐这个范围?k太小,统计结果不稳定;k太大,计算量上去了。std_dev设1.0比较严格,适合室内场景;室外场景有树叶、行人等动态物体,建议设1.5或2.0,避免把正常点误删。
3.3 点云配准
配准,就是把不同位置采集的点云对齐到同一个坐标系下。这是建图的核心,也是我花时间最多的部分。
主流算法有两个:ICP 和 NDT。我分别讲讲它们的原理和我的使用心得。
3.3.1 ICP算法(Iterative Closest Point)
ICP的思路很直观:对于源点云中的每个点,在目标点云中找到最近邻点,然后求解一个刚体变换(旋转+平移),使得这些点对的距离平方和最小。迭代这个过程,直到收敛。
但ICP有个致命弱点:对初始位姿敏感。如果两帧点云初始偏差太大,ICP很容易陷入局部最优,配准结果完全不对。
ICP的变种很多,比如Point-to-Plane ICP(点到面),比标准的Point-to-Point(点到点)收敛更快、精度更高。我个人习惯用Point-to-Plane,尤其是在地面平坦的场景下。
3.3.2 NDT算法(Normal Distributions Transform)
NDT跟ICP思路完全不同。它不直接匹配点,而是把点云用概率分布来表示。具体来说,把空间划分成网格,每个网格内计算点云的高斯分布(均值和协方差)。配准时,最大化源点云落在目标点云网格中的概率。
NDT的好处是:对初始位姿不那么敏感,而且计算效率高。我一般在以下场景优先用NDT:
- 初始位姿不确定时(比如GPS信号丢失后重定位)
- 点云密度不均匀时(NDT对密度变化不敏感)
- 需要快速粗配准时
但NDT也有缺点:网格大小不好调。网格太大,精度不够;网格太小,概率分布不稳定。我一般从 2m 开始试,根据场景调整。
// 伪代码示例:NDT配准
NormalDistributionsTransform ndt;
ndt.setTransformationEpsilon(0.01); // 收敛阈值
ndt.setStepSize(0.1); // 步长
ndt.setResolution(2.0); // 网格大小(米)
ndt.setInputSource(source_cloud);
ndt.setInputTarget(target_cloud);
Eigen::Matrix4f guess = Eigen::Matrix4f::Identity(); // 初始猜测
ndt.align(*output_cloud, guess);
3.4 本章知识体系
下面这张图,是我自己总结的点云地图构建核心流程。你可以把它当作一个检查清单,做项目时对着看,不容易漏步骤。
从图上可以看到,整个流程是线性的:原始点云 → 滤波去噪 → 配准 → 全局地图。但实际工程中,配准这一步往往需要反复迭代。比如,先用NDT粗配,再用ICP精配,然后做闭环检测修正漂移,最后再全局优化一次。
- 滤波是基础,别省这一步。体素滤波降采样,统计滤波去噪点,两个配合使用效果最好。
- 配准时,优先考虑NDT做粗配准,ICP做精配准。如果计算资源紧张,单用NDT也能接受。
- 别忘了给配准一个合理的初始猜测。哪怕只是一个粗略的GPS+IMU位姿,也能让算法少走很多弯路。
好了,点云地图构建的核心内容就这些。下一节我们会讲如何用这些地图做定位——嗯,那又是另一个故事了。