int main(int argc, char** argv)
{
  // initialize variables
  pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_original (new pcl::PointCloud<pcl::PointXYZ>);
  pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_unaltered (new pcl::PointCloud<pcl::PointXYZ>);
  pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered (new pcl::PointCloud<pcl::PointXYZ>);
  pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_objects (new pcl::PointCloud<pcl::PointXYZ>);
  pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_planeInliers (new pcl::PointCloud<pcl::PointXYZ>);
  pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_planeOutliers (new pcl::PointCloud<pcl::PointXYZ>);
  pcl::ModelCoefficients::Ptr coefficients (new pcl::ModelCoefficients());
  pcl::PointIndices::Ptr indices (new pcl::PointIndices());
  pcl::PCDReader reader;
  pcl::PCDWriter writer;
  int result = 0;  // catch function return
  
  // enable variables for time logging
  boost::posix_time::ptime time_before_execution;
  boost::posix_time::ptime time_after_execution;
  boost::posix_time::time_duration difference;
  
  // read point cloud through command line
  if (argc != 2)
  {
    std::cout << "usage: " << argv[0] << " <filename>\n";
    return 0;
  }
  else
  {	// read cloud and display its size
    std::cout << "Reading Point Cloud" << std::endl;
    reader.read(argv[1], *cloud_original);
#ifdef DEBUG
    std::cout << "size of original cloud: "
    << cloud_original->points.size() << " points" << std::endl;
#endif
  }
  
  //**************************************************************************
  // test passthroughFilter() function
  std::cout << "RUNNING PASSTHROUGH FILTER TESTS" << std::endl;
  log_passthroughFilter(cloud_original, cloud_filtered, "../pictures/T01_passthrough_01.pcd",
                        "passthrough filter, custom 1: ","z", -2.5, 0);
  log_passthroughFilter(cloud_original, cloud_filtered, "../pictures/T01_passthrough_02.pcd",
                        "passthrough filter, custom 2: ","y", -3.0, 3.0);
  log_passthroughFilter(cloud_original, cloud_filtered, "../pictures/T01_passthrough_03.pcd",
                        "passthrough filter, custom 3: ","x", -3.0, 3.0);
  
  //**************************************************************************
  // test voxelFilter() function
  std::cout << "RUNNING VOXEL FILTER TEST" << std::endl;
  log_voxelFilter(cloud_original, cloud_filtered, "../pictures/T02_voxel_01.pcd",
                  "voxel filter, custom 1:", 0.01);
  log_voxelFilter(cloud_original, cloud_filtered, "../pictures/T02_voxel_02.pcd",
                  "voxel filter, custom 2:", 0.02);
  log_voxelFilter(cloud_original, cloud_filtered, "../pictures/T02_voxel_03.pcd",
                  "voxel filter, custom 3:", 0.04);
  log_voxelFilter(cloud_original, cloud_filtered, "../pictures/T02_voxel_04.pcd",
                  "voxel filter, custom 4:", 0.08);
  
  //**************************************************************************
  // test removeNoise() function
  std::cout << "RUNNING NOISE REMOVAL TEST" << std::endl;
  log_removeNoise(cloud_original, cloud_filtered, "../pictures/T03_noise_01.pcd",
                  "noise removal, custom 1: ", 50, 1.0);
  log_removeNoise(cloud_original, cloud_filtered, "../pictures/T03_noise_01.pcd",
                  "noise removal, custom 1: ", 100, 1.0);
  log_removeNoise(cloud_original, cloud_filtered, "../pictures/T03_noise_01.pcd",
                  "noise removal, custom 1: ", 10, 1.0);
  log_removeNoise(cloud_original, cloud_filtered, "../pictures/T03_noise_01.pcd",
                  "noise removal, custom 1: ", 50, 1.9);
  log_removeNoise(cloud_original, cloud_filtered, "../pictures/T03_noise_01.pcd",
                  "noise removal, custom 1: ", 50, 0.1);
  
  //**************************************************************************
  // test getPlane() function
  std::cout << "RUNNING PLANE SEGMENTATION TEST" << std::endl;
  log_getPlane(cloud_original, cloud_planeInliers, cloud_planeOutliers,
               coefficients, indices, "../pictures/T04_planeInliers_01.pcd",
               "plane segmentation, custom 1: ", 0, 1.57, 1000, 0.01);
  log_getPlane(cloud_original, cloud_planeInliers, cloud_planeOutliers,
               coefficients, indices, "../pictures/T04_planeInliers_02.pcd",
               "plane segmentation, custom 2: ", 0, 1.57, 1, 0.01);
  log_getPlane(cloud_original, cloud_planeInliers, cloud_planeOutliers,
               coefficients, indices, "../pictures/T04_planeInliers_03.pcd",
               "plane segmentation, custom 3: ", 0, 1.57, 2000, 0.01);
  log_getPlane(cloud_original, cloud_planeInliers, cloud_planeOutliers,
               coefficients, indices, "../pictures/T04_planeInliers_04.pcd",
               "plane segmentation, custom 4: ", 0, 0.76, 1000, 0.01);
  log_getPlane(cloud_original, cloud_planeInliers, cloud_planeOutliers,
               coefficients, indices, "../pictures/T04_planeInliers_05.pcd",
               "plane segmentation, custom 5: ", 0, 2.09, 1000, 0.01);
  log_getPlane(cloud_original, cloud_planeInliers, cloud_planeOutliers,
               coefficients, indices, "../pictures/T04_planeInliers_06.pcd",
               "plane segmentation, custom 6: ", 0.35, 1.57, 1000, 0.01);
  log_getPlane(cloud_original, cloud_planeInliers, cloud_planeOutliers,
               coefficients, indices, "../pictures/T04_planeInliers_07.pcd",
               "plane segmentation, custom 7: ", 0.79, 1.57, 1000, 0.01);
  log_getPlane(cloud_original, cloud_planeInliers, cloud_planeOutliers,
               coefficients, indices, "../pictures/T04_planeInliers_08.pcd",
               "plane segmentation, custom 8: ", 0, 1.57, 1000, 0.001);
  log_getPlane(cloud_original, cloud_planeInliers, cloud_planeOutliers,
               coefficients, indices, "../pictures/T04_planeInliers_09.pcd",
               "plane segmentation, custom 9: ", 0, 1.57, 1000, 0.01);
  
  //**************************************************************************
  // test getPrism() function

   std::cout << "RUNNING EXTRACT PRISM TEST" << std::endl;
   log_getPrism(cloud_original, cloud_objects, "../pictures/T05_objects_01.pcd",
   "polygonal prism, custom 1: ", 0, 1.57, 1000, 0.01, 0.02, 0.2);

  
  // test getPrism() function
  std::cout << "RUNNING EXTRACT PRISM TEST" << std::endl;
  // get output from default plane
  time_before_execution = boost::posix_time::microsec_clock::local_time();  // time before
  result = c44::getPrism(cloud_original, cloud_objects, 0, 1.57, 1000, 0.01, 0.02, 0.2);
  time_after_execution = boost::posix_time::microsec_clock::local_time(); // time after
  if(result < 0)
  {
    std::cout << "ERROR: could not find polygonal prism data" << std::endl;
  }
  else
  {
    writer.write<pcl::PointXYZ> ("../pictures/T05_objects_01.pcd", *cloud_objects); // write out cloud
#ifdef DEBUG
    difference = time_after_execution - time_before_execution;  // get execution time
    std::cout << std::setw(5) << difference.total_milliseconds() << ": "
    << "polygonal prism, default: "
    << cloud_objects->points.size() << " points" << std::endl;
#endif
  }
  
  return 0;
}
void PclExtractor::cloudCallback(const Cloud2Msg::ConstPtr& cloud2Msg_input)
{

  boost::mutex::scoped_lock(mutex_);
  sensor_msgs::PointCloud2 output;
  sensor_msgs::PointCloud2 convex_hull;
  sensor_msgs::PointCloud2 object_msg;
  sensor_msgs::PointCloud2 nonObject_msg;
  pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
  pcl::fromROSMsg (*cloud2Msg_input, *cloud);


  pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_p(new pcl::PointCloud<pcl::PointXYZ>);
  pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_f(new pcl::PointCloud<pcl::PointXYZ>);

  pcl::ModelCoefficients::Ptr coefficients(new pcl::ModelCoefficients);
  pcl::PointIndices::Ptr inliers(new pcl::PointIndices);
  
  // *** Normal estimation
  // Create the normal estimation class and pass the input dataset to it
  pcl::NormalEstimation<pcl::PointXYZ, pcl::Normal> ne;
  ne.setInputCloud(cloud);
  // Creating the kdTree object for the search method of the extraction
  pcl::search::KdTree<pcl::PointXYZ>::Ptr tree(new pcl::search::KdTree<pcl::PointXYZ>);
  ne.setSearchMethod(tree);

  // output dataset
  pcl::PointCloud<pcl::Normal>::Ptr cloud_normals(new pcl::PointCloud<pcl::Normal>);

  // use all neighbors in a sphere of radius 3cm
  ne.setRadiusSearch(0.3);

  // compute the features
  ne.compute(*cloud_normals);
  // *** End of normal estimation
  // *** Plane Estimation From Normals Start
  // Create the segmentation object
  pcl::SACSegmentationFromNormals<pcl::PointXYZ, pcl::Normal> seg;
  // Optional
  seg.setOptimizeCoefficients(true);
  // Mandatory
//  seg.setModelType(pcl::SACMODEL_PARALLEL_PLANE);
  seg.setModelType(pcl::SACMODEL_PLANE);
//  seg.setModelType(pcl::SACMODEL_PERPENDICULAR_PLANE);
  //y가 z
//  const Eigen::Vector3f z_axis(0,-1.0,0);
//  seg.setAxis(z_axis);
//  seg.setEpsAngle(seg_setEpsAngle_);
  seg.setMethodType(pcl::SAC_RANSAC);
  seg.setMaxIterations (seg_setMaxIterations_);
  seg.setDistanceThreshold(seg_setDistanceThreshold_);
  seg.setNormalDistanceWeight(seg_setNormalDistanceWeight_);
//  seg.setProbability(seg_probability_);

  seg.setInputCloud((*cloud).makeShared());
  seg.setInputNormals(cloud_normals);
  seg.segment(*inliers, *coefficients);

  std::cerr <<"input: "<<cloud->width*cloud->height<<"Model inliers: " << inliers->indices.size () << std::endl;
  if (inliers->indices.size () == 0)
  {
    ROS_ERROR ("Could not estimate a planar model for the given dataset.");
  }
  // *** End of Plane Estimation
  // *** Plane Estimation Start
  // Create the segmentation object
/*  pcl::SACSegmentation<pcl::PointXYZ> seg;
  // Optional
  //seg.setOptimizeCoefficients(true);
  // Mandatory
  seg.setModelType(pcl::SACMODEL_PARALLEL_PLANE);
//  seg.setModelType(pcl::SACMODEL_PLANE);
//  seg.setModelType(pcl::SACMODEL_PERPENDICULAR_PLANE);
  //y가 z
  const Eigen::Vector3f z_axis(0,-1.0,0);
  seg.setAxis(z_axis);
  seg.setEpsAngle(seg_setEpsAngle_);
  seg.setMethodType(pcl::SAC_RANSAC);
  seg.setMaxIterations (seg_setMaxIterations_);
  seg.setDistanceThreshold(seg_setDistanceThreshold_);

  seg.setInputCloud((*cloud).makeShared());
  seg.segment(*inliers, *coefficients);

  std::cerr <<"input: "<<cloud->width*cloud->height<<"Model inliers: " << inliers->indices.size () << std::endl;
  if (inliers->indices.size () == 0)
  {
    ROS_ERROR ("Could not estimate a planar model for the given dataset.");
  }
  // *** End of Plane Estimation
*/
  pcl::ExtractIndices<pcl::PointXYZ> extract;
  // Extrat the inliers
  extract.setInputCloud(cloud);
  extract.setIndices(inliers);

  pcl::PointCloud<pcl::PointXYZ>::Ptr ground_hull(new pcl::PointCloud<pcl::PointXYZ>);
  pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_projected(new pcl::PointCloud<pcl::PointXYZ>);

  if ((int)inliers->indices.size() > minPoints_)
  {
    extract.setNegative(false);
    extract.filter(*cloud_p);

    pcl::toROSMsg(*cloud_p, output);
    std::cerr << "PointCloud representing the planar component: " 
      << cloud_p->width * cloud_p->height << " data points." << std::endl;

    // Step 3c. Project the ground inliers
    pcl::ProjectInliers<pcl::PointXYZ> proj;
    proj.setModelType(pcl::SACMODEL_PLANE);
    proj.setInputCloud(cloud_p);
    proj.setModelCoefficients(coefficients);
    proj.filter(*cloud_projected);
    // Step 3d. Create a Convex Hull representation of the projected inliers
    pcl::ConvexHull<pcl::PointXYZ> chull;
    //chull.setInputCloud(cloud_p);
    chull.setInputCloud(cloud_projected);
    chull.setDimension(chull_setDimension_);//2D
    chull.reconstruct(*ground_hull);
    pcl::toROSMsg(*ground_hull, convex_hull);
    //pcl::toROSMsg(*ground_hull, convex_hull);
    ROS_INFO ("Convex hull has: %d data points.", (int) ground_hull->points.size ());

    // Publish the data
    plane_pub_.publish (output);
    hull_pub_.publish(convex_hull);

  }
  // Create the filtering object
  extract.setNegative(true);
  extract.filter(*cloud_f);
  ROS_INFO ("Cloud_f has: %d data points.", (int) cloud_f->points.size ());
  // cloud.swap(cloud_f);

  pcl::PointCloud<pcl::PointXYZ>::Ptr object(new pcl::PointCloud<pcl::PointXYZ>);
  pcl::PointCloud<pcl::PointXYZ>::Ptr nonObject(new pcl::PointCloud<pcl::PointXYZ>);
  pcl::PointIndices::Ptr object_indices(new pcl::PointIndices);

  // cloud statictical filter
  pcl::PointCloud<pcl::PointXYZ>::Ptr cloudStatisticalFiltered (new pcl::PointCloud<pcl::PointXYZ>);
  pcl::StatisticalOutlierRemoval<pcl::PointXYZ> sor;
  sor.setInputCloud(cloud_f);
  sor.setMeanK(sor_setMeanK_);
  sor.setStddevMulThresh(sor_setStddevMulThresh_);
  sor.filter(*cloudStatisticalFiltered);

  pcl::ExtractIndices<pcl::PointXYZ> exObjectIndices;
  //exObjectIndices.setInputCloud(cloud_f);
  exObjectIndices.setInputCloud(cloudStatisticalFiltered);
  exObjectIndices.setIndices(object_indices);
  exObjectIndices.filter(*object);
  exObjectIndices.setNegative(true);
  exObjectIndices.filter(*nonObject);

  ROS_INFO ("Object has: %d data points.", (int) object->points.size ());
  pcl::toROSMsg(*object, object_msg);
  object_pub_.publish(object_msg);
  //pcl::toROSMsg(*nonObject, nonObject_msg);
  //pcl::toROSMsg(*cloud_f, nonObject_msg);
  pcl::toROSMsg(*cloudStatisticalFiltered, nonObject_msg);
  nonObject_pub_.publish(nonObject_msg);
}
Exemple #3
0
int 
main (int argc, char** argv)
{
  // Read in the cloud data
  pcl::PCDReader reader;
  pcl::PointCloud<pcl::PointXYZ>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZ>), cloud_f (new pcl::PointCloud<pcl::PointXYZ>);
  reader.read ("../bottle.pcd", *cloud);
  std::cout << "PointCloud before filtering has: " << cloud->points.size () << " data points." << std::endl; //*
   parseCommandLine(argc, argv);
   std::cout << "argc:" << argc << " argv:" << *argv << std::endl;
   std::cout << "x_min:" << x_pass_min_ << " x_max:" << x_pass_max_ << " y_min:" << y_pass_min_ << " y_max:"<<y_pass_max_<<std::endl;

	/*apply pass through filter*/
	
	pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered (new pcl::PointCloud<pcl::PointXYZ>);
	// Create the filtering object
	pcl::PassThrough<pcl::PointXYZ> pass;
	//pass.setFilterLimitsNegative (true);
	pass.setInputCloud (cloud);
	pass.setFilterFieldName ("z");
	pass.setFilterLimits (z_pass_min_, z_pass_max_);
	pass.filter (*cloud_filtered);

        pass.setInputCloud (cloud_filtered);
	pass.setFilterFieldName ("y");
	pass.setFilterLimits (y_pass_min_, y_pass_max_);
	pass.filter (*cloud_filtered);
	
        pass.setInputCloud (cloud_filtered);
	pass.setFilterFieldName ("x");
	pass.setFilterLimits (x_pass_min_, x_pass_max_);
	pass.filter (*cloud_filtered);

	viewer.addPointCloud<PointT> (cloud_filtered, "input_cloud");
        #if 0	
       // while (!viewer.wasStopped ())
	{
	//	viewer.spinOnce ();
	} 
        return(0);
        #endif	
        
	viewer.removeAllPointClouds();
        cloud = cloud_filtered;

    
