Example #1
0
int main()
{
  pcl::PointCloud<pcl::PointXYZ>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZ>);

  //... read, pass in or create a point cloud ...

  // Create the normal estimation class, and pass the input dataset to it
  pcl::NormalEstimation<pcl::PointXYZ, pcl::Normal> ne;
  ne.setInputCloud (cloud);

  // Create an empty kdtree representation, and pass it to the normal estimation object.
  // Its content will be filled inside the object, based on the given input dataset (as no other search surface is given).
  pcl::KdTreeFLANN<pcl::PointXYZ>::Ptr tree (new pcl::KdTreeFLANN<pcl::PointXYZ> ());
  //ne.setSearchMethod (tree);
  ne.setSearchMethod(pcl::search::KdTree<pcl::PointXYZ>::Ptr (new pcl::search::KdTree<pcl::PointXYZ>));

  // Output datasets
  pcl::PointCloud<pcl::Normal>::Ptr cloud_normals (new pcl::PointCloud<pcl::Normal>);

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

  // Compute the features
  ne.compute (*cloud_normals);

  // cloud_normals->points.size () should have the same size as the input cloud->points.size ()
}
int main (int argc, char** argv)
{
  typedef pcl::PointCloud<pcl::PointXYZ> PointXYZCloud;
  typedef pcl::PointCloud<pcl::PointNormal> PointNormalCloud;

  PointXYZCloud::Ptr cloud (new PointXYZCloud);
  cloud->width = 2;
  cloud->height = 5;
  cloud->points.resize(cloud->width * cloud->height);
  cloud->is_dense = true;

  // Create the normal estimation class, and pass the input dataset to it
  pcl::NormalEstimation<PointXYZCloud::PointType, PointNormalCloud::PointType> normalEstimation;
  normalEstimation.setInputCloud (cloud);

  // Create an empty kdtree representation, and pass it to the normal estimation object.
  // Its content will be filled inside the object, based on the given input dataset (as no other search surface is given).
  typedef pcl::search::KdTree<PointXYZCloud::PointType> TreeType;
  TreeType::Ptr tree (new TreeType);
  //normalEstimation.setSearchMethod (tree);

  //normalEstimation.setRadiusSearch (0.03);
  normalEstimation.setKSearch (3);

  // Compute the normals
  PointNormalCloud::Ptr cloud_normals (new PointNormalCloud);
  normalEstimation.compute (*cloud_normals);

  return 0;
}
//==================================================================
void pcl_visualization::cloud_cb (pcl::PointCloud<pcl::PointXYZ>::Ptr cloud)
{
    if (viewer.wasStopped() || m_stopFlag)
        return;

    // normalize
    normalize_cloud (cloud);

    // Viewer
    qDebug() << "cloud_cb_: cloud->width" << cloud->width;
    viewer.addPointCloud<pcl::PointXYZ> (cloud, "cloud");
    viewer.setPointCloudRenderingProperties (pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 2, "cloud");

    // All the objects needed
    pcl::NormalEstimation<pcl::PointXYZ, pcl::Normal> ne;
    pcl::PointCloud<pcl::Normal>::Ptr cloud_normals (new pcl::PointCloud<pcl::Normal>);
    pcl::search::KdTree<pcl::PointXYZ>::Ptr tree (new pcl::search::KdTree<pcl::PointXYZ> ());

    qDebug() << "Estimating point normals.";
    // Estimate point normals
    ne.setSearchMethod (tree);
    ne.setInputCloud (cloud);
    ne.setKSearch (10);
    ne.compute (*cloud_normals);

    qDebug() << "Adding visualizations to viewer.";
    viewer.setBackgroundColor (0, 0, 0);
    viewer.addPointCloudNormals<pcl::PointXYZ, pcl::Normal> (cloud, cloud_normals, 1, 0.1, "normals");
    viewer.setPointCloudRenderingProperties (pcl::visualization::PCL_VISUALIZER_COLOR, 1.0, 0.0, 0.0, "normals");
    viewer.setPointCloudRenderingProperties (pcl::visualization::PCL_VISUALIZER_LINE_WIDTH, 2, "normals");

    viewer.addCoordinateSystem(1.0);
    viewer.initCameraParameters();
}
pcl::ihs::InputDataProcessing::CloudProcessedPtr
pcl::ihs::InputDataProcessing::calculateNormals (const CloudInputConstPtr& cloud) const
{
  const CloudProcessedPtr cloud_out (new CloudProcessed ());

  // Calculate the normals
  CloudNormalsPtr cloud_normals (new CloudNormals ());
  normal_estimation_->setInputCloud (cloud);
  normal_estimation_->compute (*cloud_normals);

  // Copy the input cloud and normals into the output cloud.
  // While we are already iterating over the whole input we can also remove some points.
  cloud_out->resize (cloud->size ());
  cloud_out->header              = cloud->header;
  cloud_out->width               = cloud->width;
  cloud_out->height              = cloud->height;
  cloud_out->is_dense            = cloud->is_dense && cloud_normals->is_dense;
  cloud_out->sensor_origin_      = cloud->sensor_origin_;
  cloud_out->sensor_orientation_ = cloud->sensor_orientation_;

  CloudInput::const_iterator   it_in  = cloud->begin ();
  CloudNormals::const_iterator it_n   = cloud_normals->begin ();
  CloudProcessed::iterator     it_out = cloud_out->begin ();

  for (; it_in!=cloud->end (); ++it_in, ++it_n, ++it_out)
  {
    it_out->getVector4fMap ()       = it_in->getVector4fMap ();
    it_out->rgba                    = it_in->rgba;
    it_out->getNormalVector4fMap () = it_n->getNormalVector4fMap ();
  }

  return (cloud_out);
}
void
SACNormalsPlaneExtractor<PointT>::compute()
{
    CHECK ( cloud_  ) << "Input cloud is not organized!";

    all_planes_.clear();

    // ---[ PassThroughFilter
    typename pcl::PointCloud<PointT>::Ptr cloud_filtered (new pcl::PointCloud<PointT> ());
    pcl::PassThrough<PointT> pass;
    pass.setFilterLimits (0, max_z_bounds_);
    pass.setFilterFieldName ("z");
    pass.setInputCloud (cloud_);
    pass.filter (*cloud_filtered);

    if ( cloud_filtered->points.size () < k_)
    {
      PCL_WARN ("[DominantPlaneSegmentation] Filtering returned %lu points! Aborting.",
          cloud_filtered->points.size ());
      return;
    }

    // Downsample the point cloud
    typename pcl::PointCloud<PointT>::Ptr cloud_downsampled (new pcl::PointCloud<PointT> ());
    pcl::VoxelGrid<PointT> grid;
    grid.setLeafSize (downsample_leaf_, downsample_leaf_, downsample_leaf_);
    grid.setDownsampleAllData (false);
    grid.setInputCloud (cloud_filtered);
    grid.filter (*cloud_downsampled);

    // ---[ Estimate the point normals
    pcl::PointCloud<pcl::Normal>::Ptr cloud_normals (new pcl::PointCloud<pcl::Normal> ());
    pcl::NormalEstimation<PointT, pcl::Normal> n3d;
    typename pcl::search::KdTree<PointT>::Ptr normals_tree_ (new pcl::search::KdTree<PointT>);
    n3d.setKSearch ( (int) k_);
    n3d.setSearchMethod (normals_tree_);
    n3d.setInputCloud (cloud_downsampled);
    n3d.compute (*cloud_normals);

    // ---[ Perform segmentation
    pcl::SACSegmentationFromNormals<PointT, pcl::Normal> seg;
    seg.setDistanceThreshold (sac_distance_threshold_);
    seg.setMaxIterations (2000);
    seg.setNormalDistanceWeight (0.1);
    seg.setOptimizeCoefficients (true);
    seg.setModelType (pcl::SACMODEL_NORMAL_PLANE);
    seg.setMethodType (pcl::SAC_RANSAC);
    seg.setProbability (0.99);
    seg.setInputCloud (cloud_downsampled);
    seg.setInputNormals (cloud_normals);
    pcl::PointIndices table_inliers;
    pcl::ModelCoefficients coefficients;
    seg.segment ( table_inliers, coefficients);

    Eigen::Vector4f plane = Eigen::Vector4f(coefficients.values[0], coefficients.values[1],
                    coefficients.values[2], coefficients.values[3]);

    all_planes_.resize(1);
    all_planes_[0] = plane;
}
Example #6
0
//Function that computes the Viewpoint Feature Histogram
void VFH::computeVFHistogram(pcl::PointCloud<PointT>::Ptr cloud, const pcl::PointCloud<pcl::VFHSignature308>::Ptr vfhs)
{
	//---compute normals---
	pcl::PointCloud<pcl::Normal>::Ptr cloud_normals (new pcl::PointCloud<pcl::Normal>);

	//create normal estimation class, and pass the input cloud
	pcl::NormalEstimation<PointT, pcl::Normal> ne;
	ne.setInputCloud (cloud);

	//Create empty kdetree representation, and pass it to the normal estimation object.
	//its content will be filled inside the object based on the given input.
	pcl::search::KdTree<PointT>::Ptr tree(new pcl::search::KdTree<PointT> ());
	ne.setSearchMethod (tree);
	//set radious of the neighbors to use (1 cm)
	ne.setRadiusSearch(10);
	//computing normals
	ne.compute(*cloud_normals);

	//---proceed to compute VFH---

	//Create the VFH estimation class and pas the input to it
	pcl::VFHEstimation<PointT, pcl::Normal, pcl::VFHSignature308> vfh;
	vfh.setInputCloud (cloud);
	vfh.setInputNormals (cloud_normals);

	//create an empty kdtree representation and pass it to the vfh estimation object
	//its content will be filled inside the object based on the given input.
	pcl::search::KdTree<PointT>::Ptr vfhtree (new pcl::search::KdTree<PointT> ());
	vfh.setSearchMethod (vfhtree);

	//compute the features
	vfh.compute (*vfhs);
}
int 
main (int, char **argv)
{
  pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_ptr (new pcl::PointCloud<pcl::PointXYZ> ());
  pcl::PointCloud<pcl::Normal>::Ptr cloud_normals (new pcl::PointCloud<pcl::Normal> ());
  pcl::PCDWriter writer;
	
  if (pcl::io::loadPCDFile<pcl::PointXYZ> (argv[1], *cloud_ptr) == -1)
  {
    std::cout<<"Couldn't read the file "<<argv[1]<<std::endl;
    return (-1);
  }
  std::cout << "Loaded pcd file " << argv[1] << " with " << cloud_ptr->points.size () << std::endl;

  // Normal estimation
  pcl::NormalEstimation<pcl::PointXYZ, pcl::Normal> ne;
  ne.setInputCloud (cloud_ptr);

  pcl::search::KdTree<pcl::PointXYZ>::Ptr tree_n (new pcl::search::KdTree<pcl::PointXYZ>());
  ne.setSearchMethod (tree_n);
  ne.setRadiusSearch (0.03);
  ne.compute (*cloud_normals);
  std::cout << "Estimated the normals" << std::endl;

  // Creating the kdtree object for the search method of the extraction
  boost::shared_ptr<pcl::KdTree<pcl::PointXYZ> > tree_ec  (new pcl::KdTreeFLANN<pcl::PointXYZ> ());
  tree_ec->setInputCloud (cloud_ptr);
  
  // Extracting Euclidean clusters using cloud and its normals
  std::vector<int> indices;
  std::vector<pcl::PointIndices> cluster_indices;
  const float tolerance = 0.5f; // 50cm tolerance in (x, y, z) coordinate system
  const double eps_angle = 5 * (M_PI / 180.0); // 5degree tolerance in normals
  const unsigned int min_cluster_size = 50;
 
  pcl::extractEuclideanClusters (*cloud_ptr, *cloud_normals, tolerance, tree_ec, cluster_indices, eps_angle, min_cluster_size);

  std::cout << "No of clusters formed are " << cluster_indices.size () << std::endl;

  // Saving the clusters in seperate pcd files
  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_ptr->points[*pit]); 
    cloud_cluster->width = static_cast<uint32_t> (cloud_cluster->points.size ());
    cloud_cluster->height = 1;
    cloud_cluster->is_dense = true;

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

  return (0);
}
Example #8
0
QList <pcl::cloud_composer::CloudComposerItem*>
pcl::cloud_composer::NormalEstimationTool::performAction (ConstItemList input_data, PointTypeFlags::PointType type)
{
    QList <CloudComposerItem*> output;
    const CloudComposerItem* input_item;
    // Check input data length
    if ( input_data.size () == 0)
    {
        qCritical () << "Empty input in Normal Estimation Tool!";
        return output;
    }
    else if ( input_data.size () > 1)
    {
        qWarning () << "Input vector has more than one item in Normal Estimation!";
    }
    input_item = input_data.value (0);

    sensor_msgs::PointCloud2::ConstPtr input_cloud;
    if (input_item->type () == CloudComposerItem::CLOUD_ITEM)
    {
        double radius = parameter_model_->getProperty("Radius").toDouble();
        qDebug () << "Received Radius = " <<radius;
        sensor_msgs::PointCloud2::ConstPtr input_cloud = input_item->data (ItemDataRole::CLOUD_BLOB).value <sensor_msgs::PointCloud2::ConstPtr> ();
        qDebug () << "Got cloud size = "<<input_cloud->width;
        //////////////// THE WORK - COMPUTING NORMALS ///////////////////
        pcl::PointCloud<pcl::PointXYZ>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZ>);
        pcl::fromROSMsg (*input_cloud, *cloud);
        // Create the normal estimation class, and pass the input dataset to it
        pcl::NormalEstimation<pcl::PointXYZ, pcl::Normal> ne;
        ne.setInputCloud (cloud);

        // Create an empty kdtree representation, and pass it to the normal estimation object.
        // Its content will be filled inside the object, based on the given input dataset (as no other search surface is given).
        pcl::search::KdTree<pcl::PointXYZ>::Ptr tree (new pcl::search::KdTree<pcl::PointXYZ> ());
        ne.setSearchMethod (tree);

        // Output datasets
        pcl::PointCloud<pcl::Normal>::Ptr cloud_normals (new pcl::PointCloud<pcl::Normal>);

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

        // Compute the features
        ne.compute (*cloud_normals);
        //////////////////////////////////////////////////////////////////
        NormalsItem* normals_item = new NormalsItem (tr("Normals r=%1").arg(radius),cloud_normals,radius);
        output.append (normals_item);
        qDebug () << "Calced normals";
    }
    else
    {
        qDebug () << "Input item in Normal Estimation is not a cloud!!!";
    }


    return output;
}
Example #9
0
pcl::IndicesPtr normalFiltering(
		const typename pcl::PointCloud<PointT>::Ptr & cloud,
		const pcl::IndicesPtr & indices,
		float angleMax,
		const Eigen::Vector4f & normal,
		float radiusSearch,
		const Eigen::Vector4f & viewpoint)
{
	typedef typename pcl::search::KdTree<PointT> KdTree;
	typedef typename KdTree::Ptr KdTreePtr;

	pcl::NormalEstimation<PointT, pcl::Normal> ne;
	ne.setInputCloud (cloud);
	if(indices->size())
	{
		ne.setIndices(indices);
	}

	KdTreePtr tree (new KdTree(false));

	if(indices->size())
	{
		tree->setInputCloud(cloud, indices);
	}
	else
	{
		tree->setInputCloud(cloud);
	}
	ne.setSearchMethod (tree);

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

	ne.setRadiusSearch (radiusSearch);
	if(viewpoint[0] != 0 || viewpoint[1] != 0 || viewpoint[2] != 0)
	{
		ne.setViewPoint(viewpoint[0], viewpoint[1], viewpoint[2]);
	}

	ne.compute (*cloud_normals);

	pcl::IndicesPtr output(new std::vector<int>(cloud_normals->size()));
	int oi = 0; // output iterator
	Eigen::Vector3f n(normal[0], normal[1], normal[2]);
	for(unsigned int i=0; i<cloud_normals->size(); ++i)
	{
		Eigen::Vector4f v(cloud_normals->at(i).normal_x, cloud_normals->at(i).normal_y, cloud_normals->at(i).normal_z, 0.0f);
		float angle = pcl::getAngle3D(normal, v);
		if(angle < angleMax)
		{
			output->at(oi++) = indices->size()!=0?indices->at(i):i;
		}
	}
	output->resize(oi);

	return output;
}
pcl::ihs::InputDataProcessing::CloudProcessedPtr
pcl::ihs::InputDataProcessing::process (const CloudInputConstPtr& cloud) const
{
  const CloudProcessedPtr cloud_out (new CloudProcessed ());

  // Calculate the normals
  CloudNormalsPtr cloud_normals (new CloudNormals ());
  normal_estimation_->setInputCloud (cloud);
  normal_estimation_->compute (*cloud_normals);

  // Copy the input cloud and normals into the output cloud.
  // While we are already iterating over the whole input we can also remove some points.
  cloud_out->resize (cloud->size ());
  cloud_out->header              = cloud->header;
  cloud_out->width               = cloud->width;
  cloud_out->height              = cloud->height;
  cloud_out->is_dense            = false; /*cloud->is_dense && cloud_normals->is_dense;*/
  cloud_out->sensor_origin_      = cloud->sensor_origin_;
  cloud_out->sensor_orientation_ = cloud->sensor_orientation_;

  CloudInput::const_iterator   it_in  = cloud->begin ();
  CloudNormals::const_iterator it_n   = cloud_normals->begin ();
  CloudProcessed::iterator     it_out = cloud_out->begin ();

  for (; it_in!=cloud->end (); ++it_in, ++it_n, ++it_out)
  {
    if (pcl::isFinite (*it_in) && pcl::isFinite (*it_n) &&
        it_in->x >= x_min_     && it_in->x <= x_max_    &&
        it_in->y >= y_min_     && it_in->y <= y_max_    &&
        it_in->z >= z_min_     && it_in->z <= z_max_)
    {
      it_out->getVector4fMap ()       = it_in->getVector4fMap ();
      it_out->rgba                    = it_in->rgba;
      it_out->getNormalVector4fMap () = it_n->getNormalVector4fMap ();
    }
    else
    {
      // Fourth value should stay 1 (default)
      it_out->getVector3fMap () = Eigen::Vector3f (std::numeric_limits <float>::quiet_NaN (),
                                                   std::numeric_limits <float>::quiet_NaN (),
                                                   std::numeric_limits <float>::quiet_NaN ());
      // it_out->r = 0;
      // it_out->g = 0;
      // it_out->b = 0;
      // it_out->a = 255;

      // Fourth value should stay 0 (default)
      it_out->getNormalVector3fMap () = Eigen::Vector3f (std::numeric_limits <float>::quiet_NaN (),
                                                         std::numeric_limits <float>::quiet_NaN (),
                                                         std::numeric_limits <float>::quiet_NaN ());
    }
  }

  return (cloud_out);
}
Example #11
0
pcl::PointCloud<pcl::PointNormal>::Ptr computeNormals(pcl::PointCloud<pcl::PointXYZ>::Ptr cloud) {
    pcl::PointCloud<pcl::PointNormal>::Ptr cloud_normals (new pcl::PointCloud<pcl::PointNormal>); // Output datasets
    pcl::IntegralImageNormalEstimation<pcl::PointXYZ, pcl::PointNormal> ne;
    ne.setNormalEstimationMethod( ne.AVERAGE_3D_GRADIENT);
    ne.setMaxDepthChangeFactor(0.02f);
    ne.setNormalSmoothingSize(10.0f);
    ne.setInputCloud(cloud);
    ne.compute(*cloud_normals);
    copyPointCloud(*cloud, *cloud_normals);
    return cloud_normals;
}
Example #12
0
pcl::PointCloud<PointTNormal>::Ptr addNormalsToPointCloud(pcl::PointCloud<PointT>::Ptr cloud_input){
    pcl::PointCloud<PointTNormal>::Ptr cloudWithNormals(new pcl::PointCloud<PointTNormal>());

    pcl::NormalEstimation<PointT, pcl::Normal> ne;
    ne.setInputCloud (cloud_input);
    pcl::search::KdTree<PointT>::Ptr tree (new pcl::search::KdTree<PointT> ());
    ne.setSearchMethod (tree);
    pcl::PointCloud<pcl::Normal>::Ptr cloud_normals (new pcl::PointCloud<pcl::Normal>);
    ne.setRadiusSearch (0.03);
    ne.compute (*cloud_normals);
    pcl::concatenateFields(*cloud_input,*cloud_normals,*cloudWithNormals);

    return cloudWithNormals;
}
Example #13
0
pcl::PointCloud<pcl::Normal>::Ptr compute_normals(pcl::PointCloud<pcl::PointXYZ>::Ptr pcloud){
  pcl::NormalEstimation<pcl::PointXYZ, pcl::Normal> ne;
  ne.setInputCloud (pcloud);
  pcl::search::KdTree<pcl::PointXYZ>::Ptr tree (new pcl::search::KdTree<pcl::PointXYZ> ());
  ne.setSearchMethod (tree);

  // Output datasets
  pcl::PointCloud<pcl::Normal>::Ptr cloud_normals (new pcl::PointCloud<pcl::Normal>);

  // Use all neighbors in a sphere of radius 3cm
  ne.setRadiusSearch (7.0);
  ne.compute (*cloud_normals);
  return  cloud_normals;
}
int
main (int, char** av)
{
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_ptr (new pcl::PointCloud<pcl::PointXYZ>());
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_no_nans (new pcl::PointCloud<pcl::PointXYZ>());
    pcl::PointCloud<pcl::Normal>::Ptr cloud_normals (new pcl::PointCloud<pcl::Normal>());
    pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud_segmented (new pcl::PointCloud<pcl::PointXYZRGB>());

    pcl::PCDWriter writer;
    if (pcl::io::loadPCDFile(av[1], *cloud_ptr)==-1)
    {
        std::cout << "Couldn't find the file " << av[1] << std::endl;
        return -1;
    }

    std::cout << "Loaded cloud " << av[1] << " of size " << cloud_ptr->points.size() << std::endl;

    // Remove the nans
    cloud_ptr->is_dense = false;
    cloud_no_nans->is_dense = false;
    std::vector<int> indices;
    pcl::removeNaNFromPointCloud (*cloud_ptr, *cloud_no_nans, indices);
    std::cout << "Removed nans from " << cloud_ptr->points.size () << " to " << cloud_no_nans->points.size () << std::endl;

    // Estimate the normals
    pcl::NormalEstimation<pcl::PointXYZ, pcl::Normal> ne;
    ne.setInputCloud (cloud_no_nans);
    pcl::search::KdTree<pcl::PointXYZ>::Ptr tree_n (new pcl::search::KdTree<pcl::PointXYZ>());
    ne.setSearchMethod (tree_n);
    ne.setRadiusSearch (0.03);
    ne.compute (*cloud_normals);
    std::cout << "Normals are computed and size is " << cloud_normals->points.size () << std::endl;

    // Region growing
    pcl::RegionGrowing<pcl::PointXYZ, pcl::Normal> rg;
    rg.setSmoothModeFlag (false); // Depends on the cloud being processed
    rg.setInputCloud (cloud_no_nans);
    rg.setInputNormals (cloud_normals);

    std::vector <pcl::PointIndices> clusters;
    rg.extract (clusters);

    cloud_segmented = rg.getColoredCloud ();

    // Writing the resulting cloud into a pcd file
    std::cout << "No of segments done is " << clusters.size () << std::endl;
    writer.write<pcl::PointXYZRGB> ("segment_result.pcd", *cloud_segmented, false);

    return (0);
}
Example #15
0
void Normals::computeNormalsXYZRGB() {
	LOG(LWARNING) << "Normals::computeNormalsXYZRGB";
	pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud = in_cloud_xyzrgb.read();

	LOG(LWARNING) << "Normals: input size: " << cloud->size();
	pcl::PointCloud<pcl::PointXYZRGB>::Ptr copy(new pcl::PointCloud<pcl::PointXYZRGB>());



	// Remove NaNs.
	std::vector<int> indicesNANs;
	cloud->is_dense = false;
	pcl::removeNaNFromPointCloud(*cloud, *copy, indicesNANs);

	LOG(LWARNING) << "Normals: input size: " << copy->size();

	// compute centroid

//	Eigen::Vector4f centroid;
//	pcl::compute3DCentroid(*copy,centroid);
	//LOG(LDEBUG) << "Normals: centroid computed: " << centroid;

	// compute normals for centroid as viewpoint

	  pcl::NormalEstimation<pcl::PointXYZRGB, pcl::Normal> normalEstimation;
	  normalEstimation.setInputCloud (copy);
	  pcl::search::KdTree<pcl::PointXYZRGB>::Ptr tree (new pcl::search::KdTree<pcl::PointXYZRGB> ());
	  normalEstimation.setSearchMethod (tree);

	  pcl::PointCloud<pcl::Normal>::Ptr cloud_normals (new pcl::PointCloud<pcl::Normal>);
	  normalEstimation.setRadiusSearch (radius);
//	  normalEstimation.setViewPoint(centroid[0], centroid[1], centroid[2]);

	  LOG(LWARNING) << "Normals: compute normals!";
	  normalEstimation.compute (*cloud_normals);



	  pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr cloud_xyz_normals (new pcl::PointCloud<pcl::PointXYZRGBNormal>);
	  pcl::copyPointCloud(*copy, *cloud_xyz_normals);
	  pcl::copyPointCloud(*cloud_normals, *cloud_xyz_normals);

	  LOG(LWARNING) << "Normals: out_cloud_xyzrgb_normals.write " << cloud_normals->size();
	  out_cloud_xyzrgb_normals.write(cloud_xyz_normals);

	  LOG(LWARNING) << "Normals: out_cloud_normals.write " << cloud_normals->size();
	  out_cloud_normals.write(cloud_normals);
}
Example #16
0
	// --> clase que llama run() y que pasa la 'cloud' obtenida del openni_grabber <--
	void cloud_cb_ (const pcl::PointCloud<pcl::PointXYZRGBA>::ConstPtr &cloud)
	{	

		if(inicializacion == false)
		{
			viewer.addPointCloud(cloud,"cloud_RGBA-D");

			ne.setInputCloud (cloud);

			ne.setRadiusSearch (0.03);

			inicializacion = true;
		}else{
			viewer.removePointCloud(); // se carga "cloud", osease cloud_normals
		}
		
		if (!viewer.wasStopped())
		{	
			viewer.updatePointCloud(cloud);

			pcl::search::KdTree<pcl::PointXYZRGBA>::Ptr tree (new pcl::search::KdTree<pcl::PointXYZRGBA> ());

			ne.setSearchMethod (tree);

			pcl::PointCloud<pcl::Normal>::Ptr cloud_normals (new pcl::PointCloud<pcl::Normal>);
			pcl::PointCloud<pcl::Normal>::Ptr cloud_normals_out (new pcl::PointCloud<pcl::Normal>);

			ne.compute (*cloud_normals);

			/*
			// --> eliminar lineas nan <--
			std::vector<int> index;
			pcl::removeNaNNormalsFromPointCloud(*cloud_normals,*cloud_normals_out, index); 

			// remover outliers de las normales
			// probar a recorrer cloud_normals y aquellos indices que sean NAN, ponerlos a 0
			*/

			viewer.addPointCloudNormals<pcl::PointXYZRGBA,pcl::Normal>(cloud, cloud_normals); // asigna "cloud" a cloud_normals

			viewer.spinOnce(100);
		}
		
		 
	}
