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 
00037 
00038 
00039 #include <stdio.h>
00040 #include "sba/spa2d.h"
00041 #include <Eigen/Cholesky>
00042 
00043 using namespace Eigen;
00044 using namespace std;
00045 
00046 #include <iostream>
00047 #include <iomanip>
00048 #include <fstream>
00049 #include <sys/time.h>
00050 
00051 
00052 static long long utime()
00053 {
00054   timeval tv;
00055   gettimeofday(&tv,NULL);
00056   long long ts = tv.tv_sec;
00057   ts *= 1000000;
00058   ts += tv.tv_usec;
00059   return ts;
00060 }
00061 
00062 namespace sba
00063 {
00064 
00065   
00066   
00067   void Node2d::setTransform()
00068     { 
00069       w2n(0,0) = w2n(1,1) = cos(arot);
00070       w2n(0,1) = sin(arot);
00071       w2n(1,0) = -w2n(0,1);
00072       w2n.col(2).setZero();
00073       w2n.col(2) = -w2n*trans;
00074     }
00075 
00076 
00077   
00078   
00079   
00080   void Node2d::setDr()
00081   {
00082     dRdx(0,0) = dRdx(1,1) = w2n(1,0); 
00083     dRdx(0,1) = w2n(0,0);       
00084     dRdx(1,0) = -w2n(0,0);      
00085   }
00086 
00087 
00088   
00089 
00090   void Con2dP2::setJacobians(std::vector<Node2d,Eigen::aligned_allocator<Node2d> > &nodes)
00091   {
00092     
00093     Node2d &nr = nodes[ndr];
00094     Matrix<double,3,1> &tr = nr.trans;
00095     Node2d &n1 = nodes[nd1];
00096     Matrix<double,3,1> &t1 = n1.trans;
00097 
00098     
00099     Eigen::Matrix<double,2,1> pc = nr.w2n * t1;
00100 
00101     
00102 
00103     
00104     
00105     J0.block<2,2>(0,0) = -nr.w2n.block<2,2>(0,0);
00106 
00107 
00108     
00109     
00110     Eigen::Matrix<double,2,1> pwt;
00111     pwt = (t1-tr).head(2);   
00112 
00113     
00114     Eigen::Matrix<double,2,1> dp = nr.dRdx * pwt; 
00115     J0.block<2,1>(0,2) = dp;
00116 
00117     
00118     J0.block<1,2>(2,0).setZero();
00119 
00120     
00121     
00122     J0(2,2) = -1.0;
00123     J0t = J0.transpose();
00124 
00125     
00126 
00127     
00128     
00129     
00130     J1.block<2,2>(0,0) = nr.w2n.block<2,2>(0,0);
00131 
00132     
00133     J1.block<2,1>(0,2).setZero();
00134 
00135     
00136     J1.block<1,2>(2,0).setZero();
00137 
00138 
00139     
00140     
00141     J1(2,2) = 1.0;
00142     J1t = J1.transpose();
00143 
00144     
00145 
00146   };
00147 
00148 
00149 
00150   
00151   
00152   inline double Con2dP2::calcErr(const Node2d &nd0, const Node2d &nd1)
00153     { 
00154       err.block<2,1>(0,0) = nd0.w2n * nd1.trans - tmean;
00155       double aerr = (nd1.arot - nd0.arot) - amean;
00156       if (aerr > M_PI) aerr -= 2.0*M_PI;
00157       if (aerr < -M_PI) aerr += 2.0*M_PI;
00158       err(2) = aerr;
00159 
00160       
00161 
00162       return err.dot(prec * err);
00163     }
00164 
00165 
00166   
00167   double Con2dP2::calcErrDist(const Node2d &nd0, const Node2d &nd1)
00168     { 
00169       Vector2d derr = nd0.w2n * nd1.trans - tmean;
00170       return derr.dot(derr);
00171     }
00172 
00173 
00174   
00175   
00176   
00177   double SysSPA2d::calcCost(bool tcost)
00178   {
00179     double cost = 0.0;
00180     
00181     
00182     if (tcost)
00183       {
00184         for(size_t i=0; i<p2cons.size(); i++)
00185           {
00186             Con2dP2 &con = p2cons[i];
00187             double err = con.calcErrDist(nodes[con.ndr],nodes[con.nd1]);
00188             cost += err;
00189           }
00190       }
00191 
00192     
00193     else 
00194       {
00195         for(size_t i=0; i<p2cons.size(); i++)
00196           {
00197             Con2dP2 &con = p2cons[i];
00198             double err = con.calcErr(nodes[con.ndr],nodes[con.nd1]);
00199             cost += err;
00200           }
00201         errcost = cost;
00202       }
00203 
00204     return cost;
00205   }
00206 
00207 
00208   
00209   
00210   
00211   int SysSPA2d::addNode(const Vector3d &pos, int id)
00212   {
00213     Node2d nd;
00214     nd.nodeId = id;
00215 
00216     nd.arot = pos(2);
00217     nd.trans.head(2) = pos.head(2);
00218     nd.trans(2) = 1.0;
00219 
00220     
00221     nd.setTransform();          
00222     nd.setDr();
00223     int ndi = nodes.size();
00224     nodes.push_back(nd);
00225     return ndi;
00226   }
00227 
00228   
00229   
00230   
00231   
00232   
00233   
00234   bool SysSPA2d::addConstraint(int ndi0, int ndi1, const Vector3d &mean, 
00235                                  const Matrix3d &prec)
00236   {
00237     int ni0 = -1, ni1 = -1;
00238     for (int i=0; i<(int)nodes.size(); i++)
00239       {
00240         if (nodes[i].nodeId == ndi0)
00241           ni0 = i;
00242         if (nodes[i].nodeId == ndi1)
00243           ni1 = i;
00244       }
00245     if (ni0 < 0 || ni1 < 0) return false;
00246     
00247     Con2dP2 con;
00248     con.ndr = ni0;
00249     con.nd1 = ni1;
00250 
00251     con.tmean = mean.head(2);
00252     con.amean = mean(2);
00253     con.prec = prec;
00254     p2cons.push_back(con);
00255     return true;
00256   }
00257 
00258 
00259   
00260   
00261 
00262   void SysSPA2d::setupSys(double sLambda)
00263   {
00264     
00265     
00266     int nFree = nodes.size() - nFixed;
00267     A.setZero(3*nFree,3*nFree);
00268     B.setZero(3*nFree);
00269     VectorXi dcnt(nFree);
00270     dcnt.setZero(nFree);
00271 
00272     
00273     double lam = 1.0 + sLambda;
00274 
00275     
00276     for(size_t pi=0; pi<p2cons.size(); pi++)
00277       {
00278         Con2dP2 &con = p2cons[pi];
00279         con.setJacobians(nodes);
00280 
00281         
00282         int i0 = 3*(con.ndr-nFixed); 
00283         int i1 = 3*(con.nd1-nFixed); 
00284         
00285         if (i0>=0)
00286           {
00287             A.block<3,3>(i0,i0) += con.J0t * con.prec * con.J0;
00288             dcnt(con.ndr - nFixed)++;
00289           }
00290         if (i1>=0)
00291           {
00292             dcnt(con.nd1 - nFixed)++;
00293             Matrix<double,3,3> tp = con.prec * con.J1;
00294             A.block<3,3>(i1,i1) += con.J1t * tp;
00295             if (i0>=0)
00296               {
00297                 A.block<3,3>(i0,i1) += con.J0t * con.prec * con.J1;
00298                 A.block<3,3>(i1,i0) += con.J1t * con.prec * con.J0;
00299               }
00300           }
00301 
00302         
00303         if (i0>=0)
00304           B.block<3,1>(i0,0) -= con.J0t * con.prec * con.err;
00305         if (i1>=0)
00306           B.block<3,1>(i1,0) -= con.J1t * con.prec * con.err;
00307       } 
00308 
00309 
00310     
00311     A.diagonal() *= lam;
00312 
00313     
00314     for (int i=0; i<3*nFree; i++)
00315       for (int j=0; j<3*nFree; j++)
00316         if (isnan(A(i,j)) ) { printf("[SetupSys] NaN in A\n"); *(int *)0x0 = 0; }
00317 
00318     for (int j=0; j<3*nFree; j++)
00319       if (isnan(B[j]) ) { printf("[SetupSys] NaN in B\n"); *(int *)0x0 = 0; }
00320 
00321     int ndc = 0;
00322     for (int i=0; i<nFree; i++)
00323       if (dcnt(i) == 0) ndc++;
00324 
00325     if (ndc > 0)
00326       cout << "[SetupSys] " << ndc << " disconnected nodes" << endl;
00327   }
00328 
00329 
00330   
00331   
00332   void SysSPA2d::setupSparseSys(double sLambda, int iter, int sparseType)
00333   {
00334     
00335     
00336     int nFree = nodes.size() - nFixed;
00337 
00338     long long t0, t1, t2, t3;
00339     t0 = utime();
00340 
00341     if (iter == 0)
00342       csp.setupBlockStructure(nFree); 
00343     else
00344       csp.setupBlockStructure(0); 
00345 
00346     t1 = utime();
00347 
00348     VectorXi dcnt(nFree);
00349     dcnt.setZero(nFree);
00350 
00351     
00352     double lam = 1.0 + sLambda;
00353 
00354     
00355     for(size_t pi=0; pi<p2cons.size(); pi++)
00356       {
00357         Con2dP2 &con = p2cons[pi];
00358         con.setJacobians(nodes);
00359 
00360         
00361         int i0 = con.ndr-nFixed; 
00362         int i1 = con.nd1-nFixed; 
00363         
00364         if (i0>=0)
00365           {
00366            Matrix<double,3,3> m = con.J0t*con.prec*con.J0;
00367             csp.addDiagBlock(m,i0);
00368             dcnt(con.ndr - nFixed)++;
00369           }
00370         if (i1>=0)
00371           {
00372             dcnt(con.nd1 - nFixed)++;
00373             Matrix<double,3,3> tp = con.prec * con.J1;
00374             Matrix<double,3,3> m = con.J1t * tp;
00375             csp.addDiagBlock(m,i1);
00376             if (i0>=0)
00377               {
00378                 Matrix<double,3,3> m2 = con.J0t * tp;
00379                 if (i1 < i0)
00380                   {
00381                     m = m2.transpose();
00382                     csp.addOffdiagBlock(m,i1,i0);
00383                   }
00384                 else
00385                   {
00386                     csp.addOffdiagBlock(m2,i0,i1);
00387                   }
00388               }
00389           }
00390 
00391         
00392         if (i0>=0)
00393           csp.B.block<3,1>(i0*3,0) -= con.J0t * con.prec * con.err;
00394         if (i1>=0)
00395           csp.B.block<3,1>(i1*3,0) -= con.J1t * con.prec * con.err;
00396       } 
00397 
00398     t2 = utime();
00399 
00400     
00401     if (sparseType == SBA_BLOCK_JACOBIAN_PCG)
00402       csp.incDiagBlocks(lam);   
00403     else
00404       csp.setupCSstructure(lam,iter==0); 
00405     t3 = utime();
00406 
00407     if (verbose)
00408       printf("\n[SetupSparseSys] Block: %0.1f   Cons: %0.1f  CS: %0.1f\n",
00409            (t1-t0)*.001, (t2-t1)*.001, (t3-t2)*.001);
00410 
00411     int ndc = 0;
00412     for (int i=0; i<nFree; i++)
00413       if (dcnt(i) == 0) ndc++;
00414 
00415     if (ndc > 0)
00416       cout << "[SetupSparseSys] " << ndc << " disconnected nodes" << endl;
00417   }
00418   
00419 
00428 
00429   int SysSPA2d::doSPA(int niter, double sLambda, int useCSparse, double initTol,
00430                       int maxCGiters)
00431   {
00432     
00433     int ncams = nodes.size();
00434 
00435     
00436     int ncons = p2cons.size();
00437 
00438     
00439     if (nFixed <= 0)
00440       {
00441         cout << "[doSPA2d] No fixed frames" << endl;
00442         return 0;
00443       }
00444     for (int i=0; i<ncams; i++)
00445       {
00446         Node2d &nd = nodes[i];
00447         if (i >= nFixed)
00448           nd.isFixed = false;
00449         else 
00450           nd.isFixed = true;
00451         nd.setTransform();      
00452         nd.setDr();         
00453       }
00454 
00455     
00456     if (sLambda > 0.0)          
00457       lambda = sLambda;
00458 
00459     double laminc = 2.0;        
00460     double lamdec = 0.5;        
00461     int iter = 0;               
00462     sqMinDelta = 1e-8 * 1e-8;
00463     double cost = calcCost();
00464     if (verbose)
00465       cout << iter << " Initial squared cost: " << cost << " which is " 
00466            << sqrt(cost/ncons) << " rms error" << endl;
00467 
00468     int good_iter = 0;
00469     double cumTime = 0;
00470     for (; iter<niter; iter++)  
00471       {
00472         
00473         
00474         
00475 
00476         long long t0, t1, t2, t3;
00477         t0 = utime();
00478         if (useCSparse)
00479           setupSparseSys(lambda,iter,useCSparse); 
00480         else
00481           setupSys(lambda);     
00482 
00483         
00484         t1 = utime();
00485 
00486         
00487         if (useCSparse == SBA_BLOCK_JACOBIAN_PCG)
00488           {
00489             if (csp.B.rows() != 0)
00490               {
00491                 int iters = csp.doBPCG(maxCGiters,initTol,iter);
00492                 if (verbose)
00493                   cout << "[Block PCG] " << iters << " iterations" << endl;
00494               }
00495           }
00496 #ifdef SBA_DSIF
00497         
00498         else if (useCSparse == 3)
00499           {
00500             int res = csp.doPCG(maxCGiters);
00501             if (res > 1)
00502               cout << "[DoSPA] Sparse PCG failed with error " << res << endl;
00503           }
00504 #endif
00505         else if (useCSparse > 0)
00506           {
00507             if (csp.B.rows() != 0)
00508               {
00509                 bool ok = csp.doChol();
00510                 if (!ok)
00511                   cout << "[DoSBA] Sparse Cholesky failed!" << endl;
00512               }
00513           }
00514 
00515         
00516         else
00517           A.ldlt().solveInPlace(B); 
00518 
00519         t2 = utime();
00520         
00521 
00522         
00523         VectorXd &BB = useCSparse ? csp.B : B;
00524 
00525         
00526         
00527         double sqDiff = BB.squaredNorm();
00528         if (sqDiff < sqMinDelta) 
00529           {
00530             if (verbose)
00531               cout << "Converged with delta: " << sqrt(sqDiff) << endl;
00532             break;
00533           }
00534 
00535         
00536         int ci = 0;
00537         for(int i=0; i < ncams; i++)
00538           {
00539             Node2d &nd = nodes[i];
00540             if (nd.isFixed) continue; 
00541             nd.oldtrans = nd.trans; 
00542             nd.oldarot = nd.arot;
00543             nd.trans.head<2>() += BB.segment<2>(ci);
00544 
00545             nd.arot += BB(ci+2); 
00546             nd.normArot();
00547             nd.setTransform();  
00548             nd.setDr();         
00549             ci += 3;            
00550           }
00551 
00552         
00553         double newcost = calcCost();
00554         if (verbose)
00555           cout << iter << " Updated squared cost: " << newcost << " which is " 
00556                << sqrt(newcost/ncons) << " rms error" << endl;
00557         
00558         
00559         if (newcost < cost) 
00560           {
00561             cost = newcost;
00562             lambda *= lamdec;   
00563             
00564             good_iter++;
00565           }
00566         else
00567           {
00568             lambda *= laminc;   
00569             laminc *= 2.0;      
00570 
00571             
00572             for(int i=0; i<ncams; i++)
00573               {
00574                 Node2d &nd = nodes[i];
00575                 if (nd.isFixed) continue; 
00576                 nd.trans = nd.oldtrans;
00577                 nd.arot = nd.oldarot;
00578                 nd.setTransform(); 
00579                 nd.setDr();
00580               }
00581 
00582             cost = calcCost();  
00583             if (verbose)
00584               cout << iter << " Downdated cost: " << cost << endl;
00585             
00586           }
00587 
00588         t3 = utime();
00589         if (iter == 0 && verbose)
00590           {
00591             printf("[SPA] Setup: %0.2f ms  Solve: %0.2f ms  Update: %0.2f ms\n",
00592                    0.001*(double)(t1-t0),
00593                    0.001*(double)(t2-t1),
00594                    0.001*(double)(t3-t2));
00595           }
00596 
00597         double dt=1e-6*(double)(t3-t0);
00598         cumTime+=dt;
00599         if (print_iros_stats){
00600           cerr << "iteration= " << iter
00601                << "\t chi2= " << cost
00602                << "\t time= " << dt
00603                << "\t cumTime= " << cumTime
00604                << "\t kurtChi2= " << cost
00605                << endl;
00606         }
00607 
00608       }
00609 
00610     
00611     return good_iter;
00612 
00613   }
00614 
00615 
00622 
00623   static inline int getind(std::map<int,int> &m, int ind)
00624   {
00625     std::map<int,int>::iterator it;
00626     it = m.find(ind);
00627     if (it == m.end())
00628       return -1;
00629     else
00630       return it->second;
00631   }
00632 
00633   int SysSPA2d::doSPAwindowed(int window, int niter, double sLambda, int useCSparse)
00634   {
00635     
00636     int nnodes = nodes.size();
00637     if (nnodes < 2) return 0;
00638 
00639     int nlow = nnodes - window;
00640     if (nlow < 1) nlow = 1;     
00641 
00642     if (verbose)
00643       cout << "[SPA Window] From " << nlow << " to " << nnodes << endl;
00644 
00645     
00646     int ncons = p2cons.size();
00647 
00648     
00649     SysSPA2d spa;
00650     spa.verbose = verbose;
00651 
00652     
00653     std::vector<Node2d,Eigen::aligned_allocator<Node2d> > &wnodes = spa.nodes;
00654     std::vector<Con2dP2,Eigen::aligned_allocator<Con2dP2> > &wp2cons = spa.p2cons;
00655     std::map<int,int> inds;
00656     std::vector<int> rinds;     
00657 
00658     
00659     for (int i=0; i<ncons; i++)
00660       {
00661         Con2dP2 &con = p2cons[i];
00662         if (con.ndr >= nlow || con.nd1 >= nlow)
00663             wp2cons.push_back(con);
00664 
00665         if (con.ndr >= nlow && con.nd1 < nlow) 
00666           {
00667             int j = getind(inds,con.nd1); 
00668             if (j < 0)      
00669               {
00670                 inds.insert(std::pair<int,int>(con.nd1,wnodes.size()));
00671                 wnodes.push_back(nodes[con.nd1]);
00672               }
00673             rinds.push_back(con.nd1);
00674           }
00675         else if (con.nd1 >= nlow && con.ndr < nlow)
00676           {
00677             int j = getind(inds,con.ndr); 
00678             if (j < 0)      
00679               {
00680                 inds.insert(std::pair<int,int>(con.ndr,wnodes.size()));
00681                 wnodes.push_back(nodes[con.ndr]);
00682               }
00683             rinds.push_back(con.ndr);
00684           }
00685       }
00686 
00687     spa.nFixed = wnodes.size();
00688     if (verbose)
00689       cout << "[SPA Window] Fixed node count: " << spa.nFixed << endl;
00690 
00691     
00692     for (int i=0; i<(int)wp2cons.size(); i++)
00693       {
00694         Con2dP2 &con = wp2cons[i];
00695         if (con.nd1 >= nlow && con.ndr >= nlow) 
00696           {
00697             int n0 = getind(inds,con.ndr);
00698             if (n0 < 0)
00699               {
00700                 inds.insert(std::pair<int,int>(con.ndr,wnodes.size()));
00701                 wnodes.push_back(nodes[con.ndr]);
00702                 rinds.push_back(con.ndr);
00703               }
00704             int n1 = getind(inds,con.nd1);
00705             if (n1 < 0)
00706               {
00707                 inds.insert(std::pair<int,int>(con.nd1,wnodes.size()));
00708                 wnodes.push_back(nodes[con.nd1]);
00709                 rinds.push_back(con.nd1);
00710               }
00711           }
00712       }
00713 
00714     if (verbose)
00715       {
00716         cout << "[SPA Window] Variable node count: " << spa.nodes.size() - spa.nFixed << endl;
00717         cout << "[SPA Window] Constraint count: " << spa.p2cons.size() << endl;
00718       }
00719 
00720     
00721     for (int i=0; i<(int)wp2cons.size(); i++)
00722       {
00723         Con2dP2 &con = wp2cons[i];
00724         con.ndr = getind(inds,con.ndr);
00725         con.nd1 = getind(inds,con.nd1);
00726       }
00727 
00728     
00729     niter = spa.doSPA(niter,sLambda,useCSparse);
00730     
00731     
00732     for (int i=0; i<(int)wp2cons.size(); i++)
00733       {
00734         Con2dP2 &con = wp2cons[i];
00735         con.ndr = rinds[con.ndr];
00736         con.nd1 = rinds[con.nd1];
00737       }
00738     return niter;
00739   }
00740 
00741 
00742 #ifdef SBA_DSIF
00743 
00744 
00745 
00746 
00747   
00748   void SysSPA2d::setupSparseDSIF(int newnode)
00749   {
00750     
00751     
00752     int nFree = nodes.size() - nFixed;
00753 
00754     
00755     
00756 
00757     
00758     csp.setupBlockStructure(nFree,false); 
00759 
00760     
00761 
00762     
00763     for(size_t pi=0; pi<p2cons.size(); pi++)
00764       {
00765         Con2dP2 &con = p2cons[pi];
00766 
00767         
00768         if (con.ndr < newnode && con.nd1 < newnode)
00769           continue;
00770 
00771         con.setJacobians(nodes);
00772 
00773         
00774         int i0 = con.ndr-nFixed; 
00775         int i1 = con.nd1-nFixed; 
00776         
00777         
00778         
00779         double fact = 1.0;
00780         if (i0 != i1-1) fact = 0.99; 
00781 
00782         if (i0>=0)
00783           {
00784             Matrix<double,3,3> m = con.J0t*con.prec*con.J0;
00785             csp.addDiagBlock(m,i0);
00786           }
00787         if (i1>=0)
00788           {
00789             Matrix<double,3,3> m = con.J1t*con.prec*con.J1;
00790             csp.addDiagBlock(m,i1);
00791 
00792             if (i0>=0)
00793               {
00794                 Matrix<double,3,3> m2 = con.J0t*con.prec*con.J1;
00795                 m2 = m2 * fact * fact;
00796                 if (i1 < i0)
00797                   {
00798                     m = m2.transpose();
00799                     csp.addOffdiagBlock(m,i1,i0);
00800                   }
00801                 else
00802                   {
00803                     csp.addOffdiagBlock(m2,i0,i1);
00804                   }
00805               }
00806           }
00807 
00808         
00809         if (i0>=0)
00810           csp.B.block<3,1>(i0*3,0) -= con.J0t * con.prec * con.err;
00811         if (i1>=0)
00812           csp.B.block<3,1>(i1*3,0) -= con.J1t * con.prec * con.err;
00813 
00814       } 
00815 
00816     
00817 
00818     csp.Bprev = csp.B;          
00819 
00820     
00821     csp.setupCSstructure(1.0,true); 
00822 
00823     
00824 
00825     
00826     
00827 
00828   }
00829 
00830 
00833   void SysSPA2d::doDSIF(int newnode)
00834   {
00835     
00836     int nnodes = nodes.size();
00837 
00838     
00839     int ncons = p2cons.size();
00840 
00841     
00842     if (nFixed <= 0)
00843       {
00844         cout << "[doDSIF] No fixed frames" << endl;
00845         return;
00846       }
00847 
00848     
00849     if (newnode >= nnodes)
00850       {
00851         cout << "[doDSIF] no new nodes to add" << endl;
00852         return;
00853       }
00854     else                        
00855       {
00856         for (int i=newnode; i<nnodes; i++)
00857           {
00858             nodes[i].oldtrans = nodes[i].trans;
00859             nodes[i].oldarot = nodes[i].arot;
00860           }
00861       }
00862 
00863     for (int i=0; i<nnodes; i++)
00864       {
00865         Node2d &nd = nodes[i];
00866         if (i >= nFixed)
00867           nd.isFixed = false;
00868         else 
00869           nd.isFixed = true;
00870         nd.setTransform();      
00871         nd.setDr();             
00872       }
00873 
00874     
00875     double cost = calcCost();
00876     if (verbose)
00877       cout << " Initial squared cost: " << cost << " which is " 
00878            << sqrt(cost/ncons) << " rms error" << endl;
00879 
00880     
00881     long long t0, t1, t2, t3;
00882     t0 = utime();
00883     setupSparseDSIF(newnode); 
00884 
00885 #if 0
00886     cout << "[doDSIF] B = " << csp.B.transpose() << endl;
00887     csp.uncompress(A);
00888     cout << "[doDSIF] A = " << endl << A << endl;
00889 #endif
00890 
00891     
00892     t1 = utime();
00893     bool ok = csp.doChol();
00894     if (!ok)
00895       cout << "[doDSIF] Sparse Cholesky failed!" << endl;
00896     t2 = utime();
00897     
00898 
00899     
00900     VectorXd &BB = csp.B;
00901 
00902     
00903 
00904     
00905     int ci = 0;
00906     for(int i=0; i < nnodes; i++)
00907       {
00908         Node2d &nd = nodes[i];
00909         if (nd.isFixed) continue; 
00910         nd.trans.head(2) = nd.oldtrans.head(2)+BB.segment<2>(ci);
00911         nd.arot = nd.oldarot+BB(ci+2); 
00912         nd.normArot();
00913         nd.setTransform();  
00914         nd.setDr();         
00915         ci += 3;            
00916       }
00917 
00918     
00919     double newcost = calcCost();
00920     if (verbose)
00921       cout << " Updated squared cost: " << newcost << " which is " 
00922            << sqrt(newcost/ncons) << " rms error" << endl;
00923         
00924     t3 = utime();
00925   }
00926 
00927 
00928 
00929   
00930   void SysSPA2d::writeSparseA(char *fname, bool useCSparse)
00931   {
00932     ofstream ofs(fname);
00933     if (ofs == NULL)
00934       {
00935         cout << "Can't open file " << fname << endl;
00936         return;
00937       }
00938 
00939     
00940     if (useCSparse)
00941       {
00942         setupSparseSys(0.0,0);
00943         
00944         int *Ai = csp.A->i;
00945         int *Ap = csp.A->p;
00946         double *Ax = csp.A->x;
00947 
00948         for (int i=0; i<csp.csize; i++)
00949           for (int j=Ap[i]; j<Ap[i+1]; j++)
00950             if (Ai[j] <= i)
00951               ofs << Ai[j] << " " << i << setprecision(16) << " " << Ax[j] << endl;
00952       }
00953     else
00954       {
00955         Eigen::IOFormat pfmt(16);
00956 
00957         int nrows = A.rows();
00958         int ncols = A.cols();
00959     
00960         for (int i=0; i<nrows; i++)
00961           for (int j=i; j<ncols; j++)
00962             {
00963               double a = A(i,j);
00964               if (A(i,j) != 0.0)
00965                 ofs << i << " " << j << setprecision(16) << " " << a << endl;
00966             }
00967       }
00968 
00969     ofs.close();
00970   }
00971 #endif
00972 
00973 
00974   
00975   
00976   void SysSPA2d::getGraph(std::vector<float> &graph)
00977   {
00978     for (int i=0; i<(int)p2cons.size(); i++)
00979       {
00980         Con2dP2 &con = p2cons[i];
00981         Node2d &nd0 = nodes[con.ndr];
00982         Node2d &nd1 = nodes[con.nd1];
00983         graph.push_back(nd0.trans(0));
00984         graph.push_back(nd0.trans(1));
00985         graph.push_back(nd1.trans(0));
00986         graph.push_back(nd1.trans(1));
00987       }
00988   }
00989 
00990 
00991 }  
00992 
00993 
00994 
00997 
00999 
01000 #if 0
01001 
01002 
01003 
01004 
01005   
01006   void SysSPA2d::setupSparseDSIF(int newnode)
01007   {
01008     cout << "[SetupDSIF] at " << newnode << endl;
01009 
01010     
01011     
01012     int nFree = nodes.size() - nFixed;
01013 
01014     
01015     
01016 
01017     
01018     csp.setupBlockStructure(nFree,false); 
01019 
01020     
01021 
01022     
01023     for(size_t pi=0; pi<p2cons.size(); pi++)
01024       {
01025         Con2dP2 &con = p2cons[pi];
01026 
01027         
01028         if (con.ndr < newnode && con.nd1 < newnode)
01029           continue;
01030 
01031         con.setJacobians(nodes);
01032         Matrix3d J;
01033         J.setIdentity();
01034         Vector2d dRdth = nodes[con.ndr].dRdx.transpose() * con.tmean;
01035         J(0,2) = dRdth(0);
01036         J(1,2) = dRdth(1);
01037         Matrix3d Jt = J.transpose();
01038         Vector3d u;
01039         u.head(2) = nodes[con.ndr].trans.head(2);
01040         u(2) = nodes[con.ndr].arot;
01041         Vector3d f;
01042         f.head(2) = u.head(2) + nodes[con.ndr].w2n.transpose().block<2,2>(0,0) * con.tmean;
01043         f(2) = u(2) + con.amean;
01044         if (f(2) > M_PI) f(2) -= 2.0*M_PI;
01045         if (f(2) < M_PI) f(2) += 2.0*M_PI;
01046 
01047         
01048         cout << "[SetupDSIF] u  = " << u.transpose() << endl;
01049         cout << "[SetupDSIF] f  = " << f.transpose() << endl;
01050         cout << "[SetupDSIF] fo = " << nodes[con.nd1].trans.transpose() << endl;
01051 
01052 
01053         
01054         int i0 = con.ndr-nFixed; 
01055         int i1 = con.nd1-nFixed; 
01056         
01057         if (i0 != i1-1) continue; 
01058 
01059         if (i0>=0)
01060           {
01061             Matrix<double,3,3> m = Jt*con.prec*J;
01062             csp.addDiagBlock(m,i0);
01063           }
01064         if (i1>=0)
01065           {
01066             Matrix<double,3,3> m = con.prec;
01067             csp.addDiagBlock(m,i1);
01068 
01069             if (i0>=0)
01070               {
01071                 Matrix<double,3,3> m2 = -con.prec * J;
01072 
01073 
01074                 if (i1 < i0)
01075                   {
01076                     m = m2.transpose();
01077                     csp.addOffdiagBlock(m,i1,i0);
01078                   }
01079                 else
01080                   {
01081                     csp.addOffdiagBlock(m2,i0,i1);
01082                   }
01083               }
01084           }
01085 
01086         
01087         
01088         Vector3d Juf = J*u - f;
01089         if (Juf(2) > M_PI) Juf(2) -= 2.0*M_PI;
01090         if (Juf(2) < M_PI) Juf(2) += 2.0*M_PI;
01091         if (i0>=0)
01092           {
01093             csp.B.block<3,1>(i0*3,0) += Jt * con.prec * Juf;
01094           }
01095         if (i1>=0)
01096           {
01097             csp.B.block<3,1>(i1*3,0) -= con.prec * Juf;
01098           }
01099 
01100       } 
01101 
01102     
01103 
01104     csp.Bprev = csp.B;          
01105 
01106     
01107     csp.setupCSstructure(1.0,true); 
01108 
01109     
01110 
01111     
01112     
01113 
01114   }
01115 
01116 
01120   void SysSPA2d::doDSIF(int newnode, bool useCSparse)
01121   {
01122     
01123     int nnodes = nodes.size();
01124 
01125     
01126     int ncons = p2cons.size();
01127 
01128     
01129     if (nFixed <= 0)
01130       {
01131         cout << "[doDSIF] No fixed frames" << endl;
01132         return;
01133       }
01134 
01135     
01136     if (newnode >= nnodes)
01137       {
01138         cout << "[doDSIF] no new nodes to add" << endl;
01139         return;
01140       }
01141 
01142     nFixed = 0;
01143 
01144     for (int i=0; i<nnodes; i++)
01145       {
01146         Node2d &nd = nodes[i];
01147         if (i >= nFixed)
01148           nd.isFixed = false;
01149         else 
01150           nd.isFixed = true;
01151         nd.setTransform();      
01152         nd.setDr();             
01153       }
01154 
01155     
01156     double cost = calcCost();
01157     if (verbose)
01158       cout << " Initial squared cost: " << cost << " which is " 
01159            << sqrt(cost/ncons) << " rms error" << endl;
01160 
01161     if (newnode == 1)
01162       {
01163         
01164         csp.setupBlockStructure(1,false); 
01165         Matrix3d m;
01166         m.setIdentity();
01167         m = m*1000000;
01168         csp.addDiagBlock(m,0);
01169         Vector3d u;
01170         u.head(2) = nodes[0].trans.head(2);
01171         u(2) = nodes[0].arot;
01172         csp.B.head(3) = u*1000000;
01173         csp.Bprev = csp.B;              
01174         cout << "[doDSIF] B = " << csp.B.transpose() << endl;    
01175       }
01176 
01177     
01178     
01179     
01180 
01181     long long t0, t1, t2, t3;
01182     t0 = utime();
01183     if (useCSparse)
01184       setupSparseDSIF(newnode); 
01185     else
01186       {}
01187 
01188 #if 1
01189     cout << "[doDSIF] B = " << csp.B.transpose() << endl;
01190     csp.uncompress(A);
01191     cout << "[doDSIF] A = " << endl << A << endl;
01192 #endif
01193 
01194     
01195     t1 = utime();
01196     if (useCSparse)
01197       {
01198         bool ok = csp.doChol();
01199         if (!ok)
01200           cout << "[doDSIF] Sparse Cholesky failed!" << endl;
01201       }
01202     else
01203       A.ldlt().solveInPlace(B); 
01204     t2 = utime();
01205     
01206 
01207     
01208     VectorXd &BB = useCSparse ? csp.B : B;
01209 
01210     cout << "[doDSIF] RES  = " << BB.transpose() << endl;
01211 
01212     
01213     int ci = 0;
01214     for(int i=0; i < nnodes; i++)
01215       {
01216         Node2d &nd = nodes[i];
01217         if (nd.isFixed) continue; 
01218         nd.trans.head<2>() = BB.segment<2>(ci);
01219         nd.arot = BB(ci+2); 
01220         nd.normArot();
01221         nd.setTransform();  
01222         nd.setDr();         
01223         ci += 3;            
01224       }
01225 
01226     
01227     double newcost = calcCost();
01228     if (verbose)
01229       cout << " Updated squared cost: " << newcost << " which is " 
01230            << sqrt(newcost/ncons) << " rms error" << endl;
01231         
01232     t3 = utime();
01233   }
01234 
01235 
01239 
01240   
01241   void SysSPA2d::setupSparseDSIF(int newnode)
01242   {
01243     cout << "[SetupDSIF] at " << newnode << endl;
01244 
01245     
01246     
01247     int nFree = nodes.size() - nFixed;
01248 
01249     
01250     
01251 
01252     
01253     csp.setupBlockStructure(nFree,false); 
01254 
01255     
01256 
01257     
01258     for(size_t pi=0; pi<p2cons.size(); pi++)
01259       {
01260         Con2dP2 &con = p2cons[pi];
01261 
01262         
01263         if (con.ndr < newnode && con.nd1 < newnode)
01264           continue;
01265 
01266         con.setJacobians(nodes);
01267 
01268         
01269         int i0 = con.ndr-nFixed; 
01270         int i1 = con.nd1-nFixed; 
01271         
01272         if (i0 != i1-1) continue; 
01273 
01274         if (i0>=0)
01275           {
01276             Matrix<double,3,3> m = con.J0t*con.prec*con.J0;
01277             csp.addDiagBlock(m,i0);
01278           }
01279         if (i1>=0)
01280           {
01281             Matrix<double,3,3> m = con.J1t*con.prec*con.J1;
01282             csp.addDiagBlock(m,i1);
01283 
01284             if (i0>=0)
01285               {
01286                 Matrix<double,3,3> m2 = con.J0t*con.prec*con.J1;
01287                 if (i1 < i0)
01288                   {
01289                     m = m2.transpose();
01290                     csp.addOffdiagBlock(m,i1,i0);
01291                   }
01292                 else
01293                   {
01294                     csp.addOffdiagBlock(m2,i0,i1);
01295                   }
01296               }
01297           }
01298 
01299         
01300         
01301 
01302         if (i0>=0)
01303           {
01304             Vector3d u;
01305             u.head(2) = nodes[con.ndr].trans.head(2);
01306             u(2) = nodes[con.ndr].arot;
01307             Vector3d bm = con.err + con.J0 * u;
01308             csp.B.block<3,1>(i0*3,0) += (bm.transpose() * con.prec * con.J0).transpose();
01309           }
01310         if (i1>=0)
01311           {
01312             Vector3d u;
01313             u.head(2) = nodes[con.nd1].trans.head(2);
01314             u(2) = nodes[con.nd1].arot;
01315             Vector3d bm = con.err + con.J1 * u;
01316             csp.B.block<3,1>(i1*3,0) += (bm.transpose() * con.prec * con.J1).transpose();
01317           }
01318 
01319       } 
01320 
01321     
01322 
01323     csp.Bprev = csp.B;          
01324 
01325     
01326     csp.setupCSstructure(1.0,true); 
01327 
01328     
01329 
01330     
01331     
01332 
01333   }
01334 
01335 
01339   void SysSPA2d::doDSIF(int newnode, bool useCSparse)
01340   {
01341     
01342     int nnodes = nodes.size();
01343 
01344     
01345     int ncons = p2cons.size();
01346 
01347     
01348     if (nFixed <= 0)
01349       {
01350         cout << "[doDSIF] No fixed frames" << endl;
01351         return;
01352       }
01353 
01354     
01355     if (newnode >= nnodes)
01356       {
01357         cout << "[doDSIF] no new nodes to add" << endl;
01358         return;
01359       }
01360 
01361     for (int i=0; i<nnodes; i++)
01362       {
01363         Node2d &nd = nodes[i];
01364         if (i >= nFixed)
01365           nd.isFixed = false;
01366         else 
01367           nd.isFixed = true;
01368         nd.setTransform();      
01369         nd.setDr();             
01370       }
01371 
01372     
01373     double cost = calcCost();
01374     if (verbose)
01375       cout << " Initial squared cost: " << cost << " which is " 
01376            << sqrt(cost/ncons) << " rms error" << endl;
01377 
01378     
01379     
01380     
01381 
01382     long long t0, t1, t2, t3;
01383     t0 = utime();
01384     if (useCSparse)
01385       setupSparseDSIF(newnode); 
01386     else
01387       {}
01388 
01389 #if 1
01390     cout << "[doDSIF] B = " << csp.B.transpose() << endl;
01391     csp.uncompress(A);
01392     cout << "[doDSIF] A = " << endl << A << endl;
01393 #endif
01394 
01395     
01396     t1 = utime();
01397     if (useCSparse)
01398       {
01399         bool ok = csp.doChol();
01400         if (!ok)
01401           cout << "[doDSIF] Sparse Cholesky failed!" << endl;
01402       }
01403     else
01404       A.ldlt().solveInPlace(B); 
01405     t2 = utime();
01406     
01407 
01408     
01409     VectorXd &BB = useCSparse ? csp.B : B;
01410 
01411     cout << "[doDSIF] RES  = " << BB.transpose() << endl;
01412 
01413     
01414     int ci = 0;
01415     for(int i=0; i < nnodes; i++)
01416       {
01417         Node2d &nd = nodes[i];
01418         if (nd.isFixed) continue; 
01419         nd.trans.head<2>() = BB.segment<2>(ci);
01420         nd.arot = BB(ci+2); 
01421         nd.normArot();
01422         nd.setTransform();  
01423         nd.setDr();         
01424         ci += 3;            
01425       }
01426 
01427     
01428     double newcost = calcCost();
01429     if (verbose)
01430       cout << " Updated squared cost: " << newcost << " which is " 
01431            << sqrt(newcost/ncons) << " rms error" << endl;
01432         
01433     t3 = utime();
01434 
01435   }  
01436 
01437 
01440   void SysSPA2d::removeNode(int id)
01441   {
01442     int ind = -1;
01443     for (int i=0; i<(int)nodes.size(); i++)
01444       {
01445         if (nodes[i].nodeId == ind)
01446           ind = i;
01447       }
01448     if (ind < 0) return;
01449 
01450     
01451     nodes.erase(nodes.begin() + ind);
01452 
01453     
01454     
01455     
01456     int i=0;
01457     while (i <(int)p2cons.size())
01458       {
01459         std::vector<Con2dP2,Eigen::aligned_allocator<Con2dP2> >::iterator iter = p2cons.begin() + i;
01460         if (iter->ndr == ind || iter->nd1 == ind)
01461           {
01462             p2cons.erase(iter);
01463           }
01464         else
01465           {
01466             if (iter->ndr > ind) iter->ndr--;
01467             if (iter->nd1 > ind) iter->nd1--;
01468             i++;
01469           }
01470       }
01471   }
01472 
01474   
01475   bool SysSPA2d::removeConstraint(int ndi0, int ndi1)
01476   {
01477     int ni0 = -1, ni1 = -1;
01478     for (int i=0; i<(int)nodes.size(); i++)
01479       {
01480         if (nodes[i].nodeId == ndi0)
01481           ni0 = i;
01482         if (nodes[i].nodeId == ndi1)
01483           ni1 = i;
01484       }
01485     if (ni0 < 0 || ni1 < 0) return false;
01486 
01487     int i=0;
01488     while (i <(int)p2cons.size())
01489       {
01490         std::vector<Con2dP2,Eigen::aligned_allocator<Con2dP2> >::iterator iter = p2cons.begin() + i;
01491         if (iter->ndr == ni0 && iter->nd1 == ni1)
01492           {
01493             p2cons.erase(iter);
01494           }
01495         else
01496           {
01497             i++;
01498           }
01499       }
01500 
01501     return true;
01502   }
01503 
01504 
01505 
01506 #endif
01507 
01508