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
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 }