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);
避坑指南: 体素滤波会改变点的精确位置。如果你后续要做高精度配准(比如ICP),建议先降采样再配准,配准完再用原始点云做精化。我曾经直接拿降采样后的点云做地图,结果地图边缘全是锯齿,后来排查了半天才发现是体素滤波的锅。

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做帧间配准!我刚开始做的时候,直接把两帧原始点云丢进ICP,结果地图直接飞了。后来学乖了,先用轮速计或者IMU给一个初始猜测,再用ICP做精化。或者,用NDT做粗配准,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 本章知识体系

下面这张图,是我自己总结的点云地图构建核心流程。你可以把它当作一个检查清单,做项目时对着看,不容易漏步骤。

点云地图构建核心流程 原始点云 滤波去噪(体素滤波 + 统计滤波) 点云配准(ICP / NDT) ICP(点到点 / 点到面) NDT(概率分布配准) 点云地图(全局坐标系)

从图上可以看到,整个流程是线性的:原始点云 → 滤波去噪 → 配准 → 全局地图。但实际工程中,配准这一步往往需要反复迭代。比如,先用NDT粗配,再用ICP精配,然后做闭环检测修正漂移,最后再全局优化一次。

总结一下我的建议:
  • 滤波是基础,别省这一步。体素滤波降采样,统计滤波去噪点,两个配合使用效果最好。
  • 配准时,优先考虑NDT做粗配准,ICP做精配准。如果计算资源紧张,单用NDT也能接受。
  • 别忘了给配准一个合理的初始猜测。哪怕只是一个粗略的GPS+IMU位姿,也能让算法少走很多弯路。

好了,点云地图构建的核心内容就这些。下一节我们会讲如何用这些地图做定位——嗯,那又是另一个故事了。

可可精品资料库