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
00152 addSinglePoint(origin, color);
00153 return;
00154 }
00155
00156 float step_angle = angle / (float)rotation_steps;
00157
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;
00163 if (angle < 2.0f * (float) M_PI)
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
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
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
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
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();
00485 Eigen::Vector3f curr_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>;