Example #17
0
void mpcl_extract_VFH(pcl::PointCloud<pcl::PointXYZ>::Ptr cloud)
{
    // http://virtuemarket-lab.blogspot.jp/2015/03/viewpoint-feature-histogram.html
    // pcl::PointCloud<pcl::VFHSignature308>::Ptr Extract_VFH(pcl::PointCloud<pcl::PointXYZ>::Ptr cloud)
    pcl::PointCloud<pcl::Normal>::Ptr cloud_normals (new pcl::PointCloud<pcl::Normal> ());
    pcl::VFHEstimation<pcl::PointXYZ, pcl::Normal, pcl::VFHSignature308> vfh;
    pcl::PointCloud<pcl::VFHSignature308>::Ptr vfhs (new pcl::PointCloud<pcl::VFHSignature308> ());

    // cloud_normals = surface_normals(cloud);

    vfh.setInputCloud (cloud);
    vfh.setInputNormals (cloud_normals);

    pcl::search::KdTree<pcl::PointXYZ>::Ptr tree (new pcl::search::KdTree<pcl::PointXYZ> ());
    vfh.setSearchMethod (tree);

    vfh.compute (*vfhs);
    // return vfhs;
}
Example #18
0
/** \brief Loads an n-D histogram file as a VFH signature
  * \param path the input file name
  * \param vfh the resultant VFH model
  */