#if 0
#if 0
  // Create the filtering object: downsample the dataset using a leaf size of 1cm
  pcl::VoxelGrid<pcl::PointXYZ> vg;
  //pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered (new pcl::PointCloud<pcl::PointXYZ>);
  vg.setInputCloud (cloud);
  vg.setLeafSize (0.01f, 0.01f, 0.01f);
  vg.filter (*cloud_filtered);
  std::cout << "PointCloud after filtering has: " << cloud_filtered->points.size ()  << " data points." << std::endl; //*
#endif
  // Create the segmentation object for the planar model and set all the parameters
  pcl::SACSegmentation<pcl::PointXYZ> seg;
  pcl::PointIndices::Ptr inliers (new pcl::PointIndices);
  pcl::ModelCoefficients::Ptr coefficients (new pcl::ModelCoefficients);
  pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_plane (new pcl::PointCloud<pcl::PointXYZ> ());
  pcl::PCDWriter writer;
  seg.setOptimizeCoefficients (true);
  seg.setModelType (pcl::SACMODEL_PLANE);
  seg.setMethodType (pcl::SAC_RANSAC);
  seg.setMaxIterations (100);
  seg.setDistanceThreshold (0.02);

  int i=0, nr_points = (int) cloud_filtered->points.size ();
  while (cloud_filtered->points.size () > 0.3 * nr_points)
  {
    // Segment the largest planar component from the remaining cloud
    seg.setInputCloud (cloud_filtered);
    seg.segment (*inliers, *coefficients);
    if (inliers->indices.size () == 0)
    {
      std::cout << "Could not estimate a planar model for the given dataset." << std::endl;
      break;
    }

    // Extract the planar inliers from the input cloud
    pcl::ExtractIndices<pcl::PointXYZ> extract;
    extract.setInputCloud (cloud_filtered);
    extract.setIndices (inliers);
    extract.setNegative (false);

    // Get the points associated with the planar surface
    extract.filter (*cloud_plane);
    std::cout << "PointCloud representing the planar component: " << cloud_plane->points.size () << " data points." << std::endl;

    // Remove the planar inliers, extract the rest
    extract.setNegative (true);
    extract.filter (*cloud_f);
    *cloud_filtered = *cloud_f;
  }

  viewer.addPointCloud<PointT> (cloud_filtered, "input_cloud");
  while (!viewer.wasStopped ())
	{
		viewer.spinOnce ();
	} 	
