g2o
Loading...
Searching...
No Matches
generate_commands.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 <algorithm>
28#include <cassert>
29#include <csignal>
30#include <fstream>
31#include <iomanip>
32#include <iostream>
33#include <sstream>
34#include <string>
35
36#include "g2o/core/factory.h"
41#include "g2o/stuff/macros.h"
43#include "g2o/stuff/timeutil.h"
44
45static bool hasToStop = false;
46
47using namespace std;
48using namespace g2o;
49
50// sort according to max id, dimension, min id
53 SparseOptimizer::Edge* const& e2) {
54 const SparseOptimizer::Vertex* to1 =
55 static_cast<const SparseOptimizer::Vertex*>(e1->vertices()[0]);
56 const SparseOptimizer::Vertex* to2 =
57 static_cast<const SparseOptimizer::Vertex*>(e2->vertices()[0]);
58
59 int i11 = e1->vertices()[0]->id(), i12 = e1->vertices()[1]->id();
60 if (i11 > i12) {
61 swap(i11, i12);
62 }
63 int i21 = e2->vertices()[0]->id(), i22 = e2->vertices()[1]->id();
64 if (i21 > i22) {
65 swap(i21, i22);
66 }
67 if (i12 < i22) return true;
68 if (i12 > i22) return false;
69 if (to1->dimension() !=
70 to2->dimension()) { // push the odometry to be the first
71 return to1->dimension() > to2->dimension();
72 }
73 return (i11 < i21);
74 }
75};
76
77void sigquit_handler(int sig) {
78 if (sig == SIGINT) {
79 hasToStop = 1;
80 static int cnt = 0;
81 if (cnt++ == 2) {
82 cerr << __PRETTY_FUNCTION__ << " forcing exit" << endl;
83 exit(1);
84 }
85 }
86}
87
88int main(int argc, char** argv) {
89 string inputFilename;
90 string loadLookup;
91 bool listTypes;
92 int updateGraphEachN = 10;
93 string dummy;
94 // command line parsing
95 CommandArgs arg;
96 arg.param("update", updateGraphEachN, 10,
97 "updates after x odometry nodes, (default: 10)");
98 arg.param("listTypes", listTypes, false, "list the registered types");
99 arg.param("renameTypes", loadLookup, "",
100 "create a lookup for loading types into other types,\n\t "
101 "TAG_IN_FILE=INTERNAL_TAG_FOR_TYPE,TAG2=INTERNAL2\n\t e.g., "
102 "VERTEX_CAM=VERTEX_SE3:EXPMAP");
103 arg.paramLeftOver("graph-input", inputFilename, "",
104 "graph file which will be processed", true);
105
106 arg.parseArgs(argc, argv);
107
108 if (listTypes) {
110 }
111
112 SparseOptimizer optimizer;
113
114 // Loading the input data
115 if (loadLookup.size() > 0) {
116 optimizer.setRenamedTypesFromString(loadLookup);
117 }
118 if (inputFilename.size() == 0) {
119 cerr << "No input data specified" << endl;
120 return 0;
121 } else if (inputFilename == "-") {
122 cerr << "Read input from stdin" << endl;
123 if (!optimizer.load(cin)) {
124 cerr << "Error loading graph" << endl;
125 return 2;
126 }
127 } else {
128 cerr << "Read input from " << inputFilename << endl;
129 ifstream ifs(inputFilename.c_str());
130 if (!ifs) {
131 cerr << "Failed to open file" << endl;
132 return 1;
133 }
134 if (!optimizer.load(ifs)) {
135 cerr << "Error loading graph" << endl;
136 return 2;
137 }
138 }
139 cerr << "Loaded " << optimizer.vertices().size() << " vertices" << endl;
140 cerr << "Loaded " << optimizer.edges().size() << " edges" << endl;
141
142 if (optimizer.vertices().size() == 0) {
143 cerr << "Graph contains no vertices" << endl;
144 return 1;
145 }
146
147 if (1) {
148 int maxDim = 0;
149
150 cerr << "# incremental settings" << endl;
151 cerr << "#\t solve every " << updateGraphEachN << endl;
152
153 SparseOptimizer::VertexIDMap vertices = optimizer.vertices();
154 for (SparseOptimizer::VertexIDMap::const_iterator it = vertices.begin();
155 it != vertices.end(); ++it) {
156 const SparseOptimizer::Vertex* v =
157 static_cast<const SparseOptimizer::Vertex*>(it->second);
158 maxDim = (max)(maxDim, v->dimension());
159 }
160
161 vector<SparseOptimizer::Edge*> edges;
162 for (SparseOptimizer::EdgeSet::iterator it = optimizer.edges().begin();
163 it != optimizer.edges().end(); ++it) {
164 SparseOptimizer::Edge* e = dynamic_cast<SparseOptimizer::Edge*>(*it);
165 edges.push_back(e);
166 }
167 optimizer.edges().clear();
168 optimizer.vertices().clear();
169 optimizer.setVerbose(false);
170
171 // sort the edges in a way that inserting them makes sense
172 sort(edges.begin(), edges.end(), IncrementalEdgesCompare());
173
174 int vertexCount = 0;
175 int lastOptimizedVertexCount = 0;
176 bool addNextEdge = true;
177 bool freshlyOptimized = false;
178 HyperGraph::VertexSet verticesAdded;
179 int maxInGraph = -1;
180 for (vector<SparseOptimizer::Edge*>::iterator it = edges.begin();
181 it != edges.end(); ++it) {
182 SparseOptimizer::Edge* e = *it;
183 bool optimize = false;
184
185 if (addNextEdge && !optimizer.vertices().empty()) {
186 int idMax = (max)(e->vertices()[0]->id(), e->vertices()[1]->id());
187 if (maxInGraph < idMax && !freshlyOptimized) {
188 addNextEdge = false;
189 optimize = true;
190 } else {
191 addNextEdge = true;
192 optimize = false;
193 }
194 }
195
196 SparseOptimizer::Vertex* v1 = optimizer.vertex(e->vertices()[0]->id());
197 SparseOptimizer::Vertex* v2 = optimizer.vertex(e->vertices()[1]->id());
198 if (!v1 && addNextEdge) {
199 // cerr << " adding vertex " << it->id1 << endl;
201 dynamic_cast<SparseOptimizer::Vertex*>(e->vertices()[0]);
202 bool v1Added = optimizer.addVertex(v);
203 maxInGraph = (max)(maxInGraph, v->id());
204 // cerr << "adding" << v->id() << "(" << v->dimension() << ")" << endl;
205 assert(v1Added);
206 if (!v1Added)
207 cerr << "Error adding vertex " << v->id() << endl;
208 else
209 verticesAdded.insert(v);
210 if (v->dimension() == maxDim) vertexCount++;
211
212 if (v->dimension() == 3) {
213 cout << "ADD VERTEX_XYT " << v->id() << ";" << endl;
214 } else if (v->dimension() == 6) {
215 cout << "ADD VERTEX_XYZRPY " << v->id() << ";" << endl;
216 }
217 }
218
219 if (!v2 && addNextEdge) {
221 dynamic_cast<SparseOptimizer::Vertex*>(e->vertices()[1]);
222 // cerr << " adding vertex " << v->id() << endl;
223 bool v2Added = optimizer.addVertex(v);
224 maxInGraph = (max)(maxInGraph, v->id());
225 // cerr << "adding" << v->id() << "(" << v->dimension() << ")" << endl;
226 assert(v2Added);
227 if (!v2Added)
228 cerr << "Error adding vertex " << v->id() << endl;
229 else
230 verticesAdded.insert(v);
231 if (v->dimension() == maxDim) vertexCount++;
232
233 if (v->dimension() == 3) {
234 cout << "ADD VERTEX_XYT " << v->id() << ";" << endl;
235 } else if (v->dimension() == 6) {
236 cout << "ADD VERTEX_XYZRPY " << v->id() << ";" << endl;
237 }
238 }
239
240 if (addNextEdge) {
241 if (e->dimension() == 3) {
242 static int edgeCnt = 0;
243 double* information = e->informationData();
244 double meas[3];
245 e->getMeasurementData(meas);
246 // ADD EDGE_XYT 1 1 2 .1 .2 .3 1 0 0 1 0 1;
247 cout << "ADD EDGE_XYT " << edgeCnt++ << " " << e->vertices()[0]->id()
248 << " " << e->vertices()[1]->id() << " " << meas[0] << " "
249 << meas[1] << " " << meas[2];
250 for (int i = 0; i < 3; ++i)
251 for (int j = i; j < 3; ++j) cout << " " << information[i * 3 + j];
252 cout << ";" << endl;
253 } else if (e->dimension() == 6) {
254 // TODO convert to EULER angles
255 cerr << "NOT IMPLEMENTED YET" << endl;
256 }
257 static bool firstEdge = true;
258 if (firstEdge) {
259 firstEdge = false;
260 cout << "FIX 0;" << endl;
261 }
262
263 // cerr << " adding edge " << e->vertices()[0]->id() << " " <<
264 // e->vertices()[1]->id() << endl;
265 if (!optimizer.addEdge(e)) {
266 cerr << "Unable to add edge " << e->vertices()[0]->id() << " -> "
267 << e->vertices()[1]->id() << endl;
268 }
269 }
270
271 freshlyOptimized = false;
272 if (optimize) {
273 // cerr << "Optimize" << endl;
274 if (vertexCount - lastOptimizedVertexCount >= updateGraphEachN) {
275 cout << "SOLVE_STATE;" << endl;
276 cout << "QUERY_STATE;" << endl;
277 lastOptimizedVertexCount = vertexCount;
278 }
279
280 addNextEdge = true;
281 freshlyOptimized = true;
282 --it;
283 }
284
285 } // for all edges
286 }
287
288 return 0;
289}
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)
void printRegisteredTypes(std::ostream &os, bool comment=false) const
Definition factory.cpp:167
static Factory * instance()
return the instance
Definition factory.cpp:46
const VertexContainer & vertices() const
abstract Vertex, your types must derive from that one
int id() const
returns the id
std::unordered_map< int, Vertex * > VertexIDMap
std::set< Vertex * > VertexSet
const EdgeSet & edges() const
const VertexIDMap & vertices() const
void setVerbose(bool verbose)
void sigquit_handler(int sig)
static bool hasToStop
int main()
Definition gicp_demo.cpp:44
#define __PRETTY_FUNCTION__
Definition macros.h:90
Definition jet.h:876
Sort Edges for inserting them sequentially.
Definition g2o.cpp:66
bool operator()(SparseOptimizer::Edge *const &e1, SparseOptimizer::Edge *const &e2)
virtual bool addEdge(HyperGraph::Edge *e)
virtual bool addVertex(HyperGraph::Vertex *v, Data *userData)
virtual bool load(std::istream &is)
Vertex * vertex(int id)
returns the vertex number id appropriately casted
void setRenamedTypesFromString(const std::string &types)
utility functions for handling time related stuff