42 using namespace Eigen;
50 auto duration = std::chrono::system_clock::now().time_since_epoch();
51 return std::chrono::duration_cast<std::chrono::microseconds>(duration).count();
60 #define F77_FUNC(func) func ## _ 62 extern int F77_FUNC(
dpotf2)(
char *uplo,
int *n,
double *a,
int *lda,
int *info);
63 extern int F77_FUNC(
dpotrf)(
char *uplo,
int *n,
double *a,
int *lda,
int *info);
64 extern int F77_FUNC(
dpotrs)(
char *uplo,
int *n,
int *nrhs,
double *a,
int *lda,
double *b,
int *ldb,
int *info);
65 extern int F77_FUNC(
dpotri)(
char *uplo,
int *n,
double *a,
int *lda,
int *info);
79 int SysSBA::addNode(Eigen::Matrix<double,4,1> &trans,
80 Eigen::Quaternion<double> &qrot,
95 return nodes.size()-1;
102 tracks.push_back(
Track(p));
103 return tracks.size()-1;
111 bool SysSBA::addProj(
int ci,
int pi, Eigen::Vector3d &q,
bool stereo)
116 if (tracks[pi].projections.count(ci) > 0)
118 if (tracks[pi].projections[ci].kp == q)
122 tracks[pi].projections[ci] =
Proj(ci, q, stereo);
125 Eigen::Matrix3d covar;
131 tracks[pi].projections[ci].setCovariance(covar);
141 bool SysSBA::addMonoProj(
int ci,
int pi, Eigen::Vector2d &q)
143 if (tracks[pi].projections.count(ci) > 0)
145 if (tracks[pi].projections[ci].kp.head(2) == q)
149 tracks[pi].projections[ci] =
Proj(ci, q);
156 bool SysSBA::addStereoProj(
int ci,
int pi, Eigen::Vector3d &q)
158 if (tracks[pi].projections.count(ci) > 0)
160 if (tracks[pi].projections[ci].kp == q)
164 tracks[pi].projections[ci] =
Proj(ci, q,
true);
167 Eigen::Matrix3d covar;
173 tracks[pi].projections[ci].setCovariance(covar);
180 void SysSBA::setProjCovariance(
int ci,
int pi, Eigen::Matrix3d &covar)
183 tracks[pi].projections[ci].setCovariance(covar);
187 void SysSBA::addPointPlaneMatch(
int ci0,
int pi0, Eigen::Vector3d normal0,
int ci1,
int pi1, Eigen::Vector3d normal1)
189 Point pt0 = tracks[pi0].point;
190 Point pt1 = tracks[pi1].point;
195 Vector3d proj_forward;
196 proj_forward = tracks[pi1].projections[ci1].kp;
198 addStereoProj(ci1, pi0, proj_forward);
200 Proj &forward_proj = tracks[pi0].projections[ci1];
212 proj_fake = tracks[pi0].projections[ci0].kp;
213 addStereoProj(ci0, pi1, proj_fake);
214 Proj &fake_proj = tracks[pi1].projections[ci0];
220 Vector3d proj_backward;
222 proj_backward = tracks[pi0].projections[ci0].kp;
223 addStereoProj(ci0, pi1, proj_backward);
225 Proj &backward_proj = tracks[pi1].projections[ci0];
235 void SysSBA::updateNormals()
237 for(
size_t i=0; i<tracks.size(); i++)
239 ProjMap &prjs = tracks[i].projections;
240 if (prjs.size() == 0)
continue;
242 for(ProjMap::iterator itr = prjs.begin(); itr != prjs.end(); itr++)
244 Proj &prj = itr->second;
250 Quaterniond qrot = nodes[prj.
ndi].qrot;
260 Point &pt0 = tracks[i].point;
263 Vector3d w = pt0.head<3>()-plane_point;
264 Vector3d projpt = pt0.head<3>() - (w.dot(plane_normal))*plane_normal;
271 int SysSBA::countProjs()
274 for(
size_t i=0; i<tracks.size(); i++)
276 ProjMap &prjs = tracks[i].projections;
285 double SysSBA::calcCost()
288 for(
size_t i=0; i<tracks.size(); i++)
290 ProjMap &prjs = tracks[i].projections;
291 if (prjs.size() == 0)
continue;
292 for(ProjMap::iterator itr = prjs.begin(); itr != prjs.end(); itr++)
294 Proj &prj = itr->second;
296 double err = prj.
calcErr(nodes[prj.
ndi],tracks[i].point,huber);
306 double SysSBA::calcCost(
double dist)
311 for(
size_t i=0; i<tracks.size(); i++)
313 ProjMap &prjs = tracks[i].projections;
314 if (prjs.size() == 0)
continue;
315 for(ProjMap::iterator itr = prjs.begin(); itr != prjs.end(); itr++)
317 Proj &prj = itr->second;
319 double err = prj.
calcErr(nodes[prj.
ndi],tracks[i].point);
332 double SysSBA::calcRMSCost(
double dist)
338 for(
size_t i=0; i<tracks.size(); i++)
340 ProjMap &prjs = tracks[i].projections;
341 if (prjs.size() == 0)
continue;
342 for(ProjMap::iterator itr = prjs.begin(); itr != prjs.end(); itr++)
344 Proj &prj = itr->second;
346 double err = prj.
calcErr(nodes[prj.
ndi],tracks[i].point,huber);
355 return sqrt(cost/(
double)nprjs);
361 double SysSBA::calcAvgError()
366 for(
size_t i=0; i<tracks.size(); i++)
368 ProjMap &prjs = tracks[i].projections;
369 if (prjs.size() == 0)
continue;
370 for(ProjMap::iterator itr = prjs.begin(); itr != prjs.end(); itr++)
372 Proj &prj = itr->second;
374 prj.
calcErr(nodes[prj.
ndi],tracks[i].point,huber);
380 return cost/(double)nprjs;
385 int SysSBA::numBadPoints()
389 for(
size_t i=0; i<tracks.size(); i++)
391 ProjMap &prjs = tracks[i].projections;
392 if (prjs.size() == 0)
continue;
393 for(ProjMap::iterator itr = prjs.begin(); itr != prjs.end(); itr++)
395 Proj &prj = itr->second;
398 if (prj.
err[0] == 0.0 && prj.
err[1] == 0.0 && prj.
err[2] == 0.0)
413 int SysSBA::countBad(
double dist)
418 double b2 = HUBER*HUBER;
419 dist = 2*b2*(sqrt(1+dist/b2)-1);
422 for (
int i=0; i<(int)tracks.size(); i++)
424 ProjMap &prjs = tracks[i].projections;
425 if (prjs.size() == 0)
continue;
426 for(ProjMap::iterator itr = prjs.begin(); itr != prjs.end(); itr++)
428 Proj &prj = itr->second;
442 int SysSBA::removeBad(
double dist)
447 for (
int i=0; i<(int)tracks.size(); i++)
449 ProjMap &prjs = tracks[i].projections;
450 if (prjs.size() == 0)
continue;
451 for(ProjMap::iterator itr = prjs.begin(); itr != prjs.end(); itr++)
453 Proj &prj = itr->second;
468 int SysSBA::reduceTracks()
471 for (
int i=0; i<(int)tracks.size(); i++)
473 ProjMap &prjs = tracks[i].projections;
477 for(ProjMap::iterator itr = prjs.begin(); itr != prjs.end(); )
479 Proj &prj = itr->second;
501 void SysSBA::printStats()
503 int ncams = nodes.size();
504 vector<map<int,int>, Eigen::aligned_allocator<map<int,int> > > conns;
506 VectorXi dcnt(ncams);
513 int npts = tracks.size();
518 if (tracks.size() > 0)
520 for (
int i=0; i<npts; i++)
522 int s = (int)tracks[i].projections.size();
527 cout <<
"[SBAsys] Cameras: " << ncams <<
" Points: " << npts
528 <<
" Projections: " << nprjs <<
" Hessian elements: " << nhs << endl;
529 cout <<
"[SBAsys] Average " << (double)nprjs/(
double)npts
530 <<
" projections per track and " << (double)nprjs/(
double)ncams
531 <<
" projections per camera" << endl;
533 cout <<
"[SBAsys] Checking camera order in projections..." << flush;
534 for (
int i=0; i<npts; i++)
537 ProjMap &prjs = tracks[i].projections;
541 for(ProjMap::iterator itr = prjs.begin(); itr != prjs.end(); itr++)
544 Proj &prj = itr->second;
559 if (j < (
int)prjs.size()-1)
561 map<int,int> &pm = conns[cami];
562 map<int,int>::iterator it;
563 for(ProjMap::iterator itr2 = itr; itr2 != prjs.end(); itr2++)
565 Proj &prj2 = itr2->second;
566 int cami2 = prj2.
ndi;
567 map<int,int> &pm2 = conns[cami2];
577 pm2.find(cami)->second++;
593 cout <<
"ok" << endl;
596 cout <<
"[SBAsys] Number of invalid projections: " << nbad << endl;
597 cout <<
"[SBAsys] Number of null tracks: " << n0 <<
" Number of single tracks: " << n1 <<
" Number of double tracks: " << n2 << endl;
602 for (
int i=0; i<ncams; i++)
604 if (dcnt(i) == 0) dnz++;
605 if (dcnt(i) < 5) dn5++;
607 cout <<
"[SBAsys] Number of disconnected cameras: " << dnz << endl;
608 cout <<
"[SBAsys] Number of cameras with <5 projs: " << dn5 << endl;
623 for (
int i=0; i<ncams; i++)
625 int nc = conns[i].size();
629 map<int,int>::iterator it;
630 for (it = conns[i].begin(); it != conns[i].end(); it++)
632 int np = (*it).second;
634 if (np < nmin) nmin = np;
635 if (np > nmax) nmax = np;
643 cout <<
"[SBAsys] Number of camera connections: " << nconns/2 <<
" which is " 644 << (double)nconns/(
double)ncams <<
" connections per camera and " 645 << (nconns+ncams)*100.0/(ncams*ncams) <<
" percent matrix fill" << endl;
646 cout <<
"[SBAsys] Min connection points: " << nmin <<
" Max connection points: " 647 << nmax <<
" Average connection points: " << (double)ntot/(
double)nconns << endl;
648 cout <<
"[SBAsys] Total connection projections: " << ntot << endl;
649 cout <<
"[SBAsys] Connections with less than 5 points: " << nc5/2 <<
" 10 pts: " << nc10/2
650 <<
" 20 pts: " << nc20/2 <<
" 50 pts: " << nc50/2 << endl;
655 vector<map<int,int> > SysSBA::generateConns_()
657 int ncams = nodes.size();
658 vector<map<int,int> > conns;
662 connMat.resize(ncams);
663 for (
int i=0; i<ncams; i++)
665 vector<bool> &bm = connMat[i];
666 bm.assign(ncams,
false);
670 for (
int i=0; i<(int)tracks.size(); i++)
673 ProjMap &prjs = tracks[i].projections;
674 for(ProjMap::iterator itr = prjs.begin(); itr != prjs.end(); itr++)
676 Proj &prj = itr->second;
685 if (j < (
int)prjs.size()-1)
687 map<int,int> &pm = conns[cami];
688 map<int,int>::iterator it;
689 for(ProjMap::iterator itr2 = itr; itr2 != prjs.end(); itr2++)
691 Proj &prj2 = itr2->second;
692 int cami2 = prj2.
ndi;
693 map<int,int> &pm2 = conns[cami2];
703 pm2.find(cami)->second++;
716 void SysSBA::setConnMat(
int minpts)
719 int ncams = nodes.size();
721 vector<map<int,int> > conns = generateConns_();
724 multimap<int,pair<int,int> > weakcs;
725 for (
int i=0; i<ncams; i++)
727 map<int,int> cs = conns[i];
728 map<int,int>::iterator it;
729 for (it = cs.begin(); it != cs.end(); it++)
731 if (it->second < minpts && it->first > i)
732 weakcs.insert(pair<
int,pair<int,int> >(it->second, pair<int,int>(i,it->first)));
736 cout <<
"[SetConnMat] Found " << weakcs.size() <<
" connections with < " 737 << minpts <<
" points" << endl;
741 multimap<int,pair<int,int> >::iterator it;
742 for (it = weakcs.begin(); it != weakcs.end(); it++)
744 int c0 = it->second.first;
745 int c1 = it->second.second;
746 if (conns[c0].size() > 1 && conns[c1].size() > 1)
749 conns[c0].erase(conns[c0].find(c1));
750 conns[c1].erase(conns[c1].find(c0));
752 connMat[c0][c1] =
true;
753 connMat[c1][c0] =
true;
757 cout <<
"[SetConnMat] Erased " << n <<
" connections" << endl;
764 void SysSBA::setConnMatReduced(
int maxconns)
767 int ncams = nodes.size();
769 vector<map<int,int> > conns = generateConns_();
772 multimap<int,pair<int,int> > weakcs;
773 for (
int i=0; i<ncams; i++)
775 map<int,int> cs = conns[i];
776 map<int,int>::iterator it;
777 for (it = cs.begin(); it != cs.end(); it++)
780 weakcs.insert(pair<
int,pair<int,int> >(-it->second, pair<int,int>(i,it->first)));
787 found.assign(ncams,0);
788 multimap<int,pair<int,int> >::iterator it;
789 for (it = weakcs.begin(); it != weakcs.end(); it++)
791 int c0 = it->second.first;
792 int c1 = it->second.second;
793 if (found[c0] < maxconns || found[c1] < maxconns)
799 connMat[c0][c1] =
false;
800 connMat[c1][c0] =
false;
804 cout <<
"[SetConnMat] Found " << n <<
" connections in spanning tree" << endl;
811 SysSBA::tsplit(
int tri,
int len)
813 ProjMap prjs = tracks[tri].projections;
814 tracks[tri].projections.clear();
818 if ((
int)prjs.size() == len+1) len = len+1;
822 while (prjs.size() > 0 && i < len)
825 ProjMap::iterator randomitr = prjs.begin();
826 std::advance( randomitr, rand() % prjs.size());
827 Proj &prj = randomitr->second;
830 addProj(prj.ndi, tri, prj.kp, prj.stereo);
831 prjs.erase(randomitr);
836 int pti = tracks.size();
837 while (prjs.size() > 0)
840 if ((
int)prjs.size() == len+1) len = len+1;
841 while (prjs.size() > 0 && i < len)
844 ProjMap::iterator randomitr = prjs.begin();
845 std::advance( randomitr, rand() % prjs.size());
846 Proj &prj = randomitr->second;
850 addProj(prj.ndi, pti, prj.kp, prj.stereo);
851 prjs.erase(randomitr);
854 tracks[pti].point = tracks[tri].point;
863 int SysSBA::reduceLongTracks(
double len)
867 int npts = tracks.size();
869 #if 1 // this algorithm splits tracks 874 for (
int i=0; i<npts; i++)
876 if ((
int)tracks[i].projections.size() > ilen)
880 int ts = tracks[i].projections.size()+1;
888 #else // this throws them out 892 multimap<int,int> ordps;
895 for (
int i=0; i<npts; i++)
896 if ((
int)tracks[i].size() > ilen)
897 ordps.insert(pair<int,int>(-(
int)tracks[i].size(), i));
901 int nn = ordps.size();
902 map<int,int>::iterator it = ordps.begin();
904 for (
int i=0; i<nn; i++, it++)
905 rem.push_back(it->second);
906 sort(rem.begin(),rem.end());
907 cout <<
"Finished finding " << rem.size() <<
" tracks" << endl;
909 std::vector<Point, Eigen::aligned_allocator<Point> > pts;
910 std::vector< std::vector<MonoProj, Eigen::aligned_allocator<MonoProj> >,
911 Eigen::aligned_allocator<std::vector<MonoProj, Eigen::aligned_allocator<MonoProj> > > > trs;
916 for (
int i=0; i<npts; i++)
918 if (rem.size()>n && i == rem[n])
923 pts.push_back(points[i]);
924 vector<MonoProj, Eigen::aligned_allocator<MonoProj> > &prjs = tracks[i];
927 trs.push_back(tracks[i]);
932 points.resize(pts.size());
933 tracks.resize(pts.size());
946 int SysSBA::remExcessTracks(
int minpts)
950 int npts = tracks.size();
952 vector<map<int,int> > conns = generateConns_();
955 multimap<int,int> ordtrs;
956 for (
int i=0; i<npts; i++)
957 ordtrs.insert(pair<int,int>((
int)tracks[i].projections.size(),i));
961 multimap<int,int>::reverse_iterator it;
962 for (it = ordtrs.rbegin(); it != ordtrs.rend(); it++)
964 int tri = it->second;
965 ProjMap &prjs = tracks[tri].projections;
967 for(ProjMap::iterator itr = prjs.begin(); itr != prjs.end(); itr++)
969 Proj &prj = itr->second;
972 for(ProjMap::iterator itr2 = itr; itr2 != prjs.end(); itr2++)
974 Proj &prj2 = itr2->second;
976 if (conns[c0].find(c1)->second <= minpts)
987 for(ProjMap::iterator itr = prjs.begin(); itr != prjs.end(); itr++)
989 Proj &prj = itr->second;
991 for(ProjMap::iterator itr2 = itr; itr2 != prjs.end(); itr2++)
993 Proj &prj2 = itr2->second;
995 conns[c0].find(c1)->second--;
996 conns[c1].find(c0)->second--;
999 remtrs.push_back(tri);
1004 for (
int i=0; i<(int)remtrs.size(); i++)
1006 int s = tracks[remtrs[i]].projections.size();
1010 cout <<
"[RemExcessTracks] Can erase " << remtrs.size() <<
" tracks with " << hms <<
" H entries" << endl;
1012 std::sort(remtrs.begin(),remtrs.end());
1014 std::vector<Track, Eigen::aligned_allocator<Track> > trs;
1019 for (
int i=0; i<npts; i++)
1021 if ((
int)remtrs.size()>n && i == remtrs[n])
1029 trs.push_back(tracks[i]);
1033 cout <<
"[RemExcessTracks] Erased " << n <<
" tracks" << endl;
1036 tracks.resize(trs.size());
1039 return remtrs.size();
1047 void SysSBA::setupSys(
double sLambda)
1050 int nFree = nodes.size() - nFixed;
1051 A.setZero(6*nFree,6*nFree);
1053 VectorXi dcnt(nFree);
1054 dcnt.setZero(nFree);
1057 double lam = 1.0 + sLambda;
1060 for(
size_t pi=0; pi<tracks.size(); pi++)
1062 ProjMap &prjs = tracks[pi].projections;
1063 if (prjs.size() < 1)
continue;
1066 if (prjs.size() > jps.size())
1067 jps.resize(prjs.size());
1078 for(ProjMap::iterator itr = prjs.begin(); itr != prjs.end(); itr++, ii++)
1080 Proj &prj = itr->second;
1082 int ci = (prj.
ndi - nFixed) * 6;
1088 if (!nodes[prj.
ndi].isFixed)
1090 dcnt(prj.
ndi - nFixed)++;
1092 A.block<6,6>(ci,ci) += prj.
jp->
Hcc;
1093 B.block<6,1>(ci,0) -= prj.
jp->
JcTE;
1100 Hpp.diagonal() *= lam;
1101 Matrix3d Hppi = Hpp.inverse();
1102 Vector3d &tp = tps[pi];
1106 for(ProjMap::iterator itr = prjs.begin(); itr != prjs.end(); itr++)
1108 Proj &prj = itr->second;
1110 if (nodes[prj.
ndi].isFixed)
continue;
1111 int ci = (prj.
ndi - nFixed) * 6;
1113 B.block<6,1>(ci,0) -= prj.
jp->
Hpc.transpose() * tp;
1114 prj.
Tpc = prj.
jp->
Hpc.transpose() * Hppi;
1117 for(ProjMap::iterator itr2 = itr; itr2 != prjs.end(); itr2++)
1119 Proj &prj2 = itr2->second;
1121 if (nodes[prj2.
ndi].isFixed)
continue;
1122 int ci2 = (prj2.
ndi - nFixed) * 6;
1125 A.block<6,6>(ci,ci2) -= prj.
Tpc * prj2.
jp->
Hpc;
1128 A.block<6,6>(ci2,ci) = A.block<6,6>(ci,ci2).transpose();
1135 A.diagonal() *= lam;
1138 for (
int i=0; i<6*nFree; i++)
1139 for (
int j=0; j<6*nFree; j++)
1140 if (std::isnan(A(i,j)) ) { printf(
"[SetupSys] NaN in A\n"); *(
int *)0x0 = 0; }
1142 for (
int j=0; j<6*nFree; j++)
1143 if (std::isnan(B[j]) ) { printf(
"[SetupSys] NaN in B\n"); *(
int *)0x0 = 0; }
1146 for (
int i=0; i<nFree; i++)
1147 if (dcnt(i) == 0) ndc++;
1150 cout <<
"[SetupSys] " << ndc <<
" disconnected nodes" << endl;
1161 void SysSBA::setupSparseSys(
double sLambda,
int iter,
int sparseType)
1164 int nFree = nodes.size() - nFixed;
1165 if (nFree < 0) nFree = 0;
1167 long long t0, t1, t2, t3;
1170 csp.setupBlockStructure(nFree);
1172 csp.setupBlockStructure(0);
1176 VectorXi dcnt(nFree);
1177 dcnt.setZero(nFree);
1180 double lam = 1.0 + sLambda;
1183 bool useConnMat = connMat.size() > 0;
1187 for(
size_t pi=0; pi<tracks.size(); pi++)
1189 ProjMap &prjs = tracks[pi].projections;
1190 if (prjs.size() < 1)
continue;
1193 if (prjs.size() > jps.size())
1194 jps.resize(prjs.size());
1205 for(ProjMap::iterator itr = prjs.begin(); itr != prjs.end(); itr++, ii++)
1207 Proj &prj = itr->second;
1209 int ni = prj.
ndi - nFixed;
1216 if (!nodes[prj.
ndi].isFixed)
1218 dcnt(prj.
ndi - nFixed)++;
1221 csp.addDiagBlock(prj.
jp->
Hcc,ni);
1222 csp.B.block<6,1>(ci,0) -= prj.
jp->
JcTE;
1229 Hpp.diagonal() *= lam;
1230 Matrix3d Hppi = Hpp.inverse();
1231 Vector3d &tp = tps[pi];
1235 for(ProjMap::iterator itr = prjs.begin(); itr != prjs.end(); itr++)
1237 Proj &prj = itr->second;
1239 if (nodes[prj.
ndi].isFixed)
continue;
1240 int ni = prj.
ndi - nFixed;
1243 csp.B.block<6,1>(ci,0) -= prj.
jp->
Hpc.transpose() * tp;
1244 prj.
Tpc = prj.
jp->
Hpc.transpose() * Hppi;
1248 for(ProjMap::iterator itr2 = itr; itr2 != prjs.end(); itr2++)
1250 Proj &prj2 = itr2->second;
1252 if (nodes[prj2.
ndi].isFixed)
continue;
1253 int ni2 = prj2.
ndi - nFixed;
1254 if (useConnMat && connMat[prj.
ndi][prj2.
ndi])
1259 Matrix<double,6,6> m = -prj.
Tpc * prj2.
jp->
Hpc;
1261 csp.addDiagBlock(m,ni);
1263 csp.addOffdiagBlock(m,ni,ni2);
1267 Matrix<double,6,6> m = -prj.
Tpc * prj.
jp->
Hpc;
1268 csp.addDiagBlock(m,ni);
1281 csp.incDiagBlocks(lam);
1283 csp.setupCSstructure(lam,iter==0);
1288 printf(
"\n[SetupSparseSys] Block: %0.1f Cons: %0.1f CS: %0.1f\n",
1289 (t1-t0)*.001, (t2-t1)*.001, (t3-t2)*.001);
1292 for (
int i=0; i<nFree; i++)
1293 if (dcnt(i) == 0) ndc++;
1296 cout <<
"[SetupSys] " << ndc <<
" disconnected nodes" << endl;
1308 int SysSBA::doSBA(
int niter,
double sLambda,
int useCSparse,
double initTol,
int maxCGiter)
1312 oldpoints.resize(tracks.size());
1316 int npts = tracks.size();
1317 int ncams = nodes.size();
1322 for(
size_t i=0; i<tracks.size(); i++)
1324 oldpoints[i] = tracks[i].point;
1325 nprjs += tracks[i].projections.size();
1328 if (nprjs == 0 || npts == 0 || ncams == 0)
1340 cout <<
"[doSBA] No fixed frames" << endl;
1343 for (
int i=0; i<ncams; i++)
1345 Node &nd = nodes[i];
1352 nd.
setDr(useLocalAngles);
1356 double laminc = 2.0;
1357 double lamdec = 0.5;
1359 sqMinDelta = 1e-8 * 1e-8;
1361 double cost = calcCost();
1365 cout << iter <<
" Initial squared cost: " << cost <<
" which is " 1366 << sqrt(cost/nprjs) <<
" rms pixel error and " 1367 << calcAvgError() <<
" average reproj error; " 1368 << numBadPoints() <<
" bad points" << endl;
1371 for (; iter<niter; iter++)
1382 setupSparseSys(lambda,iter,useCSparse);
1393 sprintf(fn,
"A%d.txt",xs);
1394 printf(
"Writing file %s\n",fn);
1395 FILE *fd = fopen(fn,
"w");
1396 fprintf(fd,
"%d %d\n",xs,xs);
1397 for (
int ii=0; ii<xs; ii++)
1398 for (
int jj=0; jj<xs; jj++)
1399 fprintf(fd,
"%.16g\n",A(ii,jj));
1402 sprintf(fn,
"B%d.txt",xs);
1404 fprintf(fd,
"%d\n",xs);
1405 for (
int ii=0; ii<xs; ii++)
1406 fprintf(fd,
"%.16g\n",B(ii));
1415 if (csp.B.rows() != 0)
1417 int iters = csp.doBPCG(maxCGiter,initTol,iter);
1418 cout <<
"[Block PCG] " << iters <<
" iterations" << endl;
1421 else if (useCSparse > 0)
1423 if (csp.B.rows() != 0)
1425 bool ok = csp.doChol();
1427 cout <<
"[DoSBA] Sparse Cholesky failed!" << endl;
1433 A.llt().solveInPlace(B);
1435 printf(
"\nDoing dpotrf/dpotrs\n");
1436 double *a = A.data();
1437 int info, m = B.size();
1438 double *x = B.data();
1441 F77_FUNC(
dpotrs)(
"U", (
int *)&m, (
int *)&nrhs, a, (
int *)&m, x, (
int *)&m, &info);
1450 VectorXd &BB = useCSparse ? csp.B : B;
1454 double sqDiff = BB.squaredNorm();
1455 if (sqDiff < sqMinDelta)
1458 cout <<
"Converged with delta: " << sqrt(sqDiff) << endl;
1464 for(vector<
Node, Eigen::aligned_allocator<Node> >::iterator itr = nodes.begin(); itr != nodes.end(); itr++)
1470 nd.
trans.head<3>() += BB.segment<3>(ci);
1474 Quaternion<double> qr;
1475 qr.vec() = BB.segment<3>(ci+3);
1479 qr.w() = sqrt(1.0 - qr.vec().squaredNorm());
1486 nd.
qrot.coeffs().head<3>() += BB.segment<3>(ci+3);
1492 nd.
setDr(useLocalAngles);
1499 for(vector<
Track, Eigen::aligned_allocator<Track> >::iterator itr = tracks.begin();
1500 itr != tracks.end(); itr++, pi++)
1502 ProjMap &prjs = itr->projections;
1503 if (prjs.size() < 1)
continue;
1504 Vector3d tp = tps[pi];
1506 for(ProjMap::iterator pitr = prjs.begin(); pitr != prjs.end(); pitr++)
1508 Proj &prj = pitr->second;
1510 if (nodes[prj.
ndi].isFixed)
continue;
1511 int ci = (prj.
ndi - nFixed) * 6;
1513 tp -= prj.
Tpc.transpose() * BB.segment<6>(ci);
1516 oldpoints[pi] = tracks[pi].point;
1517 tracks[pi].point.head(3) += tp;
1524 double newcost = calcCost();
1529 cout << iter <<
" Updated squared cost: " << newcost <<
" which is " 1530 << sqrt(newcost/(
double)nprjs) <<
" rms pixel error and " 1531 << calcAvgError() <<
" average reproj error; " 1532 << numBadPoints() <<
" bad points" << endl;
1547 for(
int i=0; i < (int)tracks.size(); i++)
1549 tracks[i].point = oldpoints[i];
1552 for(
int i=0; i < (int)nodes.size(); i++)
1554 Node &nd = nodes[i];
1560 nd.
setDr(useLocalAngles);
1566 cout << iter <<
" Downdated cost: " << cost << endl;
1571 if (iter == 0 && verbose > 0)
1572 printf(
"\n[SBA] Cost: %0.2f ms Setup: %0.2f ms Solve: %0.2f ms Update: %0.2f ms Total: %0.2f ms\n\n",
1573 0.001*(
double)(t4-t3),
1574 0.001*(
double)(t1-t0),
1575 0.001*(
double)(t2-t1),
1576 0.001*(
double)(t3-t2),
1577 0.001*(
double)(t4-t0));
1588 void SysSBA::mergeTracks(std::vector<std::pair<int,int> > &prs)
1591 int ntrs = tracks.size();
1595 for (
int i=0; i<ntrs; i++)
1599 for (
int i=0; i<(int)prs.size(); i++)
1601 pair<int,int> &pr = prs[i];
1602 int p0 = min(pr.first,pr.second);
1603 int p1 = max(pr.first,pr.second);
1608 for (
int i=0; i<ntrs; i++)
1609 tris[i] = tris[tris[i]];
1612 if (tracks.size() > 0)
1614 for (
int i=0; i<(int)tracks.size(); i++)
1616 if (tris[i] == i)
continue;
1618 ProjMap &tr0 = tracks[tris[i]].projections;
1619 ProjMap &tr1 = tracks[i].projections;
1621 for(ProjMap::iterator itr1 = tr1.begin(); itr1 != tr1.end(); itr1++)
1623 Proj &prj = itr1->second;
1634 for (
int i=0; i<(int)tracks.size(); i++)
1636 if (tris[i] != i)
continue;
1637 if (n == i)
continue;
1638 tracks[n] = tracks[i];
1639 tracks[n].point = tracks[i].point;
1656 int SysSBA::mergeTracksSt(
int tri0,
int tri1)
1659 ProjMap tr0 = tracks[tri0].projections;
1660 ProjMap &tr1 = tracks[tri1].projections;
1662 for(ProjMap::iterator itr = tr1.begin(); itr != tr1.end(); itr++)
1664 Proj &prj = itr->second;
1668 tracks[tri0].projections = tr0;
void setKcam(const fc::CamParams &cp)
Sets the Kcam and baseline matrices from frame_common::CamParams.
void setDr(bool local=false)
Set angle derivates.
void normRot()
Normalize quaternion to unit. Problem with global derivatives near w=0, solved by a hack for now...
Eigen::Matrix< double, 3, 6 > Hpc
Point-to-camera Hessian (JpT*Jc)
Eigen::Vector3d plane_local_normal
Original normal in plane_node_index coordinate's frame.
double calcErr(const Node &nd, const Point &pt, double huber=0.0)
Calculates re-projection error and stores it in err.
std::map< const int, Proj, std::less< int >, Eigen::aligned_allocator< Proj > > ProjMap
Eigen::Quaternion< double > oldqrot
Previous quaternion rotation, saved for downdating within LM.
int F77_FUNC() dpotrf(char *uplo, int *n, double *a, int *lda, int *info)
Eigen::Matrix< double, 6, 6 > Hcc
Camera-to-camera Hessian (JcT*Jc)
void setJacobians(const Node &nd, const Point &pt, JacobProds *jpp)
Sets the jacobians and hessians for the projection to use for SBA.
int F77_FUNC() dpotrs(char *uplo, int *n, int *nrhs, double *a, int *lda, double *b, int *ldb, int *info)
Eigen::Matrix< double, 3, 3 > Hpp
Point-to-point Hessian (JpT*Jp).
Eigen::Vector3d err
Reprojection error.
bool isFixed
For SBA, is this camera fixed or free?
Eigen::Matrix< double, 3, 1 > Bp
The B matrix with respect to points (JpT*Err)
int plane_point_index
Point-plane match point index in SBA.
Eigen::Matrix< double, 4, 1 > oldtrans
Previous translation, saved for downdating within LM.
NODE holds graph nodes corresponding to frames, for use in sparse bundle adjustment. Each node has a 6DOF pose, encoded as a translation vector and rotation unit quaternion (Eigen classes). These represent the pose of the node in the world frame.
int plane_node_index
Point-plane node index in SBA.
Eigen::Matrix< double, 6, 3 > Tpc
int F77_FUNC() dpotri(char *uplo, int *n, double *a, int *lda, int *info)
Eigen::Matrix< double, 6, 1 > JcTE
Another matrix with respect to cameras (JcT*Err)
bool stereo
Whether the projection is Stereo (True) or Monocular (False).
double getErrNorm()
Get the correct norm of the error, depending on whether the projection is monocular or stereo...
Proj holds a projection measurement of a point onto a frame. They are a repository for the link betwe...
Eigen::Quaternion< double > qrot
Rotation of the node expressed as a Quaternion.
int F77_FUNC() dpotf2(char *uplo, int *n, double *a, int *lda, int *info)
int ndi
Node index, the camera node for this projection.
Eigen::Vector3d plane_point
Point for point-plane projections.
bool isValid
valid or not (could be out of bounds)
EIGEN_MAKE_ALIGNED_OPERATOR_NEW Eigen::Matrix< double, 4, 1 > trans
Translation in homogeneous coordinates, last element is 1.0.
void setTransform()
Sets the transform matrices of the node.
Eigen::Vector3d kp
Keypoint, u,v,u-d vector.
double getErrSquaredNorm()
Get the correct squared norm of the error, depending on whether the projection is monocular or stereo...
JacobProds * jp
Jacobian products.
bool pointPlane
Whether this is a point-plane match (true) or a point-point match (false).
Eigen::Vector4d Point
Point holds 3D points using in world coordinates. Currently we just represent these as 4-vectors...
#define SBA_BLOCK_JACOBIAN_PCG
Eigen::Vector3d plane_normal
Normal for point-plane projections.