g2o
Loading...
Searching...
No Matches
Classes | Functions | Variables
g2o.cpp File Reference
#include <signal.h>
#include <algorithm>
#include <cassert>
#include <fstream>
#include <iomanip>
#include <iostream>
#include <sstream>
#include <string>
#include "dl_wrapper.h"
#include "g2o/config.h"
#include "g2o/core/batch_stats.h"
#include "g2o/core/estimate_propagator.h"
#include "g2o/core/factory.h"
#include "g2o/core/hyper_dijkstra.h"
#include "g2o/core/hyper_graph_action.h"
#include "g2o/core/optimization_algorithm.h"
#include "g2o/core/optimization_algorithm_factory.h"
#include "g2o/core/robust_kernel.h"
#include "g2o/core/robust_kernel_factory.h"
#include "g2o/core/sparse_optimizer.h"
#include "g2o/core/sparse_optimizer_terminate_action.h"
#include "g2o/stuff/color_macros.h"
#include "g2o/stuff/command_args.h"
#include "g2o/stuff/filesys_tools.h"
#include "g2o/stuff/macros.h"
#include "g2o/stuff/string_tools.h"
#include "g2o/stuff/timeutil.h"
#include "g2o_common.h"
#include "output_helper.h"
Include dependency graph for g2o.cpp:

Go to the source code of this file.

Classes

struct  IncrementalEdgesCompare
 Sort Edges for inserting them sequentially. More...
 

Functions

void sigquit_handler (int sig)
 
int main (int argc, char **argv)
 

Variables

static bool hasToStop = false
 

Function Documentation

◆ main()

int main ( int  argc,
char **  argv 
)

Definition at line 100 of file g2o.cpp.