bool
loadHist (const boost::filesystem::path &path, vfh_model &vfh)
{

    pcl::PointCloud<PointType>::Ptr cloud (new pcl::PointCloud<PointType>);
    pcl::PointCloud<NormalType>::Ptr cloud_normals (new pcl::PointCloud<NormalType> ());

    if (pcl::io::loadPCDFile<PointType> (path.string(), *cloud) == -1) {
        PCL_ERROR ("Couldn't read file %s.pcd \n", path.string().c_str());
        return false;
    }
    pcl::PointCloud<PointType>::Ptr cloud_filtered (new pcl::PointCloud<PointType>);
    std::vector<int> filter_index;
    pcl::removeNaNFromPointCloud (*cloud, *cloud_filtered, filter_index);
    cloud = cloud_filtered;

    pcl::NormalEstimationOMP<PointType, NormalType> norm_est;
    norm_est.setKSearch (10);
    norm_est.setInputCloud (cloud);
    norm_est.compute (*cloud_normals);

    pcl::VFHEstimation<PointType, NormalType, pcl::VFHSignature308> vfh_est;
    vfh_est.setInputCloud (cloud);
    vfh_est.setInputNormals (cloud_normals);

    pcl::search::KdTree<PointType>::Ptr tree (new pcl::search::KdTree<PointType> ());
    vfh_est.setSearchMethod (tree);
    pcl::PointCloud<pcl::VFHSignature308>::Ptr vfhs (new pcl::PointCloud<pcl::VFHSignature308> ());
    vfh_est.compute (*vfhs);

    vfh.second.resize (308);

    for (size_t i = 0; i < pcl::VFHSignature308::descriptorSize(); ++i)
    {
        vfh.second[i] = vfhs->points[0].histogram[i];
    }
    vfh.first = path.string ();
    return (true);
}
Example #19
0
int
main (int argc, char** argv)
{
  std::string filename = argv[1];
  std::cout << "Reading " << filename << std::endl;

  pcl::PointCloud<pcl::PointXYZ>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZ>);

  if (pcl::io::loadPCDFile<pcl::PointXYZ> (filename, *cloud) == -1) // load the file
  {
    PCL_ERROR ("Couldn't read file");
    return -1;
  }

  std::cout << "points: " << cloud->points.size () << std::endl;

  // Create the normal estimation class, and pass the input dataset to it
  pcl::NormalEstimation<pcl::PointXYZ, pcl::Normal> normal_estimation;
  normal_estimation.setInputCloud (cloud);

  // Create an empty kdtree representation, and pass it to the normal estimation object.
  // Its content will be filled inside the object, based on the given input dataset (as no other search surface is given).
  pcl::search::KdTree<pcl::PointXYZ>::Ptr tree (new pcl::search::KdTree<pcl::PointXYZ>);
  normal_estimation.setSearchMethod (tree);

  // Output datasets
  pcl::PointCloud<pcl::Normal>::Ptr cloud_normals (new pcl::PointCloud<pcl::Normal>);

  // Use all neighbors in a sphere of radius 3cm
  normal_estimation.setRadiusSearch (0.03);

  // Compute the features
  normal_estimation.compute (*cloud_normals);

  // cloud_normals->points.size () should have the same size as the input cloud->points.size ()
  std::cout << "cloud_normals->points.size (): " << cloud_normals->points.size () << std::endl;
  return 0;
}
Example #20
0
void Normals::computeNormalsXYZ() {
    LOG(LTRACE) << "Normals::computeNormalsXYZ";
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud = in_cloud_xyz.read();
    pcl::PointCloud<pcl::PointXYZ>::Ptr copy(new pcl::PointCloud<pcl::PointXYZ>());

    // Remove NaNs.
    std::vector<int> indicesNANs;
    cloud->is_dense = false;
    pcl::removeNaNFromPointCloud(*cloud, *copy, indicesNANs);


    // compute centroid

//	Eigen::Vector4f centroid;
//	pcl::compute3DCentroid(*copy,centroid);

    // compute normals for centroid as viewpoint

    pcl::NormalEstimation<pcl::PointXYZ, pcl::Normal> normalEstimation;
    normalEstimation.setInputCloud (copy);
    pcl::search::KdTree<pcl::PointXYZ>::Ptr tree (new pcl::search::KdTree<pcl::PointXYZ> ());
    normalEstimation.setSearchMethod (tree);

    pcl::PointCloud<pcl::Normal>::Ptr cloud_normals (new pcl::PointCloud<pcl::Normal>);
    normalEstimation.setRadiusSearch (radius);
//	  normalEstimation.setViewPoint(centroid[0], centroid[1], centroid[2]);
    normalEstimation.compute (*cloud_normals);


//	  pcl::PointCloud<pcl::PointXYZINormal>::Ptr cloud_xyz_normals (new pcl::PointCloud<pcl::PointXYZINormal>);
//	  pcl::copyPointCloud(*copy, *cloud_xyz_normals);
//	  pcl::copyPointCloud(*cloud_normals, *cloud_xyz_normals);
//
    //  out_cloud_xyz_normals.write(cloud_xyz_normals);
    out_cloud_normals.write(cloud_normals);
}
int 
main (int argc, char** argv)
{
    pcl::PointCloud<pcl::PointXYZRGBA>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZRGBA>);
    pcl::io::loadPCDFile (argv[1], *cloud);
    
    pcl::NormalEstimation<pcl::PointXYZRGBA, pcl::Normal> ne;
    ne.setInputCloud (cloud);

    cv::Mat input_cloud; 
    input_cloud = cv::Mat(480, 640, CV_8UC3); 

    if (!cloud->empty()) {

	for (int h=0; h<cloud->height; h++) {
	    for (int w=0; w<cloud->width; w++) {
	        pcl::PointXYZRGBA point = cloud->at(w, h);

	        Eigen::Vector3i rgb = point.getRGBVector3i();

		int x_pos = 320 +  point.x/point.z  *480;
		int y_pos = 240 +  point.y/point.z * 480;

		//std::cout << "x pos" << x_pos << "y pos" << y_pos << std::endl;

		if( x_pos > 0 and x_pos < 640 and y_pos > 0 and y_pos < 480){	
			input_cloud.at<cv::Vec3b>(y_pos,x_pos)[0] = rgb[2];
			input_cloud.at<cv::Vec3b>(y_pos,x_pos)[1] = rgb[1];
			input_cloud.at<cv::Vec3b>(y_pos,x_pos)[2] = rgb[0];

			}

	    }
	}
    }

    std::cout << " saving input image " << std::endl;
    cv::imwrite( "image_no_pespective_correction.png", input_cloud );

    // Create an empty kdtree representation, and pass it to the normal estimation object.
    // Its content will be filled inside the object, based on the given input dataset (as no other search surface is given).
    pcl::search::KdTree<pcl::PointXYZRGBA>::Ptr tree (new pcl::search::KdTree<pcl::PointXYZRGBA> ());
    ne.setSearchMethod (tree);

    // Output datasets
    pcl::PointCloud<pcl::Normal>::Ptr cloud_normals (new pcl::PointCloud<pcl::Normal>);

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

    std::cout << " starting computation " << std::endl;

    // Compute the features
    ne.compute (*cloud_normals);

    std::cout << "cloud_normals->points.size (): " << cloud_normals->points.size () << std::endl;


    pcl::Normal normal_point = cloud_normals->at(320, 240);
    pcl::PointXYZRGBA _point = cloud->at(320, 240);

    std::cout << "cloud_normal at point: " << normal_point << std::endl;
    std::cout << "z of cloud at point : " << _point.z << std::endl;


    Eigen::Vector3f z_axis(normal_point.normal_x,normal_point.normal_y,normal_point.normal_z);

    Eigen::Vector3f x_axis_standard(1,0,0);

    Eigen::Vector3f x_proj = x_axis_standard - x_axis_standard.dot(z_axis)*z_axis;

    Eigen::Affine3f translate_z;
    Eigen::Affine3f transformation;

    Eigen::Vector3f tmp0 = x_proj.normalized();
    Eigen::Vector3f tmp1 = (z_axis.normalized().cross(x_proj.normalized())).normalized();
    Eigen::Vector3f tmp2 = z_axis.normalized();

    translate_z(0,0)=1; translate_z(0,1)=0; translate_z(0,2)=0; translate_z(0,3)=0.0f;
    translate_z(1,0)=0; translate_z(1,1)=1; translate_z(1,2)=0; translate_z(1,3)=0.0f;
    translate_z(2,0)=0; translate_z(2,1)=0; translate_z(2,2)=1; translate_z(2,3)=-_point.z;
    translate_z(3,0)=0.0f; translate_z(3,1)=0.0f; translate_z(3,2)=0.0f; translate_z(3,3)=1.0f;


    transformation(0,0)=tmp0[0]; transformation(0,1)=tmp0[1]; transformation(0,2)=tmp0[2]; transformation(0,3)=0.0f;
    transformation(1,0)=tmp1[0]; transformation(1,1)=tmp1[1]; transformation(1,2)=tmp1[2]; transformation(1,3)=0.0f;
    transformation(2,0)=tmp2[0]; transformation(2,1)=tmp2[1]; transformation(2,2)=tmp2[2]; transformation(2,3)=0.0f;
    transformation(3,0)=0.0f; transformation(3,1)=0.0f; transformation(3,2)=0.0f; transformation(3,3)=1.0f;


    pcl::PointCloud<pcl::PointXYZRGBA>::Ptr transformed_cloud1 (new pcl::PointCloud<pcl::PointXYZRGBA>);
    // You can either apply transform_1 or transform_2; they are the same
    pcl::transformPointCloud (*cloud, *transformed_cloud1, translate_z);


    pcl::PointCloud<pcl::PointXYZRGBA>::Ptr transformed_cloud2 (new pcl::PointCloud<pcl::PointXYZRGBA>);
    // You can either apply transform_1 or transform_2; they are the same
    pcl::transformPointCloud (*transformed_cloud1, *transformed_cloud2, transformation);


    translate_z(2,3)=_point.z;

    pcl::PointCloud<pcl::PointXYZRGBA>::Ptr transformed_cloud3 (new pcl::PointCloud<pcl::PointXYZRGBA>);
    // You can either apply transform_1 or transform_2; they are the same
    pcl::transformPointCloud (*transformed_cloud2, *transformed_cloud3, translate_z);

    _point = transformed_cloud3->at(320, 240);

    std::cout << "cloud at point: " << _point << std::endl;


    cv::Mat output_cloud; 
    output_cloud = cv::Mat(480, 640, CV_8UC3, cv::Scalar(0,0,255) ); 

    cv::Mat distance;
    distance = cv::Mat(480, 640, CV_32FC1, -1.2); //::zeros
    
    std::cout << "depth " << distance.at<float>(0,0) << std::endl;


    if (!transformed_cloud3->empty())
        {
        for (int h=0; h<transformed_cloud3->height; h++)
            {
             for (int w=0; w<transformed_cloud3->width; w++)
               {
                    pcl::PointXYZRGBA point = transformed_cloud3->at(w, h);

                    Eigen::Vector3i rgb = point.getRGBVector3i();

                    int x_pos = 320 -  point.x/point.z * 480;
                    int y_pos = 240 +  point.y/point.z * 480;

                    if( x_pos > 0 and x_pos < 640 and y_pos > 0 and y_pos < 480)
                     {

                       if( point.z > distance.at<float>(y_pos,x_pos) and point.z < -0.8 )
                        {


                        output_cloud.at<cv::Vec3b>(y_pos,x_pos)[0] = rgb[2];
                        output_cloud.at<cv::Vec3b>(y_pos,x_pos)[1] = rgb[1];
                        output_cloud.at<cv::Vec3b>(y_pos,x_pos)[2] = rgb[0];

                        distance.at<float>(y_pos,x_pos) = point.z;
                        }
                     }
                 }
             }
        }




    std::cout << " saving output image " << std::endl;
    cv::imwrite( "transformed_image_no_interpolation.png", output_cloud );

    //cv::Mat input_cloud;
    input_cloud = cv::Mat(480, 640, CV_8UC3);

    for (int h=0; h< output_cloud.rows ; h++)
       {
        for (int w=0; w<  output_cloud.cols ; w++)
            {

            cv::Vec3b color = output_cloud.at<cv::Vec3b>(cv::Point(w,h));

            if( !( (int)output_cloud.at<cv::Vec3b>(h, w)[0] == 0 and (int)output_cloud.at<cv::Vec3b>(h, w)[1] == 0 and (int)output_cloud.at<cv::Vec3b>(h, w)[2] == 255)  )
                {
                input_cloud.at<cv::Vec3b>(h, w)[0] = output_cloud.at<cv::Vec3b>(h, w)[0];
                input_cloud.at<cv::Vec3b>(h, w)[1] = output_cloud.at<cv::Vec3b>(h, w)[1];
                input_cloud.at<cv::Vec3b>(h, w)[2] = output_cloud.at<cv::Vec3b>(h, w)[2];

                }
            else
                {
            //	std::cout << " oh god" << std::endl;
                int left_pos = - 1;
                int right_pos =  1;

                while( left_pos + w > 0
                and ( (int)output_cloud.at<cv::Vec3b>(h, left_pos + w)[0] == 0 and (int)output_cloud.at<cv::Vec3b>(h, left_pos + w)[1] == 0 and (int)output_cloud.at<cv::Vec3b>(h, left_pos + w)[2] == 255) )
                    {
                    //std::cout << "ha" << std::endl;
                    left_pos--;
                    }

                while( right_pos + w < 640 -1
                and ( (int)output_cloud.at<cv::Vec3b>(h, right_pos + w)[0] == 0 and (int)output_cloud.at<cv::Vec3b>(h, right_pos + w)[1] == 0 and (int)output_cloud.at<cv::Vec3b>(h, right_pos + w)[2] == 255) )
                    {
                    //std::cout << "ha" << std::endl;
                    right_pos++;
                    }



                if( left_pos  + w >= 0 and right_pos  + w < 640)
                    {
                    if( !( (int)output_cloud.at<cv::Vec3b>(h, left_pos + w)[0] == 0 and (int)output_cloud.at<cv::Vec3b>(h, left_pos + w)[1] == 0 and (int)output_cloud.at<cv::Vec3b>(h, left_pos + w)[2] == 255)
                    and  !( (int)output_cloud.at<cv::Vec3b>(h, right_pos + w)[0] == 0 and (int)output_cloud.at<cv::Vec3b>(h, right_pos + w)[1] == 0 and (int)output_cloud.at<cv::Vec3b>(h, right_pos + w)[2] == 255) )
                        {
                        float left_right_weight = -left_pos/right_pos;
                        int pixel_color = (int) output_cloud.at<cv::Vec3b>(h, left_pos + w)[0]/2 + output_cloud.at<cv::Vec3b>(h, right_pos + w)[0]/2 ;

                        input_cloud.at<cv::Vec3b>(h, w)[0] = pixel_color;
                        input_cloud.at<cv::Vec3b>(h, w)[1] = pixel_color;
                        input_cloud.at<cv::Vec3b>(h, w)[2] = pixel_color;
                        }
                    else
                        {
                        input_cloud.at<cv::Vec3b>(h, w)[0] = 255;
                        input_cloud.at<cv::Vec3b>(h, w)[1] = 0;
                        input_cloud.at<cv::Vec3b>(h, w)[2] = 0;
                         }
                    }
                }
            }
        }


    std::cout << " saving output image " << std::endl;
    cv::imwrite( "transformed_image_perspective.png", input_cloud );

    return 0;
}
Example #22
0
     void cloud_cb_ (const pcl::PointCloud<pcl::PointXYZRGBA>::ConstPtr &cloud)
     {
		PCProc<pcl::PointXYZRGBA> pc1;
	
		pcl::PointCloud<pcl::PointXYZRGBA>::Ptr cloud_filtered (new pcl::PointCloud<pcl::PointXYZRGBA>);
		pcl::PointCloud<pcl::PointXYZRGBA>::Ptr output1 (new pcl::PointCloud<pcl::PointXYZRGBA>);
		


		
		
		
		
		if(bVoxelGrid)
		{
			pcl::PointCloud<pcl::PointXYZRGBA>::ConstPtr inputc = cloud;//.makeShared();
			pc1.downSampling(inputc,output1 , leafsz,leafsz,leafsz);

		}
		else
		{
			output1 = cloud->makeShared();
		}

		///////////////////////////////////////
		// passthrough

		pcl::PointCloud<pcl::PointXYZRGBA>::Ptr output2 (new pcl::PointCloud<pcl::PointXYZRGBA>);

		pc1.PassThroughZ(output1, output2, 1, 3);
		cloud_filtered = output2;





		
		///////////////////////////////////////
		// normal display

		
		pcl::NormalEstimation<pcl::PointXYZRGBA, pcl::Normal> ne;
		ne.setInputCloud (output2);


		// Create an empty kdtree representation, and pass it to the normal estimation object.
		// Its content will be filled inside the object, based on the given input dataset (as no other search surface is given).
		pcl::search::KdTree<pcl::PointXYZRGBA>::Ptr tree (new pcl::search::KdTree<pcl::PointXYZRGBA> ());
		ne.setSearchMethod (tree);

		// Output datasets
		pcl::PointCloud<pcl::Normal>::Ptr cloud_normals (new pcl::PointCloud<pcl::Normal>);

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

		// Compute the features
		ne.compute (*cloud_normals);

	
		
		//viewer.addPointCloudNormals<pcl::PointXYZ,pcl::Normal>(cloud, cloud_normals,  1, 0.01, "normals1", 0);




		int nf = cloud_filtered->size();

		int n = cloud->size();
		lpMapping[0] = n;
		lpMapping[1] = nf;

		lpMapping[2] = bVoxelGrid;
		lpMapping[3] = leafsz;

;


		int i;

		for(i=0; i<nf; i++)//DATA_LEN/6
		{
			float x = cloud_filtered->points[i].x;
			lpMapping[HEADER_LEN + 6*i +0] = cloud_filtered->points[i].x;
			lpMapping[HEADER_LEN + 6*i +1] = cloud_filtered->points[i].y;
			lpMapping[HEADER_LEN + 6*i +2] = cloud_filtered->points[i].z;

			lpMapping[HEADER_LEN + 6*i +3] = cloud_filtered->points[i].r;
			lpMapping[HEADER_LEN + 6*i +4] = cloud_filtered->points[i].g;
			lpMapping[HEADER_LEN + 6*i +5] = cloud_filtered->points[i].b;


		}

		//viewer.addPointCloud<pcl::PointXYZ> (cloud,  "sample cloud");

       if (!viewer.wasStopped())
         {
			 
			 viewer.showCloud (cloud_filtered);
			 
	   }
     }
