Point Cloud Library (PCL)  1.4.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
eigen.h
Go to the documentation of this file.
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_
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines