pcl::PointCloud<PointT>::Ptr cropCloud(const pcl::PointCloud<PointT>::Ptr cloud, const pcl::ModelCoefficients::Ptr planeCoef, float elev)
{
    pcl::PointCloud<PointT>::Ptr cloud_f(new pcl::PointCloud<PointT>());
    pcl::copyPointCloud(*cloud, *cloud_f);
    
    pcl::ProjectInliers<PointT> proj;
    proj.setModelType (pcl::SACMODEL_PLANE);
    proj.setInputCloud (cloud_f);
    proj.setModelCoefficients (planeCoef);

    pcl::PointCloud<PointT>::Ptr cloud_projected(new pcl::PointCloud<PointT>());
    proj.filter (*cloud_projected);
    for(size_t i = 0 ; i < cloud_f->size() ; i++ )
    {
        if( pcl_isfinite(cloud_f->at(i).z) == true )
        {
            float diffx = cloud_f->at(i).x-cloud_projected->at(i).x;
            float diffy = cloud_f->at(i).y-cloud_projected->at(i).y;
            float diffz = cloud_f->at(i).z-cloud_projected->at(i).z;

            float dist = sqrt( diffx*diffx + diffy*diffy + diffz*diffz);
            if ( dist <= elev )
            {
                cloud_f->at(i).x = NAN;
                cloud_f->at(i).y = NAN;
                cloud_f->at(i).z = NAN;
            }
        }
    }
    cloud_f->is_dense = false;
    return cloud_f;
}
示例#2
0
int
main (int argc, char** argv)
{
  pcl::PointCloud<pcl::PointXYZ>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZ>), 
                                      cloud_filtered (new pcl::PointCloud<pcl::PointXYZ>), 
                                      cloud_projected (new pcl::PointCloud<pcl::PointXYZ>);
  pcl::PCDReader reader;

  reader.read ("table_scene_mug_stereo_textured.pcd", *cloud);
  // Build a filter to remove spurious NaNs
  pcl::PassThrough<pcl::PointXYZ> pass;
  pass.setInputCloud (cloud);
  pass.setFilterFieldName ("z");
  pass.setFilterLimits (0, 1.1);
  pass.filter (*cloud_filtered);
  std::cerr << "PointCloud after filtering has: "
            << cloud_filtered->points.size () << " data points." << std::endl;

  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);
  seg.setDistanceThreshold (0.01);

  seg.setInputCloud (cloud_filtered);
  seg.segment (*inliers, *coefficients);
  std::cerr << "PointCloud after segmentation has: "
            << inliers->indices.size () << " inliers." << std::endl;

  // Project the model inliers
  pcl::ProjectInliers<pcl::PointXYZ> proj;
  proj.setModelType (pcl::SACMODEL_PLANE);
  proj.setIndices (inliers);
  proj.setInputCloud (cloud_filtered);
  proj.setModelCoefficients (coefficients);
  proj.filter (*cloud_projected);
  std::cerr << "PointCloud after projection has: "
            << cloud_projected->points.size () << " data points." << std::endl;

  // Create a Concave Hull representation of the projected inliers
  pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_hull (new pcl::PointCloud<pcl::PointXYZ>);
  pcl::ConcaveHull<pcl::PointXYZ> chull;
  chull.setInputCloud (cloud_projected);
  chull.setAlpha (0.1);
  chull.reconstruct (*cloud_hull);

  std::cerr << "Concave hull has: " << cloud_hull->points.size ()
            << " data points." << std::endl;

  pcl::PCDWriter writer;
  writer.write ("table_scene_mug_stereo_textured_hull.pcd", *cloud_hull, false);

  return (0);
}
	void DynModelExporter2::createMarkerForConvexHull(pcl::PointCloud<pcl::PointXYZ>& plane_cloud, pcl::ModelCoefficients::Ptr& plane_coefficients, visualization_msgs::Marker& marker)
	{
		// init marker
	    marker.type = visualization_msgs::Marker::TRIANGLE_LIST;
	    marker.action = visualization_msgs::Marker::ADD;

	    // project the points of the plane on the plane
	    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_projected (new pcl::PointCloud<pcl::PointXYZ> ());
	    pcl::ProjectInliers<pcl::PointXYZ> proj;
	    proj.setModelType (pcl::SACMODEL_PLANE);
	    proj.setInputCloud (plane_cloud.makeShared());
	    proj.setModelCoefficients (plane_coefficients);
	    proj.filter(*cloud_projected);

	    // create the convex hull in the plane
	    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_hull (new pcl::PointCloud<pcl::PointXYZ> ());
	    pcl::ConvexHull<pcl::PointXYZ > chull;
	    chull.setInputCloud (cloud_projected);
	    chull.reconstruct(*cloud_hull);

	    // work around known bug in ROS Diamondback perception_pcl: convex hull is centered around centroid of input cloud (fixed in pcl svn revision 443)
	    // thus: we shift the mean of cloud_hull to the mean of cloud_projected (fill dx, dy, dz and apply when creating the marker points)
	    Eigen::Vector4f meanPointCH, meanPointCP;
	    pcl::compute3DCentroid(*cloud_projected, meanPointCP);
	    pcl::compute3DCentroid(*cloud_hull, meanPointCH);
	    //float dx = 0;//meanPointCP[0]-meanPointCH[0];
	    //float dy = 0;//meanPointCP[1]-meanPointCH[1];
	    //float dz = 0;//meanPointCP[2]-meanPointCH[2];

	    // create colored part of plane by creating marker for each triangle between neighbored points on contour of convex hull an midpoint
	    marker.points.clear();
	    for (unsigned int j = 0; j < cloud_hull->points.size(); ++j)
	    {
	    	geometry_msgs::Point p;

	        p.x = cloud_hull->points[j].x; p.y = cloud_hull->points[j].y; p.z = cloud_hull->points[j].z;
	        marker.points.push_back( p );

	        p.x = cloud_hull->points[(j+1)%cloud_hull->points.size() ].x; p.y = cloud_hull->points[(j+1)%cloud_hull->points.size()].y; p.z = cloud_hull->points[(j+1)%cloud_hull->points.size()].z;
	        marker.points.push_back( p );

	        p.x = meanPointCP[0]; p.y = meanPointCP[1]; p.z = meanPointCP[2];
	        marker.points.push_back( p );

	    }

	// scale of the marker
	marker.scale.x = 1;
	marker.scale.y = 1;
	marker.scale.z = 1;

	}
