41 #include <Eigen/Cholesky>    43 using namespace Eigen;
    55   gettimeofday(&tv,NULL);
    56   long long ts = tv.tv_sec;
    67   void Node2d::setTransform()
    69       w2n(0,0) = w2n(1,1) = cos(arot);
    73       w2n.col(2) = -w2n*trans;
    82     dRdx(0,0) = dRdx(1,1) = w2n(1,0); 
    84     dRdx(1,0) = -w2n(0,0);      
    90   void Con2dP2::setJacobians(std::vector<
Node2d,Eigen::aligned_allocator<Node2d> > &nodes)
    94     Matrix<double,3,1> &tr = nr.
trans;
    96     Matrix<double,3,1> &t1 = n1.
trans;
    99     Eigen::Matrix<double,2,1> pc = nr.
w2n * t1;
   105     J0.block<2,2>(0,0) = -nr.
w2n.block<2,2>(0,0);
   110     Eigen::Matrix<double,2,1> pwt;
   111     pwt = (t1-tr).head(2);   
   114     Eigen::Matrix<double,2,1> dp = nr.
dRdx * pwt; 
   115     J0.block<2,1>(0,2) = dp;
   118     J0.block<1,2>(2,0).setZero();
   123     J0t = J0.transpose();
   130     J1.block<2,2>(0,0) = nr.
w2n.block<2,2>(0,0);
   133     J1.block<2,1>(0,2).setZero();
   136     J1.block<1,2>(2,0).setZero();
   142     J1t = J1.transpose();
   154       err.block<2,1>(0,0) = nd0.
w2n * nd1.
trans - tmean;
   155       double aerr = (nd1.
arot - nd0.
arot) - amean;
   156       if (aerr > M_PI) aerr -= 2.0*M_PI;
   157       if (aerr < -M_PI) aerr += 2.0*M_PI;
   162       return err.dot(prec * err);
   169       Vector2d derr = nd0.
w2n * nd1.
trans - tmean;
   170       return derr.dot(derr);
   177   double SysSPA2d::calcCost(
bool tcost)
   184         for(
size_t i=0; i<p2cons.size(); i++)
   195         for(
size_t i=0; i<p2cons.size(); i++)
   211   int SysSPA2d::addNode(
const Vector3d &pos, 
int id)
   217     nd.
trans.head(2) = pos.head(2);
   223     int ndi = nodes.size();
   234   bool SysSPA2d::addConstraint(
int ndi0, 
int ndi1, 
const Vector3d &mean, 
   235                                  const Matrix3d &prec)
   237     int ni0 = -1, ni1 = -1;
   238     for (
int i=0; i<(int)nodes.size(); i++)
   240         if (nodes[i].nodeId == ndi0)
   242         if (nodes[i].nodeId == ndi1)
   245     if (ni0 < 0 || ni1 < 0) 
return false;
   251     con.
tmean = mean.head(2);
   254     p2cons.push_back(con);
   262   void SysSPA2d::setupSys(
double sLambda)
   266     int nFree = nodes.size() - nFixed;
   267     A.setZero(3*nFree,3*nFree);
   269     VectorXi dcnt(nFree);
   273     double lam = 1.0 + sLambda;
   276     for(
size_t pi=0; pi<p2cons.size(); pi++)
   282         int i0 = 3*(con.
ndr-nFixed); 
   283         int i1 = 3*(con.
nd1-nFixed); 
   287             A.block<3,3>(i0,i0) += con.
J0t * con.
prec * con.
J0;
   288             dcnt(con.
ndr - nFixed)++;
   292             dcnt(con.
nd1 - nFixed)++;
   293             Matrix<double,3,3> tp = con.
prec * con.
J1;
   294             A.block<3,3>(i1,i1) += con.
J1t * tp;
   297                 A.block<3,3>(i0,i1) += con.
J0t * con.
prec * con.
J1;
   298                 A.block<3,3>(i1,i0) += con.
