void Planar_filter::Downsample_cloud(std::string input)
 {
  if(input == "Normals only"){
       _vgn.setInputCloud (_cloud_with_normals);
     _vgn.setLeafSize (0.01f,0.01f,0.01f);
     PointNormalCloudT::Ptr filtered_cloud(new PointNormalCloudT);
     _vgn.filter (*filtered_cloud);
     *_cloud_with_normals = *filtered_cloud;
   }else{
       _vgcn.setInputCloud (_cloud_color_normals);
     _vgcn.setLeafSize (0.01f,0.01f,0.01f);
     PointColorNormalCloudT::Ptr filtered_cloud(new PointColorNormalCloudT);
     _vgcn.filter (*filtered_cloud);
     *_cloud_color_normals = *filtered_cloud;
   }  
   //std::cout<<"cloud with normals has been downsampled " <<std::endl;
 }
 // Create the filtering object: downsample the dataset using a leaf size of 1cm
   void Planar_filter::Downsample_cloud()
   {
     _vg.setInputCloud (_cloud);
     _vg.setLeafSize (0.01f,0.01f,0.01f);
     PointCloudT::Ptr filtered_cloud(new PointCloudT);
     _vg.filter (*filtered_cloud);
     *_cloud = *filtered_cloud;
     //std::cout << "PointCloud after filtering has: " << _cloud->points.size ()  << " data points." << std::endl; //*
   }
