Point Cloud Library (PCL)
1.7.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 * Copyright (c) 2012-, Open Perception, Inc. 00007 * 00008 * All rights reserved. 00009 * 00010 * Redistribution and use in source and binary forms, with or without 00011 * modification, are permitted provided that the following conditions 00012 * are met: 00013 * 00014 * * Redistributions of source code must retain the above copyright 00015 * notice, this list of conditions and the following disclaimer. 00016 * * Redistributions in binary form must reproduce the above 00017 * copyright notice, this list of conditions and the following 00018 * disclaimer in the documentation and/or other materials provided 00019 * with the distribution. 00020 * * Neither the name of the copyright holder(s) nor the names of its 00021 * contributors may be used to endorse or promote products derived 00022 * from this software without specific prior written permission. 00023 * 00024 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 00025 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 00026 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 00027 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 00028 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 00029 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 00030 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 00031 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 00032 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 00033 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 00034 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 00035 * POSSIBILITY OF SUCH DAMAGE. 00036 * 00037 * $Id$ 00038 * 00039 */ 00040 00041 #ifndef PCL_SAMPLE_CONSENSUS_IMPL_SAC_MODEL_REGISTRATION_H_ 00042 #define PCL_SAMPLE_CONSENSUS_IMPL_SAC_MODEL_REGISTRATION_H_ 00043 00044 #include <pcl/sample_consensus/sac_model_registration.h> 00045 #include <pcl/common/point_operators.h> 00046 #include <pcl/common/eigen.h> 00047 #include <pcl/point_types.h> 00048 00049 ////////////////////////////////////////////////////////////////////////// 00050 template <typename PointT> bool 00051 pcl::SampleConsensusModelRegistration<PointT>::isSampleGood (const std::vector<int> &samples) const 00052 { 00053 using namespace pcl::common; 00054 using namespace pcl::traits; 00055 00056 PointT p10 = input_->points[samples[1]] - input_->points[samples[0]]; 00057 PointT p20 = input_->points[samples[2]] - input_->points[samples[0]]; 00058 PointT p21 = input_->points[samples[2]] - input_->points[samples[1]]; 00059 00060 return ((p10.x * p10.x + p10.y * p10.y + p10.z * p10.z) > sample_dist_thresh_ && 00061 (p20.x * p20.x + p20.y * p20.y + p20.z * p20.z) > sample_dist_thresh_ && 00062 (p21.x * p21.x + p21.y * p21.y + p21.z * p21.z) > sample_dist_thresh_); 00063 } 00064 00065 ////////////////////////////////////////////////////////////////////////// 00066 template <typename PointT> bool 00067 pcl::SampleConsensusModelRegistration<PointT>::computeModelCoefficients (const std::vector<int> &samples, Eigen::VectorXf &model_coefficients) 00068 { 00069 if (!target_) 00070 { 00071 PCL_ERROR ("[pcl::SampleConsensusModelRegistration::computeModelCoefficients] No target dataset given!\n"); 00072 return (false); 00073 } 00074 // Need 3 samples 00075 if (samples.size () != 3) 00076 return (false); 00077 00078 std::vector<int> indices_tgt (3); 00079 for (int i = 0; i < 3; ++i) 00080 indices_tgt[i] = correspondences_[samples[i]]; 00081 00082 estimateRigidTransformationSVD (*input_, samples, *target_, indices_tgt, model_coefficients); 00083 return (true); 00084 } 00085 00086 ////////////////////////////////////////////////////////////////////////// 00087 template <typename PointT> void 00088 pcl::SampleConsensusModelRegistration<PointT>::getDistancesToModel (const Eigen::VectorXf &model_coefficients, std::vector<double> &distances) 00089 { 00090 if (indices_->size () != indices_tgt_->size ()) 00091 { 00092 PCL_ERROR ("[pcl::SampleConsensusModelRegistration::getDistancesToModel] Number of source indices (%zu) differs than number of target indices (%zu)!\n", indices_->size (), indices_tgt_->size ()); 00093 distances.clear (); 00094 return; 00095 } 00096 if (!target_) 00097 { 00098 PCL_ERROR ("[pcl::SampleConsensusModelRegistration::getDistanceToModel] No target dataset given!\n"); 00099 return; 00100 } 00101 // Check if the model is valid given the user constraints 00102 if (!isModelValid (model_coefficients)) 00103 { 00104 distances.clear (); 00105 return; 00106 } 00107 distances.resize (indices_->size ()); 00108 00109 // Get the 4x4 transformation 00110 Eigen::Matrix4f transform; 00111 transform.row (0).matrix () = model_coefficients.segment<4>(0); 00112 transform.row (1).matrix () = model_coefficients.segment<4>(4); 00113 transform.row (2).matrix () = model_coefficients.segment<4>(8); 00114 transform.row (3).matrix () = model_coefficients.segment<4>(12); 00115 00116 for (size_t i = 0; i < indices_->size (); ++i) 00117 { 00118 Eigen::Vector4f pt_src (input_->points[(*indices_)[i]].x, 00119 input_->points[(*indices_)[i]].y, 00120 input_->points[(*indices_)[i]].z, 1); 00121 Eigen::Vector4f pt_tgt (target_->points[(*indices_tgt_)[i]].x, 00122 target_->points[(*indices_tgt_)[i]].y, 00123 target_->points[(*indices_tgt_)[i]].z, 1); 00124 00125 Eigen::Vector4f p_tr (transform * pt_src); 00126 // Calculate the distance from the transformed point to its correspondence 00127 // need to compute the real norm here to keep MSAC and friends general 00128 distances[i] = (p_tr - pt_tgt).norm (); 00129 } 00130 } 00131 00132 ////////////////////////////////////////////////////////////////////////// 00133 template <typename PointT> void 00134 pcl::SampleConsensusModelRegistration<PointT>::selectWithinDistance (const Eigen::VectorXf &model_coefficients, const double threshold, std::vector<int> &inliers) 00135 { 00136 if (indices_->size () != indices_tgt_->size ()) 00137 { 00138 PCL_ERROR ("[pcl::SampleConsensusModelRegistration::selectWithinDistance] Number of source indices (%zu) differs than number of target indices (%zu)!\n", indices_->size (), indices_tgt_->size ()); 00139 inliers.clear (); 00140 return; 00141 } 00142 if (!target_) 00143 { 00144 PCL_ERROR ("[pcl::SampleConsensusModelRegistration::selectWithinDistance] No target dataset given!\n"); 00145 return; 00146 } 00147 00148 double thresh = threshold * threshold; 00149 00150 // Check if the model is valid given the user constraints 00151 if (!isModelValid (model_coefficients)) 00152 { 00153 inliers.clear (); 00154 return; 00155 } 00156 00157 int nr_p = 0; 00158 inliers.resize (indices_->size ()); 00159 error_sqr_dists_.resize (indices_->size ()); 00160 00161 Eigen::Matrix4f transform; 00162 transform.row (0).matrix () = model_coefficients.segment<4>(0); 00163 transform.row (1).matrix () = model_coefficients.segment<4>(4); 00164 transform.row (2).matrix () = model_coefficients.segment<4>(8); 00165 transform.row (3).matrix () = model_coefficients.segment<4>(12); 00166 00167 for (size_t i = 0; i < indices_->size (); ++i) 00168 { 00169 Eigen::Vector4f pt_src (input_->points[(*indices_)[i]].x, 00170 input_->points[(*indices_)[i]].y, 00171 input_->points[(*indices_)[i]].z, 1); 00172 Eigen::Vector4f pt_tgt (target_->points[(*indices_tgt_)[i]].x, 00173 target_->points[(*indices_tgt_)[i]].y, 00174 target_->points[(*indices_tgt_)[i]].z, 1); 00175 00176 Eigen::Vector4f p_tr (transform * pt_src); 00177 00178 float distance = (p_tr - pt_tgt).squaredNorm (); 00179 // Calculate the distance from the transformed point to its correspondence 00180 if (distance < thresh) 00181 { 00182 inliers[nr_p] = (*indices_)[i]; 00183 error_sqr_dists_[nr_p] = static_cast<double> (distance); 00184 ++nr_p; 00185 } 00186 } 00187 inliers.resize (nr_p); 00188 error_sqr_dists_.resize (nr_p); 00189 } 00190 00191 ////////////////////////////////////////////////////////////////////////// 00192 template <typename PointT> int 00193 pcl::SampleConsensusModelRegistration<PointT>::countWithinDistance ( 00194 const Eigen::VectorXf &model_coefficients, const double threshold) 00195 { 00196 if (indices_->size () != indices_tgt_->size ()) 00197 { 00198 PCL_ERROR ("[pcl::SampleConsensusModelRegistration::countWithinDistance] Number of source indices (%zu) differs than number of target indices (%zu)!\n", indices_->size (), indices_tgt_->size ()); 00199 return (0); 00200 } 00201 if (!target_) 00202 { 00203 PCL_ERROR ("[pcl::SampleConsensusModelRegistration::countWithinDistance] No target dataset given!\n"); 00204 return (0); 00205 } 00206 00207 double thresh = threshold * threshold; 00208 00209 // Check if the model is valid given the user constraints 00210 if (!isModelValid (model_coefficients)) 00211 return (0); 00212 00213 Eigen::Matrix4f transform; 00214 transform.row (0).matrix () = model_coefficients.segment<4>(0); 00215 transform.row (1).matrix () = model_coefficients.segment<4>(4); 00216 transform.row (2).matrix () = model_coefficients.segment<4>(8); 00217 transform.row (3).matrix () = model_coefficients.segment<4>(12); 00218 00219 int nr_p = 0; 00220 for (size_t i = 0; i < indices_->size (); ++i) 00221 { 00222 Eigen::Vector4f pt_src (input_->points[(*indices_)[i]].x, 00223 input_->points[(*indices_)[i]].y, 00224 input_->points[(*indices_)[i]].z, 1); 00225 Eigen::Vector4f pt_tgt (target_->points[(*indices_tgt_)[i]].x, 00226 target_->points[(*indices_tgt_)[i]].y, 00227 target_->points[(*indices_tgt_)[i]].z, 1); 00228 00229 Eigen::Vector4f p_tr (transform * pt_src); 00230 // Calculate the distance from the transformed point to its correspondence 00231 if ((p_tr - pt_tgt).squaredNorm () < thresh) 00232 nr_p++; 00233 } 00234 return (nr_p); 00235 } 00236 00237 ////////////////////////////////////////////////////////////////////////// 00238 template <typename PointT> void 00239 pcl::SampleConsensusModelRegistration<PointT>::optimizeModelCoefficients (const std::vector<int> &inliers, const Eigen::VectorXf &model_coefficients, Eigen::VectorXf &optimized_coefficients) 00240 { 00241 if (indices_->size () != indices_tgt_->size ()) 00242 { 00243 PCL_ERROR ("[pcl::SampleConsensusModelRegistration::optimizeModelCoefficients] Number of source indices (%zu) differs than number of target indices (%zu)!\n", indices_->size (), indices_tgt_->size ()); 00244 optimized_coefficients = model_coefficients; 00245 return; 00246 } 00247 00248 // Check if the model is valid given the user constraints 00249 if (!isModelValid (model_coefficients) || !target_) 00250 { 00251 optimized_coefficients = model_coefficients; 00252 return; 00253 } 00254 00255 std::vector<int> indices_src (inliers.size ()); 00256 std::vector<int> indices_tgt (inliers.size ()); 00257 for (size_t i = 0; i < inliers.size (); ++i) 00258 { 00259 indices_src[i] = inliers[i]; 00260 indices_tgt[i] = correspondences_[indices_src[i]]; 00261 } 00262 00263 estimateRigidTransformationSVD (*input_, indices_src, *target_, indices_tgt, optimized_coefficients); 00264 } 00265 00266 ////////////////////////////////////////////////////////////////////////// 00267 template <typename PointT> void 00268 pcl::SampleConsensusModelRegistration<PointT>::estimateRigidTransformationSVD ( 00269 const pcl::PointCloud<PointT> &cloud_src, 00270 const std::vector<int> &indices_src, 00271 const pcl::PointCloud<PointT> &cloud_tgt, 00272 const std::vector<int> &indices_tgt, 00273 Eigen::VectorXf &transform) 00274 { 00275 transform.resize (16); 00276 00277 Eigen::Matrix<double, 3, Eigen::Dynamic> src (3, indices_src.size ()); 00278 Eigen::Matrix<double, 3, Eigen::Dynamic> tgt (3, indices_tgt.size ()); 00279 00280 for (size_t i = 0; i < indices_src.size (); ++i) 00281 { 00282 src (0, i) = cloud_src[indices_src[i]].x; 00283 src (1, i) = cloud_src[indices_src[i]].y; 00284 src (2, i) = cloud_src[indices_src[i]].z; 00285 00286 tgt (0, i) = cloud_tgt[indices_tgt[i]].x; 00287 tgt (1, i) = cloud_tgt[indices_tgt[i]].y; 00288 tgt (2, i) = cloud_tgt[indices_tgt[i]].z; 00289 } 00290 00291 // Call Umeyama directly from Eigen 00292 Eigen::Matrix4d transformation_matrix = pcl::umeyama (src, tgt, false); 00293 00294 // Return the correct transformation 00295 transform.segment<4> (0).matrix () = transformation_matrix.cast<float> ().row (0); 00296 transform.segment<4> (4).matrix () = transformation_matrix.cast<float> ().row (1); 00297 transform.segment<4> (8).matrix () = transformation_matrix.cast<float> ().row (2); 00298 transform.segment<4> (12).matrix () = transformation_matrix.cast<float> ().row (3); 00299 } 00300 00301 #define PCL_INSTANTIATE_SampleConsensusModelRegistration(T) template class PCL_EXPORTS pcl::SampleConsensusModelRegistration<T>; 00302 00303 #endif // PCL_SAMPLE_CONSENSUS_IMPL_SAC_MODEL_REGISTRATION_H_ 00304