Go to the documentation of this file.00001 #include "ros/ros.h"
00002 #include "sensor_msgs/PointCloud2.h"
00003 #include "sensor_msgs/point_cloud_conversion.h"
00004
00005 #include <boost/make_shared.hpp>
00006 #include "pcl/io/pcd_io.h"
00007 #include <pcl/features/fpfh_omp.h>
00008 #include <pcl/kdtree/kdtree_flann.h>
00009 #include <pcl/features/normal_3d_omp.h>
00010 #include "pcl/filters/voxel_grid.h"
00011
00012
00013 #include "feature_extractor_fpfh/FPFHCalc.h"
00014
00015 using namespace pcl;
00016 using namespace std;
00017 typedef KdTree<PointXYZ>::Ptr KdTreePtr;
00018
00019
00020 bool fpfh_cb(feature_extractor_fpfh::FPFHCalc::Request &req,
00021 feature_extractor_fpfh::FPFHCalc::Response &res)
00022 {
00023 float leaf_size = .01;
00024 pcl::VoxelGrid<sensor_msgs::PointCloud2> sor;
00025 sensor_msgs::PointCloud2::Ptr input_cloud(new sensor_msgs::PointCloud2());
00026 sensor_msgs::convertPointCloudToPointCloud2(req.input, *input_cloud);
00027
00028
00029 sensor_msgs::PointCloud2::Ptr cloud_filtered(new sensor_msgs::PointCloud2());
00030 sor.setInputCloud(input_cloud);
00031 sor.setLeafSize (leaf_size, leaf_size, leaf_size);
00032 sor.filter(*cloud_filtered);
00033 ROS_INFO("after filtering: %d points", cloud_filtered->width * cloud_filtered->height);
00034
00035 PointCloud<PointXYZ> cloud;
00036 fromROSMsg(*cloud_filtered, cloud);
00037 std::vector<int> indices;
00038 indices.resize (cloud.points.size());
00039 for (size_t i = 0; i < indices.size (); ++i) { indices[i] = i; }
00040
00041
00042 KdTreePtr tree;
00043 tree.reset(new KdTreeFLANN<PointXYZ> (false));
00044 tree->setInputCloud(cloud.makeShared());
00045
00046 PointCloud<Normal>::Ptr normals(new PointCloud<Normal>());
00047 boost::shared_ptr< vector<int> > indicesptr(new vector<int> (indices));
00048 NormalEstimation<PointXYZ, Normal> normal_estimator;
00049
00050
00051 normal_estimator.setIndices(indicesptr);
00052 normal_estimator.setSearchMethod(tree);
00053 normal_estimator.setKSearch(10);
00054
00055
00056 ROS_INFO("Calculating normals...\n");
00057 normal_estimator.setInputCloud(cloud.makeShared());
00058 normal_estimator.compute(*normals);
00059
00060
00061
00062 FPFHEstimationOMP<PointXYZ, Normal, FPFHSignature33> fpfh(4);
00063
00064
00065 PointCloud<FPFHSignature33>::Ptr fphists (new PointCloud<FPFHSignature33>());
00066
00067
00068 int d1, d2, d3;
00069 d1 = d2 = d3 = 11;
00070 fpfh.setNrSubdivisions(d1, d2, d3);
00071 fpfh.setIndices(indicesptr);
00072 fpfh.setSearchMethod(tree);
00073 fpfh.setKSearch(50);
00074
00075
00076 ROS_INFO("Calculating fpfh...\n");
00077 fpfh.setInputNormals(normals);
00078 fpfh.setInputCloud(cloud.makeShared());
00079 fpfh.compute(*fphists);
00080
00081 res.hist.dim[0] = d1;
00082 res.hist.dim[1] = d2;
00083 res.hist.dim[2] = d3;
00084 unsigned int total_size = d1+d2+d3;
00085 res.hist.histograms.resize(total_size * cloud.points.size());
00086 res.hist.points3d.resize(3*cloud.points.size());
00087
00088 ROS_INFO("copying into message...\n");
00089 for (unsigned int i = 0; i < cloud.points.size(); i++)
00090 {
00091 for (unsigned int j = 0; j < total_size; j++)
00092 {
00093 res.hist.histograms[i*total_size + j] = fphists->points[i].histogram[j];
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103 }
00104
00105 res.hist.points3d[3*i] = cloud.points[i].x;
00106 res.hist.points3d[3*i+1] = cloud.points[i].y;
00107 res.hist.points3d[3*i+2] = cloud.points[i].z;
00108
00109
00110
00111
00112 }
00113
00114 res.hist.npoints = cloud.points.size();
00115 ROS_INFO("done.\n");
00116
00117
00118
00119 return true;
00120 }
00121
00122
00123
00124 int main(int argc, char **argv)
00125 {
00126 ros::init(argc, argv, "fpfh_feature_extractor");
00127 ros::NodeHandle n;
00128
00129
00130 ros::ServiceServer fpfh_service = n.advertiseService("fpfh", fpfh_cb);
00131
00132
00133 ROS_INFO("ready.\n");
00134 ros::spin();
00135 return 0;
00136 }
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151