/TurtleKinect/src/old_clustering/turtle_cluster.cpp

https://github.com/Cognitive-Robotics-Lab/TurtleRPI · C++ · 173 lines · 102 code · 23 blank · 48 comment · 6 complexity · e79aa0452c36104f44a6e8168abd5da5 MD5 · raw file

  1. #include <ros/ros.h>
  2. //From http://pointclouds.org/documentation/tutorials/cluster_extraction.php#cluster-extraction
  3. #include <sensor_msgs/PointCloud2.h>
  4. #include <pcl/ModelCoefficients.h>
  5. #include <pcl/point_types.h>
  6. #include <pcl/filters/extract_indices.h>
  7. #include <pcl/filters/voxel_grid.h>
  8. #include <pcl/features/normal_3d.h>
  9. #include <pcl/kdtree/kdtree.h>
  10. #include <pcl/sample_consensus/method_types.h>
  11. #include <pcl/sample_consensus/model_types.h>
  12. #include <pcl/segmentation/sac_segmentation.h>
  13. #include <pcl/segmentation/extract_clusters.h>
  14. #include <pcl/ros/conversions.h>
  15. #include <pcl/point_cloud.h>
  16. #include <pcl/point_types.h>
  17. #include <pcl/common/impl/centroid.hpp>
  18. #include <stdlib.h>
  19. #include <sstream>
  20. #include <dynamic_reconfigure/server.h>
  21. #include <TurtleKinect/ClusterConfig.h>
  22. #include <geometry_msgs/PoseArray.h>
  23. #include <geometry_msgs/PoseStamped.h>
  24. //publishers
  25. ros::Publisher pose_pub;
  26. ros::Publisher cloud_pub;
  27. //params
  28. float ClusterTolerance;
  29. int MinClusterSize;
  30. int MaxClusterSize;
  31. void cloud_cb (sensor_msgs::PointCloud2ConstPtr input) {
  32. pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered (new pcl::PointCloud<pcl::PointXYZ>);
  33. pcl::fromROSMsg (*input, *cloud_filtered);
  34. std::cout << "Input pointCloud has: " << cloud_filtered->points.size () << " data points." << std::endl; //*
  35. // Create the segmentation object for the planar model and set all the parameters
  36. /*pcl::SACSegmentation<pcl::PointXYZ> seg;
  37. pcl::PointIndices::Ptr inliers (new pcl::PointIndices);
  38. pcl::ModelCoefficients::Ptr coefficients (new pcl::ModelCoefficients);
  39. pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_plane (new pcl::PointCloud<pcl::PointXYZ> ());
  40. seg.setOptimizeCoefficients (true);
  41. seg.setModelType (pcl::SACMODEL_PLANE);
  42. seg.setMethodType (pcl::SAC_RANSAC);
  43. seg.setMaxIterations (100);
  44. seg.setDistanceThreshold (0.02);
  45. pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_f (new pcl::PointCloud<pcl::PointXYZ>);
  46. int i=0, nr_points = (int) cloud_filtered->points.size ();
  47. while (cloud_filtered->points.size () > 0.3 * nr_points)
  48. {
  49. // Segment the largest planar component from the remaining cloud
  50. seg.setInputCloud (cloud_filtered);
  51. seg.segment (*inliers, *coefficients);
  52. if (inliers->indices.size () == 0)
  53. {
  54. std::cout << "Could not estimate a planar model for the given dataset." << std::endl;
  55. break;
  56. }
  57. // Extract the planar inliers from the input cloud
  58. pcl::ExtractIndices<pcl::PointXYZ> extract;
  59. extract.setInputCloud (cloud_filtered);
  60. extract.setIndices (inliers);
  61. extract.setNegative (false);
  62. // Write the planar inliers to disk
  63. extract.filter (*cloud_plane);
  64. //std::cout << "PointCloud representing the planar component: " << cloud_plane->points.size () << " data points." << std::endl;
  65. // Remove the planar inliers, extract the rest
  66. extract.setNegative (true);
  67. extract.filter (*cloud_f);
  68. cloud_filtered = cloud_f;
  69. }*/
  70. // Creating the KdTree object for the search method of the extraction
  71. pcl::search::KdTree<pcl::PointXYZ>::Ptr tree (new pcl::search::KdTree<pcl::PointXYZ>);
  72. tree->setInputCloud (cloud_filtered);
  73. std::vector<pcl::PointIndices> cluster_indices;
  74. pcl::EuclideanClusterExtraction<pcl::PointXYZ> ec;
  75. ec.setClusterTolerance (ClusterTolerance); // 2cm
  76. ec.setMinClusterSize (MinClusterSize);
  77. ec.setMaxClusterSize (MaxClusterSize);
  78. ec.setSearchMethod (tree);
  79. ec.setInputCloud (cloud_filtered);
  80. ec.extract (cluster_indices);
  81. pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud_clustered (new pcl::PointCloud<pcl::PointXYZRGB>);
  82. std::vector<Eigen::Vector4f> centroids;
  83. std::cout << "\t\t" << cluster_indices.size() << "Clusters:" ;
  84. int j = 0;
  85. for (std::vector<pcl::PointIndices>::const_iterator it = cluster_indices.begin (); it != cluster_indices.end (); ++it)
  86. {
  87. pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud_cluster (new pcl::PointCloud<pcl::PointXYZRGB>);
  88. uint8_t r = rand()%255, g = rand()%255, b = rand()%255;
  89. for (std::vector<int>::const_iterator pit = it->indices.begin (); pit != it->indices.end (); pit++) {
  90. pcl::PointXYZRGB p(r,g,b);
  91. p.x = cloud_filtered->points[*pit].x;
  92. p.y = cloud_filtered->points[*pit].y;
  93. p.z = cloud_filtered->points[*pit].z;
  94. cloud_cluster->points.push_back (p); //*
  95. }
  96. cloud_cluster->width = cloud_cluster->points.size ();
  97. cloud_cluster->height = 1;
  98. cloud_cluster->is_dense = true;
  99. std::cout << cloud_cluster->points.size () ;
  100. stringstream ss; ss << ":(" << (int)r << "," << (int)g << ","<< (int)b << ")";
  101. std::cout << ss.str() << " , ";
  102. Eigen::Vector4f centroid;
  103. pcl::compute3DCentroid(*cloud_cluster,centroid);
  104. centroids.push_back(centroid);
  105. *cloud_clustered += *cloud_cluster;
  106. j++;
  107. }
  108. std::cout << std::endl;
  109. geometry_msgs::PoseArray poses;
  110. poses.header.stamp = ros::Time::now();
  111. poses.header.frame_id = "/camera_rgb_optical_frame";
  112. for (std::vector<Eigen::Vector4f>::const_iterator it = centroids.begin (); it != centroids.end (); ++it) {
  113. geometry_msgs::Pose pose;
  114. pose.position.x = it->x();
  115. pose.position.y = it->y();
  116. pose.position.z = it->z();
  117. poses.poses.push_back(pose);
  118. }
  119. pose_pub.publish (poses);
  120. sensor_msgs::PointCloud2 output;
  121. pcl::toROSMsg (*cloud_clustered , output);
  122. output.header.stamp = ros::Time::now();
  123. output.header.frame_id = "/camera_rgb_optical_frame";
  124. // Publish the data
  125. cloud_pub.publish (output);
  126. }
  127. void config_callback(TurtleKinect::ClusterConfig &config, uint32_t level) {
  128. ClusterTolerance = config.ClusterTolerance;
  129. MinClusterSize = config.MinClusterSize;
  130. MaxClusterSize = config.MaxClusterSize;
  131. }
  132. int main (int argc, char** argv) {
  133. // Initialize ROS
  134. ros::init (argc, argv, "turtle_cluster");
  135. ros::NodeHandle nh("~");
  136. dynamic_reconfigure::Server<TurtleKinect::ClusterConfig> server;
  137. dynamic_reconfigure::Server<TurtleKinect::ClusterConfig>::CallbackType f = boost::bind(&config_callback, _1, _2);
  138. server.setCallback(f);
  139. // Create a ROS subscriber for the input point cloud
  140. ros::Subscriber sub = nh.subscribe ("input", 1, cloud_cb);
  141. // Create a ROS publisher for the output point cloud
  142. cloud_pub = nh.advertise<sensor_msgs::PointCloud2> ("output", 1);
  143. pose_pub = nh.advertise<geometry_msgs::PoseArray> ("centroids", 1);
  144. // Spin
  145. ros::spin ();
  146. }