test_eigen.cpp
Go to the documentation of this file.
00001 /*
00002  * Software License Agreement (BSD License)
00003  *
00004  *  Point Cloud Library (PCL) - www.pointclouds.org
00005  *  Copyright (c) 2010-2012, 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  * $Id: test_feature.cpp 3564 2011-12-16 06:11:13Z rusu $
00037  *
00038  */
00039 
00040 #include <gtest/gtest.h>
00041 #include <boost/random.hpp>
00042 #include <boost/random/variate_generator.hpp>
00043 #include <pcl/point_types.h>
00044 #include <pcl/common/eigen.h>
00045 
00046 using namespace pcl;
00047 using namespace std;
00048 
00049 boost::variate_generator< boost::mt19937, boost::uniform_real<double> > rand_double(boost::mt19937 (), boost::uniform_real<double> (0, 1));
00050 boost::variate_generator< boost::mt19937, boost::uniform_int<unsigned> > rand_uint(boost::mt19937 (), boost::uniform_int<unsigned> (0, 100));
00051 
00053 TEST (PCL, InverseGeneral3x3f)
00054 {
00055   typedef float Scalar;
00056   typedef Eigen::Matrix<Scalar, 3, 3, Eigen::RowMajor> RMatrix;
00057   typedef Eigen::Matrix<Scalar, 3, 3, Eigen::ColMajor> CMatrix;
00058   RMatrix r_matrix = RMatrix::Zero ();
00059   RMatrix r_inverse = RMatrix::Zero ();
00060   CMatrix c_matrix = CMatrix::Zero ();
00061   CMatrix c_inverse = CMatrix::Zero ();
00062   Eigen::Matrix<Scalar, 3, 3> result = Eigen::Matrix<Scalar, 3, 3>::Zero ();
00063   Eigen::Matrix<Scalar, 3, 3> error = Eigen::Matrix<Scalar, 3, 3>::Zero ();
00064   Scalar determinant;
00065   const Scalar epsilon = 1e-5f;
00066   const unsigned iterations = 1000000;
00067 
00068   // test floating point row-major : row-major
00069   for (unsigned idx = 0; idx < iterations; ++idx)
00070   {
00071     for (unsigned elIdx = 0; elIdx < 9; ++elIdx)
00072       r_matrix.coeffRef (elIdx) = Scalar(rand_double ());
00073 
00074     c_matrix = r_matrix;
00075 
00076     // test row-major -> row-major
00077     determinant = invert3x3Matrix (r_matrix, r_inverse);
00078     if (fabs (determinant) > epsilon)
00079     {
00080       float eps = std::max (epsilon, epsilon / fabs(determinant));
00081 
00082       result = r_inverse * r_matrix;
00083       error = result - Eigen::Matrix<Scalar, 3, 3>::Identity ();
00084       Scalar distance = error.cwiseAbs ().sum ();
00085       EXPECT_LE (distance, eps);
00086 
00087       result = r_matrix * r_inverse;
00088       error = result - Eigen::Matrix<Scalar, 3, 3>::Identity ();
00089       distance = error.cwiseAbs ().sum ();
00090       EXPECT_LE (distance, eps);
00091     }
00092 
00093     // test row-major -> col-major
00094     determinant = invert3x3Matrix (c_matrix, c_inverse);
00095     if (fabs (determinant) > epsilon)
00096     {
00097       Scalar eps = std::max (epsilon, epsilon / fabs(determinant));
00098 
00099       result = c_inverse * c_matrix;
00100       error = result - Eigen::Matrix<Scalar, 3, 3>::Identity ();
00101       Scalar distance = error.cwiseAbs ().sum ();
00102       EXPECT_LE (distance, eps);
00103 
00104       result = c_matrix * c_inverse;
00105       error = result - Eigen::Matrix<Scalar, 3, 3>::Identity ();
00106       distance = error.cwiseAbs ().sum ();
00107       EXPECT_LE (distance, eps);
00108     }
00109   }
00110 }
00111 
00113 TEST (PCL, InverseGeneral3x3d)
00114 {
00115   typedef double Scalar;
00116   typedef Eigen::Matrix<Scalar, 3, 3, Eigen::RowMajor> RMatrix;
00117   typedef Eigen::Matrix<Scalar, 3, 3, Eigen::ColMajor> CMatrix;
00118   RMatrix r_matrix = RMatrix::Zero ();
00119   RMatrix r_inverse = RMatrix::Zero ();
00120   CMatrix c_matrix = CMatrix::Zero ();
00121   CMatrix c_inverse = CMatrix::Zero ();
00122   Eigen::Matrix<Scalar, 3, 3> result = Eigen::Matrix<Scalar, 3, 3>::Zero ();
00123   Eigen::Matrix<Scalar, 3, 3> error = Eigen::Matrix<Scalar, 3, 3>::Zero ();
00124   Scalar determinant;
00125   const Scalar epsilon = 1e-13;
00126   const unsigned iterations = 1000000;
00127 
00128   // test floating point row-major : row-major
00129   for (unsigned idx = 0; idx < iterations; ++idx)
00130   {
00131     for (unsigned elIdx = 0; elIdx < 9; ++elIdx)
00132     {
00133       r_matrix.coeffRef (elIdx) = Scalar(rand_double ());
00134     }
00135     c_matrix = r_matrix;
00136     // test row-major -> row-major
00137     determinant = invert3x3Matrix (r_matrix, r_inverse);
00138     if (fabs (determinant) > epsilon)
00139     {
00140       Scalar eps = std::max (epsilon, epsilon / fabs (determinant));
00141 
00142       result = r_inverse * r_matrix;
00143       error = result - Eigen::Matrix<Scalar, 3, 3>::Identity ();
00144       Scalar distance = error.cwiseAbs ().sum ();
00145       EXPECT_LE (distance, eps);
00146 
00147       result = r_matrix * r_inverse;
00148       error = result - Eigen::Matrix<Scalar, 3, 3>::Identity ();
00149       distance = error.cwiseAbs ().sum ();
00150       EXPECT_LE (distance, eps);
00151     }
00152 
00153     // test row-major -> col-major
00154     determinant = invert3x3Matrix (c_matrix, c_inverse);
00155     if (fabs (determinant) > epsilon)
00156     {
00157       Scalar eps = std::max (epsilon, epsilon / fabs(determinant));
00158 
00159       result = c_inverse * c_matrix;
00160       error = result - Eigen::Matrix<Scalar, 3, 3>::Identity ();
00161       Scalar distance = error.cwiseAbs ().sum ();
00162       EXPECT_LE (distance, eps);
00163 
00164       result = c_matrix * c_inverse;
00165       error = result - Eigen::Matrix<Scalar, 3, 3>::Identity ();
00166       distance = error.cwiseAbs ().sum ();
00167       EXPECT_LE (distance, eps);
00168     }
00169   }
00170 }
00171 
00173 TEST (PCL, InverseSymmetric3x3f)
00174 {
00175   typedef float Scalar;
00176   typedef Eigen::Matrix<Scalar, 3, 3, Eigen::RowMajor> RMatrix;
00177   typedef Eigen::Matrix<Scalar, 3, 3, Eigen::ColMajor> CMatrix;
00178   RMatrix r_matrix = RMatrix::Zero ();
00179   RMatrix r_inverse = RMatrix::Zero ();
00180   CMatrix c_matrix = CMatrix::Zero ();
00181   CMatrix c_inverse = CMatrix::Zero ();
00182   Eigen::Matrix<Scalar, 3, 3> result = Eigen::Matrix<Scalar, 3, 3>::Zero ();
00183   Eigen::Matrix<Scalar, 3, 3> error = Eigen::Matrix<Scalar, 3, 3>::Zero ();
00184   Scalar determinant;
00185   const Scalar epsilon = 1e-5f;
00186   const unsigned iterations = 1000000;
00187 
00188   // test floating point row-major : row-major
00189   for (unsigned idx = 0; idx < iterations; ++idx)
00190   {
00191     for (unsigned elIdx = 0; elIdx < 9; ++elIdx)
00192       r_matrix.coeffRef (elIdx) = Scalar(rand_double ());
00193 
00194     r_matrix.coeffRef (3) = r_matrix.coeffRef (1);
00195     r_matrix.coeffRef (6) = r_matrix.coeffRef (2);
00196     r_matrix.coeffRef (7) = r_matrix.coeffRef (5);
00197     c_matrix = r_matrix;
00198 //    c_matrix.coeffRef (3) = c_matrix.coeffRef (1);
00199 //    c_matrix.coeffRef (6) = c_matrix.coeffRef (2);
00200 //    c_matrix.coeffRef (7) = c_matrix.coeffRef (5);
00201 
00202     // test row-major -> row-major
00203     determinant = invert3x3SymMatrix (r_matrix, r_inverse);
00204     if (fabs (determinant) > epsilon)
00205     {
00206       float eps = std::max (epsilon, epsilon / fabs(determinant));
00207 
00208       result = r_inverse * r_matrix;
00209       error = result - Eigen::Matrix<Scalar, 3, 3>::Identity ();
00210       Scalar distance = error.cwiseAbs ().sum ();
00211       EXPECT_LE (distance, eps);
00212 
00213       result = r_matrix * r_inverse;
00214       error = result - Eigen::Matrix<Scalar, 3, 3>::Identity ();
00215       distance = error.cwiseAbs ().sum ();
00216       EXPECT_LE (distance, eps);
00217     }
00218 
00219     // test row-major -> col-major
00220     determinant = invert3x3SymMatrix (c_matrix, c_inverse);
00221     if (fabs (determinant) > epsilon)
00222     {
00223       Scalar eps = std::max (epsilon, epsilon / fabs(determinant));
00224 
00225       result = c_inverse * c_matrix;
00226       error = result - Eigen::Matrix<Scalar, 3, 3>::Identity ();
00227       Scalar distance = error.cwiseAbs ().sum ();
00228       EXPECT_LE (distance, eps);
00229 
00230       result = c_matrix * c_inverse;
00231       error = result - Eigen::Matrix<Scalar, 3, 3>::Identity ();
00232       distance = error.cwiseAbs ().sum ();
00233       EXPECT_LE (distance, eps);
00234     }
00235   }
00236 }
00237 
00239 TEST (PCL, InverseSymmetric3x3d)
00240 {
00241   typedef double Scalar;
00242   typedef Eigen::Matrix<Scalar, 3, 3, Eigen::RowMajor> RMatrix;
00243   typedef Eigen::Matrix<Scalar, 3, 3, Eigen::ColMajor> CMatrix;
00244   RMatrix r_matrix = RMatrix::Zero ();
00245   RMatrix r_inverse = RMatrix::Zero ();
00246   CMatrix c_matrix = CMatrix::Zero ();
00247   CMatrix c_inverse = CMatrix::Zero ();
00248   Eigen::Matrix<Scalar, 3, 3> result = Eigen::Matrix<Scalar, 3, 3>::Zero ();
00249   Eigen::Matrix<Scalar, 3, 3> error = Eigen::Matrix<Scalar, 3, 3>::Zero ();
00250   Scalar determinant;
00251   const Scalar epsilon = 1e-13;
00252   const unsigned iterations = 1000000;
00253 
00254   // test floating point row-major : row-major
00255   for (unsigned idx = 0; idx < iterations; ++idx)
00256   {
00257     for (unsigned elIdx = 0; elIdx < 9; ++elIdx)
00258       r_matrix.coeffRef (elIdx) = Scalar(rand_double ());
00259 
00260     r_matrix.coeffRef (3) = r_matrix.coeffRef (1);
00261     r_matrix.coeffRef (6) = r_matrix.coeffRef (2);
00262     r_matrix.coeffRef (7) = r_matrix.coeffRef (5);
00263     c_matrix = r_matrix;
00264 //    c_matrix.coeffRef (3) = c_matrix.coeffRef (1);
00265 //    c_matrix.coeffRef (6) = c_matrix.coeffRef (2);
00266 //    c_matrix.coeffRef (7) = c_matrix.coeffRef (5);
00267 
00268     // test row-major -> row-major
00269     determinant = invert3x3SymMatrix (r_matrix, r_inverse);
00270     if (fabs (determinant) > epsilon)
00271     {
00272       Scalar eps = std::max (epsilon, epsilon / fabs (determinant));
00273 
00274       result = r_inverse * r_matrix;
00275       error = result - Eigen::Matrix<Scalar, 3, 3>::Identity ();
00276       Scalar distance = error.cwiseAbs ().sum ();
00277       EXPECT_LE (distance, eps);
00278 
00279       result = r_matrix * r_inverse;
00280       error = result - Eigen::Matrix<Scalar, 3, 3>::Identity ();
00281       distance = error.cwiseAbs ().sum ();
00282       EXPECT_LE (distance, eps);
00283     }
00284 
00285     // test row-major -> col-major
00286     determinant = invert3x3SymMatrix (c_matrix, c_inverse);
00287     if (fabs (determinant) > epsilon)
00288     {
00289       Scalar eps = std::max (epsilon, epsilon / fabs(determinant));
00290 
00291       result = c_inverse * c_matrix;
00292       error = result - Eigen::Matrix<Scalar, 3, 3>::Identity ();
00293       Scalar distance = error.cwiseAbs ().sum ();
00294       EXPECT_LE (distance, eps);
00295 
00296       result = c_matrix * c_inverse;
00297       error = result - Eigen::Matrix<Scalar, 3, 3>::Identity ();
00298       distance = error.cwiseAbs ().sum ();
00299       EXPECT_LE (distance, eps);
00300     }
00301   }
00302 }
00303 
00304 
00306 TEST (PCL, Inverse2x2f)
00307 {
00308   typedef float Scalar;
00309   typedef Eigen::Matrix<Scalar, 2, 2, Eigen::RowMajor> RMatrix;
00310   typedef Eigen::Matrix<Scalar, 2, 2, Eigen::ColMajor> CMatrix;
00311   RMatrix r_matrix = RMatrix::Zero ();
00312   RMatrix r_inverse = RMatrix::Zero ();
00313   CMatrix c_matrix = CMatrix::Zero ();
00314   CMatrix c_inverse = CMatrix::Zero ();
00315   Eigen::Matrix<Scalar, 2, 2> result = Eigen::Matrix<Scalar, 2, 2>::Zero ();
00316   Eigen::Matrix<Scalar, 2, 2> error = Eigen::Matrix<Scalar, 2, 2>::Zero ();
00317   Scalar determinant;
00318   const Scalar epsilon = 1e-6f;
00319   const unsigned iterations = 1000000;
00320 
00321   // test floating point row-major : row-major
00322   for (unsigned idx = 0; idx < iterations; ++idx)
00323   {
00324     for (unsigned elIdx = 0; elIdx < 4; ++elIdx)
00325       r_matrix.coeffRef (elIdx) = Scalar(rand_double ());
00326 
00327     c_matrix = r_matrix;
00328     // test row-major -> row-major
00329     determinant = invert2x2 (r_matrix, r_inverse);
00330     if (fabs (determinant) > epsilon)
00331     {
00332       float eps = std::max (epsilon, epsilon / fabs(determinant));
00333 
00334       result = r_inverse * r_matrix;
00335       error = result - Eigen::Matrix<Scalar, 2, 2>::Identity ();
00336       Scalar distance = error.cwiseAbs ().sum ();
00337       EXPECT_LE (distance, eps);
00338 
00339       result = r_matrix * r_inverse;
00340       error = result - Eigen::Matrix<Scalar, 2, 2>::Identity ();
00341       distance = error.cwiseAbs ().sum ();
00342       EXPECT_LE (distance, eps);
00343     }
00344 
00345     // test row-major -> col-major
00346     determinant = invert2x2 (c_matrix, c_inverse);
00347     if (fabs (determinant) > epsilon)
00348     {
00349       Scalar eps = std::max (epsilon, epsilon / fabs(determinant));
00350 
00351       result = c_inverse * c_matrix;
00352       error = result - Eigen::Matrix<Scalar, 2, 2>::Identity ();
00353       Scalar distance = error.cwiseAbs ().sum ();
00354       EXPECT_LE (distance, eps);
00355 
00356       result = c_matrix * c_inverse;
00357       error = result - Eigen::Matrix<Scalar, 2, 2>::Identity ();
00358       distance = error.cwiseAbs ().sum ();
00359       EXPECT_LE (distance, eps);
00360     }
00361   }
00362 }
00363 
00365 TEST (PCL, Inverse2x2d)
00366 {
00367   typedef double Scalar;
00368   typedef Eigen::Matrix<Scalar, 2, 2, Eigen::RowMajor> RMatrix;
00369   typedef Eigen::Matrix<Scalar, 2, 2, Eigen::ColMajor> CMatrix;
00370   RMatrix r_matrix = RMatrix::Zero ();
00371   RMatrix r_inverse = RMatrix::Zero ();
00372   CMatrix c_matrix = CMatrix::Zero ();
00373   CMatrix c_inverse = CMatrix::Zero ();
00374   Eigen::Matrix<Scalar, 2, 2> result;
00375   Eigen::Matrix<Scalar, 2, 2> error;
00376   Scalar determinant;
00377   const Scalar epsilon = 1e-15;
00378   const unsigned iterations = 1000000;
00379 
00380   // test floating point row-major : row-major
00381   for (unsigned idx = 0; idx < iterations; ++idx)
00382   {
00383     for (unsigned elIdx = 0; elIdx < 4; ++elIdx)
00384       r_matrix.coeffRef (elIdx) = Scalar(rand_double ());
00385 
00386     c_matrix = r_matrix;
00387     // test row-major -> row-major
00388     determinant = invert2x2 (r_matrix, r_inverse);
00389     if (fabs (determinant) > epsilon)
00390     {
00391       Scalar eps = std::max (epsilon, epsilon / fabs (determinant));
00392 
00393       result = r_inverse * r_matrix;
00394       error = result - Eigen::Matrix<Scalar, 2, 2>::Identity ();
00395       Scalar distance = error.cwiseAbs ().sum ();
00396       EXPECT_LE (distance, eps);
00397 
00398       result = r_matrix * r_inverse;
00399       error = result - Eigen::Matrix<Scalar, 2, 2>::Identity ();
00400       distance = error.cwiseAbs ().sum ();
00401       EXPECT_LE (distance, eps);
00402     }
00403 
00404     // test row-major -> col-major
00405     determinant = invert2x2 (c_matrix, c_inverse);
00406     if (fabs (determinant) > epsilon)
00407     {
00408       Scalar eps = std::max (epsilon, epsilon / fabs(determinant));
00409 
00410       result = c_inverse * c_matrix;
00411       error = result - Eigen::Matrix<Scalar, 2, 2>::Identity ();
00412       Scalar distance = error.cwiseAbs ().sum ();
00413       EXPECT_LE (distance, eps);
00414 
00415       result = c_matrix * c_inverse;
00416       error = result - Eigen::Matrix<Scalar, 2, 2>::Identity ();
00417       distance = error.cwiseAbs ().sum ();
00418       EXPECT_LE (distance, eps);
00419     }
00420   }
00421 }
00422 
00423 template<class Matrix>
00424 inline void generateSymPosMatrix2x2 (Matrix& matrix)
00425 {
00426   typedef typename Matrix::Scalar Scalar;
00427 
00428   unsigned test_case = rand_uint () % 10;
00429 
00430         Scalar val1 = Scalar (rand_double ());
00431         Scalar val2 = Scalar (rand_double ());
00432 
00433   // 10% of test cases include equal eigenvalues
00434   if (test_case == 0)
00435     val2 = val1;
00436   // another 20% includes one zero eigenvalue
00437   else if (test_case == 1 && val1 != 0)
00438     val2 = 0.0;
00439   else if (test_case == 2 && val2 != 0)
00440     val1 = 0.0;
00441 
00442   Scalar sqrNorm;
00443   Matrix eigenvectors = Matrix::Identity ();
00444   Matrix eigenvalues = Matrix::Zero ();
00445 
00446   unsigned test_case2 = rand_uint () % 10;
00447   if (test_case2 != 0)
00448   {
00449     do
00450     {
00451       eigenvectors.col (0)[0] = Scalar (rand_double ());
00452       eigenvectors.col (0)[1] = Scalar (rand_double ());
00453       sqrNorm = eigenvectors.col (0).squaredNorm ();
00454     } while (sqrNorm == 0);
00455     eigenvectors.col (0) /= sqrt (sqrNorm);
00456 
00457     eigenvectors.col (1)[0] = -eigenvectors.col (1)[1];
00458     eigenvectors.col (1)[1] =  eigenvectors.col (1)[0];
00459   }
00460   eigenvalues (0, 0) = val1;
00461   eigenvalues (1, 1) = val2;
00462         matrix = eigenvectors * eigenvalues * eigenvectors.adjoint();
00463 }
00464 
00466 TEST (PCL, eigen22d)
00467 {
00468   typedef double Scalar;
00469   typedef Eigen::Matrix<Scalar, 2, 2, Eigen::RowMajor> RMatrix;
00470   typedef Eigen::Matrix<Scalar, 2, 2, Eigen::ColMajor> CMatrix;
00471   RMatrix r_matrix;
00472   RMatrix r_vectors;
00473   Eigen::Matrix<Scalar, 2, 1> r_eigenvalues;
00474   Eigen::Matrix<Scalar, 2, 1> c_eigenvalues;
00475   CMatrix c_matrix;
00476   CMatrix c_vectors;
00477   Eigen::Matrix<Scalar, 2, 2> r_result;
00478   Eigen::Matrix<Scalar, 2, 2> r_error;
00479   Eigen::Matrix<Scalar, 2, 2> g_result;
00480   Eigen::Matrix<Scalar, 2, 2> g_error;
00481   Eigen::Matrix<Scalar, 2, 2> c_result;
00482   Eigen::Matrix<Scalar, 2, 2> c_error;
00483   Scalar diff;
00484 
00485   const Scalar epsilon = 1.25e-14;
00486   const unsigned iterations = 1000000;
00487 
00488   // test floating point row-major : row-major
00489   for (unsigned idx = 0; idx < iterations; ++idx)
00490   {
00491     // generate test matrices
00492     generateSymPosMatrix2x2 (r_matrix);
00493     c_matrix = r_matrix;
00494 
00495     // calculate the eigenvalue decomposition
00496     eigen22 (r_matrix, r_vectors, r_eigenvalues);
00497 
00498     // test if U * V * U^T = M
00499     r_result = r_vectors * r_eigenvalues.asDiagonal () * r_vectors.transpose ();
00500     r_error = r_result - r_matrix;
00501     diff = r_error.cwiseAbs (). sum ();
00502     EXPECT_LE (diff, epsilon);
00503 
00504     // test if the eigenvalues are orthonormal
00505     g_result = r_vectors * r_vectors.transpose ();
00506     g_error = g_result - RMatrix::Identity ();
00507     diff = g_error.cwiseAbs (). sum ();
00508     EXPECT_LE (diff, epsilon);
00509 
00510     // test if column major matrices are also calculated correctly
00511     eigen22 (c_matrix, c_vectors, c_eigenvalues);
00512     c_result = c_vectors * c_eigenvalues.asDiagonal () * c_vectors.transpose ();
00513     c_error = c_result - c_matrix;
00514     diff = c_error.cwiseAbs (). sum ();
00515     EXPECT_LE (diff, epsilon);
00516 
00517     g_result = c_vectors * c_vectors.transpose ();
00518     g_error = g_result - CMatrix::Identity ();
00519     diff = g_error.cwiseAbs (). sum ();
00520     EXPECT_LE (diff, epsilon);
00521   }
00522 }
00523 
00525 TEST (PCL, eigen22f)
00526 {
00527   typedef float Scalar;
00528   typedef Eigen::Matrix<Scalar, 2, 2, Eigen::RowMajor> RMatrix;
00529   typedef Eigen::Matrix<Scalar, 2, 2, Eigen::ColMajor> CMatrix;
00530   RMatrix r_matrix;
00531   RMatrix r_vectors;
00532   Eigen::Matrix<Scalar, 2, 1> r_eigenvalues;
00533   Eigen::Matrix<Scalar, 2, 1> c_eigenvalues;
00534   CMatrix c_matrix;
00535   CMatrix c_vectors;
00536   Eigen::Matrix<Scalar, 2, 2> r_result;
00537   Eigen::Matrix<Scalar, 2, 2> r_error;
00538   Eigen::Matrix<Scalar, 2, 2> g_result;
00539   Eigen::Matrix<Scalar, 2, 2> g_error;
00540   Eigen::Matrix<Scalar, 2, 2> c_result;
00541   Eigen::Matrix<Scalar, 2, 2> c_error;
00542   Scalar diff;
00543 
00544   const Scalar epsilon = 3.1e-5f;
00545   const unsigned iterations = 1000000;
00546 
00547   // test floating point row-major : row-major
00548   for (unsigned idx = 0; idx < iterations; ++idx)
00549   {
00550     // generate test matrices
00551     generateSymPosMatrix2x2 (r_matrix);
00552     c_matrix = r_matrix;
00553 
00554     // calculate the eigenvalue decomposition
00555     eigen22 (r_matrix, r_vectors, r_eigenvalues);
00556 
00557     // test if U * V * U^T = M
00558     r_result = r_vectors * r_eigenvalues.asDiagonal () * r_vectors.transpose ();
00559     r_error = r_result - r_matrix;
00560     diff = r_error.cwiseAbs (). sum ();
00561     EXPECT_LE (diff, epsilon);
00562 
00563     // test if the eigenvalues are orthonormal
00564     g_result = r_vectors * r_vectors.transpose ();
00565     g_error = g_result - RMatrix::Identity ();
00566     diff = g_error.cwiseAbs (). sum ();
00567     EXPECT_LE (diff, epsilon);
00568 
00569     // test if column major matrices are also calculated correctly
00570     eigen22 (c_matrix, c_vectors, c_eigenvalues);
00571     c_result = c_vectors * c_eigenvalues.asDiagonal () * c_vectors.transpose ();
00572     c_error = c_result - c_matrix;
00573     diff = c_error.cwiseAbs (). sum ();
00574     EXPECT_LE (diff, epsilon);
00575 
00576     g_result = c_vectors * c_vectors.transpose ();
00577     g_error = g_result - CMatrix::Identity ();
00578     diff = g_error.cwiseAbs (). sum ();
00579     EXPECT_LE (diff, epsilon);
00580   }
00581 }
00582 
00584 
00585 template<class Matrix>
00586 inline void generateSymPosMatrix3x3 (Matrix& matrix)
00587 {
00588   typedef typename Matrix::Scalar Scalar;
00589 
00590   // 3 equal elements != 0
00591   // 2 equal elements none 0
00592   // 2 equal elements 1 0
00593   // 2 x 0 and 1x non 0
00594   // 1 x 0
00595   // anything
00596 
00597   unsigned test_case = rand_uint ();
00598 
00599         Scalar val1 = Scalar (rand_double ());
00600         Scalar val2 = Scalar (rand_double ());
00601         Scalar val3 = Scalar (rand_double ());
00602 
00603   // 1%: all three values are equal and non-zero
00604   if (test_case == 0)
00605   {
00606     if (val1 ==0)
00607       val1 = 1.0;
00608     val2 = val1;
00609     val3 = val1;
00610   }
00611   // 1%: 2 values are equal but none is set explicitely to 0
00612   else if (test_case == 1)
00613   {
00614     val2 = val3;
00615   }
00616   // 1%: 2 values equal and the third = 0
00617   else if (test_case == 2)
00618   {
00619     if (val1 == 0)
00620       val1 = 1.0;
00621     val2 = val1;
00622     val3 = 0.0;
00623   }
00624   // 1% 2 x 0 and 1x not-0
00625   else if (test_case == 3)
00626   {
00627     if (val1 == 0)
00628       val1 = 1.0;
00629     val2 = val3 = 0.0;
00630   }
00631   else if (test_case == 4)
00632   {
00633     val1 = 0.0;
00634   }
00635 
00636   Scalar sqrNorm;
00637   Matrix eigenvectors = Matrix::Zero ();
00638   Matrix eigenvalues = Matrix::Zero ();
00639 
00640   do
00641   {
00642     eigenvectors.col (0)[0] = Scalar (rand_double ());
00643     eigenvectors.col (0)[1] = Scalar (rand_double ());
00644     eigenvectors.col (0)[2] = Scalar (rand_double ());
00645     eigenvectors.col (1)[0] = Scalar (rand_double ());
00646     eigenvectors.col (1)[1] = Scalar (rand_double ());
00647     eigenvectors.col (1)[2] = Scalar (rand_double ());
00648     eigenvectors.col (2) = eigenvectors.col (0).cross (eigenvectors.col (1));
00649 
00650     sqrNorm = eigenvectors.col (2).squaredNorm ();
00651   } while (sqrNorm == 0);
00652 
00653   eigenvectors.col (0).normalize ();
00654   eigenvectors.col (2).normalize ();
00655   eigenvectors.col (1) = eigenvectors.col (2).cross (eigenvectors.col (0));
00656 
00657   eigenvalues (0, 0) = val1;
00658   eigenvalues (1, 1) = val2;
00659   eigenvalues (2, 2) = val3;
00660 
00661         matrix = eigenvectors * eigenvalues * eigenvectors.adjoint();
00662 }
00663 
00665 TEST (PCL, eigen33d)
00666 {
00667   typedef double Scalar;
00668   typedef Eigen::Matrix<Scalar, 3, 3, Eigen::RowMajor> RMatrix;
00669   typedef Eigen::Matrix<Scalar, 3, 3, Eigen::ColMajor> CMatrix;
00670   RMatrix r_matrix;
00671   RMatrix r_vectors;
00672   Eigen::Matrix<Scalar, 3, 1> r_eigenvalues;
00673   Eigen::Matrix<Scalar, 3, 1> c_eigenvalues;
00674   CMatrix c_matrix;
00675   CMatrix c_vectors;
00676   Eigen::Matrix<Scalar, 3, 3> r_result;
00677   Eigen::Matrix<Scalar, 3, 3> r_error;
00678   Eigen::Matrix<Scalar, 3, 3> g_result;
00679   Eigen::Matrix<Scalar, 3, 3> g_error;
00680   Eigen::Matrix<Scalar, 3, 3> c_result;
00681   Eigen::Matrix<Scalar, 3, 3> c_error;
00682   Scalar diff;
00683 
00684   const Scalar epsilon = 2e-5;
00685   const unsigned iterations = 1000000;
00686 
00687   // test floating point row-major : row-major
00688   for (unsigned idx = 0; idx < iterations; ++idx)
00689   {
00690     // generate test matrices
00691     generateSymPosMatrix3x3 (r_matrix);
00692     c_matrix = r_matrix;
00693 
00694     // calculate the eigenvalue decomposition
00695     eigen33 (r_matrix, r_vectors, r_eigenvalues);
00696 
00697     // test if U * V * U^T = M
00698     r_result = r_vectors * r_eigenvalues.asDiagonal () * r_vectors.transpose ();
00699     r_error = r_result - r_matrix;
00700     diff = r_error.cwiseAbs (). sum ();
00701     EXPECT_LE (diff, epsilon);
00702 
00703     // test if the eigenvalues are orthonormal
00704     g_result = r_vectors * r_vectors.transpose ();
00705     g_error = g_result - RMatrix::Identity ();
00706     diff = g_error.cwiseAbs (). sum ();
00707     EXPECT_LE (diff, epsilon);
00708 
00709     // test if column major matrices are also calculated correctly
00710     eigen33 (c_matrix, c_vectors, c_eigenvalues);
00711     c_result = c_vectors * c_eigenvalues.asDiagonal () * c_vectors.transpose ();
00712     c_error = c_result - c_matrix;
00713     diff = c_error.cwiseAbs (). sum ();
00714     EXPECT_LE (diff, epsilon);
00715 
00716     g_result = c_vectors * c_vectors.transpose ();
00717     g_error = g_result - CMatrix::Identity ();
00718     diff = g_error.cwiseAbs (). sum ();
00719     EXPECT_LE (diff, epsilon);
00720   }
00721 }
00722 
00724 // since we use float in this test and some matrices are bad conditioned for the eigenvalue decomposition, we will have
00725 // some errors > 0.2 but less than 1% is > 1e-3 -> we will just check whether the failure rate is below 1%
00726 TEST (PCL, eigen33f)
00727 {
00728   typedef float Scalar;
00729   typedef Eigen::Matrix<Scalar, 3, 3, Eigen::RowMajor> RMatrix;
00730   typedef Eigen::Matrix<Scalar, 3, 3, Eigen::ColMajor> CMatrix;
00731   RMatrix r_matrix;
00732   RMatrix r_vectors;
00733   Eigen::Matrix<Scalar, 3, 1> r_eigenvalues;
00734   Eigen::Matrix<Scalar, 3, 1> c_eigenvalues;
00735   CMatrix c_matrix;
00736   CMatrix c_vectors;
00737   Eigen::Matrix<Scalar, 3, 3> r_result;
00738   Eigen::Matrix<Scalar, 3, 3> r_error;
00739   Eigen::Matrix<Scalar, 3, 3> g_result;
00740   Eigen::Matrix<Scalar, 3, 3> g_error;
00741   Eigen::Matrix<Scalar, 3, 3> c_result;
00742   Eigen::Matrix<Scalar, 3, 3> c_error;
00743   Scalar diff;
00744 
00745   const Scalar epsilon = 1e-3f;
00746   const unsigned iterations = 1000000;
00747   bool r_failed;
00748   bool c_failed;
00749   unsigned r_fail_count = 0;
00750   unsigned c_fail_count = 0;
00751 
00752   // test floating point row-major : row-major
00753   for (unsigned idx = 0; idx < iterations; ++idx)
00754   {
00755     r_failed = c_failed = false;
00756     // generate test matrices
00757     generateSymPosMatrix3x3 (r_matrix);
00758     c_matrix = r_matrix;
00759 
00760     // calculate the eigenvalue decomposition
00761     eigen33 (r_matrix, r_vectors, r_eigenvalues);
00762 
00763     // test if U * V * U^T = M
00764     r_result = r_vectors * r_eigenvalues.asDiagonal () * r_vectors.transpose ();
00765     r_error = r_result - r_matrix;
00766     diff = r_error.cwiseAbs (). sum ();
00767     if (diff > epsilon)
00768       r_failed = true;
00769 
00770     // test if the eigenvalues are orthonormal
00771     g_result = r_vectors * r_vectors.transpose ();
00772     g_error = g_result - RMatrix::Identity ();
00773     diff = g_error.cwiseAbs (). sum ();
00774     if (diff > epsilon)
00775       r_failed = true;
00776 
00777     if(r_failed)
00778       ++r_fail_count;
00779 
00780     // test if column major matrices are also calculated correctly
00781     eigen33 (c_matrix, c_vectors, c_eigenvalues);
00782     c_result = c_vectors * c_eigenvalues.asDiagonal () * c_vectors.transpose ();
00783     c_error = c_result - c_matrix;
00784     diff = c_error.cwiseAbs (). sum ();
00785     if (diff > epsilon)
00786       c_failed = true;
00787 
00788     g_result = c_vectors * c_vectors.transpose ();
00789     g_error = g_result - CMatrix::Identity ();
00790     diff = g_error.cwiseAbs (). sum ();
00791     if (diff > epsilon)
00792       c_failed = true;
00793 
00794     if(c_failed)
00795       ++c_fail_count;
00796   }
00797 
00798   // less than 1% failure rate
00799   EXPECT_LE (float(r_fail_count) / float(iterations), 0.01);
00800   EXPECT_LE (float(r_fail_count) / float(iterations), 0.01);
00801 }
00802 
00803 /* ---[ */
00804 int
00805 main (int argc, char** argv)
00806 {
00807   testing::InitGoogleTest (&argc, argv);
00808   return (RUN_ALL_TESTS ());
00809 }
00810 /* ]--- */


pcl
Author(s): Open Perception
autogenerated on Mon Oct 6 2014 03:18:16