示例#4
0
int
 main (int argc, char** argv)
{
  pcl::PointCloud<pcl::PointXYZ>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZ>);
  pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_projected (new pcl::PointCloud<pcl::PointXYZ>);

  // Fill in the cloud data
  cloud->width  = 5;
  cloud->height = 1;
  cloud->points.resize (cloud->width * cloud->height);

  for (size_t i = 0; i < cloud->points.size (); ++i)
  {
    cloud->points[i].x = 1024 * rand () / (RAND_MAX + 1.0f);
    cloud->points[i].y = 1024 * rand () / (RAND_MAX + 1.0f);
    cloud->points[i].z = 1024 * rand () / (RAND_MAX + 1.0f);
  }

  std::cerr << "Cloud before projection: " << std::endl;
  for (size_t i = 0; i < cloud->points.size (); ++i)
    std::cerr << "    " << cloud->points[i].x << " " 
                        << cloud->points[i].y << " " 
                        << cloud->points[i].z << std::endl;

  // Create a set of planar coefficients with X=Y=0,Z=1
  pcl::ModelCoefficients::Ptr coefficients (new pcl::ModelCoefficients ());
  coefficients->values.resize (4);
  coefficients->values[0] = coefficients->values[1] = 0;
  coefficients->values[2] = 1.0;
  coefficients->values[3] = 0;

  // Create the filtering object
  pcl::ProjectInliers<pcl::PointXYZ> proj;
  proj.setModelType (pcl::SACMODEL_PLANE);
  proj.setInputCloud (cloud);
  proj.setModelCoefficients (coefficients);
  proj.filter (*cloud_projected);

  std::cerr << "Cloud after projection: " << std::endl;
  for (size_t i = 0; i < cloud_projected->points.size (); ++i)
    std::cerr << "    " << cloud_projected->points[i].x << " " 
                        << cloud_projected->points[i].y << " " 
                        << cloud_projected->points[i].z << std::endl;

  return (0);
}
void cloud_cb (const sensor_msgs::PointCloud2ConstPtr& input)
{
  // Do data processing here...
  
  // run pass through filter to shrink point cloud
  pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud_passthrough(new pcl::PointCloud<pcl::PointXYZRGB>);
  //passthrough_z(input, cloud_passthrough);
  passthrough_y(input,cloud_passthrough);
  //passthrough_x(cloud_passthrough);
  pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud_outlier(new pcl::PointCloud<pcl::PointXYZRGB>);
  passthrough_oulier(input,cloud_outlier);
  pub_out.publish(*cloud_outlier);

  // run ransac to find floor
  pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud_projected(new pcl::PointCloud<pcl::PointXYZRGB>);
  ransac(cloud_passthrough, cloud_projected);
  pub.publish(*cloud_projected);

}
pcl::PointCloud<pcl::PointXYZRGBA>::Ptr calc_convex_hull(pcl::PointCloud<pcl::PointXYZRGBA>::ConstPtr cloud, pcl::PointIndices::Ptr inliers, pcl::ModelCoefficients::Ptr coefficients){
	pcl::PointCloud<pcl::PointXYZRGBA>::Ptr cloud_hull (new pcl::PointCloud<pcl::PointXYZRGBA>),
		cloud_projected (new pcl::PointCloud<pcl::PointXYZRGBA>);
	pcl::ConvexHull<pcl::PointXYZRGBA> chull;
	// Project the model inliers
	pcl::ProjectInliers<pcl::PointXYZRGBA> proj;
	proj.setModelType (pcl::SACMODEL_PLANE);
	proj.setIndices (inliers);
	proj.setInputCloud (cloud);
	proj.setModelCoefficients (coefficients);
	proj.filter (*cloud_projected);

	// Create a Convex Hull representation of the projected inliers
	chull.setInputCloud (cloud_projected);
	//chull.setAlpha (0.1);
	chull.reconstruct (*cloud_hull);

	return cloud_hull;
}
示例#7
0
PlaneExt::tVertices PlaneExt::ComputeConcaveHull(pcl::PointCloud<pcl::PointXYZ>::Ptr &plane_cloud, pcl::PointCloud<pcl::PointXYZ>::Ptr &plane_hull)
{
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_projected (new pcl::PointCloud<pcl::PointXYZ> ());

    // project all points onto current plane
    pcl::ProjectInliers<pcl::PointXYZ> proj;
    proj.setModelType (pcl::SACMODEL_PLANE);
    proj.setInputCloud (plane_cloud);
    proj.setModelCoefficients (planeCoefficients);
    proj.filter(*cloud_projected);

    // create the concave hull of the plane
    pcl::ConcaveHull<pcl::PointXYZ > chull;
    chull.setInputCloud (cloud_projected);
    chull.setAlpha(0.05);

    tVertices polys;
    chull.reconstruct(*plane_hull, polys);

    return polys;
}
示例#8
0
  PointI
  Cylinder::projectToAxis(const PointI& p)
  {

      pcl::ModelCoefficients::Ptr coefficients_line (new pcl::ModelCoefficients);
      coefficients_line->values.push_back(values[0]);
      coefficients_line->values.push_back(values[1]);
      coefficients_line->values.push_back(values[2]);
      coefficients_line->values.push_back(values[3]);
      coefficients_line->values.push_back(values[4]);
      coefficients_line->values.push_back(values[5]);

      pcl::PointCloud<PointI>::Ptr cloud_projected (new pcl::PointCloud<PointI>);
      pcl::PointCloud<PointI>::Ptr cloud_toProject (new pcl::PointCloud<PointI>);

      cloud_toProject->push_back (p);

      pcl::ProjectInliers<PointI> proj;
      proj.setModelType (pcl::SACMODEL_LINE);
      proj.setInputCloud (cloud_toProject);
      proj.setModelCoefficients (coefficients_line);
      proj.filter (*cloud_projected);
      return cloud_projected->points[0];
  }