#endif
#if 1

  pcl::PCDWriter writer;
  // Creating the KdTree object for the search method of the extraction
  pcl::search::KdTree<pcl::PointXYZ>::Ptr tree (new pcl::search::KdTree<pcl::PointXYZ>);
  tree->setInputCloud (cloud_filtered);

  std::vector<pcl::PointIndices> cluster_indices;
  pcl::EuclideanClusterExtraction<pcl::PointXYZ> ec;
  ec.setClusterTolerance (0.02); // 2cm
  ec.setMinClusterSize (100);
  ec.setMaxClusterSize (25000);
  ec.setSearchMethod (tree);
  ec.setInputCloud (cloud_filtered);
  ec.extract (cluster_indices);

  int j = 0;
  for (std::vector<pcl::PointIndices>::const_iterator it = cluster_indices.begin (); it != cluster_indices.end (); ++it)
  {
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_cluster (new pcl::PointCloud<pcl::PointXYZ>);
    for (std::vector<int>::const_iterator pit = it->indices.begin (); pit != it->indices.end (); pit++)
      cloud_cluster->points.push_back (cloud_filtered->points[*pit]); //*
    cloud_cluster->width = cloud_cluster->points.size ();
    cloud_cluster->height = 1;
    cloud_cluster->is_dense = true;

    cout << "ss:" << j << std::endl;  
    
    std::cout << "PointCloud representing the Cluster: " << cloud_cluster->points.size () << " data points." << std::endl;
    std::stringstream ss;
    ss << "cloud_cluster_" << j << ".pcd";
    cout << "ss:" << j << std::endl;  
    writer.write<pcl::PointXYZ> (ss.str (), *cloud_cluster, false); //*
    j++;
  }

  return (0);
#endif
}
Exemple #4
0
/** Set the number of coefficients in m_numCoef
 * based on the current degree held in m_d.
 */
