g2o
Loading...
Searching...
No Matches
base_variable_sized_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#include <cassert>
28
29namespace internal {
30inline int computeUpperTriangleIndex(int i, int j) {
31 int elemsUpToCol = ((j - 1) * j) / 2;
32 return elemsUpToCol + i;
33}
34} // namespace internal
35
36template <int D, typename E>
38 if (this->robustKernel()) {
39 double error = this->chi2();
40 Vector3 rho;
41 this->robustKernel()->robustify(error, rho);
42 Eigen::Matrix<double, D, 1, Eigen::ColMajor> omega_r =
43 -_information * _error;
44 omega_r *= rho[1];
45 computeQuadraticForm(this->robustInformation(rho), omega_r);
46 } else {
47 computeQuadraticForm(_information, -_information * _error);
48 }
49}
50
51template <int D, typename E>
53 JacobianWorkspace& jacobianWorkspace) {
54 for (size_t i = 0; i < _vertices.size(); ++i) {
56 static_cast<OptimizableGraph::Vertex*>(_vertices[i]);
57 assert(v->dimension() >= 0);
58 new (&_jacobianOplus[i])
59 JacobianType(jacobianWorkspace.workspaceForVertex(i),
60 D < 0 ? _dimension : D, v->dimension());
61 }
62 linearizeOplus();
63}
64
65template <int D, typename E>
67 const double delta = cst(1e-9);
68 const double scalar = 1 / (2 * delta);
69 ErrorVector errorBak;
70 ErrorVector errorBeforeNumeric = _error;
71
72 for (size_t i = 0; i < _vertices.size(); ++i) {
73 // Xi - estimate the jacobian numerically
75 static_cast<OptimizableGraph::Vertex*>(_vertices[i]);
76
77 if (vi->fixed()) {
78 continue;
79 }
82 const int vi_dim = vi->dimension();
83 assert(vi_dim >= 0);
85 assert(_dimension >= 0);
86 assert(_jacobianOplus[i].rows() == _dimension &&
87 _jacobianOplus[i].cols() == vi_dim &&
88 "jacobian cache dimension does not match");
89 _jacobianOplus[i].resize(_dimension, vi_dim);
90 // add small step along the unit vector in each dimension
92 add_vi.fill(0.);
93 for (int d = 0; d < vi_dim; ++d) {
94 vi->push();
95 add_vi[d] = delta;
96 vi->oplus(add_vi.data());
97 computeError();
98 errorBak = _error;
99 vi->pop();
100 vi->push();
101 add_vi[d] = -delta;
102 vi->oplus(add_vi.data());
103 computeError();
104 errorBak -= _error;
105 vi->pop();
106 add_vi[d] = 0.0;
107
108 _jacobianOplus[i].col(d) = scalar * errorBak;
109 } // end dimension
110 _error = errorBeforeNumeric;
111 }
112}
113
114template <int D, typename E>
116 bool rowMajor) {
118 assert(idx < (int)_hessian.size());
120 static_cast<OptimizableGraph::Vertex*>(HyperGraph::Edge::vertex(i));
122 static_cast<OptimizableGraph::Vertex*>(HyperGraph::Edge::vertex(j));
123 assert(vi->dimension() >= 0);
124 assert(vj->dimension() >= 0);
125 HessianHelper& h = _hessian[idx];
126 if (rowMajor) {
127 if (h.matrix.data() != d || h.transposed != rowMajor)
128 new (&h.matrix) HessianBlockType(d, vj->dimension(), vi->dimension());
129 } else {
130 if (h.matrix.data() != d || h.transposed != rowMajor)
131 new (&h.matrix) HessianBlockType(d, vi->dimension(), vj->dimension());
132 }
133 h.transposed = rowMajor;
134}
135
136template <int D, typename E>
139 int n = (int)_vertices.size();
140 int maxIdx = (n * (n - 1)) / 2;
141 assert(maxIdx >= 0);
142 _hessian.resize(maxIdx);
143 _jacobianOplus.resize(size, JacobianType(0, 0, 0));
144}
145
146template <int D, typename E>
148 for (size_t i = 0; i < _vertices.size(); ++i) {
149 if (!static_cast<const OptimizableGraph::Vertex*>(_vertices[i])->fixed()) {
150 return false;
151 }
152 }
153 return true;
154}
155
156template <int D, typename E>
158 const InformationType& omega, const ErrorVector& weightedError) {
159 for (size_t i = 0; i < _vertices.size(); ++i) {
161 static_cast<OptimizableGraph::Vertex*>(_vertices[i]);
162 bool istatus = !(from->fixed());
163
164 if (istatus) {
165 const JacobianType& A = _jacobianOplus[i];
166
167 MatrixX AtO = A.transpose() * omega;
168 int fromDim = from->dimension();
169 assert(fromDim >= 0);
170 Eigen::Map<MatrixX> fromMap(from->hessianData(), fromDim, fromDim);
171 Eigen::Map<VectorX> fromB(from->bData(), fromDim);
172
173 // ii block in the hessian
174 {
176 fromMap.noalias() += AtO * A;
177 fromB.noalias() += A.transpose() * weightedError;
178 }
179
180 // compute the off-diagonal blocks ij for all j
181 for (size_t j = i + 1; j < _vertices.size(); ++j) {
183 static_cast<OptimizableGraph::Vertex*>(_vertices[j]);
184
185 bool jstatus = !(to->fixed());
186 if (jstatus) {
188 const JacobianType& B = _jacobianOplus[j];
190 assert(idx < (int)_hessian.size());
191 HessianHelper& hhelper = _hessian[idx];
192 if (hhelper
193 .transposed) { // we have to write to the block as transposed
194 hhelper.matrix.noalias() += B.transpose() * AtO.transpose();
195 } else {
196 hhelper.matrix.noalias() += AtO * B;
197 }
198 }
199 }
200 }
201 }
202}
base class to represent an edge connecting an arbitrary number of nodes
Eigen::Map< MatrixX, MatrixX::Flags &Eigen::PacketAccessBit ? Eigen::Aligned :Eigen::Unaligned > HessianBlockType
BaseEdge< D, E >::ErrorVector ErrorVector
BaseEdge< D, E >::InformationType InformationType
provide memory workspace for computing the Jacobians
double * workspaceForVertex(int vertexIndex)
A general case Vertex for optimization.
int dimension() const
dimension of the estimated state belonging to this node
bool fixed() const
true => this node is fixed during the optimization
virtual void push()=0
backup the position of the vertex to a stack
virtual double * hessianData()=0
virtual double * bData()=0
return a pointer to the b vector associated with this vertex
VectorN< 3 > Vector3
Definition eigen_types.h:51
MatrixN< Eigen::Dynamic > MatrixX
Definition eigen_types.h:74
constexpr double cst(long double v)
Definition misc.h:60
int computeUpperTriangleIndex(int i, int j)
helper for mapping the Hessian memory of the upper triangular block
bool transposed
the block has to be transposed
Eigen::Map< MatrixX > matrix
the mapped memory