|
Point Cloud Library (PCL)
1.4.0
|
00001 /* 00002 * Software License Agreement (BSD License) 00003 * 00004 * Copyright (c) 2010, 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: eigen.h 3746 2011-12-31 22:19:47Z rusu $ 00035 * 00036 */ 00037 // This file is part of Eigen, a lightweight C++ template library 00038 // for linear algebra. 00039 // 00040 // Copyright (C) 2010 Gael Guennebaud <gael.guennebaud@inria.fr> 00041 // 00042 // Eigen is free software; you can redistribute it and/or 00043 // modify it under the terms of the GNU Lesser General Public 00044 // License as published by the Free Software Foundation; either 00045 // version 3 of the License, or (at your option) any later version. 00046 // 00047 // Alternatively, you can redistribute it and/or 00048 // modify it under the terms of the GNU General Public License as 00049 // published by the Free Software Foundation; either version 2 of 00050 // the License, or (at your option) any later version. 00051 // 00052 // Eigen is distributed in the hope that it will be useful, but WITHOUT ANY 00053 // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 00054 // FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the 00055 // GNU General Public License for more details. 00056 // 00057 // You should have received a copy of the GNU Lesser General Public 00058 // License and a copy of the GNU General Public License along with 00059 // Eigen. If not, see <http://www.gnu.org/licenses/>. 00060 00061 // The computeRoots function included in this is based on materials 00062 // covered by the following copyright and license: 00063 // 00064 // Geometric Tools, LLC 00065 // Copyright (c) 1998-2010 00066 // Distributed under the Boost Software License, Version 1.0. 00067 // 00068 // Permission is hereby granted, free of charge, to any person or organization 00069 // obtaining a copy of the software and accompanying documentation covered by 00070 // this license (the "Software") to use, reproduce, display, distribute, 00071 // execute, and transmit the Software, and to prepare derivative works of the 00072 // Software, and to permit third-parties to whom the Software is furnished to 00073 // do so, all subject to the following: 00074 // 00075 // The copyright notices in the Software and this entire statement, including 00076 // the above license grant, this restriction and the following disclaimer, 00077 // must be included in all copies of the Software, in whole or in part, and 00078 // all derivative works of the Software, unless such copies or derivative 00079 // works are solely in the form of machine-executable object code generated by 00080 // a source language processor. 00081 // 00082 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 00083 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 00084 // FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT 00085 // SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE 00086 // FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, 00087 // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 00088 // DEALINGS IN THE SOFTWARE. 00089 00090 #ifndef PCL_EIGEN_H_ 00091 #define PCL_EIGEN_H_ 00092 00093 #define NOMINMAX 00094 00095 #include <Eigen/Core> 00096 #include <Eigen/Eigenvalues> 00097 #include <Eigen/Geometry> 00098 00099 namespace pcl 00100 { 00107 template<typename Scalar, typename Roots> inline void 00108 computeRoots2 (const Scalar& b, const Scalar& c, Roots& roots) 00109 { 00110 roots(0) = Scalar(0); 00111 Scalar d = Scalar(b * b - 4.0 * c); 00112 if (d < 0.0) // no real roots!!!! THIS SHOULD NOT HAPPEN! 00113 d = 0.0; 00114 00115 Scalar sd = sqrt (d); 00116 00117 roots (2) = 0.5f * (b + sd); 00118 roots (1) = 0.5f * (b - sd); 00119 } 00120 00126 template<typename Matrix, typename Roots> inline void 00127 computeRoots (const Matrix& m, Roots& roots) 00128 { 00129 typedef typename Matrix::Scalar Scalar; 00130 00131 // The characteristic equation is x^3 - c2*x^2 + c1*x - c0 = 0. The 00132 // eigenvalues are the roots to this equation, all guaranteed to be 00133 // real-valued, because the matrix is symmetric. 00134 Scalar c0 = m(0,0)*m(1,1)*m(2,2) 00135 + Scalar(2) * m(0,1)*m(0,2)*m(1,2) 00136 - m(0,0)*m(1,2)*m(1,2) 00137 - m(1,1)*m(0,2)*m(0,2) 00138 - m(2,2)*m(0,1)*m(0,1); 00139 Scalar c1 = m(0,0)*m(1,1) - 00140 m(0,1)*m(0,1) + 00141 m(0,0)*m(2,2) - 00142 m(0,2)*m(0,2) + 00143 m(1,1)*m(2,2) - 00144 m(1,2)*m(1,2); 00145 Scalar c2 = m(0,0) + m(1,1) + m(2,2); 00146 00147 00148 if (fabs(c0) < Eigen::NumTraits<Scalar>::epsilon())// one root is 0 -> quadratic equation 00149 computeRoots2 (c2, c1, roots); 00150 else 00151 { 00152 const Scalar s_inv3 = Scalar(1.0/3.0); 00153 const Scalar s_sqrt3 = Eigen::internal::sqrt (Scalar (3.0)); 00154 // Construct the parameters used in classifying the roots of the equation 00155 // and in solving the equation for the roots in closed form. 00156 Scalar c2_over_3 = c2*s_inv3; 00157 Scalar a_over_3 = (c1 - c2*c2_over_3)*s_inv3; 00158 if (a_over_3 > Scalar (0)) 00159 a_over_3 = Scalar (0); 00160 00161 Scalar half_b = Scalar(0.5) * (c0 + c2_over_3 * (Scalar(2) * c2_over_3 * c2_over_3 - c1)); 00162 00163 Scalar q = half_b*half_b + a_over_3*a_over_3*a_over_3; 00164 if (q > Scalar(0)) 00165 q = Scalar(0); 00166 00167 // Compute the eigenvalues by solving for the roots of the polynomial. 00168 Scalar rho = Eigen::internal::sqrt (-a_over_3); 00169 Scalar theta = std::atan2 (Eigen::internal::sqrt (-q), half_b)*s_inv3; 00170 Scalar cos_theta = Eigen::internal::cos (theta); 00171 Scalar sin_theta = Eigen::internal::sin (theta); 00172 roots(0) = c2_over_3 + Scalar(2) * rho * cos_theta; 00173 roots(1) = c2_over_3 - rho * (cos_theta + s_sqrt3 * sin_theta); 00174 roots(2) = c2_over_3 - rho * (cos_theta - s_sqrt3 * sin_theta); 00175 00176 // Sort in increasing order. 00177 if (roots (0) >= roots (1)) 00178 std::swap (roots (0), roots (1)); 00179 if (roots (1) >= roots (2)) 00180 { 00181 std::swap (roots (1), roots (2)); 00182 if (roots (0) >= roots (1)) 00183 std::swap (roots (0), roots (1)); 00184 } 00185 00186 if (roots(0) <= 0) // eigenval for symetric positive semi-definite matrix can not be negative! Set it to 0 00187 computeRoots2 (c2, c1, roots); 00188 } 00189 } 00190 00198 template<typename Matrix, typename Vector> inline void 00199 eigen33 (const Matrix& mat, typename Matrix::Scalar& eigenvalue, Vector& eigenvector) 00200 { 00201 typedef typename Matrix::Scalar Scalar; 00202 // Scale the matrix so its entries are in [-1,1]. The scaling is applied 00203 // only when at least one matrix entry has magnitude larger than 1. 00204 00205 Scalar scale = mat.cwiseAbs ().maxCoeff (); 00206 if (scale <= std::numeric_limits<Scalar>::min()) 00207 scale = Scalar(1.0); 00208 00209 Matrix scaledMat = mat / scale; 00210 Vector eigenvalues; 00211 computeRoots (scaledMat, eigenvalues); 00212 00213 eigenvalue = eigenvalues(0) * scale; 00214 00215 scaledMat.diagonal ().array () -= eigenvalues (0); 00216 00217 Vector vec1 = scaledMat.row (0).cross (scaledMat.row (1)); 00218 Vector vec2 = scaledMat.row (0).cross (scaledMat.row (2)); 00219 Vector vec3 = scaledMat.row (1).cross (scaledMat.row (2)); 00220 00221 Scalar len1 = vec1.squaredNorm(); 00222 Scalar len2 = vec2.squaredNorm(); 00223 Scalar len3 = vec3.squaredNorm(); 00224 00225 if (len1 >= len2 && len1 >= len3) 00226 eigenvector = vec1 / Eigen::internal::sqrt (len1); 00227 else if (len2 >= len1 && len2 >= len3) 00228 eigenvector = vec2 / Eigen::internal::sqrt (len2); 00229 else 00230 eigenvector = vec3 / Eigen::internal::sqrt (len3); 00231 } 00232 00238 template<typename Matrix, typename Vector> inline void 00239 eigen33 (const Matrix& mat, Vector& evals) 00240 { 00241 computeRoots (mat, evals); 00242 } 00243 00250 template<typename Matrix, typename Vector> inline void 00251 eigen33 (const Matrix& mat, Matrix& evecs, Vector& evals) 00252 { 00253 typedef typename Matrix::Scalar Scalar; 00254 // Scale the matrix so its entries are in [-1,1]. The scaling is applied 00255 // only when at least one matrix entry has magnitude larger than 1. 00256 00257 Scalar scale = mat.cwiseAbs ().maxCoeff (); 00258 if (scale <= std::numeric_limits<Scalar>::min()) 00259 scale = Scalar(1.0); 00260 00261 Matrix scaledMat = mat / scale; 00262 00263 // Compute the eigenvalues 00264 computeRoots (scaledMat,evals); 00265 00266 if((evals(2)-evals(0))<=Eigen::NumTraits<Scalar>::epsilon()) 00267 { 00268 // all three equal 00269 evecs.setIdentity(); 00270 } 00271 else if ((evals(1)-evals(0))<=Eigen::NumTraits<Scalar>::epsilon() ) 00272 { 00273 // first and second equal 00274 Matrix tmp; 00275 tmp = scaledMat; 00276 tmp.diagonal ().array () -= evals (2); 00277 00278 Vector vec1 = tmp.row (0).cross (tmp.row (1)); 00279 Vector vec2 = tmp.row (0).cross (tmp.row (2)); 00280 Vector vec3 = tmp.row (1).cross (tmp.row (2)); 00281 00282 Scalar len1 = vec1.squaredNorm(); 00283 Scalar len2 = vec2.squaredNorm(); 00284 Scalar len3 = vec3.squaredNorm(); 00285 00286 if (len1 >= len2 && len1 >= len3) 00287 evecs.col (2) = vec1 / Eigen::internal::sqrt (len1); 00288 else if (len2 >= len1 && len2 >= len3) 00289 evecs.col (2) = vec2 / Eigen::internal::sqrt (len2); 00290 else 00291 evecs.col (2) = vec3 / Eigen::internal::sqrt (len3); 00292 00293 evecs.col (1) = evecs.col (2).unitOrthogonal (); 00294 evecs.col (0) = evecs.col (1).cross (evecs.col (2)); 00295 } 00296 else if ((evals(2)-evals(1))<=Eigen::NumTraits<Scalar>::epsilon() ) 00297 { 00298 // second and third equal 00299 Matrix tmp; 00300 tmp = scaledMat; 00301 tmp.diagonal ().array () -= evals (0); 00302 00303 Vector vec1 = tmp.row (0).cross (tmp.row (1)); 00304 Vector vec2 = tmp.row (0).cross (tmp.row (2)); 00305 Vector vec3 = tmp.row (1).cross (tmp.row (2)); 00306 00307 Scalar len1 = vec1.squaredNorm(); 00308 Scalar len2 = vec2.squaredNorm(); 00309 Scalar len3 = vec3.squaredNorm(); 00310 00311 if (len1 >= len2 && len1 >= len3) 00312 evecs.col (0) = vec1 / Eigen::internal::sqrt (len1); 00313 else if (len2 >= len1 && len2 >= len3) 00314 evecs.col (0) = vec2 / Eigen::internal::sqrt (len2); 00315 else 00316 evecs.col (0) = vec3 / Eigen::internal::sqrt (len3); 00317 00318 evecs.col (1) = evecs.col (0).unitOrthogonal (); 00319 evecs.col (2) = evecs.col (0).cross (evecs.col (1)); 00320 } 00321 else 00322 { 00323 Matrix tmp; 00324 tmp = scaledMat; 00325 tmp.diagonal ().array () -= evals (2); 00326 00327 Vector vec1 = tmp.row (0).cross (tmp.row (1)); 00328 Vector vec2 = tmp.row (0).cross (tmp.row (2)); 00329 Vector vec3 = tmp.row (1).cross (tmp.row (2)); 00330 00331 Scalar len1 = vec1.squaredNorm (); 00332 Scalar len2 = vec2.squaredNorm (); 00333 Scalar len3 = vec3.squaredNorm (); 00334 #ifdef _WIN32 00335 Scalar *mmax = new Scalar[3]; 00336 #else 00337 Scalar mmax[3]; 00338 #endif 00339 unsigned int min_el = 2; 00340 unsigned int max_el = 2; 00341 if (len1 >= len2 && len1 >= len3) 00342 { 00343 mmax[2] = len1; 00344 evecs.col (2) = vec1 / Eigen::internal::sqrt (len1); 00345 } 00346 else if (len2 >= len1 && len2 >= len3) 00347 { 00348 mmax[2] = len2; 00349 evecs.col (2) = vec2 / Eigen::internal::sqrt (len2); 00350 } 00351 else 00352 { 00353 mmax[2] = len3; 00354 evecs.col (2) = vec3 / Eigen::internal::sqrt (len3); 00355 } 00356 00357 tmp = scaledMat; 00358 tmp.diagonal ().array () -= evals (1); 00359 00360 vec1 = tmp.row (0).cross (tmp.row (1)); 00361 vec2 = tmp.row (0).cross (tmp.row (2)); 00362 vec3 = tmp.row (1).cross (tmp.row (2)); 00363 00364 len1 = vec1.squaredNorm (); 00365 len2 = vec2.squaredNorm (); 00366 len3 = vec3.squaredNorm (); 00367 if (len1 >= len2 && len1 >= len3) 00368 { 00369 mmax[1] = len1; 00370 evecs.col (1) = vec1 / Eigen::internal::sqrt (len1); 00371 min_el = len1 <= mmax[min_el]? 1: min_el; 00372 max_el = len1 > mmax[max_el]? 1: max_el; 00373 } 00374 else if (len2 >= len1 && len2 >= len3) 00375 { 00376 mmax[1] = len2; 00377 evecs.col (1) = vec2 / Eigen::internal::sqrt (len2); 00378 min_el = len2 <= mmax[min_el]? 1: min_el; 00379 max_el = len2 > mmax[max_el]? 1: max_el; 00380 } 00381 else 00382 { 00383 mmax[1] = len3; 00384 evecs.col (1) = vec3 / Eigen::internal::sqrt (len3); 00385 min_el = len3 <= mmax[min_el]? 1: min_el; 00386 max_el = len3 > mmax[max_el]? 1: max_el; 00387 } 00388 00389 tmp = scaledMat; 00390 tmp.diagonal ().array () -= evals (0); 00391 00392 vec1 = tmp.row (0).cross (tmp.row (1)); 00393 vec2 = tmp.row (0).cross (tmp.row (2)); 00394 vec3 = tmp.row (1).cross (tmp.row (2)); 00395 00396 len1 = vec1.squaredNorm (); 00397 len2 = vec2.squaredNorm (); 00398 len3 = vec3.squaredNorm (); 00399 if (len1 >= len2 && len1 >= len3) 00400 { 00401 mmax[0] = len1; 00402 evecs.col (0) = vec1 / Eigen::internal::sqrt (len1); 00403 min_el = len3 <= mmax[min_el]? 0: min_el; 00404 max_el = len3 > mmax[max_el]? 0: max_el; 00405 } 00406 else if (len2 >= len1 && len2 >= len3) 00407 { 00408 mmax[0] = len2; 00409 evecs.col (0) = vec2 / Eigen::internal::sqrt (len2); 00410 min_el = len3 <= mmax[min_el]? 0: min_el; 00411 max_el = len3 > mmax[max_el]? 0: max_el; 00412 } 00413 else 00414 { 00415 mmax[0] = len3; 00416 evecs.col (0) = vec3 / Eigen::internal::sqrt (len3); 00417 min_el = len3 <= mmax[min_el]? 0: min_el; 00418 max_el = len3 > mmax[max_el]? 0: max_el; 00419 } 00420 00421 unsigned mid_el = 3 - min_el - max_el; 00422 evecs.col (min_el) = evecs.col ((min_el+1)%3).cross ( evecs.col ((min_el+2)%3) ).normalized (); 00423 evecs.col (mid_el) = evecs.col ((mid_el+1)%3).cross ( evecs.col ((mid_el+2)%3) ).normalized (); 00424 #ifdef _WIN32 00425 delete [] mmax; 00426 #endif 00427 } 00428 // Rescale back to the original size. 00429 evals *= scale; 00430 } 00431 00432 00440 template<typename Matrix> inline typename Matrix::Scalar 00441 invert3x3SymMatrix (const Matrix& matrix, Matrix& inverse) 00442 { 00443 typedef typename Matrix::Scalar Scalar; 00444 // elements 00445 // a b c 00446 // b d e 00447 // c e f 00448 00449 Scalar df_ee = matrix (1, 1) * matrix (2, 2) - matrix (1, 2) * matrix (1, 2); 00450 Scalar ce_bf = matrix (0, 2) * matrix (1, 2) - matrix (0, 1) * matrix (2, 2); 00451 Scalar be_cd = matrix (0, 1) * matrix (1, 2) - matrix (0, 2) * matrix (1, 1); 00452 00453 Scalar det = matrix (0, 0) * df_ee + matrix (0, 1) * ce_bf + matrix (0, 2) * be_cd; 00454 00455 if (det != 0) 00456 { 00457 Scalar inv_det = Scalar(1.0) / det; 00458 inverse (0, 0) = df_ee * inv_det; 00459 inverse (0, 1) = ce_bf * inv_det; 00460 inverse (0, 2) = be_cd * inv_det; 00461 inverse (1, 1) = (matrix (0, 0) * matrix (2, 2) - matrix (0, 2) * matrix (0, 2)) * inv_det; 00462 inverse (1, 2) = (matrix (0, 1) * matrix (0, 2) - matrix (0, 0) * matrix (1, 2)) * inv_det; 00463 inverse (2, 2) = (matrix (0, 0) * matrix (1, 1) - matrix (0, 1) * matrix (0, 1)) * inv_det; 00464 } 00465 return det; 00466 } 00467 00475 inline void 00476 getTransFromUnitVectorsZY (const Eigen::Vector3f& z_axis, const Eigen::Vector3f& y_direction, 00477 Eigen::Affine3f& transformation); 00478 00486 inline Eigen::Affine3f 00487 getTransFromUnitVectorsZY (const Eigen::Vector3f& z_axis, const Eigen::Vector3f& y_direction); 00488 00496 inline void 00497 getTransFromUnitVectorsXY (const Eigen::Vector3f& x_axis, const Eigen::Vector3f& y_direction, 00498 Eigen::Affine3f& transformation); 00499 00507 inline Eigen::Affine3f 00508 getTransFromUnitVectorsXY (const Eigen::Vector3f& x_axis, const Eigen::Vector3f& y_direction); 00509 00517 inline void 00518 getTransformationFromTwoUnitVectors (const Eigen::Vector3f& y_direction, const Eigen::Vector3f& z_axis, 00519 Eigen::Affine3f& transformation); 00520 00528 inline Eigen::Affine3f 00529 getTransformationFromTwoUnitVectors (const Eigen::Vector3f& y_direction, const Eigen::Vector3f& z_axis); 00530 00539 inline void 00540 getTransformationFromTwoUnitVectorsAndOrigin (const Eigen::Vector3f& y_direction, const Eigen::Vector3f& z_axis, 00541 const Eigen::Vector3f& origin, Eigen::Affine3f& transformation); 00542 00550 inline void 00551 getEulerAngles (const Eigen::Affine3f& t, float& roll, float& pitch, float& yaw); 00552 00563 inline void 00564 getTranslationAndEulerAngles (const Eigen::Affine3f& t, float& x, float& y, float& z, 00565 float& roll, float& pitch, float& yaw); 00566 00577 inline void 00578 getTransformation (float x, float y, float z, float roll, float pitch, float yaw, Eigen::Affine3f& t); 00579 00590 inline Eigen::Affine3f 00591 getTransformation (float x, float y, float z, float roll, float pitch, float yaw); 00592 00598 template <typename Derived> void 00599 saveBinary (const Eigen::MatrixBase<Derived>& matrix, std::ostream& file); 00600 00606 template <typename Derived> void 00607 loadBinary (Eigen::MatrixBase<Derived>& matrix, std::istream& file); 00608 } 00609 00610 #include "pcl/common/impl/eigen.hpp" 00611 00612 #endif //#ifndef PCL_EIGEN_H_
1.7.6.1