J1t * con.
prec * con.
J0;
   304           B.block<3,1>(i0,0) -= con.
J0t * con.
prec * con.
err;
   306           B.block<3,1>(i1,0) -= con.
J1t * con.
prec * con.
err;
   314     for (
int i=0; i<3*nFree; i++)
   315       for (
int j=0; j<3*nFree; j++)
   316         if (std::isnan(A(i,j)) ) { printf(
"[SetupSys] NaN in A\n"); *(
int *)0x0 = 0; }
   318     for (
int j=0; j<3*nFree; j++)
   319       if (std::isnan(B[j]) ) { printf(
"[SetupSys] NaN in B\n"); *(
int *)0x0 = 0; }
   322     for (
int i=0; i<nFree; i++)
   323       if (dcnt(i) == 0) ndc++;
   326       cout << 
"[SetupSys] " << ndc << 
" disconnected nodes" << endl;
   332   void SysSPA2d::setupSparseSys(
double sLambda, 
int iter, 
int sparseType)
   336     int nFree = nodes.size() - nFixed;
   338     long long t0, t1, t2, t3;
   342       csp.setupBlockStructure(nFree); 
   344       csp.setupBlockStructure(0); 
   348     VectorXi dcnt(nFree);
   352     double lam = 1.0 + sLambda;
   355     for(
size_t pi=0; pi<p2cons.size(); pi++)
   361         int i0 = con.
ndr-nFixed; 
   362         int i1 = con.
nd1-nFixed; 
   366            Matrix<double,3,3> m = con.
J0t*con.
prec*con.
J0;
   367             csp.addDiagBlock(m,i0);
   368             dcnt(con.
ndr - nFixed)++;
   372             dcnt(con.
nd1 - nFixed)++;
   373             Matrix<double,3,3> tp = con.
prec * con.
J1;
   374             Matrix<double,3,3> m = con.
J1t * tp;
   375             csp.addDiagBlock(m,i1);
   378                 Matrix<double,3,3> m2 = con.
J0t * tp;
   382                     csp.addOffdiagBlock(m,i1,i0);
   386                     csp.addOffdiagBlock(m2,i0,i1);
   393           csp.B.block<3,1>(i0*3,0) -= con.
J0t * con.
prec * con.
err;
   395           csp.B.block<3,1>(i1*3,0) -= con.
J1t * con.
prec * con.
err;
   402       csp.incDiagBlocks(lam);   
   404       csp.setupCSstructure(lam,iter==0); 
   408       printf(
"\n[SetupSparseSys] Block: %0.1f   Cons: %0.1f  CS: %0.1f\n",
   409            (t1-t0)*.001, (t2-t1)*.001, (t3-t2)*.001);
   412     for (
int i=0; i<nFree; i++)
   413       if (dcnt(i) == 0) ndc++;
   416       cout << 