void callback(const sensor_msgs::PointCloud2ConstPtr& cloud)
{
  ros::Time whole_start = ros::Time::now();

  ros::Time declare_types_start = ros::Time::now();

  // filter
  pcl::VoxelGrid<sensor_msgs::PointCloud2> voxel_grid;
  pcl::PassThrough<sensor_msgs::PointCloud2> pass;
  pcl::ExtractIndices<pcl::PointXYZ> extract_indices;
  pcl::ExtractIndices<pcl::Normal> extract_normals;

  // Normal estimation
  pcl::NormalEstimation<pcl::PointXYZ, pcl::Normal> normal_estimation;
  pcl::SACSegmentationFromNormals<pcl::PointXYZ, pcl::Normal> segmentation_from_normals;

  // Create the segmentation object
  pcl::SACSegmentation<pcl::PointXYZ> seg;

  pcl::search::KdTree<pcl::PointXYZ>::Ptr tree (new pcl::search::KdTree<pcl::PointXYZ> ());
  pcl::search::KdTree<pcl::PointXYZ>::Ptr tree2 (new pcl::search::KdTree<pcl::PointXYZ> ());
  pcl::search::KdTree<pcl::PointXYZ>::Ptr tree3 (new pcl::search::KdTree<pcl::PointXYZ> ());

  // The plane and sphere coefficients
  pcl::ModelCoefficients::Ptr coefficients (new pcl::ModelCoefficients ());
  pcl::ModelCoefficients::Ptr coefficients_plane (new pcl::ModelCoefficients ());
  pcl::ModelCoefficients::Ptr coefficients_cylinder (new pcl::ModelCoefficients ());
  pcl::ModelCoefficients::Ptr coefficients_sphere (new pcl::ModelCoefficients ());

  // The plane and sphere inliers
  pcl::PointIndices::Ptr inliers (new pcl::PointIndices ());
  pcl::PointIndices::Ptr inliers_plane (new pcl::PointIndices ());
  pcl::PointIndices::Ptr inliers_cylinder (new pcl::PointIndices ());
  pcl::PointIndices::Ptr inliers_sphere (new pcl::PointIndices ());

  // The point clouds
  sensor_msgs::PointCloud2::Ptr voxelgrid_filtered (new sensor_msgs::PointCloud2);
  sensor_msgs::PointCloud2::Ptr plane_output_cloud (new sensor_msgs::PointCloud2);
  sensor_msgs::PointCloud2::Ptr rest_output_cloud (new sensor_msgs::PointCloud2);
  sensor_msgs::PointCloud2::Ptr rest_cloud_filtered (new sensor_msgs::PointCloud2);
  sensor_msgs::PointCloud2::Ptr cylinder_output_cloud (new sensor_msgs::PointCloud2);
  sensor_msgs::PointCloud2::Ptr sphere_output_cloud (new sensor_msgs::PointCloud2);


  // The PointCloud
  pcl::PointCloud<pcl::PointXYZ>::Ptr transformed_cloud (new pcl::PointCloud<pcl::PointXYZ>);
  pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_plane (new pcl::PointCloud<pcl::PointXYZ>);
  pcl::PointCloud<pcl::PointXYZ>::Ptr remove_transformed_cloud (new pcl::PointCloud<pcl::PointXYZ>);
  pcl::PointCloud<pcl::PointXYZ>::Ptr cylinder_cloud (new pcl::PointCloud<pcl::PointXYZ>);
  pcl::PointCloud<pcl::PointXYZ>::Ptr cylinder_output (new pcl::PointCloud<pcl::PointXYZ>);
  pcl::PointCloud<pcl::PointXYZ>::Ptr sphere_cloud (new pcl::PointCloud<pcl::PointXYZ>);
  pcl::PointCloud<pcl::PointXYZ>::Ptr sphere_output (new pcl::PointCloud<pcl::PointXYZ>);

  // The cloud normals
  pcl::PointCloud<pcl::Normal>::Ptr cloud_normals (new pcl::PointCloud<pcl::Normal> ());        // for plane
  pcl::PointCloud<pcl::Normal>::Ptr cloud_normals2 (new pcl::PointCloud<pcl::Normal> ());       // for cylinder
  pcl::PointCloud<pcl::Normal>::Ptr cloud_normals3 (new pcl::PointCloud<pcl::Normal> ());       // for sphere


  ros::Time declare_types_end = ros::Time::now();

  //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  //
  //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


  //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  /*
   * Voxel grid Filtering
   */
  //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

//  // Create VoxelGrid filtering
//  voxel_grid.setInputCloud (cloud);
//  voxel_grid.setLeafSize (0.01, 0.01, 0.01);
//  voxel_grid.filter (*voxelgrid_filtered);
//
//  // Convert the sensor_msgs/PointCloud2 data to pcl/PointCloud
//  pcl::fromROSMsg (*voxelgrid_filtered, *transformed_cloud);

  //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

  //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  /*
   * Passthrough Filtering
   */
  //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

//  pass through filter
//  pass.setInputCloud (cloud);
//  pass.setFilterFieldName ("z");
//  pass.setFilterLimits (0, 1.5);
//  pass.filter (*cloud_filtered);
//
//  // Convert the sensor_msgs/PointCloud2 data to pcl/PointCloud
//  pcl::fromROSMsg (*cloud_filtered, *transformed_cloud);


  //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  /*
   * Estimate point normals
   */
  //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

//  ros::Time estimate_start = ros::Time::now();
//
//  // Convert the sensor_msgs/PointCloud2 data to pcl/PointCloud
//  pcl::fromROSMsg (*cloud, *transformed_cloud);
//
//  // Estimate point normals
//  normal_estimation.setSearchMethod (tree);
//  normal_estimation.setInputCloud (transformed_cloud);
//  normal_estimation.setKSearch (50);
//  normal_estimation.compute (*cloud_normals);
//
//  ros::Time estimate_end = ros::Time::now();


  //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  /*
   * Create and processing the plane extraction
   */
  //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

//  ros::Time plane_start = ros::Time::now();
//
//  // Create the segmentation object for the planar model and set all the parameters
//  segmentation_from_normals.setOptimizeCoefficients (true);
//  segmentation_from_normals.setModelType (pcl::SACMODEL_NORMAL_PLANE);
//  segmentation_from_normals.setNormalDistanceWeight (0.1);
//  segmentation_from_normals.setMethodType (pcl::SAC_RANSAC);
//  segmentation_from_normals.setMaxIterations (100);
//  segmentation_from_normals.setDistanceThreshold (0.03);
//  segmentation_from_normals.setInputCloud (transformed_cloud);
//  segmentation_from_normals.setInputNormals (cloud_normals);
//
//  // Obtain the plane inliers and coefficients
//  segmentation_from_normals.segment (*inliers_plane, *coefficients_plane);
//  //std::cerr << "Plane coefficients: " << *coefficients_plane << std::endl;
//
//  // Extract the planar inliers from the input cloud
//  extract_indices.setInputCloud (transformed_cloud);
//  extract_indices.setIndices (inliers_plane);
//  extract_indices.setNegative (false);
//  extract_indices.filter (*cloud_plane);
//
//  pcl::toROSMsg (*cloud_plane, *plane_output_cloud);
//  plane_pub.publish(plane_output_cloud);
//
//  ros::Time plane_end = ros::Time::now();

  //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

  ros::Time plane_start = ros::Time::now();

  pcl::fromROSMsg (*cloud, *transformed_cloud);

  seg.setOptimizeCoefficients (true);
  seg.setModelType (pcl::SACMODEL_PLANE);
  seg.setMethodType (pcl::SAC_RANSAC);
  seg.setMaxIterations (1000);
  seg.setDistanceThreshold (0.01);
  seg.setInputCloud (transformed_cloud);
  seg.segment (*inliers_plane, *coefficients_plane);

  extract_indices.setInputCloud(transformed_cloud);
  extract_indices.setIndices(inliers_plane);
  extract_indices.setNegative(false);
  extract_indices.filter(*cloud_plane);

  pcl::toROSMsg (*cloud_plane, *plane_output_cloud);
  plane_pub.publish(plane_output_cloud);
  ros::Time plane_end = ros::Time::now();


  //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  /*
   * Extract rest plane and passthrough filtering
   */
  //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

  ros::Time rest_pass_start = ros::Time::now();

  // Create the filtering object
  // Remove the planar inliers, extract the rest
  extract_indices.setNegative (true);
  extract_indices.filter (*remove_transformed_cloud);
  transformed_cloud.swap (remove_transformed_cloud);

  // publish result of Removal the planar inliers, extract the rest
  pcl::toROSMsg (*transformed_cloud, *rest_output_cloud);
  rest_pub.publish(rest_output_cloud);

  // Convert the sensor_msgs/PointCloud2 data to pcl/PointCloud
//  pcl::fromROSMsg (*rest_output_cloud, *cylinder_cloud);

  // pass through filter
  pass.setInputCloud (rest_output_cloud);
  pass.setFilterFieldName ("z");
  pass.setFilterLimits (0, 2.5);
  pass.filter (*rest_cloud_filtered);

  ros::Time rest_pass_end = ros::Time::now();

  //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////



  //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  /*
   * for cylinder features
   */
  //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

  /*
  // Convert the sensor_msgs/PointCloud2 data to pcl/PointCloud
  pcl::fromROSMsg (*rest_cloud_filtered, *cylinder_cloud);

  // Estimate point normals
  normal_estimation.setSearchMethod (tree2);
  normal_estimation.setInputCloud (cylinder_cloud);
  normal_estimation.setKSearch (50);
  normal_estimation.compute (*cloud_normals2);

  // Create the segmentation object for sphere segmentation and set all the paopennirameters
  segmentation_from_normals.setOptimizeCoefficients (true);
  segmentation_from_normals.setModelType (pcl::SACMODEL_CYLINDER);
  segmentation_from_normals.setMethodType (pcl::SAC_RANSAC);
  segmentation_from_normals.setNormalDistanceWeight (0.1);
  segmentation_from_normals.setMaxIterations (10000);
  segmentation_from_normals.setDistanceThreshold (0.05);
  segmentation_from_normals.setRadiusLimits (0, 0.5);
  segmentation_from_normals.setInputCloud (cylinder_cloud);
  segmentation_from_normals.setInputNormals (cloud_normals2);

  // Obtain the sphere inliers and coefficients
  segmentation_from_normals.segment (*inliers_cylinder, *coefficients_cylinder);
  //std::cerr << "Cylinder coefficients: " << *coefficients_cylinder << std::endl;

  // Publish the sphere cloud
  extract_indices.setInputCloud (cylinder_cloud);
  extract_indices.setIndices (inliers_cylinder);
  extract_indices.setNegative (false);
  extract_indices.filter (*cylinder_output);

  if (cylinder_output->points.empty ())
     std::cerr << "Can't find the cylindrical component." << std::endl;

  pcl::toROSMsg (*cylinder_output, *cylinder_output_cloud);
  cylinder_pub.publish(cylinder_output_cloud);
  */

  //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  /*
   * for sphere features
   */
  //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


  ros::Time sphere_start = ros::Time::now();

  // Convert the sensor_msgs/PointCloud2 data to pcl/PointCloud
  pcl::fromROSMsg (*rest_cloud_filtered, *sphere_cloud);

  // Estimate point normals
  normal_estimation.setSearchMethod (tree3);
  normal_estimation.setInputCloud (sphere_cloud);
  normal_estimation.setKSearch (50);
  normal_estimation.compute (*cloud_normals3);

  // Create the segmentation object for sphere segmentation and set all the paopennirameters
  segmentation_from_normals.setOptimizeCoefficients (true);
  //segmentation_from_normals.setModelType (pcl::SACMODEL_SPHERE);
  segmentation_from_normals.setModelType (pcl::SACMODEL_SPHERE);
  segmentation_from_normals.setMethodType (pcl::SAC_RANSAC);
  segmentation_from_normals.setNormalDistanceWeight (0.1);
  segmentation_from_normals.setMaxIterations (10000);
  segmentation_from_normals.setDistanceThreshold (0.05);
  segmentation_from_normals.setRadiusLimits (0, 0.2);
  segmentation_from_normals.setInputCloud (sphere_cloud);
  segmentation_from_normals.setInputNormals (cloud_normals3);

  // Obtain the sphere inliers and coefficients
  segmentation_from_normals.segment (*inliers_sphere, *coefficients_sphere);
  //std::cerr << "Sphere coefficients: " << *coefficients_sphere << std::endl;

  // Publish the sphere cloud
  extract_indices.setInputCloud (sphere_cloud);
  extract_indices.setIndices (inliers_sphere);
  extract_indices.setNegative (false);
  extract_indices.filter (*sphere_output);

  if (sphere_output->points.empty ())
     std::cerr << "Can't find the sphere component." << std::endl;

  pcl::toROSMsg (*sphere_output, *sphere_output_cloud);
  sphere_pub.publish(sphere_output_cloud);

  ros::Time sphere_end = ros::Time::now();

  std::cout << "cloud size : " << cloud->width * cloud->height << std::endl;
  std::cout << "plane size : " << transformed_cloud->width * transformed_cloud->height << std::endl;
  //std::cout << "plane size : " << cloud_normals->width * cloud_normals->height << std::endl;
  //std::cout << "cylinder size : " << cloud_normals2->width * cloud_normals2->height << std::endl;
  std::cout << "sphere size : " << cloud_normals3->width * cloud_normals3->height << std::endl;

  ros::Time whole_now = ros::Time::now();

  printf("\n");

  std::cout << "whole time         : " << whole_now - whole_start << " sec" << std::endl;
  std::cout << "declare types time : " << declare_types_end - declare_types_start << " sec" << std::endl;
  //std::cout << "estimate time      : " << estimate_end - estimate_start << " sec" << std::endl;
  std::cout << "plane time         : " << plane_end - plane_start << " sec" << std::endl;
  std::cout << "rest and pass time : " << rest_pass_end - rest_pass_start << " sec" << std::endl;
  std::cout << "sphere time        : " << sphere_end - sphere_start << " sec" << std::endl;

  printf("\n");
}
  bool SnapIt::processModelCylinder(jsk_pcl_ros::CallSnapIt::Request& req,
                                    jsk_pcl_ros::CallSnapIt::Response& res) {
    pcl::PointCloud<pcl::PointXYZ>::Ptr candidate_points (new pcl::PointCloud<pcl::PointXYZ>);
    pcl::PointIndices::Ptr inliers(new pcl::PointIndices);
    Eigen::Vector3f n, C_orig;
    if (!extractPointsInsideCylinder(req.request.center,
                                     req.request.direction,
                                     req.request.radius,
                                     req.request.height,
                                     inliers, n, C_orig,
                                     1.3)) {
      return false;
    }
    if (inliers->indices.size() < 3) {
      NODELET_ERROR("not enough points inside of the target_plane");
      return false;
    }
    
    geometry_msgs::PointStamped centroid;
    centroid.point.x = C_orig[0];
    centroid.point.y = C_orig[1];
    centroid.point.z = C_orig[2];
    centroid.header = req.request.header;
    
    
    pcl::ExtractIndices<pcl::PointXYZ> extract;
    extract.setInputCloud(input_);
    extract.setIndices(inliers);
    extract.filter(*candidate_points);
    
    publishPointCloud(debug_candidate_points_pub_, candidate_points);


    // first, to remove plane we estimate the plane
    pcl::ModelCoefficients::Ptr plane_coefficients (new pcl::ModelCoefficients);
    pcl::PointIndices::Ptr plane_inliers (new pcl::PointIndices);
    extractPlanePoints(candidate_points, plane_inliers, plane_coefficients,
                       n, req.request.eps_angle);
    if (plane_inliers->indices.size() == 0) {
      NODELET_ERROR ("plane estimation failed");
      return false;
    }

    // remove the points blonging to the plane
    pcl::PointCloud<pcl::PointXYZ>::Ptr points_inside_pole_wo_plane (new pcl::PointCloud<pcl::PointXYZ>);
    extract.setInputCloud (candidate_points);
    extract.setIndices (plane_inliers);
    extract.setNegative (true);
    extract.filter (*points_inside_pole_wo_plane);

    publishPointCloud(debug_candidate_points_pub2_, points_inside_pole_wo_plane);
    
    // normal estimation
    pcl::PointCloud<pcl::Normal>::Ptr cloud_normals (new pcl::PointCloud<pcl::Normal>);
    pcl::NormalEstimation<pcl::PointXYZ, pcl::Normal> ne;
    pcl::search::KdTree<pcl::PointXYZ>::Ptr tree (new pcl::search::KdTree<pcl::PointXYZ> ());
    ne.setSearchMethod (tree);
    ne.setInputCloud (points_inside_pole_wo_plane);
    ne.setKSearch (50);
    ne.compute (*cloud_normals);
    
    
    // segmentation
    pcl::ModelCoefficients::Ptr cylinder_coefficients (new pcl::ModelCoefficients);
    pcl::PointIndices::Ptr cylinder_inliers (new pcl::PointIndices);
    // Create the segmentation object
    pcl::SACSegmentationFromNormals<pcl::PointXYZ, pcl::Normal> seg;
    // Optional
    seg.setOptimizeCoefficients (true);
    // Mandatory
    seg.setModelType (pcl::SACMODEL_CYLINDER);
    seg.setMethodType (pcl::SAC_RANSAC);
    seg.setRadiusLimits (0.01, req.request.radius * 1.2);
    seg.setDistanceThreshold (0.05);
    
    seg.setInputCloud(points_inside_pole_wo_plane);
    seg.setInputNormals (cloud_normals);
    seg.setMaxIterations (10000);
    seg.setNormalDistanceWeight (0.1);
    seg.setAxis(n);
    if (req.request.eps_angle != 0.0) {
      seg.setEpsAngle(req.request.eps_angle);
    }
    else {
      seg.setEpsAngle(0.35);
    }
    seg.segment (*cylinder_inliers, *cylinder_coefficients);
    if (cylinder_inliers->indices.size () == 0)
    {
      NODELET_ERROR ("Could not estimate a cylinder model for the given dataset.");
      return false;
    }

    debug_centroid_pub_.publish(centroid);
    
    pcl::PointCloud<pcl::PointXYZ>::Ptr cylinder_points (new pcl::PointCloud<pcl::PointXYZ>);
    extract.setInputCloud (points_inside_pole_wo_plane);
    extract.setIndices (cylinder_inliers);
    extract.setNegative (false);
    extract.filter (*cylinder_points);

    publishPointCloud(debug_candidate_points_pub3_, cylinder_points);

    Eigen::Vector3f n_prime;
    Eigen::Vector3f C_new;
    for (size_t i = 0; i < 3; i++) {
      C_new[i] = cylinder_coefficients->values[i];
      n_prime[i] = cylinder_coefficients->values[i + 3];
    }

    double radius = fabs(cylinder_coefficients->values[6]);
    // inorder to compute centroid, we project all the points to the center line.
    // and after that, get the minimum and maximum points in the coordinate system of the center line
    double min_alpha = DBL_MAX;
    double max_alpha = -DBL_MAX;
    for (size_t i = 0; i < cylinder_points->points.size(); i++ ) {
      pcl::PointXYZ q = cylinder_points->points[i];
      double alpha = (q.getVector3fMap() - C_new).dot(n_prime);
      if (alpha < min_alpha) {
        min_alpha = alpha;
      }
      if (alpha > max_alpha) {
        max_alpha = alpha;
      }
    }
    // the center of cylinder
    Eigen::Vector3f C_new_prime = C_new + (max_alpha + min_alpha) / 2.0 * n_prime;
    
    Eigen::Vector3f n_cross = n.cross(n_prime);
    if (n.dot(n_prime)) {
      n_cross = - n_cross;
    }
    double theta = asin(n_cross.norm());
    Eigen::Quaternionf trans (Eigen::AngleAxisf(theta, n_cross.normalized()));
    Eigen::Vector3f C = trans * C_orig;
    Eigen::Affine3f A = Eigen::Translation3f(C) * Eigen::Translation3f(C_new_prime - C) * trans * Eigen::Translation3f(C_orig).inverse();
    tf::poseEigenToMsg((Eigen::Affine3d)A, res.transformation);

    geometry_msgs::PointStamped centroid_transformed;
    centroid_transformed.point.x = C_new_prime[0];
    centroid_transformed.point.y = C_new_prime[1];
    centroid_transformed.point.z = C_new_prime[2];
    centroid_transformed.header = req.request.header;
    debug_centroid_after_trans_pub_.publish(centroid_transformed);

    // publish marker
    visualization_msgs::Marker marker;
    marker.type = visualization_msgs::Marker::CYLINDER;
    marker.scale.x = radius;
    marker.scale.y = radius;
    marker.scale.z = (max_alpha - min_alpha);
    marker.pose.position.x = C_new_prime[0];
    marker.pose.position.y = C_new_prime[1];
    marker.pose.position.z = C_new_prime[2];

    // n_prime -> z
    // n_cross.normalized() -> x
    Eigen::Vector3f z_axis = n_prime.normalized();
    Eigen::Vector3f y_axis = n_cross.normalized();
    Eigen::Vector3f x_axis = (y_axis.cross(z_axis)).normalized();
    Eigen::Matrix3f M;
    for (size_t i = 0; i < 3; i++) {
      M(i, 0) = x_axis[i];
      M(i, 1) = y_axis[i];
      M(i, 2) = z_axis[i];
    }
    
    Eigen::Quaternionf q (M);
    marker.pose.orientation.x = q.x();
    marker.pose.orientation.y = q.y();
    marker.pose.orientation.z = q.z();
    marker.pose.orientation.w = q.w();
    marker.color.g = 1.0;
    marker.color.a = 1.0;
    marker.header = input_header_;
    marker_pub_.publish(marker);
    
    return true;
  }
