学习了两天关于64线激光雷达所检测到的周围环境的PCL点云数据信息,并且研读了其中的c++源代码,深感到其中算法用代码实现的难度之大,所以今天利用半个小时时间回顾一下、夯实一下基础。
一、点云分割
首先你要在点云信息里提取出路面和障碍物两个信息,一个是路面,一个是障碍物(车或者说其他障碍物),这就有点像分离器了,我们采用的是RANSAC算法去将路面分离出来,然后利用整体点云去除路面部分点云,剩下的便是障碍物信息。使用PCL库实现如下:
所有路面的点云索引都存在了*inliers里面。
pcl::SACSegmentation<PointT> seg;
pcl::PointIndices::Ptr inliers(new pcl::PointIndices);
pcl::ModelCoefficients::Ptr coefficients(new pcl::ModelCoefficients);
/*我们有系数,这实际上是在定义模型的系数。我们查看并看到将seg setModelType定义为SACMODEL_PLANE。
*因此,这些系数实际上将定义该平面是什么,如果要在PCL查看器中实际渲染该平面,则可以使用它。
*
*RANSAC就像所有这些细分背后的秘密调味料,这种随机样本共识一样,后来我们将真正地深入探讨RANSAC的工作原理。
*/
seg.setOptimizeCoefficients(true);
seg.setModelType(pcl::SACMODEL_PLANE);
seg.setMethodType(pcl::SAC_RANSAC);//S使用RANSAC算法
seg.setMaxIterations(maxIterations);//seg对象的最大迭代次数。我们设置最大迭代次数并设置距离阈值。
seg.setDistanceThreshold(distanceThreshold);
// Segment the largest planar component from the input cloud
seg.setInputCloud(cloud);//点云做一些分割
seg.segment(*inliers, *coefficients);//然后我们要生成的是这些inlier和系数。在这个例子中我们不会使用coeffcients,如果你想,你能使用它渲染如果你想,
//但是我们最感兴趣的是inliers, 因为我们将使用它们将pointCloud分为两部分。所以我们在这里通过引用传递inlier,and this seg.segment is able to do all the processing on it.
//然后inlier指针将指向所有通过我们的RANSAC找到的属于该平面的索引列表。
if (inliers->indices.size() == 0)
{
std::cout << "Could not estimate a planar model for the given dataset." << std::endl;
}
我们已经提取出了路面的点云索引,利用整体减去路面就是障碍物信息了,这里使用的是pcl中的extract函数,具体代码看如下:
// TODO: Create two new point clouds, one cloud with obstacles and other with segmented plane
typename pcl::PointCloud<PointT>::Ptr groundCloud(new pcl::PointCloud<PointT>());//产生道路平面
typename pcl::PointCloud<PointT>::Ptr obstacleCloud(new pcl::PointCloud<PointT>());//产生障碍物平面。
/***我们可以获取其成员变量。然后从云中获取参考云,然后获取其成员点,然后获取位于该索引处的点T,我们将对每个inliers进行索引***/
for (int index : inliers->indices)
{
groundCloud->points.push_back(cloud->points[index]);//得到了道路平面点
}
//接下来我将会产生障碍物,这里我们将产生一些与PCL文档相似的分割,which was using that extract object,
pcl::ExtractIndices<PointT> extract;
extract.setInputCloud(cloud);//这是嘿,这是参考点云
//提取由indexs_in引用的cloud_in中的点作为单独的点云:https://pointclouds.org/documentation/classpcl_1_1_extract_indices_3_01pcl_1_1_p_c_l_point_cloud2_01_4.html
extract.setIndices(inliers);//这有内点,索引
extract.setNegative(true);
extract.filter(*obstacleCloud);//这里是障碍物点云。所以障碍物是个指针。因此,当我将其传递给过滤器时,我将继续取消引用它
//生成的点除了inliers之外,的电晕,保留所有不是inliers的点,内点从该参考云中删除
std::pair<typename pcl::PointCloud<PointT>::Ptr, typename pcl::PointCloud<PointT>::Ptr> segResult(obstacleCloud, groundCloud);
return segResult;
然后就返回到obstaclecloud 和grouncloud点云里,这个不是索引了。此时,就完成了障碍物与路面的分离了。 下一步的工作就是如何将障碍物进行聚类的分析,目标是识别出周围的障碍物具体车辆的位置。使用的是聚类算法也涉及到kd-trees。还在学习中,东西比较杂,现在就是梳理一下思路。
20200730