00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include <iostream>
00018 #include <string>
00019 #include <algorithm>
00020 #include <iomanip>
00021 #include <sys/time.h>
00022
00023 #include "hogman_minimal/graph_optimizer_hogman/graph_optimizer3d_chol.h"
00024 #include "hogman_minimal/graph_optimizer_hogman/graph_optimizer3d_hchol.h"
00025 #include "hogman_minimal/graph/loadEdges3d.h"
00026 #include "hogman_minimal/stuff/filesys_tools.h"
00027 #include "hogman_minimal/stuff/string_tools.h"
00028 #include "hogman_minimal/stuff/macros.h"
00029 #include "hogman_minimal/stuff/color_macros.h"
00030
00031 using namespace std;
00032 using namespace AISNavigation;
00033
00034 static const char * banner[]={
00035 "*******************************************************************",
00036 "* HOG-Man v 0.1 *",
00037 "* (c) Giorgio Grisetti, Rainer Kuemmerle, *",
00038 "* Cyrill Stachniss *",
00039 "*******************************************************************",
00040 "",
00041 "usage: hogman3d [options] <graph_file>",
00042 "",
00043 "options:",
00044 " -hogman | -chol selects the optimization strategy",
00045 " between",
00046 " HOG-Man (default)",
00047 " cholesky",
00048 " -i <int> sets the maximum number of iterations (default 10)",
00049 " -batch if toggled, the file is processed in offline mode",
00050 " -v enables the verbose mode of the optimizer",
00051 " -guiout dumps the output to be piped into graph_viewer",
00052 " -guess perform initial guess (batch mode)",
00053 " -o <filename> writes in <filename> the optimized graph",
00054 " -oc overwrite the covariances with the identity",
00055 " -h this help",
00056 0
00057 };
00058
00059 void printBanner(){
00060 const char** line=banner;
00061 while (*line){
00062 cerr<< *line<< endl;
00063 line++;
00064 }
00065 }
00066
00067 enum OptimizerType {
00068 OPT_CHOL, OPT_HCHOL
00069 };
00070
00071 static string optimizer2string(int optimizer)
00072 {
00073 switch (optimizer) {
00074 case OPT_CHOL:
00075 return "Cholesky";
00076 case OPT_HCHOL:
00077 return "Hierarchical Cholesky (HOG-Man)";
00078 default:
00079 return "Unknown Optimizer";
00080 }
00081 return "Unknown Optimizer";
00082 }
00083
00084 int main(int argc, char** argv)
00085 {
00086 if (argc<2){
00087 printBanner();
00088 return 0;
00089 }
00090
00091 bool visualize = false;
00092 bool overrideCovariances = false;
00093 int iterations = 10;
00094 bool verbose = false;
00095 bool incremental = true;
00096 bool guess = 0;
00097 int optType = OPT_CHOL;
00098 int updateGraphEachN = 1;
00099 int updateVisualizationEachN = 25;
00100 char* filename = 0;
00101 char* gnudump = 0;
00102 char* outfilename = 0;
00103 GraphOptimizer3D* optimizer = 0;
00104 int numLevels = 3;
00105 int nodeDistance = 2;
00106
00107
00108 for (int c = 1; c < argc; ++c){
00109 if (! strcmp(argv[c],"-chol")){
00110 optimizer = new CholOptimizer3D();
00111 optType = OPT_CHOL;
00112 } else if (! strcmp(argv[c],"-hchol")) {
00113 optimizer = new HCholOptimizer3D(numLevels, nodeDistance);
00114 optType = OPT_HCHOL;
00115 } else if (! strcmp(argv[c],"-v")){
00116 verbose=true;
00117 } else if (! strcmp(argv[c],"-batch")){
00118 incremental = false;
00119 } else if (! strcmp(argv[c],"-guiout")){
00120 visualize = true;
00121 } else if (! strcmp(argv[c],"-o")){
00122 c++;
00123 outfilename=argv[c];
00124 } else if (! strcmp(argv[c],"-gnudump")){
00125 c++;
00126 gnudump=argv[c];
00127 } else if (! strcmp(argv[c],"-i")){
00128 c++;
00129 iterations=atoi(argv[c]);
00130 } else if (! strcmp(argv[c],"-guess")){
00131 guess = true;
00132 } else if (! strcmp(argv[c],"-oc")){
00133 overrideCovariances = true;
00134 } else if (! strcmp(argv[c],"-h")) {
00135 printBanner();
00136 return 0;
00137 } else {
00138 filename=argv[c];
00139 }
00140 }
00141
00142 if (!optimizer) {
00143 optimizer = new HCholOptimizer3D(numLevels, nodeDistance);
00144 optType = OPT_HCHOL;
00145 }
00146
00147 ifstream is(filename);
00148 if (!is) {
00149 cerr << "Error opening " << filename << endl;
00150 return 1;
00151 }
00152
00153 cerr << "# Optimizer started, Parameter summary:" << endl;
00154 cerr << "# strategy= " << optimizer2string(optType) << endl;
00155 cerr << "# verbose= " << verbose << endl;
00156 cerr << "# iterations= " << iterations << endl;
00157 cerr << "# verbose= " << verbose << endl;
00158 cerr << "# outfile= " << ((outfilename)? outfilename : "not set") << endl;
00159 cerr << "# infile= " << ((filename)? filename : "not set") << endl;
00160 cerr << "# incemental= " << incremental << endl;
00161 cerr << "# initial guess= " << guess << endl;
00162
00163
00164 optimizer->verbose() = verbose;
00165 optimizer->visualizeToStdout() = visualize;
00166 optimizer->guessOnEdges() = incremental;
00167
00168 if (incremental) {
00169 optimizer->visualizeToStdout() = false;
00170 optimizer->verbose() = false;
00171
00172 cerr << "# Loading Edges ... ";
00173 LoadedEdgeSet3D loadedEdges;
00174 loadEdges3D(loadedEdges, is, overrideCovariances);
00175 cerr << "done." << endl;
00176
00177 struct timeval ts, te;
00178 double cumTime=0;
00179 bool addNextEdge=true;
00180 bool freshlyOptimized=false;
00181 int count=0;
00182 for (LoadedEdgeSet3D::const_iterator it = loadedEdges.begin(); it != loadedEdges.end(); ++it) {
00183 bool optimize=false;
00184
00185 if (addNextEdge && !optimizer->vertices().empty()){
00186 int maxInGraph = optimizer->vertices().rbegin()->first;
00187 int idMax = max(it->id1, it->id2);
00188 if (maxInGraph < idMax && ! freshlyOptimized){
00189 addNextEdge=false;
00190 optimize=true;
00191 count++;
00192 } else {
00193 addNextEdge=true;
00194 optimize=false;
00195 }
00196 }
00197
00198 PoseGraph3D::Vertex* v1 = optimizer->vertex(it->id1);
00199 PoseGraph3D::Vertex* v2 = optimizer->vertex(it->id2);
00200 if (! v1 && addNextEdge) {
00201
00202 v1 = optimizer->addVertex(it->id1, Transformation3(), Matrix6::eye(1.0));
00203 assert(v1);
00204 }
00205
00206 if (! v2 && addNextEdge) {
00207
00208 v2 = optimizer->addVertex(it->id2, Transformation3(), Matrix6::eye(1.0));
00209 assert(v2);
00210 }
00211
00212 if (addNextEdge){
00213
00214 optimizer->addEdge(v1, v2, it->mean, it->informationMatrix);
00215 }
00216
00217 freshlyOptimized=false;
00218 if (optimize){
00219
00220 if (!(count % updateGraphEachN)){
00221 gettimeofday(&ts, 0);
00222 int currentIt=optimizer->optimize(iterations, true);
00223 gettimeofday(&te,0);
00224 double dts=(te.tv_sec-ts.tv_sec)+1e-6*(te.tv_usec-ts.tv_usec);
00225 cumTime += dts;
00226
00227 if (verbose) {
00228 double chi2 = optimizer->chi2();
00229 cerr << "nodes= " << optimizer->vertices().size() << "\t edges= " << optimizer->edges().size() << "\t chi2= " << chi2
00230 << "\t time= " << dts << "\t iterations= " << currentIt << "\t cumTime= " << cumTime << endl;
00231 }
00232 }
00233
00234
00235 if (visualize && !(count % updateVisualizationEachN) ) {
00236 HCholOptimizer3D* opt=dynamic_cast<HCholOptimizer3D*>(optimizer);
00237 if (0 && opt) {
00238 opt=opt->level(opt->nLevels()-1);
00239 opt->visualizeToStream(cout);
00240 } else {
00241 optimizer->visualizeToStream(cout);
00242 }
00243 }
00244
00245 if (! verbose)
00246 cerr << ".";
00247 addNextEdge=true;
00248 freshlyOptimized=true;
00249 it--;
00250 count++;
00251 }
00252 }
00253
00254 if (visualize) {
00255 optimizer->visualizeToStream(cout);
00256 }
00257
00258 cerr << "**** Optimization Done ****" << endl;
00259 cerr << "TOTAL TIME= " << cumTime << " s." << endl;
00260 cerr << "# final chi=" << optimizer->chi2() << endl;
00261
00262 } else {
00263 optimizer->guessOnEdges() = guess;
00264
00265 struct timeval ts, te;
00266 optimizer->load(is, overrideCovariances);
00267 if (! optimizer->initialize(0)){
00268 cerr << "error in initialization" << endl;
00269 }
00270 cerr << "# initial chi=" << optimizer->chi2() << endl;
00271
00272 gettimeofday(&ts,0);
00273 optimizer->optimize(iterations, false);
00274 gettimeofday(&te,0);
00275 cerr << "**** Optimization Done ****" << endl;
00276 double dts=(te.tv_sec-ts.tv_sec)+1e-6*(te.tv_usec-ts.tv_usec);
00277 cerr << "TOTAL TIME= " << dts << " s." << endl;
00278 cerr << "# final chi=" << optimizer->chi2() << endl;
00279 }
00280
00281 if (outfilename) {
00282 cerr << "Saving Graph to " << outfilename << " ... ";
00283 ofstream fout(outfilename);
00284 optimizer->save(fout);
00285 fout.close();
00286 cerr << "done." << endl;
00287 }
00288
00289 if (gnudump) {
00290 cerr << "Saving Data to " << gnudump << " ... ";
00291 ofstream fout(gnudump);
00292 optimizer->saveGnuplot(fout);
00293 fout.close();
00294 cerr << "done." << endl;
00295 }
00296
00297
00298 delete optimizer;
00299
00300 return 0;
00301 }