g2o
Classes | Functions
bal_example.cpp File Reference
#include <Eigen/Core>
#include <Eigen/StdVector>
#include <Eigen/Geometry>
#include <iostream>
#include "g2o/stuff/command_args.h"
#include "g2o/core/batch_stats.h"
#include "g2o/core/sparse_optimizer.h"
#include "g2o/core/block_solver.h"
#include "g2o/core/solver.h"
#include "g2o/core/optimization_algorithm_levenberg.h"
#include "g2o/core/base_vertex.h"
#include "g2o/core/base_binary_edge.h"
#include "g2o/solvers/dense/linear_solver_dense.h"
#include "g2o/solvers/structure_only/structure_only_solver.h"
#include "g2o/solvers/pcg/linear_solver_pcg.h"
#include "EXTERNAL/ceres/autodiff.h"
Include dependency graph for bal_example.cpp:

Go to the source code of this file.

Classes

class  VertexCameraBAL
 camera vertex which stores the parameters for a pinhole camera More...
 
class  VertexPointBAL
 3D world feature More...
 
class  EdgeObservationBAL
 edge representing the observation of a world feature by a camera More...
 

Functions

int main (int argc, char **argv)
 

Function Documentation

int main ( int  argc,
char **  argv 
)

Definition at line 283 of file bal_example.cpp.

References g2o::OptimizableGraph::addEdge(), g2o::OptimizableGraph::addVertex(), g2o::SparseOptimizer::batchStatistics(), g2o::SparseOptimizer::initializeOptimization(), g2o::SparseOptimizer::optimize(), g2o::CommandArgs::param(), g2o::CommandArgs::paramLeftOver(), g2o::CommandArgs::parseArgs(), g2o::SparseOptimizer::setAlgorithm(), g2o::SparseOptimizer::setComputeBatchStatistics(), g2o::BaseVertex< D, T >::setEstimate(), g2o::OptimizableGraph::Vertex::setId(), g2o::BaseEdge< D, E >::setInformation(), g2o::OptimizableGraph::Vertex::setMarginalized(), g2o::BaseEdge< D, E >::setMeasurement(), g2o::SparseOptimizer::setVerbose(), and g2o::HyperGraph::Edge::setVertex().

