table_object_cluster.cpp
Go to the documentation of this file.
00001 
00063 #include "cob_table_object_cluster/table_object_cluster.h"
00064 
00065 #include <cob_3d_mapping_common/minimal_rectangle_2d.h>
00066 #include <pcl/segmentation/extract_polygonal_prism_data.h>
00067 #include <pcl/filters/extract_indices.h>
00068 #include <pcl/filters/crop_box.h>
00069 #include <pcl/io/io.h>
00070 #include <pcl/common/common.h>
00071 #include <pcl/kdtree/kdtree_flann.h>
00072 #include <pcl/segmentation/extract_clusters.h>
00073 #include <pcl/sample_consensus/sac_model_plane.h>
00074 #include <pcl/surface/convex_hull.h>
00075 #include <pcl/io/pcd_io.h>
00076 //#include <pcl/search/organized.h>
00077 
00078   //aditional includes
00079 #include <ros/console.h>
00080 
00081 struct null_deleter
00082 {
00083     void operator()(void const *) const
00084     {
00085     }
00086 };
00087 
00088 
00089 template<typename Point> void
00090 TableObjectCluster<Point>::extractTableRoi(PointCloudPtr& hull,
00091                                     pcl::PointIndices& pc_roi)
00092 {
00093   #ifdef PCL_MINOR_VERSION >= 6
00094   pcl::ConvexHull<Point> chull;
00095   chull.setDimension(2);
00096   chull.setInputCloud(hull);
00097   PointCloudPtr conv_hull(new pcl::PointCloud<Point>);
00098   chull.reconstruct(*conv_hull);
00099   #endif
00100 
00101   pcl::ExtractPolygonalPrismData<Point> prism;
00102   // Consider only objects in a given layer above the table
00103   //TODO: check if valid values
00104   //TODO: does not work for planes other than horizontal, PrismExtraction has to be modified
00105   //ROS_INFO("height limits: %f, %f ", height_min_, height_max_);
00106   prism.setHeightLimits(height_min_, height_max_);
00107   // ---[ Get the objects on top of the table
00108   //pcl::PointIndices roi_indices;
00109   prism.setInputCloud(input_);
00110 
00111   #ifdef PCL_MINOR_VERSION >= 6
00112   prism.setInputPlanarHull(conv_hull);
00113   #else
00114   prism.setInputPlanarHull(hull);
00115   #endif
00116 
00117   prism.segment(pc_roi);
00118   //ROS_INFO("Number of ROI inliers: %d", roi_indices.indices.size());
00119 
00120   /*pcl::ExtractIndices<Point> extract_roi;
00121   extract_roi.setInputCloud (pc_in);
00122   extract_roi.setIndices (boost::make_shared<const pcl::PointIndices> (roi_indices));
00123   extract_roi.filter (pc_roi);*/
00124 }
00125 
00126 template<typename Point> void
00127 TableObjectCluster<Point>::extractTableRoi2(const PointCloudConstPtr& pc_in,
00128                                     PointCloudPtr& hull,
00129                                     Eigen::Vector4f& plane_coeffs,
00130                                     pcl::PointCloud<Point>& pc_roi)
00131 {
00132   pcl::PointIndices indices;
00133   for(unsigned int i=0; i<pc_in->size(); i++)
00134     indices.indices.push_back(i);
00135   // Project all points
00136   pcl::PointCloud<Point> projected_points;
00137   pcl::SampleConsensusModelPlane<Point> sacmodel (pc_in);
00138   //Eigen::Vector4f e_plane_coeffs(plane_coeffs.values[0],plane_coeffs.values[1],plane_coeffs.values[2],plane_coeffs.values[3]);
00139   sacmodel.projectPoints (indices.indices, plane_coeffs, projected_points, false);
00140   pcl::io::savePCDFileASCII ("/home/goa/tmp/proj.pcd", projected_points);
00141   pcl::io::savePCDFileASCII ("/home/goa/tmp/hull.pcd", *hull);
00142   pcl::PointIndices inliers;
00143   std::cout << "Coeffs:" << plane_coeffs << std::endl;
00144   int ctr=0, ctr2=0;
00145   for(unsigned int i=0; i<pc_in->size(); i++)
00146   {
00147     double distance = pcl::pointToPlaneDistanceSigned (pc_in->points[i], plane_coeffs);
00148     if (distance < height_min_ || distance > height_max_)
00149          continue;
00150     ctr++;
00151     if (!pcl::isXYPointIn2DXYPolygon (projected_points.points[i], *hull))
00152       continue;
00153     ctr2++;
00154     ROS_INFO("Point is in polygon");
00155     inliers.indices.push_back(i);
00156   }
00157   ROS_INFO("Pts in height: %d", ctr);
00158   ROS_INFO("Pts in poly: %d", ctr2);
00159 
00160   pcl::ExtractIndices<Point> extract_roi;
00161   extract_roi.setInputCloud (pc_in);
00162   extract_roi.setIndices (boost::make_shared<const pcl::PointIndices> (inliers));
00163   extract_roi.filter (pc_roi);
00164 }
00165 
00166 template<typename Point> void
00167 TableObjectCluster<Point>::removeKnownObjects(const PointCloudConstPtr& pc_roi,
00168                    std::vector<BoundingBox>& bounding_boxes,
00169                    const PointCloudPtr& pc_roi_red)
00170 {
00171   //pcl::copyPointCloud(*pc_roi,pc_roi_red);
00172         boost::shared_ptr<pcl::PointIndices> all_indices(new pcl::PointIndices);
00173   pcl::CropBox<Point> cb;
00174   for(unsigned int i=0; i<bounding_boxes.size(); i++)
00175   {
00176     std::vector<int> indices;
00177     cb.setMin(bounding_boxes[i].min_pt);
00178     cb.setMax(bounding_boxes[i].max_pt);
00179     cb.setTransform(bounding_boxes[i].pose);
00180     cb.filter(indices);
00181     all_indices->indices.insert(all_indices->indices.end(), indices.begin(), indices.end());
00182   }
00183   pcl::ExtractIndices<Point> extract;
00184   extract.setInputCloud(pc_roi);
00185   extract.setIndices(all_indices);
00186   extract.setNegative(true);
00187   extract.filter(*pc_roi_red);
00188 }
00189 
00190 template<typename Point> void
00191 TableObjectCluster<Point>::calculateBoundingBox(
00192   const PointCloudPtr& cloud,
00193   const pcl::PointIndices& indices,
00194   const Eigen::Vector3f& plane_normal,
00195   const Eigen::Vector3f& plane_point,
00196   Eigen::Vector3f& position,
00197   Eigen::Quaternion<float>& orientation,
00198   Eigen::Vector3f& size)
00199 {
00200   // transform to table coordinate frame and project points on X-Y, save max height
00201   Eigen::Affine3f tf;
00202   pcl::getTransformationFromTwoUnitVectorsAndOrigin(plane_normal.unitOrthogonal(), plane_normal, plane_point, tf);
00203   pcl::PointCloud<pcl::PointXYZ>::Ptr pc2d(new pcl::PointCloud<pcl::PointXYZ>);
00204   float height = 0.0;
00205   for(std::vector<int>::const_iterator it=indices.indices.begin(); it != indices.indices.end(); ++it)
00206   {
00207     Eigen::Vector3f tmp = tf * (*cloud)[*it].getVector3fMap();
00208     height = std::max<float>(height, fabs(tmp(2)));
00209     pc2d->push_back(pcl::PointXYZ(tmp(0),tmp(1),0.0));
00210   }
00211 
00212   // create convex hull of projected points
00213   #ifdef PCL_MINOR_VERSION >= 6
00214   pcl::PointCloud<pcl::PointXYZ>::Ptr conv_hull(new pcl::PointCloud<pcl::PointXYZ>);
00215   pcl::ConvexHull<pcl::PointXYZ> chull;
00216   chull.setDimension(2);
00217   chull.setInputCloud(pc2d);
00218   chull.reconstruct(*conv_hull);
00219   #endif
00220 
00221   /*for(int i=0; i<conv_hull->size(); ++i)
00222     std::cout << (*conv_hull)[i].x << "," << (*conv_hull)[i].y << std::endl;*/
00223 
00224   // find the minimal bounding rectangle in 2D and table coordinates
00225   Eigen::Vector2f p1, p2, p3;
00226   cob_3d_mapping::MinimalRectangle2D mr2d;
00227   mr2d.setConvexHull(conv_hull->points);
00228   mr2d.rotatingCalipers(p2, p1, p3);
00229   /*std::cout << "BB: \n" << p1[0] << "," << p1[1] <<"\n"
00230             << p2[0] << "," << p2[1] <<"\n"
00231             << p3[0] << "," << p3[1] <<"\n ---" << std::endl;*/
00232 
00233   // compute center of rectangle
00234   position[0] = 0.5f*(p1[0] + p3[0]);
00235   position[1] = 0.5f*(p1[1] + p3[1]);
00236   position[2] = 0.0f;
00237   // transform back
00238   Eigen::Affine3f inv_tf = tf.inverse();
00239   position = inv_tf * position;
00240   // set size of bounding box
00241   float norm_1 = (p3-p2).norm();
00242   float norm_2 = (p1-p2).norm();
00243   // BoundingBox coordinates: X:= main direction, Z:= table normal
00244   Eigen::Vector3f direction; // y direction
00245   if (norm_1 < norm_2)
00246   {
00247     direction = Eigen::Vector3f(p3[0]-p2[0], p3[1]-p2[1], 0) / (norm_1);
00248     size[0] = norm_2 * 0.5f;
00249     size[1] = norm_1 * 0.5f;
00250   }
00251   else
00252   {
00253     direction = Eigen::Vector3f(p1[0]-p2[0], p1[1]-p2[1], 0) / (norm_2);
00254     size[0] = norm_1 * 0.5f;
00255     size[1] = norm_2 * 0.5f;
00256   }
00257   size[2] = -height;
00258 
00259 
00260   direction = inv_tf.rotation() * direction;
00261   orientation = pcl::getTransformationFromTwoUnitVectors(direction, plane_normal).rotation(); // (y, z-direction)
00262 
00263   return;
00264   Eigen::Matrix3f M = Eigen::Matrix3f::Identity() - plane_normal * plane_normal.transpose();
00265   Eigen::Vector3f xn = M * Eigen::Vector3f::UnitX(); // X-axis project on normal
00266   Eigen::Vector3f xxn = M * direction;
00267   float cos_phi = acos(xn.normalized().dot(xxn.normalized())); // angle between xn and main direction
00268   cos_phi = cos(0.5f * cos_phi);
00269   float sin_phi = sqrt(1.0f-cos_phi*cos_phi);
00270   //orientation.w() = cos_phi;
00271   //orientation.x() = sin_phi * plane_normal(0);
00272   //orientation.y() = sin_phi * plane_normal(1);
00273   //orientation.z() = sin_phi * plane_normal(2);
00274 }
00275 
00276 template<typename Point> void
00277 TableObjectCluster<Point>::extractClusters(
00278   const pcl::PointIndices::Ptr& pc_roi,
00279   std::vector<PointCloudPtr>& object_clusters,
00280   std::vector<pcl::PointIndices>& object_cluster_indices)
00281 {
00282 //ROS_INFO("input: %d,%d", input_->width, input_->height);
00283   #ifdef PCL_VERSION_COMPARE //fuerte
00284     //typename pcl::search::OrganizedNeighbor<Point>::Ptr clusters_tree( new pcl::search::OrganizedNeighbor<Point>());
00285     typename pcl::search::KdTree<Point>::Ptr clusters_tree (new pcl::search::KdTree<Point>());
00286   #else //electric
00287     typename pcl::KdTreeFLANN<Point>::Ptr clusters_tree (new pcl::KdTreeFLANN<Point> ());
00288   #endif
00289 
00290   pcl::EuclideanClusterExtraction<Point> cluster_obj;
00291   cluster_obj.setClusterTolerance (cluster_tolerance_);
00292   cluster_obj.setMinClusterSize (min_cluster_size_);
00293   cluster_obj.setInputCloud (input_);
00294   cluster_obj.setIndices(pc_roi);
00295   cluster_obj.setSearchMethod (clusters_tree);
00296   cluster_obj.extract (object_cluster_indices);
00297 
00298   pcl::ExtractIndices<Point> ei;
00299   ei.setInputCloud(input_);
00300   for(unsigned int i = 0; i < object_cluster_indices.size(); ++i)
00301   {
00302     PointCloudPtr cluster_ptr(new pcl::PointCloud<Point>);
00303     boost::shared_ptr<pcl::PointIndices> ind_ptr(&object_cluster_indices[i], null_deleter());
00304     ei.setIndices(ind_ptr);
00305     ei.filter(*cluster_ptr);
00306     object_clusters.push_back(cluster_ptr);
00307   }
00308 }
00309 
00310 template<typename Point> void
00311 TableObjectCluster<Point>::calculateBoundingBoxesOld(pcl::PointIndices::Ptr& pc_roi,
00312                                                   std::vector<PointCloudPtr >& object_clusters,
00313                                                   std::vector<pcl::PointCloud<pcl::PointXYZ> >& bounding_boxes)
00314 {
00315   ROS_INFO("roi: %d", pc_roi->indices.size());
00316   #ifdef PCL_VERSION_COMPARE //fuerte
00317     typename pcl::search::KdTree<Point>::Ptr clusters_tree (new pcl::search::KdTree<Point>());
00318     //typename pcl::search::OrganizedNeighbor<Point>::Ptr clusters_tree( new pcl::search::OrganizedNeighbor<Point>());
00319   #else //electric
00320     typename pcl::KdTreeFLANN<Point>::Ptr clusters_tree (new pcl::KdTreeFLANN<Point> ());
00321   #endif
00322 
00323   pcl::EuclideanClusterExtraction<Point> cluster_obj;
00324 
00325   // Table clustering parameters
00326   cluster_obj.setClusterTolerance (cluster_tolerance_);
00327   cluster_obj.setMinClusterSize (min_cluster_size_);
00328   cluster_obj.setInputCloud (input_);
00329   cluster_obj.setIndices(pc_roi);
00330   //cluster_obj.setSearchMethod (clusters_tree);
00331   std::vector<pcl::PointIndices> object_cluster_indices;
00332   cluster_obj.extract (object_cluster_indices);
00333   pcl::ExtractIndices<Point> ei;
00334   ei.setInputCloud(input_);
00335   for(unsigned int i = 0; i < object_cluster_indices.size(); ++i)
00336   {
00337     boost::shared_ptr<pcl::PointIndices> ind_ptr(&object_cluster_indices[i], null_deleter());
00338     ei.setIndices(ind_ptr);
00339     PointCloudPtr cluster_ptr(new pcl::PointCloud<Point>);
00340     ei.filter(*cluster_ptr);
00341     object_clusters.push_back(cluster_ptr);
00342     pcl::PointCloud<pcl::PointXYZ> bb;
00343     Eigen::Vector4f min_pt, max_pt;
00344     pcl::getMinMax3D(*input_, object_cluster_indices[i], min_pt, max_pt);
00345     //if(fabs(max_pt(2)-min_pt(2))<0.03) continue;
00346     pcl::PointXYZ p;
00347     p.x = min_pt(0);
00348     p.y = min_pt(1);
00349     p.z = min_pt(2);
00350     bb.push_back(p);
00351     p.x = max_pt(0);
00352     p.y = max_pt(1);
00353     p.z = max_pt(2);
00354     bb.push_back(p);
00355     bounding_boxes.push_back(bb);
00356   }
00357 }
00358 
00359 template class TableObjectCluster<pcl::PointXYZ>;
00360 
00361 template class TableObjectCluster<pcl::PointXYZRGB>;


cob_table_object_cluster
Author(s): Georg Arbeiter
autogenerated on Wed Aug 26 2015 11:05:13