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);