bool cloud_cb(data_collection::process_cloud::Request &req,
	      data_collection::process_cloud::Response &res)
{
  //Segment from cloud:
  //May need to tweak segmentation parameters to get just the cluster I'm looking for.
  std::vector<pcl::PointCloud<pcl::PointXYZ>::Ptr> clouds;
  nrg_object_recognition::segmentation seg_srv;

  seg_srv.request.scene = req.in_cloud;
  seg_srv.request.min_x = -.75, seg_srv.request.max_x = .4;
  seg_srv.request.min_y = -5, seg_srv.request.max_y = .5;
  seg_srv.request.min_z = 0.0, seg_srv.request.max_z = 1.15;
  seg_client.call(seg_srv);
  
  //SegmentCloud(req.in_cloud, clouds);
  
  //For parameter tweaking, may be good to write all cluseters to file here for examination in pcd viewer.
  
  pcl::PointCloud<pcl::PointXYZ>::Ptr cluster (new pcl::PointCloud<pcl::PointXYZ>);
  //cluster = clouds.at(0);
  pcl::fromROSMsg(seg_srv.response.clusters.at(0), *cluster);
  //std::cout << "found " << clouds.size() << " clusters.\n"; 
  std::cout << "cluster has " << cluster->height*cluster->width << " points.\n";
  
  //Write raw pcd file (objecName_angle.pcd)
  std::stringstream fileName_ss;
  fileName_ss << "data/" << req.objectName << "_" << req.angle << ".pcd";
  std::cout << "writing raw cloud to file...\n";
  std::cout << fileName_ss.str() << std::endl;
  pcl::io::savePCDFile(fileName_ss.str(), *cluster);
  std::cout << "done.\n";
 
  //Write vfh feature to file: 
  pcl::VFHEstimation<pcl::PointXYZ, pcl::Normal, pcl::VFHSignature308> vfh;
  vfh.setInputCloud (cluster);
  //Estimate normals:
  pcl::NormalEstimation<pcl::PointXYZ, pcl::Normal> ne;
  ne.setInputCloud (cluster);
  pcl::search::KdTree<pcl::PointXYZ>::Ptr tree (new pcl::search::KdTree<pcl::PointXYZ> ());
  ne.setSearchMethod (tree);
  pcl::PointCloud<pcl::Normal>::Ptr cloud_normals (new pcl::PointCloud<pcl::Normal>);
  ne.setRadiusSearch (0.03);
  ne.compute (*cloud_normals);
  vfh.setInputNormals (cloud_normals);
  //Estimate vfh:
  vfh.setSearchMethod (tree);
  pcl::PointCloud<pcl::VFHSignature308>::Ptr vfhs (new pcl::PointCloud<pcl::VFHSignature308> ());
  // Compute the feature
  vfh.compute (*vfhs);
  //Write to file: (objectName_angle_vfh.pcd)
  fileName_ss.str("");
  std::cout << "writing vfh descriptor to file...\n";
  fileName_ss << "data/" << req.objectName << "_" << req.angle << "_vfh.pcd";
  pcl::io::savePCDFile(fileName_ss.str(), *vfhs);
  std::cout << "done.\n";

 
  //Extract cph
  std::vector<float> feature;
  CPHEstimation cph(5,72);
  cph.setInputCloud(cluster);
  cph.compute(feature);
  //Write cph to file. (objectName_angle.csv)
  std::ofstream outFile;
  fileName_ss.str("");
  fileName_ss << "data/" << req.objectName << "_" << req.angle << ".csv";
  outFile.open(fileName_ss.str().c_str());
  std::cout << "writing cph descriptor to file...\n";
  for(unsigned int j=0; j<feature.size(); j++){
	outFile << feature.at(j) << " "; 
  }
  outFile.close();
  fileName_ss.str("");
  std::cout << "done.\n";
  res.result = 1;
}
void Segmentation::ransac(std::vector < pcl::PointCloud<pcl::PointXYZRGBA>::Ptr > &clusters, Eigen::Vector3f axis, std::vector < pcl::PointCloud<pcl::PointXYZRGBA>::Ptr > &vectorCloudInliers )
{
    vectorCloudInliers.clear();
    for(unsigned int i = 0; i < clusters.size(); i++)
    {
        pcl::ModelCoefficients::Ptr coeff(new pcl::ModelCoefficients);
        pcl::PointIndices::Ptr indices(new pcl::PointIndices);
        pcl::PointCloud<pcl::PointXYZRGBA>::Ptr cloud_(new pcl::PointCloud<pcl::PointXYZRGBA>);
        //pcl::PointCloud<pcl::PointXYZRGBA>::Ptr hullGround(new pcl::PointCloud<pcl::PointXYZRGBA>);


        pcl::NormalEstimation<pcl::PointXYZRGBA, pcl::Normal> ne;
        pcl::SACSegmentationFromNormals<pcl::PointXYZRGBA, pcl::Normal> seg;
        pcl::search::KdTree<pcl::PointXYZRGBA>::Ptr tree (new pcl::search::KdTree<pcl::PointXYZRGBA> ());
        pcl::PointCloud<pcl::Normal>::Ptr cloud_normals (new pcl::PointCloud<pcl::Normal>);

        // Estimate Normals
        ne.setSearchMethod(tree);
        ne.setInputCloud(clusters[i]);
        ne.setKSearch(50);
        ne.compute(*cloud_normals);

        // Create the segmentation object
        //pcl::SACSegmentation<pcl::PointXYZRGBA> seg;
        // Optional
        seg.setOptimizeCoefficients (true);

        // Mandatory
        //seg.setModelType (pcl::SACMODEL_PERPENDICULAR_PLANE); // We search a plane perpendicular to the y
        seg.setModelType (pcl::SACMODEL_NORMAL_PLANE);// We search a plane perpendicular to the y
        seg.setNormalDistanceWeight(0.005);
        seg.setMethodType (pcl::SAC_RANSAC);

        seg.setDistanceThreshold (0.020); //0.25 / 35

        //seg.setAxis(axis); // Axis Y 0, -1, 0

        seg.setEpsAngle(20.0f * (M_PI/180.0f)); // 50 degrees of error

        pcl::ExtractIndices<pcl::PointXYZRGBA> extract;
        seg.setInputCloud (clusters[i]);
        seg.setInputNormals(cloud_normals);
        seg.segment (*indices, *coeff);
        if(normalDifferenceError(coeff))
        {
            std::cout << "coeff" << coeff->values[0] << "  " << coeff->values[1] << "   " << coeff->values[2] << std::endl;
            if (indices->indices.size () == 0)
            {
                PCL_ERROR ("Could not estimate a planar model (Ground).");
                //return false;
            }
            else
            {
                extract.setInputCloud(clusters[i]);
                extract.setIndices(indices);
                extract.setNegative(false);
                extract.filter(*cloud_);

                vectorCloudInliers.push_back(cloud_);


                //return true;
            }
        }
    }
}
void cloud_callback(const sensor_msgs::PointCloud2ConstPtr& input) {
    ROS_DEBUG("Got new pointcloud.");
    // Convert the sensor_msgs/PointCloud2 data to pcl/PointCloud
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZ>), cloud_f (new pcl::PointCloud<pcl::PointXYZ>);
    std_msgs::Header header = input->header;
    pcl::fromROSMsg(*input, *cloud);
    //all the objects needed
    pcl::PCDReader reader;
    pcl::PassThrough<PointT> pass;
    pcl::NormalEstimation<PointT, pcl::Normal> ne;
    pcl::SACSegmentationFromNormals<PointT, pcl::Normal> seg; 
    pcl::PCDWriter writer;
    pcl::ExtractIndices<PointT> extract;
    pcl::ExtractIndices<pcl::Normal> extract_normals;
    pcl::search::KdTree<PointT>::Ptr tree (new pcl::search::KdTree<PointT> ());
    //data sets
    pcl::PointCloud<PointT>::Ptr cloud_filtered (new pcl::PointCloud<pcl::PointXYZ>);
    pcl::PointCloud<pcl::Normal>::Ptr cloud_normals (new pcl::PointCloud<pcl::Normal>);
    pcl::PointCloud<PointT>::Ptr cloud_filtered2 (new pcl::PointCloud<pcl::PointXYZ>);
    pcl::PointCloud<pcl::Normal>::Ptr cloud_normals2 (new pcl::PointCloud<pcl::Normal>);
    pcl::ModelCoefficients::Ptr coefficients_plane (new pcl::ModelCoefficients), coefficients_sphere (new pcl::ModelCoefficients);
    pcl::PointIndices::Ptr inliers_plane (new pcl::PointIndices), inliers_sphere (new pcl::PointIndices);
    ROS_DEBUG("PointCloud before filtering has: %i data points.", (int)cloud->points.size());
    
    //filter our NaNs
    pass.setInputCloud (cloud);
    pass.setFilterFieldName ("z");
    pass.setFilterLimits (0, 2.0);    
    pass.filter (*cloud_filtered);
    ROS_DEBUG("PointCloud after filtering has: %i data points." , (int)cloud_filtered->points.size());
    
    *cloud_filtered = *cloud;//remove the pass through filter basically
    //estimate normal points
    ne.setSearchMethod (tree);
    ne.setInputCloud (cloud_filtered);
    //ne.setKSearch(10);
    ne.setRadiusSearch(0.025);
    ne.compute (*cloud_normals);

    // Create the segmentation object for the planar model and set all the parameters
    seg.setOptimizeCoefficients (true);
    seg.setModelType (pcl::SACMODEL_NORMAL_PLANE);
    seg.setNormalDistanceWeight (0.05);
    seg.setMethodType (pcl::SAC_RANSAC);
    seg.setMaxIterations (100);
    seg.setDistanceThreshold (5.0);
    seg.setInputCloud (cloud_filtered);
    seg.setInputNormals (cloud_normals);
    // Obtain the plane inliers and coefficients
    seg.segment (*inliers_plane, *coefficients_plane);
    std::cerr << "Plane coefficients: " << *coefficients_plane << std::endl;

    // Extract the planar inliers from the input cloud
    extract.setInputCloud (cloud_filtered);
    extract.setIndices (inliers_plane);
    extract.setNegative (false);
    
    // Remove the planar inliers, extract the rest
    extract.setNegative (true);
    extract.filter (*cloud_filtered2);
    extract_normals.setNegative (true);
    extract_normals.setInputCloud (cloud_normals);
    extract_normals.setIndices (inliers_plane);
    extract_normals.filter (*cloud_normals2);
    
    seg.setOptimizeCoefficients (true);
    seg.setModelType (pcl::SACMODEL_SPHERE);
    seg.setMethodType (pcl::SAC_RANSAC);
    seg.setNormalDistanceWeight (0.1);
    seg.setMaxIterations (100);
    seg.setDistanceThreshold (5.0);
    seg.setRadiusLimits (0, 1.0);
    seg.setInputCloud (cloud_filtered2);
    seg.setInputNormals (cloud_normals2);
    
    extract.setInputCloud (cloud_filtered2);
    extract.setIndices (inliers_sphere);
    extract.setNegative (false);
    pcl::PointCloud<PointT>::Ptr sphere_cloud (new pcl::PointCloud<PointT> ());
    extract.filter(*sphere_cloud);
    
    pcl::PointCloud<pcl::PointXYZ> sphere_cloud_in = *sphere_cloud;
    sensor_msgs::PointCloud2 sphere_cloud_out;
    pcl::toROSMsg(sphere_cloud_in, sphere_cloud_out);
    sphere_cloud_out.header = header;
    buoy_cloud_pub.publish(sphere_cloud_out);

}
  void HintedHandleEstimator::estimate(
    const sensor_msgs::PointCloud2::ConstPtr& cloud_msg,
    const geometry_msgs::PointStampedConstPtr &point_msg)
  {
    boost::mutex::scoped_lock lock(mutex_);
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
    pcl::PointCloud<pcl::Normal>::Ptr cloud_normals(new pcl::PointCloud<pcl::Normal>);
    pcl::PassThrough<pcl::PointXYZ> pass;
    int K = 1;
    std::vector<int> pointIdxNKNSearch(K);
    std::vector<float> pointNKNSquaredDistance(K);
    pcl::search::KdTree<pcl::PointXYZ>::Ptr kd_tree(new pcl::search::KdTree<pcl::PointXYZ>);

    pcl::fromROSMsg(*cloud_msg, *cloud);
    geometry_msgs::PointStamped transed_point;
    ros::Time now = ros::Time::now();
    try
      {
      listener_.waitForTransform(cloud->header.frame_id, point_msg->header.frame_id, now, ros::Duration(1.0));
      listener_.transformPoint(cloud->header.frame_id, now, *point_msg, point_msg->header.frame_id, transed_point);
    }
    catch(tf::TransformException ex)
      {
      JSK_ROS_ERROR("%s", ex.what());
      return;
    }
    pcl::PointXYZ searchPoint;
    searchPoint.x = transed_point.point.x;
    searchPoint.y = transed_point.point.y;
    searchPoint.z = transed_point.point.z;

    //remove too far cloud
    pass.setInputCloud(cloud);
    pass.setFilterFieldName("x");
    pass.setFilterLimits(searchPoint.x - 3*handle.arm_w, searchPoint.x + 3*handle.arm_w);
    pass.filter(*cloud);
    pass.setInputCloud(cloud);
    pass.setFilterFieldName("y");
    pass.setFilterLimits(searchPoint.y - 3*handle.arm_w, searchPoint.y + 3*handle.arm_w);
    pass.filter(*cloud);
    pass.setInputCloud(cloud);
    pass.setFilterFieldName("z");
    pass.setFilterLimits(searchPoint.z - 3*handle.arm_w, searchPoint.z + 3*handle.arm_w);
    pass.filter(*cloud);

    if(cloud->points.size() < 10){
      JSK_ROS_INFO("points are too small");
      return;
    }
    if(1){ //estimate_normal
      pcl::NormalEstimation<pcl::PointXYZ, pcl::Normal> ne;
      ne.setInputCloud(cloud);
      ne.setSearchMethod(kd_tree);
      ne.setRadiusSearch(0.02);
      ne.setViewPoint(0, 0, 0);
      ne.compute(*cloud_normals);
    }
    else{ //use normal of msg
      
    }
    if(! (kd_tree->nearestKSearch (searchPoint, K, pointIdxNKNSearch, pointNKNSquaredDistance) > 0)){
      JSK_ROS_INFO("kdtree failed");
      return;
    }
    float x = cloud->points[pointIdxNKNSearch[0]].x;
    float y = cloud->points[pointIdxNKNSearch[0]].y;
    float z = cloud->points[pointIdxNKNSearch[0]].z;
    float v_x = cloud_normals->points[pointIdxNKNSearch[0]].normal_x;
    float v_y = cloud_normals->points[pointIdxNKNSearch[0]].normal_y;
    float v_z = cloud_normals->points[pointIdxNKNSearch[0]].normal_z;
    double theta = acos(v_x);
    // use normal for estimating handle direction
    tf::Quaternion normal(0, v_z/NORM(0, v_y, v_z) * cos(theta/2), -v_y/NORM(0, v_y, v_z) * cos(theta/2), sin(theta/2));
    tf::Quaternion final_quaternion = normal;
    double min_theta_index = 0;
    double min_width = 100;
    tf::Quaternion min_qua(0, 0, 0, 1);
    visualization_msgs::Marker debug_hand_marker;
    debug_hand_marker.header = cloud_msg->header;
    debug_hand_marker.ns = string("debug_grasp");
    debug_hand_marker.id = 0;
    debug_hand_marker.type = visualization_msgs::Marker::LINE_LIST;
    debug_hand_marker.pose.orientation.w = 1;
    debug_hand_marker.scale.x=0.003;
    tf::Matrix3x3 best_mat;
    //search 180 degree and calc the shortest direction
    for(double theta_=0; theta_<3.14/2; 
        theta_+=3.14/2/30){
      tf::Quaternion rotate_(sin(theta_), 0, 0, cos(theta_));
      tf::Quaternion temp_qua = normal * rotate_;
      tf::Matrix3x3 temp_mat(temp_qua);
      geometry_msgs::Pose pose_respected_to_tf;
      pose_respected_to_tf.position.x = x;
      pose_respected_to_tf.position.y = y;
      pose_respected_to_tf.position.z = z;
      pose_respected_to_tf.orientation.x = temp_qua.getX();
      pose_respected_to_tf.orientation.y = temp_qua.getY();
      pose_respected_to_tf.orientation.z = temp_qua.getZ();
      pose_respected_to_tf.orientation.w = temp_qua.getW();
      Eigen::Affine3d box_pose_respected_to_cloud_eigend;
      tf::poseMsgToEigen(pose_respected_to_tf, box_pose_respected_to_cloud_eigend);
      Eigen::Affine3d box_pose_respected_to_cloud_eigend_inversed
        = box_pose_respected_to_cloud_eigend.inverse();
      Eigen::Matrix4f box_pose_respected_to_cloud_eigen_inversed_matrixf;
      Eigen::Matrix4d box_pose_respected_to_cloud_eigen_inversed_matrixd
        = box_pose_respected_to_cloud_eigend_inversed.matrix();
      jsk_pcl_ros::convertMatrix4<Eigen::Matrix4d, Eigen::Matrix4f>(
                                                                    box_pose_respected_to_cloud_eigen_inversed_matrixd,
                                                                    box_pose_respected_to_cloud_eigen_inversed_matrixf);
      Eigen::Affine3f offset = Eigen::Affine3f(box_pose_respected_to_cloud_eigen_inversed_matrixf);
      pcl::PointCloud<pcl::PointXYZ>::Ptr output_cloud(new pcl::PointCloud<pcl::PointXYZ>);
      pcl::transformPointCloud(*cloud, *output_cloud, offset);

      pcl::PassThrough<pcl::PointXYZ> pass;
      pcl::PointCloud<pcl::PointXYZ>::Ptr points_z(new pcl::PointCloud<pcl::PointXYZ>), points_yz(new pcl::PointCloud<pcl::PointXYZ>), points_xyz(new pcl::PointCloud<pcl::PointXYZ>);
      pass.setInputCloud(output_cloud);
      pass.setFilterFieldName("y");
      pass.setFilterLimits(-handle.arm_w*2, handle.arm_w*2);
      pass.filter(*points_z);
      pass.setInputCloud(points_z);
      pass.setFilterFieldName("z");
      pass.setFilterLimits(-handle.finger_d, handle.finger_d);
      pass.filter(*points_yz);
      pass.setInputCloud(points_yz);
      pass.setFilterFieldName("x");
      pass.setFilterLimits(-(handle.arm_l-handle.finger_l), handle.finger_l);
      pass.filter(*points_xyz);
      pcl::KdTreeFLANN<pcl::PointXYZ> kdtree;
      for(size_t index=0; index<points_xyz->size(); index++){
        points_xyz->points[index].x = points_xyz->points[index].z = 0;
      }
      if(points_xyz->points.size() == 0){JSK_ROS_INFO("points are empty");return;}
      kdtree.setInputCloud(points_xyz);
      std::vector<int> pointIdxRadiusSearch;
      std::vector<float> pointRadiusSquaredDistance;
      pcl::PointXYZ search_point_tree;
      search_point_tree.x=search_point_tree.y=search_point_tree.z=0;
      if( kdtree.radiusSearch(search_point_tree, 10, pointIdxRadiusSearch, pointRadiusSquaredDistance) > 0 ){
        double before_w=10, temp_w;
        for(size_t index = 0; index < pointIdxRadiusSearch.size(); ++index){
          temp_w =sqrt(pointRadiusSquaredDistance[index]);
          if(temp_w - before_w > handle.finger_w*2){
            break; // there are small space for finger
          }
          before_w=temp_w;
        }
        if(before_w < min_width){
          min_theta_index = theta_;
          min_width = before_w;
          min_qua = temp_qua;
          best_mat = temp_mat;
        }
        //for debug view
        geometry_msgs::Point temp_point;
        std_msgs::ColorRGBA temp_color;
        temp_color.r=0; temp_color.g=0; temp_color.b=1; temp_color.a=1;
        temp_point.x=x-temp_mat.getColumn(1)[0] * before_w;
        temp_point.y=y-temp_mat.getColumn(1)[1] * before_w;
        temp_point.z=z-temp_mat.getColumn(1)[2] * before_w;
        debug_hand_marker.points.push_back(temp_point);
        debug_hand_marker.colors.push_back(temp_color);
        temp_point.x+=2*temp_mat.getColumn(1)[0] * before_w;
        temp_point.y+=2*temp_mat.getColumn(1)[1] * before_w;
        temp_point.z+=2*temp_mat.getColumn(1)[2] * before_w;
        debug_hand_marker.points.push_back(temp_point);
        debug_hand_marker.colors.push_back(temp_color);
      }
    }
    geometry_msgs::PoseStamped handle_pose_stamped;
    handle_pose_stamped.header = cloud_msg->header;
    handle_pose_stamped.pose.position.x = x;
    handle_pose_stamped.pose.position.y = y;
    handle_pose_stamped.pose.position.z = z;
    handle_pose_stamped.pose.orientation.x = min_qua.getX();
    handle_pose_stamped.pose.orientation.y = min_qua.getY();
    handle_pose_stamped.pose.orientation.z = min_qua.getZ();
    handle_pose_stamped.pose.orientation.w = min_qua.getW();
    std_msgs::Float64 min_width_msg;
    min_width_msg.data = min_width;
    pub_pose_.publish(handle_pose_stamped);
    pub_debug_marker_.publish(debug_hand_marker);
    pub_debug_marker_array_.publish(make_handle_array(handle_pose_stamped, handle));
    jsk_recognition_msgs::SimpleHandle simple_handle;
    simple_handle.header = handle_pose_stamped.header;
    simple_handle.pose = handle_pose_stamped.pose;
    simple_handle.handle_width = min_width;
    pub_handle_.publish(simple_handle);
  }
