|
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) 2009-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 */ 00037 00038 #ifndef PCL_KDTREE_KDTREE_IMPL_FLANN_H_ 00039 #define PCL_KDTREE_KDTREE_IMPL_FLANN_H_ 00040 00041 #include "pcl/kdtree/kdtree_flann.h" 00042 #include <pcl/console/print.h> 00043 00045 template <typename PointT, typename Dist> void 00046 pcl::KdTreeFLANN<PointT, Dist>::setInputCloud (const PointCloudConstPtr &cloud, const IndicesConstPtr &indices) 00047 { 00048 cleanup (); // Perform an automatic cleanup of structures 00049 00050 if (!initParameters()) 00051 return; 00052 00053 input_ = cloud; 00054 indices_ = indices; 00055 00056 if (input_ == NULL) 00057 return; 00058 00059 m_lock_.lock (); 00060 // Allocate enough data 00061 if (!input_) 00062 { 00063 PCL_ERROR ("[pcl::KdTreeANN::setInputCloud] Invalid input!\n"); 00064 return; 00065 } 00066 if (indices != NULL) 00067 convertCloudToArray (*input_, *indices_); 00068 else 00069 convertCloudToArray (*input_); 00070 00071 initData (); 00072 m_lock_.unlock (); 00073 } 00074 00076 template <typename PointT, typename Dist> int 00077 pcl::KdTreeFLANN<PointT, Dist>::nearestKSearch (const PointT &point, int k, 00078 std::vector<int> &k_indices, 00079 std::vector<float> &k_distances) 00080 { 00081 if (!point_representation_->isValid (point)) 00082 { 00083 //PCL_ERROR_STREAM ("[pcl::KdTreeFLANN::nearestKSearch] Invalid query point given!" << point); 00084 return (0); 00085 } 00086 00087 // Pay the price of resizing the arrays the first time nearestKSearch gets called 00088 if (k_indices.size () < (size_t)k) 00089 k_indices.resize (k); 00090 if (k_distances.size () < (size_t)k) 00091 k_distances.resize (k); 00092 00093 // Wrap the k_indices and k_distances vectors (no data copy) 00094 flann::Matrix<int> k_indices_mat (&k_indices[0], 1, k); 00095 flann::Matrix<float> k_distances_mat (&k_distances[0], 1, k); 00096 00097 std::vector<float> tmp (dim_); 00098 point_representation_->vectorize ((PointT)point, tmp); 00099 00100 flann_index_->knnSearch (flann::Matrix<float>(&tmp[0], 1, dim_), k_indices_mat, k_distances_mat, k, param_k_); 00101 00102 // Do mapping to original point cloud 00103 if (!identity_mapping_) 00104 { 00105 for (size_t i = 0; i < (size_t)k; ++i) 00106 { 00107 int& neighbor_index = k_indices[i]; 00108 neighbor_index = index_mapping_[neighbor_index]; 00109 } 00110 } 00111 00112 return (k); 00113 } 00114 00116 template <typename PointT, typename Dist> int 00117 pcl::KdTreeFLANN<PointT, Dist>::radiusSearch (const PointT &point, double radius, std::vector<int> &k_indices, 00118 std::vector<float> &k_squared_distances, int max_nn) const 00119 { 00120 static flann::Matrix<int> indices_empty; 00121 static flann::Matrix<float> dists_empty; 00122 00123 if (!point_representation_->isValid (point)) 00124 { 00125 //PCL_ERROR_STREAM ("[pcl::KdTreeFLANN::radiusSearch] Invalid query point given!" << point); 00126 return (0); 00127 } 00128 00129 std::vector<float> tmp(dim_); 00130 point_representation_->vectorize ((PointT)point, tmp); 00131 radius *= radius; // flann uses squared radius 00132 00133 size_t size; 00134 if (indices_ == NULL) // no indices set, use full size of point cloud: 00135 size = input_->points.size (); 00136 else 00137 size = indices_->size (); 00138 00139 int neighbors_in_radius = 0; 00140 if (k_indices.size () == size && k_squared_distances.size () == size) // preallocated vectors 00141 { 00142 // if using preallocated vectors we ignore max_nn as we are sure to have enought space 00143 // to store all neighbors found in radius 00144 flann::Matrix<int> k_indices_mat (&k_indices[0], 1, k_indices.size()); 00145 flann::Matrix<float> k_distances_mat (&k_squared_distances[0], 1, k_squared_distances.size()); 00146 neighbors_in_radius = flann_index_->radiusSearch (flann::Matrix<float>(&tmp[0], 1, dim_), 00147 k_indices_mat, k_distances_mat, radius, 00148 param_radius_); 00149 } 00150 else // need to do search twice, first to find how many neighbors and allocate the vectors 00151 { 00152 neighbors_in_radius = flann_index_->radiusSearch (flann::Matrix<float>(&tmp[0], 1, dim_), 00153 indices_empty, dists_empty, radius, 00154 param_radius_); 00155 00156 // If the number of maximum nearest neighbors is given, use it to cap the return 00157 if (max_nn > 0) 00158 neighbors_in_radius = std::min (neighbors_in_radius, max_nn); 00159 00160 k_indices.resize (neighbors_in_radius); 00161 k_squared_distances.resize (neighbors_in_radius); 00162 00163 if (neighbors_in_radius == 0) 00164 return (0); 00165 00166 flann::Matrix<int> k_indices_mat (&k_indices[0], 1, k_indices.size ()); 00167 flann::Matrix<float> k_distances_mat (&k_squared_distances[0], 1, k_squared_distances.size ()); 00168 flann_index_->radiusSearch (flann::Matrix<float>(&tmp[0], 1, dim_), 00169 k_indices_mat, k_distances_mat, radius, 00170 param_radius_); 00171 } 00172 00173 // Do mapping to original point cloud 00174 if (!identity_mapping_) 00175 { 00176 for (int i = 0; i < neighbors_in_radius; ++i) 00177 { 00178 int& neighbor_index = k_indices[i]; 00179 neighbor_index = index_mapping_[neighbor_index]; 00180 } 00181 } 00182 00183 return (neighbors_in_radius); 00184 } 00185 00187 template <typename PointT, typename Dist> void 00188 pcl::KdTreeFLANN<PointT, Dist>::cleanup () 00189 { 00190 delete flann_index_; 00191 00192 m_lock_.lock (); 00193 // Data array cleanup 00194 free (cloud_); 00195 cloud_ = NULL; 00196 index_mapping_.clear(); 00197 00198 if (indices_) 00199 indices_.reset (); 00200 00201 m_lock_.unlock (); 00202 } 00203 00205 template <typename PointT, typename Dist> bool 00206 pcl::KdTreeFLANN<PointT, Dist>::initParameters () 00207 { 00208 epsilon_ = 0.0; // default error bound value 00209 dim_ = point_representation_->getNumberOfDimensions (); // Number of dimensions - default is 3 = xyz 00210 // Create the kd_tree representation 00211 return (true); 00212 } 00213 00215 template <typename PointT, typename Dist> void 00216 pcl::KdTreeFLANN<PointT, Dist>::initData () 00217 { 00218 flann_index_ = new FLANNIndex (flann::Matrix<float> (cloud_, index_mapping_.size (), dim_), 00219 flann::KDTreeSingleIndexParams (15)); // max 15 points/leaf 00220 flann_index_->buildIndex (); 00221 } 00222 00224 template <typename PointT, typename Dist> void 00225 pcl::KdTreeFLANN<PointT, Dist>::convertCloudToArray (const PointCloud &cloud) 00226 { 00227 // No point in doing anything if the array is empty 00228 if (cloud.points.empty ()) 00229 { 00230 cloud_ = NULL; 00231 return; 00232 } 00233 00234 int original_no_of_points = cloud.points.size (); 00235 00236 cloud_ = (float*)malloc (original_no_of_points * dim_ * sizeof(float)); 00237 float* cloud_ptr = cloud_; 00238 index_mapping_.reserve (original_no_of_points); 00239 identity_mapping_ = true; 00240 00241 for (int cloud_index = 0; cloud_index < original_no_of_points; ++cloud_index) 00242 { 00243 const PointT point = cloud.points[cloud_index]; 00244 // Check if the point is invalid 00245 if (!point_representation_->isValid (point)) 00246 { 00247 identity_mapping_ = false; 00248 continue; 00249 } 00250 00251 index_mapping_.push_back(cloud_index); 00252 00253 point_representation_->vectorize (point, cloud_ptr); 00254 cloud_ptr += dim_; 00255 } 00256 } 00257 00259 template <typename PointT, typename Dist> void 00260 pcl::KdTreeFLANN<PointT, Dist>::convertCloudToArray (const PointCloud &cloud, const std::vector<int> &indices) 00261 { 00262 // No point in doing anything if the array is empty 00263 if (cloud.points.empty ()) 00264 { 00265 cloud_ = NULL; 00266 return; 00267 } 00268 00269 int original_no_of_points = indices.size (); 00270 00271 cloud_ = (float*)malloc (original_no_of_points * dim_ * sizeof (float)); 00272 float* cloud_ptr = cloud_; 00273 index_mapping_.reserve (original_no_of_points); 00274 identity_mapping_ = true; 00275 00276 for (int indices_index = 0; indices_index < original_no_of_points; ++indices_index) 00277 { 00278 int cloud_index = indices[indices_index]; 00279 const PointT point = cloud.points[cloud_index]; 00280 // Check if the point is invalid 00281 if (!point_representation_->isValid (point)) 00282 { 00283 identity_mapping_ = false; 00284 continue; 00285 } 00286 00287 index_mapping_.push_back (indices_index); // If the returned index should be for the indices vector 00288 //index_mapping_.push_back(cloud_index); // If the returned index should be for the ros cloud 00289 00290 point_representation_->vectorize (point, cloud_ptr); 00291 cloud_ptr += dim_; 00292 } 00293 } 00294 00295 #define PCL_INSTANTIATE_KdTreeFLANN(T) template class PCL_EXPORTS pcl::KdTreeFLANN<T>; 00296 00297 #endif //#ifndef _PCL_KDTREE_KDTREE_IMPL_FLANN_H_ 00298
1.7.6.1