fpfh_primitives.cpp
Go to the documentation of this file.
00001 
00068 #include "cob_3d_mapping_tools/point_generator.h"
00069 #include <cob_3d_mapping_common/label_defines.h>
00070 
00071 #include <pcl/io/pcd_io.h>
00072 #include <pcl/point_cloud.h>
00073 #include <pcl/visualization/pcl_visualizer.h>
00074 #include <pcl/visualization/histogram_visualizer.h>
00075 #include <pcl/visualization/point_cloud_handlers.h>
00076 #include <pcl/kdtree/kdtree_flann.h>
00077 #include <pcl/kdtree/kdtree.h>
00078 #include <pcl/features/normal_3d.h>
00079 #include <pcl/features/fpfh.h>
00080 
00081 #include <sys/time.h>
00082 #include <sys/resource.h>
00083 
00084 #include <boost/program_options.hpp>
00085 
00086 using namespace std;
00087 using namespace pcl;
00088 
00089 typedef Eigen::Vector3f Vec;
00090 typedef visualization::PointCloudColorHandlerRGBField<PointXYZ> ColorHdlRGBA;
00091 
00092 string folder_;
00093 bool vis_, pl, ed, co, cy, sp;
00094 float step_;
00095 float noise_;
00096 float rn_;
00097 float rf_;
00098 float r_;
00099 
00100 
00101 struct ft_config
00102 {
00103   float s;
00104   float rng;
00105   float rn;
00106   float rf;
00107   string file_name;
00108 };
00109 
00110 void readOptions(int argc, char* argv[])
00111 {
00112   using namespace boost::program_options;
00113   
00114   options_description cmd_line("Options");
00115   cmd_line.add_options()
00116     ("help,h", "produce help messsage")
00117     ("out,o", value<string>(&folder_), "output folder")
00118     ("step,s", value<float>(&step_)->default_value(0.005f), "define point density")
00119     ("noise,g", value<float>(&noise_)->default_value(0.0f), "add gaussian noise")
00120     ("normal,n", value<float>(&rn_)->default_value(0.015f),
00121      "neighborood radius normal estimation")
00122     ("feature,f", value<float>(&rf_)->default_value(0.025f), 
00123      "neighborood radius feature estimation")
00124     ("shaperadius,r", value<float>(&r_)->default_value(0.05f), 
00125      "radius for size of cylinder and spheres")
00126     ("vis,v", "enable visualization")
00127     ("plane,P", "enable plane")
00128     ("edge,E", "enable edge")
00129     ("corner,C", "enable corner")
00130     ("sphere,S", "enable sphere")
00131     ("cylinder,Z", "enable cylinder")
00132     ;
00133 
00134   variables_map vm;
00135   store(command_line_parser(argc, argv)
00136         .options(cmd_line).run(), vm);
00137   notify(vm);
00138 
00139   if (vm.count("help"))
00140   {
00141     cout << "Generates FPFH of a single point on various shapes" << endl;
00142     cout << "TODO: For some shape sizes the point not always lies in the center of the shape" << endl;
00143     cout << cmd_line << endl;
00144     exit(0);
00145   }
00146   if (vm.count("vis")) vis_ = true;
00147   else vis_ = false;
00148   if (vm.count("plane")) pl = true;
00149   else pl = false;
00150   if (vm.count("edge")) ed = true;
00151   else ed = false;
00152   if (vm.count("corner")) co = true;
00153   else co = false;
00154   if (vm.count("cylinder")) cy = true;
00155   else cy = false;
00156   if (vm.count("sphere")) sp = true;
00157   else sp = false;
00158 }
00159 
00160 // convert a float to string
00161 string fl2label(const float & f, const size_t & precision)
00162 {
00163   if (f == 0) 
00164     return string(precision, '0');
00165 
00166   stringstream ss;
00167   ss << f;
00168   string s = ss.str();
00169   s = s.substr(2,s.length());
00170   if (precision > s.length())
00171     s += string(precision - s.length(), '0');
00172   return (s);
00173 }
00174 
00175 void generateName(ft_config * cfg, string shape)
00176 {
00177   string name = fl2label(cfg->rf, 3) + "rf_" 
00178     + fl2label(cfg->rn, 3) + "rn_" 
00179     + fl2label(cfg->rng, 4) + "rng_"
00180     + fl2label(cfg->s, 4) + "s_"
00181     + shape + ".pcd";
00182   cfg->file_name = name;
00183 }
00184 
00185 void generateFeature(ft_config * cfg, PointCloud<PointXYZ>::Ptr & p_in,
00186                      PointCloud<Normal>::Ptr & normal_out)
00187 {
00188   PointCloud<FPFHSignature33>::Ptr fpfh (new PointCloud<FPFHSignature33>);
00189   vector<float> d;
00190   #ifdef PCL_VERSION_COMPARE //fuerte
00191     pcl::search::KdTree<PointXYZ>::Ptr tree (new pcl::search::KdTree<PointXYZ>());
00192   #else //electric
00193     pcl::KdTreeFLANN<PointXYZ>::Ptr tree (new pcl::KdTreeFLANN<PointXYZ> ());
00194   #endif
00195   tree->setInputCloud(p_in);
00196 
00197   NormalEstimation<PointXYZ, Normal> norm;
00198   norm.setInputCloud(p_in);
00199   norm.setSearchMethod(tree);
00200   norm.setRadiusSearch(cfg->rn);
00201   norm.compute(*normal_out);
00202 
00203   FPFHEstimation<PointXYZ, Normal, FPFHSignature33> fpfhE;
00204   fpfhE.setInputCloud(p_in);
00205   fpfhE.setInputNormals(normal_out);
00206   fpfhE.setSearchMethod(tree);
00207   fpfhE.setRadiusSearch(cfg->rf);
00208   fpfhE.compute(*fpfh);
00209 
00210   if (!folder_.empty()) io::savePCDFileASCII<FPFHSignature33>(folder_ + cfg->file_name, *fpfh);
00211 }
00212 
00213 void plane (ft_config * cfg, PointCloud<PointXYZ>::Ptr & out, 
00214             PointCloud<Normal>::Ptr & normal_out)
00215 {
00216   cob_3d_mapping_tools::PointGenerator<PointXYZ> pg;
00217   pg.setGaussianNoise(cfg->rng);
00218   pg.setOutputCloud(out);
00219   pg.generatePlane(cfg->s, 0.25f * Vec::UnitZ(), 0.2f * Vec::UnitX(), 0.2f * Vec::UnitY());
00220   generateName(cfg, "plane");
00221   generateFeature(cfg, out, normal_out);
00222 }
00223 
00224 void edge (ft_config * cfg, PointCloud<PointXYZ>::Ptr & out, 
00225                  PointCloud<Normal>::Ptr & normal_out)
00226 {
00227   Vec o(0.0, 0.0, 0.25);
00228   cob_3d_mapping_tools::PointGenerator<PointXYZ> pg;
00229   pg.setGaussianNoise(cfg->rng);
00230   pg.setOutputCloud(out);
00231   pg.generateEdge(cfg->s, o, 0.5f * Vec::UnitX(), Vec(0.0f, 1.0f, 1.0f).normalized() * 0.05f);
00232   pg.generateEdge(cfg->s, -o, 0.5f * Vec::UnitX(), Vec(0.0f, 1.0f, 1.0f).normalized() * 0.05f);
00233   generateName(cfg, "edge");
00234   generateFeature(cfg, out, normal_out);
00235 }
00236 
00237 void edge_concave(ft_config * cfg, PointCloud<PointXYZ>::Ptr & out, 
00238                   PointCloud<Normal>::Ptr & normal_out)
00239 {
00240   Vec o(0.0, 0.0, 0.25);
00241   cob_3d_mapping_tools::PointGenerator<PointXYZ> pg;
00242   pg.setGaussianNoise(cfg->rng);
00243   pg.setOutputCloud(out);
00244   pg.generateEdge(cfg->s, o, -0.5f * Vec::UnitX(), Vec(0.0f, 1.0f, -1.0f).normalized() * 0.2f);
00245   generateName(cfg, "edge_concave_");
00246   generateFeature(cfg, out, normal_out);
00247 }
00248 
00249 void corner(ft_config * cfg, PointCloud<PointXYZ>::Ptr & out, 
00250                    PointCloud<Normal>::Ptr & normal_out)
00251 {
00252   Vec o(0.0, 0.25, 0.25);
00253   cob_3d_mapping_tools::PointGenerator<PointXYZ> pg;
00254   pg.setGaussianNoise(cfg->rng);
00255   pg.setOutputCloud(out);
00256   pg.generateCorner(cfg->s, o, Vec::UnitX() + Vec::UnitZ(), Vec::UnitY(),
00257                     -Vec::UnitX() + Vec::UnitZ(), 0.05f);
00258   pg.generateCorner(cfg->s, -o, Vec::UnitX() + Vec::UnitZ(), Vec::UnitY(),
00259                     -Vec::UnitX() + Vec::UnitZ(), 0.05f);
00260   generateName(cfg, "corner");
00261   generateFeature(cfg, out, normal_out);
00262 }
00263 
00264 void corner_concave(ft_config * cfg, PointCloud<PointXYZ>::Ptr & out, 
00265                     PointCloud<Normal>::Ptr & normal_out)
00266 {
00267   Vec o(0.0, 0.0, 0.25);
00268   cob_3d_mapping_tools::PointGenerator<PointXYZ> pg;
00269   pg.setGaussianNoise(cfg->rng);
00270   pg.setOutputCloud(out);
00271   pg.generateCorner(cfg->s, o,
00272                     Vec::UnitX() - Vec::UnitZ(),
00273                     Vec::UnitY(),
00274                     -Vec::UnitX() - Vec::UnitZ(), 
00275                     0.05f);
00276   generateName(cfg, "edge_concave_");
00277   generateFeature(cfg, out, normal_out);
00278 }
00279 
00280 void cylinder(ft_config * cfg, PointCloud<PointXYZ>::Ptr & out, 
00281               PointCloud<Normal>::Ptr & normal_out, float r)
00282 {
00283   Vec o(0.0, 0.0, 0.25);
00284   Vec o2(0.0, 0.0, -0.25-r);
00285   cob_3d_mapping_tools::PointGenerator<PointXYZ> pg;
00286   pg.setGaussianNoise(cfg->rng);
00287   pg.setOutputCloud(out);
00288   Eigen::Quaternion<float> q;
00289   q = Eigen::AngleAxis<float>(0.1*M_PI, Vec::UnitX());
00290   pg.generateCylinder(cfg->s, o, 0.2f * Vec::UnitX(), q * (r * Vec::UnitY()), 0.8f * M_PI);
00291   pg.generateCylinder(cfg->s, o2, 0.2f * Vec::UnitX(),q * (r * Vec::UnitY()), 0.8f * M_PI);
00292   generateName(cfg, fl2label(r,3) + "cylinder");
00293   generateFeature(cfg, out, normal_out);
00294 }
00295 
00296 void cylinder_convex(ft_config * cfg, PointCloud<PointXYZ>::Ptr & out, 
00297                      PointCloud<Normal>::Ptr & normal_out, float r)
00298 {
00299   Vec o(0.0, 0.0, 2.0);
00300   cob_3d_mapping_tools::PointGenerator<PointXYZ> pg;
00301   pg.setGaussianNoise(cfg->rng);
00302   pg.setOutputCloud(out);
00303   pg.generateCylinder(cfg->s, o, 0.2f * Vec::UnitX(), -r * Vec::UnitY(), M_PI);
00304   generateName(cfg, "cylinder_convex_");
00305   generateFeature(cfg, out, normal_out);
00306 }
00307 
00308 void sphere(ft_config * cfg, PointCloud<PointXYZ>::Ptr & out, 
00309                    PointCloud<Normal>::Ptr & normal_out, float r)
00310 {
00311   Vec o(0.0, 0.0, 0.25+r);
00312   Vec o2(0.0, 0.0, -0.25);
00313   cob_3d_mapping_tools::PointGenerator<PointXYZ> pg;
00314   pg.setGaussianNoise(cfg->rng);
00315   pg.setOutputCloud(out);
00316   pg.generateSphere(cfg->s, o, -Vec::UnitZ(), r, 0.4 * M_PI);
00317   pg.generateSphere(cfg->s, o2, -Vec::UnitZ(), r, 0.4 * M_PI);
00318   generateName(cfg, fl2label(r,3) + "sphere");
00319   generateFeature(cfg, out, normal_out);
00320 }
00321 
00322 void sphere_concave(ft_config * cfg, PointCloud<PointXYZ>::Ptr & out, 
00323                    PointCloud<Normal>::Ptr & normal_out, float r)
00324 {
00325   Vec o(0.0, 0.0, 0.25);
00326   cob_3d_mapping_tools::PointGenerator<PointXYZ> pg;
00327   pg.setGaussianNoise(cfg->rng);
00328   pg.setOutputCloud(out);
00329   pg.generateSphere(cfg->s, o, Vec::UnitZ(), r, 0.45 * M_PI);
00330   generateName(cfg, "sphere_concave_");
00331   generateFeature(cfg, out, normal_out);
00332 }
00333 
00334 int main(int argc, char** argv)
00335 {
00336   readOptions(argc, argv);
00337 
00338   ft_config *c1;
00339   c1 = new ft_config;
00340   c1->s = step_;
00341   c1->rng = noise_;
00342   c1->rn = rn_;
00343   c1->rf = rf_;
00344 
00345   PointCloud<PointXYZ>::Ptr p (new PointCloud<PointXYZ>);
00346   PointCloud<Normal>::Ptr n (new PointCloud<Normal>);
00347 
00348   if(pl) plane(c1, p, n);
00349 
00350   if(ed)
00351   {
00352     p.reset(new PointCloud<PointXYZ>);
00353     n.reset(new PointCloud<Normal>);
00354     edge(c1, p, n);
00355   }
00356 
00357   if(co)
00358   {
00359     p.reset(new PointCloud<PointXYZ>);
00360     n.reset(new PointCloud<Normal>);
00361     corner(c1, p, n);
00362   }
00363 
00364   if (cy)
00365   {
00366     p.reset(new PointCloud<PointXYZ>);
00367     n.reset(new PointCloud<Normal>);
00368     cylinder(c1, p, n, r_);
00369   }
00370 
00371   if(sp)
00372   {
00373     p.reset(new PointCloud<PointXYZ>);
00374     n.reset(new PointCloud<Normal>);
00375     sphere(c1, p, n, r_);
00376   }
00377 
00378   if (vis_)
00379   {
00380     visualization::PCLVisualizer vis;
00381     int vp(0);
00382     vis.setBackgroundColor(0.5,0.5,0.5,vp);
00383     vis.addCoordinateSystem(0.1,vp);
00384     vis.addPointCloud<PointXYZ>(p, "points", vp);
00385     vis.addPointCloudNormals<PointXYZ, Normal>(p, n, 4, 0.02, "normals", vp);
00386 
00387     while(!vis.wasStopped())
00388     {
00389       vis.spinOnce(100);
00390       usleep(100000);
00391     }
00392   }
00393   return 0;
00394 }


cob_3d_evaluation_features
Author(s): Georg Arbeiter
autogenerated on Wed Aug 26 2015 11:04:38