传感器数据预处理:激光雷达点云滤波与地面去除,毫米波雷达数据解析与聚类

大家好,我是你们的老朋友。今天咱们聊聊传感器数据预处理这块硬骨头。

说实话,很多同学觉得感知算法就是调模型、跑网络。但我在项目里吃过太多亏了——数据预处理没做好,后面再怎么调参都是白搭。你想想看,垃圾进垃圾出,这个道理在自动驾驶里特别明显。

一、激光雷达点云滤波

激光雷达出来的原始点云,数据量巨大,而且噪声不少。我习惯先做滤波,把没用的点去掉,把有用的点留下来。

1.1 体素滤波(Voxel Filter)

体素滤波说白了就是降采样。把空间划分成小立方体,每个立方体里只保留一个点。这样数据量能减少一大半。

// PCL 中的体素滤波示例
pcl::VoxelGrid<pcl::PointXYZ> voxel_filter;
voxel_filter.setInputCloud(cloud);
voxel_filter.setLeafSize(0.1f, 0.1f, 0.1f);  // 10cm 体素
voxel_filter.filter(*cloud_filtered);

体素大小怎么选?我一般看场景。高速场景用 0.2m,城区场景用 0.1m。太小了计算量大,太大了细节丢失。

我的经验:体素滤波后记得检查点云密度。如果某个区域点太少,可能是体素设太大了。

1.2 直通滤波(PassThrough Filter)

这个更简单。我只保留感兴趣区域内的点。比如高度方向,我只保留地面以上 0.5m 到 3m 的点。太高的点(比如天桥)和太低的点(地面噪声)都去掉。

pcl::PassThrough<pcl::PointXYZ> pass;
pass.setInputCloud(cloud);
pass.setFilterFieldName("z");
pass.setFilterLimits(0.5, 3.0);
pass.filter(*cloud_filtered);
注意:直通滤波的阈值要根据传感器安装位置调整。我曾经在项目里直接用默认值,结果把路沿都滤掉了,导致后续障碍物检测漏检。

二、地面去除

地面点对障碍物检测来说是干扰。我常用的方法是 RANSAC 平面拟合。

2.1 RANSAC 平面拟合

原理很简单:随机选三个点拟合平面,计算其他点到平面的距离,距离小于阈值的算内点。重复多次,取内点最多的平面。

pcl::SACSegmentation<pcl::PointXYZ> seg;
seg.setOptimizeCoefficients(true);
seg.setModelType(pcl::SACMODEL_PLANE);
seg.setMethodType(pcl::SAC_RANSAC);
seg.setDistanceThreshold(0.15);  // 15cm 阈值
seg.setInputCloud(cloud);
seg.segment(*inliers, *coefficients);

阈值设多少?我一般设 0.1-0.2m。太大容易把低矮障碍物当地面,太小地面去不干净。

关键点:地面去除后一定要做可视化检查。我见过太多案例,地面去得太干净,把路沿、减速带都去掉了,结果车辆在路口无法正确识别障碍物。

2.2 基于高度图的快速地面分割

如果计算资源有限,可以用高度图法。把点云投影到网格上,每个网格取最低点作为地面候选。这个方法快,但精度不如 RANSAC。

我个人习惯:高速场景用高度图法,城区复杂场景用 RANSAC。你想想看,高速上地面平坦,高度图够用了;城区有坡道、减速带,还是 RANSAC 靠谱。

三、毫米波雷达数据解析

毫米波雷达的数据格式各家不一样。我接触过 Continental、Bosch、华为的雷达,解析方式大同小异。

3.1 CAN 数据解析

毫米波雷达通常走 CAN 总线。数据包里有目标 ID、距离、速度、角度、RCS 等信息。

// 以 Continental ARS408 为例
struct RadarObject {
    uint8_t id;          // 目标 ID
    float distance;      // 距离 (m)
    float velocity;      // 相对速度 (m/s)
    float azimuth;       // 方位角 (rad)
    float rcs;           // 雷达散射截面 (dBsm)
};

解析时要注意字节序和缩放因子。我踩过坑——有一次没注意缩放因子,距离算出来差了 10 倍,车都跑到地图外面去了。

避坑指南:解析完数据后,先打印几个目标看看数值是否合理。比如距离 100m 的目标,速度 20m/s,这些值应该符合物理常识。

3.2 数据有效性检查

毫米波雷达会有虚警。我一般做三步检查:

  • 距离范围检查:目标距离必须在雷达探测范围内
  • 速度合理性:相对速度不能超过物理极限(比如 100m/s)
  • RCS 阈值:RCS 太小的目标可能是噪声

四、毫米波雷达聚类

毫米波雷达的点比激光雷达稀疏得多。我常用的聚类方法是 DBSCAN。

4.1 DBSCAN 聚类

DBSCAN 不需要指定类别数,适合雷达这种点分布不均匀的情况。

from sklearn.cluster import DBSCAN

# 输入:雷达目标列表 [x, y, velocity]
clustering = DBSCAN(eps=2.0, min_samples=3).fit(radar_points)
labels = clustering.labels_

参数怎么调?eps 是邻域半径,我一般设 1.5-3m。min_samples 是最少点数,雷达点少,设 2-3 就够了。

注意:雷达聚类时不要把静止目标和运动目标混在一起。我习惯先按速度分组,再分别聚类。

4.2 聚类后处理

聚类完还要做后处理:

  • 计算每个聚类的中心点、平均速度
  • 过滤掉点数太少的聚类(可能是噪声)
  • 合并距离很近的聚类

嗯,这里要注意:雷达的横向分辨率不如纵向。所以聚类时,横向的 eps 可以设大一点。

五、本章知识体系

我把整个流程画了张图,方便你理解:

传感器数据预处理流程 激光雷达点云 体素滤波(降采样) 直通滤波(ROI提取) 地面去除(RANSAC/高度图) 输出:非地面点云 毫米波雷达数据 CAN数据解析(ID/距离/速度/角度) 数据有效性检查(距离/速度/RCS) DBSCAN聚类(按速度分组) 输出:目标聚类结果 后续融合 预处理目标:干净、准确、低延迟 激光雷达:滤波 → 地面去除 → 非地面点 毫米波雷达:解析 → 检查 → 聚类 → 目标列表

这张图把两个传感器的处理流程串起来了。左边是激光雷达,右边是毫米波雷达。两条线最后汇合到融合模块。

好了,这一章的内容就这些。数据预处理看起来简单,但做扎实了,后面的障碍物检测会省很多事。我当年就是在这上面吃了不少亏,才慢慢总结出这些经验。

核心要点:
  • 体素滤波的体素大小要按场景调整
  • 地面去除的阈值要可视化验证
  • 毫米波雷达解析注意字节序和缩放因子
  • DBSCAN聚类时先按速度分组

可可精品资料库