table_object_cluster_node.cpp
Go to the documentation of this file.
00001 
00064 //##################
00065 //#### includes ####
00066 
00067 // standard includes
00068 //--
00069 #include <sstream>
00070 #include <fstream>
00071 
00072 // ROS includes
00073 #include <ros/ros.h>
00074 #include <message_filters/subscriber.h>
00075 #include <message_filters/synchronizer.h>
00076 #include <message_filters/sync_policies/exact_time.h>
00077 #include <actionlib/server/simple_action_server.h>
00078 #include <dynamic_reconfigure/server.h>
00079 #include <pcl/io/io.h>
00080 #include <pcl/io/pcd_io.h>
00081 #include <pcl/point_types.h>
00082 #include <pcl_ros/point_cloud.h>
00083 #include <pcl/PointIndices.h>
00084 #include <eigen_conversions/eigen_msg.h>
00085 
00086 //#include <cob_3d_mapping_common/reconfigureable_node.h>
00087 #include <cob_table_object_cluster/table_object_cluster_nodeletConfig.h>
00088 #include <cob_3d_mapping_common/polygon.h>
00089 #include <cob_3d_mapping_common/ros_msg_conversions.h>
00090 
00091 
00092 // ROS message includes
00093 //#include <sensor_msgs/PointCloud2.h>
00094 #include <cob_3d_mapping_msgs/GetPointMap.h>
00095 #include <cob_3d_mapping_msgs/SetBoundingBoxes.h>
00096 #include <cob_3d_mapping_msgs/ShapeArray.h>
00097 #include <cob_perception_msgs/PointCloud2Array.h>
00098 #include <cob_object_detection_msgs/Detection.h>
00099 #include <cob_object_detection_msgs/DetectionArray.h>
00100 #include <cob_vision_utils/ros_msg_conversions.h>
00101 #include <visualization_msgs/Marker.h>
00102 
00103 // external includes
00104 #include <boost/timer.hpp>
00105 #include <Eigen/StdVector>
00106 
00107 #include "cob_table_object_cluster/table_object_cluster.h"
00108 #include "cob_3d_mapping_msgs/TableObjectClusterAction.h"
00109 
00110 #include <cob_3d_mapping_common/stop_watch.h>
00111 #include <pcl/filters/extract_indices.h>
00112 #include <pcl_conversions/pcl_conversions.h>
00113 
00114 using namespace cob_table_object_cluster;
00115 using namespace cob_3d_mapping;
00116 
00117 
00118 //####################
00119 //#### nodelet class ####
00120 class TableObjectClusterNode //: protected Reconfigurable_Node<table_object_cluster_nodeletConfig>
00121 {
00122 public:
00123   typedef pcl::PointXYZ Point;
00124   typedef pcl::PointCloud<Point> PointCloud;
00125   typedef message_filters::sync_policies::ExactTime<PointCloud, cob_3d_mapping_msgs::ShapeArray > MySyncPolicy;
00126   // Constructor
00127   TableObjectClusterNode()
00128   : as_(0)
00129   , ctr_(0)
00130   , enable_action_mode_(false)
00131   , last_pc_(new PointCloud)
00132   {
00133     config_server_.setCallback(boost::bind(&TableObjectClusterNode::dynReconfCallback, this, _1, _2));
00134 
00135     // subscriber:
00136     pc_sub_.subscribe(n_,"point_cloud",1);
00137     sa_sub_.subscribe(n_,"shape_array",1);
00138     sync_ = boost::make_shared <message_filters::Synchronizer<MySyncPolicy> >(100);
00139     sync_->connectInput(pc_sub_, sa_sub_);
00140     sync_->registerCallback(boost::bind(&TableObjectClusterNode::topicCallback, this, _1, _2));
00141 
00142     // publisher:
00143     bba_pub_ = n_.advertise<cob_object_detection_msgs::DetectionArray>("bounding_box_array", 1);
00144     marker_pub_ = n_.advertise<visualization_msgs::Marker>("bb_marker",100);
00145     object_cluster_pub_ = n_.advertise<cob_perception_msgs::PointCloud2Array>("cluster_array",1);
00146 
00147     // Services and Actions
00148     //get_bb_client_ = n_.serviceClient<cob_3d_mapping_msgs::GetBoundingBoxes>("get_known_objects");
00149     set_known_objects_server_ = n_.advertiseService("set_known_objects", &TableObjectClusterNode::setKnownObjects, this);
00150   }
00151 
00152   // Destructor
00153   ~TableObjectClusterNode()
00154   {
00156     if(as_) delete as_;
00157   }
00158 
00166   void
00167   dynReconfCallback(table_object_cluster_nodeletConfig &config, uint32_t level)
00168   {
00169     save_to_file_ = config.save;
00170     file_path_ = config.file_path;
00171     /*height_min_ = config.height_min;
00172     height_max_ = config.height_max;
00173     min_cluster_size_ = config.min_cluster_size;
00174     cluster_tolerance_ = config.cluster_tolerance;*/
00175     enable_action_mode_ = config.enable_action_mode;
00176     if(enable_action_mode_)
00177     {
00178       std::cout << "action mode not supported" << std::endl;
00179       //as_= new actionlib::SimpleActionServer<cob_3d_mapping_msgs::TableObjectClusterAction>(n_, "table_object_cluster", boost::bind(&TableObjectClusterNode::actionCallback, this, _1), false);
00180       //as_->start();
00181     }
00182     toc.setPrismHeight(config.height_min, config.height_max);
00183     toc.setClusterParams(config.min_cluster_size, config.cluster_tolerance);
00184   }
00185 
00186   bool
00187   setKnownObjects(cob_3d_mapping_msgs::SetBoundingBoxes::Request& req, cob_3d_mapping_msgs::SetBoundingBoxes::Response& res)
00188   {
00189     known_objects_.clear();
00190     for(unsigned int i=0; i<req.bounding_boxes.detections.size(); i++)
00191     {
00192       BoundingBox bb;
00193       bb.min_pt = Eigen::Vector4f(-req.bounding_boxes.detections[i].bounding_box_lwh.x,
00194                                   -req.bounding_boxes.detections[i].bounding_box_lwh.y, 0, 1.0);
00195       bb.max_pt = Eigen::Vector4f(req.bounding_boxes.detections[i].bounding_box_lwh.x,
00196                                   req.bounding_boxes.detections[i].bounding_box_lwh.y,
00197                                   req.bounding_boxes.detections[i].bounding_box_lwh.z, 1.0);
00198       Eigen::Affine3d tf;
00199       tf::poseMsgToEigen(req.bounding_boxes.detections[i].pose.pose , tf);
00200       bb.pose = tf.cast<float>();
00201       known_objects_.push_back(bb);
00202     }
00203     return true;
00204   }
00205 
00206   void
00207   compute(cob_object_detection_msgs::DetectionArray& bba,
00208           cob_perception_msgs::PointCloud2Array& pca)
00209   {
00210     pcl::PointCloud<Point>::Ptr pc_red(new pcl::PointCloud<Point>);
00211     toc.removeKnownObjects(last_pc_, known_objects_, pc_red);
00212     //*last_pc_ = *pc_red;
00213     toc.setInputCloud(pc_red);
00214     for(size_t i=0; i<last_sa_->shapes.size(); ++i)
00215     {
00216       //convert shape msgs to point cloud
00217       pcl::PointCloud<Point>::Ptr hull(new pcl::PointCloud<Point>);
00218       shape2hull<Point>(last_sa_->shapes[i], *hull);
00219 
00220       pcl::PointIndices::Ptr pc_roi(new pcl::PointIndices);
00221       PrecisionStopWatch sw;
00222       sw.precisionStart();
00223 
00224       // get points above table
00225       toc.extractTableRoi(hull, *pc_roi);
00226       ROS_INFO("ROI took %f seconds", sw.precisionStop());
00227       ROS_INFO("ROI has %d points", pc_roi->indices.size());
00228       if(!pc_roi->indices.size()) return;
00229 
00230       std::stringstream ss;
00231       if(save_to_file_)
00232       {
00233         ss << file_path_ << "/pc.pcd";
00234         pcl::io::savePCDFileASCII (ss.str(), *last_pc_);
00235         ss.str("");
00236         ss.clear();
00237         ss << file_path_ << "/hull.pcd";
00238         pcl::io::savePCDFileASCII (ss.str(), *hull);
00239         ss.str("");
00240         ss.clear();
00241         ss << file_path_ << "/table_roi.pcd";
00242         PointCloud roi;
00243         pcl::ExtractIndices<Point> extract_roi;
00244         extract_roi.setInputCloud (last_pc_);
00245         extract_roi.setIndices (pc_roi);
00246         extract_roi.filter (roi);
00247         pcl::io::savePCDFileASCII (ss.str(), roi);
00248         ss.str("");
00249         ss.clear();
00250       }
00251 
00252       std::vector<PointCloud::Ptr> object_clusters;
00253       std::vector<pcl::PointIndices> object_cluster_indices;
00254       sw.precisionStart();
00255       toc.extractClusters(pc_roi, object_clusters, object_cluster_indices);
00256       ROS_INFO("extract clusters took %f seconds", sw.precisionStop());
00257       sw.precisionStart();
00258       pca.segments.clear();
00259       pcl_conversions::fromPCL(last_pc_->header, pca.header);
00260       //pca.header = last_pc_->header;
00261 
00262       Eigen::Vector3f normal(last_sa_->shapes[i].params[0],
00263                              last_sa_->shapes[i].params[1],
00264                              last_sa_->shapes[i].params[2]);
00265       Eigen::Vector3f point(last_sa_->shapes[i].pose.position.x,
00266                             last_sa_->shapes[i].pose.position.y,
00267                             last_sa_->shapes[i].pose.position.z);
00268 
00269       bba.detections.clear();
00270       pcl_conversions::fromPCL(last_pc_->header, bba.header);
00271       //bba.header.stamp = last_pc_->header.stamp;
00272       //bba.header.frame_id = last_pc_->header.frame_id;
00273       pca.segments.resize(object_clusters.size());
00274       for(unsigned int j=0; j<object_clusters.size(); j++)
00275       {
00276         Eigen::Vector3f pos;
00277         Eigen::Quaternion<float> rot;
00278         Eigen::Vector3f size;
00279 
00280         toc.calculateBoundingBox(last_pc_, object_cluster_indices[j], normal, point, pos, rot, size);
00281 
00282         bba.detections.push_back(cob_object_detection_msgs::Detection());
00283         pcl_conversions::fromPCL(last_pc_->header, bba.detections.back().header);
00284         //bba.detections.back().header.stamp = last_pc_->header.stamp;
00285         //bba.detections.back().header.frame_id = last_pc_->header.frame_id;
00286         bba.detections.back().label = "Object Cluster";
00287         bba.detections.back().detector = "BoundingBoxDetector";
00288         bba.detections.back().score = 0;
00289         //bba.detections.back().mask;
00290         pcl_conversions::fromPCL(last_pc_->header, bba.detections.back().pose.header);
00291         //bba.detections.back().pose.header.stamp = last_pc_->header.stamp;
00292         //bba.detections.back().pose.header.frame_id = last_pc_->header.frame_id;
00293         cob_perception_common::EigenToROSMsg(pos,rot,bba.detections.back().pose.pose);
00294         cob_perception_common::EigenToROSMsg(size, bba.detections.back().bounding_box_lwh);
00295 
00296         pcl::toROSMsg(*object_clusters[j], pca.segments[j]);
00297         pcl_conversions::fromPCL(last_pc_->header, pca.segments[j].header);
00298         //pca.segments[j].header = last_pc_->header;
00299 
00300 
00301         if(save_to_file_)
00302         {
00303           ss << file_path_ << "/cl_" << j << ".pcd";
00304           pcl::io::savePCDFileASCII (ss.str(), *object_clusters[j]);
00305           ss.str("");
00306           ss.clear();
00307           /*
00308           ss << file_path_ << "/bb_" << j << ".pcd";
00309           pcl::io::savePCDFileASCII (ss.str(), bba[j]);
00310           ss.str("");
00311           ss.clear();
00312           */
00313         }
00314       }
00315       ROS_INFO("BB took %f seconds", sw.precisionStop());
00316       ROS_INFO("Computed %d bounding boxes", object_clusters.size());
00317     }
00318   }
00319 
00320 
00330   /*void
00331   actionCallback(const cob_3d_mapping_msgs::TableObjectClusterGoalConstPtr &goal)
00332   {
00333     //boost::lock_guard<boost::mutex> guard(mutex_);
00334     ROS_INFO("action callback");
00335     if(ctr_) deleteMarker(); // there is no assignment of ctr_ anywhere else
00336     ctr_= 0;
00337     cob_3d_mapping_msgs::TableObjectClusterFeedback feedback;
00338     cob_3d_mapping_msgs::TableObjectClusterResult result;
00339 
00340     cob_3d_mapping_msgs::GetBoundingBoxes srv;
00341     if(get_bb_client_.call(srv))
00342     {
00343       std::vector<pcl::PointCloud<pcl::PointXYZ>, Eigen::aligned_allocator<pcl::PointCloud<pcl::PointXYZ> > > known_objs;
00344       for(unsigned int i=0; i<srv.response.bounding_boxes.size(); i++)
00345       {
00346         pcl::PointCloud<pcl::PointXYZ> obj;
00347         pcl::fromROSMsg(srv.response.bounding_boxes[i], obj);
00348         known_objs.push_back(obj);
00349       }
00350       pcl::PointCloud<Point>::Ptr pc_red(new pcl::PointCloud<Point>);
00351       toc.removeKnownObjects(last_pc_, known_objs, *pc_red);
00352       *last_pc_ = *pc_red;
00353     }
00354     else
00355     {
00356       ROS_WARN("Failed to call service get_bounding_boxes");
00357     }
00358 
00359     //std::vector<pcl::PointCloud<pcl::PointXYZ> > bba;
00360     cob_object_detection_msgs::DetectionArray bba;
00361     cob_perception_msgs::PointCloud2Array pca;
00362     compute(bba, pca);
00363 
00364     bba_pub_.publish(bba);
00365     publishMarker(bba);
00366     object_cluster_pub_.publish(pca);
00367     result.bounding_boxes = bba;
00368     as_->setSucceeded(result);
00369   }*/
00370 
00371   void
00372   topicCallback(const PointCloud::ConstPtr& pc, const cob_3d_mapping_msgs::ShapeArray::ConstPtr& sa)
00373   {
00374     //boost::lock_guard<boost::mutex> guard(mutex_);
00375 
00376     *last_pc_ = *pc; // deep copy, required for removing points later on
00377     last_sa_ = sa; // copy shape array pointer
00378 
00379     ROS_INFO("Saved new PointCloud and %d potential tables", sa->shapes.size());
00380 
00381     if(enable_action_mode_) { return; }
00382 
00383     cob_object_detection_msgs::DetectionArray bba;
00384     cob_perception_msgs::PointCloud2Array pca;
00385     compute(bba, pca);
00386     publishMarker(bba);
00387     bba_pub_.publish(bba);
00388     object_cluster_pub_.publish(pca);
00389   }
00390 
00398   void
00399   publishMarker(cob_object_detection_msgs::DetectionArray& bba)
00400   {
00401     for(unsigned int i=0; i<bba.detections.size(); i++)
00402     {
00403       visualization_msgs::Marker marker;
00404       cob_perception_common::boundingBoxToMarker(bba.detections[i], marker);
00405 
00406       marker.lifetime = ros::Duration();
00407       marker.header.frame_id = bba.header.frame_id;
00408       marker.id = i;
00409 
00410       marker_pub_.publish(marker);
00411     }
00412   }
00413 
00414   void
00415   deleteMarker()
00416   {
00417     for( unsigned int i=0; i<ctr_; i++)
00418     {
00419       visualization_msgs::Marker marker;
00420       marker.action = visualization_msgs::Marker::DELETE;
00421       marker.id = i;
00422       marker_pub_.publish(marker);
00423     }
00424   }
00425 
00426 
00427   ros::NodeHandle n_;
00428 
00429 
00430 protected:
00431   actionlib::SimpleActionServer<cob_3d_mapping_msgs::TableObjectClusterAction>* as_;
00432   //ros::ServiceClient get_bb_client_;
00433         ros::ServiceServer set_known_objects_server_;
00434   ros::Publisher bba_pub_;
00435   ros::Publisher marker_pub_;
00436   ros::Publisher object_cluster_pub_;
00437   boost::shared_ptr<message_filters::Synchronizer<MySyncPolicy> > sync_;
00438   message_filters::Subscriber<PointCloud> pc_sub_;
00439   message_filters::Subscriber<cob_3d_mapping_msgs::ShapeArray> sa_sub_;
00440   dynamic_reconfigure::Server<table_object_cluster_nodeletConfig> config_server_;
00441 
00442   boost::mutex mutex_;
00443 
00444   TableObjectCluster<Point> toc;       
00445   unsigned int ctr_;
00446 
00447   bool save_to_file_;
00448   std::string file_path_;
00449   /*double height_min_;           /// paramter for object detection
00450   double height_max_;           /// paramter for object detection
00451   int min_cluster_size_;        /// paramter for object detection
00452   double cluster_tolerance_;    /// paramter for object detection*/
00453   bool enable_action_mode_;
00454 
00455   PointCloud::Ptr last_pc_;
00456   cob_3d_mapping_msgs::ShapeArray::ConstPtr last_sa_;
00457         std::vector<BoundingBox> known_objects_;
00458 };
00459 
00460 
00461 int main (int argc, char** argv)
00462 {
00463   ros::init (argc, argv, "table_object_cluster_node");
00464 
00465   TableObjectClusterNode toc;
00466 
00467   ros::Rate loop_rate(10);
00468   while (ros::ok())
00469   {
00470     ros::spinOnce ();
00471     loop_rate.sleep();
00472   }
00473 }
00474 


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