void Recognizer::setInputCloud(PointNormalCloudT::Ptr cloud,double leaf_size){
	  _vgn.setInputCloud (cloud);
      _vgn.setLeafSize (leaf_size,leaf_size,leaf_size);
      PointNormalCloudT::Ptr filtered_cloud(new PointNormalCloudT);
      _vgn.filter (*filtered_cloud);
      *cloud = *filtered_cloud;
	pcl::copyPointCloud(*cloud,*_cloud);
	pcl::copyPointCloud(*cloud,*_normals);
  pcl::copyPointCloud(*cloud,*_cloud_with_normals);	
}
Example #4
0
template<typename PointInT> void
pcl::TextureMapping<PointInT>::removeOccludedPoints (const pcl::TextureMesh &tex_mesh, pcl::TextureMesh &cleaned_mesh, const double octree_voxel_size)
{
  // copy mesh
  cleaned_mesh = tex_mesh;

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

  // load points into a PCL format
  pcl::fromPCLPointCloud2 (tex_mesh.cloud, *cloud);

  std::vector<int> visible, occluded;
  removeOccludedPoints (cloud, filtered_cloud, octree_voxel_size, visible, occluded);

  // Now that we know which points are visible, let's iterate over each face.
  // if the face has one invisible point => out!
  for (size_t polygons = 0; polygons < cleaned_mesh.tex_polygons.size (); ++polygons)
  {
    // remove all faces from cleaned mesh
    cleaned_mesh.tex_polygons[polygons].clear ();
    // iterate over faces
    for (size_t faces = 0; faces < tex_mesh.tex_polygons[polygons].size (); ++faces)
    {
      // check if all the face's points are visible
      bool faceIsVisible = true;
      std::vector<int>::iterator it;

      // iterate over face's vertex
      for (size_t points = 0; points < tex_mesh.tex_polygons[polygons][faces].vertices.size (); ++points)
      {
        it = find (occluded.begin (), occluded.end (), tex_mesh.tex_polygons[polygons][faces].vertices[points]);

        if (it == occluded.end ())
        {
          // point is not in the occluded vector
          // PCL_INFO ("  VISIBLE!\n");
        }
        else
        {
          // point was occluded
          // PCL_INFO("  OCCLUDED!\n");
          faceIsVisible = false;
        }
      }

      if (faceIsVisible)
      {
        cleaned_mesh.tex_polygons[polygons].push_back (tex_mesh.tex_polygons[polygons][faces]);
      }

    }
  }
}
Example #5
0
pcl::PointCloud<pcl::PointXYZ>::Ptr
zFilter (pcl::PointCloud<pcl::PointXYZ>::Ptr input_cloud, float min_ratio, float max_ratio)
{
    std::vector<float> z_range = findZRange(input_cloud);

    pcl::PointCloud<pcl::PointXYZ>::Ptr filtered_cloud(new pcl::PointCloud<pcl::PointXYZ>);
    pcl::PassThrough<pcl::PointXYZ> pass;

    pass.setInputCloud(input_cloud);
    pass.setFilterFieldName("z");
    pass.setFilterLimits(min_ratio * z_range[0], max_ratio * z_range[1]);
    pass.filter(*filtered_cloud);
    return filtered_cloud;
}
void recons(std::string infile, std::string outfile) {
  sensor_msgs::PointCloud2 cloud_blob;
  // run this from BodyScanner/build/surface_reconstructor/
  pcl::io::loadPCDFile(infile, cloud_blob);
  pcl::PointCloud<pcl::PointNormal>::Ptr cloud(new pcl::PointCloud<pcl::PointNormal> ());  
  pcl::fromROSMsg (cloud_blob, *cloud);

  pcl::PointCloud<pcl::PointNormal>::Ptr filtered_cloud(new pcl::PointCloud<pcl::PointNormal>());
  int l = 0;
  for(int j = 0; j < 480; j += 1) {
    for(int i = j%2; i < 640; i += 2) {
      int k = i + j*640;
      pcl::PointNormal& p = (*cloud)[k];
      if((i&1 && j&1) // keep 1/4 of the points
         && mag(p) < 3) { // keep only points within a close distance to the origin
        filtered_cloud->push_back(p);
      }
    }
  }

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

  // 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);
  setMaximumSurfaceAngle(gp3, 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(filtered_cloud);
  gp3.setSearchMethod(tree2);
  gp3.reconstruct(triangles);

  //pcl::io::savePLYFile(outfile, triangles);
  pcl::io::saveVTKFile(outfile, triangles);
}
/* ========================================
 * Fill Code: SERVICE
 * ========================================*/
bool filterCallback(lesson_perception::FilterCloud::Request& request,
                   lesson_perception::FilterCloud::Response& response)
{
 pcl::PointCloud<pcl::PointXYZ>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZ>);
 pcl::PointCloud<pcl::PointXYZ>::Ptr filtered_cloud (new pcl::PointCloud<pcl::PointXYZ>);
 if (request.pcdfilename.empty())
 {
   pcl::fromROSMsg(request.input_cloud, *cloud);
   ROS_INFO_STREAM("cloud size: " <<cloud->size());
   if (cloud->empty())
   {
     ROS_ERROR("input cloud empty");
     response.success = false;
     return false;
   }
 }
 else
 {
   pcl::io::loadPCDFile(request.pcdfilename, *cloud);
 }

 switch (request.operation)
 {

   case lesson_perception::FilterCloud::Request::VOXELGRID :
   {
     filtered_cloud = voxelGrid(cloud, 0.01);
     break;
   }
   default :
   {
     ROS_ERROR("no point cloud found");
     return false;
   }

  }

/*
* SETUP RESPONSE
*/
 pcl::toROSMsg(*filtered_cloud, response.output_cloud);
 response.output_cloud.header=request.input_cloud.header;
 response.output_cloud.header.frame_id="kinect_link";
 response.success = true;
 return true;
}
Example #8
0
void processPointCloud(const cloud_t::Ptr &cloud, std::vector<point_t> &centroids) 
{
	if (cloud->points.size() < 10) {
		return;
	}
    // Downsample using Voxel Grid
    cloud_t::Ptr filtered_cloud(new cloud_t);
    downsample(cloud, filtered_cloud);

    // Calculate normals
    pcl::search::Search<point_t>::Ptr tree = boost::shared_ptr<pcl::search::Search<point_t> > (new pcl::search::KdTree<point_t>);
    pcl::PointCloud<pcl::Normal>::Ptr normals(new pcl::PointCloud<pcl::Normal>);
    pcl::NormalEstimation<point_t, pcl::Normal> normal_estimator;
    normal_estimator.setSearchMethod (tree);
    normal_estimator.setInputCloud (filtered_cloud);
    normal_estimator.setKSearch (20);
    normal_estimator.compute (*normals);

    // Region growing
    pcl::RegionGrowing<point_t, pcl::Normal> reg;

    //Maximum and minimum number of points to classify as a cluster
    // First check: to see if object is large (or takes up a large portion of the laser's view)
    reg.setMinClusterSize(40);
    reg.setMaxClusterSize(1000000);
    reg.setSearchMethod(tree);

    // Number of neighbors to search 
    reg.setNumberOfNeighbours(35);
    reg.setInputCloud(filtered_cloud);
    reg.setInputNormals(normals);
    reg.setSmoothnessThreshold(6.0 / 180.0 * M_PI);
    reg.setCurvatureThreshold(.15);

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

    // Update colored cloud
    colored_cloud = reg.getColoredCloud();

    // Use clusters to find door(s)
    findDoorCentroids(filtered_cloud, clusters, centroids);
}
void viz(std::string fname) {
  sensor_msgs::PointCloud2 cloud_blob;
  // run this from BodyScanner/build/surface_reconstructor/
  pcl::io::loadPCDFile(fname, cloud_blob);
  pcl::PointCloud<pcl::PointNormal>::Ptr cloud(new pcl::PointCloud<pcl::PointNormal> ());  
  pcl::fromROSMsg (cloud_blob, *cloud);

  pcl::PointCloud<pcl::PointNormal>::Ptr filtered_cloud(new pcl::PointCloud<pcl::PointNormal>());
  int l = 0;
  for(int j = 0; j < 480; j += 1) {
    for(int i = j%2; i < 640; i += 2) {
      int k = i + j*640;
      pcl::PointNormal& p = (*cloud)[k];
      if((i&1 && j&1) // keep 1/4 of the points
         && mag(p) < 3) { // keep only points within a close distance to the origin
        filtered_cloud->push_back(p);
      }
    }
  }

  // potentially fancier downsampling
/*
  pcl::VoxelGrid<sensor_msgs::PointCloud2> sor;
  sor.setInputCloud (cloud_blob);
  sor.setLeafSize (0.01f, 0.01f, 0.01f);
  sor.filter (*cloud_filtered_blob);
*/

  boost::shared_ptr<pcl::visualization::PCLVisualizer> viewer = normalsVis(filtered_cloud);
  viewer->registerKeyboardCallback(&handleKeyEvent, NULL); 

  pcl::PointXYZ o;
  o.x = 1.0;
  o.y = 0;
  o.z = 0;
  viewer->addSphere (o, 0.25, "sphere", 0);
  
  while (!viewer->wasStopped ()) {
    viewer->spinOnce (100);
    boost::this_thread::sleep (boost::posix_time::microseconds (100000));
  }
}
Example #10
0
void ObjectRecognition::pipeline(pcl::PointCloud<pcl::PointXYZRGB>::Ptr input_cloud) {
    pcl::PointCloud<pcl::PointXYZRGB>::Ptr filtered_cloud(new pcl::PointCloud<pcl::PointXYZRGB>());
    pcl::PointCloud<pcl::PointXYZRGB>::Ptr table_hull(new pcl::PointCloud<pcl::PointXYZRGB>());
    pcl::PointCloud<pcl::PointXYZRGB>::Ptr objects_cloud(new pcl::PointCloud<pcl::PointXYZRGB>());
    boost::shared_ptr<std::vector<Object>> objects;
    filtered_cloud = this->object_pipeline->passthroughPointCloud(input_cloud);
    if (nullptr == filtered_cloud) {
        return;
    }
    table_hull = this->object_pipeline->findTableHull(filtered_cloud);
    if (nullptr == table_hull) {
        return;
    }
    objects_cloud = this->object_pipeline->createObjectCloud(filtered_cloud, table_hull);
    if (nullptr == objects_cloud) {
        return;
    }
    objects = this->object_pipeline->createObjectClusters(objects_cloud);
    this->object_pipeline->keyPointExtraction(objects);
    this->object_pipeline->createObjectDescriptors(objects);
    this->object_pipeline->objectMatching(objects);
    this->publish(objects);
}
void FacadeGeography::ComputeFeature(pcl::PointCloud<pcl::PointXYZ>::Ptr facade_cloud) {
	// First down sample the dense cloud
	std::cout << "down sampling ... \n";
	pcl::VoxelGrid<pcl::PointXYZ> filter;
	filter.setInputCloud(facade_cloud);
	filter.setLeafSize(0.1f, 0.1f, 0.1f);
	pcl::PointCloud<pcl::PointXYZ>::Ptr filtered_cloud(new pcl::PointCloud<pcl::PointXYZ>);
	filter.filter(*filtered_cloud);
	std::cout << "down sampling done. After filter, " << filtered_cloud->width * filtered_cloud->height <<
		" points left.\n";
	//
	pcl::search::KdTree<pcl::PointXYZ> search;

	pcl::PointXYZ cloud_min, cloud_max;
	pcl::getMinMax3D(*filtered_cloud, cloud_min, cloud_max);

	boost::progress_display  display(height_ + width_);
	Eigen::Vector4f min_pt, max_pt;
	for (int i = 0; i < width_; ++i) // for each width, compute the average z value
	{
		min_pt(0) = extents_min_.x + i * resolution_;
		min_pt(1) = extents_min_.y;
		min_pt(2) = cloud_min.x;
		min_pt(3) = 1.0;

		max_pt(0) = min_pt(0) + resolution_;
		max_pt(1) = min_pt(1) + resolution_ * height_;
		max_pt(2) = cloud_max.x;
		max_pt(3) = 1.0;

		std::vector<int> indices;
		pcl::getPointsInBox(*filtered_cloud, min_pt, max_pt, indices);

		assert(indices.size() >= 0);
		double sum = 0.0;
		for (int k = 0; k < indices.size(); ++k)
		{
			sum += filtered_cloud->points[indices[k]].z;
		}
		sum /= indices.size();

		horizonal_feature.push_back(sum);
		++display;
	}


	for (int i = 0; i < height_; ++i) // for each height, compute the average z value
	{
		min_pt(0) = extents_min_.x;
		min_pt(1) = extents_min_.y + i * resolution_;
		min_pt(2) = cloud_min.x;
		min_pt(3) = 1.0;

		max_pt(0) = min_pt(0) + resolution_ * width_;
		max_pt(1) = min_pt(1) + resolution_;
		max_pt(2) = cloud_max.x;
		max_pt(3) = 1.0;

		std::vector<int> indices;
		pcl::getPointsInBox(*filtered_cloud, min_pt, max_pt, indices);

		assert(indices.size() >= 0);
		double sum = 0.0;
		for (int k = 0; k < indices.size(); ++k)
		{
			sum += filtered_cloud->points[indices[k]].z;
		}
		sum /= indices.size();

		vertical_feature.push_back(sum);
		++display;
	}
}
Example #12
0
template<typename PointInT> int
pcl::TextureMapping<PointInT>::sortFacesByCamera (pcl::TextureMesh &tex_mesh, pcl::TextureMesh &sorted_mesh,
                                                  const pcl::texture_mapping::CameraVector &cameras, const double octree_voxel_size,
                                                  PointCloud &visible_pts)
{
  if (tex_mesh.tex_polygons.size () != 1)
  {
    PCL_ERROR ("The mesh must contain only 1 sub-mesh!\n");
    return (-1);
  }

  if (cameras.size () == 0)
  {
    PCL_ERROR ("Must provide at least one camera info!\n");
    return (-1);
  }

  // copy mesh
  sorted_mesh = tex_mesh;
  // clear polygons from cleaned_mesh
  sorted_mesh.tex_polygons.clear ();

  pcl::PointCloud<pcl::PointXYZ>::Ptr original_cloud (new pcl::PointCloud<pcl::PointXYZ>);
  pcl::PointCloud<pcl::PointXYZ>::Ptr transformed_cloud (new pcl::PointCloud<pcl::PointXYZ>);
  pcl::PointCloud<pcl::PointXYZ>::Ptr filtered_cloud (new pcl::PointCloud<pcl::PointXYZ>);

  // load points into a PCL format
  pcl::fromPCLPointCloud2 (tex_mesh.cloud, *original_cloud);

  // for each camera
  for (size_t cam = 0; cam < cameras.size (); ++cam)
  {
    // get camera pose as transform
    Eigen::Affine3f cam_trans = cameras[cam].pose;

    // transform original cloud in camera coordinates
    pcl::transformPointCloud (*original_cloud, *transformed_cloud, cam_trans.inverse ());

    // find occlusions on transformed cloud
    std::vector<int> visible, occluded;
    removeOccludedPoints (transformed_cloud, filtered_cloud, octree_voxel_size, visible, occluded);
    visible_pts = *filtered_cloud;

    // find visible faces => add them to polygon N for camera N
    // add polygon group for current camera in clean
    std::vector<pcl::Vertices> visibleFaces_currentCam;
    // iterate over the faces of the current mesh
    for (size_t faces = 0; faces < tex_mesh.tex_polygons[0].size (); ++faces)
    {
      // check if all the face's points are visible
      bool faceIsVisible = true;
      std::vector<int>::iterator it;

      // iterate over face's vertex
      for (size_t current_pt_indice = 0; faceIsVisible && current_pt_indice < tex_mesh.tex_polygons[0][faces].vertices.size (); ++current_pt_indice)
      {
        // TODO this is far too long! Better create an helper function that raycasts here.
        it = find (occluded.begin (), occluded.end (), tex_mesh.tex_polygons[0][faces].vertices[current_pt_indice]);

        if (it == occluded.end ())
        {
          // point is not occluded
          // does it land on the camera's image plane?
          pcl::PointXYZ pt = transformed_cloud->points[tex_mesh.tex_polygons[0][faces].vertices[current_pt_indice]];
          Eigen::Vector2f dummy_UV;
          if (!getPointUVCoordinates (pt, cameras[cam], dummy_UV))
          {
            // point is not visible by the camera
            faceIsVisible = false;
          }
        }
        else
        {
          faceIsVisible = false;
        }
      }

      if (faceIsVisible)
      {
        // push current visible face into the sorted mesh
        visibleFaces_currentCam.push_back (tex_mesh.tex_polygons[0][faces]);
        // remove it from the unsorted mesh
        tex_mesh.tex_polygons[0].erase (tex_mesh.tex_polygons[0].begin () + faces);
        faces--;
      }

    }
    sorted_mesh.tex_polygons.push_back (visibleFaces_currentCam);
  }

  // we should only have occluded and non-visible faces left in tex_mesh.tex_polygons[0]
  // we need to add them as an extra polygon in the sorted mesh
  sorted_mesh.tex_polygons.push_back (tex_mesh.tex_polygons[0]);
  return (0);
}
Example #13
0
void callback(const sensor_msgs::PointCloud2 &pc) {

  double t1, t2, avg_t;

  ROS_INFO("Received point cloud! Applying method %d",method_id);

  pcl::PointCloud<PointT>::Ptr scene_pc(new pcl::PointCloud<PointT>());

  pcl::PCLPointCloud2 pcl_pc;
  pcl_conversions::toPCL(pc, pcl_pc);

  pcl::fromPCLPointCloud2(pcl_pc, *scene_pc);

  if( scene_pc->empty() == true ) {
    ROS_ERROR("Recieved empty point cloud message!");
    return;
  }

  pcl::PointCloud<myPointXYZ>::Ptr scene_xyz(new pcl::PointCloud<myPointXYZ>());
  pcl::copyPointCloud(*scene_pc, *scene_xyz);

  if( view_flag == true )
  {
    viewer->removeAllPointClouds();
    viewer->addPointCloud(scene_xyz, "whole_scene");
    viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_COLOR, 0.5, 0.5, 0.5, "whole_scene");
  }
  std::vector<poseT> all_poses;
  std::vector<poseT> link_poses, node_poses;

  std::cout << " ... processing:" << std::endl;
  switch(method_id)
  {
    case 0:
      t1 = get_wall_time();
      objrec->StandardRecognize(scene_xyz, all_poses);
      t2 = get_wall_time();
      break;
    case 1:
      {
        t1 = get_wall_time();
        int pose_num = 0;
        int iter = 0;
        pcl::PointCloud<myPointXYZ>::Ptr filtered_cloud(new pcl::PointCloud<myPointXYZ>());
        filtered_cloud = scene_xyz;
        while(true)
        {
          //std::cerr<< "Recognizing Attempt --- " << iter << std::endl;
          objrec->StandardRecognize(filtered_cloud, all_poses);
          if( all_poses.size() <= pose_num )
            break;
          else
            pose_num = all_poses.size();

          pcl::PointCloud<myPointXYZ>::Ptr model_cloud = objrec->FillModelCloud(all_poses);
          filtered_cloud = FilterCloud(filtered_cloud, model_cloud);

          iter++;
        }
        t2 = get_wall_time();
        //std::cerr<< "Recognizing Done!!!" << std::endl;
        break;
      }
    case 2:
      {
        //std::vector<poseT> tmp_poses;
        t1 = get_wall_time();
        objrec->GreedyRecognize(scene_xyz, all_poses);
        t2 = get_wall_time();
        //all_poses = RefinePoses(scene_xyz, mesh_set, tmp_poses);
        break;
      }
    case 3:
      {
        pcl::PointCloud<myPointXYZ>::Ptr link_cloud(new pcl::PointCloud<myPointXYZ>());
        pcl::PointCloud<myPointXYZ>::Ptr node_cloud(new pcl::PointCloud<myPointXYZ>());
        splitCloud(scene_pc, link_cloud, node_cloud);

        t1 = get_wall_time();
        std::cout << " ... starting at " << t1 << std::endl;
        //std::vector<poseT> link_poses, node_poses;
        linkrec->StandardRecognize(link_cloud, link_poses);
        noderec->StandardRecognize(node_cloud, node_poses);
        t2 = get_wall_time();
        std::cout << " ... done at " << t2 << std::endl;

        all_poses.insert(all_poses.end(), link_poses.begin(), link_poses.end());
        all_poses.insert(all_poses.end(), node_poses.begin(), node_poses.end());
        break;
      }
    case 4:
      {
        pcl::PointCloud<myPointXYZ>::Ptr link_cloud(new pcl::PointCloud<myPointXYZ>());
        pcl::PointCloud<myPointXYZ>::Ptr node_cloud(new pcl::PointCloud<myPointXYZ>());
        splitCloud(scene_pc, link_cloud, node_cloud);

        t1 = get_wall_time();
        std::cout << " ... starting at " << t1 << std::endl;
        int pose_num = 0;
        std::vector<poseT> tmp_poses;
        int iter = 0;
        while(true)
        {
          //std::cerr<< "Recognizing Attempt --- " << iter << std::endl;
          list<AcceptedHypothesis> acc_hypotheses;

          
          std::cout << " ... generating" << std::endl;
          linkrec->genHypotheses(link_cloud, acc_hypotheses);
          noderec->genHypotheses(node_cloud, acc_hypotheses);

          std::cout << " ... merging" << std::endl;
          linkrec->mergeHypotheses(scene_xyz, acc_hypotheses, tmp_poses);

          if( tmp_poses.size() <= pose_num ) {
            break;
          } else {
            pose_num = tmp_poses.size();
            std::cout << "Number of merged hypotheses: " << tmp_poses.size() << std::endl;
          }

          pcl::PointCloud<myPointXYZ>::Ptr link_model = linkrec->FillModelCloud(tmp_poses);
          pcl::PointCloud<myPointXYZ>::Ptr node_model = noderec->FillModelCloud(tmp_poses);

          std::cout << " ... filtering" << std::endl;
          if( link_model->empty() == false ) {
            link_cloud = FilterCloud(link_cloud, link_model);
          }
          if( node_model->empty() == false) {
            node_cloud = FilterCloud(node_cloud, node_model);
          }
          iter++;
        }
        t2 = get_wall_time();
        std::cout << " ... done at " << t2 << std::endl;
        //std::cerr<< "Recognizing Done!!!" << std::endl;
        all_poses = RefinePoses(scene_xyz, mesh_set, tmp_poses);
        break;
      }
    case 5:
      {
        pcl::PointCloud<myPointXYZ>::Ptr link_cloud(new pcl::PointCloud<myPointXYZ>());
        pcl::PointCloud<myPointXYZ>::Ptr node_cloud(new pcl::PointCloud<myPointXYZ>());
        splitCloud(scene_pc, link_cloud, node_cloud);

        t1 = get_wall_time();
        linkrec->GreedyRecognize(link_cloud, link_poses);
        noderec->GreedyRecognize(node_cloud, node_poses);
        t2 = get_wall_time();

        std::vector<poseT> tmp_poses;
        tmp_poses.insert(tmp_poses.end(), link_poses.begin(), link_poses.end());
        tmp_poses.insert(tmp_poses.end(), node_poses.begin(), node_poses.end());

        //all_poses = tmp_poses;
        all_poses = RefinePoses(scene_xyz, mesh_set, tmp_poses);
        break;
      }
    default:
      ROS_ERROR("Code %d not recognized!",method_id);
      return;
  }

  if( view_flag == true )
  {
    switch(method_id)
    {
      case 0:
      case 1:
      case 2:
        objrec->visualize(viewer, all_poses);
        break;
      case 3:
      case 4:
      case 5:
        linkrec->visualize(viewer, all_poses);
        noderec->visualize(viewer, all_poses);
        break;
    }
    viewer->spin();
  }

  geometry_msgs::PoseArray links;
  geometry_msgs::PoseArray nodes;
  links.header.frame_id = pc.header.frame_id;
  nodes.header.frame_id = pc.header.frame_id;

  // publish poses as TF
  if (method_id < 3) {
    for (poseT &p: all_poses) {
      geometry_msgs::Pose pose;
      pose.position.x = p.shift[0];
      pose.position.y = p.shift[1];
      pose.position.z = p.shift[2];
      pose.orientation.x = p.rotation.x();
      pose.orientation.y = p.rotation.y();
      pose.orientation.z = p.rotation.z();
      pose.orientation.w = p.rotation.w();
      links.poses.push_back(pose);
    }
    pub_link.publish(links);
  } else {
    for (poseT &p: all_poses) {
      geometry_msgs::Pose pose;
      pose.position.x = p.shift[0];
      pose.position.y = p.shift[1];
      pose.position.z = p.shift[2];
      pose.orientation.x = p.rotation.x();
      pose.orientation.y = p.rotation.y();
      pose.orientation.z = p.rotation.z();
      pose.orientation.w = p.rotation.w();
      links.poses.push_back(pose);
    }
    for (poseT &p: all_poses) {
      geometry_msgs::Pose pose;
      pose.position.x = p.shift[0];
      pose.position.y = p.shift[1];
      pose.position.z = p.shift[2];
      pose.orientation.x = p.rotation.x();
      pose.orientation.y = p.rotation.y();
      pose.orientation.z = p.rotation.z();
      pose.orientation.w = p.rotation.w();
      nodes.poses.push_back(pose);
    }
    pub_link.publish(links);
    pub_link.publish(nodes);
  }

  std::cout << "Time 1 = " << t1 << std::endl;
  std::cout << "Time 2 = " << t2 << std::endl;
  ROS_INFO("... done.");

}
void colorRecons(std::string infile, std::string outfile) {
  sensor_msgs::PointCloud2 cloud_blob;
  // run this from BodyScanner/build/surface_reconstructor/
  pcl::io::loadPCDFile(infile, cloud_blob);
  pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZRGB> ());  
  pcl::fromROSMsg(cloud_blob, *cloud);

  pcl::PointCloud<pcl::PointXYZ>::Ptr filtered_cloud(new pcl::PointCloud<pcl::PointXYZ>());
  pcl::PointCloud<pcl::PointXYZRGB>::Ptr filtered_cloud_color(new pcl::PointCloud<pcl::PointXYZRGB>());
  int l = 0;
  for(int j = 0; j < 480; j += 1) {
    for(int i = j%2; i < 640; i += 2) {
      int k = i + j*640;
      pcl::PointXYZRGB& p = (*cloud)[k];
      pcl::PointXYZ pp;
      pcl::PointXYZRGB pc;
      pc.x = pp.x = p.x;
      pc.y = pp.y = p.y;
      pc.z = pp.z = p.z;
      pc.r = p.r;
      pc.g = p.g;
      pc.b = p.b;
      //pp.nx = 0; pp.ny = 0; pp.nz = 0;
      //if((i&1 && j&1) // keep 1/4 of the points
      if(mag(p) < 3) { // keep only points within a close distance to the origin
        filtered_cloud->push_back(pp);
        filtered_cloud_color->push_back(pc);
      }
    }
  }

  // Normal estimation*
  pcl::NormalEstimation<pcl::PointXYZ, pcl::Normal> n;
  pcl::PointCloud<pcl::Normal>::Ptr normals(new pcl::PointCloud<pcl::Normal>);
  pcl::KdTree<pcl::PointXYZ>::Ptr tree(new pcl::KdTreeFLANN<pcl::PointXYZ>);
  tree->setInputCloud(filtered_cloud);
  n.setInputCloud(filtered_cloud);
  n.setSearchMethod(tree);
  n.setKSearch(20);
  n.compute(*normals);

  // Concatenate the XYZ and normal fields*
  pcl::PointCloud<pcl::PointNormal>::Ptr filtered_cloud_with_normals(new pcl::PointCloud<pcl::PointNormal>);
  pcl::concatenateFields(*filtered_cloud, *normals, *filtered_cloud_with_normals);

  // Create search tree*
  pcl::KdTree<pcl::PointNormal>::Ptr tree2(new pcl::KdTreeFLANN<pcl::PointNormal>);
  tree2->setInputCloud(filtered_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.1);

  // Set typical values for the parameters
  gp3.setMu(2.5);
  gp3.setMaximumNearestNeighbors(50); // reducing this didn't fix flips
  setMaximumSurfaceAngle(gp3, M_PI/4); // 45 degrees
  gp3.setMinimumAngle(M_PI/18); // 10 degrees
  gp3.setMaximumAngle(2*M_PI/3); // 120 degrees
  gp3.setNormalConsistency(true); // changing this didn't fix flips

  // Get result
  gp3.setInputCloud(filtered_cloud_with_normals);
  gp3.setSearchMethod(tree2);
  gp3.reconstruct(triangles);
  
  saveObj(outfile, triangles, filtered_cloud_color);
}
  void PointCloudLocalization::cloudCallback(
    const sensor_msgs::PointCloud2::ConstPtr& cloud_msg)
  {
    vital_checker_->poke();
    boost::mutex::scoped_lock lock(mutex_);
    //JSK_NODELET_INFO("cloudCallback");
    latest_cloud_ = cloud_msg;
    if (localize_requested_){
      JSK_NODELET_INFO("localization is requested");
      try {
        pcl::PointCloud<pcl::PointNormal>::Ptr
          local_cloud (new pcl::PointCloud<pcl::PointNormal>);
        pcl::fromROSMsg(*latest_cloud_, *local_cloud);
        JSK_NODELET_INFO("waiting for tf transformation from %s tp %s",
                     latest_cloud_->header.frame_id.c_str(),
                     global_frame_.c_str());
        if (tf_listener_->waitForTransform(
              latest_cloud_->header.frame_id,
              global_frame_,
              latest_cloud_->header.stamp,
              ros::Duration(1.0))) {
          pcl::PointCloud<pcl::PointNormal>::Ptr
            input_cloud (new pcl::PointCloud<pcl::PointNormal>);
          if (use_normal_) {
            pcl_ros::transformPointCloudWithNormals(global_frame_,
                                                    *local_cloud,
                                                    *input_cloud,
                                                    *tf_listener_);
          }
          else {
            pcl_ros::transformPointCloud(global_frame_,
                                         *local_cloud,
                                         *input_cloud,
                                         *tf_listener_);
          }
          pcl::PointCloud<pcl::PointNormal>::Ptr
            input_downsampled_cloud (new pcl::PointCloud<pcl::PointNormal>);
          applyDownsampling(input_cloud, *input_downsampled_cloud);
          if (isFirstTime()) {
            all_cloud_ = input_downsampled_cloud;
            first_time_ = false;
          }
          else {
            // run ICP
            ros::ServiceClient client
              = pnh_->serviceClient<jsk_pcl_ros::ICPAlign>("icp_align");
            jsk_pcl_ros::ICPAlign icp_srv;

            if (clip_unseen_pointcloud_) {
              // Before running ICP, remove pointcloud where we cannot see
              // First, transform reference pointcloud, that is all_cloud_, into
              // sensor frame.
              // And after that, remove points which are x < 0.
              tf::StampedTransform global_sensor_tf_transform
                = lookupTransformWithDuration(
                  tf_listener_,
                  global_frame_,
                  sensor_frame_,
                  cloud_msg->header.stamp,
                  ros::Duration(1.0));
              Eigen::Affine3f global_sensor_transform;
              tf::transformTFToEigen(global_sensor_tf_transform,
                                     global_sensor_transform);
              pcl::PointCloud<pcl::PointNormal>::Ptr sensor_cloud
                (new pcl::PointCloud<pcl::PointNormal>);
              pcl::transformPointCloudWithNormals(
                *all_cloud_,
                *sensor_cloud,
                global_sensor_transform.inverse());
              // Remove negative-x points
              pcl::PassThrough<pcl::PointNormal> pass;
              pass.setInputCloud(sensor_cloud);
              pass.setFilterFieldName("x");
              pass.setFilterLimits(0.0, 100.0);
              pcl::PointCloud<pcl::PointNormal>::Ptr filtered_cloud
                (new pcl::PointCloud<pcl::PointNormal>);
              pass.filter(*filtered_cloud);
              JSK_NODELET_INFO("clipping: %lu -> %lu", sensor_cloud->points.size(), filtered_cloud->points.size());
              // Convert the pointcloud to global frame again
              pcl::PointCloud<pcl::PointNormal>::Ptr global_filtered_cloud
                (new pcl::PointCloud<pcl::PointNormal>);
              pcl::transformPointCloudWithNormals(
                *filtered_cloud,
                *global_filtered_cloud,
                global_sensor_transform);
              pcl::toROSMsg(*global_filtered_cloud,
                            icp_srv.request.target_cloud);
            }
            else {
              pcl::toROSMsg(*all_cloud_,
                            icp_srv.request.target_cloud);
            }
            pcl::toROSMsg(*input_downsampled_cloud,
                          icp_srv.request.reference_cloud);
            
            if (client.call(icp_srv)) {
              Eigen::Affine3f transform;
              tf::poseMsgToEigen(icp_srv.response.result.pose, transform);
              Eigen::Vector3f transform_pos(transform.translation());
              float roll, pitch, yaw;
              pcl::getEulerAngles(transform, roll, pitch, yaw);
              JSK_NODELET_INFO("aligned parameter --");
              JSK_NODELET_INFO("  - pos: [%f, %f, %f]",
                           transform_pos[0],
                           transform_pos[1],
                           transform_pos[2]);
              JSK_NODELET_INFO("  - rot: [%f, %f, %f]", roll, pitch, yaw);
              pcl::PointCloud<pcl::PointNormal>::Ptr
                transformed_input_cloud (new pcl::PointCloud<pcl::PointNormal>);
              if (use_normal_) {
                pcl::transformPointCloudWithNormals(*input_cloud,
                                                    *transformed_input_cloud,
                                                    transform);
              }
              else {
                pcl::transformPointCloud(*input_cloud,
                                         *transformed_input_cloud,
                                         transform);
              }
              pcl::PointCloud<pcl::PointNormal>::Ptr
                concatenated_cloud (new pcl::PointCloud<pcl::PointNormal>);
              *concatenated_cloud = *all_cloud_ + *transformed_input_cloud;
              // update *all_cloud
              applyDownsampling(concatenated_cloud, *all_cloud_);
              // update localize_transform_
              tf::Transform icp_transform;
              tf::transformEigenToTF(transform, icp_transform);
              {
                boost::mutex::scoped_lock tf_lock(tf_mutex_);
                localize_transform_ = localize_transform_ * icp_transform;
              }
            }
            else {
              JSK_NODELET_ERROR("Failed to call ~icp_align");
              return;
            }
          }
          localize_requested_ = false;
        }
        else {
          JSK_NODELET_WARN("No tf transformation is available");
        }
      }
      catch (tf2::ConnectivityException &e)
      {
        JSK_NODELET_ERROR("[%s] Transform error: %s", __PRETTY_FUNCTION__, e.what());
        return;
      }
      catch (tf2::InvalidArgumentException &e)
      {
        JSK_NODELET_ERROR("[%s] Transform error: %s", __PRETTY_FUNCTION__, e.what());
        return;
      }
    }
  }
