第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 障碍物检测的完整流程

好了,我们把上面的步骤串起来,就是一套完整的障碍物检测流水线。我画了一张流程图,帮你理清思路。

原始点云输入 直通滤波 体素降采样 统计滤波 RANSAC地面分割 欧几里得聚类 障碍物包围框生成 输出障碍物列表

这张图看起来简单,但每一步都有坑。我曾经在某个项目中,地面分割参数没调好,结果把路边的矮灌木全当成了障碍物,机器人直接原地打转。后来花了半天时间重新标定地面模型,才解决问题。

4.6 点云处理的工程陷阱

  • 坐标系问题:激光雷达的坐标系和机器人坐标系往往不一致。记得做坐标变换,否则障碍物位置全偏。
  • 时间戳同步:多传感器融合时,点云的时间戳必须对齐。差个几十毫秒,动态障碍物的位置就完全不对了。
  • 计算性能:点云处理很吃CPU。我建议用PCL的并行版本,或者把点云下采样到1万点以内再处理。

避坑指南:我曾经在室外场景直接用室内参数做地面分割,结果把斜坡当成了障碍物。后来我改用「区域生长法」做地面分割,效果好了很多。记住:没有万能算法,只有最适合场景的算法。

4.7 小结

环境感知是机器人导航的「眼睛」。点云处理入门其实不难,难的是把每一步的参数调好、把每个坑填平。直通滤波、体素滤波、RANSAC地面分割、欧几里得聚类——这四个步骤串起来,就能实现一个基础的障碍物检测系统。

嗯,这一章的内容就到这里。记住,点云处理没有银弹,多试、多调、多踩坑,才是成长的捷径。


公众号:蓝海资料掘金营,微信deep3321