treeoptimizer2.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 
00044 #include "treeoptimizer2.hh"
00045 #include <fstream>
00046 #include <sstream>
00047 #include <string>
00048 
00049 using namespace std;
00050 
00051 #define DEBUG(i) \
00052         if (verboseLevel>i) cerr
00053 
00055 struct ParameterPropagator{
00056   void perform(TreePoseGraph2::Vertex* v){
00057     if (!v->parent){
00058       v->parameters=TreePoseGraph2::Pose(0.,0.,0.);
00059       return;
00060     }
00061     v->parameters=TreePoseGraph2::Pose(v->pose.x()-v->parent->pose.x(), 
00062                       v->pose.y()-v->parent->pose.y(),
00063                       v->pose.theta()-v->parent->pose.theta());
00064   }
00065 };
00066 
00067 TreeOptimizer2::TreeOptimizer2(){
00068   sortedEdges=0;
00069 }
00070 
00071 TreeOptimizer2::~TreeOptimizer2(){
00072 }
00073 
00074 void TreeOptimizer2::initializeTreeParameters(){
00075   ParameterPropagator pp;
00076   treeDepthVisit(pp, root);
00077 }
00078 
00079 void TreeOptimizer2::initializeOptimization(){
00080   // compute the size of the preconditioning matrix
00081   int sz=maxIndex()+1;
00082   DEBUG(1) << "Size= " << sz << endl;
00083   M.resize(sz);
00084   DEBUG(1) << "allocating M(" << sz << ")" << endl;
00085   iteration=1;
00086 
00087   // sorting edges
00088   if (sortedEdges!=0){
00089     delete sortedEdges;
00090     sortedEdges=0;
00091   }
00092   sortedEdges=sortEdges();
00093 }
00094 
00095 void TreeOptimizer2::initializeOnlineOptimization(){
00096   // compute the size of the preconditioning matrix
00097   int sz=maxIndex()+1;
00098   DEBUG(1) << "Size= " << sz << endl;
00099   M.resize(sz);
00100   DEBUG(1) << "allocating M(" << sz << ")" << endl;
00101   iteration=1;
00102 }
00103 
00104 void TreeOptimizer2::computePreconditioner(){
00105   gamma[0] = gamma[1] =  gamma[2] = MAXDOUBLE;
00106 
00107   for (uint i=0; i<M.size(); i++)
00108     M[i]=Pose(0.,0.,0.);
00109 
00110   int edgeCount=0;
00111   for (EdgeSet::iterator it=sortedEdges->begin(); it!=sortedEdges->end(); it++){
00112     edgeCount++;
00113     if (! (edgeCount%10000))
00114       DEBUG(1) << "m";
00115 
00116     Edge* e=*it;
00117     Transformation t=e->transformation;
00118     InformationMatrix S=e->informationMatrix;
00119     
00120     InformationMatrix R;
00121     R.values[0][0]=t.rotationMatrix[0][0];
00122     R.values[0][1]=t.rotationMatrix[0][1];
00123     R.values[0][2]=0;
00124     
00125     R.values[1][0]=t.rotationMatrix[1][0];
00126     R.values[1][1]=t.rotationMatrix[1][1];
00127     R.values[1][2]=0;
00128     
00129     R.values[2][0]=0;
00130     R.values[2][1]=0;
00131     R.values[2][2]=1;
00132 
00133     InformationMatrix W =R*S*R.transpose();
00134     
00135     Vertex* top=e->top;
00136     for (int dir=0; dir<2; dir++){
00137       Vertex* n = (dir==0)? e->v1 : e->v2;
00138       while (n!=top){
00139         uint i=n->id;
00140         M[i].values[0]+=W.values[0][0];
00141         M[i].values[1]+=W.values[1][1];
00142         M[i].values[2]+=W.values[2][2];
00143         gamma[0]=gamma[0]<W.values[0][0]?gamma[0]:W.values[0][0];
00144         gamma[1]=gamma[1]<W.values[1][1]?gamma[1]:W.values[1][1];
00145         gamma[2]=gamma[2]<W.values[2][2]?gamma[2]:W.values[2][2];
00146         n=n->parent;
00147       }
00148     }
00149   }
00150   
00151   if (verboseLevel>1){
00152     for (uint i=0; i<M.size(); i++){
00153       cerr << "M[" << i << "]=" << M[i].x() << " " << M[i].y() << " " << M[i].theta() <<endl;
00154     }
00155   }
00156 }
00157 
00158 
00159 void TreeOptimizer2::propagateErrors(){
00160   iteration++;
00161   int edgeCount=0;
00162   
00163   for (EdgeSet::iterator it=sortedEdges->begin(); it!=sortedEdges->end(); it++){
00164       edgeCount++;
00165       if (! (edgeCount%10000))  DEBUG(1) << "c";
00166       
00167       Edge* e=*it;
00168       Vertex* top=e->top;
00169       
00170 
00171       Vertex* v1=e->v1;
00172       Vertex* v2=e->v2;
00173 
00174       double l=e->length;
00175       DEBUG(2) << "Edge: " << v1->id << " " << v2->id << ", top=" << top->id << ", length="<< l <<endl;
00176       
00177       Pose p1=getPose(v1, top);
00178       Pose p2=getPose(v2, top);
00179 
00180       DEBUG(2) << " p1=" << p1.x() << " " << p1.y() << " " << p1.theta() << endl;
00181       DEBUG(2) << " p2=" << p2.x() << " " << p2.y() << " " << p2.theta() << endl;
00182       
00183       Transformation et=e->transformation;
00184       Transformation t1(p1);
00185       Transformation t2(p2);
00186 
00187       Transformation t12=t1*et;
00188     
00189       Pose p12=t12.toPoseType();
00190       DEBUG(2) << " pt2=" << p12.x() << " " << p12.y() << " " << p12.theta() << endl;
00191 
00192       Pose r(p12.x()-p2.x(), p12.y()-p2.y(), p12.theta()-p2.theta());
00193       double angle=r.theta();
00194       angle=atan2(sin(angle),cos(angle));
00195       r.theta()=angle;
00196       DEBUG(2) << " e=" << r.x() << " " << r.y() << " " << r.theta() << endl;
00197     
00198       InformationMatrix S=e->informationMatrix;
00199       InformationMatrix R;
00200       R.values[0][0]=t1.rotationMatrix[0][0];
00201       R.values[0][1]=t1.rotationMatrix[0][1];
00202       R.values[0][2]=0;
00203       
00204       R.values[1][0]=t1.rotationMatrix[1][0];
00205       R.values[1][1]=t1.rotationMatrix[1][1];
00206       R.values[1][2]=0;
00207       
00208       R.values[2][0]=0;
00209       R.values[2][1]=0;
00210       R.values[2][2]=1;
00211 
00212       InformationMatrix W=R*S*R.transpose();
00213       Pose d=W*r*2.;
00214 
00215       DEBUG(2) << " d=" << d.x() << " " << d.y() << " " << d.theta() << endl;
00216     
00217       assert(l>0);
00218 
00219       double alpha[3] = { 1./(gamma[0]*iteration), 1./(gamma[1]*iteration), 1./(gamma[2]*iteration) };
00220 
00221       double tw[3]={0.,0.,0.};
00222       for (int dir=0; dir<2; dir++) {
00223         Vertex* n = (dir==0)? v1 : v2;
00224         while (n!=top){
00225           uint i=n->id;
00226           tw[0]+=1./M[i].values[0];
00227           tw[1]+=1./M[i].values[1];
00228           tw[2]+=1./M[i].values[2];
00229           n=n->parent;
00230         }
00231       }
00232 
00233       double beta[3] = {l*alpha[0]*d.values[0], l*alpha[1]*d.values[1], l*alpha[2]*d.values[2]};
00234       beta[0]=(fabs(beta[0])>fabs(r.values[0]))?r.values[0]:beta[0];
00235       beta[1]=(fabs(beta[1])>fabs(r.values[1]))?r.values[1]:beta[1];
00236       beta[2]=(fabs(beta[2])>fabs(r.values[2]))?r.values[2]:beta[2];
00237 
00238       DEBUG(2) << " alpha=" << alpha[0] << " " << alpha[1] << " " << alpha[2] << endl;
00239       DEBUG(2) << " beta=" << beta[0] << " " << beta[1] << " " << beta[2] << endl;
00240       
00241       for (int dir=0; dir<2; dir++) {
00242         Vertex* n = (dir==0)? v1 : v2;
00243         double sign=(dir==0)? -1. : 1.;
00244         while (n!=top){
00245           uint i=n->id;
00246           assert(M[i].values[0]>0);
00247           assert(M[i].values[1]>0);
00248           assert(M[i].values[2]>0);
00249 
00250           Pose delta( beta[0]/(M[i].values[0]*tw[0]), beta[1]/(M[i].values[1]*tw[1]), beta[2]/(M[i].values[2]*tw[2]));
00251           delta=delta*sign;
00252           DEBUG(2) << "   " << dir << ":"  << i <<"," << n->parent->id << ":"
00253                << n->parameters.x() << " " << n->parameters.y() << " " << n->parameters.theta() << " -> ";
00254 
00255           n->parameters.x()+=delta.x();
00256           n->parameters.y()+=delta.y();
00257           n->parameters.theta()+=delta.theta();
00258           DEBUG(2) << n->parameters.x() << " " << n->parameters.y() << " " << n->parameters.theta()<< endl;
00259           n=n->parent;
00260         }
00261       }
00262       updatePoseChain(v1,top);
00263       updatePoseChain(v2,top);
00264 
00265       Pose pf1=v1->pose;
00266       Pose pf2=v2->pose;
00267       
00268       DEBUG(2) << " pf1=" << pf1.x() << " " << pf1.y() << " " << pf1.theta() << endl;
00269       DEBUG(2) << " pf2=" << pf2.x() << " " << pf2.y() << " " << pf2.theta() << endl;
00270       DEBUG(2) << " en=" << p12.x()-pf2.x() << " " << p12.y()-pf2.y() << " " << p12.theta()-pf2.theta() << endl;
00271     }
00272   
00273 }
00274 
00275 void TreeOptimizer2::iterate(TreePoseGraph2::EdgeSet* eset){
00276   TreePoseGraph2::EdgeSet* temp=sortedEdges;
00277   if (eset){
00278     sortedEdges=eset;
00279   }
00280   computePreconditioner();
00281   propagateErrors();
00282   sortedEdges=temp;
00283 }
00284 
00285 void TreeOptimizer2::updatePoseChain(Vertex* v, Vertex* top){
00286   if (v!=top){
00287     updatePoseChain(v->parent, top);
00288     v->pose.x()=v->parent->pose.x()+v->parameters.x();
00289     v->pose.y()=v->parent->pose.y()+v->parameters.y();
00290     v->pose.theta()=v->parent->pose.theta()+v->parameters.theta();
00291     return;
00292   } 
00293 }
00294 
00295 TreeOptimizer2::Pose TreeOptimizer2::getPose(Vertex*v, Vertex* top){
00296   Pose p(0,0,0);
00297   Vertex* aux=v;
00298   while (aux!=top){
00299     p.x()+=aux->parameters.x();
00300     p.y()+=aux->parameters.y();
00301     p.theta()+=aux->parameters.theta();
00302     aux=aux->parent;
00303   }
00304   p.x()+=aux->pose.x();
00305   p.y()+=aux->pose.y();
00306   p.theta()+=aux->pose.theta();
00307   return p;
00308 }
00309 
00310 
00311 double TreeOptimizer2::error(const Edge* e) const{
00312   const Vertex* v1=e->v1;
00313   const Vertex* v2=e->v2;
00314   
00315   Pose p1=v1->pose;
00316   Pose p2=v2->pose;
00317   
00318   DEBUG(2) << " p1=" << p1.x() << " " << p1.y() << " " << p1.theta() << endl;
00319   DEBUG(2) << " p2=" << p2.x() << " " << p2.y() << " " << p2.theta() << endl;
00320   
00321   Transformation et=e->transformation;
00322   Transformation t1(p1);
00323   Transformation t2(p2);
00324   
00325   Transformation t12=t1*et;
00326     
00327   Pose p12=t12.toPoseType();
00328   DEBUG(2) << " pt2=" << p12.x() << " " << p12.y() << " " << p12.theta() << endl;
00329 
00330   Pose r(p12.x()-p2.x(), p12.y()-p2.y(), p12.theta()-p2.theta());
00331   double angle=r.theta();
00332   angle=atan2(sin(angle),cos(angle));
00333   r.theta()=angle;
00334   DEBUG(2) << " e=" << r.x() << " " << r.y() << " " << r.theta() << endl;
00335     
00336   InformationMatrix S=e->informationMatrix;
00337   InformationMatrix R;
00338   R.values[0][0]=t1.rotationMatrix[0][0];
00339   R.values[0][1]=t1.rotationMatrix[0][1];
00340   R.values[0][2]=0;
00341       
00342   R.values[1][0]=t1.rotationMatrix[1][0];
00343   R.values[1][1]=t1.rotationMatrix[1][1];
00344   R.values[1][2]=0;
00345       
00346   R.values[2][0]=0;
00347   R.values[2][1]=0;
00348   R.values[2][2]=1;
00349 
00350   InformationMatrix W=R*S*R.transpose();
00351 
00352   Pose r1=W*r;
00353   return r.x()*r1.x()+r.y()*r1.y()+r.theta()*r1.theta();
00354 }
00355 
00356 double TreeOptimizer2::error() const{
00357   double globalError=0.;
00358   for (TreePoseGraph2::EdgeMap::const_iterator it=edges.begin(); it!=edges.end(); it++){
00359     globalError+=error(it->second);
00360   }
00361   return globalError;
00362 }

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