第4章:环境感知:障碍物检测与分割,点云处理入门
环境感知,说白了就是让机器人「看见」周围的世界。我刚开始做机器人那会儿,用的还是超声波和红外传感器,那叫一个痛苦——碰到玻璃墙直接穿模,遇到黑色物体直接失联。后来接触了激光雷达和点云处理,才算是真正打开了新世界的大门。
这一章,我们就来聊聊怎么用点云数据做障碍物检测与分割。嗯,这里要注意,点云处理不是简单的「看图说话」,它背后有一套完整的数学逻辑和工程技巧。
4.1 点云数据长什么样?
点云,就是一堆三维坐标点的集合。每个点通常包含 (x, y, z) 坐标,有些还带有强度值(intensity)或颜色信息。你可以把它想象成「用几万个点给世界拍了一张3D照片」。
核心概念:点云 ≠ 图像。图像是规则网格,点云是无序的散点。这意味着你不能直接用卷积神经网络去处理原始点云——顺序一变,数据就变了。
我在项目中遇到过一个问题:同一个障碍物,从不同角度扫描,点云的分布完全不同。后来我意识到,点云处理的关键不是「点在哪」,而是「点与点之间的关系」。
4.2 点云预处理:先让数据干净起来
原始点云数据通常很脏。传感器噪声、地面点、离群点……如果不处理,后面的障碍物检测就是空中楼阁。
4.2.1 直通滤波(PassThrough Filter)
说白了就是切一刀。我只关心前方10米内的障碍物,那10米以外的点直接扔掉。这能大幅减少计算量。
// C++ 伪代码示例
pcl::PassThrough<pcl::PointXYZ> pass;
pass.setInputCloud(cloud);
pass.setFilterFieldName("z"); // 沿Z轴过滤
pass.setFilterLimits(0.0, 2.0); // 只保留0~2米高度范围
pass.filter(*cloud_filtered);
4.2.2 体素滤波(VoxelGrid Filter)
点云太密了怎么办?用体素网格降采样。每个小立方体里只保留一个重心点。我习惯把体素大小设为0.05米,既保留细节,又不会让计算爆炸。
我的经验:体素大小不要小于激光雷达的角分辨率。否则降采样后反而引入伪影。我曾经在这上面吃过亏,调试了整整两天才发现是体素设得太小了。
4.2.3 统计滤波(StatisticalOutlierRemoval)
离群点怎么处理?统计每个点与邻居的平均距离,如果偏离太大,就判定为噪声。嗯,这个方法在室内场景特别好用。
4.3 地面分割:把路和障碍物分开
机器人要导航,首先得知道「哪里能走」。地面分割就是把地面点云和非地面点云分开。我个人最常用的是RANSAC平面拟合。
为什么会用RANSAC?因为地面不一定是完美的平面,但大部分情况下可以用一个平面模型近似。RANSAC能容忍一定比例的离群点,正好适合处理地面上的小石子、减速带等。
// RANSAC 平面分割示例
pcl::SACSegmentation<pcl::PointXYZ> seg;
seg.setOptimizeCoefficients(true);
seg.setModelType(pcl::SACMODEL_PLANE);
seg.setMethodType(pcl::SAC_RANSAC);
seg.setDistanceThreshold(0.1); // 距离阈值0.1米
seg.setInputCloud(cloud);
seg.segment(*inliers, *coefficients);
注意:RANSAC的阈值设置很关键。设大了会把低矮障碍物当成地面,设小了会把地面凸起当成障碍物。我一般先看激光雷达的安装高度,再结合路面平整度来调。没有万能参数,每个场景都得试。
4.4 障碍物聚类:把点云变成一个个物体
地面去掉之后,剩下的点云就是潜在的障碍物。但它们是散乱的,我们需要把它们「分组」——这就是聚类。
最经典的方法是欧几里得聚类(Euclidean Cluster Extraction)。原理很简单:如果两个点之间的距离小于某个阈值,就认为它们属于同一个物体。
| 参数 | 说明 | 我的建议值 |
|---|---|---|
| 聚类半径 | 两点之间的最大距离 | 0.3~0.5米(室内) |
| 最小点数 | 一个聚类至少包含的点数 | 10~30(过滤噪声) |
| 最大点数 | 一个聚类最多包含的点数 | 50000(防止墙面被当成一个物体) |
你想想看,如果聚类半径设得太大,两个相邻的障碍物会被合并成一个;设得太小,一个障碍物会被拆成好几块。这个平衡点,得根据实际传感器和场景来调。
4.5 障碍物检测的完整流程
好了,我们把上面的步骤串起来,就是一套完整的障碍物检测流水线。我画了一张流程图,帮你理清思路。
这张图看起来简单,但每一步都有坑。我曾经在某个项目中,地面分割参数没调好,结果把路边的矮灌木全当成了障碍物,机器人直接原地打转。后来花了半天时间重新标定地面模型,才解决问题。
4.6 点云处理的工程陷阱
- 坐标系问题:激光雷达的坐标系和机器人坐标系往往不一致。记得做坐标变换,否则障碍物位置全偏。
- 时间戳同步:多传感器融合时,点云的时间戳必须对齐。差个几十毫秒,动态障碍物的位置就完全不对了。
- 计算性能:点云处理很吃CPU。我建议用PCL的并行版本,或者把点云下采样到1万点以内再处理。
避坑指南:我曾经在室外场景直接用室内参数做地面分割,结果把斜坡当成了障碍物。后来我改用「区域生长法」做地面分割,效果好了很多。记住:没有万能算法,只有最适合场景的算法。
4.7 小结
环境感知是机器人导航的「眼睛」。点云处理入门其实不难,难的是把每一步的参数调好、把每个坑填平。直通滤波、体素滤波、RANSAC地面分割、欧几里得聚类——这四个步骤串起来,就能实现一个基础的障碍物检测系统。
嗯,这一章的内容就到这里。记住,点云处理没有银弹,多试、多调、多踩坑,才是成长的捷径。
公众号:蓝海资料掘金营,微信deep3321