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