g2o
test_slam3d_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 <cstdio>
29 
31 #include "g2o/stuff/macros.h"
32 #include "edge_se3.h"
33 #include "edge_se3_prior.h"
34 
35 using namespace std;
36 using namespace g2o;
37 using namespace Eigen;
38 
40 {
41  Vector3D rotAxisAngle = Vector3D::Random();
42  rotAxisAngle += Vector3D::Random();
43  Eigen::AngleAxisd rotation(rotAxisAngle.norm(), rotAxisAngle.normalized());
44  Isometry3D result = (Isometry3D)rotation.toRotationMatrix();
45  result.translation() = Vector3D::Random();
46  return result;
47 }
48 
49 int main(int , char** )
50 {
51  if (0) {
53  ParameterSE3Offset* offsetParam = new ParameterSE3Offset;
54  offsetParam->setId(0);
55  graph.addParameter(offsetParam);
56 
57  Isometry3D zeroPose = Isometry3D::Identity();
58  VertexSE3* v1 = new VertexSE3;
59  v1->setId(0);
60  graph.addVertex(v1);
61  OptimizableGraph::VertexSet auxSet;
62  EdgeSE3Prior* priorEdge = new EdgeSE3Prior;
63  priorEdge->setVertex(0, v1);
64  priorEdge->setMeasurement(randomIsometry3d());
65  priorEdge->setParameterId(0, 0);
66  cout << PVAR(priorEdge->measurement().matrix()) << endl;
67  graph.addEdge(priorEdge);
68 
69  Eigen::Matrix<double,6,6,Eigen::ColMajor> information = Eigen::Matrix<double,6,6,Eigen::ColMajor>::Identity();
70 
71  cout << "Full information" << endl;
72  v1->setEstimate(zeroPose);
73  priorEdge->setInformation(information);
74  priorEdge->initialEstimate(auxSet, 0);
75  cout << PVAR(priorEdge->chi2()) << endl;
76  cout << v1->estimate().matrix() << endl << endl;
77  priorEdge->computeError();
78 
79  cout << "Only translation" << endl;
80  v1->setEstimate(zeroPose);
81  information.block<3,3>(0,0) = Matrix3D::Identity();
82  information.block<3,3>(3,3) = Matrix3D::Zero();
83  priorEdge->setInformation(information);
84  priorEdge->initialEstimate(auxSet, 0);
85  cout << PVAR(priorEdge->chi2()) << endl;
86  cout << v1->estimate().matrix() << endl << endl;
87  priorEdge->computeError();
88 
89  cout << "Only rotation" << endl;
90  v1->setEstimate(zeroPose);
91  information.block<3,3>(0,0) = Matrix3D::Zero();
92  information.block<3,3>(3,3) = Matrix3D::Identity();
93  priorEdge->setInformation(information);
94  priorEdge->initialEstimate(auxSet, 0);
95  cout << PVAR(priorEdge->chi2()) << endl;
96  cout << v1->estimate().matrix() << endl << endl;
97  priorEdge->computeError();
98  return 0;
99  }
100 
101  VertexSE3 v1;
102  v1.setId(0);
103 
104  VertexSE3 v2;
105  v2.setId(1);
106 
107  EdgeSE3 e;
108  e.setVertex(0, &v1);
109  e.setVertex(1, &v2);
110  e.setInformation(Eigen::Matrix<double,6,6,Eigen::ColMajor>::Identity());
111 
112  JacobianWorkspace jacobianWorkspace;
113  JacobianWorkspace numericJacobianWorkspace;
114  numericJacobianWorkspace.updateSize(&e);
115  numericJacobianWorkspace.allocate();
116 
117  for (int k = 0; k < 100000; ++k) {
118 
122 
123  // calling the analytic Jacobian but writing to the numeric workspace
124  e.BaseBinaryEdge<6, Isometry3D, VertexSE3, VertexSE3>::linearizeOplus(numericJacobianWorkspace);
125  // copy result into analytic workspace
126  jacobianWorkspace = numericJacobianWorkspace;
127 
128  // compute the numeric Jacobian into the numericJacobianWorkspace workspace as setup by the previous call
129  e.BaseBinaryEdge<6, Isometry3D, VertexSE3, VertexSE3>::linearizeOplus();
130 
131  // compare the two Jacobians
132  const double allowedDifference = 1e-6;
133  for (int i = 0; i < 2; ++i) {
134  double* n = numericJacobianWorkspace.workspaceForVertex(i);
135  double* a = jacobianWorkspace.workspaceForVertex(i);
136  for (int j = 0; j < 6*6; ++j) {
137  double d = fabs(n[j] - a[j]);
138  if (d > allowedDifference) {
139  cerr << "\ndetected difference in the Jacobians " << d << endl;
140  cerr << PVAR(v1.estimate().matrix()) << endl << endl;
141  cerr << PVAR(v2.estimate().matrix()) << endl << endl;
142  cerr << PVAR(e.measurement().matrix()) << endl << endl;
143  return 1;
144  }
145  }
146  }
147  cerr << "+";
148 
149  }
150  return 0;
151 }
Isometry3D randomIsometry3d()
Eigen::Matrix< double, 3, 1, Eigen::ColMajor > Vector3D
Definition: eigen_types.h:46
double * workspaceForVertex(int vertexIndex)
virtual double chi2() const
computes the chi2 based on the cached error value, only valid after computeError has been called...
Definition: base_edge.h:56
void setVertex(size_t i, Vertex *v)
Definition: hyper_graph.h:194
void setId(int id_)
Definition: parameter.cpp:35
Edge between two 3D pose vertices.
Definition: edge_se3.h:18
virtual void setId(int id)
sets the id of the node in the graph be sure that the graph keeps consistent after changing the id ...
bool setParameterId(int argNum, int paramId)
int main(int, char **)
virtual void setMeasurement(const Isometry3D &m)
Definition: edge_se3.h:27
void updateSize(const HyperGraph::Edge *e)
EIGEN_STRONG_INLINE void setInformation(const InformationType &information)
Definition: base_edge.h:69
Eigen::Transform< double, 3, Eigen::Isometry, Eigen::ColMajor > Isometry3D
Definition: eigen_types.h:66
bool addParameter(Parameter *p)
void setEstimate(const EstimateType &et)
set the estimate for the vertex also calls updateCache()
Definition: base_vertex.h:101
const EstimateType & estimate() const
return the current estimate of the vertex
Definition: base_vertex.h:99
3D pose Vertex, represented as an Isometry3D
Definition: vertex_se3.h:50
virtual void setMeasurement(const Isometry3D &m)
provide memory workspace for computing the Jacobians
virtual bool addEdge(HyperGraph::Edge *e)
virtual bool addVertex(HyperGraph::Vertex *v, Data *userData)
prior for an SE3 element
Protocol The SLAM executable accepts such as solving the and retrieving or vertices in the graph
Definition: protocol.txt:7
EIGEN_STRONG_INLINE const Measurement & measurement() const
accessor functions for the measurement represented by the edge
Definition: base_edge.h:75
virtual void initialEstimate(const OptimizableGraph::VertexSet &from, OptimizableGraph::Vertex *to)