g2o
Loading...
Searching...
No Matches
base_fixed_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
29template <int D, typename E, typename... VertexTypes>
31 assert(size == _nr_of_vertices &&
32 "attempting to resize a constant size edge");
34}
35
36template <int D, typename E, typename... VertexTypes>
37template <std::size_t... Ints>
39 std::index_sequence<Ints...>) const {
40 return (... && vertexXn<Ints>()->fixed());
41}
42
43template <int D, typename E, typename... VertexTypes>
45 return allVerticesFixedNs(std::make_index_sequence<_nr_of_vertices>());
46}
47
48template <int D, typename E, typename... VertexTypes>
50 if (this->robustKernel()) {
51 double error = this->chi2();
52 Vector3 rho;
53 this->robustKernel()->robustify(error, rho);
54 Eigen::Matrix<double, D, 1, Eigen::ColMajor> omega_r =
55 -_information * _error;
56 omega_r *= rho[1];
57 constructQuadraticFormNs(this->robustInformation(rho), omega_r,
58 std::make_index_sequence<_nr_of_vertices>());
59 } else {
60 constructQuadraticFormNs(_information, -_information * _error,
61 std::make_index_sequence<_nr_of_vertices>());
62 }
63}
64
65template <int D, typename E, typename... VertexTypes>
66template <std::size_t... Ints>
68 const InformationType& omega, const ErrorVector& weightedError,
69 std::index_sequence<Ints...>) {
70 (void(constructQuadraticFormN<Ints>(omega, weightedError)), ...);
71}
72
73// overloading constructOffDiagonalQuadraticFormMs to
74// prevent MSVC error when index_sequence is empty
75template <int D, typename E, typename... VertexTypes>
76template <int N, typename AtOType>
78 constructOffDiagonalQuadraticFormMs(const AtOType&, std::index_sequence<>) {
79}
80
81template <int D, typename E, typename... VertexTypes>
82template <int N, std::size_t... Ints, typename AtOType>
85 std::index_sequence<Ints...>) {
86 (void(constructOffDiagonalQuadraticFormM<N, Ints, AtOType>(AtO)), ...);
87}
88
89template <int D, typename E, typename... VertexTypes>
90template <int N, int M, typename AtOType>
92 constructOffDiagonalQuadraticFormM(const AtOType& AtO) {
93 constexpr auto fromId = N;
94 constexpr auto toId = N + M + 1;
95 assert(fromId < toId && "Index mixed up");
96 auto to = vertexXn<toId>();
97 if (!to->fixed()) {
98 const auto& B = std::get<toId>(_jacobianOplus);
99 constexpr auto K = internal::pair_to_index(fromId, toId);
101 (void)lck;
102 if (_hessianRowMajor[K]) { // we have to write to the block as transposed
103 auto& hessianTransposed = std::get<K>(_hessianTupleTransposed);
104 hessianTransposed.noalias() += B.transpose() * AtO.transpose();
105 } else {
106 auto& hessian = std::get<K>(_hessianTuple);
107 hessian.noalias() += AtO * B;
108 }
109 }
110}
111
112template <int D, typename E, typename... VertexTypes>
113template <int N>
115 const InformationType& omega, const ErrorVector& weightedError) {
116 auto from = vertexXn<N>();
117 const auto& A = std::get<N>(_jacobianOplus);
118
119 if (!(from->fixed())) {
120 const auto AtO = A.transpose() * omega;
121 {
123 (void)lck;
124 from->b().noalias() += A.transpose() * weightedError;
125 from->A().noalias() += AtO * A;
126 }
127 constructOffDiagonalQuadraticFormMs<N>(
128 AtO, std::make_index_sequence<_nr_of_vertices - N - 1>());
129 }
130};
131
132template <int D, typename E, typename... VertexTypes>
134 JacobianWorkspace& jacobianWorkspace) {
135 linearizeOplus_allocate(jacobianWorkspace,
136 std::make_index_sequence<_nr_of_vertices>());
137 linearizeOplus();
138}
139
140template <int D, typename E, typename... VertexTypes>
141template <std::size_t... Ints>
143 JacobianWorkspace& jacobianWorkspace, std::index_sequence<Ints...>) {
144 (new (&std::get<Ints>(_jacobianOplus))
145 JacobianType<D, VertexDimension<Ints>()>(
146 jacobianWorkspace.workspaceForVertex(Ints), D < 0 ? _dimension : D,
147 VertexDimension<Ints>() < 0 ? vertexXn<Ints>()->dimension()
148 : VertexDimension<Ints>()),
149 ...);
150}
151
152template <int D, typename E, typename... VertexTypes>
153template <int N>
155 auto vertex = vertexXn<N>();
156
157 if (vertex->fixed()) return;
158
159 auto& jacobianOplus = std::get<N>(_jacobianOplus);
160
161 constexpr double delta = cst(1e-9);
162 constexpr double scalar = 1 / (2 * delta);
163
164 internal::QuadraticFormLock lck(*vertex);
165 (void)lck;
166
167 typedef typename std::conditional<
170 double, static_cast<size_t>(VertexXnType<N>::Dimension)> >::type
171 FixedArray;
172 FixedArray add_vertex(vertexDimension<N>());
173 add_vertex.fill(0.);
174
175 // estimate the jacobian numerically
176 // add small step along the unit vector in each dimension
177 for (int d = 0; d < vertexDimension<N>(); ++d) {
178 vertex->push();
179 add_vertex[d] = delta;
180 vertex->oplus(add_vertex.data());
181 computeError();
182 auto errorBak = this->error();
183 vertex->pop();
184 vertex->push();
185 add_vertex[d] = -delta;
186 vertex->oplus(add_vertex.data());
187 computeError();
188 errorBak -= this->error();
189 vertex->pop();
190 add_vertex[d] = 0.0;
191
192 jacobianOplus.col(d) = scalar * errorBak;
193 } // end dimension
194}
195
196template <int D, typename E, typename... VertexTypes>
197template <std::size_t... Ints>
199 std::index_sequence<Ints...>) {
200 (void(linearizeOplusN<Ints>()), ...);
201}
202
203template <int D, typename E, typename... VertexTypes>
205 if (allVerticesFixed()) return;
206 ErrorVector errorBeforeNumeric = _error;
207 linearizeOplusNs(std::make_index_sequence<_nr_of_vertices>());
208 _error = errorBeforeNumeric;
209}
210
216 double* d;
217 int rows;
218 int cols;
219 template <typename HessianT>
220 void operator()(HessianT& hessian) {
221 new (&hessian)
222 typename std::remove_reference<decltype(hessian)>::type(d, rows, cols);
223 }
224};
225
226template <int D, typename E, typename... VertexTypes>
228 int i, int j,
229 bool rowMajor) {
230 assert(i < j && "index assumption violated");
231 // get the size of the vertices
232 int vi_dim =
233 static_cast<OptimizableGraph::Vertex*>(HyperGraph::Edge::vertex(i))
234 ->dimension();
235 int vj_dim =
236 static_cast<OptimizableGraph::Vertex*>(HyperGraph::Edge::vertex(j))
237 ->dimension();
238 int k = internal::pair_to_index(i, j);
239 _hessianRowMajor[k] = rowMajor;
240 if (rowMajor)
241 tuple_apply_i(MapHessianMemoryK{d, vj_dim, vi_dim}, _hessianTupleTransposed,
242 k);
243 else
244 tuple_apply_i(MapHessianMemoryK{d, vi_dim, vj_dim}, _hessianTuple, k);
245}
BaseEdge< D, E >::InformationType InformationType
BaseEdge< D, E >::ErrorVector ErrorVector
typename Eigen::Matrix< double, EdgeDimension, VertexDimension, EdgeDimension==1 ? Eigen::RowMajor :Eigen::ColMajor >::AlignedMapType JacobianType
NthType< VertexN, VertexTypes... > VertexXnType
The type of the N-th vertex.
provide memory workspace for computing the Jacobians
double * workspaceForVertex(int vertexIndex)
A general case Vertex for optimization.
const_pointer data() const
void fill(const value_type &val)
VectorN< 3 > Vector3
Definition eigen_types.h:51
constexpr double cst(long double v)
Definition misc.h:60
void tuple_apply_i(F &&f, T &t, int i)
Definition tuple_tools.h:39
void operator()(HessianT &hessian)