void Algebraic::calcNumCoef()
{
  m_numCoef = coefficients(m_d);
}
void ObjectDetector::performSegmentation(pcl::PointCloud<pcl::PointXYZ>::Ptr cloud)
{
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_plane (new pcl::PointCloud<pcl::PointXYZ>), cloud_plane_rotated (new pcl::PointCloud<pcl::PointXYZ>);

    ROS_INFO("PointCloud before planar segmentation: %d data points.", cloud->width * cloud->height);

    pcl::ModelCoefficients::Ptr coefficients(new pcl::ModelCoefficients);
    pcl::PointIndices::Ptr inliers(new pcl::PointIndices);
    // Create the segmentation object
    pcl::SACSegmentation<pcl::PointXYZ> seg;
    // Optional
    seg.setOptimizeCoefficients (true);
    // Fit plane
    seg.setModelType (pcl::SACMODEL_PLANE);
    // Use RANSAC
    seg.setMethodType (pcl::SAC_RANSAC);
    // Set maximum number of iterations
    seg.setMaxIterations (max_it_calibration);
    // Set distance to the model threshold
    seg.setDistanceThreshold (floor_threshold);

    // Segment the largest planar component from the cloud
    seg.setInputCloud (cloud);
    seg.segment (*inliers, *coefficients);

    // Extract the inliers of the plane
    pcl::ExtractIndices<pcl::PointXYZ> extract;
    extract.setInputCloud (cloud);
    extract.setIndices (inliers);
    extract.setNegative (false);
    extract.filter (*cloud_plane);
    ROS_INFO("PointCloud representing the planar component: %d data points.", cloud_plane->width * cloud_plane->height);

    // Create normal vector of the plane
    Eigen::Matrix<float, 1, 3> normal_plane, normal_floor, r_axis;
    normal_plane[0] = coefficients->values[0];
    normal_plane[1] = coefficients->values[1];
    normal_plane[2] = coefficients->values[2];
    ROS_INFO("Plane normal: %f %f %f", normal_plane[0], normal_plane[1], normal_plane[2]);

    // Create normal vector of the floor
    normal_floor[0] = 0.0f;
    normal_floor[1] = 1.0f;
    normal_floor[2] = 0.0f;
    ROS_INFO("Floor normal: %f %f %f", normal_floor[0], normal_floor[1], normal_floor[2]);

    // Determine rotation axis
    r_axis = normal_plane.cross(normal_floor);
    ROS_INFO("Rotation axis: %f %f %f", r_axis[0], r_axis[1], r_axis[2]);

    // Determine rotation angle theta
    theta = acos(normal_plane.dot(normal_floor));
    ROS_INFO("Rotation angle theta: %f", theta);

    // Create rotation matrix
    Eigen::Affine3f transform = Eigen::Affine3f::Identity();
    transform.rotate (Eigen::AngleAxisf (theta, Eigen::Vector3f::UnitX()));

    // Perform rotation on extracted plane
    pcl::transformPointCloud(*cloud_plane, *cloud_plane_rotated,transform);

    // Compute y translation by taking the average y values of the plane points
    int num_of_points = cloud_plane_rotated->width * cloud_plane_rotated->height;
    for (size_t i = 0; i < num_of_points; ++i)
    {
        y_translation += cloud_plane_rotated->points[i].y;
    }
    y_translation = y_translation / num_of_points;
}
pcl::PointCloud<pcl::PointXYZ>::Ptr ObjectDetector::filterCloud(pcl::PointCloud<pcl::PointXYZ>::Ptr cloud)
{
    ROS_INFO("Before passthrough: %d", cloud->width * cloud->height);
    
    if((cloud->width * cloud->height) != 0){

        pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered_x(new pcl::PointCloud<pcl::PointXYZ>), cloud_filtered_y (new pcl::PointCloud<pcl::PointXYZ>), cloud_filtered_z (new pcl::PointCloud<pcl::PointXYZ>);

        // Filter x outliers
        pcl::PassThrough<pcl::PointXYZ> pass_x;
        pass_x.setInputCloud (cloud);
        pass_x.setFilterFieldName ("x");
        pass_x.setFilterLimits (-x_max, x_max);
        pass_x.filter (*cloud_filtered_x);

        // Filter y outliers
        pcl::PassThrough<pcl::PointXYZ> pass_y;
        pass_y.setInputCloud (cloud_filtered_x);
        pass_y.setFilterFieldName ("y");
        pass_y.setFilterLimits (floor_threshold, y_max);
        pass_y.filter (*cloud_filtered_y);

        // Filter z outliers
        pcl::PassThrough<pcl::PointXYZ> pass_z;
        pass_z.setInputCloud (cloud_filtered_y);
        pass_z.setFilterFieldName ("z");
        pass_z.setFilterLimits (-z_max, 0.0);
        pass_z.filter (*cloud_filtered_z);
        
        ROS_INFO("Before RANSAC: %d", cloud_filtered_z->width * cloud_filtered_z->height);

        if((cloud_filtered_z->width * cloud_filtered_z->height) > min_points_left)
        {
            pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_ransac (new pcl::PointCloud<pcl::PointXYZ>);

            cloud_ransac = cloud_filtered_z;

            pcl::ModelCoefficients::Ptr ransac_coefficients(new pcl::ModelCoefficients);
            pcl::PointIndices::Ptr inliers(new pcl::PointIndices);
            // Create the segmentation object
            pcl::SACSegmentation<pcl::PointXYZ> seg;
            // Optional
            seg.setOptimizeCoefficients (true);
            // Fit plane
            seg.setModelType (pcl::SACMODEL_PLANE);
            // Use RANSAC
            seg.setMethodType (pcl::SAC_RANSAC);
            // Set maximum number of iterations
            seg.setMaxIterations (max_it_runtime);
            // Set distance to the model threshold
            seg.setDistanceThreshold (wall_threshold);

            // Segment the largest planar component from the cloud
            seg.setInputCloud (cloud_ransac);
            seg.segment (*inliers, *ransac_coefficients);

            while(inliers->indices.size() > ransac_removal_threshold){

                // Extract the inliers
                pcl::ExtractIndices<pcl::PointXYZ> extract;
                extract.setInputCloud (cloud_ransac);
                extract.setIndices (inliers);
                extract.setNegative (true);
                extract.filter (*cloud_ransac);

                pcl::SACSegmentation<pcl::PointXYZ> seg2;
                // Optional
                seg2.setOptimizeCoefficients (true);
                // Fit plane
                seg2.setModelType (pcl::SACMODEL_PLANE);
                // Use RANSAC
                seg2.setMethodType (pcl::SAC_RANSAC);
                // Set maximum number of iterations
                seg2.setMaxIterations (max_it_runtime);
                // Set distance to the model threshold
                seg2.setDistanceThreshold (wall_threshold);

                // Segment the largest planar component from the cloud
                seg2.setInputCloud (cloud_ransac);
                seg2.segment (*inliers, *ransac_coefficients);
            }

            ROS_INFO("After RANSAC: %d", cloud_ransac->width * cloud_ransac->height);

            if((cloud_ransac->width * cloud_ransac->height) > min_points_left){
                pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered_inc_walls (new pcl::PointCloud<pcl::PointXYZ>), cloud_filtered_only_walls (new pcl::PointCloud<pcl::PointXYZ>), cloud_projected_iw (new pcl::PointCloud<pcl::PointXYZ>), cloud_projected_ow (new pcl::PointCloud<pcl::PointXYZ>), cloud_projected_filtered (new pcl::PointCloud<pcl::PointXYZ>);

                // Points containing both walls + objects
                pcl::PassThrough<pcl::PointXYZ> pass_iw;
                pass_iw.setInputCloud (cloud_ransac);
                pass_iw.setFilterFieldName ("y");
                pass_iw.setFilterLimits (floor_threshold, object_wall_threshold);
                pass_iw.filter (*cloud_filtered_inc_walls);

                // Points only containing walls
                pcl::PassThrough<pcl::PointXYZ> pass_ow;
                pass_ow.setInputCloud (cloud_ransac);
                pass_ow.setFilterFieldName ("y");
                pass_ow.setFilterLimits (object_wall_threshold, y_max);
                pass_ow.filter (*cloud_filtered_only_walls);
                
                if(((cloud_filtered_inc_walls->width * cloud_filtered_inc_walls->height) != 0) && ((cloud_filtered_only_walls->width * cloud_filtered_only_walls->height) != 0) )
                {
                    // Create a set of planar coefficients with X=Z=0,Y=1
                    pcl::ModelCoefficients::Ptr coefficients (new pcl::ModelCoefficients ());
                    coefficients->values.resize (4);
                    coefficients->values[0] = coefficients->values[2] = 0;
                    coefficients->values[1] = 1.0;
                    coefficients->values[3] = 0;

                    // Eliminate y-axis by projection to 2D
                    pcl::ProjectInliers<pcl::PointXYZ> proj1;
                    proj1.setModelType (pcl::SACMODEL_PLANE);
                    proj1.setInputCloud (cloud_filtered_inc_walls);
                    proj1.setModelCoefficients (coefficients);
                    proj1.filter (*cloud_projected_iw);

                    pcl::ProjectInliers<pcl::PointXYZ> proj2;
                    proj2.setModelType (pcl::SACMODEL_PLANE);
                    proj2.setInputCloud (cloud_filtered_only_walls);
                    proj2.setModelCoefficients (coefficients);
                    proj2.filter (*cloud_projected_ow);

                    // Remove projected walls from cloud_projected_iw
                    if((cloud_projected_iw->width * cloud_projected_iw->height) != 0)
                    {
                        // Create kdtree
                        pcl::KdTreeFLANN<pcl::PointXYZ> kdtree;
                        kdtree.setInputCloud (cloud_projected_iw);
                        double radius = wall_threshold;

                        pcl::PointIndices::Ptr wallpoint_indices(new pcl::PointIndices);

                        // Create a set of already included indices
                        boost::unordered::unordered_set<int> inc_indices;

                        // Iterate over all points in cloud containing only walls
                        for (int i = 0; i < cloud_projected_ow->size(); i++)
                        {
                            pcl::PointXYZ owPoint = cloud_projected_ow->at(i) ;

                            std::vector<int> k_indices;
                            std::vector<float> k_distances;

                            // Find points which are closes neighbors to the walls
                            if(kdtree.radiusSearch (owPoint, radius, k_indices, k_distances) > 0){

                                // Iterate over points
                                for(std::vector<int>::size_type i = 0; i != k_indices.size(); i++) {
                                    int index = k_indices[i];
                                    // If no match is found for index, add to set & wallpoint indices
                                    if (inc_indices.find(index) == inc_indices.end()){
                                        inc_indices.insert(index);
                                        wallpoint_indices->indices.push_back(index);
                                    }
                                }
                            }
                        }

                        if(wallpoint_indices->indices.size() > 0){

                            ROS_INFO("Filter points: %d", int(wallpoint_indices->indices.size()));

                            // Remove the wall points
                            pcl::ExtractIndices<pcl::PointXYZ> extract;
                            extract.setInputCloud (cloud_filtered_inc_walls);
                            extract.setIndices (wallpoint_indices);
                            extract.setNegative (true);
                            extract.filter (*cloud_projected_filtered);
                        }
                        else{
                            cloud_projected_filtered = cloud_filtered_inc_walls;
                        }

                        ROS_INFO("After WF: %d", cloud_projected_filtered->width * cloud_projected_filtered->height);

                        return cloud_projected_filtered;
                    }
                    else
                    {
                        return cloud_filtered_inc_walls;     // correct?
                    }
                }
                else
                {
                    return cloud_ransac;        // correct?
                }
            }
            else
            {
                return cloud_ransac;
            }
        }
        else
        {
            return cloud_filtered_z;
        }
    }
    else
    {
        return cloud;
    }
}
void cloud_cb (const pcl::PCLPointCloud2ConstPtr& cloud_blob)
{
  std::cout<<"Received Kinect message\n";
  pcl::PCLPointCloud2::Ptr cloud_filtered_blob (new pcl::PCLPointCloud2);
  pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud_filtered (new pcl::PointCloud<pcl::PointXYZRGB>), cloud_p (new pcl::PointCloud<pcl::PointXYZRGB>), cloud_f (new pcl::PointCloud<pcl::PointXYZRGB>);
  
  // Create the filtering object: downsample the dataset using a leaf size of 1cm
  pcl::VoxelGrid<pcl::PCLPointCloud2> sor;
  sor.setInputCloud (cloud_blob);
  boost::this_thread::sleep (boost::posix_time::microseconds (100));

  sor.setLeafSize (0.01f, 0.01f, 0.01f);
  sor.filter (*cloud_filtered_blob);

  // Convert to the templated PointCloud
  pcl::fromPCLPointCloud2 (*cloud_filtered_blob, *cloud_filtered);

  pcl::ModelCoefficients::Ptr coefficients (new pcl::ModelCoefficients ());
  pcl::PointIndices::Ptr inliers (new pcl::PointIndices ());
  // Create the segmentation object
  pcl::SACSegmentation<pcl::PointXYZRGB> seg;
  // Optional
  seg.setOptimizeCoefficients (true);
  // Mandatory
  seg.setModelType (pcl::SACMODEL_PLANE);
  seg.setMethodType (pcl::SAC_RANSAC);
  seg.setMaxIterations (1000);
  seg.setDistanceThreshold (0.01);
  seg.setInputCloud (cloud_filtered);

  int i = 0, nr_points = (int) cloud_filtered->points.size ();
  pcl::IndicesPtr remaining (new std::vector<int>);
  remaining->resize (nr_points);
  for (size_t i = 0; i < remaining->size (); ++i) { (*remaining)[i] = static_cast<int>(i); }


  std::cout << "here again" << std::endl;


  // While 30% of the original cloud is still there
  while (remaining->size () > 0.3 * nr_points)
  {
    // Segment the largest planar component from the remaining cloud
    seg.setIndices (remaining);
    seg.segment (*inliers, *coefficients);
    if (inliers->indices.size () == 0) break;

    // Extract the inliers
    std::vector<int>::iterator it = remaining->begin();
    for (size_t i = 0; i < inliers->indices.size (); ++i)
    {
      int curr = inliers->indices[i];
      // Remove it from further consideration.
      while (it != remaining->end() && *it < curr) { ++it; }
      if (it == remaining->end()) break;
      if (*it == curr) it = remaining->erase(it);
    }
    i++;
  }
  std::cout << "Found " << i << " planes." << std::endl;

  // Color all the non-planar things.
  for (std::vector<int>::iterator it = remaining->begin(); it != remaining->end(); ++it)
  {
    uint8_t r = 0, g = 255, b = 0;
    uint32_t rgb = ((uint32_t)r << 16 | (uint32_t)g << 8 | (uint32_t)b);
    cloud_filtered->at(*it).rgb = *reinterpret_cast<float*>(&rgb);
  }

  pcl::visualization::CloudViewer viewer ("Simple Cloud Viewer");
  viewer.showCloud (cloud_filtered);
  while (!viewer.wasStopped ())
  {
  }




  // Publish the planes we found.
  pcl::PCLPointCloud2 outcloud;
  pcl::toPCLPointCloud2 (*cloud_filtered, outcloud);
  pub.publish (outcloud);
}
Exemple #8
0
int
main(int argc, char** argv)
{
	pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZRGB>);

	pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud_plane(new pcl::PointCloud<pcl::PointXYZRGB>);

	if (pcl::io::loadPCDFile<pcl::PointXYZRGB>("../learn15.pcd", *cloud) == -1) //* load the file
	{
		PCL_ERROR("Couldn't read file test_pcd.pcd \n");
		return (-1);
	}

	pcl::ModelCoefficients::Ptr coefficients(new pcl::ModelCoefficients);
	pcl::PointIndices::Ptr inliers(new pcl::PointIndices);
	// Create the segmentation object
	pcl::SACSegmentation<pcl::PointXYZRGB> seg;
	// Optional
	seg.setOptimizeCoefficients(true);
	// Mandatory
	seg.setModelType(pcl::SACMODEL_PLANE);
	seg.setMethodType(pcl::SAC_RANSAC);
	seg.setDistanceThreshold(0.01);
	seg.setInputCloud(cloud);
	seg.segment(*inliers, *coefficients);

	if (inliers->indices.size() == 0)
	{
		PCL_ERROR("Could not estimate a planar model for the given dataset.");
		return (-1);
	}

	std::cerr << "Model coefficients: " << coefficients->values[0] << " "
		<< coefficients->values[1] << " "
		<< coefficients->values[2] << " "
		<< coefficients->values[3] << std::endl;

	pcl::ExtractIndices<pcl::PointXYZRGB> extract;
	extract.setInputCloud(cloud);
	extract.setIndices(inliers);
	extract.setNegative(true);
	//Removes part_of_cloud but retain the original full_cloud
	//extract.setNegative(true); // Removes part_of_cloud from full cloud  and keep the rest
	extract.filter(*cloud_plane);

	pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud_filtered(new pcl::PointCloud<pcl::PointXYZRGB>);
	pcl::StatisticalOutlierRemoval<pcl::PointXYZRGB> sor;
	sor.setInputCloud(cloud_plane);
	sor.setMeanK(50);
	sor.setStddevMulThresh(1.0);
	sor.filter(*cloud_filtered);

	//cloud.swap(cloud_plane);
	/*
	pcl::visualization::CloudViewer viewer("Simple Cloud Viewer");
	viewer.showCloud(cloud_plane);
	while (!viewer.wasStopped())
	{
	}
	*/
	Eigen::Affine3f transform_2 = Eigen::Affine3f::Identity();
	Eigen::Matrix<float, 1, 3> fitted_plane_norm, xyaxis_plane_norm, rotation_axis;
	fitted_plane_norm[0] = coefficients->values[0];
	fitted_plane_norm[1] = coefficients->values[1];
	fitted_plane_norm[2] = coefficients->values[2];
	xyaxis_plane_norm[0] = 0.0;
	xyaxis_plane_norm[1] = 0.0;
	xyaxis_plane_norm[2] = 1.0;
	rotation_axis = xyaxis_plane_norm.cross(fitted_plane_norm);
	float theta = acos(xyaxis_plane_norm.dot(fitted_plane_norm)); 
	//float theta = -atan2(rotation_axis.norm(), xyaxis_plane_norm.dot(fitted_plane_norm));
	transform_2.rotate(Eigen::AngleAxisf(theta, rotation_axis));
	pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud_recentered(new pcl::PointCloud<pcl::PointXYZRGB>);
	pcl::transformPointCloud(*cloud_filtered, *cloud_recentered, transform_2);

	
	pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_xyz(new pcl::PointCloud<pcl::PointXYZ>); 
	pcl::copyPointCloud(*cloud_recentered, *cloud_xyz);

	///////////////////////////////////////////////////////////////////
	Eigen::Vector4f pcaCentroid;
	pcl::compute3DCentroid(*cloud_xyz, pcaCentroid);
 	Eigen::Matrix3f covariance;
	
	computeCovarianceMatrixNormalized(*cloud_xyz, pcaCentroid, covariance);
	Eigen::SelfAdjointEigenSolver<Eigen::Matrix3f> eigen_solver(covariance, Eigen::ComputeEigenvectors);
	Eigen::Matrix3f eigenVectorsPCA = eigen_solver.eigenvectors();
	std::cout << eigenVectorsPCA.size() << std::endl;
	if(eigenVectorsPCA.size()!=9)
	eigenVectorsPCA.col(2) = eigenVectorsPCA.col(0).cross(eigenVectorsPCA.col(1));


	
	Eigen::Matrix4f projectionTransform(Eigen::Matrix4f::Identity());
	projectionTransform.block<3, 3>(0, 0) = eigenVectorsPCA.transpose();
	projectionTransform.block<3, 1>(0, 3) = -1.f * (projectionTransform.block<3, 3>(0, 0) * pcaCentroid.head<3>());
	pcl::PointCloud<pcl::PointXYZ>::Ptr cloudPointsProjected(new pcl::PointCloud<pcl::PointXYZ>);
	pcl::transformPointCloud(*cloud_xyz, *cloudPointsProjected, projectionTransform);
	// Get the minimum and maximum points of the transformed cloud.
	pcl::PointXYZ minPoint, maxPoint;
	pcl::getMinMax3D(*cloudPointsProjected, minPoint, maxPoint);
	const Eigen::Vector3f meanDiagonal = 0.5f*(maxPoint.getVector3fMap() + minPoint.getVector3fMap());



	boost::shared_ptr<pcl::visualization::PCLVisualizer> viewer;
	viewer = rgbVis(cloud);
	// viewer->addPointCloud<pcl::PointXYZ>(cloudPointsProjected, "Simple Cloud");
	// viewer->addPointCloud<pcl::PointXYZRGB>(cloud, "Simple Cloud2");
	viewer->addCube(minPoint.x, maxPoint.x, minPoint.y, maxPoint.y, minPoint.z , maxPoint.z);

	while (!viewer->wasStopped())
	{
		viewer->spinOnce(100);
		boost::this_thread::sleep(boost::posix_time::microseconds(100000));
	}

	
	/*
	pcl::PCA< pcl::PointXYZ > pca;
	pcl::PointCloud< pcl::PointXYZ >::ConstPtr cloud;
	pcl::PointCloud< pcl::PointXYZ > proj;

	pca.setInputCloud(cloud);
	pca.project(*cloud, proj);

	Eigen::Vector4f proj_min;
	Eigen::Vector4f proj_max;
	pcl::getMinMax3D(proj, proj_min, proj_max);

	pcl::PointXYZ min;
	pcl::PointXYZ max;
	pca.reconstruct(proj_min, min);
	pca.reconstruct(proj_max, max);

	boost::shared_ptr<pcl::visualization::PCLVisualizer> viewer;
	viewer->addCube(min.x, max.x, min.y, max.y, min.z, max.z);

	*/


	return (0);

}
	void point_cb(const sensor_msgs::PointCloud2ConstPtr& cloud_msg){

		pcl::PCLPointCloud2* cloud = new pcl::PCLPointCloud2;
		pcl::PCLPointCloud2ConstPtr cloudPtr(cloud);
		pcl::PCLPointCloud2 cloud_filtered;

		pcl_conversions::toPCL(*cloud_msg, *cloud);

		pcl::VoxelGrid<pcl::PCLPointCloud2> sor;
		sor.setInputCloud(cloudPtr);

		float leaf = 0.005;
		sor.setLeafSize(leaf, leaf, leaf);
		sor.filter(cloud_filtered);

		sensor_msgs::PointCloud2 sensor_pcl;


		pcl_conversions::moveFromPCL(cloud_filtered, sensor_pcl);
		//publish pcl data 
		pub_voxel.publish(sensor_pcl);
		global_counter++;


		if((theta == 0.0 && y_offset == 0.0) || global_counter < 800 ){

		// part for planar segmentation starts here  ..
			pcl::PointCloud<pcl::PointXYZ>::Ptr cloud1(new pcl::PointCloud<pcl::PointXYZ>), cloud_p(new pcl::PointCloud<pcl::PointXYZ>), cloud_seg(new pcl::PointCloud<pcl::PointXYZ>); 
			pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_p_rotated(new pcl::PointCloud<pcl::PointXYZ>);
			pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_p_transformed(new pcl::PointCloud<pcl::PointXYZ>);
			pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_transformed(new pcl::PointCloud<pcl::PointXYZ>);

			sensor_msgs::PointCloud2  plane_sensor, plane_transf_sensor;

			//convert sen
			pcl::fromROSMsg(*cloud_msg, *cloud1);
			pcl::ModelCoefficients::Ptr coefficients(new pcl::ModelCoefficients);
			pcl::PointIndices::Ptr inliers(new pcl::PointIndices);

			pcl::SACSegmentation<pcl::PointXYZ> seg;

			seg.setOptimizeCoefficients(true);
			seg.setModelType (pcl::SACMODEL_PLANE);
	  		seg.setMethodType (pcl::SAC_RANSAC);
	  		seg.setMaxIterations (100);
			seg.setDistanceThreshold (0.01);

			seg.setInputCloud(cloud1);
			seg.segment (*inliers, *coefficients);

			Eigen::Matrix<float, 1, 3> surface_normal;
			Eigen::Matrix<float, 1, 3> floor_normal;
			surface_normal[0] = coefficients->values[0];
			surface_normal[1] = coefficients->values[1];
			surface_normal[2] = coefficients->values[2];
			std::cout << surface_normal[0] << "\n" << surface_normal[1] << "\n" << surface_normal[2];

			floor_normal[0] = 0.0;
			floor_normal[1] = 1.0;
			floor_normal[2] = 0.0;

			theta = acos(surface_normal.dot(floor_normal));
			//extract the inliers - copied from tutorials...

			pcl::ExtractIndices<pcl::PointXYZ> extract;
			extract.setInputCloud(cloud1);
	    	extract.setIndices (inliers);
	    	extract.setNegative(true);
	    	extract.filter(*cloud_p);

	    	ROS_INFO("print cloud info %d",  cloud_p->height);
	    	pcl::toROSMsg(*cloud_p, plane_sensor);
	    	pub_plane_simple.publish(plane_sensor);

	    	// anti rotate the point cloud by first finding the angle of rotation 

	    	Eigen::Affine3f transform_1 = Eigen::Affine3f::Identity();
	        transform_1.translation() << 0.0, 0.0, 0.0;
	        transform_1.rotate (Eigen::AngleAxisf (theta, Eigen::Vector3f::UnitX()));

	        pcl::transformPointCloud(*cloud_p, *cloud_p_rotated, transform_1);
			double y_sum = 0;
			// int num_points = 
			for (int i = 0; i < 20; i++){
				y_sum = cloud_p_rotated->points[i].y;
			}


			y_offset = y_sum / 20;

			Eigen::Affine3f transform_2 = Eigen::Affine3f::Identity();
	        transform_2.translation() << 0.0, -y_offset, 0.0;
	        transform_2.rotate (Eigen::AngleAxisf (theta, Eigen::Vector3f::UnitX()));

			pcl::transformPointCloud(*cloud_p, *cloud_p_transformed, transform_2);
	        pcl::transformPointCloud(*cloud1, *cloud_transformed, transform_2);

	        //now remove the y offset because of the camera rotation 

	        pcl::toROSMsg(*cloud_p_transformed, plane_transf_sensor);
	        // pcl::toROSMsg(*cloud_transformed, plane_transf_sensor);
	        // pcl::toROSMsg(*cloud1, plane_transf_sensor);
	        pub_plane_transf.publish(plane_transf_sensor);


		}


		ras_msgs::Cam_transform cft;

		cft.theta = theta;
		cft.y_offset = y_offset;	
		pub_ctf.publish(cft);	
		// pub_tf.publish();

	}