示例#9
0
int HeightAboveGroundKernel::execute()
{
    // we require separate contexts for the input and ground files
    PointContextRef input_ctx;
    PointContextRef ground_ctx;

    // because we are appending HeightAboveGround to the input buffer, we must
    // register it's Dimension
    input_ctx.registerDim(Dimension::Id::HeightAboveGround);

    // StageFactory will be used to create required stages
    StageFactory f;

    // setup the reader, inferring driver type from the filename
    std::string reader_driver = f.inferReaderDriver(m_input_file);
    std::unique_ptr<Reader> input(f.createReader(reader_driver));
    Options readerOptions;
    readerOptions.add("filename", m_input_file);
    input->setOptions(readerOptions);

    // go ahead and execute to get the PointBuffer
    input->prepare(input_ctx);
    PointBufferSet pbSetInput = input->execute(input_ctx);
    PointBufferPtr input_buf = *pbSetInput.begin();

    PointBufferSet pbSetGround;
    PointBufferPtr ground_buf;

    if (m_use_classification)
    {
        // the user has indicated that the classification dimension exists, so
        // we will find all ground returns
        Option source("source",
                      "import numpy as np\n"
                      "def yow1(ins,outs):\n"
                      "  cls = ins['Classification']\n"
                      "  keep_classes = [2]\n"
                      "  keep = np.equal(cls, keep_classes[0])\n"
                      "  outs['Mask'] = keep\n"
                      "  return True\n"
                     );
        Option module("module", "MyModule");
        Option function("function", "yow1");
        Options opts;
        opts.add(source);
        opts.add(module);
        opts.add(function);

        // and create a PointBuffer of only ground returns
        std::unique_ptr<Filter> pred(f.createFilter("filters.predicate"));
        pred->setOptions(opts);
        pred->setInput(input.get());
        pred->prepare(ground_ctx);
        pbSetGround = pred->execute(ground_ctx);
        ground_buf = *pbSetGround.begin();
    }
    else
    {
        // the user has provided a file containing only ground returns, setup
        // the reader, inferring driver type from the filename
        std::string ground_driver = f.inferReaderDriver(m_ground_file);
        std::unique_ptr<Reader> ground(f.createReader(ground_driver));
        Options ro;
        ro.add("filename", m_ground_file);
        ground->setOptions(ro);

        // go ahead and execute to get the PointBuffer
        ground->prepare(ground_ctx);
        pbSetGround = ground->execute(ground_ctx);
        ground_buf = *pbSetGround.begin();
    }

    typedef pcl::PointXYZ PointT;
    typedef pcl::PointCloud<PointT> Cloud;
    typedef Cloud::Ptr CloudPtr;

    // convert the input PointBuffer to a PointCloud
    CloudPtr cloud(new Cloud);
    BOX3D const& bounds = input_buf->calculateBounds();
    pclsupport::PDALtoPCD(*input_buf, *cloud, bounds);

    // convert the ground PointBuffer to a PointCloud
    CloudPtr cloud_g(new Cloud);
    // here, we offset the ground cloud by the input bounds so that the two are aligned
    pclsupport::PDALtoPCD(*ground_buf, *cloud_g, bounds);

    // create a set of planar coefficients with X=Y=0,Z=1
    pcl::ModelCoefficients::Ptr coefficients(new pcl::ModelCoefficients());
    coefficients->values.resize(4);
    coefficients->values[0] = coefficients->values[1] = 0;
    coefficients->values[2] = 1.0;
    coefficients->values[3] = 0;

    // create the filtering object and project ground returns into xy plane
    pcl::ProjectInliers<PointT> proj;
    proj.setModelType(pcl::SACMODEL_PLANE);
    proj.setInputCloud(cloud_g);
    proj.setModelCoefficients(coefficients);
    CloudPtr cloud_projected(new Cloud);
    proj.filter(*cloud_projected);

    // setup the KdTree
    pcl::KdTreeFLANN<PointT> tree;
    tree.setInputCloud(cloud_projected);

    // loop over all points in the input cloud, finding the nearest neighbor in
    // the ground returns (XY plane only), and calculating the difference in z
    int32_t k = 1;
    for (size_t idx = 0; idx < cloud->points.size(); ++idx)
    {
        // Search for nearesrt neighbor of the query point
        std::vector<int32_t> neighbors(k);
        std::vector<float> distances(k);
        PointT temp_pt = cloud->points[idx];
        temp_pt.z = 0.0f;
        int num_neighbors = tree.nearestKSearch(temp_pt, k, neighbors, distances);

        double hag = cloud->points[idx].z - cloud_g->points[neighbors[0]].z;
        input_buf->setField(Dimension::Id::HeightAboveGround, idx, hag);
    }

    // populate BufferReader with the input PointBuffer, which now has the
    // HeightAboveGround dimension
    BufferReader bufferReader;
    bufferReader.addBuffer(input_buf);

    // we require that the output be BPF for now, to house our non-standard
    // dimension
    Options wo;
    wo.add("filename", m_output_file);
    std::unique_ptr<Writer> writer(f.createWriter("writers.bpf"));
    writer->setOptions(wo);
    writer->setInput(&bufferReader);
    writer->prepare(input_ctx);
    writer->execute(input_ctx);

    return 0;
}
示例#10
0
void FilterPlanes::filterPlanes(vector<BasicPlane> &plane_stack){
  pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud_filtered (new pcl::PointCloud<pcl::PointXYZRGB>), cloud_p (new pcl::PointCloud<pcl::PointXYZRGB>);
  
  if (verbose_text>0){
    cout << "PointCloud before filtering: " << cloud->width * cloud->height << " data points." << std::endl;
  }
  
  #if DO_TIMING_PROFILE
    vector<int64_t> tic_toc;
    tic_toc.push_back(bot_timestamp_now());
  #endif

/*  Ptcoll_cfg ptcoll_cfg;
  ptcoll_cfg.point_lists_id =pose_element_id; //bot_timestamp_now();
  ptcoll_cfg.collection = pose_coll_id;
  ptcoll_cfg.element_id = pose_element_id; */
  
  //1. Downsample the dataset using a leaf size of 1cm
  // this is 99% of the cpu time
  pcl::VoxelGrid<pcl::PointXYZRGB> sor;
  sor.setInputCloud (cloud);
  // for table dataset:  sor.setLeafSize (0.01, 0.01, 0.01);
  sor.setLeafSize (0.05, 0.05, 0.05);
//  sor.setLeafSize (0.1, 0.1, 0.1);
  sor.filter (*cloud_filtered);
  if (verbose_text>0){
    cout << "PointCloud after filtering: " << cloud_filtered->width * cloud_filtered->height << " data points." << std::endl;
  }
  
  #if DO_TIMING_PROFILE
  tic_toc.push_back(bot_timestamp_now());
  #endif
  
  if (verbose_lcm>2){
/*  ptcoll_cfg.id = 200;
  ptcoll_cfg.reset=true;
  ptcoll_cfg.name ="cloud_downsampled";
  ptcoll_cfg.npoints =	 cloud_filtered->points.size();
  float colorm_temp0[] ={-1.0,-1.0,-1.0,-1.0};
  ptcoll_cfg.rgba.assign(colorm_temp0,colorm_temp0+4*sizeof(float));  
  ptcoll_cfg.type =1;
  pcdXYZRGB_to_lcm(publish_lcm,ptcoll_cfg, *cloud_filtered);*/
  }
  
  // 2. Set up the Ransac Plane Fitting Object:
  pcl::ModelCoefficients::Ptr coefficients (new pcl::ModelCoefficients ());
  pcl::PointIndices::Ptr inliers (new pcl::PointIndices ());
  pcl::SACSegmentation<pcl::PointXYZRGB> seg;
  // Optional
  seg.setOptimizeCoefficients (true);
  // Mandatory
  seg.setModelType (pcl::SACMODEL_PLANE);
  seg.setMethodType (pcl::SAC_RANSAC);
  seg.setMaxIterations (100); // was 4000
  
  seg.setDistanceThreshold (distance_threshold_); // 0.01 for table data set
  // Create the filtering object
  pcl::ExtractIndices<pcl::PointXYZRGB> extract;
  
  #if DO_TIMING_PROFILE
  tic_toc.push_back(bot_timestamp_now());
  #endif
  
  int n_major = 0, nr_points = cloud_filtered->points.size ();
  //vector<BasicPlaneX> plane_stack;
  BasicPlane one_plane;
  // Extract the primary planes:
  // major planes are the coarse planes extracted via ransac. they might contain disconnected points
  // these are broken up into minor planes which are portions of major planes
  
  if(verbose_lcm > 2){
    for (int i=0;i<7;i++){
      char n_major_char[10];
      sprintf(n_major_char,"%d",i);
 /*     ptcoll_cfg.id =210+ i+3;
      ptcoll_cfg.reset=true;
      ptcoll_cfg.name =(char*) "cloud_p ";
      ptcoll_cfg.name.append(n_major_char);
      ptcoll_cfg.npoints = 0;
      float colorm_temp0[] ={-1.0,-1.0,-1.0,-1.0};
      ptcoll_cfg.rgba.assign(colorm_temp0,colorm_temp0+4*sizeof(float));  
      ptcoll_cfg.type=1;
      pcdXYZRGB_to_lcm(publish_lcm,ptcoll_cfg, *cloud_filtered);   
*/
    }
    
    for (int i=0;i<7;i++){
/*
      Ptcoll_cfg ptcoll_cfg2;
      // the i below accounts for super planes in the same utime
      ptcoll_cfg2.point_lists_id =pose_element_id; //bot_timestamp_now();
      ptcoll_cfg2.collection = pose_coll_id;
      ptcoll_cfg2.element_id = pose_element_id;    
      if (i==0){
        ptcoll_cfg2.reset=true;
      }else{
        ptcoll_cfg2.reset=false;
      }
      ptcoll_cfg2.id =500;
      ptcoll_cfg2.name.assign("Grown Stack Final");  
      ptcoll_cfg2.npoints = 0;
      ptcoll_cfg2.type =1;      
      pcdXYZRGB_to_lcm(publish_lcm,ptcoll_cfg2, *cloud_filtered);  
*/
    }       

    // TODO: this will rest this object. need to add publish of reset
    // at start of this block and set rese ttofal
    for (int i=0;i<7;i++){
/*
      Ptcoll_cfg ptcoll_cfg2;
      // the i below accounts for super planes in the same utime
      ptcoll_cfg2.point_lists_id =pose_element_id; //bot_timestamp_now();
      ptcoll_cfg2.collection = pose_coll_id;
      ptcoll_cfg2.element_id = pose_element_id;
      if (i==0){
        ptcoll_cfg2.reset=true;
      }else{
        ptcoll_cfg2.reset=false;
      }
      ptcoll_cfg2.id =501;
      ptcoll_cfg2.name.assign("Grown Stack Final Hull");  
      ptcoll_cfg2.npoints = 0;
      ptcoll_cfg2.type =3;
      pcdXYZRGB_to_lcm(publish_lcm,ptcoll_cfg2, *cloud_filtered);  
*/
    }       
  }

  #if DO_TIMING_PROFILE
  tic_toc.push_back(bot_timestamp_now());
  #endif
  
  while (cloud_filtered->points.size () > stop_proportion_ * nr_points) { 
    // While XX% of the original cloud is still there
    char n_major_char[10];
    sprintf(n_major_char,"%d",n_major);
    
    if (n_major >6) {
      if (verbose_text >0){
	std::cout << n_major << " is the max number of planes to find, quitting" << std::endl;
      }
      break; 
    }

    //a 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;
    }
    
 
    if (inliers->indices.size () <  stop_cloud_size_) // stop when the plane is only a few points
    {
      //std::cerr << "No remaining planes in this set" << std::endl;
      break;
    }    
    
    //b Extract the inliers
    extract.setInputCloud (cloud_filtered);
    extract.setIndices (inliers);
    extract.setNegative (false);
    extract.filter (*cloud_p);
    if (verbose_text>0){
      std::cout << "PointCloud representing the planar component: " << cloud_p->width * cloud_p->height << " data points." << std::endl;
    }
    
    // Create the filtering object
    pcl::StatisticalOutlierRemoval<pcl::PointXYZRGB> sor;
    sor.setInputCloud (cloud_p);
    sor.setMeanK (30);
    sor.setStddevMulThresh (0.5); //was 1.0
    sor.filter (*cloud_p);

    if(verbose_lcm > 2){
/*
      ptcoll_cfg.id =210+ n_major+3;
      ptcoll_cfg.reset=true;
      ptcoll_cfg.name ="cloud_p ";
      ptcoll_cfg.name.append(n_major_char);
      ptcoll_cfg.npoints = cloud_p->points.size();
      float colorm_temp0[] ={-1.0,-1.0,-1.0,-1.0};
      ptcoll_cfg.rgba.assign(colorm_temp0,colorm_temp0+4*sizeof(float));  
      ptcoll_cfg.type=1;
      pcdXYZRGB_to_lcm(publish_lcm,ptcoll_cfg, *cloud_p); 
*/   
    }

    vector<BasicPlane> grown_stack;
    vector<BasicPlane> * grown_stack_ptr;
    grown_stack_ptr = &grown_stack;
    
    GrowCloud grow;
    grow.setInputCloud(cloud_p);
    grow.setMinCloudSize(stop_cloud_size_); // useing stop cloud size here too
    grow.setLCM(publish_lcm);
    grow.doGrowCloud(*grown_stack_ptr);
    
    if (verbose_text>0){
      cout << "grow_cloud new found " << grown_stack.size() << " seperate clouds\n";
    }
	
    // Spit raw clouds out to LCM:
    if(verbose_lcm > 2){
      for (int i=0;i<grown_stack.size();i++){
/*
	Ptcoll_cfg ptcoll_cfg2;
	ptcoll_cfg2.reset=false;
	// the i below accounts for super planes in the same utime
	ptcoll_cfg2.point_lists_id =10*n_major + i; //filterplanes->pose_element_id;
	ptcoll_cfg2.collection = pose_coll_id;
	ptcoll_cfg2.element_id = pose_element_id;    

	ptcoll_cfg2.id =500;
	ptcoll_cfg2.name.assign("Grown Stack Final");  
	ptcoll_cfg2.npoints = grown_stack[i].cloud.points.size ();
	ptcoll_cfg2.type =1;
	
	int id =  plane_stack.size() + i; //   10*n_major + i;
	float colorm_temp0[] ={colors[3*(id%num_colors)],colors[3*(id%num_colors)+1],colors[3*(id%num_colors)+2] ,0.0};
	ptcoll_cfg2.rgba.assign(colorm_temp0,colorm_temp0+4*sizeof(float));  
	pcdXYZRGB_to_lcm(publish_lcm,ptcoll_cfg2, grown_stack[i].cloud);  
*/
      }  
    }
    
    BasicPlane one_plane;
    int n_minor=0;
    BOOST_FOREACH( BasicPlane one_plane, grown_stack ){
      pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud_projected (new pcl::PointCloud<pcl::PointXYZRGB>);
      pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud_hull (new pcl::PointCloud<pcl::PointXYZRGB>);
      
      // c Project the model inliers (seems to be necessary to fitting convex hull
      pcl::ProjectInliers<pcl::PointXYZRGB> proj;
      proj.setModelType (pcl::SACMODEL_PLANE);
      pcl::PointCloud<pcl::PointXYZRGB>::Ptr temp (new pcl::PointCloud<pcl::PointXYZRGB> ());
      *temp = (one_plane.cloud);
      proj.setInputCloud (temp);
      proj.setModelCoefficients (coefficients);
      proj.filter (*cloud_projected);
      
      std::vector <pcl::Vertices> vertices;
      if (1==1){ // convex:
        pcl::ConvexHull<pcl::PointXYZRGB> chull;
        chull.setInputCloud (cloud_projected);
        chull.setDimension(2);
        chull.reconstruct (*cloud_hull,vertices);
      }else { // concave
        pcl::ConcaveHull<pcl::PointXYZRGB> chull;
        chull.setInputCloud (cloud_projected);
        chull.setKeepInformation(true);
        chull.setAlpha(0.5);  
        // for arch way:
        // 1.1 too few
        // 0.7 a little to few but much better
        chull.reconstruct (*cloud_hull,vertices);
      }
      
      //std::cout << "Hull has: " << cloud_hull->points.size () << " vertices." << std::endl;
      if (cloud_hull->points.size () ==0){
        cout <<"ERROR: CONVEX HULL HAS NO POINTS! - NEED TO RESOLVE THIS\n"; 
      }
      
      
      // d.2 Find the mean colour of the hull:
      int rgba[]={0,0,0,0};
      for(int i=0;i<temp->points.size();i++){
	int rgba_one = *reinterpret_cast<int*>(&temp->points[i].rgba);
	rgba[3] += ((rgba_one >> 24) & 0xff);
	rgba[2] += ((rgba_one >> 16) & 0xff);
	rgba[1] += ((rgba_one >> 8) & 0xff);
	rgba[0] += (rgba_one & 0xff);      
      }
      double scale = ((double) temp->points.size());
      rgba[3] =(int)  round(((double) rgba[3]) / scale);
      rgba[2] =(int)  round(((double) rgba[2]) / scale);
      rgba[1] =(int)  round(((double) rgba[1]) / scale);
      rgba[0] =(int)  round(((double) rgba[0]) / scale);
      
      // Write the plane to file for experimentation:
      //stringstream oss;
      //oss << ptcoll_cfg.element_id <<"_" << ptcoll_cfg.name << ".pcd";
      //writer.write (oss.str(), *this_hull, false);
      for(int i=0;i<cloud_hull->points.size();i++){
	unsigned char* rgba_ptr = (unsigned char*)&cloud_hull->points[i].rgba;
	(*rgba_ptr) =  rgba[0]  ;
	(*(rgba_ptr+1)) = rgba[1];
	(*(rgba_ptr+2)) = rgba[2];
	(*(rgba_ptr+3)) = rgba[3];	
	
      }
      
      (one_plane.coeffs) = *coefficients;
      one_plane.cloud = *cloud_hull;
      one_plane.utime = pose_element_id;
      one_plane.major = n_major;
      one_plane.minor = n_minor;
      one_plane.n_source_points = cloud_projected->points.size();
      
      
      plane_stack.push_back(one_plane);      
      n_minor++;
  
    //  int stop;
    //  cout << "int to cont: ";
    //  cin >> stop;      
    }
    
    
    // Create the filtering object
    extract.setNegative (true);
    extract.filter (*cloud_filtered);
    n_major++;
  }