int
main (int argc, char** argv)
{
  // Loading first scan of room.
  pcl::PointCloud<pcl::PointXYZ>::Ptr target_cloud (new pcl::PointCloud<pcl::PointXYZ>);
  if (pcl::io::loadPCDFile<pcl::PointXYZ> ("room_scan1.pcd", *target_cloud) == -1)
  {
    PCL_ERROR ("Couldn't read file room_scan1.pcd \n");
    return (-1);
  }
  std::cout << "Loaded " << target_cloud->size () << " data points from room_scan1.pcd" << std::endl;

  // Loading second scan of room from new perspective.
  pcl::PointCloud<pcl::PointXYZ>::Ptr input_cloud (new pcl::PointCloud<pcl::PointXYZ>);
  if (pcl::io::loadPCDFile<pcl::PointXYZ> ("room_scan2.pcd", *input_cloud) == -1)
  {
    PCL_ERROR ("Couldn't read file room_scan2.pcd \n");
    return (-1);
  }
  std::cout << "Loaded " << input_cloud->size () << " data points from room_scan2.pcd" << std::endl;

  // Filtering input scan to roughly 10% of original size to increase speed of registration.
  pcl::PointCloud<pcl::PointXYZ>::Ptr filtered_cloud (new pcl::PointCloud<pcl::PointXYZ>);
  pcl::ApproximateVoxelGrid<pcl::PointXYZ> approximate_voxel_filter;
  approximate_voxel_filter.setLeafSize (0.2, 0.2, 0.2);
  approximate_voxel_filter.setInputCloud (input_cloud);
  approximate_voxel_filter.filter (*filtered_cloud);
  std::cout << "Filtered cloud contains " << filtered_cloud->size ()
            << " data points from room_scan2.pcd" << std::endl;

  // Initializing Normal Distributions Transform (NDT).
  pcl::NormalDistributionsTransform<pcl::PointXYZ, pcl::PointXYZ> ndt;

  // Setting scale dependent NDT parameters
  // Setting minimum transformation difference for termination condition.
  ndt.setTransformationEpsilon (0.01);
  // Setting maximum step size for More-Thuente line search.
  ndt.setStepSize (0.1);
  //Setting Resolution of NDT grid structure (VoxelGridCovariance).
  ndt.setResolution (1.0);

  // Setting max number of registration iterations.
  ndt.setMaximumIterations (35);

  // Setting point cloud to be aligned.
  ndt.setInputCloud (filtered_cloud);
  // Setting point cloud to be aligned to.
  ndt.setInputTarget (target_cloud);

  // Set initial alignment estimate found using robot odometry.
  Eigen::AngleAxisf init_rotation (0.6931, Eigen::Vector3f::UnitZ ());
  Eigen::Translation3f init_translation (1.79387, 0.720047, 0);
  Eigen::Matrix4f init_guess = (init_translation * init_rotation).matrix ();

  // Calculating required rigid transform to align the input cloud to the target cloud.
  pcl::PointCloud<pcl::PointXYZ>::Ptr output_cloud (new pcl::PointCloud<pcl::PointXYZ>);
  ndt.align (*output_cloud, init_guess);

  std::cout << "Normal Distributions Transform has converged:" << ndt.hasConverged ()
            << " score: " << ndt.getFitnessScore () << std::endl;

  // Transforming unfiltered, input cloud using found transform.
  pcl::transformPointCloud (*input_cloud, *output_cloud, ndt.getFinalTransformation ());

  // Saving transformed input cloud.
  pcl::io::savePCDFileASCII ("room_scan2_transformed.pcd", *output_cloud);

  // Initializing point cloud visualizer
  boost::shared_ptr<pcl::visualization::PCLVisualizer>
  viewer_final (new pcl::visualization::PCLVisualizer ("3D Viewer"));
  viewer_final->setBackgroundColor (0, 0, 0);

  // Coloring and visualizing target cloud (red).
  pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ>
  target_color (target_cloud, 255, 0, 0);
  viewer_final->addPointCloud<pcl::PointXYZ> (target_cloud, target_color, "target cloud");
  viewer_final->setPointCloudRenderingProperties (pcl::visualization::PCL_VISUALIZER_POINT_SIZE,
                                                  1, "target cloud");

  // Coloring and visualizing transformed input cloud (green).
  pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ>
  output_color (output_cloud, 0, 255, 0);
  viewer_final->addPointCloud<pcl::PointXYZ> (output_cloud, output_color, "output cloud");
  viewer_final->setPointCloudRenderingProperties (pcl::visualization::PCL_VISUALIZER_POINT_SIZE,
                                                  1, "output cloud");

  // Starting visualizer
  viewer_final->addCoordinateSystem (1.0);
  viewer_final->initCameraParameters ();

  // Wait until visualizer window is closed.
  while (!viewer_final->wasStopped ())
  {
    viewer_final->spinOnce (100);
    boost::this_thread::sleep (boost::posix_time::microseconds (100000));
  }

  return (0);
}