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, and
00006  * 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 
00051 #define LINESIZE 81920
00052 
00053 
00054 #define DEBUG(i) \
00055         if (verboseLevel>i) cerr
00056 
00057 
00058 bool TreePoseGraph2::load(const char* filename, bool overrideCovariances){
00059   clear();
00060   ifstream is(filename);
00061   if (!is)
00062     return false;
00063 
00064   while(is){
00065     char buf[LINESIZE];
00066     is.getline(buf,LINESIZE);
00067     istringstream ls(buf);
00068     string tag;
00069     ls >> tag;
00070 
00071     if (tag=="VERTEX" || tag=="VERTEX2"){
00072       int id;
00073       Pose p;
00074       ls >> id >> p.x() >> p.y() >> p.theta(); 
00075       if (addVertex(id,p))
00076         DEBUG(2) << "V " << id << endl;
00077       
00078     }
00079 
00080     if (tag=="EDGE" || tag=="EDGE2"){
00081       int id1, id2;
00082       Pose p;
00083       InformationMatrix m;
00084       ls >> id1 >> id2 >> p.x() >> p.y() >> p.theta();
00085       if (overrideCovariances){
00086         m.values[0][0]=1;  m.values[1][1]=1; m.values[2][2]=1;
00087         m.values[0][1]=0;  m.values[0][2]=0; m.values[1][2]=0;
00088       } else {
00089         ls >> m.values[0][0] >> m.values[0][1] >> m.values [1][1]
00090            >> m.values[2][2] >> m.values[0][2] >> m.values [1][2];
00091       }
00092       m.values[1][0]=m.values[0][1];
00093       m.values[2][0]=m.values[0][2];
00094       m.values[2][1]=m.values[1][2];
00095       TreePoseGraph2::Vertex* v1=vertex(id1);
00096       TreePoseGraph2::Vertex* v2=vertex(id2);
00097       Transformation t(p);
00098       if (addEdge(v1, v2,t ,m))
00099          DEBUG(2) << "E " << id1 << " " << id2 <<  endl;
00100     }
00101   }
00102   return true;
00103 }
00104 
00105 bool TreePoseGraph2::loadEquivalences(const char* filename){
00106   ifstream is(filename);
00107   if (!is)
00108     return false;
00109   EdgeList suppressed;
00110   uint equivCount=0;
00111   while (is){
00112     char buf[LINESIZE];
00113     is.getline(buf, LINESIZE);
00114     istringstream ls(buf);
00115     string tag;
00116     ls >> tag;
00117     if (tag=="EQUIV"){
00118       int id1, id2;
00119       ls >> id1 >> id2;
00120       Edge* e=edge(id1,id2);
00121       if (!e)
00122         e=edge(id2,id1);
00123       if (e){
00124         suppressed.push_back(e);
00125         equivCount++;
00126       }
00127     }
00128   }
00129   for (EdgeList::iterator it=suppressed.begin(); it!=suppressed.end(); it++){
00130     Edge* e=*it;
00131     if (e->v1->id > e->v2->id)
00132       revertEdge(e);
00133     collapseEdge(e);
00134   }
00135   return true;
00136 }
00137 
00138 bool TreePoseGraph2::saveGnuplot(const char* filename){
00139   ofstream os(filename);
00140   if (!os)
00141     return false;
00142 
00143   for (TreePoseGraph2::EdgeMap::const_iterator it=edges.begin(); it!=edges.end(); it++){
00144     const TreePoseGraph2::Edge * e=it->second;
00145     const Vertex* v1=e->v1;
00146     const Vertex* v2=e->v2;
00147     
00148     os << v1->pose.x() << " " << v1->pose.y() << " " << v1->pose.theta() << endl;
00149     os << v2->pose.x() << " " << v2->pose.y() << " " << v2->pose.theta() << endl;
00150     os << endl;
00151   }
00152   return true;
00153 
00154 }
00155 
00156 bool TreePoseGraph2::save(const char* filename){
00157   ofstream os(filename);
00158   if (!os)
00159     return false;
00160   
00161   for (TreePoseGraph2::VertexMap::const_iterator it=vertices.begin(); it!=vertices.end(); it++){
00162     const TreePoseGraph2::Vertex* v=it->second;
00163     os << "VERTEX " 
00164        << v->id << " " 
00165        << v->pose.x() << " " 
00166        << v->pose.y() << " " 
00167        << v->pose.theta()<< endl; 
00168   }
00169   for (TreePoseGraph2::EdgeMap::const_iterator it=edges.begin(); it!=edges.end(); it++){
00170     const TreePoseGraph2::Edge * e=it->second;
00171     os << "EDGE " << e->v1->id << " " << e->v2->id << " ";
00172     Pose p=e->transformation.toPoseType();
00173     os << p.x() << " " << p.y() << " " << p.theta() << " ";
00174     os << e->informationMatrix.values[0][0] << " "
00175        << e->informationMatrix.values[0][1] << " "
00176        << e->informationMatrix.values[1][1] << " "
00177        << e->informationMatrix.values[2][2] << " "
00178        << e->informationMatrix.values[0][2] << " "
00179        << e->informationMatrix.values[1][2] << endl;
00180     }
00181   return true;
00182 }
00183 
00186 struct IdPrinter{
00187   IdPrinter(std::ostream& _os):os(_os){}
00188   std::ostream& os;
00189   void perform(TreePoseGraph2::Vertex* v){
00190     std::cout << "(" << v->id << "," << v->level << ")" << endl;
00191   }
00192 };
00193 
00194 void TreePoseGraph2::printDepth( std::ostream& os ){
00195   IdPrinter ip(os);
00196   treeDepthVisit(ip, root);
00197 }
00198 
00199 void TreePoseGraph2::printWidth( std::ostream& os ){
00200   IdPrinter ip(os);
00201   treeBreadthVisit(ip);
00202 }
00203 
00207 struct PosePropagator{
00208   void perform(TreePoseGraph2::Vertex* v){
00209     if (!v->parent)
00210       return;
00211     TreePoseGraph2::Transformation tParent(v->parent->pose);
00212     TreePoseGraph2::Transformation tNode=tParent*v->parentEdge->transformation;
00213 
00214     //cerr << "EDGE(" << v->parentEdge->v1->id << "," << v->parentEdge->v2->id <<"): " << endl;
00215     //Pose pParent=v->parent->pose;
00216     //cerr << "     p=" << pParent.x() << "," << pParent.y() << "," << pParent.theta() <<  endl;
00217     //Pose pEdge=v->parentEdge->transformation.toPoseType();
00218     //cerr << "     m=" << pEdge.x() << "," << pEdge.y() << "," << pEdge.theta() <<  endl;
00219     //Pose pNode=tNode.toPoseType();
00220     //cerr << "     n=" << pNode.x() << "," << pNode.y() << "," << pNode.theta() <<  endl;
00221 
00222     assert(v->parentEdge->v1==v->parent);
00223     assert(v->parentEdge->v2==v);
00224     v->pose=tNode.toPoseType();
00225   }
00226 };
00227 
00228 void TreePoseGraph2::initializeOnTree(){
00229   PosePropagator pp;
00230   treeDepthVisit(pp, root);
00231 }
00232 
00233 
00234 void TreePoseGraph2::printEdgesStat(std::ostream& os){
00235   for (TreePoseGraph2::EdgeMap::const_iterator it=edges.begin(); it!=edges.end(); it++){
00236     const TreePoseGraph2::Edge * e=it->second;
00237     os << "EDGE " << e->v1->id << " " << e->v2->id << " ";
00238     Pose p=e->transformation.toPoseType();
00239     os << p.x() << " " << p.y() << " " << p.theta() << " ";
00240     os << e->informationMatrix.values[0][0] << " "
00241        << e->informationMatrix.values[0][1] << " "
00242        << e->informationMatrix.values[1][1] << " "
00243        << e->informationMatrix.values[2][2] << " "
00244        << e->informationMatrix.values[0][2] << " "
00245        << e->informationMatrix.values[1][2] << endl;
00246     os << "   top=" << e->top->id << " length=" << e->length << endl;
00247   }
00248 }
00249 
00250 void TreePoseGraph2::revertEdgeInfo(Edge* e){
00251   Transformation it=e->transformation.inv();
00252   InformationMatrix R;
00253   R.values[0][0]=e->transformation.rotationMatrix[0][0];
00254   R.values[0][1]=e->transformation.rotationMatrix[0][1];
00255   R.values[0][2]=0;
00256 
00257   R.values[1][0]=e->transformation.rotationMatrix[1][0];
00258   R.values[1][1]=e->transformation.rotationMatrix[1][1];
00259   R.values[1][2]=0;
00260 
00261   R.values[2][0]=0;
00262   R.values[2][1]=0;
00263   R.values[2][2]=1;
00264 
00265   InformationMatrix IM=R.transpose()*e->informationMatrix*R;
00266   
00267 
00268   Pose np=e->transformation.toPoseType();
00269  
00270   Pose ip=it.toPoseType();
00271 
00272   Transformation tc=it*e->transformation;
00273   Pose pc=tc.toPoseType();
00274 
00275   e->transformation=it;
00276   e->informationMatrix=IM;
00277 };
00278 
00279 void TreePoseGraph2::initializeFromParentEdge(Vertex* v){
00280   Transformation tp=Transformation(v->parent->pose)*v->parentEdge->transformation;
00281   v->transformation=tp;
00282   v->pose=tp.toPoseType();
00283   v->parameters=v->pose;
00284   v->parameters.x()-=v->parent->pose.x();
00285   v->parameters.y()-=v->parent->pose.y();
00286   v->parameters.theta()-=v->parent->pose.theta();
00287   v->parameters.theta()=atan2(sin(v->parameters.theta()), cos(v->parameters.theta()));
00288 }
00289 
00290 void TreePoseGraph2::collapseEdge(Edge* e){
00291   Vertex* v1=e->v1;
00292   Vertex* v2=e->v2;
00293   
00294   // all the edges of v2 become outgoing
00295   for (EdgeList::iterator it=v2->edges.begin(); it!=v2->edges.end(); it++){
00296     if ( (*it)->v1!=v2 )
00297       revertEdge(*it);
00298   }
00299 
00300  // all the edges of v1 become outgoing
00301   for (EdgeList::iterator it=v1->edges.begin(); it!=v1->edges.end(); it++){
00302     if ( (*it)->v1!=v1 )
00303       revertEdge(*it);
00304   }
00305 
00306   assert(e->v1==v1);
00307 
00308   InformationMatrix I12=e->informationMatrix;
00309   CovarianceMatrix  C12=I12.inv();
00310   Transformation    T12=e->transformation;
00311   Pose              p12=T12.toPoseType();
00312 
00313   Transformation iT12=T12.inv();
00314 
00315   //compute the marginal information of the nodes in the path v1-v2-v*
00316   for (EdgeList::iterator it2=v2->edges.begin(); it2!=v2->edges.end(); it2++){
00317     Edge* e2=*it2;
00318     if (e2->v1==v2){ //edge leaving v2
00319       Transformation T2x=e2->transformation;
00320       Pose           p2x=T2x.toPoseType();
00321       InformationMatrix I2x=e2->informationMatrix;
00322       CovarianceMatrix  C2x=I2x.inv();
00323       
00324       //compute the estimate of the vertex based on the path v1-v2-vx
00325       
00326       Transformation tr=iT12*T2x;
00327       
00328       InformationMatrix R;
00329       R.values[0][0]=tr.rotationMatrix[0][0];
00330       R.values[0][1]=tr.rotationMatrix[0][1];
00331       R.values[0][2]=0;
00332       
00333       R.values[1][0]=tr.rotationMatrix[1][0];
00334       R.values[1][1]=tr.rotationMatrix[1][1];
00335       R.values[1][2]=0;
00336       
00337       R.values[2][0]=0;
00338       R.values[2][1]=0;
00339       R.values[2][2]=1;
00340 
00341       CovarianceMatrix CM=R.transpose()*C2x*R;
00342       
00343       
00344       Transformation T1x_pred=T12*e2->transformation;
00345       Covariance C1x_pred=C12+C2x;
00346       InformationMatrix I1x_pred=C1x_pred.inv();
00347 
00348       e2->transformation=T1x_pred;
00349       e2->informationMatrix=I1x_pred;
00350     }
00351   }
00352 
00353   //all the edges leaving v1 and leaving v2 and leading to the same point are merged
00354   std::list<Transformation> tList;
00355   std::list<InformationMatrix> iList;
00356   std::list<Vertex*> vList;
00357 
00358   //others are transformed and added to v1
00359   for (EdgeList::iterator it2=v2->edges.begin(); it2!=v2->edges.end(); it2++){
00360     Edge* e1x=0;
00361     Edge* e2x=0;
00362     if ( ((*it2)->v1!=v1)){
00363       e2x=*it2;
00364       for (EdgeList::iterator it1=v1->edges.begin(); it1!=v1->edges.end(); it1++){
00365         if ((*it1)->v2==(*it2)->v2)
00366           e1x=*it1;
00367       }
00368 
00369     }
00370     if (e1x && e2x){
00371       Transformation t1x=e1x->transformation;
00372       InformationMatrix I1x=e1x->informationMatrix;
00373       Pose p1x=t1x.toPoseType();
00374 
00375       Transformation t2x=e2x->transformation;
00376       InformationMatrix I2x=e2x->informationMatrix;;
00377       Pose p2x=t2x.toPoseType();
00378 
00379       InformationMatrix IM=I1x+I2x;
00380       CovarianceMatrix  CM=IM.inv();
00381       InformationMatrix scale1=CM*I1x;
00382       InformationMatrix scale2=CM*I2x;
00383 
00384 
00385       Pose p1=scale1*p1x;
00386       Pose p2=scale2*p2x;
00387 
00388 
00389       //need to recover the angles in a decent way.
00390       double s=scale1.values[2][2]*sin(p1x.theta())+ scale2.values[2][2]*sin(p2x.theta());
00391       double c=scale1.values[2][2]*cos(p1x.theta())+ scale2.values[2][2]*cos(p2x.theta());
00392       
00393       DEBUG(2) << "p1x= " << p1x.x() << " " << p1x.y() << " " << p1x.theta() << endl;
00394       DEBUG(2) << "p1x_pred= " << p2x.x() << " " << p2x.y() << " " << p2x.theta() << endl;
00395       
00396       Pose pFinal(p1.x()+p2.x(), p1.y()+p2.y(), atan2(s,c));
00397       DEBUG(2) << "p1x_final= " << pFinal.x() << " " << pFinal.y() << " " << pFinal.theta() << endl;
00398       
00399       e1x->transformation=Transformation(pFinal);
00400       e1x->informationMatrix=IM;
00401     }
00402     if (!e1x && e2x){
00403       tList.push_back(e2x->transformation);
00404       iList.push_back(e2x->informationMatrix);
00405       vList.push_back(e2x->v2);
00406     }
00407   }
00408   removeVertex(v2->id);
00409 
00410   std::list<Transformation>::iterator t=tList.begin();
00411   std::list<InformationMatrix>::iterator i=iList.begin();
00412   std::list<Vertex*>::iterator v=vList.begin();
00413   while (i!=iList.end()){
00414     addEdge(v1,*v,*t,*i);
00415     i++;
00416     t++;
00417     v++;
00418   }
00419 }

Generated on Mon Nov 12 11:43:00 2007 for TORO by  doxygen 1.5.0