//input should be point cloud that is amplitude filetered, statistical outlier filtered, voxel filtered, coordinate system should be /map
void
PlaneExtraction::extractPlanes(const pcl::PointCloud<Point>::ConstPtr& pc_in,
                               std::vector<pcl::PointCloud<Point>, Eigen::aligned_allocator<pcl::PointCloud<Point> > >& v_cloud_hull,
                               std::vector<std::vector<pcl::Vertices> >& v_hull_polygons,
                               std::vector<pcl::ModelCoefficients>& v_coefficients_plane)
{
  static int ctr=0;
  static double time=0;
  PrecisionStopWatch t;
  t.precisionStart();
  std::stringstream ss;
  ROS_DEBUG("Extract planes");
  ROS_DEBUG("Saving files: %d", save_to_file_);
  if(save_to_file_)
  {
    ss.str("");
    ss.clear();
    ss << file_path_ << "/planes/pc_" << ctr_ << ".pcd";
    pcl::io::savePCDFileASCII (ss.str(), *pc_in);
  }
  //ROS_INFO("pc_in size: %d" , pc_in->size());
  // Extract Eucledian clusters

  std::vector<pcl::PointIndices> clusters;
  cluster_.setInputCloud (pc_in);
  cluster_.extract (clusters);
  //extractClusters (pc_in, clusters);
  ROS_DEBUG ("Number of clusters found: %d", (int)clusters.size ());
  //ROS_INFO("Clustering took %f s", t.precisionStop());
  //t.precisionStart();

  // Estimate point normals
  //normal_estimator_.setInputCloud(pc_in);
  //normalEstimator.setNumberOfThreads(4);
  //pcl::PointCloud<pcl::Normal>::Ptr cloud_normals(new pcl::PointCloud<pcl::Normal> ());
  //normal_estimator_.compute(*cloud_normals);
  //ROS_INFO("Normal estimation took %f s", t.precisionStop());
  //t.precisionStart();

  seg_.setInputCloud (pc_in);
  //seg_.setInputNormals (cloud_normals);

  proj_.setInputCloud (pc_in);

  // Go through all clusters and search for planes
  extracted_planes_indices_.clear();
  for(unsigned int i = 0; i < clusters.size(); ++i)
  {
    ROS_DEBUG("Processing cluster no. %u", i);
    // Extract cluster points
    /*pcl::PointCloud<Point> cluster;
    extract_.setInputCloud (pc_in);
    extract_.setIndices (boost::make_shared<const pcl::PointIndices> (clusters[i]));
    extract_.setNegative (false);
    extract_.filter (cluster);
    ROS_INFO("Extraction1 took %f s", t.precisionStop());
    t.precisionStart();*/
    /*pcl::PointCloud<Point>::Ptr cluster_ptr = cluster.makeShared();
    if(save_to_file_)
    {
      ss.str("");
      ss.clear();
      ss << file_path_ << "/planes/cluster_" << ctr_ << ".pcd";
      pcl::io::savePCDFileASCII (ss.str(), cluster);
    }*/

    // Find plane
    pcl::PointIndices::Ptr inliers_plane (new pcl::PointIndices ());
    //pcl::PointIndices::Ptr clusters_ptr(&clusters[i]);
    //pcl::PointIndices::Ptr consider_in_cluster(new pcl::PointIndices ());
    //for(unsigned int idx_ctr=0; idx_ctr < clusters[i].indices.size(); idx_ctr++)
    //  consider_in_cluster->indices.push_back(clusters[i].indices[idx_ctr]);
    int ctr = 0;
    // iterate over cluster to find all planes until cluster is too small
    while(clusters[i].indices.size() > min_plane_size_)
    {
      //ROS_INFO("Cluster size: %d", (int)consider_in_cluster->indices.size());

      seg_.setIndices(boost::make_shared<const pcl::PointIndices> (clusters[i]));
      // Obtain the plane inliers and coefficients
      pcl::ModelCoefficients coefficients_plane;
      seg_.segment (*inliers_plane, coefficients_plane);

      // Evaluate plane
      if (coefficients_plane.values.size () <=3)
      {
        //ROS_INFO("Failed to detect plane in scan, skipping cluster");
        break;
      }
      //TODO: parameter
      if ( inliers_plane->indices.size() < min_plane_size_)
      {
        //std::cout << "Plane coefficients: " << *coefficients_plane << std::endl;
        //ROS_INFO("Plane detection has %d inliers, below min threshold of %d, skipping cluster", (int)inliers_plane->indices.size(), 150);
        break;
      }
      bool validPlane = false;
      validPlane = isValidPlane (coefficients_plane);
      //std::cout << " Plane valid = " << validPlane << std::endl;

      if(validPlane)
      {
        // Extract plane points, only needed for storing bag file
        ROS_DEBUG("Plane has %d inliers", (int)inliers_plane->indices.size());
        /*pcl::PointCloud<Point> dominant_plane;
        extract_.setInputCloud(pc_in);
        extract_.setIndices(inliers_plane);
        extract_.filter(dominant_plane);
        if(save_to_file_)
        {
          ss.str("");
          ss.clear();
          ss << file_path_ << "/planes/plane_" << ctr_ << "_" << ctr << ".pcd";
          pcl::io::savePCDFileASCII (ss.str(), dominant_plane);
        }*/

        // Project the model inliers
        pcl::PointCloud<Point>::Ptr cloud_projected (new pcl::PointCloud<Point>);

        proj_.setModelCoefficients (boost::make_shared<pcl::ModelCoefficients>(coefficients_plane));
        proj_.setIndices(inliers_plane);
        proj_.filter (*cloud_projected);
        if(save_to_file_)
        {
          ss.str("");
          ss.clear();
          ss << file_path_ << "/planes/plane_pr_" << ctr_ << "_" << ctr << ".pcd";
          pcl::io::savePCDFileASCII (ss.str(), *cloud_projected);
        }

        std::vector<pcl::PointIndices> plane_clusters;
        cluster_plane_.setInputCloud (cloud_projected);
        cluster_plane_.extract (plane_clusters);

        extract_.setInputCloud(cloud_projected);
        /*std::cout << "projected: " << cloud_projected->size() << std::endl;
        std::cout << "inliers_plane: " << inliers_plane->indices.size() << std::endl;*/
        for(unsigned int j=0; j<plane_clusters.size(); j++)
        {
          pcl::PointCloud<Point> plane_cluster;
          extract_.setIndices(boost::make_shared<const pcl::PointIndices> (plane_clusters[j]));
          extract_.filter(plane_cluster);
          pcl::PointCloud<Point>::Ptr plane_cluster_ptr = plane_cluster.makeShared();

          if(plane_cluster_ptr->size() < min_plane_size_) continue;
          //else std::cout << "plane cluster has " << plane_cluster_ptr->size() << " points" << std::endl;

          // <evaluation_stuff>
          extracted_planes_indices_.push_back(std::vector<int>());
          //std::cout << "plane_cluster: " << plane_clusters[j].indices.size() << std::endl;
          for (size_t idx = 0; idx < plane_clusters[j].indices.size(); ++idx)
          {
            //std::cout << plane_clusters[j].indices[idx] << " ";
            extracted_planes_indices_.back().push_back(inliers_plane->indices[ plane_clusters[j].indices[idx] ]);
          }
          // </evaluation_stuff>

          // Create a Concave Hull representation of the projected inliers
          pcl::PointCloud<Point> cloud_hull;
          std::vector< pcl::Vertices > hull_polygons;
          chull_.setInputCloud (plane_cluster_ptr);
          //TODO: parameter

          chull_.reconstruct (cloud_hull, hull_polygons);
          /*std::cout << "Hull: " << cloud_hull.size() << ", " << hull_polygons[0].vertices.size()
            << ", "<< plane_cluster_ptr->size() << std::endl;*/
          if(hull_polygons.size() > 1)
          {
            extracted_planes_indices_.pop_back();
            continue;
            ROS_WARN("Extracted Polygon %d contours, separating ...", hull_polygons.size());
            pcl::PointCloud<Point>::Ptr cloud_hull_ptr = cloud_hull.makeShared();
            pcl::ExtractIndices<Point> extract_2;
            extract_2.setInputCloud(cloud_hull_ptr);
            for( unsigned int z=0; z<hull_polygons.size(); z++)
            {
              //ROS_WARN("\tC%d size: %d", z,hull_polygons[z].vertices.size());
              pcl::PointCloud<Point> cloud_hull_2;
              std::vector< pcl::Vertices > hull_polygons_2;
              pcl::PointIndices hull_poly_indices;
              for (unsigned int x=0; x<hull_polygons[z].vertices.size(); x++)
                hull_poly_indices.indices.push_back(hull_polygons[z].vertices[x]);
              //ROS_INFO("Size indices: %d", hull_poly_indices.indices.size());
              extract_2.setIndices(boost::make_shared<const pcl::PointIndices> (hull_poly_indices));
              extract_2.filter(cloud_hull_2);
              //ROS_INFO("Hull 2 size: %d", cloud_hull_2.size());
              pcl::Vertices verts;
              for(unsigned int y=0; y<cloud_hull_2.size(); y++)
                verts.vertices.push_back(y);
              verts.vertices.push_back(0);
              //ROS_INFO("Verts size: %d", verts.vertices.size());
              hull_polygons_2.push_back(verts);
              v_cloud_hull.push_back(cloud_hull_2);
              v_hull_polygons.push_back(hull_polygons_2);
              v_coefficients_plane.push_back(coefficients_plane);
            }
          }
          else
          {
            //ROS_INFO("Hull size: %d", cloud_hull.size());
            //ROS_INFO("Verts size: %d", hull_polygons[0].vertices.size());
            v_cloud_hull.push_back(cloud_hull);
            v_hull_polygons.push_back(hull_polygons);
            v_coefficients_plane.push_back(coefficients_plane);
          }
          ROS_DEBUG("v_cloud_hull size: %d", (unsigned int)v_cloud_hull.size());

          if(save_to_file_)
          {
            saveHulls(cloud_hull, hull_polygons, ctr);
          }
          ctr++;
        }

      }

      // Remove plane inliers from indices vector
      for(unsigned int idx_ctr1=0; idx_ctr1 < clusters[i].indices.size(); idx_ctr1++)
      {
        for(unsigned int idx_ctr2=0; idx_ctr2 < inliers_plane->indices.size(); idx_ctr2++)
        {
          if(clusters[i].indices[idx_ctr1] == inliers_plane->indices[idx_ctr2])
            clusters[i].indices.erase(clusters[i].indices.begin()+idx_ctr1);
        }
      }
      //ctr_++;
    }
    //ROS_INFO("Plane estimation took %f s", t.precisionStop());
    //t.precisionStart();
    /*if(clusters[i].indices.size() >0 )
    {
      if(save_to_file_)
      {
        ss.str("");
        ss.clear();
        ss << file_path_ << "/planes/rem_pts_" << ctr_ << "_" << ctr << ".pcd";
        if(consider_in_cluster->indices.size() == cluster_ptr->size())
          pcl::io::savePCDFileASCII (ss.str(), *cluster_ptr);
        else
        {
          pcl::PointCloud<Point> remaining_pts;
          extract_.setInputCloud (cluster_ptr);
          extract_.setIndices (consider_in_cluster);
          extract_.filter (remaining_pts);
          pcl::io::savePCDFileASCII (ss.str(), remaining_pts);
        }
      }
    }*/
    ctr_++;
  }
  double step_time = t.precisionStop();
  //ROS_INFO("Plane extraction took %f", step_time);
  time += step_time;
  //ROS_INFO("[plane extraction] Accumulated time at step %d: %f s", ctr, time);
  ctr++;
  return;
}
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);
}
// input: cloudInput
// input: pointCloudNormals
// output: cloudOutput
// output: pointCloudNormalsFiltered
void extractHandles(PointCloud::Ptr& cloudInput, PointCloud::Ptr& cloudOutput, PointCloudNormal::Ptr& pointCloudNormals, std::vector<int>& handles) {
	// PCL objects
	//pcl::PassThrough<Point> vgrid_;                   // Filtering + downsampling object
	pcl::VoxelGrid<Point> vgrid_; // Filtering + downsampling object
	pcl::SACSegmentationFromNormals<Point, pcl::Normal> seg_; // Planar segmentation object
	pcl::SACSegmentation<Point> seg_line_; // Planar segmentation object
	pcl::ProjectInliers<Point> proj_; // Inlier projection object
	pcl::ExtractIndices<Point> extract_; // Extract (too) big tables
	pcl::ConvexHull<Point> chull_;
	pcl::ExtractPolygonalPrismData<Point> prism_;
	pcl::PointCloud<Point> cloud_objects_;
	pcl::EuclideanClusterExtraction<Point> cluster_, handle_cluster_;
	pcl::PCDWriter writer;

	double sac_distance_, normal_distance_weight_;
	double eps_angle_, seg_prob_;
	int max_iter_;

	sac_distance_ = 0.05;  //0.02
	normal_distance_weight_ = 0.05;
	max_iter_ = 500;
	eps_angle_ = 30.0; //20.0
	seg_prob_ = 0.99;
	btVector3 axis(0.0, 0.0, 1.0);

	seg_.setModelType(pcl::SACMODEL_NORMAL_PARALLEL_PLANE);
	seg_.setMethodType(pcl::SAC_RANSAC);
	seg_.setDistanceThreshold(sac_distance_);
	seg_.setNormalDistanceWeight(normal_distance_weight_);
	seg_.setOptimizeCoefficients(true);
	seg_.setAxis(Eigen::Vector3f(fabs(axis.getX()), fabs(axis.getY()), fabs(axis.getZ())));
	seg_.setEpsAngle(pcl::deg2rad(eps_angle_));
	seg_.setMaxIterations(max_iter_);
	seg_.setProbability(seg_prob_);

	cluster_.setClusterTolerance(0.03);
	cluster_.setMinClusterSize(200);
	KdTreePtr clusters_tree_(new KdTree);
	clusters_tree_->setEpsilon(1);
	cluster_.setSearchMethod(clusters_tree_);

	seg_line_.setModelType(pcl::SACMODEL_LINE);
	seg_line_.setMethodType(pcl::SAC_RANSAC);
	seg_line_.setDistanceThreshold(0.05);
	seg_line_.setOptimizeCoefficients(true);
	seg_line_.setMaxIterations(max_iter_);
	seg_line_.setProbability(seg_prob_);

	//filter cloud
	double leafSize = 0.001;
	pcl::VoxelGrid<Point> sor;
	sor.setInputCloud (cloudInput);
	sor.setLeafSize (leafSize, leafSize, leafSize);
	sor.filter (*cloudOutput);
	//sor.setInputCloud (pointCloudNormals);
	//sor.filter (*pointCloudNormalsFiltered);
	//std::vector<int> tempIndices;
	//pcl::removeNaNFromPointCloud(*cloudInput, *cloudOutput, tempIndices);
	//pcl::removeNaNFromPointCloud(*pointCloudNormals, *pointCloudNormalsFiltered, tempIndices);

	// Segment planes
	pcl::OrganizedMultiPlaneSegmentation<Point, PointNormal, pcl::Label> mps;
	ROS_INFO("Segmenting planes");
	mps.setMinInliers (20000);
	mps.setMaximumCurvature(0.02);
	mps.setInputNormals (pointCloudNormals);
	mps.setInputCloud (cloudInput);
	std::vector<pcl::PlanarRegion<Point> > regions;
	std::vector<pcl::PointIndices> regionPoints;
	std::vector< pcl::ModelCoefficients > planes_coeff;
	mps.segment(planes_coeff, regionPoints);
	ROS_INFO_STREAM("Number of regions:" << regionPoints.size());

	if ((int) regionPoints.size() < 1) {
		ROS_ERROR("no planes found");
		return;
	}

  	std::stringstream filename;
	for (size_t plane = 0; plane < regionPoints.size (); plane++)
	{
		filename.str("");
		filename << "plane" << plane << ".pcd";
		writer.write(filename.str(), *cloudInput, regionPoints[plane].indices, true);
		ROS_INFO("Plane model: [%f, %f, %f, %f] with %d inliers.",
				planes_coeff[plane].values[0], planes_coeff[plane].values[1],
				planes_coeff[plane].values[2], planes_coeff[plane].values[3], (int)regionPoints[plane].indices.size ());

		//Project Points into the Perfect plane
		PointCloud::Ptr cloud_projected(new PointCloud());
		pcl::PointIndicesPtr cloudPlaneIndicesPtr(new pcl::PointIndices(regionPoints[plane]));
		pcl::ModelCoefficientsPtr coeff(new pcl::ModelCoefficients(planes_coeff[plane]));
		proj_.setInputCloud(cloudInput);
		proj_.setIndices(cloudPlaneIndicesPtr);
		proj_.setModelCoefficients(coeff);
		proj_.setModelType(pcl::SACMODEL_PARALLEL_PLANE);
		proj_.filter(*cloud_projected);

		PointCloud::Ptr cloud_hull(new PointCloud());
		// Create a Convex Hull representation of the projected inliers
		chull_.setInputCloud(cloud_projected);
		chull_.reconstruct(*cloud_hull);
		ROS_INFO("Convex hull has: %d data points.", (int)cloud_hull->points.size ());
		if ((int) cloud_hull->points.size() == 0)
		{
			ROS_WARN("Convex hull has: %d data points. Returning.", (int)cloud_hull->points.size ());
			return;
		}

		// Extract the handle clusters using a polygonal prism
		pcl::PointIndices::Ptr handlesIndicesPtr(new pcl::PointIndices());
		prism_.setHeightLimits(0.05, 0.1);
		prism_.setInputCloud(cloudInput);
		prism_.setInputPlanarHull(cloud_hull);
		prism_.segment(*handlesIndicesPtr);

		ROS_INFO("Number of handle candidates: %d.", (int)handlesIndicesPtr->indices.size ());
		if((int)handlesIndicesPtr->indices.size () < 1100)
			continue;

		/*######### handle clustering code
		handle_clusters.clear();
		handle_cluster_.setClusterTolerance(0.03);
		handle_cluster_.setMinClusterSize(200);
		handle_cluster_.setSearchMethod(clusters_tree_);
		handle_cluster_.setInputCloud(handles);
		handle_cluster_.setIndices(handlesIndicesPtr);
		handle_cluster_.extract(handle_clusters);
		for(size_t j = 0; j < handle_clusters.size(); j++)
		{
			filename.str("");
			filename << "handle" << (int)i << "-" << (int)j << ".pcd";
			writer.write(filename.str(), *handles, handle_clusters[j].indices, true);
		}*/

		pcl::StatisticalOutlierRemoval<Point> sor;
		PointCloud::Ptr cloud_filtered (new pcl::PointCloud<Point>);
		sor.setInputCloud (cloudInput);
		sor.setIndices(handlesIndicesPtr);
		sor.setMeanK (50);
		sor.setStddevMulThresh (1.0);
		sor.filter (*cloud_filtered);
		PointCloudNormal::Ptr cloud_filtered_hack (new PointCloudNormal);
		pcl::copyPointCloud(*cloud_filtered, *cloud_filtered_hack);

		// Our handle is in cloud_filtered.  We want indices of a cloud (also filtered for NaNs)
		pcl::KdTreeFLANN<PointNormal> kdtreeNN;
		std::vector<int> pointIdxNKNSearch(1);
		std::vector<float> pointNKNSquaredDistance(1);
		kdtreeNN.setInputCloud(pointCloudNormals);
		for(size_t j = 0; j < cloud_filtered_hack->points.size(); j++)
		{
			kdtreeNN.nearestKSearch(cloud_filtered_hack->points[j], 1, pointIdxNKNSearch, pointNKNSquaredDistance);
			handles.push_back(pointIdxNKNSearch[0]);
		}
	}
}
示例#14
-1
/**
 * extract handles from a pointcloud
 * @param[pointCloudIn] input point cloud
 * @param[pointCloudNormals] normals for the input cloud
 * @param[handle_indices] vector of indices, each item being a set of indices representing a handle
 * @param[handle_coefficients] vector of cofficients, each item being the coefficients of the line representing the handle
 */
