|
Point Cloud Library (PCL)
1.5.1
|
00001 /* 00002 * Software License Agreement (BSD License) 00003 * 00004 * Copyright (c) 2009, Willow Garage, Inc. 00005 * All rights reserved. 00006 * 00007 * Redistribution and use in source and binary forms, with or without 00008 * modification, are permitted provided that the following conditions 00009 * are met: 00010 * 00011 * * Redistributions of source code must retain the above copyright 00012 * notice, this list of conditions and the following disclaimer. 00013 * * Redistributions in binary form must reproduce the above 00014 * copyright notice, this list of conditions and the following 00015 * disclaimer in the documentation and/or other materials provided 00016 * with the distribution. 00017 * * Neither the name of Willow Garage, Inc. nor the names of its 00018 * contributors may be used to endorse or promote products derived 00019 * from this software without specific prior written permission. 00020 * 00021 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 00022 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 00023 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 00024 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 00025 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 00026 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 00027 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 00028 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 00029 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 00030 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 00031 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 00032 * POSSIBILITY OF SUCH DAMAGE. 00033 * 00034 * $Id: shot_common.hpp 4702 2012-02-23 09:39:33Z gedikli $ 00035 */ 00036 00037 #ifndef PCL_FEATURES_IMPL_SHOT_COMMON_H_ 00038 #define PCL_FEATURES_IMPL_SHOT_COMMON_H_ 00039 00040 #include <utility> 00041 00042 // Useful constants. 00043 #define PST_PI 3.1415926535897932384626433832795 00044 #define PST_RAD_45 0.78539816339744830961566084581988 00045 #define PST_RAD_90 1.5707963267948966192313216916398 00046 #define PST_RAD_135 2.3561944901923449288469825374596 00047 #define PST_RAD_180 PST_PI 00048 #define PST_RAD_360 6.283185307179586476925286766558 00049 #define PST_RAD_PI_7_8 2.7488935718910690836548129603691 00050 00051 const double zeroDoubleEps15 = 1E-15; 00052 const float zeroFloatEps8 = 1E-8f; 00053 00055 // Compute a local Reference Frame for a 3D feature; the output is stored in the "rf" vector 00056 template <typename PointInT> float 00057 pcl::getLocalRF (const pcl::PointCloud<PointInT> &cloud, 00058 const double search_radius, 00059 const Eigen::Vector4f & central_point, 00060 const std::vector<int> &indices, 00061 const std::vector<float> &dists, 00062 std::vector<Eigen::Vector4f, Eigen::aligned_allocator<Eigen::Vector4f> > &rf) 00063 { 00064 if (rf.size () != 3) 00065 rf.resize (3); 00066 00067 // Allocate enough space 00068 Eigen::Vector4d *vij = new Eigen::Vector4d[indices.size ()]; 00069 00070 Eigen::Matrix3d cov_m = Eigen::Matrix3d::Zero (); 00071 00072 double distance = 0.0; 00073 double sum = 0.0; 00074 00075 int valid_nn_points = 0; 00076 00077 for (size_t i_idx = 0; i_idx < indices.size (); ++i_idx) 00078 { 00079 /*if (indices[i_idx] == index) 00080 continue;*/ 00081 00082 Eigen::Vector4f pt = cloud.points[indices[i_idx]].getVector4fMap (); 00083 pt[3] = 0; 00084 00085 if (pt == central_point) 00086 continue; 00087 00088 // Difference between current point and origin 00089 vij[valid_nn_points] = (pt - central_point).cast<double> (); 00090 vij[valid_nn_points][3] = 0; 00091 00092 distance = search_radius - sqrt (dists[i_idx]); 00093 00094 // Multiply vij * vij' 00095 cov_m += distance * (vij[valid_nn_points].head<3> () * vij[valid_nn_points].head<3> ().transpose ()); 00096 00097 sum += distance; 00098 valid_nn_points++; 00099 } 00100 00101 if (valid_nn_points < 5) 00102 { 00103 PCL_ERROR ("[pcl::%s::getSHOTLocalRF] Warning! Neighborhood has less than 5 vertexes. Aborting Local RF computation of feature point (%lf, %lf, %lf)\n", "SHOT", central_point[0], central_point[1], central_point[2]); 00104 rf[0].setZero (); 00105 rf[1].setZero (); 00106 rf[2].setZero (); 00107 00108 rf[0][0] = 1; 00109 rf[1][1] = 1; 00110 rf[2][2] = 1; 00111 00112 delete [] vij; 00113 00114 return (std::numeric_limits<float>::max ()); 00115 } 00116 00117 cov_m /= sum; 00118 00119 Eigen::SelfAdjointEigenSolver<Eigen::Matrix3d> solver (cov_m); 00120 00121 // Disambiguation 00122 00123 Eigen::Vector3d v1c = solver.eigenvectors ().col (0); 00124 Eigen::Vector3d v2c = solver.eigenvectors ().col (1); 00125 Eigen::Vector3d v3c = solver.eigenvectors ().col (2); 00126 00127 double e1c = solver.eigenvalues ()[0]; 00128 double e2c = solver.eigenvalues ()[1]; 00129 double e3c = solver.eigenvalues ()[2]; 00130 00131 if(!pcl_isfinite(e1c) || !pcl_isfinite(e2c) || !pcl_isfinite(e3c)){ 00132 PCL_ERROR ("[pcl::%s::getSHOTLocalRF] Warning! Eigenvectors are NaN. Aborting Local RF computation of feature point (%lf, %lf, %lf)\n", "SHOT", central_point[0], central_point[1], central_point[2]); 00133 rf[0].setZero (); 00134 rf[1].setZero (); 00135 rf[2].setZero (); 00136 00137 rf[0][0] = 1; 00138 rf[1][1] = 1; 00139 rf[2][2] = 1; 00140 00141 delete [] vij; 00142 00143 return (std::numeric_limits<float>::max ()); 00144 } 00145 00146 Eigen::Vector4d v1 = Eigen::Vector4d::Zero (); 00147 Eigen::Vector4d v3 = Eigen::Vector4d::Zero (); 00148 00149 if (e1c > e2c) 00150 { 00151 if (e1c > e3c) // v1c > max(v2c,v3c) 00152 { 00153 v1.head<3> () = v1c; 00154 00155 if (e2c > e3c) // v1c > v2c > v3c 00156 v3.head<3> () = v3c; 00157 else // v1c > v3c > v2c 00158 v3.head<3> () = v2c; 00159 } 00160 else // v3c > v1c > v2c 00161 { 00162 v1.head<3> () = v3c; 00163 v3.head<3> () = v2c; 00164 } 00165 } 00166 else 00167 { 00168 if (e2c > e3c) // v2c > max(v1c,v3c) 00169 { 00170 v1.head<3> () = v2c; 00171 00172 if (e1c > e3c) // v2c > v1c > v3c 00173 v3.head<3> () = v3c; 00174 else // v2c > v3c > v1c 00175 v3.head<3> () = v1c; 00176 } 00177 else // v3c > v2c > v1c 00178 { 00179 v1.head<3> () = v3c; 00180 v3.head<3> () = v1c; 00181 } 00182 } 00183 00184 int plusNormal = 0, plusTangentDirection1=0; 00185 for (int ne = 0; ne < valid_nn_points; ne++) 00186 { 00187 double dp = vij[ne].dot (v1); 00188 if (dp >= 0) 00189 plusTangentDirection1++; 00190 00191 dp = vij[ne].dot (v3); 00192 if (dp >= 0) 00193 plusNormal++; 00194 } 00195 00196 //TANGENT 00197 if( abs ( plusTangentDirection1 - valid_nn_points + plusTangentDirection1 ) > 0 ) 00198 { 00199 if (plusTangentDirection1 < valid_nn_points - plusTangentDirection1) 00200 v1 *= - 1; 00201 } 00202 else 00203 { 00204 plusTangentDirection1=0; 00205 int points = 5; 00206 int medianIndex = valid_nn_points/2; 00207 00208 for (int i = -points/2; i <= points/2; i++) 00209 if ( vij[medianIndex- i ].dot (v1) > 0) 00210 plusTangentDirection1 ++; 00211 00212 if (plusTangentDirection1 < points/2+1) 00213 v1 *= - 1; 00214 } 00215 00216 //Normal 00217 if( abs ( plusNormal - valid_nn_points + plusNormal ) > 0 ) 00218 { 00219 if (plusNormal < valid_nn_points - plusNormal) 00220 v3 *= - 1; 00221 } 00222 else 00223 { 00224 plusNormal = 0; 00225 int points = 5; //std::min(valid_nn_points*2/2+1, 11); 00226 //std::cout << points << std::endl; 00227 int medianIndex = valid_nn_points/2; 00228 00229 for (int i = -points/2; i <= points/2; i++) 00230 if ( vij[medianIndex- i ].dot (v3) > 0) 00231 plusNormal ++; 00232 00233 if (plusNormal < points/2+1) 00234 v3 *= - 1; 00235 } 00236 00237 00238 00239 rf[0] = v1.cast<float>(); 00240 rf[2] = v3.cast<float>(); 00241 rf[1] = rf[2].cross3 (rf[0]); 00242 rf[0][3] = 0; rf[1][3] = 0; rf[2][3] = 0; 00243 00244 delete [] vij; 00245 00246 return (0.0f); 00247 } 00248 00249 #endif // PCL_FEATURES_IMPL_SHOT_COMMON_H_ 00250
1.8.0