介绍
ros下velodyne激光雷达的回调函数, 利用RANSAC平面分割, 从单帧激光点云中提取出地面点
该方法可用于incremental的地面提取, 优势是速度快;
但由于地面并不总是平面, 所以该方法不如batch方法, 但batch方法要对全部激光点云进行计算, 速度较慢.
代码
void vldHandle(const sensor_msgs::PointCloud2ConstPtr &laserCloudMsg)
{
double timeCur = laserCloudMsg->header.stamp.toSec();
time_now = timeCur;
pcl::PointCloud<PointType>::Ptr laserCloudIn;
laserCloudIn.reset(new pcl::PointCloud<PointType>());
pcl::fromROSMsg(*laserCloudMsg, *laserCloudIn);
// Remove Nan points
std::vector<int> indices;
pcl::removeNaNFromPointCloud(*laserCloudIn, *laserCloudIn, indices);
pcl::PointCloud<PointType>::Ptr ground_cloud, ground_cloud_candidate;
ground_cloud.reset(new pcl::PointCloud<PointType>());
ground_cloud_candidate.reset(new pcl::PointCloud<PointType>());
pcl::PassThrough<PointType> pass;
pcl::ModelCoefficients::Ptr coefficients (new pcl::ModelCoefficients);
pcl::PointIndices::Ptr inliers (new pcl::PointIndices);
pcl::SACSegmentation<PointType> seg;
pcl::ExtractIndices<PointType> extract;
// 初始化RANSAC分割器
seg.setOptimizeCoefficients(true);
seg.setModelType(pcl::SACMODEL_PLANE);
seg.setMethodType(pcl::SAC_RANSAC);
seg.setDistanceThreshold(ground_RANSAC_threshold);
//seg.setAxis(Eigen::Vector3f(0, 0, 1.0));
// 提取地面点
pass.setInputCloud(laserCloudIn);
pass.setFilterFieldName("z");
pass.setFilterLimits(ground_lower_threshold - sensorMountHeight, ground_upper_threshold - sensorMountHeight);
pass.filter(*ground_cloud_candidate);
seg.setOptimizeCoefficients(true);
seg.setModelType(pcl::SACMODEL_PLANE);
seg.setMethodType(pcl::SAC_RANSAC);
seg.setDistanceThreshold(0.1);
seg.setInputCloud(ground_cloud_candidate);
seg.segment(*inliers, *coefficients);
extract.setInputCloud(ground_cloud_candidate);
extract.setIndices(inliers);
extract.setNegative(false);
extract.filter(*ground_cloud);
if(ground_cloud_time_que.size() == 0 || ground_cloud_time_que.back() != timeCur)
{
//increaseGroundCloud(ground_cloud);
ground_cloud_que.push(ground_cloud);
ground_cloud_time_que.push(timeCur);
ground_cloud_current.reset(new pcl::PointCloud<PointType>());
*ground_cloud_current += *ground_cloud;
}
if(obstacle_cloud_time_que.size() == 0 || obstacle_cloud_time_que.back() != timeCur)
{
obstacle_cloud_que.push(laserCloudIn);
obstacle_cloud_time_que.push(timeCur);
obstacle_cloud_current.reset(new pcl::PointCloud<PointType>());
*obstacle_cloud_current += *laserCloudIn;
}
//cout<<"receive vld, time: "<<setprecision(14)<<timeCur<<endl;
}
其中的部分全局变量
pcl::PointCloud<PointType>::Ptr ground_cloud_current; // 当前帧地面点云
pcl::PointCloud<PointType>::Ptr obstacle_cloud_current; // 当前帧全部点云
queue<pcl::PointCloud<PointType>::Ptr> ground_cloud_que; // 存放地面点云的queue
queue<double> ground_cloud_time_que; // 存放地面点云time_stamp的queue
queue<pcl::PointCloud<PointType>::Ptr> obstacle_cloud_que; // 存放全部点云的queue
queue<double> obstacle_cloud_time_que; // 存放全部点云time_stamp读queue