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
00024
00025
00026
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
00032 cloud_subscriber_ = public_node_handle_.subscribe("cloud", 0, &CylinderDetectorAlgNode::cloud_callback, this);
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043 MarkerArray_msg_.markers.resize(2);
00044 }
00045
00046 CylinderDetectorAlgNode::~CylinderDetectorAlgNode(void)
00047 {
00048
00049 }
00050
00051 void CylinderDetectorAlgNode::mainNodeThread(void)
00052 {
00053
00054
00055
00056
00057
00058
00059
00060 }
00061
00062
00063 void CylinderDetectorAlgNode::cloud_callback(const sensor_msgs::PointCloud2::ConstPtr& msg)
00064 {
00065 ROS_DEBUG("CylinderDetectorAlgNode::cloud_callback: New Message Received");
00066
00067
00068
00069
00070
00071
00072 pcl::PointCloud<pcl::PointXYZ>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZ> ());
00073 pcl::fromROSMsg(*msg, *cloud);
00074
00075
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
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
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
00115
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
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
00153 pcl::toROSMsg(*cloud,PointCloud2_msg_);
00154 cloud_filtered_publisher_.publish(PointCloud2_msg_);
00155
00156 if( cloud->points.size()>0)
00157 {
00158
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
00168 MarkerArray_msg_.markers[0].action = MarkerArray_msg_.markers[1].action = visualization_msgs::Marker::ADD;
00169
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
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
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
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
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
00202
00203
00204 }
00205
00206
00207
00208
00209
00210
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
00224 int main(int argc,char *argv[])
00225 {
00226 return algorithm_base::main<CylinderDetectorAlgNode>(argc, argv, "cylinder_detector_alg_node");
00227 }