int
main (int argc, char** argv)
{
  // All the objects needed
  pcl::PCDReader reader;
  pcl::PassThrough<PointT> pass;
  pcl::NormalEstimation<PointT, pcl::Normal> ne;
  pcl::SACSegmentationFromNormals<PointT, pcl::Normal> seg; 
  pcl::PCDWriter writer;
  pcl::ExtractIndices<PointT> extract;
  pcl::ExtractIndices<pcl::Normal> extract_normals;
  pcl::search::KdTree<PointT>::Ptr tree (new pcl::search::KdTree<PointT> ());

  // Datasets
  pcl::PointCloud<PointT>::Ptr cloud (new pcl::PointCloud<PointT>);
  pcl::PointCloud<PointT>::Ptr cloud_filtered (new pcl::PointCloud<PointT>);
  pcl::PointCloud<pcl::Normal>::Ptr cloud_normals (new pcl::PointCloud<pcl::Normal>);
  pcl::PointCloud<PointT>::Ptr cloud_filtered2 (new pcl::PointCloud<PointT>);
  pcl::PointCloud<pcl::Normal>::Ptr cloud_normals2 (new pcl::PointCloud<pcl::Normal>);
  pcl::ModelCoefficients::Ptr coefficients_plane (new pcl::ModelCoefficients), coefficients_cylinder (new pcl::ModelCoefficients);
  pcl::PointIndices::Ptr inliers_plane (new pcl::PointIndices), inliers_cylinder (new pcl::PointIndices);

  // Read in the cloud data
  reader.read ("table_scene_mug_stereo_textured.pcd", *cloud);
  std::cerr << "PointCloud has: " << cloud->points.size () << " data points." << std::endl;

  // Build a passthrough filter to remove spurious NaNs
  pass.setInputCloud (cloud);
  pass.setFilterFieldName ("z");
  pass.setFilterLimits (0, 1.5);
  pass.filter (*cloud_filtered);
  std::cerr << "PointCloud after filtering has: " << cloud_filtered->points.size () << " data points." << std::endl;

  // Estimate point normals
  ne.setSearchMethod (tree);
  ne.setInputCloud (cloud_filtered);
  ne.setKSearch (50);
  ne.compute (*cloud_normals);

  // Create the segmentation object for the planar model and set all the parameters
  seg.setOptimizeCoefficients (true);
  seg.setModelType (pcl::SACMODEL_NORMAL_PLANE);
  seg.setNormalDistanceWeight (0.1);
  seg.setMethodType (pcl::SAC_RANSAC);
  seg.setMaxIterations (100);
  seg.setDistanceThreshold (0.03);
  seg.setInputCloud (cloud_filtered);
  seg.setInputNormals (cloud_normals);
  // Obtain the plane inliers and coefficients
  seg.segment (*inliers_plane, *coefficients_plane);
  std::cerr << "Plane coefficients: " << *coefficients_plane << std::endl;

  // Extract the planar inliers from the input cloud
  extract.setInputCloud (cloud_filtered);
  extract.setIndices (inliers_plane);
  extract.setNegative (false);

  // Write the planar inliers to disk
  pcl::PointCloud<PointT>::Ptr cloud_plane (new pcl::PointCloud<PointT> ());
  extract.filter (*cloud_plane);
  std::cerr << "PointCloud representing the planar component: " << cloud_plane->points.size () << " data points." << std::endl;
  writer.write ("table_scene_mug_stereo_textured_plane.pcd", *cloud_plane, false);

  // Remove the planar inliers, extract the rest
  extract.setNegative (true);
  extract.filter (*cloud_filtered2);
  extract_normals.setNegative (true);
  extract_normals.setInputCloud (cloud_normals);
  extract_normals.setIndices (inliers_plane);
  extract_normals.filter (*cloud_normals2);

  // Create the segmentation object for cylinder segmentation and set all the parameters
  seg.setOptimizeCoefficients (true);
  seg.setModelType (pcl::SACMODEL_CYLINDER);
  seg.setMethodType (pcl::SAC_RANSAC);
  seg.setNormalDistanceWeight (0.1);
  seg.setMaxIterations (10000);
  seg.setDistanceThreshold (0.05);
  seg.setRadiusLimits (0, 0.1);
  seg.setInputCloud (cloud_filtered2);
  seg.setInputNormals (cloud_normals2);

  // Obtain the cylinder inliers and coefficients
  seg.segment (*inliers_cylinder, *coefficients_cylinder);
  std::cerr << "Cylinder coefficients: " << *coefficients_cylinder << std::endl;

  // Write the cylinder inliers to disk
  extract.setInputCloud (cloud_filtered2);
  extract.setIndices (inliers_cylinder);
  extract.setNegative (false);
  pcl::PointCloud<PointT>::Ptr cloud_cylinder (new pcl::PointCloud<PointT> ());
  extract.filter (*cloud_cylinder);
  if (cloud_cylinder->points.empty ()) 
    std::cerr << "Can't find the cylindrical component." << std::endl;
  else
  {
	  std::cerr << "PointCloud representing the cylindrical component: " << cloud_cylinder->points.size () << " data points." << std::endl;
	  writer.write ("table_scene_mug_stereo_textured_cylinder.pcd", *cloud_cylinder, false);
  }
  return (0);
}
Example #30
0
int main (int argc, char** argv)
{

	/* DOWNSAMPLING ********************************************************************************************************************/
	std::ofstream output_file("properties.txt");
	std::ofstream curvature("curvature.txt");
	std::ofstream normals_text("normals.txt");

	/*

	std::cerr << "PointCloud before filtering: " << cloud->width * cloud->height 
		<< " data points (" << pcl::getFieldsList (*cloud) << ")." << std::endl;

	// Create the filtering object
	pcl::VoxelGrid<pcl::PCLPointCloud2> sor;
	sor.setInputCloud (cloud);
	sor.setLeafSize (0.01f, 0.01f, 0.01f);
	sor.filter (*cloud_filtered);

	output_file << "Number of filtered points" << std::endl;
	output_file << cloud_filtered->width * cloud_filtered->height<<std::endl;

	std::cerr << "PointCloud after filtering: " << cloud_filtered->width * cloud_filtered->height 
		<< " data points (" << pcl::getFieldsList (*cloud_filtered) << ")." << std::endl;


	pcl::PointCloud<pcl::PointXYZ>::Ptr descriptor (new pcl::PointCloud<pcl::PointXYZ>);

	descriptor->width = 5000 ;
	descriptor->height = 1 ;
	descriptor->points.resize (descriptor->width * descriptor->height) ;
	std::cerr << descriptor->points.size() << std::endl ;

	pcl::PCDWriter writer;
	writer.write ("out.pcd", *cloud_filtered, Eigen::Vector4f::Zero (), Eigen::Quaternionf::Identity (), false);

	*/
		
	/***********************************************************************************************************************************/

	/* CALCULATING VOLUME AND SURFACE AREA ********************************************************************************************************************/		

	/*pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_hull (new pcl::PointCloud<pcl::PointXYZ>);
	  pcl::ConcaveHull<pcl::PointXYZ> chull;
	  chull.setInputCloud(test);

	  chull.reconstruct(*cloud_hull);*/

	/*for (size_t i=0; i < test->points.size (); i++)
	  {
	  std::cout<< test->points[i].x <<std::endl;
	  std::cout<< test->points[i].y <<std::endl;
	  std::cout<< test->points[i].z <<std::endl;
	  }*/
	//std::cout<<data.size()<<std::endl;

	// Load input file into a PointCloud<T> with an appropriate type
	pcl::PointCloud<pcl::PointXYZ>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZ>);
	pcl::PCLPointCloud2 cloud_blob;
	pcl::io::loadPCDFile ("mini_soccer_ball_downsampled.pcd", cloud_blob);
	pcl::fromPCLPointCloud2 (cloud_blob, *cloud);		
	pcl::PointCloud<pcl::PointXYZ>::Ptr cloud1 (new pcl::PointCloud<pcl::PointXYZ>);
	pcl::fromPCLPointCloud2 (cloud_blob, *cloud1);
		//* the data should be available in cloud

	// Normal estimation*
	pcl::NormalEstimation<pcl::PointXYZ, pcl::Normal> n;
	pcl::PointCloud<pcl::Normal>::Ptr normals (new pcl::PointCloud<pcl::Normal>);
	pcl::search::KdTree<pcl::PointXYZ>::Ptr tree (new pcl::search::KdTree<pcl::PointXYZ>);
	tree->setInputCloud (cloud);
	n.setInputCloud (cloud);
	n.setSearchMethod (tree);
	n.setKSearch (20);
	n.compute (*normals);
	//* normals should not contain the point normals + surface curvatures

	// Concatenate the XYZ and normal fields*
	pcl::PointCloud<pcl::PointNormal>::Ptr cloud_with_normals (new pcl::PointCloud<pcl::PointNormal>);
	pcl::concatenateFields (*cloud, *normals,*cloud_with_normals);
	//* cloud_with_normals = cloud + normals

	// Create search tree*
	pcl::search::KdTree<pcl::PointNormal>::Ptr tree2 (new pcl::search::KdTree<pcl::PointNormal>);
	tree2->setInputCloud (cloud_with_normals);

	// Initialize objects
	pcl::GreedyProjectionTriangulation<pcl::PointNormal> gp3;
	pcl::PolygonMesh triangles;

	// Set the maximum distance between connected points (maximum edge length)
	gp3.setSearchRadius (0.025);

	// Set typical values for the parameters
	gp3.setMu (2.5);
	gp3.setMaximumNearestNeighbors (100);
	gp3.setMaximumSurfaceAngle(M_PI/4); // 45 degrees
	gp3.setMinimumAngle(M_PI/18); // 10 degrees
	gp3.setMaximumAngle(2*M_PI/3); // 120 degrees
	gp3.setNormalConsistency(false);


	// Get result
	gp3.setInputCloud (cloud_with_normals);
	gp3.setSearchMethod (tree2);
	gp3.reconstruct (triangles);

	// Additional vertex information
	std::vector<int> parts = gp3.getPartIDs();
	std::vector<int> states = gp3.getPointStates();	

	pcl::PolygonMesh::Ptr mesh(&triangles);
	pcl::PointCloud<pcl::PointXYZ>::Ptr triangle_cloud(new pcl::PointCloud<pcl::PointXYZ>);
	pcl::fromPCLPointCloud2(mesh->cloud, *triangle_cloud);	
