g2o
sclam_laser_calib.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 
27 #include <iostream>
28 #include <map>
29 #include <csignal>
30 #include <fstream>
31 
34 #include "gm2dl_io.h"
35 
36 #include "g2o/stuff/macros.h"
37 #include "g2o/stuff/color_macros.h"
38 #include "g2o/stuff/command_args.h"
40 #include "g2o/stuff/string_tools.h"
41 #include "g2o/stuff/timeutil.h"
42 
46 #include "g2o/core/factory.h"
47 
48 using namespace std;
49 using namespace g2o;
50 
51 static bool hasToStop = false;
52 
54 G2O_USE_TYPE_GROUP(slam2d);
55 
56 void sigquit_handler(int sig)
57 {
58  if (sig == SIGINT) {
59  hasToStop = 1;
60  static int cnt = 0;
61  if (cnt++ == 2) {
62  cerr << __PRETTY_FUNCTION__ << " forcing exit" << endl;
63  exit(1);
64  }
65  }
66 }
67 
68 int main(int argc, char** argv)
69 {
70  int maxIterations;
71  bool verbose;
72  string inputFilename;
73  string gnudump;
74  string outputfilename;
75  bool initialGuess;
76  // command line parsing
77  CommandArgs commandLineArguments;
78  commandLineArguments.param("i", maxIterations, 10, "perform n iterations");
79  commandLineArguments.param("v", verbose, false, "verbose output of the optimization process");
80  commandLineArguments.param("guess", initialGuess, false, "initial guess based on spanning tree");
81  commandLineArguments.param("gnudump", gnudump, "", "dump to gnuplot data file");
82  commandLineArguments.param("o", outputfilename, "", "output final version of the graph");
83  commandLineArguments.paramLeftOver("gm2dl-input", inputFilename, "", "gm2dl file which will be processed");
84 
85  commandLineArguments.parseArgs(argc, argv);
86 
87  OptimizationAlgorithmFactory* solverFactory = OptimizationAlgorithmFactory::instance();
88 
89  SparseOptimizer optimizer;
90  optimizer.setVerbose(verbose);
91  optimizer.setForceStopFlag(&hasToStop);
92 
93  OptimizationAlgorithmProperty solverProperty;
94  optimizer.setAlgorithm(solverFactory->construct("lm_var", solverProperty));
95 
96  // loading
97  if (! Gm2dlIO::readGm2dl(inputFilename, optimizer, false)) {
98  cerr << "Error while loading gm2dl file" << endl;
99  }
100 
101  VertexSE2* laserOffset = dynamic_cast<VertexSE2*>(optimizer.vertex(numeric_limits<int>::max()));
102  //laserOffset->setEstimate(SE2()); // set to Identity
103  if (laserOffset) {
104  cerr << "Initial laser offset " << laserOffset->estimate().toVector().transpose() << endl;
105  }
106  bool gaugeFreedom = optimizer.gaugeFreedom();
107 
108  OptimizableGraph::Vertex* gauge = optimizer.findGauge();
109  if (gaugeFreedom) {
110  if (! gauge) {
111  cerr << "# cannot find a vertex to fix in this thing" << endl;
112  return 2;
113  } else {
114  cerr << "# graph is fixed by node " << gauge->id() << endl;
115  gauge->setFixed(true);
116  }
117  } else {
118  cerr << "# graph is fixed by priors" << endl;
119  }
120 
121  // sanity check
122  HyperDijkstra d(&optimizer);
124  d.shortestPaths(gauge, &f);
125  //cerr << PVAR(d.visited().size()) << endl;
126 
127  if (d.visited().size()!=optimizer.vertices().size()) {
128  cerr << CL_RED("Warning: d.visited().size() != optimizer.vertices().size()") << endl;
129  cerr << "visited: " << d.visited().size() << endl;
130  cerr << "vertices: " << optimizer.vertices().size() << endl;
131  if (1)
132  for (SparseOptimizer::VertexIDMap::const_iterator it = optimizer.vertices().begin(); it != optimizer.vertices().end(); ++it) {
133  OptimizableGraph::Vertex* v = static_cast<OptimizableGraph::Vertex*>(it->second);
134  if (d.visited().count(v) == 0) {
135  cerr << "\t unvisited vertex " << it->first << " " << (void*)v << endl;
136  v->setFixed(true);
137  }
138  }
139  }
140 
141  optimizer.initializeOptimization();
142  optimizer.computeActiveErrors();
143  cerr << "Initial chi2 = " << FIXED(optimizer.chi2()) << endl;
144 
145  //if (guessCostFunction)
146  //optimizer.computeInitialGuess(guessCostFunction);
147 
148  signal(SIGINT, sigquit_handler);
149 
150  int i=optimizer.optimize(maxIterations);
151  if (maxIterations > 0 && !i){
152  cerr << "optimize failed, result might be invalid" << endl;
153  }
154 
155  if (laserOffset) {
156  cerr << "Calibrated laser offset " << laserOffset->estimate().toVector().transpose() << endl;
157  }
158 
159  if (outputfilename.size() > 0) {
160  Gm2dlIO::updateLaserData(optimizer);
161  cerr << "Writing " << outputfilename << " ... ";
162  bool writeStatus = Gm2dlIO::writeGm2dl(outputfilename, optimizer);
163  cerr << (writeStatus ? "done." : "failed") << endl;
164  }
165 
166  if (gnudump.size() > 0) {
167  ofstream fout(gnudump.c_str());
168  for (SparseOptimizer::VertexIDMap::const_iterator it = optimizer.vertices().begin(); it != optimizer.vertices().end(); ++it) {
169  VertexSE2* v = dynamic_cast<VertexSE2*>(it->second);
170  fout << v->estimate().toVector().transpose() << endl;
171  }
172  }
173 
174  return true;
175 }
int id() const
returns the id
Definition: hyper_graph.h:148
#define __PRETTY_FUNCTION__
Definition: macros.h:89
Command line parsing of argc and argv.
Definition: command_args.h:46
HyperGraph::VertexSet & visited()
G2O_USE_TYPE_GROUP(slam2d)
Vector3D toVector() const
convert to a 3D vector (x, y, theta)
Definition: se2.h:108
describe the properties of a solver
G2O_USE_OPTIMIZATION_LIBRARY(csparse)
int main(int argc, char **argv)
int optimize(int iterations, bool online=false)
#define CL_RED(s)
Definition: color_macros.h:46
2D pose Vertex, (x,y,theta)
Definition: vertex_se2.h:41
create solvers based on their short name
const VertexIDMap & vertices() const
Definition: hyper_graph.h:225
Vertex * vertex(int id)
returns the vertex number id appropriately casted
utility functions for handling time related stuff
virtual Vertex * findGauge()
finds a gauge in the graph to remove the undefined dof.
static bool hasToStop
double chi2() const
returns the chi2 of the current configuration
bool parseArgs(int argc, char **argv, bool exitOnError=true)
void shortestPaths(HyperGraph::Vertex *v, HyperDijkstra::CostFunction *cost, double maxDistance=std::numeric_limits< double >::max(), double comparisonConditioner=1e-3, bool directed=false, double maxEdgeCost=std::numeric_limits< double >::max())
void setVerbose(bool verbose)
void setForceStopFlag(bool *flag)
void paramLeftOver(const std::string &name, std::string &p, const std::string &defValue, const std::string &desc, bool optional=false)
void setAlgorithm(OptimizationAlgorithm *algorithm)
void param(const std::string &name, bool &p, bool defValue, const std::string &desc)
A general case Vertex for optimization.
void sigquit_handler(int sig)
const EstimateType & estimate() const
return the current estimate of the vertex
Definition: base_vertex.h:99
void setFixed(bool fixed)
true => this node should be considered fixed during the optimization
virtual bool initializeOptimization(HyperGraph::EdgeSet &eset)
OptimizationAlgorithm * construct(const std::string &tag, OptimizationAlgorithmProperty &solverProperty) const