point_generator.cpp
Go to the documentation of this file.
00001 
00063 #include <cob_3d_mapping_tools/point_generator.h>
00064 #include <cob_3d_mapping_common/label_defines.h>
00065 
00066 #include <Eigen/Geometry>
00067 
00068 using namespace std;
00069 using namespace cob_3d_mapping_tools;
00070 
00071 
00072 template<typename PointT> 
00073 PointGenerator<PointT>::PointGenerator() :
00074   noise_(0.0f),
00075   n_dist_(0.0f, 1.0f),
00076   n_rng_(rng_, n_dist_)
00077 { }
00078 
00079 template<typename PointT> 
00080 PointGenerator<PointT>::~PointGenerator() 
00081 { }
00082 
00083 template<typename PointT> void 
00084 PointGenerator<PointT>::generateLine(const float & step_size,
00085                                      const Eigen::Vector3f & origin,
00086                                      const Eigen::Vector3f & direction,
00087                                      const uint32_t & color)
00088 {
00089   if(!cloud_)
00090   {
00091     PCL_WARN("[PointGenerator<PointT>] No output cloud given!\n");
00092     return;
00093   }
00094 
00095   float direction_norm = direction.norm();
00096   
00097   Eigen::Vector3f step_vector;
00098   Eigen::Vector3f curr_point = Eigen::Vector3f::Zero();
00099   pcl::PointCloud<PointT> new_cloud;
00100   int direction_steps = round(direction_norm / step_size);
00101   step_vector = (direction_norm / (float)direction_steps) * direction.normalized();
00102   for (int step = 0; step <= direction_steps; ++step)
00103   {
00104     PointT p;
00105     curr_point = step * step_vector;
00106     p.x = curr_point.x() + origin.x() + random();
00107     p.y = curr_point.y() + origin.y() + random();
00108     p.z = curr_point.z() + origin.z() + random();
00109     if (rgba_index_ >= 0)
00110     {
00111       memcpy (((char *)&p) + rgba_index_, &color, sizeof(uint32_t));
00112     }
00113     new_cloud.push_back(p);
00114 
00115   }
00116   *cloud_ += new_cloud;
00117 }
00118 
00119 template<typename PointT> void
00120 PointGenerator<PointT>::generateCircle(const float & step_size,
00121                                        const Eigen::Vector3f & origin,
00122                                        const Eigen::Vector3f & rotation_axis,
00123                                        const Eigen::Vector3f & radius,
00124                                        const float & angle,
00125                                        const uint32_t & color)
00126 {
00127   using namespace Eigen;
00128 
00129   if(!cloud_)
00130   {
00131     PCL_WARN("[PointGenerator<PointT>] No output cloud given!\n");
00132     return;
00133   }
00134   if( (angle > (2.0f * (float)M_PI)) || (angle < 0.0f) )
00135   {
00136     PCL_WARN("[PointGenerator<PointT>::generateCircle] invalid angle(%f)\n",angle);
00137     return;
00138   }
00139 
00140   pcl::PointCloud<PointT> new_cloud;
00141   float radius_norm = radius.norm();
00142 
00143   int rotation_steps = round(angle * radius_norm / step_size);
00144 
00145   if (rotation_steps <= 1)
00146   {
00147     PCL_WARN("[PointGenerator<PointT>::generateCircle] step_size(%f) >= angle(%f) * radius(%f)\n",
00148              step_size, angle, radius_norm);
00149     PCL_WARN("only a single point at center was created\n");
00150 
00151     // single point at center:
00152     addSinglePoint(origin, color);
00153     return;
00154   }
00155 
00156   float step_angle = angle / (float)rotation_steps;
00157   // make sure radius vector is orthogonal to rotation_axis, but keep radius vector length:
00158   Vector3f axis = rotation_axis.normalized();
00159   Vector3f radius_save = (Matrix3f::Identity() - axis * axis.transpose()) * radius;
00160   radius_save = radius_save.normalized() * radius_norm;
00161   Quaternion<float> q;
00162   Vector3f curr_point = radius; // set first point
00163   if (angle < 2.0f * (float) M_PI) // make last step if not full circle
00164     rotation_steps++;
00165   new_cloud.reserve((size_t)rotation_steps);
00166   for (int step = 1; step <= rotation_steps; ++step)
00167   {
00168     PointT p;
00169     p.x = curr_point.x() + origin.x() + random();
00170     p.y = curr_point.y() + origin.y() + random();
00171     p.z = curr_point.z() + origin.z() + random();
00172     if (rgba_index_ >= 0)
00173     {
00174       memcpy (((char *)&p) + rgba_index_, &color, sizeof(uint32_t));
00175     }
00176     new_cloud.push_back(p);
00177 
00178     // rotate current point vector
00179     q = AngleAxis<float>(step * step_angle, axis);
00180     curr_point = q * radius;
00181   }
00182   *cloud_ += new_cloud;
00183 }
00184 
00185 template<typename PointT> void
00186 PointGenerator<PointT>::generateCirclePlane(const float & step_size,
00187                                             const Eigen::Vector3f & origin,
00188                                             const Eigen::Vector3f & rotation_axis,
00189                                             const float & radius)
00190 {
00191   generateCirclePlane(step_size, origin, rotation_axis, 
00192                       getArbitraryPerpendicularNormalized(rotation_axis) * radius);
00193 }
00194 
00195 template<typename PointT> void
00196 PointGenerator<PointT>::generateCirclePlane(const float & step_size,
00197                                             const Eigen::Vector3f & origin,
00198                                             const Eigen::Vector3f & rotation_axis,
00199                                             const Eigen::Vector3f & radius,
00200                                             const float & angle)
00201 {
00202   float radius_norm = radius.norm();
00203   Eigen::Vector3f radius_step = (step_size / radius_norm) * radius;
00204   Eigen::Vector3f curr_radius = Eigen::Vector3f::Zero();
00205   while (curr_radius.norm() <= radius_norm)
00206   {
00207     generateCircle(step_size, origin, rotation_axis, curr_radius, angle, LBL_PLANE);
00208     curr_radius += radius_step;
00209   }
00210 }
00211 
00212 template<typename PointT> void 
00213 PointGenerator<PointT>::generatePlane(const float & step_size, 
00214                                       const Eigen::Vector3f & origin,
00215                                       const Eigen::Vector3f &direction_1,
00216                                       const Eigen::Vector3f &direction_2)
00217 {
00218   Eigen::Vector3f curr_direction;
00219   Eigen::Vector3f direction_normalized = direction_2.normalized();
00220   int direction_steps = round(direction_2.norm() / step_size);
00221   float step_size_adjusted = direction_2.norm() / (float)direction_steps;
00222 
00223   for (int step = 1; step <= direction_steps; ++step)
00224   {
00225     curr_direction = step * step_size_adjusted * direction_normalized;
00226     generateLine(step_size, origin + curr_direction, direction_1, LBL_PLANE);
00227   }
00228 }
00229 
00230 template<typename PointT> void
00231 PointGenerator<PointT>::generateEdge(const float & step_size, 
00232                                      const Eigen::Vector3f & origin,
00233                                      const Eigen::Vector3f & direction_edge,
00234                                      const Eigen::Vector3f & direction_depth)
00235 {
00236   Eigen::Vector3f direction_2;
00237   direction_2 = direction_edge.cross(direction_depth);
00238   direction_2 = direction_2.normalized() * direction_depth.norm();
00239   generateEdge( step_size, origin, direction_edge, direction_depth, direction_2);
00240 }
00241 
00242 template<typename PointT> void
00243 PointGenerator<PointT>::generateEdge(const float & step_size,
00244                                      const Eigen::Vector3f & origin,
00245                                      const Eigen::Vector3f & direction_edge,
00246                                      const Eigen::Vector3f & direction_1,
00247                                      const Eigen::Vector3f & direction_2)
00248 {
00249   Eigen::Vector3f curr_direction;
00250   Eigen::Vector3f direction_normalized = direction_edge.normalized();
00251   int direction_steps = round(direction_edge.norm() / step_size);
00252   float step_size_adjusted = direction_edge.norm() / (float)direction_steps;
00253 
00254   for (int step = 1; step <= direction_steps; ++step)
00255   {
00256     curr_direction = step * step_size_adjusted * direction_normalized;
00257     generateLine(step_size, origin + curr_direction + direction_1, -direction_1, LBL_EDGE);
00258     generateLine(step_size, origin + curr_direction + direction_2, -direction_2, LBL_EDGE);
00259     addSinglePoint(origin + curr_direction, LBL_EDGE);
00260   }
00261 }
00262 
00263 template<typename PointT> void
00264 PointGenerator<PointT>::generateCorner(const float & step_size,
00265                                        const Eigen::Vector3f & origin,
00266                                        const Eigen::Vector3f & direction_1,
00267                                        const Eigen::Vector3f & direction_2,
00268                                        const Eigen::Vector3f & direction_3,
00269                                        const float & corner_size)
00270 {
00271   Eigen::Vector3f curr_direction_1;
00272   Eigen::Vector3f curr_direction_2;
00273   Eigen::Vector3f curr_direction_3;
00274   Eigen::Vector3f direction_1_normalized = direction_1.normalized();
00275   Eigen::Vector3f direction_2_normalized = direction_2.normalized();
00276   Eigen::Vector3f direction_3_normalized = direction_3.normalized();
00277   int steps;
00278   float step_size_adjusted, size;
00279   if (corner_size != 0.0f) 
00280     size = corner_size;
00281   else 
00282     size = direction_1.norm();
00283   steps = round(size / step_size);
00284   step_size_adjusted = size / (float)steps;
00285 
00286   for (int step = 1; step <= steps; ++step)
00287   {
00288     curr_direction_1 = step * step_size_adjusted * direction_1_normalized;
00289     curr_direction_2 = step * step_size_adjusted * direction_2_normalized;
00290     curr_direction_3 = step * step_size_adjusted * direction_3_normalized;
00291     generateLine(step_size, origin + curr_direction_1, direction_3_normalized * size, LBL_EDGE);
00292     generateLine(step_size, origin + curr_direction_2, direction_1_normalized * size, LBL_EDGE);
00293     generateLine(step_size, origin + curr_direction_3, direction_2_normalized * size, LBL_EDGE);
00294   }
00295   addSinglePoint(origin, LBL_EDGE);
00296 }
00297 
00298 template<typename PointT> void
00299 PointGenerator<PointT>::generateBox(const float & step_size,
00300                                     const Eigen::Vector3f & origin,
00301                                     const Eigen::Vector3f & direction_1,
00302                                     const Eigen::Vector3f & direction_2,
00303                                     const float & corner_size,
00304                                     const float & height)
00305 {
00306   Eigen::Vector3f direction_3 = direction_1.cross(direction_2).normalized() * height;
00307   generateBox(step_size, origin, direction_1, direction_2, direction_3, corner_size);
00308 }
00309 
00310 template<typename PointT> void
00311 PointGenerator<PointT>::generateBox(const float & step_size,
00312                                     const Eigen::Vector3f & origin,
00313                                     const Eigen::Vector3f & direction_1,
00314                                     const Eigen::Vector3f & direction_2,
00315                                     const Eigen::Vector3f & direction_3,
00316                                     const float & corner_size)
00317 {
00318   Eigen::Vector3f edge_direction_1;
00319   Eigen::Vector3f edge_direction_2;
00320   Eigen::Vector3f edge_direction_3;
00321   Eigen::Vector3f corner_direction_1;
00322   Eigen::Vector3f corner_direction_2;
00323   Eigen::Vector3f corner_direction_3;
00324   float edge_length;
00325   bool enable_edge_1 = true;
00326   bool enable_edge_2 = true;
00327   bool enable_edge_3 = true;
00328   if ((edge_length = direction_1.norm() - 2 * corner_size) > 0)
00329   {
00330     edge_direction_1 = direction_1.normalized() * (edge_length);
00331     corner_direction_1  = direction_1.normalized() * corner_size;
00332   }
00333   else
00334   {
00335     enable_edge_1 = false;
00336     corner_direction_1  = direction_1.normalized() * (direction_1.norm() / 2);
00337   }
00338 
00339   if ((edge_length = direction_2.norm() - 2 * corner_size) > 0)
00340   {
00341     edge_direction_2 = direction_2.normalized() * (edge_length);
00342     corner_direction_2  = direction_2.normalized() * corner_size;
00343   }
00344   else
00345   {
00346     enable_edge_2 = false;
00347     corner_direction_2  = direction_2.normalized() * (direction_2.norm() / 2);
00348   }
00349 
00350   if ((edge_length = direction_3.norm() - 2 * corner_size) > 0)
00351   {
00352     edge_direction_3 = direction_3.normalized() * (edge_length);
00353     corner_direction_3  = direction_3.normalized() * corner_size;
00354   }
00355   else
00356   {
00357     enable_edge_3 = false;
00358     corner_direction_3  = direction_3.normalized() * (direction_3.norm() / 2);
00359   }
00360 
00361   // Generate edges:
00362   if (enable_edge_1)
00363   {
00364     generateEdge(step_size, origin + corner_direction_1, 
00365                  edge_direction_1, corner_direction_2, corner_direction_3);
00366     generateEdge(step_size, origin + direction_2 + corner_direction_1, 
00367                  edge_direction_1, corner_direction_3, -corner_direction_2);
00368     generateEdge(step_size, origin + direction_3 + corner_direction_1, 
00369                  edge_direction_1, -corner_direction_3, corner_direction_2);
00370     generateEdge(step_size, origin + direction_2 + direction_3 + corner_direction_1,
00371                  edge_direction_1, -corner_direction_2, -corner_direction_3);
00372   }
00373   if (enable_edge_2)
00374   {
00375     generateEdge(step_size, origin + corner_direction_2, 
00376                  edge_direction_2, corner_direction_3, corner_direction_1);
00377     generateEdge(step_size, origin + direction_1 + corner_direction_2, 
00378                  edge_direction_2, -corner_direction_1, corner_direction_3);
00379     generateEdge(step_size, origin + direction_3 + corner_direction_2, 
00380                  edge_direction_2, corner_direction_1, -corner_direction_3);
00381     generateEdge(step_size, origin + direction_3 + direction_1 + corner_direction_2, 
00382                  edge_direction_2, -corner_direction_3, -corner_direction_1);
00383   }
00384   if (enable_edge_3)
00385   {
00386     generateEdge(step_size, origin + corner_direction_3, 
00387                  edge_direction_3, corner_direction_1, corner_direction_2);
00388     generateEdge(step_size, origin + direction_1 + corner_direction_3, 
00389                  edge_direction_3, corner_direction_2, -corner_direction_1);
00390     generateEdge(step_size, origin + direction_2 + corner_direction_3, 
00391                  edge_direction_3, -corner_direction_2, corner_direction_1);
00392     generateEdge(step_size, origin + direction_1 + direction_2 + corner_direction_3, 
00393                  edge_direction_3, -corner_direction_1, -corner_direction_2);
00394   }
00395 
00396   // Generate corners:
00397   generateCorner(step_size, origin, 
00398                  corner_direction_1, corner_direction_2, corner_direction_3);
00399 
00400   generateCorner(step_size, origin + direction_1, 
00401                  -corner_direction_1, corner_direction_2, corner_direction_3);
00402   generateCorner(step_size, origin + direction_2, 
00403                  corner_direction_1, -corner_direction_2, corner_direction_3);
00404   generateCorner(step_size, origin + direction_3, 
00405                  corner_direction_1, corner_direction_2, -corner_direction_3);
00406 
00407   generateCorner(step_size, origin + direction_1 + direction_2,
00408                  -corner_direction_1, -corner_direction_2, corner_direction_3);
00409   generateCorner(step_size, origin + direction_2 + direction_3,
00410                  corner_direction_1, -corner_direction_2, -corner_direction_3);
00411   generateCorner(step_size, origin + direction_1 + direction_3,
00412                  -corner_direction_1, corner_direction_2, -corner_direction_3);
00413 
00414   generateCorner(step_size, origin + direction_1 + direction_2 + direction_3,
00415                  -corner_direction_1, -corner_direction_2, -corner_direction_3);
00416 
00417   // Generate planes:
00418   if (enable_edge_1 && enable_edge_2)
00419   {
00420     generatePlane(step_size, origin + corner_direction_1 + corner_direction_2, 
00421                   edge_direction_1, edge_direction_2);
00422     generatePlane(step_size, origin + direction_3 + corner_direction_1 + corner_direction_2, 
00423                   edge_direction_1, edge_direction_2);
00424   }
00425   if (enable_edge_2 && enable_edge_3)
00426   {
00427     generatePlane(step_size,origin + corner_direction_2 + corner_direction_3,
00428                   edge_direction_2, edge_direction_3);
00429     generatePlane(step_size, origin + direction_1 + corner_direction_2 + corner_direction_3,
00430                   edge_direction_2, edge_direction_3);
00431   }
00432   if (enable_edge_3 && enable_edge_1)
00433   {
00434     generatePlane(step_size, origin + corner_direction_3 + corner_direction_1,
00435                   edge_direction_3, edge_direction_1);
00436     generatePlane(step_size, origin + direction_2 + corner_direction_3 + corner_direction_1,
00437                   edge_direction_3, edge_direction_1);
00438   }
00439 }
00440 
00441 template<typename PointT> void
00442 PointGenerator<PointT>::generateCylinder(const float & step_size,
00443                                          const Eigen::Vector3f & origin,
00444                                          const Eigen::Vector3f & direction,
00445                                          const float & radius)
00446 {
00447   Eigen::Vector3f radius_vector = getArbitraryPerpendicularNormalized(direction) * radius;
00448   generateCylinder(step_size, origin, direction, radius_vector, 2*M_PI);
00449 }
00450 
00451 template<typename PointT> void
00452 PointGenerator<PointT>::generateCylinder(const float & step_size,
00453                                          const Eigen::Vector3f & origin,
00454                                          const Eigen::Vector3f & direction,
00455                                          const Eigen::Vector3f & radius, 
00456                                          const float & angle)
00457 {
00458   using namespace Eigen;
00459 
00460   int rotation_steps = round(angle * radius.norm() / step_size);
00461   float step_angle = angle / (float)rotation_steps;
00462   Vector3f curr_point;
00463   Vector3f direction_normalized = direction.normalized();
00464 
00465   curr_point = radius;  
00466   Quaternion<float> q;
00467   for(int step = 1; step <= rotation_steps; ++step)
00468   {
00469     generateLine(step_size, origin + curr_point, direction, LBL_CYL);
00470     q = AngleAxis<float>(step * step_angle, direction_normalized);
00471     curr_point = q * radius;
00472   }
00473 }
00474 
00475 template<typename PointT> void
00476 PointGenerator<PointT>::generateCone(const float & step_size,
00477                                      const Eigen::Vector3f & origin,
00478                                      const Eigen::Vector3f & direction,
00479                                      const float & radius_base,
00480                                      const float & radius_peek)
00481 {
00482   Eigen::Vector3f direction_step;
00483   Eigen::Vector3f radius_step;
00484   Eigen::Vector3f curr_direction = Eigen::Vector3f::Zero(); // direction vector iterator
00485   Eigen::Vector3f curr_radius; // radius vector iterator, start at base radius
00486 
00487   float direction_norm = direction.norm();
00488   float side_length = sqrt (pow (radius_base - radius_peek, 2) + pow (direction_norm, 2));
00489   int steps = round(side_length / step_size);
00490   direction_step = direction_norm / (float)steps * direction.normalized();
00491   curr_radius = getArbitraryPerpendicularNormalized(direction);
00492   radius_step = ((radius_base - radius_peek) / (float)steps) * curr_radius;
00493   curr_radius = curr_radius * radius_base;
00494 
00495   for (int step = 0; step <=  steps; ++step)
00496   {
00497     generateCircle(step_size, origin + curr_direction, direction, curr_radius, 2 * M_PI, LBL_CYL);
00498     curr_direction += direction_step;
00499     curr_radius -= radius_step;
00500   }
00501 }
00502 
00503 template<typename PointT> void
00504 PointGenerator<PointT>::generateSphere(const float & step_size,
00505                                        const Eigen::Vector3f & center,
00506                                        const Eigen::Vector3f & rotation_axis,
00507                                        const float & radius,
00508                                        const float & angle)
00509 {
00510   if( (angle > ((float)M_PI)) || (angle < 0.0f) )
00511   {
00512     PCL_WARN("[PointGenerator<PointT>::generateSphere] invalid angle(%f)\n",angle);
00513     PCL_WARN("0.0 < angle <= PI\n");
00514     return;
00515   }
00516   int radius_steps = round(angle * radius / step_size);
00517   float step_angle = angle / (float)radius_steps;
00518   Eigen::Vector3f curr_radius;
00519   Eigen::Vector3f curr_point;
00520   Eigen::Vector3f rotation_axis_vector = rotation_axis.normalized() * radius;
00521   Eigen::Vector3f radius_vector = getArbitraryPerpendicularNormalized(rotation_axis) * radius;
00522   
00523   for (int step = 0; step <= radius_steps; ++step)
00524   {
00525     curr_radius = radius_vector * sin((float)step * step_angle);
00526     curr_point = rotation_axis_vector * cos((float)step * step_angle);
00527     generateCircle(step_size, center + curr_point, rotation_axis_vector, curr_radius,
00528                    2 * M_PI, LBL_SPH);
00529   } 
00530 }
00531 
00532 template<typename PointT> void
00533 PointGenerator<PointT>::generateSphere(const float & step_size,
00534                                        const Eigen::Vector3f & center,
00535                                        const float & radius)
00536 {
00537   generateSphere(step_size, center, Eigen::Vector3f::UnitY(), radius);
00538 }
00539 
00540 template<typename PointT> void
00541 PointGenerator<PointT>::generateHandle(const float & step_size,
00542                                        const Eigen::Vector3f & origin,
00543                                        const Eigen::Vector3f & rotation_axis,
00544                                        const Eigen::Vector3f & radius_curvature,
00545                                        const float & radius_handle,
00546                                        const float & angle)
00547 {
00548   int radius_steps = round(2 * M_PI * radius_handle / step_size);
00549   float step_angle = 2 * M_PI / (float)radius_steps;
00550   Eigen::Vector3f curr_radius;
00551   Eigen::Vector3f vector_radius_handle = radius_curvature.normalized() * radius_handle;
00552   Eigen::Vector3f rotation_axis_radius_handle = radius_curvature.cross(rotation_axis);
00553   rotation_axis_radius_handle = rotation_axis_radius_handle.normalized();
00554 
00555   Eigen::Quaternion<float> q;
00556   for (int step = 0; step <= radius_steps; ++step)
00557   {
00558     q = Eigen::AngleAxis<float>((float)step * step_angle, rotation_axis_radius_handle);
00559     curr_radius = q * vector_radius_handle;
00560     generateCircle(step_size, origin, rotation_axis, radius_curvature + curr_radius, angle, LBL_EDGE);
00561   }
00562 }
00563 
00564 template<typename PointT> void
00565 PointGenerator<PointT>::addSinglePoint(const Eigen::Vector3f & point, const uint32_t & color)
00566 {
00567   PointT p;
00568   p.x = point.x() + random();
00569   p.y = point.y() + random();
00570   p.z = point.z() + random();
00571   if (rgba_index_ >= 0)
00572   {
00573     memcpy (((char *)&p) + rgba_index_, &color, sizeof(uint32_t));
00574   }
00575   pcl::PointCloud<PointT> pc;
00576   pc.push_back(p);
00577   *cloud_ += pc;
00578 }
00579 
00580 template class PointGenerator<pcl::PointXYZ>;
00581 template class PointGenerator<pcl::PointXYZRGBA>;


cob_3d_mapping_tools
Author(s): Georg Arbeiter
autogenerated on Wed Aug 26 2015 11:04:27