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 
00040 
00041 
00042 
00043 
00044 
00045 
00046 
00047 
00048 
00049 
00050 
00051 
00052 #include <stdio.h>
00053 #include "sba/sba.h"
00054 #include <Eigen/Cholesky>
00055 
00056 using namespace Eigen;
00057 using namespace std;
00058 
00059 #include <iostream>
00060 #include <iomanip>
00061 #include <fstream>
00062 #include <sys/time.h>
00063 
00064 
00065 static long long utime()
00066 {
00067   timeval tv;
00068   gettimeofday(&tv,NULL);
00069   long long ts = tv.tv_sec;
00070   ts *= 1000000;
00071   ts += tv.tv_usec;
00072   return ts;
00073 }
00074 
00075 namespace sba
00076 {
00077   
00078   bool readP2File(char *fname, SysSPA spa)
00079   {
00080     
00081     
00082     
00083     
00084     
00085     
00086     
00087     
00088 
00089     ifstream ifs(fname);
00090     if (ifs == NULL)
00091       {
00092         cout << "Can't open file " << fname << endl;
00093         return false;
00094       }
00095     ifs.precision(10);          
00096 
00097     
00098     string line;
00099     if (!getline(ifs,line) || line != "# P2 Constraint File")
00100     {
00101       cout << "Bad header" << endl;
00102       return false;
00103     }
00104     cout << "Found P2 constraint file" << endl;
00105 
00106     
00107     int ncams, nss, nscs, np2s;
00108     if (!(ifs >> ncams >> nss >> np2s >> nscs))
00109     {
00110       cout << "Bad entity count" << endl;  
00111       return false;
00112     }
00113     cout << "Number of cameras: " << ncams 
00114          << "  Number of scalers: " << nss
00115          << "  Number of p2p constraints: " << np2s
00116          << "  Number of scale constraints: " << nscs << endl;
00117     
00118     cout << "Reading in camera data..." << flush;
00119     std::vector<Node,Eigen::aligned_allocator<Node> > &nodes = spa.nodes;
00120     Node nd;
00121 
00122     for (int i=0; i<ncams; i++)
00123       {
00124         double v1,v2,v3;
00125         if (!(ifs >> v1 >> v2 >> v3))
00126           {
00127             cout << "Bad node translation params at number " << i << endl;
00128             return false;
00129           }
00130         nd.trans = Vector4d(v1,v2,v3,1.0);
00131 
00132         if (!(ifs >> v1 >> v2 >> v3))
00133           {
00134             cout << "Bad node rotation quaternion at number " << i << endl;
00135             return false;
00136           }
00137         Matrix3d m;
00138         nd.qrot = Quaternion<double>(v1,v2,v2,0.0);
00139         nd.normRot();           
00140         
00141         nodes.push_back(nd);
00142       }
00143     cout << "done" << endl;
00144 
00145     
00146     cout << "Reading in constraint data..." << flush;
00147     std::vector<ConP2,Eigen::aligned_allocator<ConP2> > &cons = spa.p2cons;
00148     ConP2 con;
00149 
00150     for (int i=0; i<np2s; i++)
00151       {
00152         int p1, p2;
00153         double vz[6];           
00154         double vv[36];          
00155 
00156         if (!(ifs >> p1 >> p2))
00157           {
00158             cout << "Bad node indices at constraint " << i << endl;
00159             return false;
00160           }
00161 
00162         for (int i=0; i<6; i++)
00163           {
00164             if (!(ifs >> vz[i]))
00165               {
00166                 cout << "Bad constraint mean at constraint " << i << endl;
00167                 return false;
00168               }
00169           }
00170 
00171         for (int i=0; i<36; i++)
00172           {
00173             if (!(ifs >> vv[i]))
00174               {
00175                 cout << "Bad constraint precision at constraint " << i << endl;
00176                 return false;
00177               }
00178           }
00179 
00180         con.ndr = p1;
00181         con.nd1 = p2;
00182 
00183         
00184         con.prec = Matrix<double,6,6>(vv);
00185 
00186         cons.push_back(con);
00187       }
00188 
00189 
00190     
00191     cout << "Reading in scale constraint data..." << flush;
00192     std::vector<ConScale,Eigen::aligned_allocator<ConScale> > &scons = spa.scons;
00193     ConScale scon;
00194 
00195     for (int i=0; i<nscs; i++)
00196       {
00197         int p1, p2, sv;
00198         double ks, w;
00199 
00200         if (!(ifs >> p1 >> p2 >> sv >> ks >> w))
00201           {
00202             cout << "Bad scale constraint at constraint " << i << endl;
00203             return false;
00204           }
00205         
00206         scon.nd0 = p1;
00207         scon.nd1 = p2;
00208         scon.sv  = sv;
00209         scon.ks  = ks;
00210         scon.w   = w;
00211 
00212         scons.push_back(scon);
00213       }
00214 
00215     return true;
00216   }
00217 
00218 
00219 #define NORMALIZE_Q
00220 
00221   
00222   
00223 
00224   void ConP2::setJacobians(std::vector<Node,Eigen::aligned_allocator<Node> > &nodes)
00225   {
00226     
00227     Node &nr = nodes[ndr];
00228     Matrix<double,4,1> &tr = nr.trans;
00229     Quaternion<double> &qr = nr.qrot;
00230     Node &n1 = nodes[nd1];
00231     Matrix<double,4,1> &t1 = n1.trans;
00232     Quaternion<double> &q1 = n1.qrot;
00233 
00234     
00235     Eigen::Matrix<double,3,1> pc = nr.w2n * t1;
00236 
00237     
00238 
00239     
00240     
00241     J0.block<3,3>(0,0) = -nr.w2n.block<3,3>(0,0);
00242 
00243 
00244     
00245     
00246     Eigen::Matrix<double,3,1> pwt;
00247     pwt = (t1-tr).head(3);   
00248 
00249     
00250     Eigen::Matrix<double,3,1> dp = nr.dRdx * pwt; 
00251     J0.block<3,1>(0,3) = dp;
00252     
00253     dp = nr.dRdy * pwt; 
00254     J0.block<3,1>(0,4) = dp;
00255     
00256     dp = nr.dRdz * pwt; 
00257     J0.block<3,1>(0,5) = dp;
00258 
00259     
00260     J0.block<3,3>(3,0).setZero();
00261 
00262     
00263     
00264 
00265     
00266     Eigen::Quaternion<double> qr0, qr1, qrn, qrd;
00267     qr1.coeffs() = q1.coeffs();
00268     qrn.coeffs() = Vector4d(-qpmean.w(),-qpmean.z(),qpmean.y(),qpmean.x());  
00269     qr0.coeffs() = Vector4d(-qr.x(),-qr.y(),-qr.z(),qr.w());
00270     qr0 = qr0*qr1;              
00271     qrd = qpmean*qr0;           
00272     qrn = qrn*qr0;
00273 
00274 #ifdef NORMALIZE_Q
00275     if (qrd.w() < 0.0)
00276       qrn.vec() = -qrn.vec();
00277 #endif
00278 
00279     J0.block<3,1>(3,3) = qrn.vec();
00280 
00281     
00282     qrn.coeffs() = Vector4d(qpmean.z(),-qpmean.w(),-qpmean.x(),qpmean.y());  
00283     qrn = qrn*qr0;
00284 
00285 #ifdef NORMALIZE_Q
00286     if (qrd.w() < 0.0)
00287       qrn.vec() = -qrn.vec();
00288 #endif
00289 
00290     J0.block<3,1>(3,4) = qrn.vec();
00291 
00292     
00293     qrn.coeffs() = Vector4d(-qpmean.y(),qpmean.x(),-qpmean.w(),qpmean.z());  
00294     qrn = qrn*qr0;
00295 
00296 #ifdef NORMALIZE_Q
00297     if (qrd.w() < 0.0)
00298       qrn.vec() = -qrn.vec();
00299 #endif
00300 
00301     J0.block<3,1>(3,5) = qrn.vec();
00302 
00303     
00304     J0t = J0.transpose();
00305 
00306     
00307 
00308     
00309     
00310     
00311     J1.block<3,3>(0,0) = nr.w2n.block<3,3>(0,0);
00312 
00313     
00314     J1.block<3,3>(0,3).setZero();
00315 
00316     
00317     J1.block<3,3>(3,0).setZero();
00318 
00319 
00320     
00321     
00322 
00323     Eigen::Quaternion<double> qrc;
00324     qrc.coeffs() = Vector4d(-qr.x(),-qr.y(),-qr.z(),qr.w());
00325     qrc = qpmean*qrc*qr1;       
00326     qrc.normalize();
00327 
00328     
00329 
00330     double dq = 1.0e-8;
00331     double wdq = 1.0 - dq*dq;
00332     qr1.coeffs() = Vector4d(dq,0,0,wdq);
00333     
00334     
00335 
00336     
00337     qrn.coeffs() = Vector4d(1,0,0,0);
00338     qrn = qrc*qrn;
00339 
00340     
00341 
00342 #ifdef NORMALIZE_Q
00343     if (qrc.w() < 0.0)
00344       qrn.vec() = -qrn.vec();
00345 #endif
00346 
00347     J1.block<3,1>(3,3) = qrn.vec();
00348 
00349     
00350     qrn.coeffs() = Vector4d(0,1,0,0);
00351     qrn = qrc*qrn;
00352 
00353 #ifdef NORMALIZE_Q
00354     if (qrc.w() < 0.0)
00355       qrn.vec() = -qrn.vec();
00356 #endif
00357 
00358     J1.block<3,1>(3,4) = qrn.vec();
00359 
00360     
00361     qrn.coeffs() = Vector4d(0,0,1,0);
00362     qrn = qrc*qrn;
00363 
00364 #ifdef NORMALIZE_Q
00365     if (qrc.w() < 0.0)
00366       qrn.vec() = -qrn.vec();
00367 #endif
00368 
00369     J1.block<3,1>(3,5) = qrn.vec();
00370 
00371     
00372     J1t = J1.transpose();
00373 
00374     
00375 
00376   };
00377 
00378 
00379 
00380   
00381   
00382 
00383   void ConScale::setJacobians(std::vector<Node,Eigen::aligned_allocator<Node> > &nodes)
00384   {
00385     
00386     Node &n0 = nodes[nd0];
00387     Matrix<double,4,1> &t0 = n0.trans;
00388     Node &n1 = nodes[nd1];
00389     Matrix<double,4,1> &t1 = n1.trans;
00390 
00391     Eigen::Matrix<double,3,1> td = (t1-t0).head(3);
00392 
00393     
00394     
00395 
00396     
00397     J0 = -2.0 * td;
00398 
00399     
00400     J1 =  2.0 * td;
00401 
00402     
00403   };
00404 
00405 
00406 
00407   
00408   
00409   
00410 
00411   void ConP3P::setJacobians(std::vector<Node,Eigen::aligned_allocator<Node> > nodes)
00412   {
00413     
00414     Node nr = nodes[ndr];
00415     Matrix<double,4,1> &tr = nr.trans;
00416     Quaternion<double> &qr = nr.qrot;
00417     Node n1 = nodes[nd1];
00418     Matrix<double,4,1> &t1 = n1.trans;
00419     Quaternion<double> &q1 = n1.qrot;
00420     Node n2 = nodes[nd2];
00421     Matrix<double,4,1> &t2 = n2.trans;
00422     Quaternion<double> &q2 = n2.qrot;
00423 
00424     
00425     
00426     
00427 
00428     
00429     
00430     J10.block<3,3>(0,0) = -nr.w2n.block<3,3>(0,0);
00431 
00432     
00433     
00434     Matrix<double,3,1> pwt = (t1-tr).head(3);
00435     Matrix<double,3,1> dp = nr.dRdx * pwt; 
00436     J10.block<3,1>(0,3) = dp;
00437     dp = nr.dRdy * pwt; 
00438     J10.block<3,1>(0,4) = dp;
00439     dp = nr.dRdz * pwt; 
00440     J10.block<3,1>(0,5) = dp;
00441 
00442     
00443     J10.block<3,3>(3,0).setZero();
00444 
00445     
00446     
00447 
00448     
00449     double wn = -1.0/qr.w();  
00450     dp[0] = wn*t1[0]*qr.x() - t1[3];
00451     dp[1] = wn*t1[1]*qr.x() + t1[2];
00452     dp[2] = wn*t1[2]*qr.x() - t1[1];
00453     J10.block<3,1>(3,3) = dp;
00454 
00455     
00456     dp[0] = wn*t1[0]*qr.y() - t1[2];
00457     dp[1] = wn*t1[1]*qr.y() - t1[3];
00458     dp[2] = wn*t1[2]*qr.y() + t1[0];
00459     J10.block<3,1>(3,4) = dp;
00460 
00461     
00462     dp[0] = wn*t1[0]*qr.z() + t1[1];
00463     dp[1] = wn*t1[1]*qr.z() - t1[0];
00464     dp[2] = wn*t1[2]*qr.z() - t1[3];
00465     J10.block<3,1>(3,5) = dp;
00466 
00467     
00468 
00469     
00470     
00471     
00472     J20.block<3,3>(0,0) = -nr.w2n.block<3,3>(0,0);
00473 
00474     
00475     
00476     pwt = (t2-tr).head(3);
00477     dp = nr.dRdx * pwt; 
00478     J20.block<3,1>(0,3) = dp;
00479     dp = nr.dRdy * pwt; 
00480     J20.block<3,1>(0,4) = dp;
00481     dp = nr.dRdz * pwt; 
00482     J20.block<3,1>(0,5) = dp;
00483 
00484     
00485     J20.block<3,3>(3,0).setZero();
00486 
00487     
00488     
00489 
00490     
00491     wn = -1.0/qr.w();  
00492     dp[0] = wn*q2.x()*qr.x() - q2.w();
00493     dp[1] = wn*q2.y()*qr.x() + q2.z();
00494     dp[2] = wn*q2.z()*qr.x() - q2.y();
00495     J20.block<3,1>(3,3) = dp;
00496 
00497     
00498     dp[0] = wn*q2.x()*qr.y() - q2.z();
00499     dp[1] = wn*q2.y()*qr.y() - q2.w();
00500     dp[2] = wn*q2.z()*qr.y() + q2.x();
00501     J20.block<3,1>(3,4) = dp;
00502 
00503     
00504     dp[0] = wn*q2.x()*qr.z() + q2.y();
00505     dp[1] = wn*q2.y()*qr.z() - q2.x();
00506     dp[2] = wn*q2.z()*qr.z() - q2.w();
00507     J20.block<3,1>(3,5) = dp;
00508 
00509     
00510     
00511     
00512 
00513     
00514     
00515     J11.block<3,3>(0,0) = nr.w2n.block<3,3>(0,0);
00516 
00517     
00518     J11.block<3,3>(0,3).setZero();
00519 
00520     
00521     J11.block<3,3>(3,0).setZero();
00522 
00523     
00524     
00525 
00526     
00527     wn = 1.0/q1.w();  
00528     dp[0] = wn*qr.x()*q1.x() + qr.w();
00529     dp[1] = wn*qr.y()*q1.x() - qr.z();
00530     dp[2] = wn*qr.z()*q1.x() + qr.y();
00531     J11.block<3,1>(3,3) = dp;
00532 
00533     
00534     dp[0] = wn*qr.x()*q1.y() + qr.z();
00535     dp[1] = wn*qr.y()*q1.y() + qr.w();
00536     dp[2] = wn*qr.z()*q1.y() - qr.x();
00537     J11.block<3,1>(3,4) = dp;
00538 
00539     
00540     dp[0] = wn*qr.x()*q1.z() - qr.y();
00541     dp[1] = wn*qr.y()*q1.z() + qr.x();
00542     dp[2] = wn*qr.z()*q1.z() + qr.w();
00543     J11.block<3,1>(3,5) = dp;
00544 
00545     
00546 
00547     
00548     
00549     
00550 
00551     
00552     
00553     J22.block<3,3>(0,0) = nr.w2n.block<3,3>(0,0);
00554 
00555     
00556     J22.block<3,3>(0,3).setZero();
00557 
00558     
00559     J22.block<3,3>(3,0).setZero();
00560 
00561     
00562     
00563 
00564     
00565     wn = 1.0/q2.w();  
00566     dp[0] = wn*qr.x()*q2.x() + qr.w();
00567     dp[1] = wn*qr.y()*q2.x() - qr.z();
00568     dp[2] = wn*qr.z()*q2.x() + qr.y();
00569     J22.block<3,1>(3,3) = dp;
00570 
00571     
00572     dp[0] = wn*qr.x()*q2.y() + qr.z();
00573     dp[1] = wn*qr.y()*q2.y() + qr.w();
00574     dp[2] = wn*qr.z()*q2.y() - qr.x();
00575     J22.block<3,1>(3,4) = dp;
00576 
00577     
00578     dp[0] = wn*qr.x()*q2.z() - qr.y();
00579     dp[1] = wn*qr.y()*q2.z() + qr.x();
00580     dp[2] = wn*qr.z()*q2.z() + qr.w();
00581     J22.block<3,1>(3,5) = dp;
00582 
00583     
00584 
00585   };
00586 
00587 
00588   
00589   inline double ConP2::calcErr(const Node &nd0, const Node &nd1)
00590     { 
00591       Quaternion<double> q0p,q1;
00592       q0p.vec()   = -nd0.qrot.coeffs().head(3); 
00593       q0p.w()     =  nd0.qrot.w();
00594       q1          =  nd1.qrot;
00595       err.block<3,1>(0,0) = nd0.w2n * nd1.trans - tmean;
00596 
00597       
00598       
00599       
00600       
00601 
00602       q1 = qpmean * q0p * q1;
00603 
00604       
00605 
00606 
00607 #ifdef NORMALIZE_Q                              
00608       if (q1.w() < 0.0)
00609         err.block<3,1>(3,0) = -q1.vec(); 
00610       else
00611 #endif
00612         err.block<3,1>(3,0) = q1.vec(); 
00613       
00614       return err.dot(prec * err);
00615     }
00616 
00617 
00618   
00619   double ConP2::calcErrDist(const Node &nd0, const Node &nd1)
00620     { 
00621       Vector3d derr;
00622       Quaternion<double> q0p,q1;
00623       q0p.vec()   = -nd0.qrot.vec(); 
00624       q0p.w()     =  nd0.qrot.w();
00625       q1          =  nd1.qrot;
00626       derr = nd0.w2n * nd1.trans - tmean;
00627       return derr.dot(derr);
00628     }
00629 
00630 
00631   
00632   inline double ConScale::calcErr(const Node &nd0, const Node &nd1, double alpha)
00633     { 
00634       err = (nd1.trans - nd0.trans).squaredNorm();
00635       err -= ks*alpha;
00636       
00637       return w*err*err;
00638     }
00639 
00640 
00641   
00642   
00643   int SysSPA::addNode(Eigen::Matrix<double,4,1> &trans, 
00644                       Eigen::Quaternion<double> &qrot,
00645                       bool isFixed)
00646   {
00647     Node nd;
00648     nd.trans = trans;
00649     nd.qrot = qrot;
00650     nd.isFixed = isFixed;
00651     nd.setTransform(); 
00652     nd.setDr(true); 
00653     
00654     nd.normRot();
00655     nodes.push_back(nd);
00656     return nodes.size()-1;
00657   }
00658 
00659 
00660   
00661   
00662   
00663   
00664   
00665   bool SysSPA::addConstraint(int nd0, int nd1,
00666                              Eigen::Vector3d &tmean,
00667                              Eigen::Quaterniond &qpmean,
00668                              Eigen::Matrix<double,6,6> &prec)
00669   {
00670     if (nd0 >= (int)nodes.size() || nd1 >= (int)nodes.size()) 
00671       return false;
00672     
00673     ConP2 con;
00674     con.ndr = nd0;
00675     con.nd1 = nd1;
00676 
00677     con.tmean = tmean;
00678     Quaternion<double> qr;
00679     qr = qpmean;
00680     qr.normalize();
00681     con.qpmean = qr.inverse(); 
00682     con.prec = prec;            
00683 
00684     p2cons.push_back(con);
00685     return true;
00686   }
00687 
00688 
00689   
00690   
00691   
00692   double SysSPA::calcCost(bool tcost)
00693   {
00694     double cost = 0.0;
00695     
00696     
00697     if (tcost)
00698       {
00699         for(size_t i=0; i<p2cons.size(); i++)
00700           {
00701             ConP2 &con = p2cons[i];
00702             double err = con.calcErrDist(nodes[con.ndr],nodes[con.nd1]);
00703             cost += err;
00704           }
00705       }
00706 
00707     
00708     else 
00709       {
00710         for(size_t i=0; i<p2cons.size(); i++)
00711           {
00712             ConP2 &con = p2cons[i];
00713             double err = con.calcErr(nodes[con.ndr],nodes[con.nd1]);
00714             cost += err;
00715           }
00716         if (scons.size() > 0)       
00717           for(size_t i=0; i<scons.size(); i++)
00718             {
00719               ConScale &con = scons[i];
00720               double err = con.calcErr(nodes[con.nd0],nodes[con.nd1],scales[con.sv]);
00721               cost += err;
00722             }
00723       }
00724 
00725     return cost;
00726   }
00727 
00728 
00729   
00730   
00731   
00732 
00733   void SysSPA::setupSys(double sLambda)
00734   {
00735     
00736     
00737     int nFree = nodes.size() - nFixed;
00738     int nscales = scales.size();
00739     A.setZero(6*nFree+nscales,6*nFree+nscales);
00740     B.setZero(6*nFree+nscales);
00741     VectorXi dcnt(nFree);
00742     dcnt.setZero(nFree);
00743 
00744     
00745     double lam = 1.0 + sLambda;
00746 
00747     
00748     for(size_t pi=0; pi<p2cons.size(); pi++)
00749       {
00750         ConP2 &con = p2cons[pi];
00751         con.setJacobians(nodes);
00752 
00753         
00754         
00755         int i0 = 6*(con.ndr-nFixed); 
00756         int i1 = 6*(con.nd1-nFixed); 
00757         
00758         if (i0>=0)
00759           {
00760             A.block<6,6>(i0,i0) += con.J0t * con.prec * con.J0;
00761             dcnt(con.ndr - nFixed)++;
00762           }
00763         if (i1>=0)
00764           {
00765             dcnt(con.nd1 - nFixed)++;
00766             Matrix<double,6,6> tp = con.prec * con.J1;
00767             A.block<6,6>(i1,i1) += con.J1t * tp;
00768             if (i0>=0)
00769               {
00770                 A.block<6,6>(i0,i1) += con.J0t * con.prec * con.J1;
00771                 A.block<6,6>(i1,i0) += con.J1t * con.prec * con.J0;
00772               }
00773           }
00774 
00775         
00776         if (i0>=0)
00777           B.block<6,1>(i0,0) -= con.J0t * con.prec * con.err;
00778         if (i1>=0)
00779           B.block<6,1>(i1,0) -= con.J1t * con.prec * con.err;
00780       } 
00781 
00782     
00783     if (scons.size() > 0)       
00784       for(size_t pi=0; pi<scons.size(); pi++)
00785         {
00786           ConScale &con = scons[pi];
00787           con.setJacobians(nodes);
00788         
00789         
00790         int i0 = 6*(con.nd0-nFixed); 
00791         int i1 = 6*(con.nd1-nFixed); 
00792         
00793         if (i0>=0)
00794           {
00795             A.block<3,3>(i0,i0) += con.w * con.J0 * con.J0.transpose();
00796           }
00797         if (i1>=0)
00798           {
00799             A.block<3,3>(i1,i1) += con.w * con.J1 * con.J1.transpose();
00800             if (i0>=0)
00801               {
00802                 A.block<3,3>(i0,i1) += con.w * con.J0 * con.J1.transpose();
00803                 A.block<3,3>(i1,i0) = A.block<3,3>(i0,i1).transpose();
00804               }
00805           }
00806 
00807         
00808         if (i0>=0)
00809           B.block<3,1>(i0,0) -= con.w * con.J0 * con.err;
00810         if (i1>=0)
00811           B.block<3,1>(i1,0) -= con.w * con.J1 * con.err;
00812 
00813         
00814         int is = 6*nFree+con.sv;
00815         A(is,is) += con.w * con.ks * con.ks;
00816         if (i0>=0)
00817           {
00818             A.block<3,1>(i0,is) += con.w * con.J0 * -con.ks;
00819             A.block<1,3>(is,i0) = A.block<3,1>(i0,is).transpose();
00820           }
00821         if (i1>=0)
00822           {
00823             A.block<3,1>(i1,is) += con.w * con.J1 * -con.ks;
00824             A.block<1,3>(is,i1) = A.block<3,1>(i1,is).transpose();
00825           }
00826 
00827         
00828         B(is) -= con.w * (-con.ks) * con.err;
00829 
00830       } 
00831 
00832 
00833     
00834     A.diagonal() *= lam;
00835 
00836     
00837     for (int i=0; i<6*nFree; i++)
00838       for (int j=0; j<6*nFree; j++)
00839         if (isnan(A(i,j)) ) { printf("[SetupSys] NaN in A\n"); *(int *)0x0 = 0; }
00840 
00841     for (int j=0; j<6*nFree; j++)
00842       if (isnan(B[j]) ) { printf("[SetupSys] NaN in B\n"); *(int *)0x0 = 0; }
00843 
00844     int ndc = 0;
00845     for (int i=0; i<nFree; i++)
00846       if (dcnt(i) == 0) ndc++;
00847 
00848     if (ndc > 0)
00849       cout << "[SetupSys] " << ndc << " disconnected nodes" << endl;
00850   }
00851 
00852 
00853   
00854   
00855   void SysSPA::setupSparseSys(double sLambda, int iter, int sparseType)
00856   {
00857     
00858     
00859     int nFree = nodes.size() - nFixed;
00860 
00861     
00862     
00863 
00864     if (iter == 0)
00865       csp.setupBlockStructure(nFree); 
00866     else
00867       csp.setupBlockStructure(0); 
00868 
00869     
00870 
00871     VectorXi dcnt(nFree);
00872     dcnt.setZero(nFree);
00873 
00874     
00875     double lam = 1.0 + sLambda;
00876 
00877     
00878     for(size_t pi=0; pi<p2cons.size(); pi++)
00879       {
00880         ConP2 &con = p2cons[pi];
00881         con.setJacobians(nodes);
00882 
00883         
00884         int i0 = con.ndr-nFixed; 
00885         int i1 = con.nd1-nFixed; 
00886         
00887         if (i0>=0)
00888           {
00889            Matrix<double,6,6> m = con.J0t*con.prec*con.J0;
00890             csp.addDiagBlock(m,i0);
00891             dcnt(con.ndr - nFixed)++;
00892           }
00893         if (i1>=0)
00894           {
00895             dcnt(con.nd1 - nFixed)++;
00896             Matrix<double,6,6> tp = con.prec * con.J1;
00897             Matrix<double,6,6> m = con.J1t * tp;
00898             csp.addDiagBlock(m,i1);
00899             if (i0>=0)
00900               {
00901                 Matrix<double,6,6> m2 = con.J0t * tp;
00902                 if (i1 < i0)
00903                   {
00904                     m = m2.transpose();
00905                     csp.addOffdiagBlock(m,i1,i0);
00906                   }
00907                 else
00908                   csp.addOffdiagBlock(m2,i0,i1);
00909               }
00910           }
00911 
00912         
00913         if (i0>=0)
00914           csp.B.block<6,1>(i0*6,0) -= con.J0t * con.prec * con.err;
00915         if (i1>=0)
00916           csp.B.block<6,1>(i1*6,0) -= con.J1t * con.prec * con.err;
00917       } 
00918 
00919     
00920 
00921     
00922     if (sparseType == SBA_BLOCK_JACOBIAN_PCG)
00923       csp.incDiagBlocks(lam);   
00924     else
00925       csp.setupCSstructure(lam,iter==0); 
00926 
00927     
00928 
00929     
00930     
00931 
00932     int ndc = 0;
00933     for (int i=0; i<nFree; i++)
00934       if (dcnt(i) == 0) ndc++;
00935 
00936     if (ndc > 0)
00937       cout << "[SetupSparseSys] " << ndc << " disconnected nodes" << endl;
00938   }
00939   
00940 
00949 
00950   int SysSPA::doSPA(int niter, double sLambda, int useCSparse, double initTol,
00951                       int maxCGiters)
00952   {
00953     Node::initDr();
00954     int nFree = nodes.size() - nFixed; 
00955 
00956     
00957     int ncams = nodes.size();
00958     
00959     int nscales = scales.size();
00960 
00961     
00962     vector<double> oldscales;   
00963     oldscales.resize(nscales);
00964     
00965     
00966     if (sLambda > 0.0)          
00967       lambda = sLambda;
00968 
00969     
00970     int ncons = p2cons.size();
00971 
00972     
00973     for (int i=0; i<ncams; i++)
00974       {
00975         Node &nd = nodes[i];
00976         if (i >= nFixed)
00977           nd.isFixed = false;
00978         else 
00979           nd.isFixed = true;
00980         nd.setTransform();      
00981         nd.setDr(true);         
00982       }
00983 
00984     
00985     double laminc = 2.0;        
00986     double lamdec = 0.5;        
00987     int iter = 0;               
00988     sqMinDelta = 1e-8 * 1e-8;
00989     double cost = calcCost();
00990     if (verbose)
00991       cout << iter << " Initial squared cost: " << cost << " which is " 
00992            << sqrt(cost/ncons) << " rms error" << endl; 
00993 
00994     int good_iter = 0;
00995     for (; iter<niter; iter++)  
00996     {
00997         
00998         
00999         
01000 
01001         long long t0, t1, t2, t3;
01002         t0 = utime();
01003         if (useCSparse)
01004           setupSparseSys(lambda,iter,useCSparse); 
01005         else
01006           setupSys(lambda);     
01007 
01008         
01009         if (useCSparse == SBA_BLOCK_JACOBIAN_PCG)
01010           {
01011             if (csp.B.rows() != 0)
01012               {
01013                 int iters = csp.doBPCG(maxCGiters,initTol,iter);
01014                 if (verbose)
01015                   cout << "[Block PCG] " << iters << " iterations" << endl;
01016               }
01017           }
01018         else if (useCSparse > 0)
01019         {
01020             bool ok = csp.doChol();
01021             if (!ok)
01022               cout << "[DoSPA] Sparse Cholesky failed!" << endl;
01023         }
01024         else
01025           A.ldlt().solveInPlace(B); 
01026 
01027         
01028         VectorXd &BB = useCSparse ? csp.B : B;
01029 
01030         
01031         
01032         double sqDiff = BB.squaredNorm();
01033         if (sqDiff < sqMinDelta) 
01034         {
01035           break;
01036         }
01037 
01038         
01039         int ci = 0;
01040         for(int i=0; i < ncams; i++)
01041         {
01042             Node &nd = nodes[i];
01043             if (nd.isFixed) continue; 
01044             nd.oldtrans = nd.trans; 
01045             nd.oldqrot = nd.qrot;
01046             nd.trans.head<3>() += BB.segment<3>(ci);
01047 
01048             Quaternion<double> qr;
01049             qr.vec() = BB.segment<3>(ci+3); 
01050             qr.w() = sqrt(1.0 - qr.vec().squaredNorm());
01051 
01052             Quaternion<double> qrn,qrx;
01053             qrn = nd.qrot;
01054             qr = qrn*qr;        
01055             qr.normalize();
01056             if (qr.w() < 0.0)
01057               nd.qrot.coeffs() = -qr.coeffs();
01058             else
01059               nd.qrot.coeffs() = qr.coeffs();
01060 
01061             nd.setTransform();  
01062             nd.setDr(true);     
01063             ci += 6;            
01064         }
01065 
01066         
01067         ci = 6*nFree;       
01068         if (nscales > 0)        
01069           for(int i=0; i < nscales; i++)
01070           {
01071               oldscales[i] = scales[i];
01072               scales[i] += B(ci);
01073               ci++;
01074           }
01075 
01076 
01077         
01078         double newcost = calcCost();
01079         if (verbose)
01080           cout << iter << " Updated squared cost: " << newcost << " which is " 
01081            << sqrt(newcost/ncons) << " rms error" << endl;
01082         
01083         
01084         if (newcost < cost) 
01085         {
01086             cost = newcost;
01087             lambda *= lamdec;   
01088             
01089             good_iter++;
01090         }
01091         else
01092         {
01093             lambda *= laminc;   
01094             laminc *= 2.0;      
01095 
01096             
01097             for(int i=0; i<ncams; i++)
01098             {
01099                 Node &nd = nodes[i];
01100                 if (nd.isFixed) continue; 
01101                 nd.trans = nd.oldtrans;
01102                 nd.qrot = nd.oldqrot;
01103                 nd.setTransform(); 
01104                 nd.setDr(true);
01105             }
01106 
01107             
01108             if (nscales > 0)    
01109               for(int i=0; i < nscales; i++)
01110                 scales[i] = oldscales[i];
01111 
01112 
01113             cost = calcCost();  
01114             if (verbose)
01115               cout << iter << " Downdated cost: " << cost << endl;
01116             
01117         }
01118       }
01119 
01120     
01121     return good_iter;
01122 
01123   }
01124 
01125 
01126   
01127   void SysSPA::writeSparseA(char *fname, bool useCSparse)
01128   {
01129     ofstream ofs(fname);
01130     if (ofs == NULL)
01131       {
01132         cout << "Can't open file " << fname << endl;
01133         return;
01134       }
01135 
01136     
01137     if (useCSparse)
01138       {
01139         setupSparseSys(0.0,0,useCSparse);
01140         
01141         int *Ai = csp.A->i;
01142         int *Ap = csp.A->p;
01143         double *Ax = csp.A->x;
01144 
01145         for (int i=0; i<csp.csize; i++)
01146           for (int j=Ap[i]; j<Ap[i+1]; j++)
01147             if (Ai[j] <= i)
01148               ofs << Ai[j] << " " << i << setprecision(16) << " " << Ax[j] << endl;
01149       }
01150     else
01151       {
01152         Eigen::IOFormat pfmt(16);
01153 
01154         int nrows = A.rows();
01155         int ncols = A.cols();
01156     
01157         for (int i=0; i<nrows; i++)
01158           for (int j=i; j<ncols; j++)
01159             {
01160               double a = A(i,j);
01161               if (A(i,j) != 0.0)
01162                 ofs << i << " " << j << setprecision(16) << " " << a << endl;
01163             }
01164       }
01165 
01166     ofs.close();
01167   }
01168 
01169 
01170   
01171   void SysSPA::spanningTree(int node)
01172   {
01173     int nnodes = nodes.size();
01174 
01175     
01176     vector<vector<int> > cind;
01177     cind.resize(nnodes);
01178 
01179     for(size_t pi=0; pi<p2cons.size(); pi++)
01180       {
01181         ConP2 &con = p2cons[pi];
01182         int i0 = con.ndr;
01183         int i1 = con.nd1;
01184         cind[i0].push_back(i1);
01185         cind[i1].push_back(i0);        
01186       }
01187 
01188     
01189     VectorXd dist(nnodes);
01190     dist.setConstant(1e100);
01191     if (node >= nnodes)
01192       node = 0;
01193     dist[node] = 0.0;
01194     multimap<double,int> open;  
01195     open.insert(make_pair<double,int>(0.0,node));
01196 
01197     
01198     while (!open.empty())
01199       {
01200         
01201         int ni = open.begin()->second;
01202         double di = open.begin()->first;
01203         open.erase(open.begin());
01204         if (di > dist[ni]) continue; 
01205 
01206         
01207         Node &nd = nodes[ni];
01208         Matrix<double,3,4> n2w;
01209         transformF2W(n2w,nd.trans,nd.qrot); 
01210 
01211         vector<int> &nns = cind[ni];
01212         for (int i=0; i<(int)nns.size(); i++)
01213           {
01214             ConP2 &con = p2cons[nns[i]];
01215             double dd = con.tmean.norm(); 
01216             
01217             int nn = con.nd1;
01218             if (nn == ni)
01219               nn = con.ndr;
01220             Node &nd2 = nodes[nn];
01221             Vector3d tmean = con.tmean;
01222             Quaterniond qpmean = con.qpmean;
01223             if (nn == con.ndr)       
01224               {
01225                 qpmean = qpmean.inverse();
01226                 tmean = nd.qrot.toRotationMatrix().transpose()*nd2.qrot.toRotationMatrix()*tmean;
01227               }
01228                 
01229             if (dist[nn] > di + dd) 
01230               {
01231                 
01232                 dist[nn] = di+dd;
01233                 open.insert(make_pair<double,int>(di+dd,nn));
01234                 
01235                 Vector4d trans;
01236                 trans.head(3) = tmean;
01237                 trans(3) = 1.0;
01238                 nd2.trans.head(3) = n2w*trans;
01239                 nd2.qrot = qpmean*nd.qrot;
01240                 nd2.normRot();
01241                 nd2.setTransform();
01242                 nd2.setDr(true);
01243               }
01244           }
01245       }
01246     
01247   }
01248   
01249 
01250 }