void HandleExtractor::extractHandles(PointCloud::Ptr &cloudInput, PointCloudNormal::Ptr &pointCloudNormals,
                                     std::vector< pcl::PointIndices> &handle_indices, std::vector< pcl::ModelCoefficients> &handle_coefficients
                                    )
{

  // setup handle cluster object
  pcl::EuclideanClusterExtraction<Point> handle_cluster_;
  KdTreePtr clusters_tree_(new KdTree);
  handle_cluster_.setClusterTolerance(handle_cluster_tolerance);
  handle_cluster_.setMinClusterSize(min_handle_cluster_size);
  handle_cluster_.setSearchMethod(clusters_tree_);
  handle_cluster_.setInputCloud(cloudInput);

  pcl::PointCloud<Point>::Ptr cloud_filtered(new pcl::PointCloud<Point>());
  pcl::VoxelGrid<Point> vg;
  vg.setInputCloud(cloudInput);
  vg.setLeafSize(0.01, 0.01, 0.01);
  vg.filter(*cloud_filtered);

  // setup line ransac object
  pcl::SACSegmentation<Point> seg_line_;
  seg_line_.setModelType(pcl::SACMODEL_LINE);
  seg_line_.setMethodType(pcl::SAC_RANSAC);
  seg_line_.setInputCloud(cloudInput);
  seg_line_.setDistanceThreshold(line_ransac_distance);
  seg_line_.setOptimizeCoefficients(true);
  seg_line_.setMaxIterations(line_ransac_max_iter);

  // setup Inlier projection object
  pcl::ProjectInliers<Point> proj_;
  proj_.setInputCloud(cloud_filtered);
  proj_.setModelType(pcl::SACMODEL_PARALLEL_PLANE);

  // setup polygonal prism
  pcl::ExtractPolygonalPrismData<Point> prism_;
  prism_.setHeightLimits(min_handle_height, max_handle_height);
  prism_.setInputCloud(cloudInput);

  //setup Plane Segmentation
  outInfo("Segmenting planes");
  pcl::SACSegmentation<Point> seg_plane_;
  seg_plane_.setOptimizeCoefficients(true);
  seg_plane_.setModelType(pcl::SACMODEL_PLANE);
  seg_plane_.setMethodType(pcl::SAC_RANSAC);
  seg_plane_.setDistanceThreshold(0.03);
  seg_plane_.setMaxIterations(500);
  seg_plane_.setInputCloud(cloud_filtered);
  pcl::ModelCoefficients::Ptr plane_coefficients(new pcl::ModelCoefficients());
  pcl::PointIndices::Ptr plane_inliers(new pcl::PointIndices());
  seg_plane_.segment(*plane_inliers, *plane_coefficients);

  if(plane_inliers->indices.size() != 0)
  {
    outDebug("Plane model: "
             << plane_coefficients->values[0] << ","
             << plane_coefficients->values[1] << ","
             << plane_coefficients->values[2] << ","
             << plane_coefficients->values[3] << " with "
             << (int)plane_inliers->indices.size() << "inliers ");

    //Project inliers of the planes into a perfect plane
    PointCloud::Ptr cloud_projected(new PointCloud());
    proj_.setIndices(plane_inliers);
    proj_.setModelCoefficients(plane_coefficients);
    proj_.filter(*cloud_projected);

    // Create a Convex Hull representation using the projected inliers
    PointCloud::Ptr cloud_hull(new PointCloud());
    pcl::ConvexHull<Point> chull_;
    chull_.setDimension(2);
    chull_.setInputCloud(cloud_projected);
    chull_.reconstruct(*cloud_hull);
    outInfo("Convex hull has: " << (int)cloud_hull->points.size() << " data points.");
    if((int) cloud_hull->points.size() == 0)
    {
      outInfo("Convex hull has: no data points. Returning.");
      return;
    }

    // Extract the handle clusters using a polygonal prism
    pcl::PointIndices::Ptr handlesIndicesPtr(new pcl::PointIndices());
    prism_.setInputPlanarHull(cloud_hull);
    prism_.segment(*handlesIndicesPtr);

    // cluster the points found in the prism
    std::vector< pcl::PointIndices> handle_clusters;
    handle_cluster_.setIndices(handlesIndicesPtr);
    handle_cluster_.extract(handle_clusters);
    for(size_t j = 0; j < handle_clusters.size(); j++)
    {
      // for each cluster in the prism, attempt to fit a line using ransac
      pcl::PointIndices single_handle_indices;
      pcl::ModelCoefficients handle_line_coefficients;
      seg_line_.setIndices(getIndicesPointerFromObject(handle_clusters[j]));
      seg_line_.segment(single_handle_indices, handle_line_coefficients);
      if(single_handle_indices.indices.size() > 0)
      {
        outInfo("Found a handle with " << single_handle_indices.indices.size() << " inliers.");
        outDebug("Handle Line coefficients: " << handle_line_coefficients);
        handle_indices.push_back(single_handle_indices);
        handle_coefficients.push_back(handle_line_coefficients);
      }
    }
  }
  else
  {
    outInfo("no planes found");
    return;
  }
}