g2o
test_mat2quat_jacobian.cpp
Go to the documentation of this file.
1 // g2o - General Graph Optimization
2 // Copyright (C) 2011 R. Kuemmerle, G. Grisetti, W. Burgard
3 // All rights reserved.
4 //
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions are
7 // met:
8 //
9 // * Redistributions of source code must retain the above copyright notice,
10 // this list of conditions and the following disclaimer.
11 // * Redistributions in binary form must reproduce the above copyright
12 // notice, this list of conditions and the following disclaimer in the
13 // documentation and/or other materials provided with the distribution.
14 //
15 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
16 // IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
17 // TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
18 // PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
19 // HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
21 // TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
22 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
23 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
24 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 
27 #include <iostream>
28 #include "dquat2mat.h"
29 #include "isometry3d_mappings.h"
30 #include "g2o/stuff/macros.h"
31 #include "EXTERNAL/ceres/autodiff.h"
32 
33 #include <cstdio>
34 
35 using namespace std;
36 using namespace g2o;
37 using namespace g2o::internal;
38 using namespace Eigen;
39 
44 {
45  template<typename T>
46  bool operator()(const T* rotMatSerialized, T* quaternion) const
47  {
48  typename Eigen::Matrix<T, 3, 3, Eigen::ColMajor>::ConstMapType R(rotMatSerialized);
49 
50  T t = R.trace();
51  if (t > T(0)) {
52  cerr << "w";
53  t = sqrt(t + T(1));
54  //T w = T(0.5)*t;
55  t = T(0.5)/t;
56  quaternion[0] = (R(2,1) - R(1,2)) * t;
57  quaternion[1] = (R(0,2) - R(2,0)) * t;
58  quaternion[2] = (R(1,0) - R(0,1)) * t;
59  } else {
60  int i = 0;
61  if (R(1,1) > R(0,0))
62  i = 1;
63  if (R(2,2) > R(i,i))
64  i = 2;
65  int j = (i+1)%3;
66  int k = (j+1)%3;
67  cerr << i;
68 
69  t = sqrt(R(i,i) - R(j,j) - R(k,k) + T(1.0));
70  quaternion[i] = T(0.5) * t;
71  t = T(0.5)/t;
72  quaternion[j] = (R(j,i) + R(i,j)) * t;
73  quaternion[k] = (R(k,i) + R(i,k)) * t;
74  T w = (R(k,j) - R(j,k)) * t;
75  // normalize to our manifold, such that w is positive
76  if (w < 0.) {
77  //cerr << " normalizing w > 0 ";
78  for (int l = 0; l < 3; ++l)
79  quaternion[l] *= T(-1);
80  }
81  }
82  return true;
83  }
84 };
85 
86 int main(int , char** )
87 {
88  for (int k = 0; k < 100000; ++k) {
89 
90  // create a random rotation matrix by sampling a random 3d vector
91  // that will be used in axis-angle representation to create the matrix
92  Vector3D rotAxisAngle = Vector3D::Random();
93  rotAxisAngle += Vector3D::Random();
94  Eigen::AngleAxisd rotation(rotAxisAngle.norm(), rotAxisAngle.normalized());
95  Matrix3D Re = rotation.toRotationMatrix();
96 
97  // our analytic function which we want to evaluate
98  Matrix<double, 3, 9, Eigen::ColMajor> dq_dR;
99  compute_dq_dR (dq_dR,
100  Re(0,0),Re(1,0),Re(2,0),
101  Re(0,1),Re(1,1),Re(2,1),
102  Re(0,2),Re(1,2),Re(2,2));
103 
104  // compute the Jacobian using AD
105  Matrix<double, 3, 9, Eigen::RowMajor> dq_dR_AD;
106  typedef ceres::internal::AutoDiff<RotationMatrix2QuaternionManifold, double, 9> AutoDiff_Dq_DR;
107  double *parameters[] = { Re.data() };
108  double *jacobians[] = { dq_dR_AD.data() };
109  double value[3];
111  AutoDiff_Dq_DR::Differentiate(rot2quat, parameters, 3, value, jacobians);
112 
113  // compare the two Jacobians
114  const double allowedDifference = 1e-6;
115  for (int i = 0; i < dq_dR.rows(); ++i) {
116  for (int j = 0; j < dq_dR.cols(); ++j) {
117  double d = fabs(dq_dR_AD(i,j) - dq_dR(i,j));
118  if (d > allowedDifference) {
119  cerr << "\ndetected difference in the Jacobians" << endl;
120  cerr << PVAR(Re) << endl << endl;
121  cerr << PVAR(dq_dR_AD) << endl << endl;
122  cerr << PVAR(dq_dR) << endl << endl;
123  return 1;
124  }
125  }
126  }
127  cerr << "+";
128 
129  }
130  return 0;
131 }
int main(int, char **)
Eigen::Matrix< double, 3, 1, Eigen::ColMajor > Vector3D
Definition: eigen_types.h:46
void compute_dq_dR(Eigen::Matrix< double, 3, 9, Eigen::ColMajor > &dq_dR, const double &r11, const double &r21, const double &r31, const double &r12, const double &r22, const double &r32, const double &r13, const double &r23, const double &r33)
Definition: dquat2mat.cpp:42
Eigen::Matrix< double, 3, 3, Eigen::ColMajor > Matrix3D
Definition: eigen_types.h:61
Functor used to compute the Jacobian via AD.
bool operator()(const T *rotMatSerialized, T *quaternion) const