100 {
102 int maxIterations;
103 bool verbose;
104 string inputFilename;
105 string gnudump;
106 string outputfilename;
107 string solverProperties;
108 string strSolver;
109 string loadLookup;
110 bool initialGuess;
111 bool initialGuessOdometry;
112 bool marginalize;
113 bool listTypes;
114 bool listSolvers;
115 bool listRobustKernels;
116 bool incremental;
117 bool guiOut;
118 int gaugeId;
119 string robustKernel;
120 bool computeMarginals;
121 bool printSolverProperties;
122 double huberWidth;
123 double gain;
124 int maxIterationsWithGain;
125 // double lambdaInit;
126 int updateGraphEachN = 10;
127 string statsFile;
128 string summaryFile;
129 bool nonSequential;
130 // command line parsing
131 std::vector<int> gaugeList;
132 CommandArgs arg;
133 arg.param("i", maxIterations, 5,
134 "perform n iterations, if negative consider the gain");
135 arg.param("gain", gain, 1e-6, "the gain used to stop optimization");
136 arg.param("ig", maxIterationsWithGain, std::numeric_limits<int>::max(),
137 "Maximum number of iterations with gain enabled");
138 arg.param("v", verbose, false, "verbose output of the optimization process");
139 arg.param("guess", initialGuess, false,
140 "initial guess based on spanning tree");
141 arg.param("guessOdometry", initialGuessOdometry, false,
142 "initial guess based on odometry");
143 arg.param("inc", incremental, false, "run incremetally");
144 arg.param("update", updateGraphEachN, 10, "updates after x odometry nodes");
145 arg.param("guiout", guiOut, false, "gui output while running incrementally");
146 arg.param("marginalize", marginalize, false, "on or off");
147 arg.param("printSolverProperties", printSolverProperties, false,
148 "print the properties of the solver");
149 arg.param("solverProperties", solverProperties, "",
150 "set the internal properties of a solver,\n\te.g., "
151 "initialLambda=0.0001,maxTrialsAfterFailure=2");
152 arg.param("gnudump", gnudump, "", "dump to gnuplot data file");
153 arg.param("robustKernel", robustKernel, "", "use this robust error function");
154 arg.param("robustKernelWidth", huberWidth, -1.,
155 "width for the robust Kernel (only if robustKernel)");
156 arg.param("computeMarginals", computeMarginals, false,
157 "computes the marginal covariances of something. FOR TESTING ONLY");
158 arg.param("gaugeId", gaugeId, -1, "force the gauge");
159 arg.param("o", outputfilename, "", "output final version of the graph");
160 arg.param("solver", strSolver, "gn_var",
161 "specify which solver to use underneat\n\t {gn_var, lm_fix3_2, "
162 "gn_fix6_3, lm_fix7_3}");
163#ifndef G2O_DISABLE_DYNAMIC_LOADING_OF_LIBRARIES
164 string dummy;
165 arg.param("solverlib", dummy, "",
166 "specify a solver library which will be loaded");
167 arg.param("typeslib", dummy, "",
168 "specify a types library which will be loaded");
169#endif
170 arg.param("stats", statsFile, "", "specify a file for the statistics");
171 arg.param("listTypes", listTypes, false, "list the registered types");
172 arg.param("listRobustKernels", listRobustKernels, false,
173 "list the registered robust kernels");
174 arg.param("listSolvers", listSolvers, false, "list the available solvers");
175 arg.param("renameTypes", loadLookup, "",
176 "create a lookup for loading types into other types,\n\t "
177 "TAG_IN_FILE=INTERNAL_TAG_FOR_TYPE,TAG2=INTERNAL2\n\t e.g., "
178 "VERTEX_CAM=VERTEX_SE3:EXPMAP");
179 arg.param("gaugeList", gaugeList, std::vector<int>(),
180 "set the list of gauges separated by commas without spaces \n "
181 "e.g: 1,2,3,4,5 ");
182 arg.param("summary", summaryFile, "",
183 "append a summary of this optimization run to the summary file "
184 "passed as argument");
185 arg.paramLeftOver("graph-input", inputFilename, "",
186 "graph file which will be processed", true);
187 arg.param("nonSequential", nonSequential, false,
188 "apply the robust kernel only on loop closures and not odometries");
189
190 arg.parseArgs(argc, argv);
191
192 if (verbose) {
193 cout << "# Used Compiler: " << G2O_CXX_COMPILER << endl;
194 }
195
196#ifndef G2O_DISABLE_DYNAMIC_LOADING_OF_LIBRARIES
197 // registering all the types from the libraries
198 DlWrapper dlTypesWrapper;
199 loadStandardTypes(dlTypesWrapper, argc, argv);
200 // register all the solvers
201 DlWrapper dlSolverWrapper;
202 loadStandardSolver(dlSolverWrapper, argc, argv);
203#else
204 if (verbose) cout << "# linked version of g2o" << endl;
205#endif
206
207 OptimizationAlgorithmFactory* solverFactory =
209 if (listSolvers) {
210 solverFactory->listSolvers(cout);
211 }
212
213 if (listTypes) {
215 }
216
217 if (listRobustKernels) {
218 std::vector<std::string> kernels;
220 cout << "Robust Kernels:" << endl;
221 for (size_t i = 0; i < kernels.size(); ++i) {
222 cout << kernels[i] << endl;
223 }
224 }
225
226 SparseOptimizer optimizer;
227 optimizer.setVerbose(verbose);
228 optimizer.setForceStopFlag(&hasToStop);
229
230 if (maxIterations < 0) {
231 cerr << "# setup termination criterion based on the gain of the iteration"
232 << endl;
233 maxIterations = maxIterationsWithGain;
234 SparseOptimizerTerminateAction* terminateAction =
236 terminateAction->setGainThreshold(gain);
237 terminateAction->setMaxIterations(maxIterationsWithGain);
238 optimizer.addPostIterationAction(terminateAction);
239 }
240
241 // allocating the desired solver + testing whether the solver is okay
242 OptimizationAlgorithmProperty solverProperty;
243 optimizer.setAlgorithm(solverFactory->construct(strSolver, solverProperty));
244 if (!optimizer.solver()) {
245 cerr << "Error allocating solver. Allocating \"" << strSolver
246 << "\" failed!" << endl;
247 return 0;
248 }
249
250 if (solverProperties.size() > 0) {
251 bool updateStatus =
252 optimizer.solver()->updatePropertiesFromString(solverProperties);
253 if (!updateStatus) {
254 cerr << "Failure while updating the solver properties from the given "
255 "string"
256 << endl;
257 }
258 }
259 if (solverProperties.size() > 0 || printSolverProperties) {
260 optimizer.solver()->printProperties(cerr);
261 }
262
263 // Loading the input data
264 if (loadLookup.size() > 0) {
265 optimizer.setRenamedTypesFromString(loadLookup);
266 }
267 if (inputFilename.size() == 0) {
268 cerr << "No input data specified" << endl;
269 return 0;
270 } else if (inputFilename == "-") {
271 cerr << "Read input from stdin" << endl;
272 if (!optimizer.load(cin)) {
273 cerr << "Error loading graph" << endl;
274 return 2;
275 }
276 } else {
277 cerr << "Read input from " << inputFilename << endl;
278 ifstream ifs(inputFilename.c_str());
279 if (!ifs) {
280 cerr << "Failed to open file" << endl;
281 return 1;
282 }
283 if (!optimizer.load(ifs)) {
284 cerr << "Error loading graph" << endl;
285 return 2;
286 }
287 }
288 cerr << "Loaded " << optimizer.vertices().size() << " vertices" << endl;
289 cerr << "Loaded " << optimizer.edges().size() << " edges" << endl;
290
291 if (optimizer.vertices().size() == 0) {
292 cerr << "Graph contains no vertices" << endl;
293 return 1;
294 }
295
296 set<int> vertexDimensions = optimizer.dimensions();
297 if (!optimizer.isSolverSuitable(solverProperty, vertexDimensions)) {
298 cerr << "The selected solver is not suitable for optimizing the given graph"
299 << endl;
300 return 3;
301 }
302 assert(optimizer.solver());
303 // optimizer.setMethod(str2method(strMethod));
304 // optimizer.setUserLambdaInit(lambdaInit);
305
306 // check for vertices to fix to remove DoF
307 bool gaugeFreedom = optimizer.gaugeFreedom();
308 OptimizableGraph::Vertex* gauge = 0;
309 if (gaugeList.size()) {
310 cerr << "Fixing gauges: ";
311 for (size_t i = 0; i < gaugeList.size(); i++) {
312 int id = gaugeList[i];
313 OptimizableGraph::Vertex* v = optimizer.vertex(id);
314 if (!v) {
315 cerr << "fatal, not found the vertex of id " << id
316 << " in the gaugeList. Aborting";
317 return -1;
318 } else {
319 if (i == 0) gauge = v;
320 cerr << v->id() << " ";
321 v->setFixed(1);
322 }
323 }
324 cerr << endl;
325 gaugeFreedom = false;
326 } else {
327 gauge = optimizer.findGauge();
328 }
329 if (gaugeFreedom) {
330 if (!gauge) {
331 cerr << "# cannot find a vertex to fix in this thing" << endl;
332 return 2;
333 } else {
334 cerr << "# graph is fixed by node " << gauge->id() << endl;
335 gauge->setFixed(true);
336 }
337 } else {
338 cerr << "# graph is fixed by priors or already fixed vertex" << endl;
339 }
340
341 // if schur, we wanna marginalize the landmarks...
342 if (marginalize || solverProperty.requiresMarginalize) {
343 int maxDim = *vertexDimensions.rbegin();
344 int minDim = *vertexDimensions.begin();
345 if (maxDim != minDim) {
346 cerr << "# Preparing Marginalization of the Landmarks ... ";
347 for (HyperGraph::VertexIDMap::iterator it = optimizer.vertices().begin();
348 it != optimizer.vertices().end(); ++it) {
350 static_cast<OptimizableGraph::Vertex*>(it->second);
351 if (v->dimension() != maxDim) {
352 v->setMarginalized(true);
353 }
354 }
355 cerr << "done." << endl;
356 }
357 }
358
359 if (robustKernel.size() > 0) {
361 RobustKernelFactory::instance()->creator(robustKernel);
362 cerr << "# Preparing robust error function ... ";
363 if (creator) {
364 if (nonSequential) {
365 for (SparseOptimizer::EdgeSet::iterator it = optimizer.edges().begin();
366 it != optimizer.edges().end(); ++it) {
367 SparseOptimizer::Edge* e = dynamic_cast<SparseOptimizer::Edge*>(*it);
368 if (e->vertices().size() >= 2 &&
369 std::abs(e->vertex(0)->id() - e->vertex(1)->id()) != 1) {
370 e->setRobustKernel(creator->construct());
371 if (huberWidth > 0) e->robustKernel()->setDelta(huberWidth);
372 }
373 }
374 } else {
375 for (SparseOptimizer::EdgeSet::iterator it = optimizer.edges().begin();
376 it != optimizer.edges().end(); ++it) {
377 SparseOptimizer::Edge* e = dynamic_cast<SparseOptimizer::Edge*>(*it);
378 e->setRobustKernel(creator->construct());
379 if (huberWidth > 0) e->robustKernel()->setDelta(huberWidth);
380 }
381 }
382 cerr << "done." << endl;
383 } else {
384 cerr << "Unknown Robust Kernel: " << robustKernel << endl;
385 }
386 }
387
388 // sanity check
389 HyperDijkstra d(&optimizer);
391 d.shortestPaths(gauge, &f);
392 // cerr << PVAR(d.visited().size()) << endl;
393
394 if (d.visited().size() != optimizer.vertices().size()) {
395 cerr << CL_RED("Warning: d.visited().size() != optimizer.vertices().size()")
396 << endl;
397 cerr << "visited: " << d.visited().size() << endl;
398 cerr << "vertices: " << optimizer.vertices().size() << endl;
399 }
400
401 if (incremental) {
402 cerr << CL_RED(
403 "# Note: this variant performs batch steps in each time step")
404 << endl;
405 cerr << CL_RED(
406 "# For a variant which updates the Cholesky factor use "
407 "the binary g2o_incremental")
408 << endl;
409 int incIterations = maxIterations;
410 if (!arg.parsedParam("i")) {
411 cerr << "# Setting default number of iterations" << endl;
412 incIterations = 1;
413 }
414 int updateDisplayEveryN = updateGraphEachN;
415 int maxDim = 0;
416
417 cerr << "# incremental settings" << endl;
418 cerr << "#\t solve every " << updateGraphEachN << endl;
419 cerr << "#\t iterations " << incIterations << endl;
420
421 SparseOptimizer::VertexIDMap vertices = optimizer.vertices();
422 for (SparseOptimizer::VertexIDMap::const_iterator it = vertices.begin();
423 it != vertices.end(); ++it) {
424 const SparseOptimizer::Vertex* v =
425 static_cast<const SparseOptimizer::Vertex*>(it->second);
426 maxDim = max(maxDim, v->dimension());
427 }
428
429 vector<SparseOptimizer::Edge*> edges;
430 for (SparseOptimizer::EdgeSet::iterator it = optimizer.edges().begin();
431 it != optimizer.edges().end(); ++it) {
432 SparseOptimizer::Edge* e = dynamic_cast<SparseOptimizer::Edge*>(*it);
433 edges.push_back(e);
434 }
435 optimizer.edges().clear();
436 optimizer.vertices().clear();
437 optimizer.setVerbose(false);
438
439 // sort the edges in a way that inserting them makes sense
440 sort(edges.begin(), edges.end(), IncrementalEdgesCompare());
441
442 double cumTime = 0.;
443 int vertexCount = 0;
444 int lastOptimizedVertexCount = 0;
445 int lastVisUpdateVertexCount = 0;
446 bool freshlyOptimized = false;
447 bool firstRound = true;
448 HyperGraph::VertexSet verticesAdded;
449 HyperGraph::EdgeSet edgesAdded;
450 for (vector<SparseOptimizer::Edge*>::iterator it = edges.begin();
451 it != edges.end(); ++it) {
452 SparseOptimizer::Edge* e = *it;
453
454 int doInit = 0;
455 SparseOptimizer::Vertex* v1 = optimizer.vertex(e->vertices()[0]->id());
456 SparseOptimizer::Vertex* v2 = optimizer.vertex(e->vertices()[1]->id());
457
458 if (!v1) {
459 SparseOptimizer::Vertex* v = v1 =
460 dynamic_cast<SparseOptimizer::Vertex*>(e->vertices()[0]);
461 bool v1Added = optimizer.addVertex(v);
462 // cerr << "adding" << v->id() << "(" << v->dimension() << ")" << endl;
463 assert(v1Added);
464 if (!v1Added)
465 cerr << "Error adding vertex " << v->id() << endl;
466 else
467 verticesAdded.insert(v);
468 doInit = 1;
469 if (v->dimension() == maxDim) vertexCount++;
470 }
471
472 if (!v2) {
473 SparseOptimizer::Vertex* v = v2 =
474 dynamic_cast<SparseOptimizer::Vertex*>(e->vertices()[1]);
475 bool v2Added = optimizer.addVertex(v);
476 // cerr << "adding" << v->id() << "(" << v->dimension() << ")" << endl;
477 assert(v2Added);
478 if (!v2Added)
479 cerr << "Error adding vertex " << v->id() << endl;
480 else
481 verticesAdded.insert(v);
482 doInit = 2;
483 if (v->dimension() == maxDim) vertexCount++;
484 }
485
486 // adding the edge and initialization of the vertices
487 {
488 // cerr << " adding edge " << e->vertices()[0]->id() << " " <<
489 // e->vertices()[1]->id() << endl;
490 if (!optimizer.addEdge(e)) {
491 cerr << "Unable to add edge " << e->vertices()[0]->id() << " -> "
492 << e->vertices()[1]->id() << endl;
493 } else {
494 edgesAdded.insert(e);
495 }
496
497 if (doInit) {
499 static_cast<OptimizableGraph::Vertex*>(e->vertices()[0]);
501 static_cast<OptimizableGraph::Vertex*>(e->vertices()[1]);
502 switch (doInit) {
503 case 1: // initialize v1 from v2
504 {
506 toSet.insert(to);
507 if (e->initialEstimatePossible(toSet, from) > 0.) {
508 // cerr << "init: "
509 //<< to->id() << "(" << to->dimension() << ") -> "
510 //<< from->id() << "(" << from->dimension() << ") " << endl;
511 e->initialEstimate(toSet, from);
512 } else {
513 assert(0 && "Added uninitialized variable to the graph");
514 }
515 break;
516 }
517 case 2: {
518 HyperGraph::VertexSet fromSet;
519 fromSet.insert(from);
520 if (e->initialEstimatePossible(fromSet, to) > 0.) {
521 // cerr << "init: "
522 //<< from->id() << "(" << from->dimension() << ") -> "
523 //<< to->id() << "(" << to->dimension() << ") " << endl;
524 e->initialEstimate(fromSet, to);
525 } else {
526 assert(0 && "Added uninitialized variable to the graph");
527 }
528 break;
529 }
530 default:
531 cerr << "doInit wrong value\n";
532 }
533 }
534 }
535
536 freshlyOptimized = false;
537 {
538 // cerr << "Optimize" << endl;
539 if (vertexCount - lastOptimizedVertexCount >= updateGraphEachN) {
540 if (firstRound) {
541 if (!optimizer.initializeOptimization()) {
542 cerr << "initialization failed" << endl;
543 return 0;
544 }
545 } else {
546 if (!optimizer.updateInitialization(verticesAdded, edgesAdded)) {
547 cerr << "updating initialization failed" << endl;
548 return 0;
549 }
550 }
551 verticesAdded.clear();
552 edgesAdded.clear();
553 double ts = get_monotonic_time();
554 int currentIt = optimizer.optimize(incIterations, !firstRound);
555 double dts = get_monotonic_time() - ts;
556 cumTime += dts;
557 firstRound = false;
558 // optimizer->setOptimizationTime(cumTime);
559 if (verbose) {
560 double chi2 = optimizer.chi2();
561 cerr << "nodes= " << optimizer.vertices().size()
562 << "\t edges= " << optimizer.edges().size()
563 << "\t chi2= " << chi2 << "\t time= " << dts
564 << "\t iterations= " << currentIt << "\t cumTime= " << cumTime
565 << endl;
566 }
567 lastOptimizedVertexCount = vertexCount;
568 freshlyOptimized = true;
569
570 if (guiOut) {
571 if (vertexCount - lastVisUpdateVertexCount >= updateDisplayEveryN) {
572 dumpEdges(cout, optimizer);
573 lastVisUpdateVertexCount = vertexCount;
574 }
575 }
576 }
577
578 if (!verbose) cerr << ".";
579 }
580
581 } // for all edges
582
583 if (!freshlyOptimized) {
584 double ts = get_monotonic_time();
585 int currentIt = optimizer.optimize(incIterations, !firstRound);
586 double dts = get_monotonic_time() - ts;
587 cumTime += dts;
588 // optimizer->setOptimizationTime(cumTime);
589 if (verbose) {
590 double chi2 = optimizer.chi2();
591 cerr << "nodes= " << optimizer.vertices().size()
592 << "\t edges= " << optimizer.edges().size() << "\t chi2= " << chi2
593 << "\t time= " << dts << "\t iterations= " << currentIt
594 << "\t cumTime= " << cumTime << endl;
595 }
596 }
597
598 } else {
599 // BATCH optimization
600
601 if (statsFile != "") {
602 // allocate buffer for statistics;
603 optimizer.setComputeBatchStatistics(true);
604 }
605 optimizer.initializeOptimization();
606 optimizer.computeActiveErrors();
607 double loadChi = optimizer.chi2();
608 cerr << "Initial chi2 = " << FIXED(loadChi) << endl;
609
610 if (initialGuess) {
611 optimizer.computeInitialGuess();
612 } else if (initialGuessOdometry) {
613 EstimatePropagatorCostOdometry costFunction(&optimizer);
614 optimizer.computeInitialGuess(costFunction);
615 }
616 double initChi = optimizer.chi2();
617
618 signal(SIGINT, sigquit_handler);
619 int result = optimizer.optimize(maxIterations);
620 if (maxIterations > 0 && result == OptimizationAlgorithm::Fail) {
621 cerr << "Cholesky failed, result might be invalid" << endl;
622 } else if (computeMarginals) {
623 std::vector<std::pair<int, int> > blockIndices;
624 for (size_t i = 0; i < optimizer.activeVertices().size(); i++) {
625 OptimizableGraph::Vertex* v = optimizer.activeVertices()[i];
626 if (v->hessianIndex() >= 0) {
627 blockIndices.push_back(
628 make_pair(v->hessianIndex(), v->hessianIndex()));
629 }
630 if (v->hessianIndex() > 0) {
631 blockIndices.push_back(
632 make_pair(v->hessianIndex() - 1, v->hessianIndex()));
633 }
634 }
636 if (optimizer.computeMarginals(spinv, blockIndices)) {
637 for (size_t i = 0; i < optimizer.activeVertices().size(); i++) {
638 OptimizableGraph::Vertex* v = optimizer.activeVertices()[i];
639 cerr << "Vertex id:" << v->id() << endl;
640 if (v->hessianIndex() >= 0) {
641 cerr << "inv block :" << v->hessianIndex() << ", "
642 << v->hessianIndex() << endl;
643 cerr << *(spinv.block(v->hessianIndex(), v->hessianIndex()));
644 cerr << endl;
645 }
646 if (v->hessianIndex() > 0) {
647 cerr << "inv block :" << v->hessianIndex() - 1 << ", "
648 << v->hessianIndex() << endl;
649 cerr << *(spinv.block(v->hessianIndex() - 1, v->hessianIndex()));
650 cerr << endl;
651 }
652 }
653 }
654 }
655
656 optimizer.computeActiveErrors();
657 double finalChi = optimizer.chi2();
658
659 if (summaryFile != "") {
660 PropertyMap summary;
661 summary.makeProperty<StringProperty>("filename", inputFilename);
662 summary.makeProperty<IntProperty>("n_vertices",
663 optimizer.vertices().size());
664 summary.makeProperty<IntProperty>("n_edges", optimizer.edges().size());
665
666 int nLandmarks = 0;
667 int nPoses = 0;
668 int maxDim = *vertexDimensions.rbegin();
669 for (HyperGraph::VertexIDMap::iterator it = optimizer.vertices().begin();
670 it != optimizer.vertices().end(); ++it) {
672 static_cast<OptimizableGraph::Vertex*>(it->second);
673 if (v->dimension() != maxDim) {
674 nLandmarks++;
675 } else
676 nPoses++;
677 }
678 set<string> edgeTypes;
679 for (HyperGraph::EdgeSet::iterator it = optimizer.edges().begin();
680 it != optimizer.edges().end(); ++it) {
681 edgeTypes.insert(Factory::instance()->tag(*it));
682 }
683 stringstream edgeTypesString;
684 for (std::set<string>::iterator it = edgeTypes.begin();
685 it != edgeTypes.end(); ++it) {
686 edgeTypesString << *it << " ";
687 }
688
689 summary.makeProperty<IntProperty>("n_poses", nPoses);
690 summary.makeProperty<IntProperty>("n_landmarks", nLandmarks);
691 summary.makeProperty<StringProperty>("edge_types", edgeTypesString.str());
692 summary.makeProperty<DoubleProperty>("load_chi", loadChi);
693 summary.makeProperty<StringProperty>("solver", strSolver);
694 summary.makeProperty<BoolProperty>("robustKernel",
695 robustKernel.size() > 0);
696 summary.makeProperty<DoubleProperty>("init_chi", initChi);
697 summary.makeProperty<DoubleProperty>("final_chi", finalChi);
698 summary.makeProperty<IntProperty>("maxIterations", maxIterations);
699 summary.makeProperty<IntProperty>("realIterations", result);
700 ofstream os;
701 os.open(summaryFile.c_str(), ios::app);
702 summary.writeToCSV(os);
703 }
704
705 if (statsFile != "") {
706 cerr << "writing stats to file \"" << statsFile << "\" ... ";
707 ofstream os(statsFile.c_str());
708 const BatchStatisticsContainer& bsc = optimizer.batchStatistics();
709
710 for (int i = 0; i < maxIterations; i++) {
711 os << bsc[i] << endl;
712 }
713 cerr << "done." << endl;
714 }
715 }
716
717 // saving again
718 if (gnudump.size() > 0) {
719 bool gnuPlotStatus = saveGnuplot(gnudump, optimizer);
720 if (!gnuPlotStatus) {
721 cerr << "Error while writing gnuplot files" << endl;
722 }
723 }
724
725 if (outputfilename.size() > 0) {
726 if (outputfilename == "-") {
727 cerr << "saving to stdout";
728 optimizer.save(cout);
729 } else {
730 cerr << "saving " << outputfilename << " ... ";
731 optimizer.save(outputfilename.c_str());
732 }
733 cerr << "done." << endl;
734 }
735
736 // destroy all the singletons
737 // Factory::destroy();
738 // OptimizationAlgorithmFactory::destroy();
739 // HyperGraphActionLibrary::destroy();
740
741 return 0;
742}
Abstract interface for allocating a robust kernel.
virtual RobustKernel * construct()=0
Command line parsing of argc and argv.
bool parseArgs(int argc, char **argv, bool exitOnError=true)
void paramLeftOver(const std::string &name, std::string &p, const std::string &defValue, const std::string &desc, bool optional=false)
void param(const std::string &name, bool &p, bool defValue, const std::string &desc)
bool parsedParam(const std::string &paramFlag) const
Loading libraries during run-time.
Definition dl_wrapper.h:46
cost for traversing only odometry edges.
void printRegisteredTypes(std::ostream &os, bool comment=false) const
Definition factory.cpp:167
static Factory * instance()
return the instance
Definition factory.cpp:46
const std::string & tag(const HyperGraph::HyperGraphElement *v) const
return the TAG given a vertex
Definition factory.cpp:138
int id() const
returns the id
std::set< Edge * > EdgeSet
std::set< Vertex * > VertexSet
const EdgeSet & edges() const
const VertexIDMap & vertices() const
A general case Vertex for optimization.
int dimension() const
dimension of the estimated state belonging to this node
void setFixed(bool fixed)
true => this node should be considered fixed during the optimization
void setMarginalized(bool marginalized)
true => this node should be marginalized out during the optimization
create solvers based on their short name
OptimizationAlgorithm * construct(const std::string &tag, OptimizationAlgorithmProperty &solverProperty) const
static OptimizationAlgorithmFactory * instance()
return the instance
void listSolvers(std::ostream &os) const
list the known solvers into a stream
void printProperties(std::ostream &os) const
bool updatePropertiesFromString(const std::string &propString)
a collection of properties mapping from name to the property itself
Definition property.h:78
P * makeProperty(const std::string &name_, const typename P::ValueType &v)
Definition property.h:116
void writeToCSV(std::ostream &os) const
Definition property.cpp:70
void fillKnownKernels(std::vector< std::string > &types) const
AbstractRobustKernelCreator * creator(const std::string &tag) const
static RobustKernelFactory * instance()
return the instance
Sparse matrix which uses blocks.
SparseMatrixBlock * block(int r, int c, bool alloc=false)
stop iterating based on the gain which is (oldChi - currentChi) / currentChi.
int optimize(int iterations, bool online=false)
void setForceStopFlag(bool *flag)
void setVerbose(bool verbose)
virtual bool initializeOptimization(HyperGraph::EdgeSet &eset)
virtual void computeInitialGuess()
void setAlgorithm(OptimizationAlgorithm *algorithm)
const BatchStatisticsContainer & batchStatistics() const
void setComputeBatchStatistics(bool computeBatchStatistics)
virtual Vertex * findGauge()
finds a gauge in the graph to remove the undefined dof.
const VertexContainer & activeVertices() const
the vertices active in the current optimization
OptimizationAlgorithm * solver()
virtual bool updateInitialization(HyperGraph::VertexSet &vset, HyperGraph::EdgeSet &eset)
bool computeMarginals(SparseBlockMatrix< MatrixX > &spinv, const std::vector< std::pair< int, int > > &blockIndices)
#define CL_RED(s)
void sigquit_handler(int sig)
Definition g2o.cpp:89
static bool hasToStop
Definition g2o.cpp:59
Property< std::string > StringProperty
Definition property.h:152
void loadStandardTypes(DlWrapper &dlTypesWrapper, int argc, char **argv)
std::vector< G2OBatchStatistics > BatchStatisticsContainer
Definition batch_stats.h:86
bool saveGnuplot(const std::string &gnudump, const OptimizableGraph &optimizer)
bool dumpEdges(std::ostream &os, const OptimizableGraph &optimizer)
double get_monotonic_time()
Definition timeutil.cpp:43
void loadStandardSolver(DlWrapper &dlSolverWrapper, int argc, char **argv)
Sort Edges for inserting them sequentially.
Definition g2o.cpp:66
std::set< int > dimensions() const
bool isSolverSuitable(const OptimizationAlgorithmProperty &solverProperty, const std::set< int > &vertDims=std::set< int >()) const
virtual bool addEdge(HyperGraph::Edge *e)
bool addPostIterationAction(HyperGraphAction *action)
add an action to be executed after each iteration
virtual bool save(std::ostream &os, int level=0) const
save the graph to a stream. Again uses the Factory system.
virtual bool addVertex(HyperGraph::Vertex *v, Data *userData)
virtual bool load(std::istream &is)
double chi2() const
returns the chi2 of the current configuration
Vertex * vertex(int id)
returns the vertex number id appropriately casted
void setRenamedTypesFromString(const std::string &types)