/*	for(int i = 0; i < 2; i++){
		std::cout<<triangles.polygons[i]<<std::endl;
	}
*/	std::cout<<"first vertice "<<triangles.polygons[0].vertices[0] << std::endl; 	
	
	//std::cout<<"Prolly not gonna work "<<triangle_cloud->points[triangles.polygons[0].vertices[0]] << std::endl; 	


	//pcl::fromPCLPointCloud2(triangles.cloud, triangle_cloud); 
	std::cout << "size of points " << triangle_cloud->points.size() << std::endl ;
	
	std::cout<<triangle_cloud->points[0]<<std::endl;
	for(unsigned i = 0; i < triangle_cloud->points.size(); i++){
		std::cout << triangles.polgyons[i].getVector3fMap() <<"test"<< std::endl;
	} 	
	//std::cout<<"surface: "<<calculateAreaPolygon(triangles, triangle_cloud)<<std::endl;

	/******************************************************************************************************************************************/	

	/* CALCULATING CURVATURE AND NORMALS ********************************************************************************************************************/

	// Create the normal estimation class, and pass the input dataset to it
	pcl::NormalEstimation<pcl::PointXYZ, pcl::Normal> ne;	

	ne.setInputCloud (cloud);

	// Create an empty kdtree representation, and pass it to the normal estimation object.
	// Its content will be filled inside the object, based on the given input dataset (as no other search surface is given).
	pcl::search::KdTree<pcl::PointXYZ>::Ptr tree3 (new pcl::search::KdTree<pcl::PointXYZ> ());

	ne.setSearchMethod (tree3);

	// Output datasets
	pcl::PointCloud<pcl::Normal>::Ptr cloud_normals (new pcl::PointCloud<pcl::Normal>);

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

	// Compute the features
	ne.compute (*cloud_normals);

	output_file << "size of points " << cloud->points.size() << std::endl ;

	output_file << "size of the normals " << cloud_normals->points.size() << std::endl ; 	

	//pcl::PointCloud<pcl::PointXYZRGB>::Ptr point_cloud_ptr (new pcl::PointCloud<pcl::PointXYZRGB>);

	/************************************************************************************************************************************/

	/* PARSING DATA ********************************************************************************************************************/

	int k=0 ;
	float dist ;
	float square_of_dist ;
	float x1,y1,z1,x2,y2,z2 ;
	float nu[3], nv[3], pv_pu[3], pu_pv[3] ;
	float highest = triangle_cloud->points[0].z;
	float lowest = triangle_cloud->points[0].z;


	for ( int i = 0; i < cloud_normals->points.size() ; i++)
	{
		output_file<<i<<": triangulated "<<triangle_cloud->points[i].x<<", "<<triangle_cloud->points[i].y<<", "<<triangle_cloud->points[i].z<<std::endl;
		output_file<<i<<": normal"<<cloud1->points[i].x<<", "<<cloud1->points[i].y<<", "<<cloud1->points[i].z<<std::endl;
		if(triangle_cloud->points[i].z > highest)
		{
			highest = triangle_cloud->points[i].z;
		}
		if(triangle_cloud->points[i].z < lowest)
		{
			lowest = triangle_cloud->points[i].z;
		}
		normals_text <<i+1 <<": "<<" x-normal-> "<<cloud_normals->points[i].normal_x<<" y-normal-> "<<cloud_normals->points[i].normal_y<<" z-normal-> "<<cloud_normals->points[i].normal_z<<std::endl;
		curvature <<i+1 <<": curvature: "<<cloud_normals->points[i].curvature<<std::endl;
		
		float x, y, z, dist, nx, ny, nz, ndist;
		
		/*

		if(i != cloud_normals->points.size()-1){
			x = cloud->points[i+1].x - cloud->points[i].x;
			y = cloud->points[i+1].y - cloud->points[i].y;
			z = cloud->points[i+1].z - cloud->points[i].z;
			dist = sqrt(pow(x, 2)+pow(y, 2) + pow(z, 2));
			output_file << i+1 <<" -> "<< i+2 << " distance normal: " << dist <<std::endl;
			
			nx = triangle_cloud[i+1].indices[0] - triangle_cloud.points[i].x;
			ny = triangle_cloud.points[i+1].y - triangle_cloud.points[i].y;
			nz = triangle_cloud.points[i+1].z - triangle_cloud.points[i].z;
			ndist = sqrt(pow(nx, 2)+pow(ny, 2) + pow(nz, 2));
			output_file << i+1 <<" -> "<< i+2 << " distance triangulated: " << ndist <<std::endl;
		}

		*/	
		/*
		   pcl::PointXYZRGB point;
		   point.x = cloud_filtered_converted->points[i].x;
		   point.y = cloud_filtered_converted->points[i].y;
		   point.z = cloud_filtered_converted->points[i].z;
		   point.r = 0;
		   point.g = 100;
		   point.b = 200;
		   point_cloud_ptr->points.push_back (point);
		 */
	}
	output_file << "highest point: "<< highest<<std::endl;
	output_file << "lowest point: "<< lowest<<std::endl;	
	//pcl::PointCloud<pcl::PointXYZ>::Ptr test (new pcl::PointCloud<pcl::PointXYZ>);
	//float surface_area = calculateAreaPolygon(test);
	//std::cout<< surface_area<<std::endl;

	/*

	   descriptor->width = k ;
	   descriptor->height = 1 ;
	   descriptor->points.resize (descriptor->width * descriptor->height) ;
	   std::cerr << descriptor->points.size() << std::endl ;
	   float voxelSize = 0.01f ;  // how to find appropriate voxel resolution
	   pcl::octree::OctreePointCloud<pcl::PointXYZ> octree (voxelSize);
	   octree.setInputCloud(descriptor) ;
	   ctree.defineBoundingBox(0.0,0.0,0.0,3.14,3.14,3.14) ;   //octree.defineBoundingBox (minX, minY, minZ, maxX, maxY, maxZ)
	   octree.addPointsFromInputCloud ();   // octree created for block

	   int k_ball=0 ;
	   float dist_ball ;
	   float square_of_dist_ball ;
	   double X,Y,Z ;
	   bool occupied ;
	   highest = cloud_ball->points[0].z;

	   for ( int i = 0; i < cloud_normals_ball->points.size() ; i++)
	   {
	   if(cloud->points[i].z > highest){
	   highest = cloud_ball->points[i].z;
	   }
	   for (int j = i+1 ; (j < cloud_normals_ball->points.size()) ; j++)     
	   {
	   x1 = cloud_ball->points[i].x ;
	   y1 = cloud_ball->points[i].y ;
	   z1 = cloud_ball->points[i].z ;
	   nu[0] = cloud_normals_ball->points[i].normal_x ;
	   nu[1] = cloud_normals_ball->points[i].normal_y ;
	   nu[2] = cloud_normals_ball->points[i].normal_z ;
	   x2 = cloud_ball->points[j].x ;
	   y2 = cloud_ball->points[j].y ;
	   z2 = cloud_ball->points[j].z ;
	   nv[0] = cloud_normals_ball->points[j].normal_x ;
	   nv[1] = cloud_normals_ball->points[j].normal_y ;
	   nv[2] = cloud_normals_ball->points[j].normal_z ;
	   square_of_dist = ((x2-x1)*(x2-x1)) + ((y2-y1)*(y2-y1)) + ((z2-z1)*(z2-z1)) ;
	   dist = sqrt(square_of_dist) ;
	//std::cerr << dist ;
	pv_pu[0] = x2-x1 ;
	pv_pu[1] = y2-y1 ;
	pv_pu[2] = z2-z1 ;
	pu_pv[0] = x1-x2 ;
	pu_pv[1] = y1-y2 ;
	pu_pv[2] = z1-z2 ;
	if ((dist > 0.0099) && (dist < 0.0101))
	{
	X = angle_between_vectors (nu, nv) ;
	Y  = angle_between_vectors (nu, pv_pu) ;
	Z = angle_between_vectors (nv, pu_pv) ;
	// output_file << descriptor->points[k].x << "\t" << descriptor->points[k].y << "\t" << descriptor->points[k].z  ;
	// output_file << "\n";	
	//k_ball = k_ball + 1 ;
	occupied = octree.isVoxelOccupiedAtPoint (X,Y,Z) ;
	if (occupied == 1)
	{
	//k_ball = k_ball + 1 ;
	std::cerr << "Objects Matched" << "\t" << k_ball << std::endl ;
	return(0); 
	}

	}

	}

	}	

	 */

	/***********************************************************************************************************************************/


	/*

	   points.open("secondItemPoints.txt");
	   myfile<<"Second point \n";
	   myfile<<"second highest "<<highest;
	   for(int i = 0; i < cloud_normals->points.size(); i++){
	   points<<cloud->points[i].x<<", "<<cloud->points[i].y<<", "<<cloud->points[i].z<<"\n";
	   if(cloud->points[i].z >= highest - (highest/100)){
	   myfile<<cloud->points[i].x<<", "<<cloud->points[i].y<<", "<<cloud->points[i].z<<"\n";
	   }
	   }
	   points.close();
	   myfile.close();

	   std::cerr << "Objects Not Matched" << "\t" << k_ball << std::endl ;

	 */

	//output_file <<"Volume: "<<volume <<std::endl;
	//output_file <<"Surface Area: "<<surface_area <<std::endl;

	return (0);
}