00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
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
00215
00216
00217
00218
00219
00220
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
00295 for (EdgeList::iterator it=v2->edges.begin(); it!=v2->edges.end(); it++){
00296 if ( (*it)->v1!=v2 )
00297 revertEdge(*it);
00298 }
00299
00300
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
00316 for (EdgeList::iterator it2=v2->edges.begin(); it2!=v2->edges.end(); it2++){
00317 Edge* e2=*it2;
00318 if (e2->v1==v2){
00319 Transformation T2x=e2->transformation;
00320 Pose p2x=T2x.toPoseType();
00321 InformationMatrix I2x=e2->informationMatrix;
00322 CovarianceMatrix C2x=I2x.inv();
00323
00324
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
00354 std::list<Transformation> tList;
00355 std::list<InformationMatrix> iList;
00356 std::list<Vertex*> vList;
00357
00358
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
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 }