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
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
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
00088 if (sortedEdges!=0){
00089 delete sortedEdges;
00090 sortedEdges=0;
00091 }
00092 sortedEdges=sortEdges();
00093 }
00094
00095 void TreeOptimizer2::initializeOnlineOptimization(){
00096
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 }