|
Point Cloud Library (PCL)
1.4.0
|
00001 /* 00002 * Software License Agreement (BSD License) 00003 * 00004 * Point Cloud Library (PCL) - www.pointclouds.org 00005 * Copyright (c) 2010-2011, Willow Garage, Inc. 00006 * 00007 * All rights reserved. 00008 * 00009 * Redistribution and use in source and binary forms, with or without 00010 * modification, are permitted provided that the following conditions 00011 * are met: 00012 * 00013 * * Redistributions of source code must retain the above copyright 00014 * notice, this list of conditions and the following disclaimer. 00015 * * Redistributions in binary form must reproduce the above 00016 * copyright notice, this list of conditions and the following 00017 * disclaimer in the documentation and/or other materials provided 00018 * with the distribution. 00019 * * Neither the name of Willow Garage, Inc. nor the names of its 00020 * contributors may be used to endorse or promote products derived 00021 * from this software without specific prior written permission. 00022 * 00023 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 00024 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 00025 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 00026 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 00027 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 00028 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 00029 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 00030 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 00031 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 00032 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 00033 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 00034 * POSSIBILITY OF SUCH DAMAGE. 00035 * 00036 * $Id: voxel_grid.h 3746 2011-12-31 22:19:47Z rusu $ 00037 * 00038 */ 00039 00040 #ifndef PCL_FILTERS_VOXEL_GRID_MAP_H_ 00041 #define PCL_FILTERS_VOXEL_GRID_MAP_H_ 00042 00043 #include "pcl/filters/filter.h" 00044 #include <map> 00045 #include <boost/unordered_map.hpp> 00046 #include <boost/fusion/sequence/intrinsic/at_key.hpp> 00047 00048 namespace pcl 00049 { 00058 PCL_EXPORTS void 00059 getMinMax3D (const sensor_msgs::PointCloud2ConstPtr &cloud, int x_idx, int y_idx, int z_idx, 00060 Eigen::Vector4f &min_pt, Eigen::Vector4f &max_pt); 00061 00076 PCL_EXPORTS void 00077 getMinMax3D (const sensor_msgs::PointCloud2ConstPtr &cloud, int x_idx, int y_idx, int z_idx, 00078 const std::string &distance_field_name, float min_distance, float max_distance, 00079 Eigen::Vector4f &min_pt, Eigen::Vector4f &max_pt, bool limit_negative = false); 00080 00085 inline Eigen::MatrixXi 00086 getHalfNeighborCellIndices () 00087 { 00088 Eigen::MatrixXi relative_coordinates (3, 13); 00089 int idx = 0; 00090 00091 // 0 - 8 00092 for (int i = -1; i < 2; i++) 00093 { 00094 for (int j = -1; j < 2; j++) 00095 { 00096 relative_coordinates (0, idx) = i; 00097 relative_coordinates (1, idx) = j; 00098 relative_coordinates (2, idx) = -1; 00099 idx++; 00100 } 00101 } 00102 // 9 - 11 00103 for (int i = -1; i < 2; i++) 00104 { 00105 relative_coordinates (0, idx) = i; 00106 relative_coordinates (1, idx) = -1; 00107 relative_coordinates (2, idx) = 0; 00108 idx++; 00109 } 00110 // 12 00111 relative_coordinates (0, idx) = -1; 00112 relative_coordinates (1, idx) = 0; 00113 relative_coordinates (2, idx) = 0; 00114 00115 return (relative_coordinates); 00116 } 00117 00122 inline Eigen::MatrixXi 00123 getAllNeighborCellIndices () 00124 { 00125 Eigen::MatrixXi relative_coordinates = getHalfNeighborCellIndices (); 00126 Eigen::MatrixXi relative_coordinates_all( 3, 26); 00127 relative_coordinates_all.block<3, 13> (0, 0) = relative_coordinates; 00128 relative_coordinates_all.block<3, 13> (0, 13) = -relative_coordinates; 00129 return (relative_coordinates_all); 00130 } 00131 00143 template <typename PointT> void 00144 getMinMax3D (const typename pcl::PointCloud<PointT>::ConstPtr &cloud, 00145 const std::string &distance_field_name, float min_distance, float max_distance, 00146 Eigen::Vector4f &min_pt, Eigen::Vector4f &max_pt, bool limit_negative = false); 00147 00160 template <typename PointT> 00161 class VoxelGrid: public Filter<PointT> 00162 { 00163 using Filter<PointT>::filter_name_; 00164 using Filter<PointT>::getClassName; 00165 using Filter<PointT>::input_; 00166 using Filter<PointT>::indices_; 00167 00168 typedef typename Filter<PointT>::PointCloud PointCloud; 00169 typedef typename PointCloud::Ptr PointCloudPtr; 00170 typedef typename PointCloud::ConstPtr PointCloudConstPtr; 00171 00172 public: 00174 VoxelGrid () : 00175 downsample_all_data_ (true), save_leaf_layout_ (false), 00176 filter_field_name_ (""), 00177 filter_limit_min_ (-FLT_MAX), filter_limit_max_ (FLT_MAX), 00178 filter_limit_negative_ (false) 00179 { 00180 leaf_size_.setZero (); 00181 min_b_.setZero (); 00182 max_b_.setZero (); 00183 filter_name_ = "VoxelGrid"; 00184 } 00185 00187 virtual ~VoxelGrid () 00188 { 00189 leaves_.clear(); 00190 } 00191 00195 inline void 00196 setLeafSize (const Eigen::Vector4f &leaf_size) 00197 { 00198 leaf_size_ = leaf_size; 00199 // Avoid division errors 00200 if (leaf_size_[3] == 0) 00201 leaf_size_[3] = 1; 00202 // Use multiplications instead of divisions 00203 inverse_leaf_size_ = Eigen::Array4f::Ones () / leaf_size_.array (); 00204 } 00205 00211 inline void 00212 setLeafSize (float lx, float ly, float lz) 00213 { 00214 leaf_size_[0] = lx; leaf_size_[1] = ly; leaf_size_[2] = lz; 00215 // Avoid division errors 00216 if (leaf_size_[3] == 0) 00217 leaf_size_[3] = 1; 00218 // Use multiplications instead of divisions 00219 inverse_leaf_size_ = Eigen::Array4f::Ones () / leaf_size_.array (); 00220 } 00221 00223 inline Eigen::Vector3f 00224 getLeafSize () { return (leaf_size_.head<3> ()); } 00225 00229 inline void 00230 setDownsampleAllData (bool downsample) { downsample_all_data_ = downsample; } 00231 00235 inline bool 00236 getDownsampleAllData () { return (downsample_all_data_); } 00237 00241 inline void 00242 setSaveLeafLayout (bool save_leaf_layout) { save_leaf_layout_ = save_leaf_layout; } 00243 00245 inline bool 00246 getSaveLeafLayout () { return (save_leaf_layout_); } 00247 00251 inline Eigen::Vector3i 00252 getMinBoxCoordinates () { return (min_b_.head<3> ()); } 00253 00257 inline Eigen::Vector3i 00258 getMaxBoxCoordinates () { return (max_b_.head<3> ()); } 00259 00263 inline Eigen::Vector3i 00264 getNrDivisions () { return (div_b_.head<3> ()); } 00265 00269 inline Eigen::Vector3i 00270 getDivisionMultiplier () { return (divb_mul_.head<3> ()); } 00271 00280 inline int 00281 getCentroidIndex (const PointT &p) 00282 { 00283 return leaf_layout_.at ((Eigen::Vector4i (floor (p.x / leaf_size_[0]), floor (p.y / leaf_size_[1]), floor (p.z / leaf_size_[2]), 0) - min_b_).dot (divb_mul_)); 00284 } 00285 00292 inline std::vector<int> 00293 getNeighborCentroidIndices (const PointT &reference_point, const Eigen::MatrixXi &relative_coordinates) 00294 { 00295 Eigen::Vector4i ijk (floor (reference_point.x / leaf_size_[0]), floor (reference_point.y / leaf_size_[1]), floor (reference_point.z / leaf_size_[2]), 0); 00296 Eigen::Array4i diff2min = min_b_ - ijk; 00297 Eigen::Array4i diff2max = max_b_ - ijk; 00298 std::vector<int> neighbors (relative_coordinates.cols()); 00299 for (int ni = 0; ni < relative_coordinates.cols (); ni++) 00300 { 00301 Eigen::Vector4i displacement = (Eigen::Vector4i() << relative_coordinates.col(ni), 0).finished(); 00302 // checking if the specified cell is in the grid 00303 if ((diff2min <= displacement.array()).all() && (diff2max >= displacement.array()).all()) 00304 neighbors[ni] = leaf_layout_[((ijk + displacement - min_b_).dot (divb_mul_))]; // .at() can be omitted 00305 else 00306 neighbors[ni] = -1; // cell is out of bounds, consider it empty 00307 } 00308 return (neighbors); 00309 } 00310 00314 inline std::vector<int> 00315 getLeafLayout () { return (leaf_layout_); } 00316 00322 inline Eigen::Vector3i 00323 getGridCoordinates (float x, float y, float z) 00324 { 00325 return (Eigen::Vector3i (floor (x / leaf_size_[0]), floor (y / leaf_size_[1]), floor (z / leaf_size_[2]))); 00326 } 00327 00331 inline int 00332 getCentroidIndexAt (const Eigen::Vector3i &ijk) 00333 { 00334 int idx = ((Eigen::Vector4i() << ijk, 0).finished() - min_b_).dot (divb_mul_); 00335 if (idx < 0 || idx >= (int)leaf_layout_.size ()) // this checks also if leaf_layout_.size () == 0 i.e. everything was computed as needed 00336 { 00337 //if (verbose) 00338 // PCL_ERROR ("[pcl::%s::getCentroidIndexAt] Specified coordinate is outside grid bounds, or leaf layout is not saved, make sure to call setSaveLeafLayout(true) and filter(output) first!\n", getClassName ().c_str ()); 00339 return (-1); 00340 } 00341 return (leaf_layout_[idx]); 00342 } 00343 00348 inline void 00349 setFilterFieldName (const std::string &field_name) 00350 { 00351 filter_field_name_ = field_name; 00352 } 00353 00355 inline std::string const 00356 getFilterFieldName () 00357 { 00358 return (filter_field_name_); 00359 } 00360 00365 inline void 00366 setFilterLimits (const double &limit_min, const double &limit_max) 00367 { 00368 filter_limit_min_ = limit_min; 00369 filter_limit_max_ = limit_max; 00370 } 00371 00376 inline void 00377 getFilterLimits (double &limit_min, double &limit_max) 00378 { 00379 limit_min = filter_limit_min_; 00380 limit_max = filter_limit_max_; 00381 } 00382 00387 inline void 00388 setFilterLimitsNegative (const bool limit_negative) 00389 { 00390 filter_limit_negative_ = limit_negative; 00391 } 00392 00396 inline void 00397 getFilterLimitsNegative (bool &limit_negative) 00398 { 00399 limit_negative = filter_limit_negative_; 00400 } 00401 00405 inline bool 00406 getFilterLimitsNegative () 00407 { 00408 return (filter_limit_negative_); 00409 } 00410 00411 protected: 00414 struct Leaf 00415 { 00416 Leaf () : nr_points(0) {} 00417 Eigen::VectorXf centroid; // @todo we do not support FLOAT64 just yet due to memory issues. Need to fix this. 00418 int nr_points; 00419 }; 00420 00422 boost::unordered_map<size_t, Leaf> leaves_; 00423 00425 Eigen::Vector4f leaf_size_; 00426 00428 Eigen::Array4f inverse_leaf_size_; 00429 00431 bool downsample_all_data_; 00432 00434 bool save_leaf_layout_; 00435 00437 std::vector<int> leaf_layout_; 00438 00440 Eigen::Vector4i min_b_, max_b_, div_b_, divb_mul_; 00441 00443 std::string filter_field_name_; 00444 00446 double filter_limit_min_; 00447 00449 double filter_limit_max_; 00450 00452 bool filter_limit_negative_; 00453 00454 typedef typename pcl::traits::fieldList<PointT>::type FieldList; 00455 00459 void 00460 applyFilter (PointCloud &output); 00461 }; 00462 00475 template <> 00476 class PCL_EXPORTS VoxelGrid<sensor_msgs::PointCloud2> : public Filter<sensor_msgs::PointCloud2> 00477 { 00478 using Filter<sensor_msgs::PointCloud2>::filter_name_; 00479 using Filter<sensor_msgs::PointCloud2>::getClassName; 00480 00481 typedef sensor_msgs::PointCloud2 PointCloud2; 00482 typedef PointCloud2::Ptr PointCloud2Ptr; 00483 typedef PointCloud2::ConstPtr PointCloud2ConstPtr; 00484 00485 public: 00487 VoxelGrid () : 00488 downsample_all_data_ (true), save_leaf_layout_ (false), 00489 filter_field_name_ (""), filter_limit_min_ (-FLT_MAX), filter_limit_max_ (FLT_MAX), 00490 filter_limit_negative_ (false) 00491 { 00492 leaf_size_.setZero (); 00493 min_b_.setZero (); 00494 max_b_.setZero (); 00495 filter_name_ = "VoxelGrid"; 00496 } 00497 00499 virtual ~VoxelGrid () 00500 { 00501 leaves_.clear (); 00502 } 00503 00507 inline void 00508 setLeafSize (const Eigen::Vector4f &leaf_size) 00509 { 00510 leaf_size_ = leaf_size; 00511 // Avoid division errors 00512 if (leaf_size_[3] == 0) 00513 leaf_size_[3] = 1; 00514 // Use multiplications instead of divisions 00515 inverse_leaf_size_ = Eigen::Array4f::Ones () / leaf_size_.array (); 00516 } 00517 00523 inline void 00524 setLeafSize (float lx, float ly, float lz) 00525 { 00526 leaf_size_[0] = lx; leaf_size_[1] = ly; leaf_size_[2] = lz; 00527 // Avoid division errors 00528 if (leaf_size_[3] == 0) 00529 leaf_size_[3] = 1; 00530 // Use multiplications instead of divisions 00531 inverse_leaf_size_ = Eigen::Array4f::Ones () / leaf_size_.array (); 00532 } 00533 00535 inline Eigen::Vector3f 00536 getLeafSize () { return (leaf_size_.head<3> ()); } 00537 00541 inline void 00542 setDownsampleAllData (bool downsample) { downsample_all_data_ = downsample; } 00543 00547 inline bool 00548 getDownsampleAllData () { return (downsample_all_data_); } 00549 00553 inline void 00554 setSaveLeafLayout (bool save_leaf_layout) { save_leaf_layout_ = save_leaf_layout; } 00555 00557 inline bool 00558 getSaveLeafLayout () { return (save_leaf_layout_); } 00559 00563 inline Eigen::Vector3i 00564 getMinBoxCoordinates () { return (min_b_.head<3> ()); } 00565 00569 inline Eigen::Vector3i 00570 getMaxBoxCoordinates () { return (max_b_.head<3> ()); } 00571 00575 inline Eigen::Vector3i 00576 getNrDivisions () { return (div_b_.head<3> ()); } 00577 00581 inline Eigen::Vector3i 00582 getDivisionMultiplier () { return (divb_mul_.head<3> ()); } 00583 00591 inline int 00592 getCentroidIndex (float x, float y, float z) 00593 { 00594 return (leaf_layout_.at ((Eigen::Vector4i ((int) floor (x / leaf_size_[0]), (int) floor (y / leaf_size_[1]), (int) floor (z / leaf_size_[2]), 0) - min_b_).dot (divb_mul_))); 00595 } 00596 00605 inline std::vector<int> 00606 getNeighborCentroidIndices (float x, float y, float z, const Eigen::MatrixXi &relative_coordinates) 00607 { 00608 Eigen::Vector4i ijk ((int) floor (x / leaf_size_[0]), (int) floor (y / leaf_size_[1]), (int) floor (z / leaf_size_[2]), 0); 00609 Eigen::Array4i diff2min = min_b_ - ijk; 00610 Eigen::Array4i diff2max = max_b_ - ijk; 00611 std::vector<int> neighbors (relative_coordinates.cols()); 00612 for (int ni = 0; ni < relative_coordinates.cols (); ni++) 00613 { 00614 Eigen::Vector4i displacement = (Eigen::Vector4i() << relative_coordinates.col(ni), 0).finished(); 00615 // checking if the specified cell is in the grid 00616 if ((diff2min <= displacement.array()).all() && (diff2max >= displacement.array()).all()) 00617 neighbors[ni] = leaf_layout_[((ijk + displacement - min_b_).dot (divb_mul_))]; // .at() can be omitted 00618 else 00619 neighbors[ni] = -1; // cell is out of bounds, consider it empty 00620 } 00621 return (neighbors); 00622 } 00623 00632 inline std::vector<int> 00633 getNeighborCentroidIndices (float x, float y, float z, const std::vector<Eigen::Vector3i> &relative_coordinates) 00634 { 00635 Eigen::Vector4i ijk ((int) floor (x / leaf_size_[0]), (int) floor (y / leaf_size_[1]), (int) floor (z / leaf_size_[2]), 0); 00636 std::vector<int> neighbors; 00637 neighbors.reserve (relative_coordinates.size ()); 00638 for (std::vector<Eigen::Vector3i>::const_iterator it = relative_coordinates.begin (); it != relative_coordinates.end (); it++) 00639 neighbors.push_back (leaf_layout_[(ijk + (Eigen::Vector4i() << *it, 0).finished() - min_b_).dot (divb_mul_)]); 00640 return (neighbors); 00641 } 00642 00646 inline std::vector<int> 00647 getLeafLayout () { return (leaf_layout_); } 00648 00654 inline Eigen::Vector3i 00655 getGridCoordinates (float x, float y, float z) 00656 { 00657 return (Eigen::Vector3i ((int) floor (x / leaf_size_[0]), (int) floor (y / leaf_size_[1]), (int) floor (z / leaf_size_[2]))); 00658 } 00659 00663 inline int 00664 getCentroidIndexAt (const Eigen::Vector3i &ijk) 00665 { 00666 int idx = ((Eigen::Vector4i() << ijk, 0).finished() - min_b_).dot (divb_mul_); 00667 if (idx < 0 || idx >= (int)leaf_layout_.size ()) // this checks also if leaf_layout_.size () == 0 i.e. everything was computed as needed 00668 { 00669 //if (verbose) 00670 // PCL_ERROR ("[pcl::%s::getCentroidIndexAt] Specified coordinate is outside grid bounds, or leaf layout is not saved, make sure to call setSaveLeafLayout(true) and filter(output) first!\n", getClassName ().c_str ()); 00671 return (-1); 00672 } 00673 return (leaf_layout_[idx]); 00674 } 00675 00680 inline void 00681 setFilterFieldName (const std::string &field_name) 00682 { 00683 filter_field_name_ = field_name; 00684 } 00685 00687 inline std::string const 00688 getFilterFieldName () 00689 { 00690 return (filter_field_name_); 00691 } 00692 00697 inline void 00698 setFilterLimits (const double &limit_min, const double &limit_max) 00699 { 00700 filter_limit_min_ = limit_min; 00701 filter_limit_max_ = limit_max; 00702 } 00703 00708 inline void 00709 getFilterLimits (double &limit_min, double &limit_max) 00710 { 00711 limit_min = filter_limit_min_; 00712 limit_max = filter_limit_max_; 00713 } 00714 00719 inline void 00720 setFilterLimitsNegative (const bool limit_negative) 00721 { 00722 filter_limit_negative_ = limit_negative; 00723 } 00724 00728 inline void 00729 getFilterLimitsNegative (bool &limit_negative) 00730 { 00731 limit_negative = filter_limit_negative_; 00732 } 00733 00737 inline bool 00738 getFilterLimitsNegative () 00739 { 00740 return (filter_limit_negative_); 00741 } 00742 00743 protected: 00746 struct Leaf 00747 { 00748 Leaf () : nr_points(0) { } 00749 Eigen::VectorXf centroid; // @todo we do not support FLOAT64 just yet due to memory issues. Need to fix this. 00750 int nr_points; 00751 }; 00752 00754 boost::unordered_map<size_t, Leaf> leaves_; 00755 00757 Eigen::Vector4f leaf_size_; 00758 00760 Eigen::Array4f inverse_leaf_size_; 00761 00763 bool downsample_all_data_; 00764 00768 bool save_leaf_layout_; 00769 00773 std::vector<int> leaf_layout_; 00774 00778 Eigen::Vector4i min_b_, max_b_, div_b_, divb_mul_; 00779 00781 std::string filter_field_name_; 00782 00784 double filter_limit_min_; 00785 00787 double filter_limit_max_; 00788 00790 bool filter_limit_negative_; 00791 00795 void 00796 applyFilter (PointCloud2 &output); 00797 }; 00798 } 00799 00800 #endif //#ifndef PCL_FILTERS_VOXEL_GRID_MAP_H_
1.7.6.1