00001 #include <segment_cluster_creator.hpp>
00002 #include <boost/date_time/posix_time/posix_time.hpp>
00003 #include <boost/date_time/posix_time/posix_time_io.hpp>
00004
00005 using namespace pcl;
00006
00007 EuclideanCluster::EuclideanCluster(ros::NodeHandle nh, ros::NodeHandle n)
00008 : nh_(nh),
00009 rate_(n.param("loop_rate", 10)),
00010 accumulation_counter_(0),
00011 frame_id_(n.param<std::string>("clustering_frame_id", "base_link"))
00012 {
00013 source_pc_sub_ = nh_.subscribe(n.param<std::string>("source_pc_topic_name", "/hokuyo3d/hokuyo_cloud2"), 1, &EuclideanCluster::EuclideanCallback, this);
00014 fileterd_cloud_pub_ = nh_.advertise<sensor_msgs::PointCloud2>(n.param<std::string>("filtered_pc_topic_name", "/filtered_pointcloud"), 1);
00015 euclidean_cluster_pub_ = nh_.advertise<jsk_recognition_msgs::BoundingBoxArray>(n.param<std::string>("box_name", "/clustering_result"), 1);
00016
00017
00018 n.param<double>("clusterTolerance", clusterTolerance_, 0.3);
00019 n.param<int>("minSize", minSize_, 100);
00020 n.param<int>("maxSize", maxSize_, 25000);
00021
00022 n.param<float>("crop_x_min", crop_min_.x, -35.5);
00023 n.param<float>("crop_x_max", crop_max_.x, 35.5);
00024 n.param<float>("crop_y_min", crop_min_.y, -35.5);
00025 n.param<float>("crop_y_max", crop_max_.y, 35.5);
00026 n.param<float>("crop_z_min", crop_min_.z, 0.05);
00027 n.param<float>("crop_z_max", crop_max_.z, 15.5);
00028
00029 boost::posix_time::ptime thistime = boost::posix_time::from_time_t(ros::Time::now().toSec());
00030 output_file_prefix_ = to_simple_string(thistime) + "Cluster_";
00031 }
00032
00033 void EuclideanCluster::EuclideanCallback(
00034 const sensor_msgs::PointCloud2::ConstPtr &source_pc) {
00035
00036
00037
00038 sensor_msgs::PointCloud2 trans_pc;
00039 try {
00040 pcl_ros::transformPointCloud(frame_id_, *source_pc, trans_pc, tf_);
00041 } catch (tf::ExtrapolationException e) {
00042 ROS_ERROR("pcl_ros::transformPointCloud %s", e.what());
00043 }
00044
00045
00046 pcl::PointCloud<PointXYZI> pcl_source;
00047 pcl::fromROSMsg(trans_pc, pcl_source);
00048 pcl::PointCloud<PointXYZI>::Ptr pcl_source_ptr(new pcl::PointCloud<PointXYZI>(pcl_source));
00049
00050
00051
00052
00053
00054
00055 pcl::StatisticalOutlierRemoval<pcl::PointXYZI> sor;
00056 sor.setInputCloud (pcl_source_ptr);
00057 sor.setMeanK (100);
00058 sor.setStddevMulThresh (0.1);
00059 sor.filter (*pcl_source_ptr);
00060
00061
00062 CropBox(pcl_source_ptr, crop_min_, crop_max_);
00063
00064
00065 sensor_msgs::PointCloud2 filtered_pc2;
00066 pcl::toROSMsg(*pcl_source_ptr, filtered_pc2);
00067 filtered_pc2.header.stamp = ros::Time::now();
00068 filtered_pc2.header.frame_id = "base_link";
00069 fileterd_cloud_pub_.publish(filtered_pc2);
00070
00071
00072 Clustering(pcl_source_ptr);
00073 }
00074
00075 void EuclideanCluster::CropBox(pcl::PointCloud<pcl::PointXYZI>::Ptr cloud,
00076 pcl::PointXYZ min, pcl::PointXYZ max) {
00077 Eigen::Vector4f minPoint;
00078
00079 minPoint[0] = min.x;
00080 minPoint[1] = min.y;
00081 minPoint[2] = min.z;
00082
00083 Eigen::Vector4f maxPoint;
00084 maxPoint[0] = max.x;
00085 maxPoint[1] = max.y;
00086 maxPoint[2] = max.z;
00087
00088 Eigen::Vector3f boxTranslatation;
00089 boxTranslatation[0] = 0;
00090 boxTranslatation[1] = 0;
00091 boxTranslatation[2] = 0;
00092
00093 Eigen::Vector3f boxRotation;
00094 boxRotation[0] = 0;
00095 boxRotation[1] = 0;
00096 boxRotation[2] = 0;
00097
00098 Eigen::Affine3f boxTransform;
00099
00100 pcl::CropBox<pcl::PointXYZI> cropFilter;
00101 cropFilter.setInputCloud(cloud);
00102 cropFilter.setMin(minPoint);
00103 cropFilter.setMax(maxPoint);
00104 cropFilter.setTranslation(boxTranslatation);
00105 cropFilter.setRotation(boxRotation);
00106
00107 pcl::PointCloud<pcl::PointXYZI>::Ptr cloud_filtered(new pcl::PointCloud<pcl::PointXYZI>());
00108 cropFilter.filter(*cloud_filtered);
00109 pcl::copyPointCloud<pcl::PointXYZI, pcl::PointXYZI>(*cloud_filtered, *cloud);
00110 }
00111
00112 void EuclideanCluster::Clustering(pcl::PointCloud<pcl::PointXYZI>::Ptr cloud) {
00113 pcl::search::KdTree<pcl::PointXYZI>::Ptr tree(new pcl::search::KdTree<pcl::PointXYZI>);
00114 tree->setInputCloud(cloud);
00115
00116 std::vector<pcl::PointIndices> cluster_indices;
00117 pcl::EuclideanClusterExtraction<pcl::PointXYZI> ec;
00118 ec.setClusterTolerance(clusterTolerance_);
00119 ec.setMinClusterSize(minSize_);
00120 ec.setMaxClusterSize(maxSize_);
00121 ec.setSearchMethod(tree);
00122 ec.setInputCloud(cloud);
00123 ec.extract(cluster_indices);
00124
00125 int j = 0;
00126 jsk_recognition_msgs::BoundingBoxArray box_array;
00127
00128 for (std::vector<pcl::PointIndices>::const_iterator it = cluster_indices.begin(); it != cluster_indices.end(); ++it) {
00129 pcl::PointCloud<pcl::PointXYZI>::Ptr cloud_cluster(new pcl::PointCloud<pcl::PointXYZI>);
00130 for (std::vector<int>::const_iterator pit = it->indices.begin(); pit != it->indices.end(); ++pit)
00131 cloud_cluster->points.push_back(cloud->points[*pit]);
00132
00133 cloud_cluster->width = cloud_cluster->points.size();
00134 cloud_cluster->height = 1;
00135 cloud_cluster->is_dense = true;
00136
00137 std::stringstream filename;
00138 filename << output_file_prefix_ << std::setw(4) << std::setfill('0') << accumulation_counter_;
00139 pcl::io::savePCDFileASCII ("./"+filename.str()+".pcd" , *cloud_cluster);
00140
00141 j++;
00142 accumulation_counter_++;
00143 }
00144
00145
00146 ROS_INFO("Found %lu clusters:", cluster_indices.size());
00147
00148
00149 cluster_indices.clear();
00150 }
00151
00152
00153
00154 void EuclideanCluster::run()
00155 {
00156 while(nh_.ok()){
00157 ros::spinOnce();
00158 rate_.sleep();
00159 }
00160 }