共计 3737 个字符,预计需要花费 10 分钟才能阅读完成。
背景介绍
在自动驾驶系统中,激光雷达(LiDAR)是环境感知的核心传感器之一。它通过发射激光束并接收反射信号,能够获取周围环境的高精度三维点云数据。然而,原始点云数据往往包含大量冗余信息(如地面、植被等),如何从中准确分割出车辆、行人等关键障碍物,是自动驾驶感知模块的重要挑战。

点云分割的主要难点在于:
- 点云数据稀疏且不均匀
- 不同物体之间存在遮挡
- 实时性要求高(通常需要 10Hz 以上的处理频率)
- 复杂环境下的鲁棒性要求
技术方案:欧式聚类算法
欧式聚类(Euclidean Cluster Extraction)是一种基于空间距离的点云分割方法,其核心思想是将空间中距离相近的点归为同一类。算法流程如下:
- 构建点云的 KD-Tree 结构加速近邻搜索
- 对每个未处理的点,寻找其邻域内距离小于阈值的所有点
- 将这些点标记为同一簇,并递归扩展搜索
- 当无法找到新的邻近点时,完成当前簇的提取
- 重复上述过程直到所有点都被处理
相比其他分割方法,欧式聚类的优势在于:
- 实现简单,计算效率高
- 对刚体物体(如车辆)分割效果良好
- 参数物理意义明确(主要依赖距离阈值)
实现细节
地面去除
地面点是点云中最大的平面结构,通常使用以下方法去除:
- 使用 PassThrough 滤波器在 Z 轴方向设置高度阈值,快速去除明显高于地面的点
- 应用 RANSAC 平面拟合算法检测地面平面
- 提取并移除所有属于该平面的点
PCL 代码示例:
pcl::PointCloud<pcl::PointXYZ>::Ptr removeGround(pcl::PointCloud<pcl::PointXYZ>::Ptr cloud) {
// 创建分割对象
pcl::SACSegmentation<pcl::PointXYZ> seg;
pcl::PointIndices::Ptr inliers(new pcl::PointIndices);
pcl::ModelCoefficients::Ptr coefficients(new pcl::ModelCoefficients);
seg.setOptimizeCoefficients(true);
seg.setModelType(pcl::SACMODEL_PLANE);
seg.setMethodType(pcl::SAC_RANSAC);
seg.setDistanceThreshold(0.2); // 地面点距离阈值
seg.setInputCloud(cloud);
seg.segment(*inliers, *coefficients);
// 提取非地面点
pcl::ExtractIndices<pcl::PointXYZ> extract;
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered(new pcl::PointCloud<pcl::PointXYZ>());
extract.setInputCloud(cloud);
extract.setIndices(inliers);
extract.setNegative(true); // 获取非地面点
extract.filter(*cloud_filtered);
return cloud_filtered;
}
欧式聚类参数调优
关键参数及其影响:
- 聚类距离阈值(clusterTolerance):
- 过小会导致同一物体被分割为多个簇
- 过大会导致不同物体被合并
-
建议值:0.3-0.6 米(根据传感器精度调整)
-
最小簇大小(minClusterSize):
- 过滤噪声点和小物体
-
建议值:20-100 个点
-
最大簇大小(maxClusterSize):
- 防止超大簇消耗过多资源
- 建议值:25000-50000 个点
RViz 可视化配置
-
安装 RViz 插件:
sudo apt-get install ros-$ROS_DISTRO-rviz -
添加显示类型:
- PointCloud2:显示原始点云
-
MarkerArray:显示 Bounding Box
-
配置话题:
- 输入点云:/points_raw
- 输出 Bounding Box:/detection/objects
完整代码示例
#include <pcl/segmentation/extract_clusters.h>
#include <autoware_msgs/DetectedObjectArray.h>
void cloudCallback(const sensor_msgs::PointCloud2ConstPtr& input) {
// 转换为 PCL 格式
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
pcl::fromROSMsg(*input, *cloud);
// 地面去除
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_no_ground = removeGround(cloud);
// 创建 KD-Tree
pcl::search::KdTree<pcl::PointXYZ>::Ptr tree(new pcl::search::KdTree<pcl::PointXYZ>);
tree->setInputCloud(cloud_no_ground);
// 欧式聚类
std::vector<pcl::PointIndices> cluster_indices;
pcl::EuclideanClusterExtraction<pcl::PointXYZ> ec;
ec.setClusterTolerance(0.5); // 50cm
ec.setMinClusterSize(50);
ec.setMaxClusterSize(25000);
ec.setSearchMethod(tree);
ec.setInputCloud(cloud_no_ground);
ec.extract(cluster_indices);
// 创建 Bounding Box
autoware_msgs::DetectedObjectArray objects;
for (const auto& indices : cluster_indices) {pcl::PointCloud<pcl::PointXYZ>::Ptr cluster(new pcl::PointCloud<pcl::PointXYZ>);
pcl::copyPointCloud(*cloud_no_ground, indices, *cluster);
// 计算包围盒
Eigen::Vector4f centroid;
pcl::compute3DCentroid(*cluster, centroid);
autoware_msgs::DetectedObject obj;
obj.pose.position.x = centroid[0];
obj.pose.position.y = centroid[1];
obj.pose.position.z = centroid[2];
// 发布到 RViz...
objects.objects.push_back(obj);
}
pub_objects.publish(objects);
}
性能优化
处理大规模点云时的优化策略:
-
降采样 :使用 VoxelGrid 滤波器减少点云密度
pcl::VoxelGrid<pcl::PointXYZ> vg; vg.setInputCloud(cloud); vg.setLeafSize(0.1f, 0.1f, 0.1f); // 10cm 体素 vg.filter(*cloud_filtered); -
多线程处理 :使用 OpenMP 加速 KD-Tree 构建和邻域搜索
#pragma omp parallel for for (int i = 0; i < cloud->size(); ++i) {// 并行处理} -
GPU 加速 :使用 CUDA 版本的 PCL(PCL-GPU)
避坑指南
常见问题及解决方案:
- 聚类结果不完整 :
- 检查地面去除是否过度
-
适当增大 clusterTolerance
-
不同物体被合并 :
- 减小 clusterTolerance
-
检查传感器标定是否准确
-
处理延迟高 :
- 启用降采样
-
优化 KD-Tree 参数(leaf size)
-
RViz 显示异常 :
- 检查坐标系设置(通常应为 ”base_link” 或 ”map”)
- 确认话题名称匹配
扩展思考
当前方案的局限性及改进方向:
- 动态阈值 :根据距离自适应调整聚类阈值(远处物体点云更稀疏)
- 多模态融合 :结合相机图像进行语义分割,提升分类准确性
- 时序跟踪 :加入卡尔曼滤波等跟踪算法,稳定检测结果
- 深度学习 :使用 PointNet++ 等网络实现端到端分割
实践建议
- 从 KITTI 等公开数据集开始练习
- 使用 Rosbag 记录和回放数据方便调试
- 逐步调整参数,观察对结果的影响
- 参考 Autoware 官方文档了解最新 API
学习资源
- 《点云库 PCL 从入门到精通》
- Autoware 官方文档:https://autowarefoundation.github.io/
- PCL 教程:http://pointclouds.org/documentation/tutorials/
- ROS RViz 教程:http://wiki.ros.org/rviz/Tutorials
正文完
