|
Point Cloud Library (PCL)
1.5.1
|
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 4702 2012-02-23 09:39:33Z gedikli $ 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 protected: 00164 using Filter<PointT>::filter_name_; 00165 using Filter<PointT>::getClassName; 00166 using Filter<PointT>::input_; 00167 using Filter<PointT>::indices_; 00168 00169 typedef typename Filter<PointT>::PointCloud PointCloud; 00170 typedef typename PointCloud::Ptr PointCloudPtr; 00171 typedef typename PointCloud::ConstPtr PointCloudConstPtr; 00172 00173 public: 00175 VoxelGrid () : 00176 downsample_all_data_ (true), save_leaf_layout_ (false), 00177 filter_field_name_ (""), 00178 filter_limit_min_ (-FLT_MAX), filter_limit_max_ (FLT_MAX), 00179 filter_limit_negative_ (false) 00180 { 00181 leaf_size_.setZero (); 00182 min_b_.setZero (); 00183 max_b_.setZero (); 00184 filter_name_ = "VoxelGrid"; 00185 } 00186 00188 virtual ~VoxelGrid () 00189 { 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: 00413 Eigen::Vector4f leaf_size_; 00414 00416 Eigen::Array4f inverse_leaf_size_; 00417 00419 bool downsample_all_data_; 00420 00422 bool save_leaf_layout_; 00423 00425 std::vector<int> leaf_layout_; 00426 00428 Eigen::Vector4i min_b_, max_b_, div_b_, divb_mul_; 00429 00431 std::string filter_field_name_; 00432 00434 double filter_limit_min_; 00435 00437 double filter_limit_max_; 00438 00440 bool filter_limit_negative_; 00441 00442 typedef typename pcl::traits::fieldList<PointT>::type FieldList; 00443 00447 void 00448 applyFilter (PointCloud &output); 00449 }; 00450 00463 template <> 00464 class PCL_EXPORTS VoxelGrid<sensor_msgs::PointCloud2> : public Filter<sensor_msgs::PointCloud2> 00465 { 00466 using Filter<sensor_msgs::PointCloud2>::filter_name_; 00467 using Filter<sensor_msgs::PointCloud2>::getClassName; 00468 00469 typedef sensor_msgs::PointCloud2 PointCloud2; 00470 typedef PointCloud2::Ptr PointCloud2Ptr; 00471 typedef PointCloud2::ConstPtr PointCloud2ConstPtr; 00472 00473 public: 00475 VoxelGrid () : 00476 downsample_all_data_ (true), save_leaf_layout_ (false), 00477 filter_field_name_ (""), filter_limit_min_ (-FLT_MAX), filter_limit_max_ (FLT_MAX), 00478 filter_limit_negative_ (false) 00479 { 00480 leaf_size_.setZero (); 00481 min_b_.setZero (); 00482 max_b_.setZero (); 00483 filter_name_ = "VoxelGrid"; 00484 } 00485 00487 virtual ~VoxelGrid () 00488 { 00489 } 00490 00494 inline void 00495 setLeafSize (const Eigen::Vector4f &leaf_size) 00496 { 00497 leaf_size_ = leaf_size; 00498 // Avoid division errors 00499 if (leaf_size_[3] == 0) 00500 leaf_size_[3] = 1; 00501 // Use multiplications instead of divisions 00502 inverse_leaf_size_ = Eigen::Array4f::Ones () / leaf_size_.array (); 00503 } 00504 00510 inline void 00511 setLeafSize (float lx, float ly, float lz) 00512 { 00513 leaf_size_[0] = lx; leaf_size_[1] = ly; leaf_size_[2] = lz; 00514 // Avoid division errors 00515 if (leaf_size_[3] == 0) 00516 leaf_size_[3] = 1; 00517 // Use multiplications instead of divisions 00518 inverse_leaf_size_ = Eigen::Array4f::Ones () / leaf_size_.array (); 00519 } 00520 00522 inline Eigen::Vector3f 00523 getLeafSize () { return (leaf_size_.head<3> ()); } 00524 00528 inline void 00529 setDownsampleAllData (bool downsample) { downsample_all_data_ = downsample; } 00530 00534 inline bool 00535 getDownsampleAllData () { return (downsample_all_data_); } 00536 00540 inline void 00541 setSaveLeafLayout (bool save_leaf_layout) { save_leaf_layout_ = save_leaf_layout; } 00542 00544 inline bool 00545 getSaveLeafLayout () { return (save_leaf_layout_); } 00546 00550 inline Eigen::Vector3i 00551 getMinBoxCoordinates () { return (min_b_.head<3> ()); } 00552 00556 inline Eigen::Vector3i 00557 getMaxBoxCoordinates () { return (max_b_.head<3> ()); } 00558 00562 inline Eigen::Vector3i 00563 getNrDivisions () { return (div_b_.head<3> ()); } 00564 00568 inline Eigen::Vector3i 00569 getDivisionMultiplier () { return (divb_mul_.head<3> ()); } 00570 00578 inline int 00579 getCentroidIndex (float x, float y, float z) 00580 { 00581 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_))); 00582 } 00583 00592 inline std::vector<int> 00593 getNeighborCentroidIndices (float x, float y, float z, const Eigen::MatrixXi &relative_coordinates) 00594 { 00595 Eigen::Vector4i ijk ((int) floor (x / leaf_size_[0]), (int) floor (y / leaf_size_[1]), (int) floor (z / leaf_size_[2]), 0); 00596 Eigen::Array4i diff2min = min_b_ - ijk; 00597 Eigen::Array4i diff2max = max_b_ - ijk; 00598 std::vector<int> neighbors (relative_coordinates.cols()); 00599 for (int ni = 0; ni < relative_coordinates.cols (); ni++) 00600 { 00601 Eigen::Vector4i displacement = (Eigen::Vector4i() << relative_coordinates.col(ni), 0).finished(); 00602 // checking if the specified cell is in the grid 00603 if ((diff2min <= displacement.array()).all() && (diff2max >= displacement.array()).all()) 00604 neighbors[ni] = leaf_layout_[((ijk + displacement - min_b_).dot (divb_mul_))]; // .at() can be omitted 00605 else 00606 neighbors[ni] = -1; // cell is out of bounds, consider it empty 00607 } 00608 return (neighbors); 00609 } 00610 00619 inline std::vector<int> 00620 getNeighborCentroidIndices (float x, float y, float z, const std::vector<Eigen::Vector3i> &relative_coordinates) 00621 { 00622 Eigen::Vector4i ijk ((int) floor (x / leaf_size_[0]), (int) floor (y / leaf_size_[1]), (int) floor (z / leaf_size_[2]), 0); 00623 std::vector<int> neighbors; 00624 neighbors.reserve (relative_coordinates.size ()); 00625 for (std::vector<Eigen::Vector3i>::const_iterator it = relative_coordinates.begin (); it != relative_coordinates.end (); it++) 00626 neighbors.push_back (leaf_layout_[(ijk + (Eigen::Vector4i() << *it, 0).finished() - min_b_).dot (divb_mul_)]); 00627 return (neighbors); 00628 } 00629 00633 inline std::vector<int> 00634 getLeafLayout () { return (leaf_layout_); } 00635 00641 inline Eigen::Vector3i 00642 getGridCoordinates (float x, float y, float z) 00643 { 00644 return (Eigen::Vector3i ((int) floor (x / leaf_size_[0]), (int) floor (y / leaf_size_[1]), (int) floor (z / leaf_size_[2]))); 00645 } 00646 00650 inline int 00651 getCentroidIndexAt (const Eigen::Vector3i &ijk) 00652 { 00653 int idx = ((Eigen::Vector4i() << ijk, 0).finished() - min_b_).dot (divb_mul_); 00654 if (idx < 0 || idx >= (int)leaf_layout_.size ()) // this checks also if leaf_layout_.size () == 0 i.e. everything was computed as needed 00655 { 00656 //if (verbose) 00657 // 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 ()); 00658 return (-1); 00659 } 00660 return (leaf_layout_[idx]); 00661 } 00662 00667 inline void 00668 setFilterFieldName (const std::string &field_name) 00669 { 00670 filter_field_name_ = field_name; 00671 } 00672 00674 inline std::string const 00675 getFilterFieldName () 00676 { 00677 return (filter_field_name_); 00678 } 00679 00684 inline void 00685 setFilterLimits (const double &limit_min, const double &limit_max) 00686 { 00687 filter_limit_min_ = limit_min; 00688 filter_limit_max_ = limit_max; 00689 } 00690 00695 inline void 00696 getFilterLimits (double &limit_min, double &limit_max) 00697 { 00698 limit_min = filter_limit_min_; 00699 limit_max = filter_limit_max_; 00700 } 00701 00706 inline void 00707 setFilterLimitsNegative (const bool limit_negative) 00708 { 00709 filter_limit_negative_ = limit_negative; 00710 } 00711 00715 inline void 00716 getFilterLimitsNegative (bool &limit_negative) 00717 { 00718 limit_negative = filter_limit_negative_; 00719 } 00720 00724 inline bool 00725 getFilterLimitsNegative () 00726 { 00727 return (filter_limit_negative_); 00728 } 00729 00730 protected: 00732 Eigen::Vector4f leaf_size_; 00733 00735 Eigen::Array4f inverse_leaf_size_; 00736 00738 bool downsample_all_data_; 00739 00743 bool save_leaf_layout_; 00744 00748 std::vector<int> leaf_layout_; 00749 00753 Eigen::Vector4i min_b_, max_b_, div_b_, divb_mul_; 00754 00756 std::string filter_field_name_; 00757 00759 double filter_limit_min_; 00760 00762 double filter_limit_max_; 00763 00765 bool filter_limit_negative_; 00766 00770 void 00771 applyFilter (PointCloud2 &output); 00772 }; 00773 } 00774 00775 #endif //#ifndef PCL_FILTERS_VOXEL_GRID_MAP_H_
1.8.0