References g2o::SparseOptimizer::activeVertices(), g2o::OptimizableGraph::addEdge(), g2o::OptimizableGraph::addPostIterationAction(), g2o::OptimizableGraph::addVertex(), g2o::SparseOptimizer::batchStatistics(), g2o::SparseBlockMatrix< MatrixType >::block(), g2o::OptimizableGraph::chi2(), CL_RED, g2o::SparseOptimizer::computeActiveErrors(), g2o::SparseOptimizer::computeInitialGuess(), g2o::SparseOptimizer::computeMarginals(), g2o::AbstractRobustKernelCreator::construct(), g2o::OptimizationAlgorithmFactory::construct(), g2o::RobustKernelFactory::creator(), g2o::OptimizableGraph::Vertex::dimension(), g2o::OptimizableGraph::dimensions(), g2o::dumpEdges(), g2o::HyperGraph::edges(), g2o::RobustKernelFactory::fillKnownKernels(), g2o::SparseOptimizer::findGauge(), g2o::SparseOptimizer::gaugeFreedom(), g2o::get_monotonic_time(), hasToStop, g2o::OptimizableGraph::Vertex::hessianIndex(), g2o::HyperGraph::Vertex::id(), g2o::SparseOptimizer::initializeOptimization(), g2o::OptimizableGraph::initMultiThreading(), g2o::Factory::instance(), g2o::OptimizationAlgorithmFactory::instance(), g2o::RobustKernelFactory::instance(), g2o::OptimizableGraph::isSolverSuitable(), g2o::OptimizationAlgorithmFactory::listSolvers(), g2o::OptimizableGraph::load(), g2o::loadStandardSolver(), g2o::loadStandardTypes(), g2o::PropertyMap::makeProperty(), g2o::SparseOptimizer::optimize(), g2o::CommandArgs::param(), g2o::CommandArgs::paramLeftOver(), g2o::CommandArgs::parseArgs(), g2o::CommandArgs::parsedParam(), g2o::OptimizationAlgorithm::printProperties(), g2o::Factory::printRegisteredTypes(), g2o::OptimizationAlgorithmProperty::requiresMarginalize, g2o::OptimizableGraph::save(), g2o::saveGnuplot(), g2o::SparseOptimizer::setAlgorithm(), g2o::SparseOptimizer::setComputeBatchStatistics(), g2o::OptimizableGraph::Vertex::setFixed(), g2o::SparseOptimizer::setForceStopFlag(), g2o::SparseOptimizerTerminateAction::setGainThreshold(), g2o::OptimizableGraph::Vertex::setMarginalized(), g2o::SparseOptimizerTerminateAction::setMaxIterations(), g2o::OptimizableGraph::setRenamedTypesFromString(), g2o::SparseOptimizer::setVerbose(), g2o::HyperDijkstra::shortestPaths(), sigquit_handler(), g2o::SparseOptimizer::solver(), g2o::Factory::tag(), g2o::SparseOptimizer::updateInitialization(), g2o::OptimizationAlgorithm::updatePropertiesFromString(), g2o::OptimizableGraph::vertex(), g2o::HyperGraph::Edge::vertex(), g2o::HyperGraph::Edge::vertices(), g2o::HyperGraph::vertices(), g2o::HyperDijkstra::visited(), and g2o::PropertyMap::writeToCSV().

◆ sigquit_handler()

void sigquit_handler ( int  sig)

Definition at line 89 of file g2o.cpp.

89 {
90 if (sig == SIGINT) {
91 hasToStop = 1;
92 static int cnt = 0;
93 if (cnt++ == 2) {
94 cerr << __PRETTY_FUNCTION__ << " forcing exit" << endl;
95 exit(1);
96 }
97 }
98}
#define __PRETTY_FUNCTION__
Definition macros.h:90

References __PRETTY_FUNCTION__, and hasToStop.

Referenced by main().

Variable Documentation

◆ hasToStop

bool hasToStop = false
static

Definition at line 59 of file g2o.cpp.

Referenced by main(), and sigquit_handler().