g2o
converteSegmentLine.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 <signal.h>
28 #include <iostream>
29 #include <iomanip>
30 #include <string>
31 #include <fstream>
32 #include <sstream>
33 #include <algorithm>
34 #include <cassert>
35 
36 #include "dl_wrapper.h"
37 #include "output_helper.h"
38 #include "g2o_common.h"
39 
42 #include "g2o/core/factory.h"
46 #include "g2o/core/batch_stats.h"
49 
50 #include "g2o/stuff/macros.h"
51 #include "g2o/stuff/color_macros.h"
52 #include "g2o/stuff/command_args.h"
54 #include "g2o/stuff/string_tools.h"
55 #include "g2o/stuff/timeutil.h"
57 
58 static bool hasToStop=false;
59 
60 using namespace std;
61 using namespace g2o;
62 
63 // sort according to max id, dimension
65  bool operator()(SparseOptimizer::Edge* const & e1, SparseOptimizer::Edge* const & e2)
66  {
67  const SparseOptimizer::Vertex* to1 = static_cast<const SparseOptimizer::Vertex*>(e1->vertices()[1]);
68  const SparseOptimizer::Vertex* to2 = static_cast<const SparseOptimizer::Vertex*>(e2->vertices()[1]);
69 
70  int i11 = e1->vertices()[0]->id(), i12 = e1->vertices()[1]->id();
71  if (i11 > i12){
72  swap(i11, i12);
73  }
74  int i21 = e2->vertices()[0]->id(), i22 = e2->vertices()[1]->id();
75  if (i21 > i22){
76  swap(i21, i22);
77  }
78  if (i12 < i22)
79  return true;
80  if (i12 > i22)
81  return false;
82  // push the odometry to be the first
83  return to1->dimension() > to2->dimension();
84  }
85 };
86 
87 void sigquit_handler(int sig)
88 {
89  if (sig == SIGINT) {
90  hasToStop = 1;
91  static int cnt = 0;
92  if (cnt++ == 2) {
93  cerr << __PRETTY_FUNCTION__ << " forcing exit" << endl;
94  exit(1);
95  }
96  }
97 }
98 
99 struct LineInfo {
101  line=new VertexLine2D();
102  line->setId(s->id());
103  line->setEstimate(computeLineParameters(s->estimateP1(), s->estimateP2()));
104  p1=0;
105  p2=0;
106  }
110 };
111 
112 typedef std::map<int, LineInfo> LineInfoMap;
113 
114 int main(int argc, char** argv)
115 {
116  string outputfilename;
117  CommandArgs arg;
118  arg.param("o", outputfilename, "", "output final version of the graph");
119  arg.paramLeftOver("graph-input", inputFilename, "", "graph file which will be processed", true);
120 
121 
122  arg.parseArgs(argc, argv);
123 
124  // registering all the types from the libraries
125  DlWrapper dlTypesWrapper;
126  loadStandardTypes(dlTypesWrapper, argc, argv);
127 
128  if (inputFilename.size() == 0) {
129  cerr << "No input data specified" << endl;
130  return 0;
131  } else if (inputFilename == "-") {
132  cerr << "Read input from stdin" << endl;
133  if (!optimizer.load(cin)) {
134  cerr << "Error loading graph" << endl;
135  return 2;
136  }
137  } else {
138  cerr << "Read input from " << inputFilename << endl;
139  ifstream ifs(inputFilename.c_str());
140  if (!ifs) {
141  cerr << "Failed to open file" << endl;
142  return 1;
143  }
144  if (!optimizer.load(ifs)) {
145  cerr << "Error loading graph" << endl;
146  return 2;
147  }
148  }
149  cerr << "Loaded " << optimizer.vertices().size() << " vertices" << endl;
150  cerr << "Loaded " << optimizer.edges().size() << " edges" << endl;
151 
152  LineInfoMap lmap;
153  OptimizableGraph outGraph();
154  // insert all lines in the infomap
155  int currentId = 0;
156  for (OptimizableGraph::VertexIDMap::iterator it=optimizer.vertices().begin(); it!=optimizer->vertices().end(); it++){
157  VertexSE2 *p=dynamic_cast<VertexSegment2D*> (it->second());
158  if (p){
159  VertexSE2 *np=p->clone();
160  np->setId(p->id());
161  outGraph->addVertex(np);
162  }
163  VertexSegment2D* s=dynamic_cast<VertexSegment2D*> (it->second());
164  if (s){
165  lmap.insert(make_pair(s->id(), LineInfo(s)));
166  }
167  currentId = it->first;
168  }
169  currentId++;
170  for (OptimizableGraph::EdgeSet::iterator it=optimizer.edges().begin(); it!=optimizer->edges().end(); it++){
171  EdgeSE2* ods=dynamic_cast<EdgeSE2*> (*it);
172  if (ods){
173  EdgeSE2* ods2=new EdgeSE2();
174  ods2->setMeasdurement(ods2->measurement());
175  ods2->setInformation(ods2->information());
176  ods2->vertices[0]=outGraph->vertices(ods->vertices()[0]->id());
177  ods2->vertices[1]=outGraph->vertices(ods->vertices()[1]->id());
178  outGraph->addEdge(ods2);
179  }
180 
181  EdgeSE2Segment2D* es=dynamic_cast<EdgeSE2Segment2D*> (*it);
182  EdgeSE2Segment2DLine* el=dynamic_cast<EdgeSE2Segment2DLine*> (*it);
183  EdgeSE2Segment2DPointLine* espl=dynamic_cast<EdgeSE2Segment2DPointLine*> (*it);
184 
185  if (es || el || espl){
186  VertexSE2* pose = dynamic_cast<VertexSE2*>((*it)->vertices()[0]);
187  VertexSegment2D* segment = dynamic_cast<VertexSegment2D*>((*it)->vertices()[1]);
188  if (!pose)
189  continue;
190  pose=dynamic_cast<VertexSE2*>(outGraph->vertex(pose->id()));
191  LineInfo& linfo = lmap[(*it)->vertices()[0]->id()];
192  VertexLine* line =linfo->line;
193 
194  EdgeSE2Line el2=new EdgeSE2Line();
195  VertexPoint* & p1=linfo->p1;
196  VertexPoint* & p2=linfo->p2;
197  el2->vertices()[0]=p;
198  el2->vertices()[1]=l;
199  if (el) {
200  el2->setMeasurement(el->measurement());
201  el2->setInformation(el->information());
202  outGraph->addEdge(el2);
203  }
204  if (es) {
205  el2-setMeasurement(computeLineParameters(s->measurementP1(), s->measurementP2()));
206  if (!p1){
207  p1=new VertexPointXY();
208  p1->setEstimate(segment->estimateP1());
209  p1->setId(currentId++);
210  outGraph->addVertex(p1);
211 
213  p1e->vertices()[0]=line;
214  p1e->vertices()[1]=p1;
215  p1e->setMeasurement(0);
216  Matrix1d p1i;
217  p1i(0,0)=1e6;
218  p1e->setInformation(p1i);
219  outGraph->addEdge(p1);
220  }
221  if (! p2) {
222  p2=new VertexPointXY();
223  p2->setEstimate(segment->estimateP2());
224  p2->setId(currentId++);
225  outGraph->addVertex(p2);
226 
228  p2e->vertices()[0]=line;
229  p2e->vertices()[1]=p2;
230  p2e->setMeasurement(0);
231  Matrix1d p2i;
232  p2i(0,0)=1e6;
233  p2e->setInformation(p2i);
234  outGraph->addEdge(p2);
235  }
236  EdgeSE2PointXY* p1e = new EdgeSE2PointXY();
237  p1e->vertices()[0]=line;
238  p1e->vertices()[1]=p1;
239  p1e->setMeasurement(es->measurementP1());
240  Matrix4d si=segment->information();
241  Matrix2d p1i=si.block<2,2>(0,0);
242  p1e->setInformation(p1i);
243  outGraph->addEdge(p1e);
244 
245  EdgeSE2PointXY* p2e = new EdgeSE2PointXY();
246  p2e->vertices()[0]=line;
247  p2e->vertices()[1]=p2;
248  p2e->setMeasurement(es->measurementP2());
249  Matrix4d si=segment->information();
250  Matrix2d p2i=si.block<2,2>(2,2);
251  p2e->setInformation(p2i);
252  outGraph->addEdge(p2e);
253  }
254 
255  if (espl) {
256  Vector2d lparams;
257  lparams[0]=espl->theta();
258  Vector2d n(cos(espl->theta()), sin(espl->theta()));
259  lparams[1]=n.dot(espl->point());
260  Matrix2d li;
261  li << 1000, 0, 0, 100;
262  el2->setMeasurement(lparams);
263  el2->setInformation(li);
264 
265  VertexPointXY*& pX = (espl->pointNum()==0 )? p1:p2;
266 
267  if (!pX){
268  pX=new VertexPointXY();
269  pX->setEstimate(segment->estimatePX());
270  pX->setId(currentId++);
271  outGraph->addVertex(pX);
272 
274  pXe->vertices()[0]=line;
275  pXe->vertices()[1]=pX;
276  pXe->setMeasurement(0);
277  Matrix1d pXi;
278  pXi(0,0)=1e6;
279  pXe->setInformation(pXi);
280  outGraph->addEdge(pX);
281  }
282 
283  EdgeSE2PointXY* pXe = new EdgeSE2PointXY();
284  pXe->vertices()[0]=line;
285  pXe->vertices()[1]=pX;
286  pXe->setMeasurement(es->measurementPX());
287  Matrix4d si=segment->information();
288  Matrix2d pXi=si.block<2,2>(0,0);
289  pXe->setInformation(pXi);
290  outGraph->addEdge(pXe);
291  }
292  }
293  }
294 
295 
296  if (outputfilename.size() > 0) {
297  if (outputfilename == "-") {
298  cerr << "saving to stdout";
299  optimizer.save(cout);
300  } else {
301  cerr << "saving " << outputfilename << " ... ";
302  optimizer.save(outputfilename.c_str());
303  }
304  cerr << "done." << endl;
305  }
306 
307  // destroy all the singletons
308  //Factory::destroy();
309  //OptimizationAlgorithmFactory::destroy();
310  //HyperGraphActionLibrary::destroy();
311 
312  return 0;
313 }
Eigen::Vector2d computeLineParameters(const Eigen::Vector2d &p1, const Eigen::Vector2d &p2)
Definition: simutils.cpp:120
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
VertexLine2D * line
2D edge between two Vertex2
Definition: edge_se2.h:40
void loadStandardTypes(DlWrapper &dlTypesWrapper, int argc, char **argv)
Definition: g2o_common.cpp:96
virtual void setMeasurement(const Measurement &m)
Definition: base_edge.h:76
2D pose Vertex, (x,y,theta)
Definition: vertex_se2.h:41
const VertexIDMap & vertices() const
Definition: hyper_graph.h:225
Vertex * vertex(int id)
returns the vertex number id appropriately casted
bool operator()(SparseOptimizer::Edge *const &e1, SparseOptimizer::Edge *const &e2)
utility functions for handling time related stuff
VertexPointXY * p2
virtual void setId(int id)
sets the id of the node in the graph be sure that the graph keeps consistent after changing the id ...
const VertexContainer & vertices() const
Definition: hyper_graph.h:178
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)
EIGEN_STRONG_INLINE void setInformation(const InformationType &information)
Definition: base_edge.h:69
void param(const std::string &name, bool &p, bool defValue, const std::string &desc)
G2O_TYPES_SLAM2D_ADDONS_API Vector2D measurementP1()
std::map< int, LineInfo > LineInfoMap
void setEstimate(const EstimateType &et)
set the estimate for the vertex also calls updateCache()
Definition: base_vertex.h:101
Loading libraries during run-time.
Definition: dl_wrapper.h:44
EIGEN_STRONG_INLINE const InformationType & information() const
information matrix of the constraint
Definition: base_edge.h:67
int main(int argc, char **argv)
Sort Edges for inserting them sequentially.
Definition: g2o.cpp:67
VertexPointXY * p1
Vector2D estimateP1() const
G2O_TYPES_SLAM2D_ADDONS_API Vector2D measurementP2()
static bool hasToStop
virtual Vertex * clone() const
returns a deep copy of the current vertex
Vector2D estimateP2() const
virtual bool addEdge(HyperGraph::Edge *e)
virtual bool addVertex(HyperGraph::Vertex *v, Data *userData)
LineInfo(VertexSegment2D *s)
void sigquit_handler(int sig)
EIGEN_STRONG_INLINE const Measurement & measurement() const
accessor functions for the measurement represented by the edge
Definition: base_edge.h:75