284 {
285  int maxIterations;
286  bool verbose;
287  bool usePCG;
288  string outputFilename;
289  string inputFilename;
290  string statsFilename;
291  CommandArgs arg;
292  arg.param("i", maxIterations, 5, "perform n iterations");
293  arg.param("o", outputFilename, "", "write points into a vrml file");
294  arg.param("pcg", usePCG, false, "use PCG instead of the Cholesky");
295  arg.param("v", verbose, false, "verbose output of the optimization process");
296  arg.param("stats", statsFilename, "", "specify a file for the statistics");
297  arg.paramLeftOver("graph-input", inputFilename, "", "file which will be processed");
298 
299  arg.parseArgs(argc, argv);
300 
301  typedef g2o::BlockSolver< g2o::BlockSolverTraits<9, 3> > BalBlockSolver;
302 #ifdef G2O_HAVE_CHOLMOD
303  string choleskySolverName = "CHOLMOD";
305 #elif defined G2O_HAVE_CSPARSE
306  string choleskySolverName = "CSparse";
308 #else
309 #error neither CSparse nor CHOLMOD are available
310 #endif
311  typedef g2o::LinearSolverPCG<BalBlockSolver::PoseMatrixType> BalLinearSolverPCG;
312 
313  g2o::SparseOptimizer optimizer;
315  if (usePCG) {
316  cout << "Using PCG" << endl;
317  linearSolver = new BalLinearSolverPCG();
318  } else {
319  cout << "Using Cholesky: " << choleskySolverName << endl;
320  BalLinearSolver* cholesky = new BalLinearSolver();
321  cholesky->setBlockOrdering(true);
322  linearSolver = cholesky;
323  }
324  BalBlockSolver* solver_ptr = new BalBlockSolver(linearSolver);
326  //solver->setUserLambdaInit(1);
327  optimizer.setAlgorithm(solver);
328  if (statsFilename.size() > 0){
329  optimizer.setComputeBatchStatistics(true);
330  }
331 
332  vector<VertexPointBAL*> points;
333  vector<VertexCameraBAL*> cameras;
334 
335  // parse BAL dataset
336  cout << "Loading BAL dataset " << inputFilename << endl;
337  {
338  ifstream ifs(inputFilename.c_str());
339  int numCameras, numPoints, numObservations;
340  ifs >> numCameras >> numPoints >> numObservations;
341 
342  cerr << PVAR(numCameras) << " " << PVAR(numPoints) << " " << PVAR(numObservations) << endl;
343 
344  int id = 0;
345  cameras.reserve(numCameras);
346  for (int i = 0; i < numCameras; ++i, ++id) {
347  VertexCameraBAL* cam = new VertexCameraBAL;
348  cam->setId(id);
349  optimizer.addVertex(cam);
350  cameras.push_back(cam);
351  }
352 
353  points.reserve(numPoints);
354  for (int i = 0; i < numPoints; ++i, ++id) {
356  p->setId(id);
357  p->setMarginalized(true);
358  bool addedVertex = optimizer.addVertex(p);
359  if (! addedVertex) {
360  cerr << "failing adding vertex" << endl;
361  }
362  points.push_back(p);
363  }
364 
365  // read in the observation
366  for (int i = 0; i < numObservations; ++i) {
367  int camIndex, pointIndex;
368  double obsX, obsY;
369  ifs >> camIndex >> pointIndex >> obsX >> obsY;
370 
371  assert(camIndex >= 0 && (size_t)camIndex < cameras.size() && "Index out of bounds");
372  VertexCameraBAL* cam = cameras[camIndex];
373  assert(pointIndex >= 0 && (size_t)pointIndex < points.size() && "Index out of bounds");
374  VertexPointBAL* point = points[pointIndex];
375 
377  e->setVertex(0, cam);
378  e->setVertex(1, point);
379  e->setInformation(Eigen::Matrix2d::Identity());
380  e->setMeasurement(Eigen::Vector2d(obsX, obsY));
381  bool addedEdge = optimizer.addEdge(e);
382  if (! addedEdge) {
383  cerr << "error adding edge" << endl;
384  }
385  }
386 
387  // read in the camera params
388  Eigen::VectorXd cameraParameter(9);
389  for (int i = 0; i < numCameras; ++i) {
390  for (int j = 0; j < 9; ++j)
391  ifs >> cameraParameter(j);
392  VertexCameraBAL* cam = cameras[i];
393  cam->setEstimate(cameraParameter);
394  }
395 
396  // read in the points
397  Eigen::Vector3d p;
398  for (int i = 0; i < numPoints; ++i) {
399  ifs >> p(0) >> p(1) >> p(2);
400 
401  VertexPointBAL* point = points[i];
402  point->setEstimate(p);
403  }
404 
405  }
406  cout << "done." << endl;
407 
408  cout << "Initializing ... " << flush;
409  optimizer.initializeOptimization();
410  cout << "done." << endl;
411  optimizer.setVerbose(verbose);
412  cout << "Start to optimize" << endl;
413  optimizer.optimize(maxIterations);
414 
415  if (statsFilename!=""){
416  cerr << "writing stats to file \"" << statsFilename << "\" ... ";
417  ofstream fout(statsFilename.c_str());
418  const BatchStatisticsContainer& bsc = optimizer.batchStatistics();
419  for (size_t i=0; i<bsc.size(); i++)
420  fout << bsc[i] << endl;
421  cerr << "done." << endl;
422  }
423 
424  // dump the points
425  if (outputFilename.size() > 0) {
426  ofstream fout(outputFilename.c_str()); // loadable with meshlab
427  fout
428  << "#VRML V2.0 utf8\n"
429  << "Shape {\n"
430  << " appearance Appearance {\n"
431  << " material Material {\n"
432  << " diffuseColor " << 1 << " " << 0 << " " << 0 << "\n"
433  << " ambientIntensity 0.2\n"
434  << " emissiveColor 0.0 0.0 0.0\n"
435  << " specularColor 0.0 0.0 0.0\n"
436  << " shininess 0.2\n"
437  << " transparency 0.0\n"
438  << " }\n"
439  << " }\n"
440  << " geometry PointSet {\n"
441  << " coord Coordinate {\n"
442  << " point [\n";
443  for (vector<VertexPointBAL*>::const_iterator it = points.begin(); it != points.end(); ++it) {
444  fout << (*it)->estimate().transpose() << endl;
445  }
446  fout << " ]\n" << " }\n" << "}\n" << " }\n";
447  }
448 
449  return 0;
450 }
const BatchStatisticsContainer & batchStatistics() const
Command line parsing of argc and argv.
Definition: command_args.h:46
void setComputeBatchStatistics(bool computeBatchStatistics)
Implementation of the Levenberg Algorithm.
int optimize(int iterations, bool online=false)
virtual void setMeasurement(const Measurement &m)
Definition: base_edge.h:76
linear solver using PCG, pre-conditioner is block Jacobi
void setVertex(size_t i, Vertex *v)
Definition: hyper_graph.h:194
virtual void setId(int id)
sets the id of the node in the graph be sure that the graph keeps consistent after changing the id ...
bool parseArgs(int argc, char **argv, bool exitOnError=true)
basic solver for Ax = b
Definition: linear_solver.h:41
void setVerbose(bool verbose)
linear solver which uses CSparse
void paramLeftOver(const std::string &name, std::string &p, const std::string &defValue, const std::string &desc, bool optional=false)
void setAlgorithm(OptimizationAlgorithm *algorithm)
EIGEN_STRONG_INLINE void setInformation(const InformationType &information)
Definition: base_edge.h:69
void param(const std::string &name, bool &p, bool defValue, const std::string &desc)
basic solver for Ax = b which has to reimplemented for different linear algebra libraries ...
void setEstimate(const EstimateType &et)
set the estimate for the vertex also calls updateCache()
Definition: base_vertex.h:101
3D world feature
void setMarginalized(bool marginalized)
true => this node should be marginalized out during the optimization
edge representing the observation of a world feature by a camera
Implementation of a solver operating on the blocks of the Hessian.
Definition: block_solver.h:96
virtual bool initializeOptimization(HyperGraph::EdgeSet &eset)
virtual bool addEdge(HyperGraph::Edge *e)
virtual bool addVertex(HyperGraph::Vertex *v, Data *userData)
std::vector< G2OBatchStatistics > BatchStatisticsContainer
Definition: batch_stats.h:81
camera vertex which stores the parameters for a pinhole camera
Definition: bal_example.cpp:65