00001
00002
00003
00004
00005
00006
00007
00008 #include <perception_tools/segmentation/SphereSegmentation.h>
00009 #include <tf_conversions/tf_eigen.h>
00010 #include <sensor_msgs/PointCloud2.h>
00011 #include <sensor_msgs/point_cloud_conversion.h>
00012 #include <boost/assign.hpp>
00013 #include <boost/shared_ptr.hpp>
00014 #include <boost/make_shared.hpp>
00015 #include <pcl/common/transforms.h>
00016 #include <pcl/surface/convex_hull.h>
00017 #include <pcl/segmentation/extract_clusters.h>
00018 #include <pcl/filters/passthrough.h>
00019 #include <pcl/filters/project_inliers.h>
00020 #include <pcl/filters/extract_indices.h>
00021 #include <pcl/segmentation/extract_polygonal_prism_data.h>
00022 #include <cmath>
00023
00024
00025 SphereSegmentation::SphereSegmentation()
00026 :_Parameters(),
00027 _LastSphereSegCluster(),
00028 _LastCoefficients(),
00029 _LastIndices(),
00030 _LastSphereSegSuccess(false)
00031 {
00032
00033
00034 }
00035
00036 SphereSegmentation::~SphereSegmentation() {
00037
00038 }
00039
00040 void SphereSegmentation::setParameters(const SphereSegmentation::Parameters ¶meters)
00041 {
00042 _Parameters = parameters;
00043 }
00044
00045 SphereSegmentation::Parameters SphereSegmentation::getParameters()
00046 {
00047 return _Parameters;
00048 }
00049
00050 void SphereSegmentation::fetchParameters(std::string nameSpace)
00051 {
00052 _Parameters.fetchParameters(nameSpace);
00053 }
00054
00055 bool SphereSegmentation::segment(const sensor_msgs::PointCloud &cloudMsg,arm_navigation_msgs::CollisionObject &obj)
00056 {
00057
00058 sensor_msgs::PointCloud2 intermediateCloudMsg;
00059 sensor_msgs::convertPointCloudToPointCloud2(cloudMsg,intermediateCloudMsg);
00060 return segment(intermediateCloudMsg,obj);
00061 }
00062
00063 void SphereSegmentation::getSphereCluster(sensor_msgs::PointCloud &cluster)
00064 {
00065 if(_LastSphereSegSuccess)
00066 {
00067 cluster.points.clear();
00068 sensor_msgs::PointCloud2 tempCloud;
00069 pcl::toROSMsg(_LastSphereSegCluster,tempCloud);
00070 sensor_msgs::convertPointCloud2ToPointCloud(tempCloud,cluster);
00071 }
00072 }
00073
00074 bool SphereSegmentation::segment(const sensor_msgs::PointCloud2 &cloudMsg,arm_navigation_msgs::CollisionObject &obj)
00075 {
00076
00077 Cloud3D cluster = Cloud3D();
00078
00079
00080 pcl::fromROSMsg(cloudMsg,cluster);
00081
00082 return segment(cluster,obj);
00083 }
00084
00085 bool SphereSegmentation::segment(const std::vector<sensor_msgs::PointCloud> &clusters, arm_navigation_msgs::CollisionObject &obj,
00086 int &bestClusterIndex)
00087 {
00088
00089 double score = 0.0f;
00090 bool success = false;
00091 arm_navigation_msgs::CollisionObject currentObj;
00092 Cloud3D bestCluster;
00093 pcl::PointIndices bestIndices;
00094 pcl::ModelCoefficients bestCoefficients;
00095 bool bestSeg;
00096
00097 for(unsigned int i = 0; i < clusters.size(); i++)
00098 {
00099 success = segment(clusters[i],currentObj);
00100 if(success)
00101 {
00102 if(_LastSegmentationScore > score)
00103 {
00104 bestClusterIndex = i;
00105 obj.header.frame_id = currentObj.header.frame_id;
00106 obj.id = currentObj.id;
00107 obj.poses = currentObj.poses;
00108 obj.padding = currentObj.padding;
00109 obj.shapes = currentObj.shapes;
00110 bestCluster = _LastSphereSegCluster;
00111 bestIndices = _LastIndices;
00112 bestCoefficients = _LastCoefficients;
00113 score = _LastSegmentationScore;
00114
00115 }
00116 }
00117 }
00118
00119
00120 _LastSphereSegCluster = bestCluster;
00121 _LastIndices = bestIndices;
00122 _LastCoefficients = bestCoefficients;
00123 _LastSphereSegSuccess = success;
00124
00125 return success;
00126 }
00127
00128 bool SphereSegmentation::segment(const Cloud3D &cluster,arm_navigation_msgs::CollisionObject &obj)
00129 {
00130 std::string nodeName = ros::this_node::getName() + "/segmentation";
00131
00132
00133 Cloud3D cloud = Cloud3D();
00134 pcl::copyPointCloud(cluster,cloud);
00135
00136
00137 tf::StampedTransform clusterInWorld; clusterInWorld.setIdentity();
00138 std::string clusterFrameId = cloud.header.frame_id;
00139
00140 try
00141 {
00142 _TfListener.lookupTransform(_Parameters.WorldFrameId,clusterFrameId,ros::Time(0),clusterInWorld);
00143 }
00144 catch(tf::TransformException ex)
00145 {
00146 ROS_ERROR("%s",std::string(nodeName + " , failed to resolve transform from " +
00147 _Parameters.WorldFrameId + " to " + clusterFrameId + " \n\t\t" + " tf error msg: " + ex.what()).c_str());
00148 ROS_WARN("%s",std::string(nodeName + ": Will use Identity as cluster transform").c_str());
00149 }
00150
00151
00152 Eigen::Affine3d tfEigen;
00153 tf::TransformTFToEigen(clusterInWorld,tfEigen);
00154 pcl::transformPointCloud(cloud,cloud,Eigen::Affine3f(tfEigen));
00155
00156
00157
00158
00159
00160 bool centroidFound = false;
00161 pcl::PointXYZ topCentroid;
00162 centroidFound = findTopCentroid(cloud,topCentroid);
00163
00164
00165 if(centroidFound)
00166 {
00167 filterWithPolygonalPrism(cloud,topCentroid,20,_Parameters.MaxRadius,1.5f*_Parameters.MaxRadius,0.0f);
00168 ROS_INFO_STREAM(nodeName<<": Polygonal prism extraction found "<< cloud.points.size()<<" points");
00169 }
00170 else
00171 {
00172 ROS_WARN_STREAM(nodeName<<": did not find top centroid, skipping polygonal prism extraction");
00173 }
00174
00175
00176 pcl::ModelCoefficients::Ptr coefficients(new pcl::ModelCoefficients());
00177 pcl::PointIndices::Ptr inliers(new pcl::PointIndices());
00178
00179 if(!performSphereSegmentation(cloud,coefficients,inliers))
00180 {
00181
00182
00183 _LastIndices = pcl::PointIndices();
00184 _LastCoefficients = pcl::ModelCoefficients();
00185 _LastSphereSegCluster.clear();
00186 _LastSphereSegSuccess = false;
00187
00188 ROS_ERROR_STREAM(nodeName<<": insufficient inliers found "<<inliers->indices.size()<<", exiting segmentation");
00189
00190 return false;
00191 }
00192 else
00193 {
00194 ROS_INFO_STREAM(nodeName<<": found "<<inliers->indices.size()<<" total inliers");
00195
00196
00197 pcl::ExtractIndices<pcl::PointXYZ> extract;
00198 extract.setIndices(inliers);
00199 extract.setInputCloud(boost::make_shared<Cloud3D>(cloud));
00200 extract.setNegative(false);
00201 _LastSphereSegCluster.clear();
00202 extract.filter(_LastSphereSegCluster);
00203 _LastSphereSegCluster.header = cloud.header;
00204
00205
00206 _LastIndices = *inliers;
00207 _LastCoefficients = *coefficients;
00208 _LastSphereSegSuccess = true;
00209 }
00210
00211 if(_Parameters.AlignToTopCentroid && centroidFound)
00212 {
00213 coefficients->values[0] = topCentroid.x;
00214 coefficients->values[1] = topCentroid.y;
00215 coefficients->values[2] = topCentroid.z - coefficients->values[3];
00216 ROS_INFO_STREAM(nodeName<<": Aligned to top centroid");
00217 }
00218 else
00219 {
00220 ROS_WARN_STREAM(nodeName<<": did not find top centroid");
00221 }
00222
00223 ROS_INFO_STREAM(nodeName<<": segmentation succeeded");
00224 createObject(*coefficients,obj);
00225
00226 return true;
00227 }
00228
00229 bool SphereSegmentation::performSphereSegmentation(const Cloud3D &cloud,pcl::ModelCoefficients::Ptr coefficients,
00230 pcl::PointIndices::Ptr inliers)
00231 {
00232 using namespace pcl;
00233
00234
00235 NormalEstimation<PointXYZ,Normal> normalEstm;
00236 SACSegmentationFromNormals<PointXYZ,Normal> seg;
00237 ExtractIndices<PointXYZ> extractPoints;
00238 ExtractIndices<Normal> extractNormals;
00239 pcl::search::KdTree<PointXYZ>::Ptr searchTree = boost::make_shared< pcl::search::KdTree<PointXYZ> >();
00240
00241
00242 PointCloud<Normal>::Ptr cloudNormals(new PointCloud<Normal>());
00243 Cloud3D::Ptr cloudPtr = boost::make_shared<Cloud3D>(cloud);
00244
00245
00246 normalEstm.setSearchMethod(searchTree);
00247 normalEstm.setInputCloud(cloudPtr);
00248 normalEstm.setKSearch(_Parameters.KNearestNeighbors);
00249 normalEstm.compute(*cloudNormals);
00250
00251
00252 seg.setOptimizeCoefficients(true);
00253 seg.setModelType(SACMODEL_SPHERE);
00254 seg.setMethodType(SAC_RANSAC);
00255 seg.setNormalDistanceWeight(_Parameters.NormalDistanceWeight);
00256 seg.setMaxIterations(_Parameters.MaxIterations);
00257 seg.setDistanceThreshold(_Parameters.DistanceThreshold);
00258 seg.setRadiusLimits(0.0f,_Parameters.MaxRadius);
00259 seg.setInputCloud(cloudPtr);
00260 seg.setInputNormals(cloudNormals);
00261 seg.segment(*inliers,*coefficients);
00262
00263
00264
00265 _LastSegmentationScore = (double)inliers->indices.size();
00266
00267 if(inliers->indices.size() == 0 || _LastSegmentationScore < _Parameters.MinFitnessScore)
00268 {
00269
00270 return false;
00271 }
00272 else
00273 {
00274 return true;
00275 }
00276 }
00277
00278 bool SphereSegmentation::findSphereUsingTopPoint(const Cloud3D &cloud,pcl::ModelCoefficients::Ptr coefficients,
00279 pcl::PointIndices::Ptr inliers)
00280 {
00281 std::string nodeName = ros::this_node::getName() + "/segmentation";
00282 std::stringstream stdOut;
00283
00284 pcl::PointXYZ centroid;
00285 if(!findTopCentroid(cloud,centroid))
00286 {
00287 return false;
00288 }
00289
00290
00291 coefficients->values.clear();
00292 coefficients->values.push_back(centroid.x);
00293 coefficients->values.push_back(centroid.y);
00294 coefficients->values.push_back(centroid.z - _Parameters.MaxRadius);
00295 coefficients->values.push_back(_Parameters.MaxRadius);
00296
00297 stdOut << nodeName << ": Found sphere center at: x = " << coefficients->values[0] <<
00298 ", y = " << coefficients->values[1] << ", z = " << coefficients->values[2];
00299 ROS_INFO("%s",stdOut.str().c_str());stdOut.str("");
00300
00301 return true;
00302
00303 }
00304
00305 bool SphereSegmentation::findTopCentroid(const Cloud3D &cloud,pcl::PointXYZ &topCentroid)
00306 {
00307 std::string nodeName = ros::this_node::getName() + "/segmentation";
00308 std::stringstream stdOut;
00309
00310
00311 pcl::PointXYZ pointMax, pointMin;
00312 pcl::getMinMax3D(cloud,pointMin,pointMax);
00313
00314
00315 double maxZ = pointMax.z;
00316 ROS_INFO_STREAM(nodeName << ": Found Min Point at x: "<<pointMin.x<<", y: "<<pointMin.y<<", z: " << pointMin.z);
00317 ROS_INFO_STREAM(nodeName<< ": Found Max Point at x: "<<pointMax.x<<", y: "<<pointMax.y<<", z: " << maxZ);
00318
00319
00320
00321 Cloud3D::Ptr planeCloud = boost::make_shared<Cloud3D>();
00322 pcl::PassThrough<pcl::PointXYZ> passFilter;
00323 passFilter.setInputCloud(boost::make_shared<Cloud3D>(cloud));
00324 passFilter.setFilterFieldName("z");
00325 passFilter.setFilterLimits(maxZ - std::abs(_Parameters.DistanceThreshold),
00326 maxZ + std::abs(_Parameters.DistanceThreshold));
00327 passFilter.filter(*planeCloud);
00328 if(planeCloud->size() > 0)
00329 {
00330 stdOut << nodeName << ": Found " << planeCloud->size()<<" points at a proximity of "
00331 <<_Parameters.DistanceThreshold << " to top plane";
00332 ROS_INFO("%s",stdOut.str().c_str());stdOut.str("");
00333
00334 }
00335 else
00336 {
00337 stdOut<<nodeName<< ": Found no points on top plane, canceling segmentation";
00338 ROS_INFO("%s",stdOut.str().c_str());stdOut.str("");
00339 return false;
00340 }
00341
00342
00343
00344
00345 tf::Vector3 normal = tf::Vector3(0.0f,0.0f,1.0f);
00346 double offset = -normal.dot(tf::Vector3(0.0f,0.0f,maxZ));
00347 pcl::ModelCoefficients::Ptr planeCoeffs = boost::make_shared<pcl::ModelCoefficients>();
00348 planeCoeffs->values.resize(4);
00349 planeCoeffs->values[0] = normal.getX();
00350 planeCoeffs->values[1] = normal.getY();
00351 planeCoeffs->values[2] = normal.getZ();
00352 planeCoeffs->values[3] = offset;
00353 stdOut << nodeName << ": Created Top Plane with planeCoeffs: " << planeCoeffs->values[0]
00354 << ", " << planeCoeffs->values[1] << ", " << planeCoeffs->values[2] << ", " << planeCoeffs->values[3];
00355 ROS_INFO("%s",stdOut.str().c_str());stdOut.str("");
00356
00357
00358 Cloud3D::Ptr projectedCloud = boost::make_shared<Cloud3D>();
00359 pcl::ProjectInliers<pcl::PointXYZ> projectObj;
00360 projectObj.setModelType(pcl::SACMODEL_PLANE);
00361 projectObj.setInputCloud(planeCloud);
00362 projectObj.setModelCoefficients(planeCoeffs);
00363 projectObj.filter(*projectedCloud);
00364
00365
00366
00367
00368
00369
00370 if(_Parameters.MaxRadius > 0)
00371 {
00372 bool continueSearch = true;
00373 unsigned int index = 0;
00374 pcl::search::KdTree<pcl::PointXYZ>::Ptr searchTree = boost::make_shared<pcl::search::KdTree<pcl::PointXYZ> >();
00375 std::vector<int> indices;
00376 std::vector<float> sqDistances;
00377 searchTree->setInputCloud(projectedCloud);
00378
00379 while(continueSearch)
00380 {
00381 int found = searchTree->radiusSearch(projectedCloud->points[index],
00382 _Parameters.MaxRadius,indices,sqDistances);
00383
00384 if(found > 0)
00385 {
00386 continueSearch = false;
00387 }
00388 else
00389 {
00390 index++; std::string nodeName = ros::this_node::getName();
00391 std::stringstream stdOut;
00392
00393
00394 pcl::PointXYZ pointMax, pointMin;
00395 pcl::getMinMax3D(cloud,pointMin,pointMax);
00396
00397
00398 double maxZ = pointMax.z;
00399 ROS_INFO_STREAM(nodeName << ": Found Min Point at x: "<<pointMin.x<<", y: "<<pointMin.y<<", z: " << pointMin.z);
00400 ROS_INFO_STREAM(nodeName<< ": Found Max Point at x: "<<pointMax.x<<", y: "<<pointMax.y<<", z: " << maxZ);
00401
00402
00403
00404 Cloud3D::Ptr planeCloud = boost::make_shared<Cloud3D>();
00405 pcl::PassThrough<pcl::PointXYZ> passFilter;
00406 passFilter.setInputCloud(boost::make_shared<Cloud3D>(cloud));
00407 passFilter.setFilterFieldName("z");
00408 passFilter.setFilterLimits(maxZ - std::abs(_Parameters.DistanceThreshold),
00409 maxZ + std::abs(_Parameters.DistanceThreshold));
00410 passFilter.filter(*planeCloud);
00411 if(planeCloud->size() > 0)
00412 {
00413 stdOut << nodeName << ": Found " << planeCloud->size()<<" points at a proximity of "
00414 <<_Parameters.DistanceThreshold << " to top plane";
00415 ROS_INFO("%s",stdOut.str().c_str());stdOut.str("");
00416
00417 }
00418 else
00419 {
00420 stdOut<<nodeName<< ": Found no points on top plane, canceling segmentation";
00421 ROS_INFO("%s",stdOut.str().c_str());stdOut.str("");
00422 return false;
00423 }
00424
00425
00426
00427
00428 tf::Vector3 normal = tf::Vector3(0.0f,0.0f,1.0f);
00429 double offset = -normal.dot(tf::Vector3(0.0f,0.0f,maxZ));
00430 pcl::ModelCoefficients::Ptr planeCoeffs = boost::make_shared<pcl::ModelCoefficients>();
00431 planeCoeffs->values.resize(4);
00432 planeCoeffs->values[0] = normal.getX();
00433 planeCoeffs->values[1] = normal.getY();
00434 planeCoeffs->values[2] = normal.getZ();
00435 planeCoeffs->values[3] = offset;
00436 stdOut << nodeName << ": Created Top Plane with planeCoeffs: " << planeCoeffs->values[0]
00437 << ", " << planeCoeffs->values[1] << ", " << planeCoeffs->values[2] << ", " << planeCoeffs->values[3];
00438 ROS_INFO("%s",stdOut.str().c_str());stdOut.str("");
00439
00440
00441 Cloud3D::Ptr projectedCloud = boost::make_shared<Cloud3D>();
00442 pcl::ProjectInliers<pcl::PointXYZ> projectObj;
00443 projectObj.setModelType(pcl::SACMODEL_PLANE);
00444 projectObj.setInputCloud(planeCloud);
00445 projectObj.setModelCoefficients(planeCoeffs);
00446 projectObj.filter(*projectedCloud);
00447
00448
00449
00450
00451
00452
00453 if(_Parameters.MaxRadius > 0)
00454 {
00455 bool continueSearch = true;
00456 unsigned int index = 0;
00457 pcl::search::KdTree<pcl::PointXYZ>::Ptr searchTree = boost::make_shared<pcl::search::KdTree<pcl::PointXYZ> >();
00458 std::vector<int> indices;
00459 std::vector<float> sqDistances;
00460 searchTree->setInputCloud(projectedCloud);
00461
00462 while(continueSearch)
00463 {
00464 int found = searchTree->radiusSearch(projectedCloud->points[index],
00465 _Parameters.MaxRadius,indices,sqDistances);
00466
00467 if(found > 0)
00468 {
00469 continueSearch = false;
00470 }
00471 else
00472 {
00473 index++;
00474 if(index == projectedCloud->points.size())
00475 {
00476 ROS_ERROR_STREAM(nodeName << ": Did not find points within search radius: " <<
00477 _Parameters.MaxRadius <<", exiting");
00478 return false;
00479 }
00480 }
00481 }
00482
00483
00484 pcl::PointIndices::Ptr inliers = boost::make_shared<pcl::PointIndices>();
00485 inliers->indices = indices;
00486 pcl::ExtractIndices<pcl::PointXYZ> extractObj;
00487 extractObj.setInputCloud(projectedCloud);
00488 extractObj.setIndices(inliers);
00489 extractObj.setNegative(false);
00490 extractObj.filter(*projectedCloud);
00491
00492 stdOut << nodeName << ": Found " << projectedCloud->size() << " points within search radius: " <<
00493 _Parameters.MaxRadius;
00494 ROS_INFO("%s",stdOut.str().c_str());stdOut.str("");
00495 }
00496 else
00497 {
00498 ROS_INFO_STREAM(nodeName<<": search radius <= 0, skipping search and using all points found instead");
00499 }
00500
00501
00502 Eigen::Vector4f centroid;
00503 pcl::compute3DCentroid(*projectedCloud,centroid);
00504 if(index == projectedCloud->points.size())
00505 {
00506 ROS_ERROR_STREAM(nodeName << ": Did not find points within search radius: " <<
00507 _Parameters.MaxRadius <<", exiting");
00508 return false;
00509 }
00510 }
00511 }
00512
00513
00514 pcl::PointIndices::Ptr inliers = boost::make_shared<pcl::PointIndices>();
00515 inliers->indices = indices;
00516 pcl::ExtractIndices<pcl::PointXYZ> extractObj;
00517 extractObj.setInputCloud(projectedCloud);
00518 extractObj.setIndices(inliers);
00519 extractObj.setNegative(false);
00520 extractObj.filter(*projectedCloud);
00521
00522 stdOut << nodeName << ": Found " << projectedCloud->size() << " points within search radius: " <<
00523 _Parameters.MaxRadius;
00524 ROS_INFO("%s",stdOut.str().c_str());stdOut.str("");
00525 }
00526 else
00527 {
00528 ROS_INFO_STREAM(nodeName<<": search radius <= 0, skipping search and using all points found instead");
00529 }
00530
00531
00532 Eigen::Vector4f centroid;
00533 pcl::compute3DCentroid(*projectedCloud,centroid);
00534
00535 topCentroid.x = centroid[0];
00536 topCentroid.y = centroid[1];
00537 topCentroid.z = centroid[2];
00538
00539 return true;
00540 }
00541
00542 void SphereSegmentation::filterBounds(Cloud3D &cloud)
00543 {
00544
00545 std::vector<std::string> filterFields;
00546 filterFields.push_back("x"),filterFields.push_back("y"),filterFields.push_back("z");
00547 std::vector<double> filterMins;
00548 filterMins.push_back(_Parameters.Xmin) ,filterMins.push_back(_Parameters.Ymin),filterMins.push_back(_Parameters.Zmin);
00549 std::vector<double> filterMaxs;
00550 filterMaxs.push_back(_Parameters.Xmax),filterMaxs.push_back(_Parameters.Ymax),filterMaxs.push_back(_Parameters.Zmax);
00551
00552 pcl::PassThrough<pcl::PointXYZ> passFilter;
00553 passFilter.setInputCloud(boost::make_shared<Cloud3D>(cloud));
00554
00555 for(unsigned int i = 0; i < filterFields.size(); i++)
00556 {
00557 std::string fieldName = filterFields[i];
00558 double max, min;
00559 max = filterMaxs[i];
00560 min = filterMins[i];
00561
00562 passFilter.setFilterFieldName(fieldName);
00563 passFilter.setFilterLimits(min,max);
00564 passFilter.filter(cloud);
00565 }
00566
00567 }
00568
00569 void SphereSegmentation::filterWithPolygonalPrism(Cloud3D &cloud,pcl::PointXYZ &point,int nSides,double radius,double heightMax,double heightMin)
00570 {
00571 Cloud3D::Ptr polygonCloudPtr(new Cloud3D());
00572 Cloud3D::Ptr cloudPtr = boost::make_shared<Cloud3D>(cloud);
00573
00574
00575 double maxAngle = 2*M_PI;
00576 radius = 1.20f * radius;
00577 for(int i = 0; i < nSides; i++)
00578 {
00579 pcl::PointXYZ vertex;
00580 vertex.x = radius * cos((i*maxAngle)/((double)nSides)) + point.x;
00581 vertex.y = radius * sin((i*maxAngle)/((double)nSides)) + point.y;
00582 vertex.z = point.z;
00583
00584 polygonCloudPtr->push_back(vertex);
00585 }
00586
00587
00588 pcl::ExtractPolygonalPrismData<pcl::PointXYZ> extractor;
00589 pcl::PointIndices::Ptr indicesPtr(new pcl::PointIndices());
00590 extractor.setInputCloud(cloudPtr);
00591 extractor.setInputPlanarHull(polygonCloudPtr);
00592 extractor.setHeightLimits(heightMin,heightMax);
00593 extractor.segment(*indicesPtr);
00594
00595
00596 pcl::ExtractIndices<pcl::PointXYZ> indexExtractor;
00597 indexExtractor.setInputCloud(cloudPtr);
00598 indexExtractor.setIndices(indicesPtr);
00599 indexExtractor.setNegative(false);
00600 indexExtractor.filter(cloud);
00601
00602 }
00603
00604 void SphereSegmentation::concatenateClouds(const std::vector<sensor_msgs::PointCloud> &clusters,Cloud3D &cluster)
00605 {
00606
00607 cluster.clear();
00608 cluster.header.frame_id = clusters.begin()->header.frame_id;
00609
00610
00611 sensor_msgs::PointCloud2 tempCloudMsg;
00612 Cloud3D tempCloud = Cloud3D();
00613
00614 BOOST_FOREACH(sensor_msgs::PointCloud clusterMsg,clusters)
00615 {
00616 sensor_msgs::convertPointCloudToPointCloud2(clusterMsg,tempCloudMsg);
00617
00618
00619 pcl::fromROSMsg(tempCloudMsg,tempCloud);
00620
00621
00622 cluster += tempCloud;
00623 }
00624 }
00625
00626 void SphereSegmentation::createObject(const pcl::ModelCoefficients &coeffs,arm_navigation_msgs::CollisionObject &obj)
00627 {
00628 const std::string nodeName = ros::this_node::getName() + "/segmentation";
00629
00630 std::string name = "sphere_object";
00631 obj.id = name;
00632 obj.header.frame_id = _Parameters.WorldFrameId;
00633 obj.padding = 0.0f;
00634 obj.shapes = std::vector<arm_navigation_msgs::Shape>();
00635 obj.poses = std::vector<geometry_msgs::Pose>();
00636
00637
00638 ROS_INFO_STREAM(nodeName<<": creating sphere shape");
00639 arm_navigation_msgs::Shape shape;
00640 shape.type = arm_navigation_msgs::Shape::SPHERE;
00641 shape.dimensions.push_back(coeffs.values[3]);
00642
00643
00644 ROS_INFO_STREAM(nodeName<<": creating sphere pose");
00645 geometry_msgs::Pose pose;
00646 tf::poseTFToMsg(tf::Transform(tf::Quaternion::getIdentity(),tf::Vector3(coeffs.values[0],
00647 coeffs.values[1], coeffs.values[2])),pose);
00648
00649
00650 obj.shapes.push_back(shape);
00651 obj.poses.push_back(pose);
00652
00653 }