Home | History | Annotate | Download | only in ceres
      1 // Ceres Solver - A fast non-linear least squares minimizer
      2 // Copyright 2010, 2011, 2012 Google Inc. All rights reserved.
      3 // http://code.google.com/p/ceres-solver/
      4 //
      5 // Redistribution and use in source and binary forms, with or without
      6 // modification, are permitted provided that the following conditions are met:
      7 //
      8 // * Redistributions of source code must retain the above copyright notice,
      9 //   this list of conditions and the following disclaimer.
     10 // * Redistributions in binary form must reproduce the above copyright notice,
     11 //   this list of conditions and the following disclaimer in the documentation
     12 //   and/or other materials provided with the distribution.
     13 // * Neither the name of Google Inc. nor the names of its contributors may be
     14 //   used to endorse or promote products derived from this software without
     15 //   specific prior written permission.
     16 //
     17 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
     18 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     19 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     20 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
     21 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     22 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     23 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     24 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     25 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     26 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     27 // POSSIBILITY OF SUCH DAMAGE.
     28 //
     29 // Author: sameeragarwal (at) google.com (Sameer Agarwal)
     30 
     31 #include <cmath>
     32 #include <limits>
     33 #include <string>
     34 #include "ceres/internal/eigen.h"
     35 #include "ceres/internal/port.h"
     36 #include "ceres/jet.h"
     37 #include "ceres/rotation.h"
     38 #include "ceres/stringprintf.h"
     39 #include "ceres/test_util.h"
     40 #include "glog/logging.h"
     41 #include "gmock/gmock.h"
     42 #include "gtest/gtest.h"
     43 
     44 namespace ceres {
     45 namespace internal {
     46 
     47 const double kPi = 3.14159265358979323846;
     48 const double kHalfSqrt2 = 0.707106781186547524401;
     49 
     50 double RandDouble() {
     51   double r = rand();
     52   return r / RAND_MAX;
     53 }
     54 
     55 // A tolerance value for floating-point comparisons.
     56 static double const kTolerance = numeric_limits<double>::epsilon() * 10;
     57 
     58 // Looser tolerance used for numerically unstable conversions.
     59 static double const kLooseTolerance = 1e-9;
     60 
     61 // Use as:
     62 // double quaternion[4];
     63 // EXPECT_THAT(quaternion, IsNormalizedQuaternion());
     64 MATCHER(IsNormalizedQuaternion, "") {
     65   if (arg == NULL) {
     66     *result_listener << "Null quaternion";
     67     return false;
     68   }
     69 
     70   double norm2 = arg[0] * arg[0] + arg[1] * arg[1] +
     71       arg[2] * arg[2] + arg[3] * arg[3];
     72   if (fabs(norm2 - 1.0) > kTolerance) {
     73     *result_listener << "squared norm is " << norm2;
     74     return false;
     75   }
     76 
     77   return true;
     78 }
     79 
     80 // Use as:
     81 // double expected_quaternion[4];
     82 // double actual_quaternion[4];
     83 // EXPECT_THAT(actual_quaternion, IsNearQuaternion(expected_quaternion));
     84 MATCHER_P(IsNearQuaternion, expected, "") {
     85   if (arg == NULL) {
     86     *result_listener << "Null quaternion";
     87     return false;
     88   }
     89 
     90   // Quaternions are equivalent upto a sign change. So we will compare
     91   // both signs before declaring failure.
     92   bool near = true;
     93   for (int i = 0; i < 4; i++) {
     94     if (fabs(arg[i] - expected[i]) > kTolerance) {
     95       near = false;
     96       break;
     97     }
     98   }
     99 
    100   if (near) {
    101     return true;
    102   }
    103 
    104   near = true;
    105   for (int i = 0; i < 4; i++) {
    106     if (fabs(arg[i] + expected[i]) > kTolerance) {
    107       near = false;
    108       break;
    109     }
    110   }
    111 
    112   if (near) {
    113     return true;
    114   }
    115 
    116   *result_listener << "expected : "
    117                    << expected[0] << " "
    118                    << expected[1] << " "
    119                    << expected[2] << " "
    120                    << expected[3] << " "
    121                    << "actual : "
    122                    << arg[0] << " "
    123                    << arg[1] << " "
    124                    << arg[2] << " "
    125                    << arg[3];
    126   return false;
    127 }
    128 
    129 // Use as:
    130 // double expected_axis_angle[4];
    131 // double actual_axis_angle[4];
    132 // EXPECT_THAT(actual_axis_angle, IsNearAngleAxis(expected_axis_angle));
    133 MATCHER_P(IsNearAngleAxis, expected, "") {
    134   if (arg == NULL) {
    135     *result_listener << "Null axis/angle";
    136     return false;
    137   }
    138 
    139   for (int i = 0; i < 3; i++) {
    140     if (fabs(arg[i] - expected[i]) > kTolerance) {
    141       *result_listener << "component " << i << " should be " << expected[i];
    142       return false;
    143     }
    144   }
    145 
    146   return true;
    147 }
    148 
    149 // Use as:
    150 // double matrix[9];
    151 // EXPECT_THAT(matrix, IsOrthonormal());
    152 MATCHER(IsOrthonormal, "") {
    153   if (arg == NULL) {
    154     *result_listener << "Null matrix";
    155     return false;
    156   }
    157 
    158   for (int c1 = 0; c1 < 3; c1++) {
    159     for (int c2 = 0; c2 < 3; c2++) {
    160       double v = 0;
    161       for (int i = 0; i < 3; i++) {
    162         v += arg[i + 3 * c1] * arg[i + 3 * c2];
    163       }
    164       double expected = (c1 == c2) ? 1 : 0;
    165       if (fabs(expected - v) > kTolerance) {
    166         *result_listener << "Columns " << c1 << " and " << c2
    167                          << " should have dot product " << expected
    168                          << " but have " << v;
    169         return false;
    170       }
    171     }
    172   }
    173 
    174   return true;
    175 }
    176 
    177 // Use as:
    178 // double matrix1[9];
    179 // double matrix2[9];
    180 // EXPECT_THAT(matrix1, IsNear3x3Matrix(matrix2));
    181 MATCHER_P(IsNear3x3Matrix, expected, "") {
    182   if (arg == NULL) {
    183     *result_listener << "Null matrix";
    184     return false;
    185   }
    186 
    187   for (int i = 0; i < 9; i++) {
    188     if (fabs(arg[i] - expected[i]) > kTolerance) {
    189       *result_listener << "component " << i << " should be " << expected[i];
    190       return false;
    191     }
    192   }
    193 
    194   return true;
    195 }
    196 
    197 // Transforms a zero axis/angle to a quaternion.
    198 TEST(Rotation, ZeroAngleAxisToQuaternion) {
    199   double axis_angle[3] = { 0, 0, 0 };
    200   double quaternion[4];
    201   double expected[4] = { 1, 0, 0, 0 };
    202   AngleAxisToQuaternion(axis_angle, quaternion);
    203   EXPECT_THAT(quaternion, IsNormalizedQuaternion());
    204   EXPECT_THAT(quaternion, IsNearQuaternion(expected));
    205 }
    206 
    207 // Test that exact conversion works for small angles.
    208 TEST(Rotation, SmallAngleAxisToQuaternion) {
    209   // Small, finite value to test.
    210   double theta = 1.0e-2;
    211   double axis_angle[3] = { theta, 0, 0 };
    212   double quaternion[4];
    213   double expected[4] = { cos(theta/2), sin(theta/2.0), 0, 0 };
    214   AngleAxisToQuaternion(axis_angle, quaternion);
    215   EXPECT_THAT(quaternion, IsNormalizedQuaternion());
    216   EXPECT_THAT(quaternion, IsNearQuaternion(expected));
    217 }
    218 
    219 // Test that approximate conversion works for very small angles.
    220 TEST(Rotation, TinyAngleAxisToQuaternion) {
    221   // Very small value that could potentially cause underflow.
    222   double theta = pow(numeric_limits<double>::min(), 0.75);
    223   double axis_angle[3] = { theta, 0, 0 };
    224   double quaternion[4];
    225   double expected[4] = { cos(theta/2), sin(theta/2.0), 0, 0 };
    226   AngleAxisToQuaternion(axis_angle, quaternion);
    227   EXPECT_THAT(quaternion, IsNormalizedQuaternion());
    228   EXPECT_THAT(quaternion, IsNearQuaternion(expected));
    229 }
    230 
    231 // Transforms a rotation by pi/2 around X to a quaternion.
    232 TEST(Rotation, XRotationToQuaternion) {
    233   double axis_angle[3] = { kPi / 2, 0, 0 };
    234   double quaternion[4];
    235   double expected[4] = { kHalfSqrt2, kHalfSqrt2, 0, 0 };
    236   AngleAxisToQuaternion(axis_angle, quaternion);
    237   EXPECT_THAT(quaternion, IsNormalizedQuaternion());
    238   EXPECT_THAT(quaternion, IsNearQuaternion(expected));
    239 }
    240 
    241 // Transforms a unit quaternion to an axis angle.
    242 TEST(Rotation, UnitQuaternionToAngleAxis) {
    243   double quaternion[4] = { 1, 0, 0, 0 };
    244   double axis_angle[3];
    245   double expected[3] = { 0, 0, 0 };
    246   QuaternionToAngleAxis(quaternion, axis_angle);
    247   EXPECT_THAT(axis_angle, IsNearAngleAxis(expected));
    248 }
    249 
    250 // Transforms a quaternion that rotates by pi about the Y axis to an axis angle.
    251 TEST(Rotation, YRotationQuaternionToAngleAxis) {
    252   double quaternion[4] = { 0, 0, 1, 0 };
    253   double axis_angle[3];
    254   double expected[3] = { 0, kPi, 0 };
    255   QuaternionToAngleAxis(quaternion, axis_angle);
    256   EXPECT_THAT(axis_angle, IsNearAngleAxis(expected));
    257 }
    258 
    259 // Transforms a quaternion that rotates by pi/3 about the Z axis to an axis
    260 // angle.
    261 TEST(Rotation, ZRotationQuaternionToAngleAxis) {
    262   double quaternion[4] = { sqrt(3) / 2, 0, 0, 0.5 };
    263   double axis_angle[3];
    264   double expected[3] = { 0, 0, kPi / 3 };
    265   QuaternionToAngleAxis(quaternion, axis_angle);
    266   EXPECT_THAT(axis_angle, IsNearAngleAxis(expected));
    267 }
    268 
    269 // Test that exact conversion works for small angles.
    270 TEST(Rotation, SmallQuaternionToAngleAxis) {
    271   // Small, finite value to test.
    272   double theta = 1.0e-2;
    273   double quaternion[4] = { cos(theta/2), sin(theta/2.0), 0, 0 };
    274   double axis_angle[3];
    275   double expected[3] = { theta, 0, 0 };
    276   QuaternionToAngleAxis(quaternion, axis_angle);
    277   EXPECT_THAT(axis_angle, IsNearAngleAxis(expected));
    278 }
    279 
    280 // Test that approximate conversion works for very small angles.
    281 TEST(Rotation, TinyQuaternionToAngleAxis) {
    282   // Very small value that could potentially cause underflow.
    283   double theta = pow(numeric_limits<double>::min(), 0.75);
    284   double quaternion[4] = { cos(theta/2), sin(theta/2.0), 0, 0 };
    285   double axis_angle[3];
    286   double expected[3] = { theta, 0, 0 };
    287   QuaternionToAngleAxis(quaternion, axis_angle);
    288   EXPECT_THAT(axis_angle, IsNearAngleAxis(expected));
    289 }
    290 
    291 TEST(Rotation, QuaternionToAngleAxisAngleIsLessThanPi) {
    292   double quaternion[4];
    293   double angle_axis[3];
    294 
    295   const double half_theta = 0.75 * kPi;
    296 
    297   quaternion[0] = cos(half_theta);
    298   quaternion[1] = 1.0 * sin(half_theta);
    299   quaternion[2] = 0.0;
    300   quaternion[3] = 0.0;
    301   QuaternionToAngleAxis(quaternion, angle_axis);
    302   const double angle = sqrt(angle_axis[0] * angle_axis[0] +
    303                             angle_axis[1] * angle_axis[1] +
    304                             angle_axis[2] * angle_axis[2]);
    305   EXPECT_LE(angle, kPi);
    306 }
    307 
    308 static const int kNumTrials = 10000;
    309 
    310 // Takes a bunch of random axis/angle values, converts them to quaternions,
    311 // and back again.
    312 TEST(Rotation, AngleAxisToQuaterionAndBack) {
    313   srand(5);
    314   for (int i = 0; i < kNumTrials; i++) {
    315     double axis_angle[3];
    316     // Make an axis by choosing three random numbers in [-1, 1) and
    317     // normalizing.
    318     double norm = 0;
    319     for (int i = 0; i < 3; i++) {
    320       axis_angle[i] = RandDouble() * 2 - 1;
    321       norm += axis_angle[i] * axis_angle[i];
    322     }
    323     norm = sqrt(norm);
    324 
    325     // Angle in [-pi, pi).
    326     double theta = kPi * 2 * RandDouble() - kPi;
    327     for (int i = 0; i < 3; i++) {
    328       axis_angle[i] = axis_angle[i] * theta / norm;
    329     }
    330 
    331     double quaternion[4];
    332     double round_trip[3];
    333     // We use ASSERTs here because if there's one failure, there are
    334     // probably many and spewing a million failures doesn't make anyone's
    335     // day.
    336     AngleAxisToQuaternion(axis_angle, quaternion);
    337     ASSERT_THAT(quaternion, IsNormalizedQuaternion());
    338     QuaternionToAngleAxis(quaternion, round_trip);
    339     ASSERT_THAT(round_trip, IsNearAngleAxis(axis_angle));
    340   }
    341 }
    342 
    343 // Takes a bunch of random quaternions, converts them to axis/angle,
    344 // and back again.
    345 TEST(Rotation, QuaterionToAngleAxisAndBack) {
    346   srand(5);
    347   for (int i = 0; i < kNumTrials; i++) {
    348     double quaternion[4];
    349     // Choose four random numbers in [-1, 1) and normalize.
    350     double norm = 0;
    351     for (int i = 0; i < 4; i++) {
    352       quaternion[i] = RandDouble() * 2 - 1;
    353       norm += quaternion[i] * quaternion[i];
    354     }
    355     norm = sqrt(norm);
    356 
    357     for (int i = 0; i < 4; i++) {
    358       quaternion[i] = quaternion[i] / norm;
    359     }
    360 
    361     double axis_angle[3];
    362     double round_trip[4];
    363     QuaternionToAngleAxis(quaternion, axis_angle);
    364     AngleAxisToQuaternion(axis_angle, round_trip);
    365     ASSERT_THAT(round_trip, IsNormalizedQuaternion());
    366     ASSERT_THAT(round_trip, IsNearQuaternion(quaternion));
    367   }
    368 }
    369 
    370 // Transforms a zero axis/angle to a rotation matrix.
    371 TEST(Rotation, ZeroAngleAxisToRotationMatrix) {
    372   double axis_angle[3] = { 0, 0, 0 };
    373   double matrix[9];
    374   double expected[9] = { 1, 0, 0, 0, 1, 0, 0, 0, 1 };
    375   AngleAxisToRotationMatrix(axis_angle, matrix);
    376   EXPECT_THAT(matrix, IsOrthonormal());
    377   EXPECT_THAT(matrix, IsNear3x3Matrix(expected));
    378 }
    379 
    380 TEST(Rotation, NearZeroAngleAxisToRotationMatrix) {
    381   double axis_angle[3] = { 1e-24, 2e-24, 3e-24 };
    382   double matrix[9];
    383   double expected[9] = { 1, 0, 0, 0, 1, 0, 0, 0, 1 };
    384   AngleAxisToRotationMatrix(axis_angle, matrix);
    385   EXPECT_THAT(matrix, IsOrthonormal());
    386   EXPECT_THAT(matrix, IsNear3x3Matrix(expected));
    387 }
    388 
    389 // Transforms a rotation by pi/2 around X to a rotation matrix and back.
    390 TEST(Rotation, XRotationToRotationMatrix) {
    391   double axis_angle[3] = { kPi / 2, 0, 0 };
    392   double matrix[9];
    393   // The rotation matrices are stored column-major.
    394   double expected[9] = { 1, 0, 0, 0, 0, 1, 0, -1, 0 };
    395   AngleAxisToRotationMatrix(axis_angle, matrix);
    396   EXPECT_THAT(matrix, IsOrthonormal());
    397   EXPECT_THAT(matrix, IsNear3x3Matrix(expected));
    398   double round_trip[3];
    399   RotationMatrixToAngleAxis(matrix, round_trip);
    400   EXPECT_THAT(round_trip, IsNearAngleAxis(axis_angle));
    401 }
    402 
    403 // Transforms an axis angle that rotates by pi about the Y axis to a
    404 // rotation matrix and back.
    405 TEST(Rotation, YRotationToRotationMatrix) {
    406   double axis_angle[3] = { 0, kPi, 0 };
    407   double matrix[9];
    408   double expected[9] = { -1, 0, 0, 0, 1, 0, 0, 0, -1 };
    409   AngleAxisToRotationMatrix(axis_angle, matrix);
    410   EXPECT_THAT(matrix, IsOrthonormal());
    411   EXPECT_THAT(matrix, IsNear3x3Matrix(expected));
    412 
    413   double round_trip[3];
    414   RotationMatrixToAngleAxis(matrix, round_trip);
    415   EXPECT_THAT(round_trip, IsNearAngleAxis(axis_angle));
    416 }
    417 
    418 TEST(Rotation, NearPiAngleAxisRoundTrip) {
    419   double in_axis_angle[3];
    420   double matrix[9];
    421   double out_axis_angle[3];
    422 
    423   srand(5);
    424   for (int i = 0; i < kNumTrials; i++) {
    425     // Make an axis by choosing three random numbers in [-1, 1) and
    426     // normalizing.
    427     double norm = 0;
    428     for (int i = 0; i < 3; i++) {
    429       in_axis_angle[i] = RandDouble() * 2 - 1;
    430       norm += in_axis_angle[i] * in_axis_angle[i];
    431     }
    432     norm = sqrt(norm);
    433 
    434     // Angle in [pi - kMaxSmallAngle, pi).
    435     const double kMaxSmallAngle = 1e-2;
    436     double theta = kPi - kMaxSmallAngle * RandDouble();
    437 
    438     for (int i = 0; i < 3; i++) {
    439       in_axis_angle[i] *= (theta / norm);
    440     }
    441     AngleAxisToRotationMatrix(in_axis_angle, matrix);
    442     RotationMatrixToAngleAxis(matrix, out_axis_angle);
    443 
    444     for (int i = 0; i < 3; ++i) {
    445       EXPECT_NEAR(out_axis_angle[i], in_axis_angle[i], kLooseTolerance);
    446     }
    447   }
    448 }
    449 
    450 TEST(Rotation, AtPiAngleAxisRoundTrip) {
    451   // A rotation of kPi about the X axis;
    452   static const double kMatrix[3][3] = {
    453     {1.0,  0.0,  0.0},
    454     {0.0,  -1.0,  0.0},
    455     {0.0,  0.0,  -1.0}
    456   };
    457 
    458   double in_matrix[9];
    459   // Fill it from kMatrix in col-major order.
    460   for (int j = 0, k = 0; j < 3; ++j) {
    461      for (int i = 0; i < 3; ++i, ++k) {
    462        in_matrix[k] = kMatrix[i][j];
    463      }
    464   }
    465 
    466   const double expected_axis_angle[3] = { kPi, 0, 0 };
    467 
    468   double out_matrix[9];
    469   double axis_angle[3];
    470   RotationMatrixToAngleAxis(in_matrix, axis_angle);
    471   AngleAxisToRotationMatrix(axis_angle, out_matrix);
    472 
    473   LOG(INFO) << "AngleAxis = " << axis_angle[0] << " " << axis_angle[1]
    474             << " " << axis_angle[2];
    475   LOG(INFO) << "Expected AngleAxis = " << kPi << " 0 0";
    476   double out_rowmajor[3][3];
    477   for (int j = 0, k = 0; j < 3; ++j) {
    478     for (int i = 0; i < 3; ++i, ++k) {
    479       out_rowmajor[i][j] = out_matrix[k];
    480     }
    481   }
    482   LOG(INFO) << "Rotation:";
    483   LOG(INFO) << "EXPECTED      |        ACTUAL";
    484   for (int i = 0; i < 3; ++i) {
    485     string line;
    486     for (int j = 0; j < 3; ++j) {
    487       StringAppendF(&line, "%g ", kMatrix[i][j]);
    488     }
    489     line += "         |        ";
    490     for (int j = 0; j < 3; ++j) {
    491       StringAppendF(&line, "%g ", out_rowmajor[i][j]);
    492     }
    493     LOG(INFO) << line;
    494   }
    495 
    496   EXPECT_THAT(axis_angle, IsNearAngleAxis(expected_axis_angle));
    497   EXPECT_THAT(out_matrix, IsNear3x3Matrix(in_matrix));
    498 }
    499 
    500 // Transforms an axis angle that rotates by pi/3 about the Z axis to a
    501 // rotation matrix.
    502 TEST(Rotation, ZRotationToRotationMatrix) {
    503   double axis_angle[3] =  { 0, 0, kPi / 3 };
    504   double matrix[9];
    505   // This is laid-out row-major on the screen but is actually stored
    506   // column-major.
    507   double expected[9] = { 0.5, sqrt(3) / 2, 0,   // Column 1
    508                          -sqrt(3) / 2, 0.5, 0,  // Column 2
    509                          0, 0, 1 };             // Column 3
    510   AngleAxisToRotationMatrix(axis_angle, matrix);
    511   EXPECT_THAT(matrix, IsOrthonormal());
    512   EXPECT_THAT(matrix, IsNear3x3Matrix(expected));
    513   double round_trip[3];
    514   RotationMatrixToAngleAxis(matrix, round_trip);
    515   EXPECT_THAT(round_trip, IsNearAngleAxis(axis_angle));
    516 }
    517 
    518 // Takes a bunch of random axis/angle values, converts them to rotation
    519 // matrices, and back again.
    520 TEST(Rotation, AngleAxisToRotationMatrixAndBack) {
    521   srand(5);
    522   for (int i = 0; i < kNumTrials; i++) {
    523     double axis_angle[3];
    524     // Make an axis by choosing three random numbers in [-1, 1) and
    525     // normalizing.
    526     double norm = 0;
    527     for (int i = 0; i < 3; i++) {
    528       axis_angle[i] = RandDouble() * 2 - 1;
    529       norm += axis_angle[i] * axis_angle[i];
    530     }
    531     norm = sqrt(norm);
    532 
    533     // Angle in [-pi, pi).
    534     double theta = kPi * 2 * RandDouble() - kPi;
    535     for (int i = 0; i < 3; i++) {
    536       axis_angle[i] = axis_angle[i] * theta / norm;
    537     }
    538 
    539     double matrix[9];
    540     double round_trip[3];
    541     AngleAxisToRotationMatrix(axis_angle, matrix);
    542     ASSERT_THAT(matrix, IsOrthonormal());
    543     RotationMatrixToAngleAxis(matrix, round_trip);
    544 
    545     for (int i = 0; i < 3; ++i) {
    546       EXPECT_NEAR(round_trip[i], axis_angle[i], kLooseTolerance);
    547     }
    548   }
    549 }
    550 
    551 // Transposes a 3x3 matrix.
    552 static void Transpose3x3(double m[9]) {
    553   std::swap(m[1], m[3]);
    554   std::swap(m[2], m[6]);
    555   std::swap(m[5], m[7]);
    556 }
    557 
    558 // Convert Euler angles from radians to degrees.
    559 static void ToDegrees(double ea[3]) {
    560   for (int i = 0; i < 3; ++i)
    561     ea[i] *= 180.0 / kPi;
    562 }
    563 
    564 // Compare the 3x3 rotation matrices produced by the axis-angle
    565 // rotation 'aa' and the Euler angle rotation 'ea' (in radians).
    566 static void CompareEulerToAngleAxis(double aa[3], double ea[3]) {
    567   double aa_matrix[9];
    568   AngleAxisToRotationMatrix(aa, aa_matrix);
    569   Transpose3x3(aa_matrix);  // Column to row major order.
    570 
    571   double ea_matrix[9];
    572   ToDegrees(ea);  // Radians to degrees.
    573   const int kRowStride = 3;
    574   EulerAnglesToRotationMatrix(ea, kRowStride, ea_matrix);
    575 
    576   EXPECT_THAT(aa_matrix, IsOrthonormal());
    577   EXPECT_THAT(ea_matrix, IsOrthonormal());
    578   EXPECT_THAT(ea_matrix, IsNear3x3Matrix(aa_matrix));
    579 }
    580 
    581 // Test with rotation axis along the x/y/z axes.
    582 // Also test zero rotation.
    583 TEST(EulerAnglesToRotationMatrix, OnAxis) {
    584   int n_tests = 0;
    585   for (double x = -1.0; x <= 1.0; x += 1.0) {
    586     for (double y = -1.0; y <= 1.0; y += 1.0) {
    587       for (double z = -1.0; z <= 1.0; z += 1.0) {
    588         if ((x != 0) + (y != 0) + (z != 0) > 1)
    589           continue;
    590         double axis_angle[3] = {x, y, z};
    591         double euler_angles[3] = {x, y, z};
    592         CompareEulerToAngleAxis(axis_angle, euler_angles);
    593         ++n_tests;
    594       }
    595     }
    596   }
    597   CHECK_EQ(7, n_tests);
    598 }
    599 
    600 // Test that a random rotation produces an orthonormal rotation
    601 // matrix.
    602 TEST(EulerAnglesToRotationMatrix, IsOrthonormal) {
    603   srand(5);
    604   for (int trial = 0; trial < kNumTrials; ++trial) {
    605     double ea[3];
    606     for (int i = 0; i < 3; ++i)
    607       ea[i] = 360.0 * (RandDouble() * 2.0 - 1.0);
    608     double ea_matrix[9];
    609     ToDegrees(ea);  // Radians to degrees.
    610     EulerAnglesToRotationMatrix(ea, 3, ea_matrix);
    611     EXPECT_THAT(ea_matrix, IsOrthonormal());
    612   }
    613 }
    614 
    615 // Tests using Jets for specific behavior involving auto differentiation
    616 // near singularity points.
    617 
    618 typedef Jet<double, 3> J3;
    619 typedef Jet<double, 4> J4;
    620 
    621 J3 MakeJ3(double a, double v0, double v1, double v2) {
    622   J3 j;
    623   j.a = a;
    624   j.v[0] = v0;
    625   j.v[1] = v1;
    626   j.v[2] = v2;
    627   return j;
    628 }
    629 
    630 J4 MakeJ4(double a, double v0, double v1, double v2, double v3) {
    631   J4 j;
    632   j.a = a;
    633   j.v[0] = v0;
    634   j.v[1] = v1;
    635   j.v[2] = v2;
    636   j.v[3] = v3;
    637   return j;
    638 }
    639 
    640 
    641 bool IsClose(double x, double y) {
    642   EXPECT_FALSE(IsNaN(x));
    643   EXPECT_FALSE(IsNaN(y));
    644   double absdiff = fabs(x - y);
    645   if (x == 0 || y == 0) {
    646     return absdiff <= kTolerance;
    647   }
    648   double reldiff = absdiff / max(fabs(x), fabs(y));
    649   return reldiff <= kTolerance;
    650 }
    651 
    652 template <int N>
    653 bool IsClose(const Jet<double, N> &x, const Jet<double, N> &y) {
    654   if (IsClose(x.a, y.a)) {
    655     for (int i = 0; i < N; i++) {
    656       if (!IsClose(x.v[i], y.v[i])) {
    657         return false;
    658       }
    659     }
    660   }
    661   return true;
    662 }
    663 
    664 template <int M, int N>
    665 void ExpectJetArraysClose(const Jet<double, N> *x, const Jet<double, N> *y) {
    666   for (int i = 0; i < M; i++) {
    667     if (!IsClose(x[i], y[i])) {
    668       LOG(ERROR) << "Jet " << i << "/" << M << " not equal";
    669       LOG(ERROR) << "x[" << i << "]: " << x[i];
    670       LOG(ERROR) << "y[" << i << "]: " << y[i];
    671       Jet<double, N> d, zero;
    672       d.a = y[i].a - x[i].a;
    673       for (int j = 0; j < N; j++) {
    674         d.v[j] = y[i].v[j] - x[i].v[j];
    675       }
    676       LOG(ERROR) << "diff: " << d;
    677       EXPECT_TRUE(IsClose(x[i], y[i]));
    678     }
    679   }
    680 }
    681 
    682 // Log-10 of a value well below machine precision.
    683 static const int kSmallTinyCutoff =
    684     static_cast<int>(2 * log(numeric_limits<double>::epsilon())/log(10.0));
    685 
    686 // Log-10 of a value just below values representable by double.
    687 static const int kTinyZeroLimit   =
    688     static_cast<int>(1 + log(numeric_limits<double>::min())/log(10.0));
    689 
    690 // Test that exact conversion works for small angles when jets are used.
    691 TEST(Rotation, SmallAngleAxisToQuaternionForJets) {
    692   // Examine small x rotations that are still large enough
    693   // to be well within the range represented by doubles.
    694   for (int i = -2; i >= kSmallTinyCutoff; i--) {
    695     double theta = pow(10.0, i);
    696     J3 axis_angle[3] = { J3(theta, 0), J3(0, 1), J3(0, 2) };
    697     J3 quaternion[4];
    698     J3 expected[4] = {
    699         MakeJ3(cos(theta/2), -sin(theta/2)/2, 0, 0),
    700         MakeJ3(sin(theta/2), cos(theta/2)/2, 0, 0),
    701         MakeJ3(0, 0, sin(theta/2)/theta, 0),
    702         MakeJ3(0, 0, 0, sin(theta/2)/theta),
    703     };
    704     AngleAxisToQuaternion(axis_angle, quaternion);
    705     ExpectJetArraysClose<4, 3>(quaternion, expected);
    706   }
    707 }
    708 
    709 
    710 // Test that conversion works for very small angles when jets are used.
    711 TEST(Rotation, TinyAngleAxisToQuaternionForJets) {
    712   // Examine tiny x rotations that extend all the way to where
    713   // underflow occurs.
    714   for (int i = kSmallTinyCutoff; i >= kTinyZeroLimit; i--) {
    715     double theta = pow(10.0, i);
    716     J3 axis_angle[3] = { J3(theta, 0), J3(0, 1), J3(0, 2) };
    717     J3 quaternion[4];
    718     // To avoid loss of precision in the test itself,
    719     // a finite expansion is used here, which will
    720     // be exact up to machine precision for the test values used.
    721     J3 expected[4] = {
    722         MakeJ3(1.0, 0, 0, 0),
    723         MakeJ3(0, 0.5, 0, 0),
    724         MakeJ3(0, 0, 0.5, 0),
    725         MakeJ3(0, 0, 0, 0.5),
    726     };
    727     AngleAxisToQuaternion(axis_angle, quaternion);
    728     ExpectJetArraysClose<4, 3>(quaternion, expected);
    729   }
    730 }
    731 
    732 // Test that derivatives are correct for zero rotation.
    733 TEST(Rotation, ZeroAngleAxisToQuaternionForJets) {
    734   J3 axis_angle[3] = { J3(0, 0), J3(0, 1), J3(0, 2) };
    735   J3 quaternion[4];
    736   J3 expected[4] = {
    737       MakeJ3(1.0, 0, 0, 0),
    738       MakeJ3(0, 0.5, 0, 0),
    739       MakeJ3(0, 0, 0.5, 0),
    740       MakeJ3(0, 0, 0, 0.5),
    741   };
    742   AngleAxisToQuaternion(axis_angle, quaternion);
    743   ExpectJetArraysClose<4, 3>(quaternion, expected);
    744 }
    745 
    746 // Test that exact conversion works for small angles.
    747 TEST(Rotation, SmallQuaternionToAngleAxisForJets) {
    748   // Examine small x rotations that are still large enough
    749   // to be well within the range represented by doubles.
    750   for (int i = -2; i >= kSmallTinyCutoff; i--) {
    751     double theta = pow(10.0, i);
    752     double s = sin(theta);
    753     double c = cos(theta);
    754     J4 quaternion[4] = { J4(c, 0), J4(s, 1), J4(0, 2), J4(0, 3) };
    755     J4 axis_angle[3];
    756     J4 expected[3] = {
    757         MakeJ4(s, -2*theta, 2*theta*c, 0, 0),
    758         MakeJ4(0, 0, 0, 2*theta/s, 0),
    759         MakeJ4(0, 0, 0, 0, 2*theta/s),
    760     };
    761     QuaternionToAngleAxis(quaternion, axis_angle);
    762     ExpectJetArraysClose<3, 4>(axis_angle, expected);
    763   }
    764 }
    765 
    766 // Test that conversion works for very small angles.
    767 TEST(Rotation, TinyQuaternionToAngleAxisForJets) {
    768   // Examine tiny x rotations that extend all the way to where
    769   // underflow occurs.
    770   for (int i = kSmallTinyCutoff; i >= kTinyZeroLimit; i--) {
    771     double theta = pow(10.0, i);
    772     double s = sin(theta);
    773     double c = cos(theta);
    774     J4 quaternion[4] = { J4(c, 0), J4(s, 1), J4(0, 2), J4(0, 3) };
    775     J4 axis_angle[3];
    776     // To avoid loss of precision in the test itself,
    777     // a finite expansion is used here, which will
    778     // be exact up to machine precision for the test values used.
    779     J4 expected[3] = {
    780         MakeJ4(theta, -2*theta, 2.0, 0, 0),
    781         MakeJ4(0, 0, 0, 2.0, 0),
    782         MakeJ4(0, 0, 0, 0, 2.0),
    783     };
    784     QuaternionToAngleAxis(quaternion, axis_angle);
    785     ExpectJetArraysClose<3, 4>(axis_angle, expected);
    786   }
    787 }
    788 
    789 // Test that conversion works for no rotation.
    790 TEST(Rotation, ZeroQuaternionToAngleAxisForJets) {
    791   J4 quaternion[4] = { J4(1, 0), J4(0, 1), J4(0, 2), J4(0, 3) };
    792   J4 axis_angle[3];
    793   J4 expected[3] = {
    794       MakeJ4(0, 0, 2.0, 0, 0),
    795       MakeJ4(0, 0, 0, 2.0, 0),
    796       MakeJ4(0, 0, 0, 0, 2.0),
    797   };
    798   QuaternionToAngleAxis(quaternion, axis_angle);
    799   ExpectJetArraysClose<3, 4>(axis_angle, expected);
    800 }
    801 
    802 TEST(Quaternion, RotatePointGivesSameAnswerAsRotationByMatrixCanned) {
    803   // Canned data generated in octave.
    804   double const q[4] = {
    805     +0.1956830471754074,
    806     -0.0150618562474847,
    807     +0.7634572982788086,
    808     -0.3019454777240753,
    809   };
    810   double const Q[3][3] = {  // Scaled rotation matrix.
    811     { -0.6355194033477252,  0.0951730541682254,  0.3078870197911186 },
    812     { -0.1411693904792992,  0.5297609702153905, -0.4551502574482019 },
    813     { -0.2896955822708862, -0.4669396571547050, -0.4536309793389248 },
    814   };
    815   double const R[3][3] = {  // With unit rows and columns.
    816     { -0.8918859164053080,  0.1335655625725649,  0.4320876677394745 },
    817     { -0.1981166751680096,  0.7434648665444399, -0.6387564287225856 },
    818     { -0.4065578619806013, -0.6553016349046693, -0.6366242786393164 },
    819   };
    820 
    821   // Compute R from q and compare to known answer.
    822   double Rq[3][3];
    823   QuaternionToScaledRotation<double>(q, Rq[0]);
    824   ExpectArraysClose(9, Q[0], Rq[0], kTolerance);
    825 
    826   // Now do the same but compute R with normalization.
    827   QuaternionToRotation<double>(q, Rq[0]);
    828   ExpectArraysClose(9, R[0], Rq[0], kTolerance);
    829 }
    830 
    831 
    832 TEST(Quaternion, RotatePointGivesSameAnswerAsRotationByMatrix) {
    833   // Rotation defined by a unit quaternion.
    834   double const q[4] = {
    835     0.2318160216097109,
    836     -0.0178430356832060,
    837     0.9044300776717159,
    838     -0.3576998641394597,
    839   };
    840   double const p[3] = {
    841     +0.11,
    842     -13.15,
    843     1.17,
    844   };
    845 
    846   double R[3 * 3];
    847   QuaternionToRotation(q, R);
    848 
    849   double result1[3];
    850   UnitQuaternionRotatePoint(q, p, result1);
    851 
    852   double result2[3];
    853   VectorRef(result2, 3) = ConstMatrixRef(R, 3, 3)* ConstVectorRef(p, 3);
    854   ExpectArraysClose(3, result1, result2, kTolerance);
    855 }
    856 
    857 
    858 // Verify that (a * b) * c == a * (b * c).
    859 TEST(Quaternion, MultiplicationIsAssociative) {
    860   double a[4];
    861   double b[4];
    862   double c[4];
    863   for (int i = 0; i < 4; ++i) {
    864     a[i] = 2 * RandDouble() - 1;
    865     b[i] = 2 * RandDouble() - 1;
    866     c[i] = 2 * RandDouble() - 1;
    867   }
    868 
    869   double ab[4];
    870   double ab_c[4];
    871   QuaternionProduct(a, b, ab);
    872   QuaternionProduct(ab, c, ab_c);
    873 
    874   double bc[4];
    875   double a_bc[4];
    876   QuaternionProduct(b, c, bc);
    877   QuaternionProduct(a, bc, a_bc);
    878 
    879   ASSERT_NEAR(ab_c[0], a_bc[0], kTolerance);
    880   ASSERT_NEAR(ab_c[1], a_bc[1], kTolerance);
    881   ASSERT_NEAR(ab_c[2], a_bc[2], kTolerance);
    882   ASSERT_NEAR(ab_c[3], a_bc[3], kTolerance);
    883 }
    884 
    885 
    886 TEST(AngleAxis, RotatePointGivesSameAnswerAsRotationMatrix) {
    887   double angle_axis[3];
    888   double R[9];
    889   double p[3];
    890   double angle_axis_rotated_p[3];
    891   double rotation_matrix_rotated_p[3];
    892 
    893   for (int i = 0; i < 10000; ++i) {
    894     double theta = (2.0 * i * 0.0011 - 1.0) * kPi;
    895     for (int j = 0; j < 50; ++j) {
    896       double norm2 = 0.0;
    897       for (int k = 0; k < 3; ++k) {
    898         angle_axis[k] = 2.0 * RandDouble() - 1.0;
    899         p[k] = 2.0 * RandDouble() - 1.0;
    900         norm2 = angle_axis[k] * angle_axis[k];
    901       }
    902 
    903       const double inv_norm = theta / sqrt(norm2);
    904       for (int k = 0; k < 3; ++k) {
    905         angle_axis[k] *= inv_norm;
    906       }
    907 
    908       AngleAxisToRotationMatrix(angle_axis, R);
    909       rotation_matrix_rotated_p[0] = R[0] * p[0] + R[3] * p[1] + R[6] * p[2];
    910       rotation_matrix_rotated_p[1] = R[1] * p[0] + R[4] * p[1] + R[7] * p[2];
    911       rotation_matrix_rotated_p[2] = R[2] * p[0] + R[5] * p[1] + R[8] * p[2];
    912 
    913       AngleAxisRotatePoint(angle_axis, p, angle_axis_rotated_p);
    914       for (int k = 0; k < 3; ++k) {
    915         EXPECT_NEAR(rotation_matrix_rotated_p[k],
    916                     angle_axis_rotated_p[k],
    917                     kTolerance) << "p: " << p[0]
    918                                 << " " << p[1]
    919                                 << " " << p[2]
    920                                 << " angle_axis: " << angle_axis[0]
    921                                 << " " << angle_axis[1]
    922                                 << " " << angle_axis[2];
    923       }
    924     }
    925   }
    926 }
    927 
    928 TEST(AngleAxis, NearZeroRotatePointGivesSameAnswerAsRotationMatrix) {
    929   double angle_axis[3];
    930   double R[9];
    931   double p[3];
    932   double angle_axis_rotated_p[3];
    933   double rotation_matrix_rotated_p[3];
    934 
    935   for (int i = 0; i < 10000; ++i) {
    936     double norm2 = 0.0;
    937     for (int k = 0; k < 3; ++k) {
    938       angle_axis[k] = 2.0 * RandDouble() - 1.0;
    939       p[k] = 2.0 * RandDouble() - 1.0;
    940       norm2 = angle_axis[k] * angle_axis[k];
    941     }
    942 
    943     double theta = (2.0 * i * 0.0001  - 1.0) * 1e-16;
    944     const double inv_norm = theta / sqrt(norm2);
    945     for (int k = 0; k < 3; ++k) {
    946       angle_axis[k] *= inv_norm;
    947     }
    948 
    949     AngleAxisToRotationMatrix(angle_axis, R);
    950     rotation_matrix_rotated_p[0] = R[0] * p[0] + R[3] * p[1] + R[6] * p[2];
    951     rotation_matrix_rotated_p[1] = R[1] * p[0] + R[4] * p[1] + R[7] * p[2];
    952     rotation_matrix_rotated_p[2] = R[2] * p[0] + R[5] * p[1] + R[8] * p[2];
    953 
    954     AngleAxisRotatePoint(angle_axis, p, angle_axis_rotated_p);
    955     for (int k = 0; k < 3; ++k) {
    956       EXPECT_NEAR(rotation_matrix_rotated_p[k],
    957                   angle_axis_rotated_p[k],
    958                   kTolerance) << "p: " << p[0]
    959                               << " " << p[1]
    960                               << " " << p[2]
    961                               << " angle_axis: " << angle_axis[0]
    962                               << " " << angle_axis[1]
    963                               << " " << angle_axis[2];
    964     }
    965   }
    966 }
    967 
    968 TEST(MatrixAdapter, RowMajor3x3ReturnTypeAndAccessIsCorrect) {
    969   double array[9] = { 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0 };
    970   const float const_array[9] =
    971       { 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f };
    972   MatrixAdapter<double, 3, 1> A = RowMajorAdapter3x3(array);
    973   MatrixAdapter<const float, 3, 1> B = RowMajorAdapter3x3(const_array);
    974 
    975   for (int i = 0; i < 3; ++i) {
    976     for (int j = 0; j < 3; ++j) {
    977       // The values are integers from 1 to 9, so equality tests are appropriate
    978       // even for float and double values.
    979       EXPECT_EQ(A(i, j), array[3*i+j]);
    980       EXPECT_EQ(B(i, j), const_array[3*i+j]);
    981     }
    982   }
    983 }
    984 
    985 TEST(MatrixAdapter, ColumnMajor3x3ReturnTypeAndAccessIsCorrect) {
    986   double array[9] = { 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0 };
    987   const float const_array[9] =
    988       { 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f };
    989   MatrixAdapter<double, 1, 3> A = ColumnMajorAdapter3x3(array);
    990   MatrixAdapter<const float, 1, 3> B = ColumnMajorAdapter3x3(const_array);
    991 
    992   for (int i = 0; i < 3; ++i) {
    993     for (int j = 0; j < 3; ++j) {
    994       // The values are integers from 1 to 9, so equality tests are
    995       // appropriate even for float and double values.
    996       EXPECT_EQ(A(i, j), array[3*j+i]);
    997       EXPECT_EQ(B(i, j), const_array[3*j+i]);
    998     }
    999   }
   1000 }
   1001 
   1002 TEST(MatrixAdapter, RowMajor2x4IsCorrect) {
   1003   const int expected[8] = { 1, 2, 3, 4, 5, 6, 7, 8 };
   1004   int array[8];
   1005   MatrixAdapter<int, 4, 1> M(array);
   1006   M(0, 0) = 1; M(0, 1) = 2; M(0, 2) = 3; M(0, 3) = 4;
   1007   M(1, 0) = 5; M(1, 1) = 6; M(1, 2) = 7; M(1, 3) = 8;
   1008   for (int k = 0; k < 8; ++k) {
   1009     EXPECT_EQ(array[k], expected[k]);
   1010   }
   1011 }
   1012 
   1013 TEST(MatrixAdapter, ColumnMajor2x4IsCorrect) {
   1014   const int expected[8] = { 1, 5, 2, 6, 3, 7, 4, 8 };
   1015   int array[8];
   1016   MatrixAdapter<int, 1, 2> M(array);
   1017   M(0, 0) = 1; M(0, 1) = 2; M(0, 2) = 3; M(0, 3) = 4;
   1018   M(1, 0) = 5; M(1, 1) = 6; M(1, 2) = 7; M(1, 3) = 8;
   1019   for (int k = 0; k < 8; ++k) {
   1020     EXPECT_EQ(array[k], expected[k]);
   1021   }
   1022 }
   1023 
   1024 }  // namespace internal
   1025 }  // namespace ceres
   1026