posegraph2.cpp
Go to the documentation of this file.
00001 /**********************************************************************
00002  *
00003  * This source code is part of the Tree-based Network Optimizer (TORO)
00004  *
00005  *   TORO Copyright (c) 2007 Giorgio Grisetti, Cyrill Stachniss, 
00006  *                           Slawomir Grzonka and  Wolfram Burgard
00007  *
00008  * TORO is licences under the Common Creative License,
00009  * Attribution-NonCommercial-ShareAlike 3.0
00010  *
00011  * You are free:
00012  *   - to Share - to copy, distribute and transmit the work
00013  *   - to Remix - to adapt the work
00014  *
00015  * Under the following conditions:
00016  *
00017  *   - Attribution. You must attribute the work in the manner specified
00018  *     by the author or licensor (but not in any way that suggests that
00019  *     they endorse you or your use of the work).
00020  *  
00021  *   - Noncommercial. You may not use this work for commercial purposes.
00022  *  
00023  *   - Share Alike. If you alter, transform, or build upon this work,
00024  *     you may distribute the resulting work only under the same or
00025  *     similar license to this one.
00026  *
00027  * Any of the above conditions can be waived if you get permission
00028  * from the copyright holder.  Nothing in this license impairs or
00029  * restricts the author's moral rights.
00030  *
00031  * TORO is distributed in the hope that it will be useful,
00032  * but WITHOUT ANY WARRANTY; without even the implied 
00033  * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
00034  * PURPOSE.  
00035  **********************************************************************/
00036 
00043 #include "posegraph2.hh"
00044 #include <fstream>
00045 #include <sstream>
00046 #include <string>
00047 
00048 using namespace std;
00049 
00050 namespace AISNavigation {
00051 
00052 
00053 typedef unsigned int uint;
00054 #define LINESIZE 81920
00055 
00056 
00057 #define DEBUG(i) \
00058         if (verboseLevel>i) cerr
00059 
00060 
00061 bool TreePoseGraph2::load(const char* filename, bool overrideCovariances){
00062   clear();
00063   ifstream is(filename);
00064   if (!is)
00065     return false;
00066 
00067   while(is){
00068     char buf[LINESIZE];
00069     is.getline(buf,LINESIZE);
00070     istringstream ls(buf);
00071     string tag;
00072     ls >> tag;
00073 
00074     if (tag=="VERTEX" || tag=="VERTEX2"){
00075       int id;
00076       Pose p;
00077       ls >> id >> p.x() >> p.y() >> p.theta(); 
00078       if (addVertex(id,p))
00079         DEBUG(2) << "V " << id << endl;
00080       
00081     }
00082 
00083     if (tag=="EDGE" || tag=="EDGE2"){
00084       int id1, id2;
00085       Pose p;
00086       InformationMatrix m;
00087       ls >> id1 >> id2 >> p.x() >> p.y() >> p.theta();
00088       if (overrideCovariances){
00089         m.values[0][0]=1;  m.values[1][1]=1; m.values[2][2]=1;
00090         m.values[0][1]=0;  m.values[0][2]=0; m.values[1][2]=0;
00091       } else {
00092         ls >> m.values[0][0] >> m.values[0][1] >> m.values [1][1]
00093            >> m.values[2][2] >> m.values[0][2] >> m.values [1][2];
00094       }
00095       m.values[1][0]=m.values[0][1];
00096       m.values[2][0]=m.values[0][2];
00097       m.values[2][1]=m.values[1][2];
00098       TreePoseGraph2::Vertex* v1=vertex(id1);
00099       TreePoseGraph2::Vertex* v2=vertex(id2);
00100       Transformation t(p);
00101       if (addEdge(v1, v2,t ,m))
00102          DEBUG(2) << "E " << id1 << " " << id2 <<  endl;
00103     }
00104   }
00105   return true;
00106 }
00107 
00108 bool TreePoseGraph2::loadEquivalences(const char* filename){
00109   ifstream is(filename);
00110   if (!is)
00111     return false;
00112   EdgeList suppressed;
00113   uint equivCount=0;
00114   while (is){
00115     char buf[LINESIZE];
00116     is.getline(buf, LINESIZE);
00117     istringstream ls(buf);
00118     string tag;
00119     ls >> tag;
00120     if (tag=="EQUIV"){
00121       int id1, id2;
00122       ls >> id1 >> id2;
00123       Edge* e=edge(id1,id2);
00124       if (!e)
00125         e=edge(id2,id1);
00126       if (e){
00127         suppressed.push_back(e);
00128         equivCount++;
00129       }
00130     }
00131   }
00132   for (EdgeList::iterator it=suppressed.begin(); it!=suppressed.end(); it++){
00133     Edge* e=*it;
00134     if (e->v1->id > e->v2->id)
00135       revertEdge(e);
00136     collapseEdge(e);
00137   }
00138   for (TreePoseGraph2::VertexMap::iterator it=vertices.begin(); it!=vertices.end(); it++){
00139     Vertex* v=it->second;
00140     v->edges.clear();
00141   }
00142   for (TreePoseGraph2::EdgeMap::iterator it=edges.begin(); it!=edges.end(); it++){
00143     TreePoseGraph2::Edge * e=it->second;
00144     e->v1->edges.push_back(e);
00145     e->v2->edges.push_back(e);
00146   }
00147   return true;
00148 }
00149 
00150 bool TreePoseGraph2::saveGnuplot(const char* filename){
00151   ofstream os(filename);
00152   if (!os)
00153     return false;
00154 
00155   for (TreePoseGraph2::EdgeMap::const_iterator it=edges.begin(); it!=edges.end(); it++){
00156     const TreePoseGraph2::Edge * e=it->second;
00157     const Vertex* v1=e->v1;
00158     const Vertex* v2=e->v2;
00159     
00160     os << v1->pose.x() << " " << v1->pose.y() << " " << v1->pose.theta() << endl;
00161     os << v2->pose.x() << " " << v2->pose.y() << " " << v2->pose.theta() << endl;
00162     os << endl;
00163   }
00164   return true;
00165 
00166 }
00167 
00168 bool TreePoseGraph2::save(const char* filename){
00169   ofstream os(filename);
00170   if (!os)
00171     return false;
00172   
00173   for (TreePoseGraph2::VertexMap::const_iterator it=vertices.begin(); it!=vertices.end(); it++){
00174     const TreePoseGraph2::Vertex* v=it->second;
00175     os << "VERTEX " 
00176        << v->id << " " 
00177        << v->pose.x() << " " 
00178        << v->pose.y() << " " 
00179        << v->pose.theta()<< endl; 
00180   }
00181   for (TreePoseGraph2::EdgeMap::const_iterator it=edges.begin(); it!=edges.end(); it++){
00182     const TreePoseGraph2::Edge * e=it->second;
00183     os << "EDGE " << e->v1->id << " " << e->v2->id << " ";
00184     Pose p=e->transformation.toPoseType();
00185     os << p.x() << " " << p.y() << " " << p.theta() << " ";
00186     os << e->informationMatrix.values[0][0] << " "
00187        << e->informationMatrix.values[0][1] << " "
00188        << e->informationMatrix.values[1][1] << " "
00189        << e->informationMatrix.values[2][2] << " "
00190        << e->informationMatrix.values[0][2] << " "
00191        << e->informationMatrix.values[1][2] << endl;
00192     }
00193   return true;
00194 }
00195 
00198 struct IdPrinter{
00199   IdPrinter(std::ostream& _os):os(_os){}
00200   std::ostream& os;
00201   void perform(TreePoseGraph2::Vertex* v){
00202     std::cout << "(" << v->id << "," << v->level << ")" << endl;
00203   }
00204 };
00205 
00206 void TreePoseGraph2::printDepth( std::ostream& os ){
00207   IdPrinter ip(os);
00208   treeDepthVisit(ip, root);
00209 }
00210 
00211 void TreePoseGraph2::printWidth( std::ostream& os ){
00212   IdPrinter ip(os);
00213   treeBreadthVisit(ip);
00214 }
00215 
00219 struct PosePropagator{
00220   void perform(TreePoseGraph2::Vertex* v){
00221     if (!v->parent)
00222       return;
00223     TreePoseGraph2::Transformation tParent(v->parent->pose);
00224     TreePoseGraph2::Transformation tNode=tParent*v->parentEdge->transformation;
00225 
00226     //cerr << "EDGE(" << v->parentEdge->v1->id << "," << v->parentEdge->v2->id <<"): " << endl;
00227     //Pose pParent=v->parent->pose;
00228     //cerr << "     p=" << pParent.x() << "," << pParent.y() << "," << pParent.theta() <<  endl;
00229     //Pose pEdge=v->parentEdge->transformation.toPoseType();
00230     //cerr << "     m=" << pEdge.x() << "," << pEdge.y() << "," << pEdge.theta() <<  endl;
00231     //Pose pNode=tNode.toPoseType();
00232     //cerr << "     n=" << pNode.x() << "," << pNode.y() << "," << pNode.theta() <<  endl;
00233 
00234     assert(v->parentEdge->v1==v->parent);
00235     assert(v->parentEdge->v2==v);
00236     v->pose=tNode.toPoseType();
00237   }
00238 };
00239 
00240 void TreePoseGraph2::initializeOnTree(){
00241   PosePropagator pp;
00242   treeDepthVisit(pp, root);
00243 }
00244 
00245 
00246 void TreePoseGraph2::printEdgesStat(std::ostream& os){
00247   for (TreePoseGraph2::EdgeMap::const_iterator it=edges.begin(); it!=edges.end(); it++){
00248     const TreePoseGraph2::Edge * e=it->second;
00249     os << "EDGE " << e->v1->id << " " << e->v2->id << " ";
00250     Pose p=e->transformation.toPoseType();
00251     os << p.x() << " " << p.y() << " " << p.theta() << " ";
00252     os << e->informationMatrix.values[0][0] << " "
00253        << e->informationMatrix.values[0][1] << " "
00254        << e->informationMatrix.values[1][1] << " "
00255        << e->informationMatrix.values[2][2] << " "
00256        << e->informationMatrix.values[0][2] << " "
00257        << e->informationMatrix.values[1][2] << endl;
00258     os << "   top=" << e->top->id << " length=" << e->length << endl;
00259   }
00260 }
00261 
00262 void TreePoseGraph2::revertEdgeInfo(Edge* e){
00263   Transformation it=e->transformation.inv();
00264   InformationMatrix R;
00265   R.values[0][0]=e->transformation.rotationMatrix[0][0];
00266   R.values[0][1]=e->transformation.rotationMatrix[0][1];
00267   R.values[0][2]=0;
00268 
00269   R.values[1][0]=e->transformation.rotationMatrix[1][0];
00270   R.values[1][1]=e->transformation.rotationMatrix[1][1];
00271   R.values[1][2]=0;
00272 
00273   R.values[2][0]=0;
00274   R.values[2][1]=0;
00275   R.values[2][2]=1;
00276 
00277   InformationMatrix IM=R.transpose()*e->informationMatrix*R;
00278 
00279 
00280   //Pose np=e->transformation.toPoseType();
00281  
00282   //Pose ip=it.toPoseType();
00283 
00284   //Transformation tc=it*e->transformation;
00285   //Pose pc=tc.toPoseType();
00286 
00287   e->transformation=it;
00288   e->informationMatrix=IM;
00289 };
00290 
00291 void TreePoseGraph2::initializeFromParentEdge(Vertex* v){
00292   Transformation tp=Transformation(v->parent->pose)*v->parentEdge->transformation;
00293   v->transformation=tp;
00294   v->pose=tp.toPoseType();
00295   v->parameters=v->pose;
00296   v->parameters.x()-=v->parent->pose.x();
00297   v->parameters.y()-=v->parent->pose.y();
00298   v->parameters.theta()-=v->parent->pose.theta();
00299   v->parameters.theta()=atan2(sin(v->parameters.theta()), cos(v->parameters.theta()));
00300 }
00301 
00302 void TreePoseGraph2::collapseEdge(Edge* e){
00303   EdgeMap::iterator ie_it=edges.find(e);
00304   if (ie_it==edges.end())
00305     return;
00306   //VertexMap::iterator it1=vertices.find(e->v1->id);
00307   //VertexMap::iterator it2=vertices.find(e->v2->id);
00308   assert(vertices.find(e->v1->id)!=vertices.end());
00309   assert(vertices.find(e->v2->id)!=vertices.end());
00310 
00311   Vertex* v1=e->v1;
00312   Vertex* v2=e->v2;
00313   
00314   
00315   // all the edges of v2 become outgoing
00316   for (EdgeList::iterator it=v2->edges.begin(); it!=v2->edges.end(); it++){
00317     if ( (*it)->v1!=v2 )
00318       revertEdge(*it);
00319   }
00320 
00321  // all the edges of v1 become outgoing
00322   for (EdgeList::iterator it=v1->edges.begin(); it!=v1->edges.end(); it++){
00323     if ( (*it)->v1!=v1 )
00324       revertEdge(*it);
00325   }
00326 
00327   assert(e->v1==v1);
00328 
00329   InformationMatrix I12=e->informationMatrix;
00330   CovarianceMatrix  C12=I12.inv();
00331   Transformation    T12=e->transformation;
00332   //Pose              p12=T12.toPoseType();
00333 
00334   //Transformation iT12=T12.inv();
00335 
00336   //compute the marginal information of the nodes in the path v1-v2-v*
00337   for (EdgeList::iterator it2=v2->edges.begin(); it2!=v2->edges.end(); it2++){
00338     Edge* e2=*it2;
00339     if (e2->v1==v2){ //edge leaving v2
00340       //Transformation T2x=e2->transformation;
00341       //Pose           p2x=T2x.toPoseType();
00342       InformationMatrix I2x=e2->informationMatrix;
00343       CovarianceMatrix  C2x=I2x.inv();
00344       
00345       //compute the estimate of the vertex based on the path v1-v2-vx
00346       
00347       //Transformation tr=iT12*T2x;
00348       
00349       //InformationMatrix R;
00350       //R.values[0][0]=tr.rotationMatrix[0][0];
00351       //R.values[0][1]=tr.rotationMatrix[0][1];
00352       //R.values[0][2]=0;
00353       
00354       //R.values[1][0]=tr.rotationMatrix[1][0];
00355       //R.values[1][1]=tr.rotationMatrix[1][1];
00356       //R.values[1][2]=0;
00357       
00358       //R.values[2][0]=0;
00359       //R.values[2][1]=0;
00360       //R.values[2][2]=1;
00361 
00362       //CovarianceMatrix CM=R.transpose()*C2x*R;
00363       
00364       
00365       Transformation T1x_pred=T12*e2->transformation;
00366       Covariance C1x_pred=C12+C2x;
00367       InformationMatrix I1x_pred=C1x_pred.inv();
00368 
00369       e2->transformation=T1x_pred;
00370       e2->informationMatrix=I1x_pred;
00371     }
00372   }
00373 
00374   //all the edges leaving v1 and leaving v2 and leading to the same point are merged
00375   std::list<Transformation> tList;
00376   std::list<InformationMatrix> iList;
00377   std::list<Vertex*> vList;
00378 
00379   //others are transformed and added to v1
00380   for (EdgeList::iterator it2=v2->edges.begin(); it2!=v2->edges.end(); it2++){
00381     Edge* e1x=0;
00382     Edge* e2x=0;
00383     if ( ((*it2)->v1!=v1)){
00384       e2x=*it2;
00385       for (EdgeList::iterator it1=v1->edges.begin(); it1!=v1->edges.end(); it1++){
00386         if ((*it1)->v2==(*it2)->v2)
00387           e1x=*it1;
00388       }
00389 
00390     }
00391     if (e1x && e2x){
00392       Transformation t1x=e1x->transformation;
00393       InformationMatrix I1x=e1x->informationMatrix;
00394       Pose p1x=t1x.toPoseType();
00395 
00396       Transformation t2x=e2x->transformation;
00397       InformationMatrix I2x=e2x->informationMatrix;;
00398       Pose p2x=t2x.toPoseType();
00399 
00400       InformationMatrix IM=I1x+I2x;
00401       CovarianceMatrix  CM=IM.inv();
00402       InformationMatrix scale1=CM*I1x;
00403       InformationMatrix scale2=CM*I2x;
00404 
00405 
00406       Pose p1=scale1*p1x;
00407       Pose p2=scale2*p2x;
00408 
00409 
00410       //need to recover the angles in a decent way.
00411       double s=scale1.values[2][2]*sin(p1x.theta())+ scale2.values[2][2]*sin(p2x.theta());
00412       double c=scale1.values[2][2]*cos(p1x.theta())+ scale2.values[2][2]*cos(p2x.theta());
00413       
00414       DEBUG(2) << "p1x= " << p1x.x() << " " << p1x.y() << " " << p1x.theta() << endl;
00415       DEBUG(2) << "p1x_pred= " << p2x.x() << " " << p2x.y() << " " << p2x.theta() << endl;
00416       
00417       Pose pFinal(p1.x()+p2.x(), p1.y()+p2.y(), atan2(s,c));
00418       DEBUG(2) << "p1x_final= " << pFinal.x() << " " << pFinal.y() << " " << pFinal.theta() << endl;
00419       
00420       e1x->transformation=Transformation(pFinal);
00421       e1x->informationMatrix=IM;
00422     }
00423     if (!e1x && e2x){
00424       tList.push_back(e2x->transformation);
00425       iList.push_back(e2x->informationMatrix);
00426       vList.push_back(e2x->v2);
00427     }
00428   }
00429   removeVertex(v2->id);
00430 
00431   std::list<Transformation>::iterator t=tList.begin();
00432   std::list<InformationMatrix>::iterator i=iList.begin();
00433   std::list<Vertex*>::iterator v=vList.begin();
00434   while (i!=iList.end()){
00435     addEdge(v1,*v,*t,*i);
00436     i++;
00437     t++;
00438     v++;
00439   }
00440 }
00441 
00442 }; //namespace AISNavigation


rtabmap
Author(s): Mathieu Labbe
autogenerated on Fri Aug 28 2015 12:51:32