g2o
base_binary_edge.hpp
Go to the documentation of this file.
1 // g2o - General Graph Optimization
2 // Copyright (C) 2011 R. Kuemmerle, G. Grisetti, H. Strasdat, 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 template <int D, typename E, typename VertexXiType, typename VertexXjType>
28 OptimizableGraph::Vertex* BaseBinaryEdge<D, E, VertexXiType, VertexXjType>::createFrom(){
29  return createVertex(0);
30 }
31 
32 template <int D, typename E, typename VertexXiType, typename VertexXjType>
33 OptimizableGraph::Vertex* BaseBinaryEdge<D, E, VertexXiType, VertexXjType>::createTo(){
34  return createVertex(1);
35 }
36 
37 template <int D, typename E, typename VertexXiType, typename VertexXjType>
38 OptimizableGraph::Vertex* BaseBinaryEdge<D, E, VertexXiType, VertexXjType>::createVertex(int i){
39  switch(i) {
40  case 0: return new VertexXiType();
41  case 1: return new VertexXjType();
42  default: return 0;
43  }
44 }
45 
46 
47 template <int D, typename E, typename VertexXiType, typename VertexXjType>
48 void BaseBinaryEdge<D, E, VertexXiType, VertexXjType>::resize(size_t size)
49 {
50  if (size != 2) {
51  std::cerr << "WARNING, attempting to resize binary edge " << BaseEdge<D, E>::id() << " to " << size << std::endl;
52  }
53  BaseEdge<D, E>::resize(size);
54 }
55 
56 template <int D, typename E, typename VertexXiType, typename VertexXjType>
57 bool BaseBinaryEdge<D, E, VertexXiType, VertexXjType>::allVerticesFixed() const
58 {
59  return (static_cast<const VertexXiType*> (_vertices[0])->fixed() &&
60  static_cast<const VertexXjType*> (_vertices[1])->fixed());
61 }
62 
63 template <int D, typename E, typename VertexXiType, typename VertexXjType>
64 void BaseBinaryEdge<D, E, VertexXiType, VertexXjType>::constructQuadraticForm()
65 {
66  VertexXiType* from = static_cast<VertexXiType*>(_vertices[0]);
67  VertexXjType* to = static_cast<VertexXjType*>(_vertices[1]);
68 
69  // get the Jacobian of the nodes in the manifold domain
70  const JacobianXiOplusType& A = jacobianOplusXi();
71  const JacobianXjOplusType& B = jacobianOplusXj();
72 
73 
74  bool fromNotFixed = !(from->fixed());
75  bool toNotFixed = !(to->fixed());
76 
77  if (fromNotFixed || toNotFixed) {
78 #ifdef G2O_OPENMP
79  from->lockQuadraticForm();
80  to->lockQuadraticForm();
81 #endif
82  const InformationType& omega = _information;
83  Eigen::Matrix<double, D, 1, Eigen::ColMajor> omega_r = - omega * _error;
84  if (this->robustKernel() == 0) {
85  if (fromNotFixed) {
86  Eigen::Matrix<double, VertexXiType::Dimension, D, Eigen::ColMajor> AtO = A.transpose() * omega;
87  from->b().noalias() += A.transpose() * omega_r;
88  from->A().noalias() += AtO*A;
89  if (toNotFixed ) {
90  if (_hessianRowMajor) // we have to write to the block as transposed
91  _hessianTransposed.noalias() += B.transpose() * AtO.transpose();
92  else
93  _hessian.noalias() += AtO * B;
94  }
95  }
96  if (toNotFixed) {
97  to->b().noalias() += B.transpose() * omega_r;
98  to->A().noalias() += B.transpose() * omega * B;
99  }
100  } else { // robust (weighted) error according to some kernel
101  double error = this->chi2();
102  Vector3D rho;
103  this->robustKernel()->robustify(error, rho);
104  InformationType weightedOmega = this->robustInformation(rho);
105  //std::cout << PVAR(rho.transpose()) << std::endl;
106  //std::cout << PVAR(weightedOmega) << std::endl;
107 
108  omega_r *= rho[1];
109  if (fromNotFixed) {
110  from->b().noalias() += A.transpose() * omega_r;
111  from->A().noalias() += A.transpose() * weightedOmega * A;
112  if (toNotFixed ) {
113  if (_hessianRowMajor) // we have to write to the block as transposed
114  _hessianTransposed.noalias() += B.transpose() * weightedOmega * A;
115  else
116  _hessian.noalias() += A.transpose() * weightedOmega * B;
117  }
118  }
119  if (toNotFixed) {
120  to->b().noalias() += B.transpose() * omega_r;
121  to->A().noalias() += B.transpose() * weightedOmega * B;
122  }
123  }
124 #ifdef G2O_OPENMP
125  to->unlockQuadraticForm();
126  from->unlockQuadraticForm();
127 #endif
128  }
129 }
130 
131 template <int D, typename E, typename VertexXiType, typename VertexXjType>
132 void BaseBinaryEdge<D, E, VertexXiType, VertexXjType>::linearizeOplus(JacobianWorkspace& jacobianWorkspace)
133 {
134  new (&_jacobianOplusXi) JacobianXiOplusType(jacobianWorkspace.workspaceForVertex(0), D, Di);
135  new (&_jacobianOplusXj) JacobianXjOplusType(jacobianWorkspace.workspaceForVertex(1), D, Dj);
136  linearizeOplus();
137 }
138 
139 template <int D, typename E, typename VertexXiType, typename VertexXjType>
140 void BaseBinaryEdge<D, E, VertexXiType, VertexXjType>::linearizeOplus()
141 {
142  VertexXiType* vi = static_cast<VertexXiType*>(_vertices[0]);
143  VertexXjType* vj = static_cast<VertexXjType*>(_vertices[1]);
144 
145  bool iNotFixed = !(vi->fixed());
146  bool jNotFixed = !(vj->fixed());
147 
148  if (!iNotFixed && !jNotFixed)
149  return;
150 
151 #ifdef G2O_OPENMP
152  vi->lockQuadraticForm();
153  vj->lockQuadraticForm();
154 #endif
155 
156  const double delta = 1e-9;
157  const double scalar = 1.0 / (2*delta);
158  ErrorVector errorBak;
159  ErrorVector errorBeforeNumeric = _error;
160 
161  if (iNotFixed) {
162  //Xi - estimate the jacobian numerically
163  double add_vi[VertexXiType::Dimension];
164  std::fill(add_vi, add_vi + VertexXiType::Dimension, 0.0);
165  // add small step along the unit vector in each dimension
166  for (int d = 0; d < VertexXiType::Dimension; ++d) {
167  vi->push();
168  add_vi[d] = delta;
169  vi->oplus(add_vi);
170  computeError();
171  errorBak = _error;
172  vi->pop();
173  vi->push();
174  add_vi[d] = -delta;
175  vi->oplus(add_vi);
176  computeError();
177  errorBak -= _error;
178  vi->pop();
179  add_vi[d] = 0.0;
180 
181  _jacobianOplusXi.col(d) = scalar * errorBak;
182  } // end dimension
183  }
184 
185  if (jNotFixed) {
186  //Xj - estimate the jacobian numerically
187  double add_vj[VertexXjType::Dimension];
188  std::fill(add_vj, add_vj + VertexXjType::Dimension, 0.0);
189  // add small step along the unit vector in each dimension
190  for (int d = 0; d < VertexXjType::Dimension; ++d) {
191  vj->push();
192  add_vj[d] = delta;
193  vj->oplus(add_vj);
194  computeError();
195  errorBak = _error;
196  vj->pop();
197  vj->push();
198  add_vj[d] = -delta;
199  vj->oplus(add_vj);
200  computeError();
201  errorBak -= _error;
202  vj->pop();
203  add_vj[d] = 0.0;
204 
205  _jacobianOplusXj.col(d) = scalar * errorBak;
206  }
207  } // end dimension
208 
209  _error = errorBeforeNumeric;
210 #ifdef G2O_OPENMP
211  vj->unlockQuadraticForm();
212  vi->unlockQuadraticForm();
213 #endif
214 }
215 
216 template <int D, typename E, typename VertexXiType, typename VertexXjType>
217 void BaseBinaryEdge<D, E, VertexXiType, VertexXjType>::mapHessianMemory(double* d, int i, int j, bool rowMajor)
218 {
219  (void) i; (void) j;
220  //assert(i == 0 && j == 1);
221  if (rowMajor) {
222  new (&_hessianTransposed) HessianBlockTransposedType(d, VertexXjType::Dimension, VertexXiType::Dimension);
223  } else {
224  new (&_hessian) HessianBlockType(d, VertexXiType::Dimension, VertexXjType::Dimension);
225  }
226  _hessianRowMajor = rowMajor;
227 }
Eigen::Matrix< double, 3, 1, Eigen::ColMajor > Vector3D
Definition: eigen_types.h:46