344int main(
int argc,
char** argv) {
347 string inputFilename;
349 string outputfilename;
359 int updateGraphEachN = 10;
363 arg.
param(
"i", maxIterations, 5,
"perform n iterations");
364 arg.
param(
"v", verbose,
false,
"verbose output of the optimization process");
365 arg.
param(
"guess", initialGuess,
false,
366 "initial guess based on spanning tree");
367 arg.
param(
"inc", incremental,
false,
"run incremetally");
368 arg.
param(
"update", updateGraphEachN, 10,
369 "updates afert x odometry nodes, (default: 10)");
370 arg.
param(
"guiOut", guiOut,
false,
"gui output while running incrementally");
371 arg.
param(
"lambdaInit", lambdaInit, 0,
372 "user specified lambda init for levenberg");
373 arg.
param(
"marginalize", marginalize,
false,
"on or off");
374 arg.
param(
"method", strMethod,
"Gauss",
"Gauss or Levenberg");
375 arg.
param(
"gnudump", gnudump,
"",
"dump to gnuplot data file");
376 arg.
param(
"o", outputfilename,
"",
"output final version of the graph");
377 arg.
param(
"solver", strSolver,
"var",
378 "specify which solver to use underneat\n\t {var, fix3_2, fix6_3, "
380 arg.
param(
"stats", statsFile,
"",
"specify a file for the statistics");
381 arg.
param(
"listTypes", listTypes,
false,
"list the registered types");
382 arg.
param(
"renameTypes", loadLookup,
"",
383 "create a lookup for loading types into other types,\n\t "
384 "TAG_IN_FILE=INTERNAL_TAG_FOR_TYPE,TAG2=INTERNAL2\n\t e.g., "
385 "VERTEX_CAM=VERTEX_SE3:EXPMAP");
387 "graph file which will be processed");
392 OptimizableGraph::printRegisteredTypes(cout,
true);
401 if (!optimizer.
solver()) {
402 cerr <<
"Error allocating solver" << endl;
405 optimizer.userLambdaInit() = lambdaInit;
407 assert(optimizer.
solver());
408 ActivePathCostFunction* guessCostFunction = 0;
409 if (initialGuess) guessCostFunction =
new ActivePathCostFunction(&optimizer);
411 cerr <<
"Read input from " << inputFilename << endl;
412 ifstream ifs(inputFilename.c_str());
414 cerr <<
"Failed to open file" << endl;
418 if (loadLookup.size() > 0) {
422 if (!optimizer.
load(ifs)) {
423 cerr <<
"Error loading graph" << endl;
427 cerr <<
"Loaded " << optimizer.
vertices().size() <<
" vertices" << endl;
428 cerr <<
"Loaded " << optimizer.
edges().size() <<
" edges" << endl;
430 if (optimizer.
vertices().size() == 0) {
431 cerr <<
"HyperGraph contains no vertices" << endl;
437 cerr <<
"Preparing Marginalization of the Landmarks ... ";
439 for (HyperGraph::VertexIDMap::iterator it = optimizer.
vertices().begin();
440 it != optimizer.
vertices().end(); ++it) {
445 for (HyperGraph::VertexIDMap::iterator it = optimizer.
vertices().begin();
446 it != optimizer.
vertices().end(); ++it) {
454 cerr <<
"done." << endl;
465 int incIterations = 1;
466 int updateDisplayEveryN = updateGraphEachN;
470 for (SparseOptimizer::VertexIDMap::const_iterator it = vertices.begin();
471 it != vertices.end(); ++it) {
474 maxDim = (max)(maxDim, v->dimension());
477 vector<SparseOptimizer::Edge*> edges;
478 for (SparseOptimizer::EdgeSet::iterator it = optimizer.
edges().begin();
479 it != optimizer.
edges().end(); ++it) {
483 optimizer.
edges().clear();
492 int lastOptimizedVertexCount = 0;
493 int lastVisUpdateVertexCount = 0;
494 bool addNextEdge =
true;
495 bool freshlyOptimized =
false;
496 for (vector<SparseOptimizer::Edge*>::iterator it = edges.begin();
497 it != edges.end(); ++it) {
499 bool optimize =
false;
501 if (addNextEdge && !optimizer.
vertices().empty()) {
502 int maxInGraph = optimizer.
vertices().rbegin()->first;
504 if (maxInGraph < idMax && !freshlyOptimized) {
516 if (!v1 && addNextEdge) {
523 if (v->dimension() == maxDim) vertexCount++;
526 if (!v2 && addNextEdge) {
533 if (v->dimension() == maxDim) vertexCount++;
540 cerr <<
"Unable to add edge " << e->
vertex(0)->
id() <<
" -> "
551 if (e->initialEstimatePossible(to, from)) {
556 e->initialEstimate(to, from);
560 if (e->initialEstimatePossible(from, to)) {
564 e->initialEstimate(from, to);
568 cerr <<
"doInit wrong value\n";
573 freshlyOptimized =
false;
576 if (vertexCount - lastOptimizedVertexCount >= updateGraphEachN) {
578 int currentIt = optimizer.
optimize(incIterations);
583 double chi2 = optimizer.
chi2();
584 cerr <<
"nodes= " << optimizer.
vertices().size()
585 <<
"\t edges= " << optimizer.
edges().size()
586 <<
"\t chi2= " << chi2 <<
"\t time= " << dts
587 <<
"\t iterations= " << currentIt <<
"\t cumTime= " << cumTime
590 lastOptimizedVertexCount = vertexCount;
593 if (!verbose) cerr <<
".";
595 freshlyOptimized =
true;
600 if (vertexCount - lastVisUpdateVertexCount >= updateDisplayEveryN) {
602 lastVisUpdateVertexCount = vertexCount;
609 if (gnudump.size() > 0)
611 optimizer.
edges().end(),
true,
false);
612 if (gnudump.size() > 0)
614 optimizer.
edges().end());
615 if (gnudump.size() > 0)
617 optimizer.
edges().end(),
true,
true);
621 cerr <<
"Initial chi2 = " << optimizer.
chi2() << endl;
623 if (statsFile !=
"") {
628 int i = optimizer.
optimize(maxIterations, guessCostFunction);
630 cerr <<
"Cholesky failed, result might be invalid" << endl;
633 if (gnudump.size() > 0)
635 optimizer.
edges().end(),
true,
false);
636 if (gnudump.size() > 0)
638 optimizer.
edges().end());
639 if (gnudump.size() > 0)
641 optimizer.
edges().end(),
true,
true);
643 cerr <<
"Computing chi2 statistics ";
644 double sumChi2 = 0.0;
645 double chi2Thres = 0.0;
648 for (HyperGraph::EdgeSet::const_iterator it = optimizer.
edges().begin();
649 it != optimizer.
edges().end(); ++it) {
653 sumChi2 += e->
chi2();
656 chi2Thres = sumChi2 / cnt * 1.4;
657 cerr <<
" threshold=" << chi2Thres <<
" done" << endl;
659 cerr <<
"Searching for high error edges .. ";
667 for (HyperGraph::EdgeSet::const_iterator it = optimizer.
edges().begin();
668 it != optimizer.
edges().end(); ++it) {
672 double edgeChi2 = e->
chi2();
673 if (edgeChi2 > chi2Thres) {
678 highErrorEdges.insert(*it);
684 highErrorEdgesToFeatures.insert(*it);
689 cerr <<
" found=" << highErrorEdges.size() <<
"/"
690 << highErrorEdgesToFeatures.size() <<
" edges with high errors .. done"
693 if (gnudump.size() > 0)
695 highErrorEdges.end(),
true,
false);
697 if (gnudump.size() > 0)
698 gnudump_edges(gnudump,
"heef_", highErrorEdgesToFeatures.begin(),
699 highErrorEdgesToFeatures.end(),
true,
true);
702 cerr <<
"Fixing the whole graph ";
703 for (std::map<int, HyperGraph::Vertex*>::iterator vit =
705 vit != optimizer.
vertices().end(); ++vit) {
710 cerr <<
" done" << endl;
712 typedef std::pair<HyperGraph::EdgeSet, HyperGraph::EdgeSet> EdgeSetPair;
713 typedef std::vector<EdgeSetPair> EdgeSetPairVector;
715 EdgeSetPairVector myEdgeStack;
717 cerr <<
"Collecting clusters...";
719 while (!highErrorEdges.empty()) {
720 HyperGraph::EdgeSet::iterator it = highErrorEdges.begin();
727 bool edgesSelected =
false;
732 if (selected.size() > 10) {
733 edgesSelected =
true;
734 cerr <<
" (" << selected.size() <<
", " << border.size() <<
")";
739 edgesToOptimize_selected.insert(selected.begin(), selected.end());
740 edgesToOptimize_border.insert(border.begin(), border.end());
741 edgesToOptimize.insert(selected.begin(), selected.end());
742 edgesToOptimize.insert(border.begin(), border.end());
744 cerr <<
" [" << selected.size() <<
", " << border.size() <<
"]";
748 for (HyperGraph::EdgeSet::iterator eit = selected.begin();
749 eit != selected.end(); ++eit) {
750 HyperGraph::EdgeSet::iterator removeMe = highErrorEdges.find(*eit);
751 if (removeMe != highErrorEdges.end()) {
752 highErrorEdges.erase(removeMe);
757 myEdgeStack.push_back(EdgeSetPair(selected, border));
760 cerr <<
" done" << endl;
762 cerr <<
"Found " << myEdgeStack.size() <<
" clusters in sum with "
763 << edgesToOptimize_selected.size() <<
" high error edges"
764 <<
" and " << edgesToOptimize_border.size() <<
" border edges."
767 if (gnudump.size() > 0)
768 gnudump_edges(gnudump,
"selected", edgesToOptimize_selected.begin(),
769 edgesToOptimize_selected.end(),
true,
false);
771 if (gnudump.size() > 0)
772 gnudump_edges(gnudump,
"border", edgesToOptimize_border.begin(),
773 edgesToOptimize_border.end(),
true,
false);
775 if (gnudump.size() > 0)
776 gnudump_edges(gnudump,
"reoptimizeme", edgesToOptimize.begin(),
777 edgesToOptimize.end(),
true,
false);
779 cerr <<
"Unfixing high error edges ";
780 for (EdgeSetPairVector::iterator it = myEdgeStack.begin();
781 it != myEdgeStack.end(); ++it) {
783 for (HyperGraph::EdgeSet::iterator eit = (*it).first.begin();
784 eit != (*it).first.end(); ++eit) {
789 vfrom->
fixed() =
false;
792 vto->
fixed() =
false;
795 cerr <<
"done" << endl;
798 cerr <<
"Initialize optimization of subgraphs .. ";
800 cerr <<
"done" << endl;
802 if (guessCostFunction == 0)
803 guessCostFunction =
new ActivePathCostFunction(&optimizer);
805 cerr <<
"Searching for init nodes and re-initialize subgraphs .. ";
806 for (EdgeSetPairVector::iterator it = myEdgeStack.begin();
807 it != myEdgeStack.end(); ++it) {
810 HyperGraph::EdgeSet::iterator eit = (*it).second.begin();
818 if (vfrom && vfrom->
fixed())
820 else if (vto && vto->
fixed())
827 optimizer.initializeActiveSubsetViaMeasurements(initNode,
831 cerr <<
" .. done" << endl;
833 if (gnudump.size() > 0)
835 optimizer.
edges().end(),
true,
false);
838 cerr <<
"Optimize subgraphs .. " << endl;
839 optimizer.optimizeLoop(maxIterations);
840 cerr <<
"done" << endl;
842 if (gnudump.size() > 0)
844 optimizer.
edges().end(),
true,
false);
847 if (highErrorEdgesToFeatures.size() > 0) {
851 cerr <<
"Fixing the whole graph ";
852 for (std::map<int, HyperGraph::Vertex*>::iterator vit =
854 vit != optimizer.
vertices().end(); ++vit) {
859 cerr <<
" done" << endl;
861 cerr <<
"Unfixing bad features";
862 for (HyperGraph::EdgeSet::iterator eit =
863 highErrorEdgesToFeatures.begin();
864 eit != highErrorEdgesToFeatures.end(); ++eit) {
869 edgesToBadFeatures.insert(v->
edges().begin(), v->
edges().end());
872 cerr <<
" considering " << edgesToBadFeatures.size()
873 <<
" edges .. done" << endl;
875 if (gnudump.size() > 0)
876 gnudump_edges(gnudump,
"featurereinit", edgesToBadFeatures.begin(),
877 edgesToBadFeatures.end(),
true,
true);
878 if (gnudump.size() > 0)
880 edgesToBadFeatures.begin(),
881 edgesToBadFeatures.end());
883 cerr <<
"Initialize optimization of bad features .. ";
885 cerr <<
"done" << endl;
888 cerr <<
"Optimize bad features .. " << endl;
889 optimizer.optimizeLoop(maxIterations / 2);
890 cerr <<
"done" << endl;
892 if (gnudump.size() > 0)
894 optimizer.
edges().end(),
true,
false);
898 for (std::map<int, HyperGraph::Vertex*>::iterator vit =
900 vit != optimizer.
vertices().end(); ++vit) {
907 cerr <<
"Initialize final optimization .. ";
909 cerr <<
"done" << endl;
910 cerr <<
"Optimize .. " << endl;
911 optimizer.optimizeLoop(maxIterations);
912 cerr <<
"done" << endl;
915 if (gnudump.size() > 0)
917 optimizer.
edges().end(),
true,
false);
918 if (gnudump.size() > 0)
920 optimizer.
edges().end());
921 if (gnudump.size() > 0)
923 optimizer.
edges().end(),
true,
true);
925 if (statsFile !=
"") {
926 cerr <<
"writing stats to file \"" << statsFile <<
"\"";
927 ofstream os(statsFile.c_str());
928 for (
int i = 0; i < maxIterations; i++) {
929 os << optimizer._statistics[i] << endl;
967 if (outputfilename.size() > 0) {
968 cerr <<
"saving " << outputfilename <<
" ... ";
969 optimizer.
save(outputfilename.c_str());
970 cerr <<
"done." << endl;