// Ros kinect topic callback
void callback(const sensor_msgs::PointCloud2ConstPtr& input) {
pcl::PointCloud<pcl::PointXYZ>::Ptr cloudKinect(new pcl::PointCloud<pcl::PointXYZ>());
pcl::fromROSMsg(*input, *cloudKinect);
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_f(new pcl::PointCloud<pcl::PointXYZ>());

//std::cout << cloud << std::endl;

//ROS_INFO(input);	

	//Inside the callback should be all the process that needed to be done with the point cloud
	//pcl::PointCloud<pcl::PointXYZ> cloudKinect;
	//pcl::fromROSMsg(*input, cloudKinect);
	pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(cloudKinect);
	//pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_f(new pcl::PointCloud<pcl::PointXYZ>);
	std::cout << cloud->points.size () << std::endl;
			 // Create the filtering object: downsample the dataset using a leaf size of 1cm
	  pcl::VoxelGrid<pcl::PointXYZ> vg;
	  pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered (new pcl::PointCloud<pcl::PointXYZ>());
 
	  vg.setInputCloud (cloud);
	  vg.setLeafSize (0.01f, 0.01f, 0.01f);
	  vg.filter (*cloud_filtered);

	std::cout << *cloud << std::endl;

 // pcl::PassThrough<pcl::PointXYZ> pass;
 // pass.setInputCloud (cloud);


	  // Create the segmentation object for the planar model and set all the parameters
	  pcl::SACSegmentation<pcl::PointXYZ> seg;
	  pcl::PointIndices::Ptr inliers (new pcl::PointIndices);
	  pcl::ModelCoefficients::Ptr coefficients (new pcl::ModelCoefficients);
	  pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_plane (new pcl::PointCloud<pcl::PointXYZ> ());
	  pcl::PCDWriter writer;
	  seg.setOptimizeCoefficients (true);
	  seg.setModelType (pcl::SACMODEL_PLANE);
	  seg.setMethodType (pcl::SAC_RANSAC);
	  seg.setMaxIterations (100);
	  seg.setDistanceThreshold (0.02);

	  int i=0, nr_points = (int) cloud_filtered->points.size ();
	  while (cloud_filtered->points.size () > 0.3 * nr_points)
	  {
	    // Segment the largest planar component from the remaining cloud
	    seg.setInputCloud (cloud_filtered);
	    seg.segment (*inliers, *coefficients);
	    if (inliers->indices.size () == 0)
	    {
	      std::cout << "Could not estimate a planar model for the given dataset." << std::endl;
	      break;
	    }

	    // Extract the planar inliers from the input cloud
	    pcl::ExtractIndices<pcl::PointXYZ> extract;
	    extract.setInputCloud (cloud_filtered);
	    extract.setIndices (inliers);
	    extract.setNegative (false);

	    // Get the points associated with the planar surface
	    extract.filter (*cloud_plane);

	    // Remove the planar inliers, extract the rest
	    extract.setNegative (true);
	    extract.filter (*cloud_f);
	 *cloud_filtered = *cloud_f;
	  }

	  // Creating the KdTree object for the search method of the extraction
	  pcl::search::KdTree<pcl::PointXYZ>::Ptr tree (new pcl::search::KdTree<pcl::PointXYZ>);
	  tree->setInputCloud (cloud_filtered);

	  std::vector<pcl::PointIndices> cluster_indices;
	  pcl::EuclideanClusterExtraction<pcl::PointXYZ> ec;
	  ec.setClusterTolerance (0.02); // 2cm
	  ec.setMinClusterSize (100);
	  ec.setMaxClusterSize (25000);
	  ec.setSearchMethod (tree);
	  ec.setInputCloud (cloud_filtered);
	  ec.extract (cluster_indices);

	  int j = 0;
	  for (std::vector<pcl::PointIndices>::const_iterator it = cluster_indices.begin (); it != cluster_indices.end (); ++it)
	    {
	      float minX = 1000000.0;
	      float minY = 1000000.0;
	      float maxX = -1000000.0;
	      float maxY = -1000000.0;

	      pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_cluster (new pcl::PointCloud<pcl::PointXYZ>);
	      for (std::vector<int>::const_iterator pit = it->indices.begin (); pit != it->indices.end (); pit++){
	        pcl::PointXYZ p = cloud_filtered->points[*pit];
	        cloud_cluster->points.push_back (cloud_filtered->points[*pit]);
	  	if(p.x < minX){ minX = p.x; }
	  	if(p.x > maxX){ maxX = p.x; }
	  	if(p.y < minY){ minY = p.y; }
	  	if(p.y > maxY){ maxY = p.y; }
	  }
	      cloud_cluster->width = cloud_cluster->points.size ();
	      cloud_cluster->height = 1;
	      cloud_cluster->is_dense = true;

	      Eigen::Vector4f centroid;
	      pcl::compute3DCentroid(*cloud_cluster, centroid);

//	      for (pcl::PointCloud<pcl::PointXYZ>::iterator p = cloud_cluster->points.begin(); p < cloud_cluster->points.end(); p++)
//	      {
//	  	if(p.x < minX){ minX = p; }
//	  	if(p.x > maxX){ maxX = p; }
//	  	if(p.y < minY){ minY = p; }
//	  	if(p.y > maxY){ maxY = p; }
//	      }

// 	      std::cout << "PointCloud representing the Cluster: " << cloud_cluster->points.size () << " data points." << std::endl;
// 	      std::cout << "Centroid " << centroid[0] << "," << centroid[1] << "," << centroid[2] << "." << std::endl;
// 	      std::cout << "min x: " << minX << std::endl;
// 	      std::cout << "max x: " << maxX << std::endl;
// 	      std::cout << "min y: " << minY << std::endl;
// 	      std::cout << "max y: " << maxY << std::endl;

	      float xdist = std::abs(minX-maxY);
	      float ydist = std::abs(minY-maxY);

// 	      std::cout << "dist x: " << xdist << std::endl;
// 	      std::cout << "dist y: " << ydist << std::endl;

	      if(xdist < grippersize || ydist < grippersize){
// 	        std::cout << "Graspable" << std::endl;
	     	std_msgs::String msg;
	     	std::stringstream rosmsg;
	     	rosmsg << centroid[0] << ",";
	     	rosmsg << centroid[1] << ",";
	     	rosmsg << centroid[2];
	     	msg.data = rosmsg.str();
	     	visionPublisher.publish(msg);
	     	
	     	std::stringstream ss;
            ss << "graspable_object" << j << ".pcd";
            writer.write<pcl::PointXYZ> (ss.str (), *cloud_cluster, false);
    	    j++;
	      }

	  }



}
Exemple #11
0
int
main(int argc, char** argv)
{
	// Objects for storing the point clouds.
	pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
	pcl::PointCloud<pcl::PointXYZ>::Ptr cloudNoPlane(new pcl::PointCloud<pcl::PointXYZ>);
	pcl::PointCloud<pcl::PointXYZ>::Ptr planePoints(new pcl::PointCloud<pcl::PointXYZ>);
	pcl::PointCloud<pcl::PointXYZ>::Ptr projectedPoints(new pcl::PointCloud<pcl::PointXYZ>);
 
	// Read a PCD file from disk.
	if (pcl::io::loadPCDFile<pcl::PointXYZ>(argv[1], *cloud) != 0)
	{
		return -1;
	}
 
	// Get the plane model, if present.
	pcl::ModelCoefficients::Ptr coefficients(new pcl::ModelCoefficients);
	pcl::SACSegmentation<pcl::PointXYZ> segmentation;
	segmentation.setInputCloud(cloud);
	segmentation.setModelType(pcl::SACMODEL_PLANE);
	segmentation.setMethodType(pcl::SAC_RANSAC);
	segmentation.setDistanceThreshold(0.01);
	segmentation.setOptimizeCoefficients(true);
	pcl::PointIndices::Ptr inlierIndices(new pcl::PointIndices);
	segmentation.segment(*inlierIndices, *coefficients);
 
	if (inlierIndices->indices.size() == 0)
		std::cout << "Could not find a plane in the scene." << std::endl;
	else
	{
		std::cerr << "Plane coefficients: " << coefficients->values[0] << " "
				  << coefficients->values[1] << " "
				  << coefficients->values[2] << " "
				  << coefficients->values[3] << std::endl;
 
		// Create a second point cloud that does not have the plane points.
		// Also, extract the plane points to visualize them later.
		pcl::ExtractIndices<pcl::PointXYZ> extract;
		extract.setInputCloud(cloud);
		extract.setIndices(inlierIndices);
		extract.filter(*planePoints);
		extract.setNegative(true);
		extract.filter(*cloudNoPlane);
 
		// Object for projecting points onto a model.
		pcl::ProjectInliers<pcl::PointXYZ> projection;
		// We have to specify what model we used.
		projection.setModelType(pcl::SACMODEL_PLANE);
		projection.setInputCloud(cloudNoPlane);
		// And we have to give the coefficients we got.
		projection.setModelCoefficients(coefficients);
		projection.filter(*projectedPoints);
 
		// Visualize everything.
		pcl::visualization::CloudViewer viewerPlane("Plane");
		viewerPlane.showCloud(planePoints);
		while (!viewerPlane.wasStopped())
		{
			// Do nothing but wait.
		}
		pcl::visualization::CloudViewer viewerProjection("Projected points");
		viewerProjection.showCloud(projectedPoints);
		while (!viewerProjection.wasStopped())
		{
			// Do nothing but wait.
		}
	}
}
int
 main (int argc, char** argv)
{
  pcl::PointCloud<pcl::PointXYZ> cloud;

  pcl::io::loadPCDFile(argv[1],cloud);
  //pcl::io::loadPLYFile(argv[1], cloud);

  pcl::ModelCoefficients::Ptr coefficients (new pcl::ModelCoefficients);
  pcl::PointIndices::Ptr inliers (new pcl::PointIndices);
  // Create the segmentation object

  pcl::SACSegmentation<pcl::PointXYZ> seg;
  // Optional
  seg.setOptimizeCoefficients (true);
  // Mandatory
  seg.setModelType (pcl::SACMODEL_PLANE);
  seg.setMethodType (pcl::SAC_RANSAC);
  double distanceTh = 0.025;
  if(argc > 2)
      distanceTh = atof(argv[2]);
  seg.setDistanceThreshold (distanceTh);

  seg.setInputCloud (cloud.makeShared ());
  seg.segment (*inliers, *coefficients);

  if (inliers->indices.size () == 0)
  {
    PCL_ERROR ("Could not estimate a planar model for the given dataset.");
    return (-1);
  }

  std::cerr << "Model coefficients: " << coefficients->values[0] << " " 
                                      << coefficients->values[1] << " "
                                      << coefficients->values[2] << " " 
                                      << coefficients->values[3] << std::endl;

  pcl::PointCloud<pcl::PointXYZ> output;
  output.width = inliers->indices.size();
  output.height = 1;
  output.points.resize(output.width * output.height);

  std::cerr << "Model inliers: " << inliers->indices.size () << std::endl;
  for (size_t i = 0; i < inliers->indices.size (); ++i){
    /*std::cerr << inliers->indices[i] << "    " << cloud.points[inliers->indices[i]].x << " "
                                               << cloud.points[inliers->indices[i]].y << " "
                                               << cloud.points[inliers->indices[i]].z << std::endl;*/
    output.points[i].x = cloud.points[inliers->indices[i]].x;
    output.points[i].y = cloud.points[inliers->indices[i]].y;
    output.points[i].z = cloud.points[inliers->indices[i]].z;
  }
  pcl::PointCloud<pcl::PointXYZ> object;

  pcl::ExtractIndices<pcl::PointXYZ> extract;
  pcl::PointCloud<pcl::PointXYZ>::Ptr tempPtr(new pcl::PointCloud<pcl::PointXYZ>);
  pcl::copyPointCloud(cloud,*tempPtr);
  extract.setInputCloud(tempPtr);
  extract.setIndices(inliers);
  extract.setNegative(true);
  extract.filter(object);

  pcl::io::savePCDFile("output.pcd",output);
  pcl::io::savePCDFile("object.pcd",object);


  /*THE PLANAR SEGMENT REMOVED NOW RUN CLUSTERING AND COMPARE WITH EACH ONE.*/
  system("../eucliden_clustering/build/cluster_extraction ./object.pcd");
  return (0);
}
void cloud_cb(const sensor_msgs::PointCloud2ConstPtr &input) {
  // std::cerr << "in cloud_cb" << std::endl;
  /* 0. Importing input cloud */
  std_msgs::Header header = input->header;
  // std::string frame_id = input->header.frame_id;
  // sensor_msgs::PointCloud2 input_cloud = *input;

  pcl::PCLPointCloud2 *cloud = new pcl::PCLPointCloud2; // initialize object
  pcl_conversions::toPCL(*input, *cloud); // from input, generate content of cloud

  /* 1. Downsampling and Publishing voxel */
  // LeafSize: should small enough to caputure a leaf of plants
  pcl::PCLPointCloud2ConstPtr cloudPtr(cloud); // imutable pointer
  pcl::PCLPointCloud2 cloud_voxel; // cloud_filtered to cloud_voxel
  pcl::VoxelGrid<pcl::PCLPointCloud2> sor;

  sor.setInputCloud(cloudPtr); // set input
  sor.setLeafSize(0.02f, 0.02f, 0.02f); // 2cm, model equation
  sor.filter(cloud_voxel); // set output

  sensor_msgs::PointCloud2 output_voxel;
  pcl_conversions::fromPCL(cloud_voxel, output_voxel);
  pub_voxel.publish(output_voxel);

  /* 2. Filtering with RANSAC */
  // RANSAC initialization
  pcl::SACSegmentation<pcl::PointXYZ> seg; // Create the segmentation object
  pcl::PointIndices::Ptr inliers (new pcl::PointIndices ());
  pcl::ModelCoefficients::Ptr coefficients (new pcl::ModelCoefficients ());
  seg.setOptimizeCoefficients(true); // Optional
  // seg.setModelType(pcl::SACMODEL_PLANE);
  seg.setModelType(pcl::SACMODEL_PERPENDICULAR_PLANE); // Use SACMODEL_PERPENDICULAR_PLANE instead
  seg.setMethodType(pcl::SAC_RANSAC);

  // minimum number of points calculated from N and distanceThres
  seg.setMaxIterations (1000); // N in RANSAC
  // seg.setDistanceThreshold(0.025); // 0.01 - 0.05 default: 0.02 // 閾値(しきい値)
  seg.setDistanceThreshold(0.050); // 0.01 - 0.05 default: 0.02 // 閾値(しきい値)

  // param for perpendicular
  seg.setAxis(Eigen::Vector3f (0.0, 0.0, 1.0));
  seg.setEpsAngle(pcl::deg2rad (10.0f)); // 5.0 -> 10.0

  // convert from PointCloud2 to PointXYZ
  pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_voxel_xyz (new pcl::PointCloud<pcl::PointXYZ>);
  pcl::fromPCLPointCloud2(cloud_voxel, *cloud_voxel_xyz);

  // RANSAC application
  seg.setInputCloud(cloud_voxel_xyz);
  seg.segment(*inliers, *coefficients); // values are empty at beginning

  // inliers.indices have array index of the points which are included as inliers
  pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_plane_xyz (new pcl::PointCloud<pcl::PointXYZ>);
  for (std::vector<int>::const_iterator pit = inliers->indices.begin ();
       pit != inliers->indices.end (); pit++) {
    cloud_plane_xyz->points.push_back(cloud_voxel_xyz->points[*pit]);
  }
  // Organized as an image-structure
  cloud_plane_xyz->width = cloud_plane_xyz->points.size ();
  cloud_plane_xyz->height = 1;

  /* insert code to set arbitary frame_id setting
   such as frame_id ="/assemble_cloud_1"
  with respect to "/odom or /base_link" */

  // Conversions: PointCloud<T>, PCLPointCloud2, sensor_msgs::PointCloud2
  pcl::PCLPointCloud2 cloud_plane_pcl;
  pcl::toPCLPointCloud2(*cloud_plane_xyz, cloud_plane_pcl);
  sensor_msgs::PointCloud2 cloud_plane_ros;
  pcl_conversions::fromPCL(cloud_plane_pcl, cloud_plane_ros);
  // cloud_plane_ros.header.frame_id = "/base_link"; // odom -> /base_link
  cloud_plane_ros.header.frame_id = header.frame_id;
  cloud_plane_ros.header.stamp = header.stamp; // ros::Time::now() -> header.stamp
  pub_plane.publish(cloud_plane_ros);

  /* 3. PCA application to get eigen */
  pcl::PCA<pcl::PointXYZ> pca;
  pca.setInputCloud(cloud_plane_xyz);
  Eigen::Matrix3f eigen_vectors = pca.getEigenVectors(); // 3x3 eigen_vectors(n,m)

  /* 4. PCA Visualization */
  visualization_msgs::Marker points;
  // points.header.frame_id = "/base_link"; // odom -> /base_link
  points.header.frame_id = header.frame_id;
  points.header.stamp = input->header.stamp; // ros::Time::now() -> header.stamp
  points.ns = "pca"; // namespace + id
  points.id = 0; // pca/0
  points.action = visualization_msgs::Marker::ADD;
  points.type = visualization_msgs::Marker::ARROW;

  points.pose.orientation.w = 1.0;
  points.scale.x = 0.05;
  points.scale.y = 0.05;
  points.scale.z = 0.05;
  points.color.g = 1.0f;
  points.color.r = 0.0f;
  points.color.b = 0.0f;
  points.color.a = 1.0;

  geometry_msgs::Point p_0, p_1;
  p_0.x = 0; p_0.y = 0; p_0.z = 0; // get from tf
  p_1.x = eigen_vectors(0,0);
  p_1.y = eigen_vectors(0,1); // always negative
  std::cerr << "y = " << eigen_vectors(0,1) << std::endl;
  p_1.z = eigen_vectors(0,2);
  points.points.push_back(p_0);
  points.points.push_back(p_1);
  pub_marker.publish(points);

  /* 5. Point Cloud Rotation  */
  eigen_vectors(0,2) = 0; // ignore very small z-value
  double norm = pow((pow(eigen_vectors(0,0), 2) + pow(eigen_vectors(0,1), 2)), 0.5);
  double nx = eigen_vectors(0,0) / norm;
  double ny = eigen_vectors(0,1) / norm;

  Eigen::Matrix4d rot_z; // rotation inversed, convert to Matrix4f
  rot_z(0,0) = nx; rot_z(0,1) = ny; rot_z(0,2) = 0; rot_z(0,3) = 0; // ny: +/-
  rot_z(1,0) = -ny; rot_z(1,1) = nx; rot_z(1,2) = 0; rot_z(1,3) = 0; // ny: +/-
  rot_z(2,0) = 0; rot_z(2,1) = 0; rot_z(2,2) = 1; rot_z(2,3) = 0;
  rot_z(3,0) = 0; rot_z(3,1) = 0; rot_z(3,2) = 0; rot_z(3,3) = 1;

  // Transformation: Rotation, Translation
  pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_xyz (new pcl::PointCloud<pcl::PointXYZ>);
  pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_xyz_rot (new pcl::PointCloud<pcl::PointXYZ>);
  pcl::fromPCLPointCloud2(*cloudPtr, *cloud_xyz); // from PointCloud2 to PointXYZ
  pcl::transformPointCloud(*cloud_xyz, *cloud_xyz_rot, rot_z); // original, transformed, transformation
  pcl::PCLPointCloud2 cloud_rot_pcl;
  sensor_msgs::PointCloud2 cloud_rot_ros;
  pcl::toPCLPointCloud2(*cloud_xyz_rot, cloud_rot_pcl);
  pcl_conversions::fromPCL(cloud_rot_pcl, cloud_rot_ros);
  pub_rot.publish(cloud_rot_ros);

  /* 6. Point Cloud Reduction */
  std::vector<pcl::PointCloud<pcl::PointXYZ>::Ptr >
    vector_cloud_separated_xyz = separate(cloud_xyz_rot, header);
  pcl::PCLPointCloud2 cloud_separated_pcl;
  sensor_msgs::PointCloud2 cloud_separated_ros;

  pcl::toPCLPointCloud2(*vector_cloud_separated_xyz.at(1), cloud_separated_pcl);
  pcl_conversions::fromPCL(cloud_separated_pcl, cloud_separated_ros);
  // cloud_separated_ros.header.frame_id = "/base_link"; // odom -> /base_link
  cloud_separated_ros.header.frame_id = header.frame_id;
  cloud_separated_ros.header.stamp = input->header.stamp; // ros::Time::now() -> header.stamp
  pub_red.publish(cloud_separated_ros);

  // setMarker
  // visualization_msgs::Marker width_min_line;
  // width_min_line.header.frame_id = "/base_link";
  // width_min_line.header.stamp = input->header.stamp; // ros::Time::now() -> header.stamp
  // width_min_line.ns = "width_min";
  // width_min_line.action = visualization_msgs::Marker::ADD;
  // width_min_line.type = visualization_msgs::Marker::LINE_STRIP;
  // width_min_line.pose.orientation.w = 1.0;
  // width_min_line.id = 0;
  // width_min_line.scale.x = 0.025;
  // width_min_line.color.r = 0.0f;
  // width_min_line.color.g = 1.0f;
  // width_min_line.color.b = 0.0f;
  // width_min_line.color.a = 1.0;
  // width_min_line.points.push_back(point_vector.at(0));
  // width_min_line.points.push_back(point_vector.at(2));
  // pub_marker.publish(width_min_line);

  // /* 6. Visualize center line */
  // visualization_msgs::Marker line_strip;
  // line_strip.header.frame_id = "/base_link"; // odom -> /base_link
  // line_strip.header.stamp = input->header.stamp; // ros::Time::now() -> header.stamp
  // line_strip.ns = "center";
  // line_strip.action = visualization_msgs::Marker::ADD;
  // line_strip.type = visualization_msgs::Marker::LINE_STRIP;
  // line_strip.pose.orientation.w = 1.0;
  // line_strip.id = 0; // set id
  // line_strip.scale.x = 0.05;
  // line_strip.color.r = 1.0f;
  // line_strip.color.g = 0.0f;
  // line_strip.color.b = 0.0f;
  // line_strip.color.a = 1.0;
  // // geometry_msgs::Point p_stitch, p_min;
  // p_s.x = 0; p_s.y = 0; p_s.z = 0;
  // p_e.x = p_m.x; p_e.y = p_m.y; p_e.z = 0;
  // line_strip.points.push_back(p_s);
  // line_strip.points.push_back(p_e);
  // pub_marker.publish(line_strip);

  /* PCA Visualization */
  // geometry_msgs::Pose pose; tf::poseEigenToMsg(pca.getEigenVectors, pose);
  /* to use Pose marker in rviz */
  /* Automatic Measurement */
  // 0-a. stitch measurement: -0.5 < z < -0.3
  // 0-b. min width measurement: 0.3 < z < 5m
  // 1. iterate
  // 2. pick point if y < 0
  // 3. compare point with all points if 0 < y
  // 4. pick point-pare recording shortest distance
  // 5. compare the point with previous point
  // 6. update min
  // 7. display value in text in between 2 points
}