"[SetupSparseSys] " << ndc << 
" disconnected nodes" << endl;
   429   int SysSPA2d::doSPA(
int niter, 
double sLambda, 
int useCSparse, 
double initTol,
   433     int ncams = nodes.size();
   436     int ncons = p2cons.size();
   441         cout << 
"[doSPA2d] No fixed frames" << endl;
   444     for (
int i=0; i<ncams; i++)
   462     sqMinDelta = 1e-8 * 1e-8;
   463     double cost = calcCost();
   465       cout << iter << 
" Initial squared cost: " << cost << 
" which is "    466            << sqrt(cost/ncons) << 
" rms error" << endl;
   470     for (; iter<niter; iter++)  
   476         long long t0, t1, t2, t3;
   479           setupSparseSys(lambda,iter,useCSparse); 
   489             if (csp.B.rows() != 0)
   491                 int iters = csp.doBPCG(maxCGiters,initTol,iter);
   493                   cout << 
"[Block PCG] " << iters << 
" iterations" << endl;
   498         else if (useCSparse == 3)
   500             int res = csp.doPCG(maxCGiters);
   502               cout << 
"[DoSPA] Sparse PCG failed with error " << res << endl;
   505         else if (useCSparse > 0)
   507             if (csp.B.rows() != 0)
   509                 bool ok = csp.doChol();
   511                   cout << 
"[DoSBA] Sparse Cholesky failed!" << endl;
   517           A.ldlt().solveInPlace(B); 
   523         VectorXd &BB = useCSparse ? csp.B : B;
   527         double sqDiff = BB.squaredNorm();
   528         if (sqDiff < sqMinDelta) 
   531               cout << 
"Converged with delta: " << sqrt(sqDiff) << endl;
   537         for(
int i=0; i < ncams; i++)
   543             nd.
trans.head<2>() += BB.segment<2>(ci);
   553         double newcost = calcCost();
   555           cout << iter << 
" Updated squared cost: " << newcost << 
" which is "    556                << sqrt(newcost/ncons) << 
" rms error" << endl;
   572             for(
int i=0; i<ncams; i++)
   584               cout << iter << 
" Downdated cost: " << cost << endl;
   589         if (iter == 0 && verbose)
   591             printf(
"[SPA] Setup: %0.2f ms  Solve: %0.2f ms  Update: %0.2f ms\n",
   592                    0.001*(
double)(t1-t0),
   593                    0.001*(
double)(t2-t1),
   594                    0.001*(
double)(t3-t2));
   597         double dt=1e-6*(double)(t3-t0);
   599         if (print_iros_stats){
   600           cerr << 
"iteration= " << iter
   601                << 
"\t chi2= " << cost
   603                << 
"\t cumTime= " << cumTime
   604                << 
"\t kurtChi2= " << cost
   623   static inline int getind(std::map<int,int> &m, 
int ind)
   625     std::map<int,int>::iterator it;
   633   int SysSPA2d::doSPAwindowed(
int window, 
int niter, 
double sLambda, 
int useCSparse)
   636     int nnodes = nodes.size();
   637     if (nnodes < 2) 
return 0;
   639     int nlow = nnodes - window;
   640     if (nlow < 1) nlow = 1;     
   643       cout << 
"[SPA Window] From " << nlow << 
" to " << nnodes << endl;
   646     int ncons = p2cons.size();
   653     std::vector<Node2d,Eigen::aligned_allocator<Node2d> > &wnodes = spa.
nodes;
   654     std::vector<Con2dP2,Eigen::aligned_allocator<Con2dP2> > &wp2cons = spa.
p2cons;
   655     std::map<int,int> inds;
   656     std::vector<int> rinds;     
   659     for (
int i=0; i<ncons; i++)
   662         if (con.
ndr >= nlow || con.
nd1 >= nlow)
   663             wp2cons.push_back(con);
   665         if (con.
ndr >= nlow && con.
nd1 < nlow) 
   670                 inds.insert(std::pair<int,int>(con.
nd1,wnodes.size()));
   671                 wnodes.push_back(nodes[con.
nd1]);
   673             rinds.push_back(con.
nd1);
   675         else if (con.
nd1 >= nlow && con.
ndr < nlow)
   680                 inds.insert(std::pair<int,int>(con.
ndr,wnodes.size()));
   681                 wnodes.push_back(nodes[con.
ndr]);
   683             rinds.push_back(con.
ndr);
   687     spa.
nFixed = wnodes.size();
   689       cout << 
"[SPA Window] Fixed node count: " << spa.
nFixed << endl;
   692     for (
int i=0; i<(int)wp2cons.size(); i++)
   695         if (con.
nd1 >= nlow && con.
ndr >= nlow) 
   700                 inds.insert(std::pair<int,int>(con.
ndr,wnodes.size()));
   701                 wnodes.push_back(nodes[con.
ndr]);
   702                 rinds.push_back(con.
ndr);
   707                 inds.insert(std::pair<int,int>(con.
nd1,wnodes.size()));
   708                 wnodes.push_back(nodes[con.
nd1]);
   709                 rinds.push_back(con.
nd1);
   716         cout << 
"[SPA Window] Variable node count: " << spa.
nodes.size() - spa.
nFixed << endl;
   717         cout << 
"[SPA Window] Constraint count: " << spa.
p2cons.size() << endl;
   721     for (
int i=0; i<(int)wp2cons.size(); i++)
   729     niter = spa.
doSPA(niter,sLambda,useCSparse);
   732     for (
int i=0; i<(int)wp2cons.size(); i++)
   748   void SysSPA2d::setupSparseDSIF(
int newnode)
   752     int nFree = nodes.size() - nFixed;
   758     csp.setupBlockStructure(nFree,
false); 
   763     for(
size_t pi=0; pi<p2cons.size(); pi++)
   768         if (con.
ndr < newnode && con.
nd1 < newnode)
   774         int i0 = con.
ndr-nFixed; 
   775         int i1 = con.
nd1-nFixed; 
   780         if (i0 != i1-1) fact = 0.99; 
   784             Matrix<double,3,3> m = con.
J0t*con.
prec*con.
J0;
   785             csp.addDiagBlock(m,i0);
   789             Matrix<double,3,3> m = con.
J1t*con.
prec*con.
J1;
   790             csp.addDiagBlock(m,i1);
   794                 Matrix<double,3,3> m2 = con.
J0t*con.
prec*con.
J1;
   795                 m2 = m2 * fact * fact;
   799                     csp.addOffdiagBlock(m,i1,i0);
   803                     csp.addOffdiagBlock(m2,i0,i1);
   810           csp.B.block<3,1>(i0*3,0) -= con.
J0t * con.
prec * con.
err;
   812           csp.B.block<3,1>(i1*3,0) -= con.
J1t * con.
prec * con.
err;
   821     csp.setupCSstructure(1.0,
true); 
   833   void SysSPA2d::doDSIF(
int newnode)
   836     int nnodes = nodes.size();
   839     int ncons = p2cons.size();
   844         cout << 
"[doDSIF] No fixed frames" << endl;
   849     if (newnode >= nnodes)
   851         cout << 
"[doDSIF] no new nodes to add" << endl;
   856         for (
int i=newnode; i<nnodes; i++)
   858             nodes[i].oldtrans = nodes[i].trans;
   859             nodes[i].oldarot = nodes[i].arot;
   863     for (
int i=0; i<nnodes; i++)
   875     double cost = calcCost();
   877       cout << 
" Initial squared cost: " << cost << 
" which is "    878            << sqrt(cost/ncons) << 
" rms error" << endl;
   881     long long t0, t1, t2, t3;
   883     setupSparseDSIF(newnode); 
   886     cout << 
"[doDSIF] B = " << csp.B.transpose() << endl;
   888     cout << 
"[doDSIF] A = " << endl << A << endl;
   893     bool ok = csp.doChol();
   895       cout << 
"[doDSIF] Sparse Cholesky failed!" << endl;
   900     VectorXd &BB = csp.B;
   906     for(
int i=0; i < nnodes; i++)
   919     double newcost = calcCost();
   921       cout << 
" Updated squared cost: " << newcost << 
" which is "    922            << sqrt(newcost/ncons) << 
" rms error" << endl;
   935         cout << 
"Can't open file " << fname << endl;
   942         setupSparseSys(0.0,0);
   946         double *Ax = csp.A->x;
   948         for (
int i=0; i<csp.csize; i++)
   949           for (
int j=Ap[i]; j<Ap[i+1]; j++)
   951               ofs << Ai[j] << 
" " << i << setprecision(16) << 
" " << Ax[j] << endl;
   955         Eigen::IOFormat pfmt(16);
   957         int nrows = A.rows();
   958         int ncols = A.cols();
   960         for (
int i=0; i<nrows; i++)
   961           for (
int j=i; j<ncols; j++)
   965                 ofs << i << 
" " << j << setprecision(16) << 
" " << a << endl;
   976   void SysSPA2d::getGraph(std::vector<float> &graph)
   978     for (
int i=0; i<(int)p2cons.size(); i++)
   983         graph.push_back(nd0.
trans(0));
   984         graph.push_back(nd0.
trans(1));
   985         graph.push_back(nd1.
trans(0));
   986         graph.push_back(nd1.
trans(1));
  1006   void SysSPA2d::setupSparseDSIF(
int newnode)
  1008     cout << 
"[SetupDSIF] at " << newnode << endl;
  1012     int nFree = nodes.size() - nFixed;
  1018     csp.setupBlockStructure(nFree,
false); 
  1023     for(
size_t pi=0; pi<p2cons.size(); pi++)
  1028         if (con.
ndr < newnode && con.
nd1 < newnode)
  1034         Vector2d dRdth = nodes[con.
ndr].dRdx.transpose() * con.
tmean;
  1037         Matrix3d Jt = J.transpose();
  1039         u.head(2) = nodes[con.
ndr].trans.head(2);
  1040         u(2) = nodes[con.
ndr].arot;
  1042         f.head(2) = u.head(2) + nodes[con.
ndr].w2n.transpose().block<2,2>(0,0) * con.
tmean;
  1043         f(2) = u(2) + con.
amean;
  1044         if (f(2) > M_PI) f(2) -= 2.0*M_PI;
  1045         if (f(2) < M_PI) f(2) += 2.0*M_PI;
  1048         cout << 
"[SetupDSIF] u  = " << u.transpose() << endl;
  1049         cout << 
"[SetupDSIF] f  = " << f.transpose() << endl;
  1050         cout << 
"[SetupDSIF] fo = " << nodes[con.
nd1].trans.transpose() << endl;
  1054         int i0 = con.
ndr-nFixed; 
  1055         int i1 = con.
nd1-nFixed; 
  1057         if (i0 != i1-1) 
continue; 
  1061             Matrix<double,3,3> m = Jt*con.
prec*J;
  1062             csp.addDiagBlock(m,i0);
  1066             Matrix<double,3,3> m = con.
prec;
  1067             csp.addDiagBlock(m,i1);
  1071                 Matrix<double,3,3> m2 = -con.
prec * J;
  1077                     csp.addOffdiagBlock(m,i1,i0);
  1081                     csp.addOffdiagBlock(m2,i0,i1);
  1088         Vector3d Juf = J*u - f;
  1089         if (Juf(2) > M_PI) Juf(2) -= 2.0*M_PI;
  1090         if (Juf(2) < M_PI) Juf(2) += 2.0*M_PI;
  1093             csp.B.block<3,1>(i0*3,0) += Jt * con.
prec * Juf;
  1097             csp.B.block<3,1>(i1*3,0) -= con.
prec * Juf;
  1107     csp.setupCSstructure(1.0,
true); 
  1120   void SysSPA2d::doDSIF(
int newnode, 
bool useCSparse)
  1123     int nnodes = nodes.size();
  1126     int ncons = p2cons.size();
  1131         cout << 
"[doDSIF] No fixed frames" << endl;
  1136     if (newnode >= nnodes)
  1138         cout << 
"[doDSIF] no new nodes to add" << endl;
  1144     for (
int i=0; i<nnodes; i++)
  1156     double cost = calcCost();
  1158       cout << 
" Initial squared cost: " << cost << 
" which is "   1159            << sqrt(cost/ncons) << 
" rms error" << endl;
  1164         csp.setupBlockStructure(1,
false); 
  1168         csp.addDiagBlock(m,0);
  1170         u.head(2) = nodes[0].trans.head(2);
  1171         u(2) = nodes[0].arot;
  1172         csp.B.head(3) = u*1000000;
  1174         cout << 
"[doDSIF] B = " << csp.B.transpose() << endl;    
  1181     long long t0, t1, t2, t3;
  1184       setupSparseDSIF(newnode); 
  1189     cout << 
"[doDSIF] B = " << csp.B.transpose() << endl;
  1191     cout << 
"[doDSIF] A = " << endl << A << endl;
  1198         bool ok = csp.doChol();
  1200           cout << 
"[doDSIF] Sparse Cholesky failed!" << endl;
  1203       A.ldlt().solveInPlace(B); 
  1208     VectorXd &BB = useCSparse ? csp.B : B;
  1210     cout << 
"[doDSIF] RES  = " << BB.transpose() << endl;
  1214     for(
int i=0; i < nnodes; i++)
  1218         nd.
trans.head<2>() = BB.segment<2>(ci);
  1227     double newcost = calcCost();
  1229       cout << 
" Updated squared cost: " << newcost << 
" which is "   1230            << sqrt(newcost/ncons) << 
" rms error" << endl;
  1241   void SysSPA2d::setupSparseDSIF(
int newnode)
  1243     cout << 
"[SetupDSIF] at " << newnode << endl;
  1247     int nFree = nodes.size() - nFixed;
  1253     csp.setupBlockStructure(nFree,
false); 
  1258     for(
size_t pi=0; pi<p2cons.size(); pi++)
  1263         if (con.
ndr < newnode && con.
nd1 < newnode)
  1269         int i0 = con.
ndr-nFixed; 
  1270         int i1 = con.
nd1-nFixed; 
  1272         if (i0 != i1-1) 
continue; 
  1276             Matrix<double,3,3> m = con.
J0t*con.
prec*con.
J0;
  1277             csp.addDiagBlock(m,i0);
  1281             Matrix<double,3,3> m = con.
J1t*con.
prec*con.
J1;
  1282             csp.addDiagBlock(m,i1);
  1286                 Matrix<double,3,3> m2 = con.
J0t*con.
prec*con.
J1;
  1290                     csp.addOffdiagBlock(m,i1,i0);
  1294                     csp.addOffdiagBlock(m2,i0,i1);
  1305             u.head(2) = nodes[con.
ndr].trans.head(2);
  1306             u(2) = nodes[con.
ndr].arot;
  1307             Vector3d bm = con.
err + con.
J0 * u;
  1308             csp.B.block<3,1>(i0*3,0) += (bm.transpose() * con.
prec * con.
J0).transpose();
  1313             u.head(2) = nodes[con.
nd1].trans.head(2);
  1314             u(2) = nodes[con.
nd1].arot;
  1315             Vector3d bm = con.
err + con.
J1 * u;
  1316             csp.B.block<3,1>(i1*3,0) += (bm.transpose() * con.
prec * con.
J1).transpose();
  1326     csp.setupCSstructure(1.0,
true); 
  1339   void SysSPA2d::doDSIF(
int newnode, 
bool useCSparse)
  1342     int nnodes = nodes.size();
  1345     int ncons = p2cons.size();
  1350         cout << 
"[doDSIF] No fixed frames" << endl;
  1355     if (newnode >= nnodes)
  1357         cout << 
"[doDSIF] no new nodes to add" << endl;
  1361     for (
int i=0; i<nnodes; i++)
  1373     double cost = calcCost();
  1375       cout << 
" Initial squared cost: " << cost << 
" which is "   1376            << sqrt(cost/ncons) << 
" rms error" << endl;
  1382     long long t0, t1, t2, t3;
  1385       setupSparseDSIF(newnode); 
  1390     cout << 
"[doDSIF] B = " << csp.B.transpose() << endl;
  1392     cout << 
"[doDSIF] A = " << endl << A << endl;
  1399         bool ok = csp.doChol();
  1401           cout << 
"[doDSIF] Sparse Cholesky failed!" << endl;
  1404       A.ldlt().solveInPlace(B); 
  1409     VectorXd &BB = useCSparse ? csp.B : B;
  1411     cout << 
"[doDSIF] RES  = " << BB.transpose() << endl;
  1415     for(
int i=0; i < nnodes; i++)
  1419         nd.
trans.head<2>() = BB.segment<2>(ci);
  1428     double newcost = calcCost();
  1430       cout << 
" Updated squared cost: " << newcost << 
" which is "   1431            << sqrt(newcost/ncons) << 
" rms error" << endl;
  1440   void SysSPA2d::removeNode(
int id)
  1443     for (
int i=0; i<(int)nodes.size(); i++)
  1445         if (nodes[i].nodeId == ind)
  1448     if (ind < 0) 
return;
  1451     nodes.erase(nodes.begin() + ind);
  1457     while (i <(
int)p2cons.size())
  1459         std::vector<Con2dP2,Eigen::aligned_allocator<Con2dP2> >::iterator iter = p2cons.begin() + i;
  1460         if (iter->ndr == ind || iter->nd1 == ind)
  1466             if (iter->ndr > ind) iter->ndr--;
  1467             if (iter->nd1 > ind) iter->nd1--;
  1475   bool SysSPA2d::removeConstraint(
int ndi0, 
int ndi1)
  1477     int ni0 = -1, ni1 = -1;
  1478     for (
int i=0; i<(int)nodes.size(); i++)
  1480         if (nodes[i].nodeId == ndi0)
  1482         if (nodes[i].nodeId == ndi1)
  1485     if (ni0 < 0 || ni1 < 0) 
return false;
  1488     while (i <(
int)p2cons.size())
  1490         std::vector<Con2dP2,Eigen::aligned_allocator<Con2dP2> >::iterator iter = p2cons.begin() + i;
  1491         if (iter->ndr == ni0 && iter->nd1 == ni1)
 int doSPA(int niter, double sLambda=1.0e-4, int useCSparse=SBA_SPARSE_CHOLESKY, double initTol=1.0e-8, int CGiters=50)
Eigen::Vector2d tmean
Mean vector, quaternion (inverse) and precision matrix for this constraint. 
Eigen::Matrix< double, 3, 3 > J1
Eigen::Matrix< double, 3, 3 > J0
jacobian with respect to frames; uses dR'/dq from Node2d calculation 
void setJacobians(std::vector< Node2d, Eigen::aligned_allocator< Node2d > > &nodes)
bool isFixed
For SPA, is this camera fixed or free? 
int nd1
Node2d index for the second node. 
EIGEN_MAKE_ALIGNED_OPERATOR_NEW int nodeId
node id - somewhat redundant, but can be useful, e.g., in KARTO links 
Eigen::Matrix< double, 3, 3 > J1t
Eigen::Matrix< double, 3, 3 > J0t
Eigen::Matrix< double, 3, 3 > prec
double calcErr(const Node2d &nd0, const Node2d &nd1)
calculates projection error and stores it in <err> 
Eigen::Matrix< double, 3, 1 > trans
6DOF pose as a unit quaternion and translation vector 
Eigen::Matrix< double, 3, 1 > err
error 
void writeSparseA(const char *fname, SysSBA &sba)
void normArot()
Normalize to [-pi,+pi]. 
bool verbose
if we want statistics 
Eigen::Matrix< double, 3, 1 > oldtrans
Eigen::Matrix< double, 2, 3 > w2n
Resultant transform from world to node coordinates;. 
std::vector< Con2dP2, Eigen::aligned_allocator< Con2dP2 > > p2cons
Set of P2 constraints. 
std::vector< Node2d, Eigen::aligned_allocator< Node2d > > nodes
set of nodes (camera frames) for SPA system, indexed by position; 
static int getind(std::map< int, int > &m, int ind)
EIGEN_MAKE_ALIGNED_OPERATOR_NEW int ndr
Reference pose index. 
#define SBA_BLOCK_JACOBIAN_PCG
SysSPA2d holds a set of nodes and constraints for sparse pose adjustment. 
int nFixed
Number of fixed nodes. 
double calcErrDist(const Node2d &nd0, const Node2d &nd1)
calculate error in distance only, no weighting