point_cloud_segmentation.h
Go to the documentation of this file.
00001 /*********************************************************************
00002  * Software License Agreement (BSD License)
00003  *
00004  *  Copyright (c) 2012, Georgia Institute of Technology
00005  *  All rights reserved.
00006  *
00007  *  Redistribution and use in source and binary forms, with or without
00008  *  modification, are permitted provided that the following conditions
00009  *  are met:
00010  *
00011  *   * Redistributions of source code must retain the above copyright
00012  *     notice, this list of conditions and the following disclaimer.
00013  *   * Redistributions in binary form must reproduce the above
00014  *     copyright notice, this list of conditions and the following
00015  *     disclaimer in the documentation and/or other materials provided
00016  *     with the distribution.
00017  *   * Neither the name of the Georgia Institute of Technology nor the names of
00018  *     its contributors may be used to endorse or promote products derived
00019  *     from this software without specific prior written permission.
00020  *
00021  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00022  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00023  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00024  *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00025  *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00026  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00027  *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00028  *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00029  *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00030  *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00031  *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00032  *  POSSIBILITY OF SUCH DAMAGE.
00033  *********************************************************************/
00034 #ifndef point_cloud_segmentation_h_DEFINED
00035 #define point_cloud_segmentation_h_DEFINED
00036 
00037 // ROS Message Types
00038 #include <std_msgs/Header.h>
00039 #include <sensor_msgs/CameraInfo.h>
00040 #include <geometry_msgs/PointStamped.h>
00041 
00042 // TF
00043 #include <tf/transform_listener.h>
00044 
00045 // PCL
00046 #include <pcl16/point_cloud.h>
00047 #include <pcl16/point_types.h>
00048 #include <pcl16/common/eigen.h>
00049 #include <pcl16/common/io.h>
00050 #include <pcl16/ModelCoefficients.h>
00051 
00052 // OpenCV
00053 #include <opencv2/core/core.hpp>
00054 
00055 // STL
00056 #include <vector>
00057 #include <deque>
00058 #include <string>
00059 #include <math.h>
00060 
00061 // Boost
00062 #include <boost/shared_ptr.hpp>
00063 
00064 namespace tabletop_pushing
00065 {
00066 
00067 typedef pcl16::PointCloud<pcl16::PointXYZ> XYZPointCloud;
00068 typedef pcl16::PointCloud<pcl16::Normal> NormalCloud;
00069 class ProtoObject
00070 {
00071  public:
00072   XYZPointCloud cloud;
00073   NormalCloud normals;
00074   Eigen::Vector4f centroid;
00075   int id;
00076   bool moved;
00077   Eigen::Matrix4f transform;
00078   std::vector<int> boundary_angle_dist;
00079   std::vector<int> push_history;
00080   bool singulated;
00081   double icp_score;
00082 };
00083 typedef std::deque<ProtoObject> ProtoObjects;
00084 
00085 class PointCloudSegmentation
00086 {
00087  public:
00088   PointCloudSegmentation(boost::shared_ptr<tf::TransformListener> tf);
00089 
00099   void getTablePlane(XYZPointCloud& cloud, XYZPointCloud& objs_cloud,
00100                      XYZPointCloud& plane_cloud, Eigen::Vector4f& center,
00101                      bool find_hull=false, bool find_centroid=false);
00102 
00112   void getTablePlaneMPS(XYZPointCloud& cloud, XYZPointCloud& objs_cloud,
00113                         XYZPointCloud& plane_cloud, Eigen::Vector4f& center,
00114                         bool find_hull=false, bool find_centroid=false);
00115 
00123   void findTabletopObjects(XYZPointCloud& input_cloud, ProtoObjects& objs, bool use_mps=false);
00124 
00133   void findTabletopObjects(XYZPointCloud& input_cloud, ProtoObjects& objs,
00134                            XYZPointCloud& objs_cloud, bool use_mps=false);
00135 
00145   void findTabletopObjects(XYZPointCloud& input_cloud, ProtoObjects& objs,
00146                                    XYZPointCloud& objs_cloud,
00147                                    XYZPointCloud& plane_cloud, bool use_mps=false);
00148 
00155   void clusterProtoObjects(XYZPointCloud& objects_cloud, ProtoObjects& objs);
00156 
00165   double ICPProtoObjects(ProtoObject& a, ProtoObject& b, Eigen::Matrix4f& transform);
00166 
00167   double ICPBoundarySamples(XYZPointCloud& hull_t_0, XYZPointCloud& hull_t_1, Eigen::Matrix4f& transform,
00168                             XYZPointCloud& aligned);
00169 
00178   void getMovedRegions(XYZPointCloud& prev_cloud, XYZPointCloud& cur_cloud, ProtoObjects& moved_regions,
00179                        std::string suf="");
00180 
00188   void matchMovedRegions(ProtoObjects& objs, ProtoObjects& moved_regions);
00189 
00190   void fitCylinderRANSAC(ProtoObject& obj, XYZPointCloud& cylinder_cloud, pcl16::ModelCoefficients& cylinder);
00191   void fitSphereRANSAC(ProtoObject& obj, XYZPointCloud& sphere_cloud, pcl16::ModelCoefficients& sphere);
00192 
00193   static inline double dist(pcl16::PointXYZ a, pcl16::PointXYZ b)
00194   {
00195     const double dx = a.x-b.x;
00196     const double dy = a.y-b.y;
00197     const double dz = a.z-b.z;
00198     return std::sqrt(dx*dx+dy*dy+dz*dz);
00199   }
00200 
00201   static inline double dist(geometry_msgs::Point b, pcl16::PointXYZ a)
00202   {
00203     return dist(a,b);
00204   }
00205 
00206   static inline double dist(pcl16::PointXYZ a, geometry_msgs::Point b)
00207   {
00208     const double dx = a.x-b.x;
00209     const double dy = a.y-b.y;
00210     const double dz = a.z-b.z;
00211     return std::sqrt(dx*dx+dy*dy+dz*dz);
00212   }
00213 
00214   static inline double sqrDist(Eigen::Vector3f& a, pcl16::PointXYZ& b)
00215   {
00216     const double dx = a[0]-b.x;
00217     const double dy = a[1]-b.y;
00218     const double dz = a[2]-b.z;
00219     return dx*dx+dy*dy+dz*dz;
00220   }
00221 
00222   static inline double sqrDist(Eigen::Vector4f& a, Eigen::Vector4f& b)
00223   {
00224     const double dx = a[0]-b[0];
00225     const double dy = a[1]-b[1];
00226     const double dz = a[2]-b[2];
00227     return dx*dx+dy*dy+dz*dz;
00228   }
00229 
00230   static inline double sqrDist(pcl16::PointXYZ a, pcl16::PointXYZ b)
00231   {
00232     const double dx = a.x-b.x;
00233     const double dy = a.y-b.y;
00234     const double dz = a.z-b.z;
00235     return dx*dx+dy*dy+dz*dz;
00236   }
00237 
00238   static inline double sqrDistXY(pcl16::PointXYZ a, pcl16::PointXYZ b)
00239   {
00240     const double dx = a.x-b.x;
00241     const double dy = a.y-b.y;
00242     return dx*dx+dy*dy;
00243   }
00244 
00255   bool cloudsIntersect(XYZPointCloud cloud0, XYZPointCloud cloud1);
00256 
00257   bool cloudsIntersect(XYZPointCloud cloud0, XYZPointCloud cloud1,
00258                        double thresh);
00259 
00260   bool pointIntersectsCloud(XYZPointCloud cloud, geometry_msgs::Point pt,
00261                             double thresh);
00262 
00263   float pointLineXYDist(pcl16::PointXYZ p,Eigen::Vector3f vec,Eigen::Vector4f base);
00264 
00265   void lineCloudIntersection(XYZPointCloud& cloud, Eigen::Vector3f vec,
00266                              Eigen::Vector4f base, XYZPointCloud& line_cloud);
00267   void lineCloudIntersectionEndPoints(XYZPointCloud& cloud, Eigen::Vector3f vec, Eigen::Vector4f base,
00268                                       std::vector<pcl16::PointXYZ>& end_points);
00269 
00278   void downsampleCloud(XYZPointCloud& cloud_in, XYZPointCloud& cloud_down);
00279 
00289   cv::Mat projectProtoObjectsIntoImage(ProtoObjects& objs, cv::Size img_size, std::string target_frame);
00290 
00300   cv::Mat projectProtoObjectIntoImage(ProtoObject& obj, cv::Size img_size, std::string target_frame);
00301 
00308   cv::Mat displayObjectImage(cv::Mat& obj_img,
00309                              std::string win_name="projected objects",
00310                              bool use_display=true);
00311 
00312   void projectPointCloudIntoImage(XYZPointCloud& cloud, cv::Mat& lbl_img,
00313                                   std::string target_frame, unsigned int id=1);
00314 
00315   cv::Point projectPointIntoImage(pcl16::PointXYZ cur_point_pcl,
00316                                   std::string point_frame,
00317                                   std::string target_frame);
00318 
00319   void projectPointCloudIntoImage(XYZPointCloud& cloud, cv::Mat& lbl_img);
00320 
00321   cv::Point projectPointIntoImage(geometry_msgs::PointStamped cur_point);
00322 
00323   cv::Point projectPointIntoImage(geometry_msgs::PointStamped cur_point,
00324                                   std::string target_frame);
00325   cv::Point projectPointIntoImage(Eigen::Vector3f cur_point_eig,
00326                                   std::string point_frame, std::string target_frame);
00327 
00328   Eigen::Vector4f getTableCentroid() const
00329   {
00330     return table_centroid_;
00331   }
00332 
00333  protected:
00334   boost::shared_ptr<tf::TransformListener> tf_;
00335   Eigen::Vector4f table_centroid_;
00336 
00337  public:
00338   std::vector<cv::Vec3f> colors_;
00339   double min_table_z_;
00340   double max_table_z_;
00341   double min_workspace_x_;
00342   double max_workspace_x_;
00343   double min_workspace_z_;
00344   double max_workspace_z_;
00345   double table_ransac_thresh_;
00346   double table_ransac_angle_thresh_;
00347   double cluster_tolerance_;
00348   double cloud_diff_thresh_;
00349   int min_cluster_size_;
00350   int max_cluster_size_;
00351   double voxel_down_res_;
00352   double cloud_intersect_thresh_;
00353   double hull_alpha_;
00354   bool use_voxel_down_;
00355   int num_downsamples_;
00356   sensor_msgs::CameraInfo cam_info_;
00357   std_msgs::Header cur_camera_header_;
00358   int moved_count_thresh_;
00359   int icp_max_iters_;
00360   double icp_transform_eps_;
00361   double icp_max_cor_dist_;
00362   double icp_ransac_thresh_;
00363   int mps_min_inliers_;
00364   double mps_min_angle_thresh_;
00365   double mps_min_dist_thresh_;
00366   double cylinder_ransac_thresh_;
00367   double cylinder_ransac_angle_thresh_;
00368   double sphere_ransac_thresh_;
00369   bool optimize_cylinder_coefficients_;
00370 };
00371 
00372 void getMaskedPointCloud(XYZPointCloud& input_cloud, cv::Mat& mask, XYZPointCloud& masked_cloud)
00373 {
00374   // Select points from point cloud that are in the mask:
00375   pcl16::PointIndices mask_indices;
00376   mask_indices.header = input_cloud.header;
00377   for (int y = 0; y < mask.rows; ++y)
00378   {
00379     uchar* mask_row = mask.ptr<uchar>(y);
00380     for (int x = 0; x < mask.cols; ++x)
00381     {
00382       if (mask_row[x] != 0)
00383       {
00384         mask_indices.indices.push_back(y*input_cloud.width + x);
00385       }
00386     }
00387   }
00388 
00389   pcl16::copyPointCloud(input_cloud, mask_indices, masked_cloud);
00390 }
00391 };
00392 #endif // point_cloud_segmentation_h_DEFINED


tabletop_pushing
Author(s): Tucker Hermans
autogenerated on Wed Nov 27 2013 11:59:44