00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00039 template <typename PointT> inline void
00040 pcl::compute3DCentroid (const pcl::PointCloud<PointT> &cloud, Eigen::Vector4f ¢roid)
00041 {
00042
00043 centroid.setZero ();
00044 if (cloud.points.empty ())
00045 return;
00046
00047 int cp = 0;
00048
00049
00050 if (cloud.is_dense)
00051 {
00052 for (size_t i = 0; i < cloud.points.size (); ++i)
00053 centroid += cloud.points[i].getVector4fMap ();
00054 centroid[3] = 0;
00055 centroid /= cloud.points.size ();
00056 }
00057
00058 else
00059 {
00060 for (size_t i = 0; i < cloud.points.size (); ++i)
00061 {
00062
00063 if (!pcl_isfinite (cloud.points[i].x) ||
00064 !pcl_isfinite (cloud.points[i].y) ||
00065 !pcl_isfinite (cloud.points[i].z))
00066 continue;
00067
00068 centroid += cloud.points[i].getVector4fMap ();
00069 cp++;
00070 }
00071 centroid[3] = 0;
00072 centroid /= cp;
00073 }
00074 }
00075
00077 template <typename PointT> inline void
00078 pcl::compute3DCentroid (const pcl::PointCloud<PointT> &cloud, const std::vector<int> &indices,
00079 Eigen::Vector4f ¢roid)
00080 {
00081
00082 centroid.setZero ();
00083 if (indices.empty ())
00084 return;
00085
00086 int cp = 0;
00087
00088
00089 if (cloud.is_dense)
00090 {
00091 for (size_t i = 0; i < indices.size (); ++i)
00092 centroid += cloud.points[indices[i]].getVector4fMap ();
00093 centroid[3] = 0;
00094 centroid /= indices.size ();
00095 }
00096
00097 else
00098 {
00099 for (size_t i = 0; i < indices.size (); ++i)
00100 {
00101
00102 if (!pcl_isfinite (cloud.points[indices[i]].x) ||
00103 !pcl_isfinite (cloud.points[indices[i]].y) ||
00104 !pcl_isfinite (cloud.points[indices[i]].z))
00105 continue;
00106
00107 centroid += cloud.points[indices[i]].getVector4fMap ();
00108 cp++;
00109 }
00110 centroid[3] = 0;
00111 centroid /= cp;
00112 }
00113 }
00114
00116 template <typename PointT> inline void
00117 pcl::compute3DCentroid (const pcl::PointCloud<PointT> &cloud,
00118 const pcl::PointIndices &indices, Eigen::Vector4f ¢roid)
00119 {
00120 return (pcl::compute3DCentroid<PointT> (cloud, indices.indices, centroid));
00121 }
00122
00124 template <typename PointT> inline void
00125 pcl::computeNDCentroid (const pcl::PointCloud<PointT> &cloud, Eigen::VectorXf ¢roid)
00126 {
00127 typedef typename pcl::traits::fieldList<PointT>::type FieldList;
00128
00129
00130 centroid.setZero (boost::mpl::size<FieldList>::value);
00131
00132 if (cloud.points.empty ())
00133 return;
00134
00135 int size = cloud.points.size ();
00136 for (int i = 0; i < size; ++i)
00137 {
00138
00139 pcl::for_each_type <FieldList> (NdCentroidFunctor <PointT> (cloud.points[i], centroid));
00140 }
00141 centroid /= size;
00142 }
00143
00145 template <typename PointT> inline void
00146 pcl::computeNDCentroid (const pcl::PointCloud<PointT> &cloud, const std::vector<int> &indices,
00147 Eigen::VectorXf ¢roid)
00148 {
00149 typedef typename pcl::traits::fieldList<PointT>::type FieldList;
00150
00151
00152 centroid.setZero (boost::mpl::size<FieldList>::value);
00153
00154 if (indices.empty ())
00155 return;
00156
00157 int nr_points = indices.size ();
00158 for (int i = 0; i < nr_points; ++i)
00159 {
00160
00161 pcl::for_each_type <FieldList> (NdCentroidFunctor <PointT> (cloud.points[indices[i]], centroid));
00162 }
00163 centroid /= nr_points;
00164 }
00165
00167 template <typename PointT> inline void
00168 pcl::computeNDCentroid (const pcl::PointCloud<PointT> &cloud,
00169 const pcl::PointIndices &indices, Eigen::VectorXf ¢roid)
00170 {
00171 return (pcl::computeNDCentroid<PointT> (cloud, indices.indices, centroid));
00172 }
00173
00175 template <typename PointT> inline void
00176 pcl::computeCovarianceMatrix (const pcl::PointCloud<PointT> &cloud,
00177 const Eigen::Vector4f ¢roid,
00178 Eigen::Matrix3f &covariance_matrix)
00179 {
00180
00181 covariance_matrix.setZero ();
00182
00183 if (cloud.points.empty ())
00184 return;
00185
00186 if (cloud.is_dense)
00187 {
00188
00189 for (size_t i = 0; i < cloud.points.size (); ++i)
00190 {
00191 Eigen::Vector4f pt = cloud.points[i].getVector4fMap () - centroid;
00192
00193 covariance_matrix (1, 1) += pt.y () * pt.y ();
00194 covariance_matrix (1, 2) += pt.y () * pt.z ();
00195
00196 covariance_matrix (2, 2) += pt.z () * pt.z ();
00197
00198 pt *= pt.x ();
00199 covariance_matrix (0, 0) += pt.x ();
00200 covariance_matrix (0, 1) += pt.y ();
00201 covariance_matrix (0, 2) += pt.z ();
00202 }
00203 }
00204
00205 else
00206 {
00207
00208 for (size_t i = 0; i < cloud.points.size (); ++i)
00209 {
00210
00211 if (!pcl_isfinite (cloud.points[i].x) ||
00212 !pcl_isfinite (cloud.points[i].y) ||
00213 !pcl_isfinite (cloud.points[i].z))
00214 continue;
00215
00216 Eigen::Vector4f pt = cloud.points[i].getVector4fMap () - centroid;
00217
00218 covariance_matrix (1, 1) += pt.y () * pt.y ();
00219 covariance_matrix (1, 2) += pt.y () * pt.z ();
00220
00221 covariance_matrix (2, 2) += pt.z () * pt.z ();
00222
00223 pt *= pt.x ();
00224 covariance_matrix (0, 0) += pt.x ();
00225 covariance_matrix (0, 1) += pt.y ();
00226 covariance_matrix (0, 2) += pt.z ();
00227 }
00228 }
00229 covariance_matrix (1, 0) = covariance_matrix (0, 1);
00230 covariance_matrix (2, 0) = covariance_matrix (0, 2);
00231 covariance_matrix (2, 1) = covariance_matrix (1, 2);
00232 }
00233
00235 template <typename PointT> inline void
00236 pcl::computeCovarianceMatrixNormalized (const pcl::PointCloud<PointT> &cloud,
00237 const Eigen::Vector4f ¢roid,
00238 Eigen::Matrix3f &covariance_matrix)
00239 {
00240 pcl::computeCovarianceMatrix (cloud, centroid, covariance_matrix);
00241 covariance_matrix /= cloud.points.size ();
00242 }
00243
00245 template <typename PointT> inline void
00246 pcl::computeCovarianceMatrix (const pcl::PointCloud<PointT> &cloud,
00247 const std::vector<int> &indices,
00248 const Eigen::Vector4f ¢roid,
00249 Eigen::Matrix3f &covariance_matrix)
00250 {
00251
00252 covariance_matrix.setZero ();
00253
00254 if (indices.empty ())
00255 return;
00256
00257 if (cloud.is_dense)
00258 {
00259
00260 for (size_t i = 0; i < indices.size (); ++i)
00261 {
00262 Eigen::Vector4f pt = cloud.points[indices[i]].getVector4fMap () - centroid;
00263
00264 covariance_matrix (1, 1) += pt.y () * pt.y ();
00265 covariance_matrix (1, 2) += pt.y () * pt.z ();
00266
00267 covariance_matrix (2, 2) += pt.z () * pt.z ();
00268
00269 pt *= pt.x ();
00270 covariance_matrix (0, 0) += pt.x ();
00271 covariance_matrix (0, 1) += pt.y ();
00272 covariance_matrix (0, 2) += pt.z ();
00273 }
00274 }
00275
00276 else
00277 {
00278
00279 for (size_t i = 0; i < indices.size (); ++i)
00280 {
00281
00282 if (!pcl_isfinite (cloud.points[indices[i]].x) ||
00283 !pcl_isfinite (cloud.points[indices[i]].y) ||
00284 !pcl_isfinite (cloud.points[indices[i]].z))
00285 continue;
00286
00287 Eigen::Vector4f pt = cloud.points[indices[i]].getVector4fMap () - centroid;
00288
00289 covariance_matrix (1, 1) += pt.y () * pt.y ();
00290 covariance_matrix (1, 2) += pt.y () * pt.z ();
00291
00292 covariance_matrix (2, 2) += pt.z () * pt.z ();
00293
00294 pt *= pt.x ();
00295 covariance_matrix (0, 0) += pt.x ();
00296 covariance_matrix (0, 1) += pt.y ();
00297 covariance_matrix (0, 2) += pt.z ();
00298 }
00299 }
00300 covariance_matrix (1, 0) = covariance_matrix (0, 1);
00301 covariance_matrix (2, 0) = covariance_matrix (0, 2);
00302 covariance_matrix (2, 1) = covariance_matrix (1, 2);
00303 }
00304
00306 template <typename PointT> inline void
00307 pcl::computeCovarianceMatrix (const pcl::PointCloud<PointT> &cloud,
00308 const pcl::PointIndices &indices,
00309 const Eigen::Vector4f ¢roid,
00310 Eigen::Matrix3f &covariance_matrix)
00311 {
00312 return (pcl::computeCovarianceMatrix<PointT> (cloud, indices.indices, centroid));
00313 }
00314
00316 template <typename PointT> inline void
00317 pcl::computeCovarianceMatrixNormalized (const pcl::PointCloud<PointT> &cloud,
00318 const std::vector<int> &indices,
00319 const Eigen::Vector4f ¢roid,
00320 Eigen::Matrix3f &covariance_matrix)
00321 {
00322 pcl::computeCovarianceMatrix (cloud, indices, centroid, covariance_matrix);
00323 covariance_matrix /= indices.size ();
00324 }
00325
00327 template <typename PointT> inline void
00328 pcl::computeCovarianceMatrixNormalized (const pcl::PointCloud<PointT> &cloud,
00329 const pcl::PointIndices &indices,
00330 const Eigen::Vector4f ¢roid,
00331 Eigen::Matrix3f &covariance_matrix)
00332 {
00333 return (pcl::computeCovarianceMatrix (cloud, indices.indices, centroid, covariance_matrix));
00334 }
00335
00337 inline void
00338 pcl::solvePlaneParameters (const Eigen::Matrix3f &covariance_matrix,
00339 const Eigen::Vector4f &point,
00340 Eigen::Vector4f &plane_parameters, float &curvature)
00341 {
00342
00343 for (int i = 0; i < 3; ++i)
00344 for (int j = 0; j < 3; ++j)
00345 if (!pcl_isfinite (covariance_matrix (i, j)))
00346 {
00347
00348 plane_parameters.setConstant (std::numeric_limits<float>::quiet_NaN ());
00349 curvature = std::numeric_limits<float>::quiet_NaN ();
00350 return;
00351 }
00352
00353
00354
00355
00356
00357 EIGEN_ALIGN16 Eigen::Vector3f eigen_values;
00358 EIGEN_ALIGN16 Eigen::Matrix3f eigen_vectors;
00359 pcl::eigen33 (covariance_matrix, eigen_vectors, eigen_values);
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370 plane_parameters[0] = eigen_vectors (0, 0);
00371 plane_parameters[1] = eigen_vectors (1, 0);
00372 plane_parameters[2] = eigen_vectors (2, 0);
00373 plane_parameters[3] = 0;
00374
00375
00376 plane_parameters[3] = -1 * plane_parameters.dot (point);
00377
00378
00379 float eig_sum = eigen_values.sum ();
00380 if (eig_sum != 0)
00381 curvature = fabs ( eigen_values[0] / eig_sum );
00382 else
00383 curvature = 0;
00384 }
00385
00387 inline void
00388 pcl::solvePlaneParameters (const Eigen::Matrix3f &covariance_matrix,
00389 float &nx, float &ny, float &nz, float &curvature)
00390 {
00391
00392 for (int i = 0; i < 3; ++i)
00393 for (int j = 0; j < 3; ++j)
00394 if (!pcl_isfinite (covariance_matrix (i, j)))
00395 {
00396
00397 nx = ny = nz = curvature = std::numeric_limits<float>::quiet_NaN ();
00398 return;
00399 }
00400
00401
00402
00403
00404 EIGEN_ALIGN16 Eigen::Vector3f eigen_values;
00405 EIGEN_ALIGN16 Eigen::Matrix3f eigen_vectors;
00406 pcl::eigen33 (covariance_matrix, eigen_vectors, eigen_values);
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417 nx = eigen_vectors (0, 0);
00418 ny = eigen_vectors (1, 0);
00419 nz = eigen_vectors (2, 0);
00420
00421
00422 float eig_sum = eigen_values.sum ();
00423 if (eig_sum != 0)
00424 curvature = fabs ( eigen_values[0] / eig_sum );
00425 else
00426 curvature = 0;
00427 }
00428
00432 template <typename PointInT, typename PointOutT> void
00433 pcl::Feature<PointInT, PointOutT>::compute (PointCloudOut &output)
00434 {
00435
00436 output.header = input_->header;
00437
00438 if (!initCompute ())
00439 {
00440 ROS_ERROR ("[pcl::%s::compute] Init failed.", getClassName ().c_str ());
00441 output.width = output.height = 0;
00442 output.points.clear ();
00443 return;
00444 }
00445
00446
00447 if (input_->points.empty ())
00448 {
00449 output.width = output.height = 0;
00450 output.points.clear ();
00451 deinitCompute ();
00452 return;
00453 }
00454
00455
00456 if (!tree_)
00457 {
00458 ROS_ERROR ("[pcl::%s::compute] No spatial search method was given!", getClassName ().c_str ());
00459 output.width = output.height = 0;
00460 output.points.clear ();
00461 deinitCompute ();
00462 return;
00463 }
00464
00465
00466 if (!surface_)
00467 {
00468 fake_surface_ = true;
00469 surface_ = input_;
00470 }
00471
00472
00473 tree_->setInputCloud (surface_);
00474
00475
00476 if (search_radius_ != 0.0)
00477 {
00478 if (k_ != 0)
00479 {
00480 ROS_ERROR ("[pcl::%s::compute] Both radius (%f) and K (%d) defined! Set one of them to zero first and then re-run compute ().", getClassName ().c_str (), search_radius_, k_);
00481 output.width = output.height = 0;
00482 output.points.clear ();
00483
00484
00485 deinitCompute ();
00486
00487 if (fake_surface_)
00488 {
00489 surface_.reset ();
00490 fake_surface_ = false;
00491 }
00492 return;
00493 }
00494 else
00495 {
00496 search_parameter_ = search_radius_;
00497 if (surface_ == input_)
00498 {
00499
00500 int (KdTree::*radiusSearch)(int index, double radius, std::vector<int> &k_indices,
00501 std::vector<float> &k_distances, int max_nn) const = &KdTree::radiusSearch;
00502 search_method_ = boost::bind (radiusSearch, boost::ref (tree_), _1, _2, _3, _4, INT_MAX);
00503 }
00504 else
00505 {
00506
00507 int (KdTree::*radiusSearchSurface)(const PointCloudIn &cloud, int index, double radius, std::vector<int> &k_indices,
00508 std::vector<float> &k_distances, int max_nn) const = &KdTree::radiusSearch;
00509 search_method_surface_ = boost::bind (radiusSearchSurface, boost::ref (tree_), _1, _2, _3, _4, _5, INT_MAX);
00510 }
00511 }
00512 }
00513 else
00514 {
00515 if (k_ != 0)
00516 {
00517 search_parameter_ = k_;
00518 if (surface_ == input_)
00519 {
00520
00521 int (KdTree::*nearestKSearch)(int index, int k, std::vector<int> &k_indices, std::vector<float> &k_distances) = &KdTree::nearestKSearch;
00522 search_method_ = boost::bind (nearestKSearch, boost::ref (tree_), _1, _2, _3, _4);
00523 }
00524 else
00525 {
00526
00527 int (KdTree::*nearestKSearchSurface)(const PointCloudIn &cloud, int index, int k, std::vector<int> &k_indices, std::vector<float> &k_distances) = &KdTree::nearestKSearch;
00528 search_method_surface_ = boost::bind (nearestKSearchSurface, boost::ref (tree_), _1, _2, _3, _4, _5);
00529 }
00530 }
00531 else
00532 {
00533 ROS_ERROR ("[pcl::%s::compute] Neither radius nor K defined! Set one of them to a positive number first and then re-run compute ().", getClassName ().c_str ());
00534 output.width = output.height = 0;
00535 output.points.clear ();
00536
00537
00538 deinitCompute ();
00539
00540 if (fake_surface_)
00541 {
00542 surface_.reset ();
00543 fake_surface_ = false;
00544 }
00545 return;
00546 }
00547 }
00548
00549
00550 if (output.points.size () != indices_->size ())
00551 output.points.resize (indices_->size ());
00552
00553 if (indices_->size () != input_->points.size ())
00554 {
00555 output.width = indices_->size ();
00556 output.height = 1;
00557 }
00558 else
00559 {
00560 output.width = input_->width;
00561 output.height = input_->height;
00562 }
00563 output.is_dense = input_->is_dense;
00564
00565
00566 computeFeature (output);
00567
00568 deinitCompute ();
00569
00570
00571 if (fake_surface_)
00572 {
00573 surface_.reset ();
00574 fake_surface_ = false;
00575 }
00576 }
00577