posegraph3.cpp
Go to the documentation of this file.
1 /**********************************************************************
2  *
3  * This source code is part of the Tree-based Network Optimizer (TORO)
4  *
5  * TORO Copyright (c) 2007 Giorgio Grisetti, Cyrill Stachniss,
6  * Slawomir Grzonka, and Wolfram Burgard
7  *
8  * TORO is licences under the Common Creative License,
9  * Attribution-NonCommercial-ShareAlike 3.0
10  *
11  * You are free:
12  * - to Share - to copy, distribute and transmit the work
13  * - to Remix - to adapt the work
14  *
15  * Under the following conditions:
16  *
17  * - Attribution. You must attribute the work in the manner specified
18  * by the author or licensor (but not in any way that suggests that
19  * they endorse you or your use of the work).
20  *
21  * - Noncommercial. You may not use this work for commercial purposes.
22  *
23  * - Share Alike. If you alter, transform, or build upon this work,
24  * you may distribute the resulting work only under the same or
25  * similar license to this one.
26  * * Any of the above conditions can be waived if you get permission
27  * from the copyright holder. Nothing in this license impairs or
28  * restricts the author's moral rights.
29  *
30  * TORO is distributed in the hope that it will be useful,
31  * but WITHOUT ANY WARRANTY; without even the implied
32  * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
33  * PURPOSE.
34  **********************************************************************/
35 
42 #include "posegraph3.h"
43 
44 #include <fstream>
45 #include <sstream>
46 #include <string>
47 
48 using namespace std;
49 
50 namespace AISNavigation {
51 
52 #define LINESIZE 81920
53 
54 
55 //#define DEBUG(i) if (verboseLevel>i) cerr
56 
57 
58 bool TreePoseGraph3::load(const char* filename, bool overrideCovariances, bool twoDimensions){
59  clear();
60  ifstream is(filename);
61  if (!is)
62  return false;
63 
64  while(is){
65  char buf[LINESIZE];
66  is.getline(buf,LINESIZE);
67  istringstream ls(buf);
68  string tag;
69  ls >> tag;
70 
71  if (twoDimensions){
72  if (tag=="VERTEX"){
73  int id;
74  Pose p(0.,0.,0.,0.,0.,0.);
75  ls >> id >> p.x() >> p.y() >> p.yaw();
76  TreePoseGraph3::Vertex* v=addVertex(id,p);
77  if (v){
78  v->transformation=Transformation(p);
79  }
80  }
81  } else {
82  if (tag=="VERTEX3"){
83  int id;
84  Pose p;
85  ls >> id >> p.x() >> p.y() >> p.z() >> p.roll() >> p.pitch() >> p.yaw();
86  TreePoseGraph3::Vertex* v=addVertex(id,p);
87  if (v){
88  v->transformation=Transformation(p);
89  }
90  }
91  }
92  }
93  is.clear(); /* clears the end-of-file and error flags */
94  is.seekg(0, ios::beg);
95 
96  //bool edgesOk=true;
97  while(is){
98  char buf[LINESIZE];
99  is.getline(buf,LINESIZE);
100  istringstream ls(buf);
101  string tag;
102  ls >> tag;
103 
104  if (twoDimensions){
105  if (tag=="EDGE"){
106  int id1, id2;
107  Pose p(0.,0.,0.,0.,0.,0.);
109  ls >> id1 >> id2 >> p.x() >> p.y() >> p.yaw();
111  if (! overrideCovariances){
112  ls >> m[0][0] >> m[0][1] >> m[1][1] >> m[2][2] >> m[0][2] >> m[1][2];
113  m[2][0]=m[0][2]; m[2][1]=m[1][2]; m[1][0]=m[0][1];
114  }
115 
116  TreePoseGraph3::Vertex* v1=vertex(id1);
117  TreePoseGraph3::Vertex* v2=vertex(id2);
118  Transformation t(p);
119  if (!addEdge(v1, v2,t ,m)){
120  cerr << "Fatal, attempting to insert an edge between non existing nodes, skipping";
121  cerr << "edge=" << id1 <<" -> " << id2 << endl;
122  //edgesOk=false;
123  }
124  }
125  } else {
126  if (tag=="EDGE3"){
127  int id1, id2;
128  Pose p;
130  ls >> id1 >> id2 >> p.x() >> p.y() >> p.z() >> p.roll() >> p.pitch() >> p.yaw();
132  if (! overrideCovariances){
133  for (int i=0; i<6; i++)
134  for (int j=i; j<6; j++)
135  ls >> m[i][j];
136  }
137  TreePoseGraph3::Vertex* v1=vertex(id1);
138  TreePoseGraph3::Vertex* v2=vertex(id2);
139  Transformation t(p);
140  if (!addEdge(v1, v2,t ,m)){
141  cerr << "Fatal, attempting to insert an edge between non existing nodes, skipping";
142  cerr << "edge=" << id1 <<" -> " << id2 << endl;
143  //edgesOk=false;
144  }
145  }
146  }
147  }
148  return true;
149  //return edgesOk;
150 }
151 
152 bool TreePoseGraph3::loadEquivalences(const char* filename){
153  ifstream is(filename);
154  if (!is)
155  return false;
156  EdgeList suppressed;
157  uint equivCount=0;
158  while (is){
159  char buf[LINESIZE];
160  is.getline(buf, LINESIZE);
161  istringstream ls(buf);
162  string tag;
163  ls >> tag;
164  if (tag=="EQUIV"){
165  int id1, id2;
166  ls >> id1 >> id2;
167  Edge* e=edge(id1,id2);
168  if (!e)
169  e=edge(id2,id1);
170  if (e){
171  suppressed.push_back(e);
172  equivCount++;
173  }
174  }
175  }
176  for (EdgeList::iterator it=suppressed.begin(); it!=suppressed.end(); it++){
177  Edge* e=*it;
178  if (e->v1->id > e->v2->id)
179  revertEdge(e);
180  collapseEdge(e);
181  }
182  return true;
183 }
184 
185 bool TreePoseGraph3::saveGnuplot(const char* filename){
186  ofstream os(filename);
187  if (!os)
188  return false;
189  for (TreePoseGraph3::VertexMap::iterator it=vertices.begin(); it!=vertices.end(); it++){
190  TreePoseGraph3::Vertex* v=it->second;
191  v->pose=v->transformation.toPoseType();
192  }
193  for (TreePoseGraph3::EdgeMap::const_iterator it=edges.begin(); it!=edges.end(); it++){
194  const TreePoseGraph3::Edge * e=it->second;
195  const Vertex* v1=e->v1;
196  const Vertex* v2=e->v2;
197 
198  os << v1->pose.x() << " " << v1->pose.y() << " " << v1->pose.z() << " "
199  << v1->pose.roll() << " " << v1->pose.pitch() << " " << v1->pose.yaw() <<endl;
200  os << v2->pose.x() << " " << v2->pose.y() << " " << v2->pose.z() << " "
201  << v2->pose.roll() << " " << v2->pose.pitch() << " " << v2->pose.yaw() <<endl;
202  os << endl << endl;
203  }
204  return true;
205 
206 }
207 
208 bool TreePoseGraph3::save(const char* filename){
209  ofstream os(filename);
210  if (!os)
211  return false;
212 
213  for (TreePoseGraph3::VertexMap::iterator it=vertices.begin(); it!=vertices.end(); it++){
214  TreePoseGraph3::Vertex* v=it->second;
215  v->pose=v->transformation.toPoseType();
216 
217  os << "VERTEX3 "
218  << v->id << " "
219  << v->pose.x() << " "
220  << v->pose.y() << " "
221  << v->pose.z() << " "
222  << v->pose.roll() << " "
223  << v->pose.pitch() << " "
224  << v->pose.yaw() << endl;
225  }
226  for (TreePoseGraph3::EdgeMap::const_iterator it=edges.begin(); it!=edges.end(); it++){
227  const TreePoseGraph3::Edge * e=it->second;
228  os << "EDGE3 " << e->v1->id << " " << e->v2->id << " ";
229  Pose p=e->transformation.toPoseType();
230  os << p.x() << " " << p.y() << " " << p.z() << " " << p.roll() << " " << p.pitch() << " " << p.yaw() << " ";
231  for (int i=0; i<6; i++)
232  for (int j=i; j<6; j++)
233  os << e->informationMatrix[i][j] << " ";
234  os << endl;
235  }
236  return true;
237 }
238 
241 struct IdPrinter{
242  IdPrinter(std::ostream& _os):os(_os){}
243  std::ostream& os;
244  void perform(TreePoseGraph3::Vertex* v){
245  std::cout << "(" << v->id << "," << v->level << ")" << endl;
246  }
247 };
248 
249 void TreePoseGraph3::printDepth( std::ostream& os ){
250  IdPrinter ip(os);
251  treeDepthVisit(ip, root);
252 }
253 
254 void TreePoseGraph3::printWidth( std::ostream& os ){
255  IdPrinter ip(os);
256  treeBreadthVisit(ip);
257 }
258 
263 struct PosePropagator{
264  void perform(TreePoseGraph3::Vertex* v){
265  if (!v->parent)
266  return;
267  TreePoseGraph3::Transformation tParent(v->parent->transformation);
268  TreePoseGraph3::Transformation tNode=tParent*v->parentEdge->transformation;
269 
270  assert(v->parentEdge->v1==v->parent);
271  assert(v->parentEdge->v2==v);
272  v->transformation=tNode;
273  }
274 };
275 
276 void TreePoseGraph3::initializeOnTree(){
277  PosePropagator pp;
278  treeDepthVisit(pp, root);
279 }
280 
281 
282 void TreePoseGraph3::printEdgesStat(std::ostream& os){
283  for (TreePoseGraph3::EdgeMap::const_iterator it=edges.begin(); it!=edges.end(); it++){
284  const TreePoseGraph3::Edge * e=it->second;
285  os << "EDGE " << e->v1->id << " " << e->v2->id << " ";
286  Pose p=e->transformation.toPoseType();
287  os << p.x() << " " << p.y() << " " << p.z() << " " << p.roll() << " " << p.pitch() << " " << p.yaw() << endl;
288  os << " top=" << e->top->id << " length=" << e->length << endl;
289  }
290 }
291 
292 void TreePoseGraph3::revertEdgeInfo(Edge* e){
293  // here we assume uniform covariances, and we neglect the transofrmation
294  // induced by the Jacobian when reverting the link
295  e->transformation=e->transformation.inv();
296 };
297 
298 void TreePoseGraph3::initializeFromParentEdge(Vertex* v){
299  Transformation tp=Transformation(v->parent->pose)*v->parentEdge->transformation;
300  v->transformation=tp;
301  v->pose=tp.toPoseType();
302  v->parameters=v->parentEdge->transformation;
303 }
304 
305 
306 void TreePoseGraph3::collapseEdge(Edge* e){
307  Vertex* v1=e->v1;
308  Vertex* v2=e->v2;
309 
310  // all the edges of v2 become outgoing
311  for (EdgeList::iterator it=v2->edges.begin(); it!=v2->edges.end(); it++){
312  if ( (*it)->v1!=v2 )
313  revertEdge(*it);
314  }
315 
316  // all the edges of v1 become outgoing
317  for (EdgeList::iterator it=v1->edges.begin(); it!=v1->edges.end(); it++){
318  if ( (*it)->v1!=v1 )
319  revertEdge(*it);
320  }
321 
322  assert(e->v1==v1);
323 
324  InformationMatrix I12=e->informationMatrix;
325  CovarianceMatrix C12=I12.inv();
326  Transformation T12=e->transformation;
327  Pose p12=T12.toPoseType();
328 
329  //Transformation iT12=T12.inv();
330 
331  //compute the marginal information of the nodes in the path v1-v2-v*
332  for (EdgeList::iterator it2=v2->edges.begin(); it2!=v2->edges.end(); it2++){
333  Edge* e2=*it2;
334  if (e2->v1==v2){ //edge leaving v2
335  Transformation T2x=e2->transformation;
336  Pose p2x=T2x.toPoseType();
337  InformationMatrix I2x=e2->informationMatrix;
338  CovarianceMatrix C2x=I2x.inv();
339 
340  //compute the estimate of the vertex based on the path v1-v2-vx
341 
342  //Transformation tr=iT12*T2x;
343 
344  CovarianceMatrix CM=C2x;
345 
346 
347  Transformation T1x_pred=T12*e2->transformation;
348  Covariance C1x_pred=C12+C2x;
349  InformationMatrix I1x_pred=C1x_pred.inv();
350 
351  e2->transformation=T1x_pred;
352  e2->informationMatrix=I1x_pred;
353  }
354  }
355 
356  //all the edges leaving v1 and leaving v2 and leading to the same point are merged
357  std::list<Transformation> tList;
358  std::list<InformationMatrix> iList;
359  std::list<Vertex*> vList;
360 
361  //others are transformed and added to v1
362  for (EdgeList::iterator it2=v2->edges.begin(); it2!=v2->edges.end(); it2++){
363  Edge* e1x=0;
364  Edge* e2x=0;
365  if ( ((*it2)->v1!=v1)){
366  e2x=*it2;
367  for (EdgeList::iterator it1=v1->edges.begin(); it1!=v1->edges.end(); it1++){
368  if ((*it1)->v2==(*it2)->v2)
369  e1x=*it1;
370  }
371 
372  }
373  // FIXME
374  // edges leading to the same node are ignored
375  // should be merged
376  if (e1x && e2x){
377  // here goes something for mergin the constraints, according to the information matrices.
378  // in 3D it is a nightmare, so i postpone this, and i simply ignore the redundant constraints.
379  // the resultng system is overconfident
380  }
381  if (!e1x && e2x){
382  tList.push_back(e2x->transformation);
383  iList.push_back(e2x->informationMatrix);
384  vList.push_back(e2x->v2);
385  }
386  }
387  removeVertex(v2->id);
388 
389  std::list<Transformation>::iterator t=tList.begin();
390  std::list<InformationMatrix>::iterator i=iList.begin();
391  std::list<Vertex*>::iterator v=vList.begin();
392  while (i!=iList.end()){
393  addEdge(v1,*v,*t,*i);
394  i++;
395  t++;
396  v++;
397  }
398 }
399 
400 void TreePoseGraph3::recomputeAllTransformations(){
402  treeDepthVisit(tp,root);
403 }
404 
405 }; //namespace AISNavigation
AISNavigation::IdPrinter
A class (struct) used to print vertex information to a stream. Needed for debugging.
Definition: posegraph2.cpp:198
v1
v1
edges
vector< MFAS::KeyPair > edges
CM
int CM
tango_gl::vertices
static const float vertices[]
Definition: quad.cpp:39
os
ofstream os("timeSchurFactors.csv")
AISNavigation::Transformation3::toPoseType
Pose3< T > toPoseType() const
AISNavigation::Pose3
Definition: transformation3.h:108
LINESIZE
#define LINESIZE
Definition: posegraph3.cpp:52
AISNavigation::IdPrinter::IdPrinter
IdPrinter(std::ostream &_os)
Definition: posegraph3.cpp:242
j
std::ptrdiff_t j
filename
filename
DMatrix::inv
DMatrix inv() const
posegraph3.h
AISNavigation::TreePoseGraph< Operations3D< double > >::Covariance
Operations3D< double > ::CovarianceType Covariance
Definition: posegraph.h:97
AISNavigation::uint
unsigned int uint
Definition: posegraph2.cpp:54
m
Matrix3f m
p
Point3_ p(2)
AISNavigation::TreePoseGraph3::TransformationPropagator
A class (struct) to compute the parameterization of the vertex v.
Definition: posegraph3.h:129
e
Array< double, 1, 3 > e(1./3., 0.5, 2.)
DMatrix::I
static DMatrix I(int)
AISNavigation::IdPrinter::perform
void perform(TreePoseGraph3::Vertex *v)
Definition: posegraph3.cpp:244
std
id
id
v
Array< int, Dynamic, 1 > v
AISNavigation::PosePropagator::perform
void perform(TreePoseGraph3::Vertex *v)
Definition: posegraph3.cpp:264
root
root
t
Point2 t(10, 10)
AISNavigation::TreePoseGraph< Operations3D< double > >::EdgeList
std::list< Edge * > EdgeList
Definition: posegraph.h:119
AISNavigation
Definition: posegraph.h:57
i
int i
DMatrix
Definition: dmatrix.h:46
v2
v2
AISNavigation::Transformation3
Definition: transformation3.h:256
AISNavigation::PosePropagator
A class (struct) for realizing the pose update of the individual nodes. Assumes the correct order of ...
Definition: posegraph2.cpp:219


rtabmap
Author(s): Mathieu Labbe
autogenerated on Thu Jul 25 2024 02:50:14