00001 
00063 #include <sstream>
00064 
00065 
00066 #include <ros/ros.h>
00067 #include <pluginlib/class_list_macros.h>
00068 #include <boost/make_shared.hpp>
00069 
00070 #include <pcl/io/io.h>
00071 #include <pcl/io/pcd_io.h>
00072   #ifdef PCL_VERSION_COMPARE //fuerte
00073     #include <pcl/for_each_type.h>
00074   #else //electric
00075     #include <pcl/ros/for_each_type.h>
00076   #endif
00077 
00078 #include <pcl_ros/point_cloud.h>
00079 #include <pcl_conversions/pcl_conversions.h>
00080 
00081 
00082 #include <cob_3d_mapping_msgs/ShapeArray.h>
00083 #include <cob_3d_mapping_common/cylinder.h>
00084 #include <cob_3d_mapping_common/ros_msg_conversions.h>
00085 #include <cob_3d_mapping_common/stop_watch.h>
00086 #include "cob_3d_segmentation/segmentation_all_in_one_nodelet.h"
00087 
00088 
00089 void
00090 cob_3d_segmentation::SegmentationAllInOneNodelet::onInit()
00091 {
00092   nh_ = getNodeHandle();
00093 
00094   config_server_.reset(new dynamic_reconfigure::Server<segmentation_nodeletConfig>(getPrivateNodeHandle()));
00095   config_server_->setCallback(boost::bind(&SegmentationAllInOneNodelet::configCallback, this, _1, _2));
00096 
00097   one_.setOutputLabels(labels_);
00098   one_.setPixelSearchRadius(8,2,2);
00099   one_.setSkipDistantPointThreshold(8);
00100 
00101   seg_.setNormalCloudIn(normals_);
00102   seg_.setLabelCloudInOut(labels_);
00103   seg_.setClusterGraphOut(graph_);
00104 
00105   cc_.setClusterHandler(graph_->clusters());
00106   cc_.setNormalCloudInOut(normals_);
00107   cc_.setLabelCloudIn(labels_);
00108 
00109   if(!is_running_ && !enable_action_mode_)
00110   {
00111     ROS_INFO("Starting segmentation...");
00112     sub_points_ = nh_.subscribe("cloud_in", 1, &SegmentationAllInOneNodelet::receivedCloudCallback, this);
00113     is_running_ = true;
00114   }
00115   pub_segmented_ = nh_.advertise<PointCloud>("/segmentation/segmented_cloud", 1);
00116   pub_classified_ = nh_.advertise<PointCloud>("/segmentation/classified_cloud", 1);
00117   pub_shape_array_ = nh_.advertise<cob_3d_mapping_msgs::ShapeArray>("/segmentation/shape_array",1);
00118   pub_chull_ = nh_.advertise<PointCloud>("/segmentation/concave_hull", 1);
00119   pub_chull_dense_ = nh_.advertise<PointCloud>("/segmentation/concave_hull_dense", 1);
00120   std::cout << "Loaded segmentation nodelet" << std::endl;
00121 
00122   as_ = new actionlib::SimpleActionServer<cob_3d_mapping_msgs::TriggerAction>(nh_, "segmentation/trigger", boost::bind(&SegmentationAllInOneNodelet::actionCallback, this, _1), false);
00123   as_->start();
00124 }
00125 
00126 void
00127 cob_3d_segmentation::SegmentationAllInOneNodelet::configCallback(
00128     cob_3d_segmentation::segmentation_nodeletConfig& config,
00129     uint32_t level)
00130 {
00131   NODELET_INFO("[segmentation]: received new parameters");
00132   centroid_passthrough_ = config.centroid_passthrough;
00133   enable_action_mode_ = config.enable_action_mode;
00134 }
00135 
00136 
00137 void
00138 cob_3d_segmentation::SegmentationAllInOneNodelet::actionCallback(
00139   const cob_3d_mapping_msgs::TriggerGoalConstPtr& goal)
00140 {
00141   cob_3d_mapping_msgs::TriggerResult result;
00142   if(goal->start && !is_running_)
00143   {
00144     ROS_INFO("Starting segmentation...");
00145     sub_points_ = nh_.subscribe("cloud_in", 1, &SegmentationAllInOneNodelet::receivedCloudCallback, this);
00146     is_running_ = true;
00147   }
00148   else if(!goal->start && is_running_)
00149   {
00150     ROS_INFO("Stopping segmentation...");
00151     sub_points_.shutdown();
00152     is_running_ = false;
00153   }
00154 
00155   as_->setSucceeded(result);
00156 }
00157 
00158 
00159 void
00160 cob_3d_segmentation::SegmentationAllInOneNodelet::receivedCloudCallback(PointCloud::ConstPtr cloud)
00161 {
00162   PrecisionStopWatch t;
00163   t.precisionStart();
00164   NODELET_INFO("Start with segmentation .... ");
00165   one_.setInputCloud(cloud);
00166   one_.compute(*normals_);
00167 
00168   *classified_ = *segmented_ = *cloud;
00169 
00170   seg_.setInputCloud(cloud);
00171   seg_.performInitialSegmentation();
00172   seg_.refineSegmentation();
00173   graph_->clusters()->mapClusterColor(segmented_);
00174 
00175   
00176   
00177   NODELET_INFO("Done with segmentation .... ");
00178 
00179 
00180   cc_.setPointCloudIn(cloud);
00181   cc_.classify();
00182   graph_->clusters()->mapTypeColor(classified_);
00183   graph_->clusters()->mapClusterBorders(classified_);
00184   std::cout << "segmentation took " << t.precisionStop() << " s." << std::endl;
00185   
00186   pub_segmented_.publish(segmented_);
00187   
00188   pub_classified_.publish(classified_);
00189   
00190   
00191 
00192 
00193 
00194 
00195 
00196 
00197 
00198   publishShapeArray(graph_->clusters(), cloud);
00199 
00200   NODELET_INFO("Done with publishing .... ");
00201 
00202 }
00203 
00204 void
00205 cob_3d_segmentation::SegmentationAllInOneNodelet::publishShapeArray(
00206   ST::CH::Ptr cluster_handler, PointCloud::ConstPtr cloud)
00207 {
00208   cob_3d_mapping_msgs::ShapeArray sa;
00209   pcl_conversions::fromPCL(cloud->header, sa.header);
00210   
00211   
00212   
00213   pcl::PointCloud<pcl::PointXYZRGB>::Ptr hull_cloud(new pcl::PointCloud<pcl::PointXYZRGB>);
00214   pcl::PointCloud<pcl::PointXYZRGB>::Ptr hull(new pcl::PointCloud<pcl::PointXYZRGB>);
00215   pcl::PointCloud<pcl::PointXYZRGB>::Ptr hull_cloud_dense(new pcl::PointCloud<pcl::PointXYZRGB>);
00216 
00217   unsigned int id = 0;
00218   for (ST::CH::ClusterPtr c = cluster_handler->begin(); c != cluster_handler->end(); ++c)
00219   {
00220     
00221     if (c->getCentroid()[2] > centroid_passthrough_) continue;
00222     if (c->type != I_PLANE && c->type != I_CYL) continue;
00223     if (c->size() <= ceil(1.1f * static_cast<float>(c->border_points.size())))
00224     {
00225       
00226       continue;
00227     }
00228 
00229     for (size_t i = 0; i < c->border_points.size(); ++i)
00230       hull_cloud_dense->push_back((*segmented_)[c->border_points[i].y * segmented_->width + c->border_points[i].x]);
00231 
00232     PolygonContours<PolygonPoint> poly;
00233     
00234     pe_.outline(cloud->width, cloud->height, c->border_points, poly);
00235     if (!poly.polys_.size()) continue; 
00236     
00237 
00238     int max_idx=0, max_size=0;
00239     
00240     for (int i = 0; i < (int)poly.polys_.size(); ++i)
00241     {
00242       
00243       if ((int)poly.polys_[i].size() > max_size) { max_idx = i; max_size = poly.polys_[i].size(); }
00244     }
00245     
00246 
00247     sa.shapes.push_back(cob_3d_mapping_msgs::Shape());
00248     cob_3d_mapping_msgs::Shape* s = &sa.shapes.back();
00249     
00250     
00251     s->header.frame_id = cloud->header.frame_id.c_str();
00252     Eigen::Vector3f color_tmp = c->computeDominantColorVector().cast<float>();
00253     float temp_inv = 1.0f/255.0f;
00254     std::vector<float> color(4,1);
00255     color[0] = color_tmp(0) * temp_inv;
00256     color[1] = color_tmp(1) * temp_inv;
00257     color[2] = color_tmp(2) * temp_inv;
00258     
00259 
00260 
00261 
00262     
00263     
00264     
00265 
00266 
00267 
00268 
00269 
00270 
00271 
00272 
00273 
00274 
00275 
00276 
00277 
00278 
00279 
00280 
00281 
00282 
00283 
00284 
00285 
00286 
00287 
00288 
00289 
00290 
00291 
00292 
00293 
00294     
00295 
00296 
00297 
00298     
00299 
00300 
00301 
00302     std::vector<pcl::PointCloud<pcl::PointXYZ> > contours_3d;
00303     std::vector<bool> holes;
00304     
00305     for (int i = 0; i < (int)poly.polys_.size(); ++i)
00306     {
00307       pcl::PointCloud<pcl::PointXYZ> contour;
00308       if (i == max_idx)
00309       {
00310         holes.push_back(false);
00311         std::vector<PolygonPoint>::iterator it = poly.polys_[i].begin();
00312         for ( ; it != poly.polys_[i].end(); ++it) {
00313           pcl::PointXYZ pt;
00314           pt.getVector3fMap() = cloud->points[ it->x + it->y * cloud->width ].getVector3fMap();
00315           contour.push_back( pt );
00316           
00317         }
00318       }
00319       else
00320       {
00321         holes.push_back(true);
00322         std::vector<PolygonPoint>::reverse_iterator it = poly.polys_[i].rbegin();
00323         for ( ; it != poly.polys_[i].rend(); ++it) {
00324           pcl::PointXYZ pt;
00325           pt.getVector3fMap() = cloud->points[ it->x + it->y * cloud->width ].getVector3fMap();
00326           contour.push_back( pt );
00327           
00328         }
00329       }
00330       contour.height = 1;
00331       contour.width = contour.size();
00332       contours_3d.push_back(contour);
00333       
00334       
00335     }
00336 
00337     
00338     switch(c->type)
00339     {
00340     case I_PLANE:
00341     {
00342       cob_3d_mapping::Polygon::Ptr  poly(new cob_3d_mapping::Polygon(id,
00343                                                                      c->pca_point_comp3,
00344                                                                      c->getCentroid(),
00345                                                                      contours_3d,
00346                                                                      holes,
00347                                                                      color));
00348       cob_3d_mapping::toROSMsg(*poly, *s);
00349       
00350       
00351 
00352 
00353 
00354 
00355 
00356 
00357 
00358       break;
00359     }
00360     case I_CYL:
00361     {
00362       
00363 
00364 
00365 
00366 
00367 
00368 
00369       
00370       
00371       
00372       Eigen::Vector3f origin = c->getCentroid();
00373       double radius = cob_3d_mapping::radiusAndOriginFromCloud(cloud, c->indices_, origin, c->pca_inter_comp1);
00374       cob_3d_mapping::Cylinder::Ptr cyl = cob_3d_mapping::Cylinder::Ptr(new cob_3d_mapping::Cylinder(id,
00375                                                                                                       origin,
00376                                                                                                       c->pca_inter_comp1,
00377                                                                                                       radius,
00378                                                                                                       contours_3d,
00379                                                                                                       holes,
00380                                                                                                       color));
00381       
00382       
00383 
00384       
00385       
00386       
00387       
00388       
00389       
00390 
00391       cob_3d_mapping::toROSMsg(*cyl, *s);
00392       
00393       
00394       
00395 
00396 
00397 
00398 
00399 
00400 
00401 
00402 
00403 
00404 
00405 
00406 
00407 
00408 
00409       break;
00410     }
00411     default:
00412     {
00413       break;
00414     }
00415     }
00416     id++;
00417     
00418 
00419 
00420 
00421 
00422 
00423   }
00424   hull_cloud->header = cloud->header;
00425   hull_cloud->height = 1;
00426   hull_cloud->width = hull_cloud->size();
00427   hull_cloud_dense->header = cloud->header;
00428   hull_cloud_dense->height = 1;
00429   hull_cloud_dense->width = hull_cloud_dense->size();
00430   pub_chull_.publish(hull_cloud);
00431   pub_chull_dense_.publish(hull_cloud_dense);
00432   pub_shape_array_.publish(sa);
00433   
00434 }
00435 
00436 
00437 PLUGINLIB_DECLARE_CLASS(cob_3d_segmentation, SegmentationAllInOneNodelet, cob_3d_segmentation::SegmentationAllInOneNodelet, nodelet::Nodelet);