g2o
Loading...
Searching...
No Matches
graph_optimizer_sparse_online.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
28
29#include <fstream>
30#include <iomanip>
31#include <iostream>
32
38#include "g2o/stuff/macros.h"
39#include "types_slam2d_online.h"
40#include "types_slam3d_online.h"
41
42using namespace std;
43using namespace Eigen;
44
45namespace g2o {
46
47namespace {
48template <int p, int l>
49std::unique_ptr<g2o::Solver> AllocatePCGSolver() {
50 std::cerr << "# Using PCG online poseDim " << p << " landMarkDim " << l
51 << " blockordering 1" << std::endl;
52
53 auto linearSolver = std::make_unique<
54 LinearSolverPCG<typename BlockSolverPL<p, l>::PoseMatrixType>>();
55 linearSolver->setMaxIterations(6);
56 return std::make_unique<BlockSolverPL<p, l>>(std::move(linearSolver));
57}
58} // namespace
59
60// force linking to the cholmod solver
62
65 slamDimension(3),
66 newEdges(0),
67 batchStep(true),
68 vizWithGnuplot(false),
69 _gnuplot(0),
70 _usePcg(pcg),
71 _underlyingSolver(0) {}
72
74 if (_gnuplot) {
75#ifdef WINDOWS
76 _pclose(_gnuplot);
77#else
78 pclose(_gnuplot);
79#endif
80 }
81}
82
83int SparseOptimizerOnline::optimize(int iterations, bool online) {
84 // return SparseOptimizer::optimize(iterations, online);
85
86 (void)iterations; // we only do one iteration anyhow
88
89 bool ok = true;
90
91 solver->init(online);
92 if (!online) {
94 if (!ok) {
95 cerr << __PRETTY_FUNCTION__ << ": Failure while building CCS structure"
96 << endl;
97 return 0;
98 }
99 }
100
101 if (_usePcg) batchStep = true;
102
103 if (!online || batchStep) {
104 // cerr << "BATCH" << endl;
105 //_underlyingSolver->buildStructure();
106 // copy over the updated estimate as new linearization point
107 if (slamDimension == 3) {
108 for (size_t i = 0; i < indexMapping().size(); ++i) {
109 OnlineVertexSE2* v = static_cast<OnlineVertexSE2*>(indexMapping()[i]);
111 }
112 } else if (slamDimension == 6) {
113 for (size_t i = 0; i < indexMapping().size(); ++i) {
114 OnlineVertexSE3* v = static_cast<OnlineVertexSE3*>(indexMapping()[i]);
116 }
117 }
118
120 // SparseOptimizer::linearizeSystem();
122 } else {
123 // cerr << "UPDATE" << endl;
124 // compute the active errors for the required edges
125 for (HyperGraph::EdgeSet::iterator it = newEdges->begin();
126 it != newEdges->end(); ++it) {
127 OptimizableGraph::Edge* e = static_cast<OptimizableGraph::Edge*>(*it);
128 e->computeError();
129 }
130 // linearize the constraints and update the Hessian
131 for (HyperGraph::EdgeSet::iterator it = newEdges->begin();
132 it != newEdges->end(); ++it) {
133 OptimizableGraph::Edge* e = static_cast<OptimizableGraph::Edge*>(*it);
136 }
137 // update the b vector
138 for (int i = 0; i < static_cast<int>(indexMapping().size()); ++i) {
140 int iBase = v->colInHessian();
141 v->copyB(_underlyingSolver->b() + iBase);
142 }
143 }
144 ok = _underlyingSolver->solve();
146
147 if (verbose()) {
149 cerr << "nodes = " << vertices().size()
150 << "\t edges= " << _activeEdges.size()
151 << "\t chi2= " << FIXED(activeChi2()) << endl;
152 }
153
155
156 if (!ok) return 0;
157 return 1;
158}
159
160void SparseOptimizerOnline::update(double* update) {
161 if (slamDimension == 3) {
162 for (size_t i = 0; i < _ivMap.size(); ++i) {
163 OnlineVertexSE2* v = static_cast<OnlineVertexSE2*>(_ivMap[i]);
165 update += 3;
166 }
167 } else if (slamDimension == 6) {
168 for (size_t i = 0; i < _ivMap.size(); ++i) {
169 OnlineVertexSE3* v = static_cast<OnlineVertexSE3*>(_ivMap[i]);
171 update += 6;
172 }
173 }
174}
175
177 HyperGraph::EdgeSet& eset) {
178 newEdges = &eset;
179 bool result = SparseOptimizer::updateInitialization(vset, eset);
180 for (HyperGraph::VertexSet::iterator it = vset.begin(); it != vset.end();
181 ++it) {
183 v->clearQuadraticForm(); // be sure that b is zero for this vertex
184 }
185 return result;
186}
187
188bool SparseOptimizerOnline::initSolver(int dimension, int /*batchEveryN*/) {
189 slamDimension = dimension;
190 OptimizationAlgorithmFactory* solverFactory =
192 OptimizationAlgorithmProperty solverProperty;
193 if (_usePcg) {
194 std::unique_ptr<Solver> s;
195 if (dimension == 3) {
196 s = AllocatePCGSolver<3, 2>();
197 } else {
198 s = AllocatePCGSolver<6, 3>();
199 }
200
202 new OptimizationAlgorithmGaussNewton(std::move(s));
203 setAlgorithm(gaussNewton);
204 } else {
205 if (dimension == 3) {
207 solverFactory->construct("gn_fix3_2_cholmod", solverProperty));
208 } else {
210 solverFactory->construct("gn_fix6_3_cholmod", solverProperty));
211 }
212 }
213
216 _underlyingSolver = &gaussNewton->solver();
217
218 if (!solver()) {
219 cerr << "Error allocating solver. Allocating CHOLMOD solver failed!"
220 << endl;
221 return false;
222 }
223 return true;
224}
225
227 if (slamDimension == 3) {
228 if (!_gnuplot) {
229#ifdef WINDOWS
230 _gnuplot = _popen("gnuplot -persistent", "w");
231#else
232 _gnuplot = popen("gnuplot -persistent", "w");
233#endif
234 if (_gnuplot == 0) return;
235 fprintf(_gnuplot, "set terminal X11 noraise\n");
236 fprintf(_gnuplot, "set size ratio -1\n");
237 }
238 fprintf(_gnuplot, "plot \"-\" w l\n");
239 for (EdgeSet::iterator it = edges().begin(); it != edges().end(); ++it) {
240 OnlineEdgeSE2* e = static_cast<OnlineEdgeSE2*>(*it);
241 OnlineVertexSE2* v1 = static_cast<OnlineVertexSE2*>(e->vertices()[0]);
242 OnlineVertexSE2* v2 = static_cast<OnlineVertexSE2*>(e->vertices()[1]);
243 fprintf(_gnuplot, "%f %f\n", v1->updatedEstimate.translation().x(),
244 v1->updatedEstimate.translation().y());
245 fprintf(_gnuplot, "%f %f\n\n", v2->updatedEstimate.translation().x(),
246 v2->updatedEstimate.translation().y());
247 }
248 fprintf(_gnuplot, "e\n");
249 }
250 if (slamDimension == 6) {
251 if (!_gnuplot) {
252#ifdef WINDOWS
253 _gnuplot = _popen("gnuplot -persistent", "w");
254#else
255 _gnuplot = popen("gnuplot -persistent", "w");
256#endif
257 if (_gnuplot == 0) return;
258 fprintf(_gnuplot, "set terminal X11 noraise\n");
259 }
260 fprintf(_gnuplot, "splot \"-\" w l\n");
261 for (EdgeSet::iterator it = edges().begin(); it != edges().end(); ++it) {
262 OnlineEdgeSE3* e = (OnlineEdgeSE3*)*it;
263 OnlineVertexSE3* v1 = static_cast<OnlineVertexSE3*>(e->vertices()[0]);
264 OnlineVertexSE3* v2 = static_cast<OnlineVertexSE3*>(e->vertices()[1]);
265 fprintf(_gnuplot, "%f %f %f\n", v1->updatedEstimate.translation().x(),
266 v1->updatedEstimate.translation().y(),
267 v1->updatedEstimate.translation().z());
268 fprintf(_gnuplot, "%f %f %f \n\n\n",
269 v2->updatedEstimate.translation().x(),
270 v2->updatedEstimate.translation().y(),
271 v2->updatedEstimate.translation().z());
272 }
273 fprintf(_gnuplot, "e\n");
274 }
275}
276
277} // namespace g2o
void setEstimate(const EstimateType &et)
set the estimate for the vertex also calls updateCache()
const VertexContainer & vertices() const
std::set< Edge * > EdgeSet
std::set< Vertex * > VertexSet
const EdgeSet & edges() const
const VertexIDMap & vertices() const
VertexSE2::EstimateType updatedEstimate
void oplusUpdatedEstimate(double *update)
VertexSE3::EstimateType updatedEstimate
void oplusUpdatedEstimate(double *update)
virtual void linearizeOplus(JacobianWorkspace &jacobianWorkspace)=0
virtual void computeError()=0
virtual void constructQuadraticForm()=0
A general case Vertex for optimization.
int colInHessian() const
get the row of this vertex in the Hessian
virtual void clearQuadraticForm()=0
virtual int copyB(double *b_) const =0
create solvers based on their short name
OptimizationAlgorithm * construct(const std::string &tag, OptimizationAlgorithmProperty &solverProperty) const
static OptimizationAlgorithmFactory * instance()
return the instance
Implementation of the Gauss Newton Algorithm.
Solver & solver()
return the underlying solver used to solve the linear system
Generic interface for a non-linear solver operating on a graph.
virtual bool init(bool online=false)=0
const Vector2 & translation() const
translational component
Definition se2.h:57
double * b()
return b, the right hand side of the system
Definition solver.h:101
virtual bool buildStructure(bool zeroBlocks=false)=0
double * x()
return x, the solution vector
Definition solver.h:98
virtual bool solve()=0
virtual bool buildSystem()=0
virtual bool initSolver(int dimension, int batchEveryN)
int optimize(int iterations, bool online=false)
virtual bool updateInitialization(HyperGraph::VertexSet &vset, HyperGraph::EdgeSet &eset)
EdgeContainer _activeEdges
sorted according to EdgeIDCompare
void setAlgorithm(OptimizationAlgorithm *algorithm)
OptimizationAlgorithm * _algorithm
bool verbose() const
verbose information during optimization
const VertexContainer & indexMapping() const
the index mapping of the vertices
OptimizationAlgorithm * solver()
virtual bool updateInitialization(HyperGraph::VertexSet &vset, HyperGraph::EdgeSet &eset)
#define __PRETTY_FUNCTION__
Definition macros.h:90
Definition jet.h:938
Definition jet.h:876
#define G2O_USE_OPTIMIZATION_LIBRARY(libraryname)
JacobianWorkspace & jacobianWorkspace()
the workspace for storing the Jacobians of the graph