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 // Takes a bunch of random axis/angle values near zero, converts them
    552 // to rotation matrices, and back again.
    553 TEST(Rotation, AngleAxisToRotationMatrixAndBackNearZero) {
    554   srand(5);
    555   for (int i = 0; i < kNumTrials; i++) {
    556     double axis_angle[3];
    557     // Make an axis by choosing three random numbers in [-1, 1) and
    558     // normalizing.
    559     double norm = 0;
    560     for (int i = 0; i < 3; i++) {
    561       axis_angle[i] = RandDouble() * 2 - 1;
    562       norm += axis_angle[i] * axis_angle[i];
    563     }
    564     norm = sqrt(norm);
    565 
    566     // Tiny theta.
    567     double theta = 1e-16 * (kPi * 2 * RandDouble() - kPi);
    568     for (int i = 0; i < 3; i++) {
    569       axis_angle[i] = axis_angle[i] * theta / norm;
    570     }
    571 
    572     double matrix[9];
    573     double round_trip[3];
    574     AngleAxisToRotationMatrix(axis_angle, matrix);
    575     ASSERT_THAT(matrix, IsOrthonormal());
    576     RotationMatrixToAngleAxis(matrix, round_trip);
    577 
    578     for (int i = 0; i < 3; ++i) {
    579       EXPECT_NEAR(round_trip[i], axis_angle[i],
    580                   std::numeric_limits<double>::epsilon());
    581     }
    582   }
    583 }
    584 
    585 
    586 // Transposes a 3x3 matrix.
    587 static void Transpose3x3(double m[9]) {
    588   std::swap(m[1], m[3]);
    589   std::swap(m[2], m[6]);
    590   std::swap(m[5], m[7]);
    591 }
    592 
    593 // Convert Euler angles from radians to degrees.
    594 static void ToDegrees(double ea[3]) {
    595   for (int i = 0; i < 3; ++i)
    596     ea[i] *= 180.0 / kPi;
    597 }
    598 
    599 // Compare the 3x3 rotation matrices produced by the axis-angle
    600 // rotation 'aa' and the Euler angle rotation 'ea' (in radians).
    601 static void CompareEulerToAngleAxis(double aa[3], double ea[3]) {
    602   double aa_matrix[9];
    603   AngleAxisToRotationMatrix(aa, aa_matrix);
    604   Transpose3x3(aa_matrix);  // Column to row major order.
    605 
    606   double ea_matrix[9];
    607   ToDegrees(ea);  // Radians to degrees.
    608   const int kRowStride = 3;
    609   EulerAnglesToRotationMatrix(ea, kRowStride, ea_matrix);
    610 
    611   EXPECT_THAT(aa_matrix, IsOrthonormal());
    612   EXPECT_THAT(ea_matrix, IsOrthonormal());
    613   EXPECT_THAT(ea_matrix, IsNear3x3Matrix(aa_matrix));
    614 }
    615 
    616 // Test with rotation axis along the x/y/z axes.
    617 // Also test zero rotation.
    618 TEST(EulerAnglesToRotationMatrix, OnAxis) {
    619   int n_tests = 0;
    620   for (double x = -1.0; x <= 1.0; x += 1.0) {
    621     for (double y = -1.0; y <= 1.0; y += 1.0) {
    622       for (double z = -1.0; z <= 1.0; z += 1.0) {
    623         if ((x != 0) + (y != 0) + (z != 0) > 1)
    624           continue;
    625         double axis_angle[3] = {x, y, z};
    626         double euler_angles[3] = {x, y, z};
    627         CompareEulerToAngleAxis(axis_angle, euler_angles);
    628         ++n_tests;
    629       }
    630     }
    631   }
    632   CHECK_EQ(7, n_tests);
    633 }
    634 
    635 // Test that a random rotation produces an orthonormal rotation
    636 // matrix.
    637 TEST(EulerAnglesToRotationMatrix, IsOrthonormal) {
    638   srand(5);
    639   for (int trial = 0; trial < kNumTrials; ++trial) {
    640     double ea[3];
    641     for (int i = 0; i < 3; ++i)
    642       ea[i] = 360.0 * (RandDouble() * 2.0 - 1.0);
    643     double ea_matrix[9];
    644     ToDegrees(ea);  // Radians to degrees.
    645     EulerAnglesToRotationMatrix(ea, 3, ea_matrix);
    646     EXPECT_THAT(ea_matrix, IsOrthonormal());
    647   }
    648 }
    649 
    650 // Tests using Jets for specific behavior involving auto differentiation
    651 // near singularity points.
    652 
    653 typedef Jet<double, 3> J3;
    654 typedef Jet<double, 4> J4;
    655 
    656 J3 MakeJ3(double a, double v0, double v1, double v2) {
    657   J3 j;
    658   j.a = a;
    659   j.v[0] = v0;
    660   j.v[1] = v1;
    661   j.v[2] = v2;
    662   return j;
    663 }
    664 
    665 J4 MakeJ4(double a, double v0, double v1, double v2, double v3) {
    666   J4 j;
    667   j.a = a;
    668   j.v[0] = v0;
    669   j.v[1] = v1;
    670   j.v[2] = v2;
    671   j.v[3] = v3;
    672   return j;
    673 }
    674 
    675 
    676 bool IsClose(double x, double y) {
    677   EXPECT_FALSE(IsNaN(x));
    678   EXPECT_FALSE(IsNaN(y));
    679   double absdiff = fabs(x - y);
    680   if (x == 0 || y == 0) {
    681     return absdiff <= kTolerance;
    682   }
    683   double reldiff = absdiff / max(fabs(x), fabs(y));
    684   return reldiff <= kTolerance;
    685 }
    686 
    687 template <int N>
    688 bool IsClose(const Jet<double, N> &x, const Jet<double, N> &y) {
    689   if (IsClose(x.a, y.a)) {
    690     for (int i = 0; i < N; i++) {
    691       if (!IsClose(x.v[i], y.v[i])) {
    692         return false;
    693       }
    694     }
    695   }
    696   return true;
    697 }
    698 
    699 template <int M, int N>
    700 void ExpectJetArraysClose(const Jet<double, N> *x, const Jet<double, N> *y) {
    701   for (int i = 0; i < M; i++) {
    702     if (!IsClose(x[i], y[i])) {
    703       LOG(ERROR) << "Jet " << i << "/" << M << " not equal";
    704       LOG(ERROR) << "x[" << i << "]: " << x[i];
    705       LOG(ERROR) << "y[" << i << "]: " << y[i];
    706       Jet<double, N> d, zero;
    707       d.a = y[i].a - x[i].a;
    708       for (int j = 0; j < N; j++) {
    709         d.v[j] = y[i].v[j] - x[i].v[j];
    710       }
    711       LOG(ERROR) << "diff: " << d;
    712       EXPECT_TRUE(IsClose(x[i], y[i]));
    713     }
    714   }
    715 }
    716 
    717 // Log-10 of a value well below machine precision.
    718 static const int kSmallTinyCutoff =
    719     static_cast<int>(2 * log(numeric_limits<double>::epsilon())/log(10.0));
    720 
    721 // Log-10 of a value just below values representable by double.
    722 static const int kTinyZeroLimit   =
    723     static_cast<int>(1 + log(numeric_limits<double>::min())/log(10.0));
    724 
    725 // Test that exact conversion works for small angles when jets are used.
    726 TEST(Rotation, SmallAngleAxisToQuaternionForJets) {
    727   // Examine small x rotations that are still large enough
    728   // to be well within the range represented by doubles.
    729   for (int i = -2; i >= kSmallTinyCutoff; i--) {
    730     double theta = pow(10.0, i);
    731     J3 axis_angle[3] = { J3(theta, 0), J3(0, 1), J3(0, 2) };
    732     J3 quaternion[4];
    733     J3 expected[4] = {
    734         MakeJ3(cos(theta/2), -sin(theta/2)/2, 0, 0),
    735         MakeJ3(sin(theta/2), cos(theta/2)/2, 0, 0),
    736         MakeJ3(0, 0, sin(theta/2)/theta, 0),
    737         MakeJ3(0, 0, 0, sin(theta/2)/theta),
    738     };
    739     AngleAxisToQuaternion(axis_angle, quaternion);
    740     ExpectJetArraysClose<4, 3>(quaternion, expected);
    741   }
    742 }
    743 
    744 
    745 // Test that conversion works for very small angles when jets are used.
    746 TEST(Rotation, TinyAngleAxisToQuaternionForJets) {
    747   // Examine tiny x rotations that extend all the way to where
    748   // underflow occurs.
    749   for (int i = kSmallTinyCutoff; i >= kTinyZeroLimit; i--) {
    750     double theta = pow(10.0, i);
    751     J3 axis_angle[3] = { J3(theta, 0), J3(0, 1), J3(0, 2) };
    752     J3 quaternion[4];
    753     // To avoid loss of precision in the test itself,
    754     // a finite expansion is used here, which will
    755     // be exact up to machine precision for the test values used.
    756     J3 expected[4] = {
    757         MakeJ3(1.0, 0, 0, 0),
    758         MakeJ3(0, 0.5, 0, 0),
    759         MakeJ3(0, 0, 0.5, 0),
    760         MakeJ3(0, 0, 0, 0.5),
    761     };
    762     AngleAxisToQuaternion(axis_angle, quaternion);
    763     ExpectJetArraysClose<4, 3>(quaternion, expected);
    764   }
    765 }
    766 
    767 // Test that derivatives are correct for zero rotation.
    768 TEST(Rotation, ZeroAngleAxisToQuaternionForJets) {
    769   J3 axis_angle[3] = { J3(0, 0), J3(0, 1), J3(0, 2) };
    770   J3 quaternion[4];
    771   J3 expected[4] = {
    772       MakeJ3(1.0, 0, 0, 0),
    773       MakeJ3(0, 0.5, 0, 0),
    774       MakeJ3(0, 0, 0.5, 0),
    775       MakeJ3(0, 0, 0, 0.5),
    776   };
    777   AngleAxisToQuaternion(axis_angle, quaternion);
    778   ExpectJetArraysClose<4, 3>(quaternion, expected);
    779 }
    780 
    781 // Test that exact conversion works for small angles.
    782 TEST(Rotation, SmallQuaternionToAngleAxisForJets) {
    783   // Examine small x rotations that are still large enough
    784   // to be well within the range represented by doubles.
    785   for (int i = -2; i >= kSmallTinyCutoff; i--) {
    786     double theta = pow(10.0, i);
    787     double s = sin(theta);
    788     double c = cos(theta);
    789     J4 quaternion[4] = { J4(c, 0), J4(s, 1), J4(0, 2), J4(0, 3) };
    790     J4 axis_angle[3];
    791     J4 expected[3] = {
    792         MakeJ4(s, -2*theta, 2*theta*c, 0, 0),
    793         MakeJ4(0, 0, 0, 2*theta/s, 0),
    794         MakeJ4(0, 0, 0, 0, 2*theta/s),
    795     };
    796     QuaternionToAngleAxis(quaternion, axis_angle);
    797     ExpectJetArraysClose<3, 4>(axis_angle, expected);
    798   }
    799 }
    800 
    801 // Test that conversion works for very small angles.
    802 TEST(Rotation, TinyQuaternionToAngleAxisForJets) {
    803   // Examine tiny x rotations that extend all the way to where
    804   // underflow occurs.
    805   for (int i = kSmallTinyCutoff; i >= kTinyZeroLimit; i--) {
    806     double theta = pow(10.0, i);
    807     double s = sin(theta);
    808     double c = cos(theta);
    809     J4 quaternion[4] = { J4(c, 0), J4(s, 1), J4(0, 2), J4(0, 3) };
    810     J4 axis_angle[3];
    811     // To avoid loss of precision in the test itself,
    812     // a finite expansion is used here, which will
    813     // be exact up to machine precision for the test values used.
    814     J4 expected[3] = {
    815         MakeJ4(theta, -2*theta, 2.0, 0, 0),
    816         MakeJ4(0, 0, 0, 2.0, 0),
    817         MakeJ4(0, 0, 0, 0, 2.0),
    818     };
    819     QuaternionToAngleAxis(quaternion, axis_angle);
    820     ExpectJetArraysClose<3, 4>(axis_angle, expected);
    821   }
    822 }
    823 
    824 // Test that conversion works for no rotation.
    825 TEST(Rotation, ZeroQuaternionToAngleAxisForJets) {
    826   J4 quaternion[4] = { J4(1, 0), J4(0, 1), J4(0, 2), J4(0, 3) };
    827   J4 axis_angle[3];
    828   J4 expected[3] = {
    829       MakeJ4(0, 0, 2.0, 0, 0),
    830       MakeJ4(0, 0, 0, 2.0, 0),
    831       MakeJ4(0, 0, 0, 0, 2.0),
    832   };
    833   QuaternionToAngleAxis(quaternion, axis_angle);
    834   ExpectJetArraysClose<3, 4>(axis_angle, expected);
    835 }
    836 
    837 TEST(Quaternion, RotatePointGivesSameAnswerAsRotationByMatrixCanned) {
    838   // Canned data generated in octave.
    839   double const q[4] = {
    840     +0.1956830471754074,
    841     -0.0150618562474847,
    842     +0.7634572982788086,
    843     -0.3019454777240753,
    844   };
    845   double const Q[3][3] = {  // Scaled rotation matrix.
    846     { -0.6355194033477252,  0.0951730541682254,  0.3078870197911186 },
    847     { -0.1411693904792992,  0.5297609702153905, -0.4551502574482019 },
    848     { -0.2896955822708862, -0.4669396571547050, -0.4536309793389248 },
    849   };
    850   double const R[3][3] = {  // With unit rows and columns.
    851     { -0.8918859164053080,  0.1335655625725649,  0.4320876677394745 },
    852     { -0.1981166751680096,  0.7434648665444399, -0.6387564287225856 },
    853     { -0.4065578619806013, -0.6553016349046693, -0.6366242786393164 },
    854   };
    855 
    856   // Compute R from q and compare to known answer.
    857   double Rq[3][3];
    858   QuaternionToScaledRotation<double>(q, Rq[0]);
    859   ExpectArraysClose(9, Q[0], Rq[0], kTolerance);
    860 
    861   // Now do the same but compute R with normalization.
    862   QuaternionToRotation<double>(q, Rq[0]);
    863   ExpectArraysClose(9, R[0], Rq[0], kTolerance);
    864 }
    865 
    866 
    867 TEST(Quaternion, RotatePointGivesSameAnswerAsRotationByMatrix) {
    868   // Rotation defined by a unit quaternion.
    869   double const q[4] = {
    870     0.2318160216097109,
    871     -0.0178430356832060,
    872     0.9044300776717159,
    873     -0.3576998641394597,
    874   };
    875   double const p[3] = {
    876     +0.11,
    877     -13.15,
    878     1.17,
    879   };
    880 
    881   double R[3 * 3];
    882   QuaternionToRotation(q, R);
    883 
    884   double result1[3];
    885   UnitQuaternionRotatePoint(q, p, result1);
    886 
    887   double result2[3];
    888   VectorRef(result2, 3) = ConstMatrixRef(R, 3, 3)* ConstVectorRef(p, 3);
    889   ExpectArraysClose(3, result1, result2, kTolerance);
    890 }
    891 
    892 
    893 // Verify that (a * b) * c == a * (b * c).
    894 TEST(Quaternion, MultiplicationIsAssociative) {
    895   double a[4];
    896   double b[4];
    897   double c[4];
    898   for (int i = 0; i < 4; ++i) {
    899     a[i] = 2 * RandDouble() - 1;
    900     b[i] = 2 * RandDouble() - 1;
    901     c[i] = 2 * RandDouble() - 1;
    902   }
    903 
    904   double ab[4];
    905   double ab_c[4];
    906   QuaternionProduct(a, b, ab);
    907   QuaternionProduct(ab, c, ab_c);
    908 
    909   double bc[4];
    910   double a_bc[4];
    911   QuaternionProduct(b, c, bc);
    912   QuaternionProduct(a, bc, a_bc);
    913 
    914   ASSERT_NEAR(ab_c[0], a_bc[0], kTolerance);
    915   ASSERT_NEAR(ab_c[1], a_bc[1], kTolerance);
    916   ASSERT_NEAR(ab_c[2], a_bc[2], kTolerance);
    917   ASSERT_NEAR(ab_c[3], a_bc[3], kTolerance);
    918 }
    919 
    920 
    921 TEST(AngleAxis, RotatePointGivesSameAnswerAsRotationMatrix) {
    922   double angle_axis[3];
    923   double R[9];
    924   double p[3];
    925   double angle_axis_rotated_p[3];
    926   double rotation_matrix_rotated_p[3];
    927 
    928   for (int i = 0; i < 10000; ++i) {
    929     double theta = (2.0 * i * 0.0011 - 1.0) * kPi;
    930     for (int j = 0; j < 50; ++j) {
    931       double norm2 = 0.0;
    932       for (int k = 0; k < 3; ++k) {
    933         angle_axis[k] = 2.0 * RandDouble() - 1.0;
    934         p[k] = 2.0 * RandDouble() - 1.0;
    935         norm2 = angle_axis[k] * angle_axis[k];
    936       }
    937 
    938       const double inv_norm = theta / sqrt(norm2);
    939       for (int k = 0; k < 3; ++k) {
    940         angle_axis[k] *= inv_norm;
    941       }
    942 
    943       AngleAxisToRotationMatrix(angle_axis, R);
    944       rotation_matrix_rotated_p[0] = R[0] * p[0] + R[3] * p[1] + R[6] * p[2];
    945       rotation_matrix_rotated_p[1] = R[1] * p[0] + R[4] * p[1] + R[7] * p[2];
    946       rotation_matrix_rotated_p[2] = R[2] * p[0] + R[5] * p[1] + R[8] * p[2];
    947 
    948       AngleAxisRotatePoint(angle_axis, p, angle_axis_rotated_p);
    949       for (int k = 0; k < 3; ++k) {
    950         EXPECT_NEAR(rotation_matrix_rotated_p[k],
    951                     angle_axis_rotated_p[k],
    952                     kTolerance) << "p: " << p[0]
    953                                 << " " << p[1]
    954                                 << " " << p[2]
    955                                 << " angle_axis: " << angle_axis[0]
    956                                 << " " << angle_axis[1]
    957                                 << " " << angle_axis[2];
    958       }
    959     }
    960   }
    961 }
    962 
    963 TEST(AngleAxis, NearZeroRotatePointGivesSameAnswerAsRotationMatrix) {
    964   double angle_axis[3];
    965   double R[9];
    966   double p[3];
    967   double angle_axis_rotated_p[3];
    968   double rotation_matrix_rotated_p[3];
    969 
    970   for (int i = 0; i < 10000; ++i) {
    971     double norm2 = 0.0;
    972     for (int k = 0; k < 3; ++k) {
    973       angle_axis[k] = 2.0 * RandDouble() - 1.0;
    974       p[k] = 2.0 * RandDouble() - 1.0;
    975       norm2 = angle_axis[k] * angle_axis[k];
    976     }
    977 
    978     double theta = (2.0 * i * 0.0001  - 1.0) * 1e-16;
    979     const double inv_norm = theta / sqrt(norm2);
    980     for (int k = 0; k < 3; ++k) {
    981       angle_axis[k] *= inv_norm;
    982     }
    983 
    984     AngleAxisToRotationMatrix(angle_axis, R);
    985     rotation_matrix_rotated_p[0] = R[0] * p[0] + R[3] * p[1] + R[6] * p[2];
    986     rotation_matrix_rotated_p[1] = R[1] * p[0] + R[4] * p[1] + R[7] * p[2];
    987     rotation_matrix_rotated_p[2] = R[2] * p[0] + R[5] * p[1] + R[8] * p[2];
    988 
    989     AngleAxisRotatePoint(angle_axis, p, angle_axis_rotated_p);
    990     for (int k = 0; k < 3; ++k) {
    991       EXPECT_NEAR(rotation_matrix_rotated_p[k],
    992                   angle_axis_rotated_p[k],
    993                   kTolerance) << "p: " << p[0]
    994                               << " " << p[1]
    995                               << " " << p[2]
    996                               << " angle_axis: " << angle_axis[0]
    997                               << " " << angle_axis[1]
    998                               << " " << angle_axis[2];
    999     }
   1000   }
   1001 }
   1002 
   1003 TEST(MatrixAdapter, RowMajor3x3ReturnTypeAndAccessIsCorrect) {
   1004   double array[9] = { 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0 };
   1005   const float const_array[9] =
   1006       { 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f };
   1007   MatrixAdapter<double, 3, 1> A = RowMajorAdapter3x3(array);
   1008   MatrixAdapter<const float, 3, 1> B = RowMajorAdapter3x3(const_array);
   1009 
   1010   for (int i = 0; i < 3; ++i) {
   1011     for (int j = 0; j < 3; ++j) {
   1012       // The values are integers from 1 to 9, so equality tests are appropriate
   1013       // even for float and double values.
   1014       EXPECT_EQ(A(i, j), array[3*i+j]);
   1015       EXPECT_EQ(B(i, j), const_array[3*i+j]);
   1016     }
   1017   }
   1018 }
   1019 
   1020 TEST(MatrixAdapter, ColumnMajor3x3ReturnTypeAndAccessIsCorrect) {
   1021   double array[9] = { 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0 };
   1022   const float const_array[9] =
   1023       { 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f };
   1024   MatrixAdapter<double, 1, 3> A = ColumnMajorAdapter3x3(array);
   1025   MatrixAdapter<const float, 1, 3> B = ColumnMajorAdapter3x3(const_array);
   1026 
   1027   for (int i = 0; i < 3; ++i) {
   1028     for (int j = 0; j < 3; ++j) {
   1029       // The values are integers from 1 to 9, so equality tests are
   1030       // appropriate even for float and double values.
   1031       EXPECT_EQ(A(i, j), array[3*j+i]);
   1032       EXPECT_EQ(B(i, j), const_array[3*j+i]);
   1033     }
   1034   }
   1035 }
   1036 
   1037 TEST(MatrixAdapter, RowMajor2x4IsCorrect) {
   1038   const int expected[8] = { 1, 2, 3, 4, 5, 6, 7, 8 };
   1039   int array[8];
   1040   MatrixAdapter<int, 4, 1> M(array);
   1041   M(0, 0) = 1; M(0, 1) = 2; M(0, 2) = 3; M(0, 3) = 4;
   1042   M(1, 0) = 5; M(1, 1) = 6; M(1, 2) = 7; M(1, 3) = 8;
   1043   for (int k = 0; k < 8; ++k) {
   1044     EXPECT_EQ(array[k], expected[k]);
   1045   }
   1046 }
   1047 
   1048 TEST(MatrixAdapter, ColumnMajor2x4IsCorrect) {
   1049   const int expected[8] = { 1, 5, 2, 6, 3, 7, 4, 8 };
   1050   int array[8];
   1051   MatrixAdapter<int, 1, 2> M(array);
   1052   M(0, 0) = 1; M(0, 1) = 2; M(0, 2) = 3; M(0, 3) = 4;
   1053   M(1, 0) = 5; M(1, 1) = 6; M(1, 2) = 7; M(1, 3) = 8;
   1054   for (int k = 0; k < 8; ++k) {
   1055     EXPECT_EQ(array[k], expected[k]);
   1056   }
   1057 }
   1058 
   1059 }  // namespace internal
   1060 }  // namespace ceres
   1061