cylinder_detector_alg_node.cpp
Go to the documentation of this file.
00001 #include "cylinder_detector_alg_node.h"
00002 #include <pcl/ros/conversions.h>
00003 #include <pcl/point_cloud.h>
00004 #include <pcl/point_types.h>
00005 #include <pcl/io/pcd_io.h>
00006 #include <pcl/filters/passthrough.h>
00007 #include <pcl/filters/voxel_grid.h>
00008 #include <pcl/filters/statistical_outlier_removal.h>
00009 #include <pcl/ModelCoefficients.h>
00010 #include <pcl/features/normal_3d.h>
00011 #include <pcl/sample_consensus/method_types.h>
00012 #include <pcl/sample_consensus/model_types.h>
00013 #include <pcl/segmentation/sac_segmentation.h>
00014 #include <pcl/filters/extract_indices.h>
00015 #include <tf/transform_datatypes.h>
00016 
00017 using namespace std;
00018 
00019 CylinderDetectorAlgNode::CylinderDetectorAlgNode(void) :
00020   algorithm_base::IriBaseAlgorithm<CylinderDetectorAlgorithm>()
00021 {
00022   ROS_INFO("Cylinder Detector Running");
00023   //init class attributes if necessary
00024   //this->loop_rate_ = 2;//in [Hz]
00025 
00026   // [init publishers]
00027   marker_publisher_         = public_node_handle_.advertise<visualization_msgs::MarkerArray>("marker",         0);
00028   cloud_filtered_publisher_ = public_node_handle_.advertise<sensor_msgs::PointCloud2>       ("cloud_filtered", 0);
00029   pose_publisher_           = public_node_handle_.advertise<geometry_msgs::PoseStamped>     ("pose",           0);
00030   
00031   // [init subscribers]
00032   cloud_subscriber_ = public_node_handle_.subscribe("cloud", 0, &CylinderDetectorAlgNode::cloud_callback, this);
00033   
00034   // [init services]
00035   
00036   // [init clients]
00037   
00038   // [init action servers]
00039   
00040   // [init action clients]
00041    
00042   
00043   MarkerArray_msg_.markers.resize(2);
00044 }
00045 
00046 CylinderDetectorAlgNode::~CylinderDetectorAlgNode(void)
00047 {
00048   // [free dynamic memory]
00049 }
00050 
00051 void CylinderDetectorAlgNode::mainNodeThread(void)
00052 {
00053   // [fill msg structures]
00054   
00055   // [fill srv structure and make request to the server]
00056   
00057   // [fill action structure and make request to the action server]
00058 
00059   // [publish messages]
00060 }
00061 
00062 /*  [subscriber callbacks] */
00063 void CylinderDetectorAlgNode::cloud_callback(const sensor_msgs::PointCloud2::ConstPtr& msg) 
00064 { 
00065   ROS_DEBUG("CylinderDetectorAlgNode::cloud_callback: New Message Received"); 
00066 
00067   //use appropiate mutex to shared variables if necessary 
00068   //this->alg_.lock(); 
00069   //this->cloud_mutex_.enter(); 
00070 
00071   // Transformar pointcloud2 a pcl pointcloud
00072   pcl::PointCloud<pcl::PointXYZ>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZ> ());
00073   pcl::fromROSMsg(*msg, *cloud);
00074 
00075   // Filtrar area
00076   float xmin=-3.0,xmax=3.0;
00077   float ymin=-3.0,ymax=3.0;
00078   float zmin=-1.0,zmax=1.0;
00079   ros::Time begin = ros::Time::now();
00080   pcl::PassThrough<pcl::PointXYZ> pass;
00081   pass.setInputCloud (cloud); 
00082   pass.setFilterFieldName ("x");
00083   pass.setFilterLimits (xmin, xmax);
00084   pass.filter (*cloud);
00085   pass.setFilterFieldName ("y");
00086   pass.setFilterLimits (ymin, ymax);
00087   pass.filter (*cloud);
00088   pass.setFilterFieldName ("z");
00089   pass.setFilterLimits (zmin, zmax);
00090   pass.filter (*cloud);
00091   ROS_DEBUG_STREAM("Filtered by fields: " << cloud->points.size ());
00092   ROS_DEBUG_STREAM("Fbf time:" << (ros::Time::now() - begin));
00093 
00094   // downsample
00095   begin = ros::Time::now();
00096   pcl::VoxelGrid<pcl::PointXYZ> vg;
00097   vg.setInputCloud (cloud);
00098   vg.setLeafSize (0.05f, 0.05f, 0.05f);
00099   vg.filter (*cloud);
00100   ROS_DEBUG_STREAM("Downsampled: " << cloud->points.size ());
00101   ROS_DEBUG_STREAM("VG time:" << (ros::Time::now() - begin));
00102 
00103   // remove outliers
00104   begin = ros::Time::now();
00105   pcl::StatisticalOutlierRemoval<pcl::PointXYZ> sor;
00106   sor.setInputCloud (cloud);
00107   sor.setMeanK (50);
00108   sor.setStddevMulThresh (0.1);
00109   sor.filter (*cloud);
00110   ROS_DEBUG_STREAM("Removed outliers: " << cloud->points.size ());
00111   ROS_DEBUG_STREAM("SOR time:" << (ros::Time::now() - begin));
00112 
00113   begin = ros::Time::now();
00114   // trobar cilindre(s)
00115   //Estimate point normals
00116   pcl::NormalEstimation<pcl::PointXYZ, pcl::Normal> ne;
00117   pcl::search::KdTree<pcl::PointXYZ>::Ptr  tree (new pcl::search::KdTree<pcl::PointXYZ> ());
00118   pcl::PointCloud<pcl::Normal>::Ptr        cloud_normals (new pcl::PointCloud<pcl::Normal> ());
00119   ne.setSearchMethod (tree);
00120   ne.setInputCloud (cloud);
00121   ne.setKSearch (5);
00122   ne.compute (*cloud_normals);
00123   ROS_DEBUG_STREAM("Normals time:" << (ros::Time::now() - begin));
00124 
00125   // Create the segmentation object for cylinder segmentation and set all the parameters
00126   begin = ros::Time::now();
00127   pcl::SACSegmentationFromNormals<pcl::PointXYZ, pcl::Normal> seg;
00128   pcl::ModelCoefficients::Ptr coefficients_cylinder (new pcl::ModelCoefficients);
00129   pcl::PointIndices::Ptr      inliers_cylinder (new pcl::PointIndices);
00130   seg.setOptimizeCoefficients (true);
00131   seg.setModelType (pcl::SACMODEL_CYLINDER);
00132   seg.setMethodType (pcl::SAC_RANSAC);
00133   seg.setNormalDistanceWeight (0.1);
00134   seg.setMaxIterations (5000);
00135   seg.setDistanceThreshold (0.02);
00136   seg.setRadiusLimits (0.15,0.25);
00137   seg.setInputCloud (cloud);
00138   seg.setInputNormals (cloud_normals);
00139   seg.segment (*inliers_cylinder, *coefficients_cylinder);
00140   ROS_DEBUG_STREAM("Cylinder coefficients: " << *coefficients_cylinder);
00141   ROS_DEBUG_STREAM("Seg time:" << (ros::Time::now() - begin));
00142 
00143   begin = ros::Time::now();
00144   pcl::ExtractIndices<pcl::PointXYZ> extract;
00145   extract.setInputCloud (cloud);
00146   extract.setIndices (inliers_cylinder);
00147   extract.setNegative (false);
00148   extract.filter (*cloud);
00149   ROS_DEBUG_STREAM("Extracted: " << cloud->points.size ());
00150   ROS_DEBUG_STREAM("Extract time:" << (ros::Time::now() - begin));
00151   
00152   // Cylinder Cloud Publisher
00153   pcl::toROSMsg(*cloud,PointCloud2_msg_);
00154   cloud_filtered_publisher_.publish(PointCloud2_msg_);
00155 
00156   if( cloud->points.size()>0)
00157   {
00158     // POSE
00159     PoseStamped_msg_.header.stamp    = ros::Time::now();
00160     PoseStamped_msg_.header.frame_id = msg->header.frame_id;
00161     PoseStamped_msg_.pose.position.x = coefficients_cylinder->values[0];
00162     PoseStamped_msg_.pose.position.y = coefficients_cylinder->values[1];
00163     PoseStamped_msg_.pose.position.z = coefficients_cylinder->values[2];
00164     PoseStamped_msg_.pose.orientation.x = PoseStamped_msg_.pose.orientation.y = PoseStamped_msg_.pose.orientation.z = 0;
00165     PoseStamped_msg_.pose.orientation.w = 1;
00166     pose_publisher_.publish(PoseStamped_msg_);
00167     // MARKERS ADD
00168     MarkerArray_msg_.markers[0].action = MarkerArray_msg_.markers[1].action = visualization_msgs::Marker::ADD;
00169      // CYLINDER AND TEXT
00170     MarkerArray_msg_.markers[0].header.frame_id = MarkerArray_msg_.markers[1].header.frame_id = msg->header.frame_id;
00171     MarkerArray_msg_.markers[0].header.stamp = MarkerArray_msg_.markers[1].header.stamp = ros::Time::now();
00172     MarkerArray_msg_.markers[0].id = MarkerArray_msg_.markers[1].id = 0;
00173     MarkerArray_msg_.markers[0].pose = MarkerArray_msg_.markers[1].pose = PoseStamped_msg_.pose;
00174     MarkerArray_msg_.markers[0].lifetime = MarkerArray_msg_.markers[1].lifetime = ros::Duration();
00175     //red
00176     MarkerArray_msg_.markers[0].color.r = MarkerArray_msg_.markers[1].color.r = 1.0;
00177     MarkerArray_msg_.markers[0].color.g = MarkerArray_msg_.markers[1].color.g = 0.0;
00178     MarkerArray_msg_.markers[0].color.b = MarkerArray_msg_.markers[1].color.b = 0.0;
00179     // ONLY CYLINDER
00180     MarkerArray_msg_.markers[0].ns = "cylinder";
00181     MarkerArray_msg_.markers[0].type = visualization_msgs::Marker::CYLINDER;
00182     MarkerArray_msg_.markers[0].pose.position.z = -0.2;
00183     MarkerArray_msg_.markers[0].scale.x = 0.4;
00184     MarkerArray_msg_.markers[0].scale.y = 0.4;
00185     MarkerArray_msg_.markers[0].scale.z = 2;
00186     MarkerArray_msg_.markers[0].color.a = 0.4;
00187     // ONLY TEXT
00188     MarkerArray_msg_.markers[1].ns = "text";
00189     MarkerArray_msg_.markers[1].type = visualization_msgs::Marker::TEXT_VIEW_FACING;
00190     MarkerArray_msg_.markers[1].text = alg_.config_.markertext;
00191     MarkerArray_msg_.markers[1].pose.position.z = 1;
00192     MarkerArray_msg_.markers[1].scale.z = 0.3;
00193     MarkerArray_msg_.markers[1].color.a = 1.0;
00194   }else{
00195     // MARKERS DELETE
00196     MarkerArray_msg_.markers[0].action = MarkerArray_msg_.markers[1].action = visualization_msgs::Marker::DELETE; 
00197   }
00198   
00199   marker_publisher_.publish(MarkerArray_msg_);  
00200     
00201   //unlock previously blocked shared variables 
00202   //this->alg_.unlock(); 
00203   //this->cloud_mutex_.exit(); 
00204 }
00205 
00206 /*  [service callbacks] */
00207 
00208 /*  [action callbacks] */
00209 
00210 /*  [action requests] */
00211 
00212 void CylinderDetectorAlgNode::node_config_update(Config &config, uint32_t level)
00213 {
00214   this->alg_.lock();
00215 
00216   this->alg_.unlock();
00217 }
00218 
00219 void CylinderDetectorAlgNode::addNodeDiagnostics(void)
00220 {
00221 }
00222 
00223 /* main function */
00224 int main(int argc,char *argv[])
00225 {
00226   return algorithm_base::main<CylinderDetectorAlgNode>(argc, argv, "cylinder_detector_alg_node");
00227 }


iri_cylinder_detector
Author(s): mmorta
autogenerated on Fri Dec 6 2013 20:52:06