00001 /* 00002 * blob.hh 00003 * Mac Mason <mmason@willowgarage.com> 00004 * 00005 * We need a (C++) object for tracking the variety of things we, well, track. 00006 * 00007 * The Blob object also keeps track of several static function that do useful 00008 * things to blobs, like merging arrays of them. 00009 */ 00010 00011 #pragma once 00012 00013 #include <vector> 00014 #include <boost/utility.hpp> // for boost::noncopyable 00015 #include "pcl16/point_types.h" 00016 #include "pcl16/point_cloud.h" 00017 #include <cstddef> 00018 00019 namespace semanticmodel 00020 { 00021 00022 class Blob : public boost::noncopyable 00023 { 00024 private: 00025 // Keep our typing sane. 00026 typedef pcl16::PointXYZRGB Point; 00027 typedef pcl16::PointCloud<Point> PointCloud; 00028 00029 public: 00030 // The raw cloud of the object. 00031 PointCloud::Ptr cloud; 00032 // The convex hull of the (flattened) data, at z == 0.0. 00033 PointCloud::Ptr hull; 00034 // Unique id of this blob 00035 unsigned int id; 00036 00037 // Given a cluster (generated by our filter), fill everything in. 00038 Blob(const PointCloud::ConstPtr& cluster); 00039 00040 // No need for a destructor; viva shared_ptr! 00041 00042 // Does this Blob overlap that blob? Our algorithm is to accept any 00043 // overlap between the (flattened) convex hulls. 00044 bool overlaps(const Blob& rhs) const; 00045 00046 // Bring the contents of rhs into this Blob. 00047 void mergeFrom(const Blob& rhs); 00048 00049 // Compute the (average) color of the object. Given values in the range 00050 // [0.0, 1.0] (for ease of use with visualization_msgs). 00051 void RGB(float& r, float& g, float& b) const; 00052 00053 // Compute the size of the bounding box of the Blob. Note that the 00054 // returned box will be axis-aligned, which is not (necessarily) what you 00055 // meant. Deal with it. 00056 void size(double& x, double& y, double& z) const; 00057 00058 // Return a copy, with all the z-values set to the appropriate value. 00059 // Since shared_ptrs are cheap to copy, let's return one. 00060 static PointCloud::Ptr flatten(PointCloud::Ptr& in, double z = 0.0); 00061 00062 // Given a set of objects (the current set), and a new object, do the 00063 // overlap checking to include this object in the set, merging as 00064 // necessary. ("Smart" merging, with recursive checks). objects is 00065 // expected to hold zero or more blobs, none of which overlap. blob is 00066 // expected to be a new object to merge in. This function takes ownership 00067 // of the passed-in pointer; DO NOT DELETE IT YOURSELF. The objects vector 00068 // will be modified by this function; whoever owned that vector beforehand 00069 // still does. 00070 // 00071 // See also MergeBlobWithSetHelper, below. 00072 static void MergeBlobWithSet(std::vector<Blob*>& objects, Blob* blob); 00073 00074 private: 00075 00076 // This is the one-pass helper for MergeBlobWithSet. This version takes in 00077 // a single vector; the object-to-be-potentially-merged is the last 00078 // element. If it returns true, a merge happened, and the newly-merged 00079 // object is the last element; if it returns false, no edits are made to 00080 // objects. 00081 static bool MergeBlobWithSetHelper(std::vector<Blob*>& objects); 00082 00083 static unsigned int next_id; 00084 00085 // A helper for the constructor; fill in hull from a cloud. This is 00086 // smart about self-hull-assignment; see the usage in mergeFrom. 00087 void hullerize(const PointCloud::ConstPtr& cloud); 00088 00089 // An overlaps() helper; a direct port from plane_data_assocation.py. 00090 bool oneSidedIntersect(const PointCloud::ConstPtr& p1, 00091 const PointCloud::ConstPtr& p2) const; 00092 00093 // See previous comment. 00094 void projectOntoNormal(const PointCloud::ConstPtr& poly, 00095 const Point& q1, const Point& q2, 00096 double& inf, double& sup) const; 00097 }; 00098 00099 }