g2o
Classes | Functions
circle_fit.cpp File Reference
#include <Eigen/Core>
#include <Eigen/StdVector>
#include <Eigen/Geometry>
#include <iostream>
#include "g2o/stuff/sampler.h"
#include "g2o/stuff/command_args.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/optimization_algorithm_gauss_newton.h"
#include "g2o/core/base_vertex.h"
#include "g2o/core/base_unary_edge.h"
#include "g2o/solvers/csparse/linear_solver_csparse.h"
Include dependency graph for circle_fit.cpp:

Go to the source code of this file.

Classes

class  VertexCircle
 a circle located at x,y with radius r More...
 
class  EdgePointOnCircle
 measurement for a point on the circle More...
 

Functions

double errorOfSolution (int numPoints, Eigen::Vector2d *points, const Eigen::Vector3d &circle)
 
int main (int argc, char **argv)
 

Function Documentation

double errorOfSolution ( int  numPoints,
Eigen::Vector2d *  points,
const Eigen::Vector3d &  circle 
)

Definition at line 45 of file circle_fit.cpp.

Referenced by main().

46 {
47  Eigen::Vector2d center = circle.head<2>();
48  double radius = circle(2);
49  double error = 0.;
50  for (int i = 0; i < numPoints; ++i) {
51  double d = (points[i] - center).norm() - radius;
52  error += d*d;
53  }
54  return error;
55 }
int main ( int  argc,
char **  argv 
)

Definition at line 128 of file circle_fit.cpp.

References g2o::OptimizableGraph::addEdge(), g2o::OptimizableGraph::addVertex(), errorOfSolution(), g2o::BaseVertex< D, T >::estimate(), g2o::Sampler::gaussRand(), g2o::SparseOptimizer::initializeOptimization(), M_PI, g2o::SparseOptimizer::optimize(), g2o::CommandArgs::param(), g2o::CommandArgs::parseArgs(), g2o::Sampler::seedRand(), g2o::SparseOptimizer::setAlgorithm(), g2o::BaseVertex< D, T >::setEstimate(), g2o::OptimizableGraph::Vertex::setId(), g2o::BaseEdge< D, E >::setInformation(), g2o::BaseEdge< D, E >::setMeasurement(), g2o::SparseOptimizer::setVerbose(), g2o::HyperGraph::Edge::setVertex(), and g2o::Sampler::uniformRand().

129 {
130  int numPoints;
131  int maxIterations;
132  bool verbose;
133  std::vector<int> gaugeList;
134  g2o::CommandArgs arg;
135  arg.param("numPoints", numPoints, 100, "number of points sampled from the circle");
136  arg.param("i", maxIterations, 10, "perform n iterations");
137  arg.param("v", verbose, false, "verbose output of the optimization process");
138 
139  arg.parseArgs(argc, argv);
140 
141  // generate random data
142  Eigen::Vector2d center(4.0, 2.0);
143  double radius = 2.0;
144  Eigen::Vector2d* points = new Eigen::Vector2d[numPoints];
145 
147  for (int i = 0; i < numPoints; ++i) {
148  double r = g2o::Sampler::gaussRand(radius, 0.05);
149  double angle = g2o::Sampler::uniformRand(0.0, 2.0 * M_PI);
150  points[i].x() = center.x() + r * cos(angle);
151  points[i].y() = center.y() + r * sin(angle);
152  }
153 
154  // some handy typedefs
157 
158  // setup the solver
159  g2o::SparseOptimizer optimizer;
160  optimizer.setVerbose(false);
161  MyLinearSolver* linearSolver = new MyLinearSolver();
162  MyBlockSolver* solver_ptr = new MyBlockSolver(linearSolver);
164  //g2o::OptimizationAlgorithmGaussNewton* solver = new g2o::OptimizationAlgorithmGaussNewton(solver_ptr);
165  optimizer.setAlgorithm(solver);
166 
167  // build the optimization problem given the points
168  // 1. add the circle vertex
169  VertexCircle* circle = new VertexCircle();
170  circle->setId(0);
171  circle->setEstimate(Eigen::Vector3d(3.0, 3.0, 3.0)); // some initial value for the circle
172  optimizer.addVertex(circle);
173  // 2. add the points we measured
174  for (int i = 0; i < numPoints; ++i) {
176  e->setInformation(Eigen::Matrix<double, 1, 1>::Identity());
177  e->setVertex(0, circle);
178  e->setMeasurement(points[i]);
179  optimizer.addEdge(e);
180  }
181 
182  // perform the optimization
183  optimizer.initializeOptimization();
184  optimizer.setVerbose(verbose);
185  optimizer.optimize(maxIterations);
186 
187  if (verbose)
188  cout << endl;
189 
190  // print out the result
191  cout << "Iterative least squares solution" << endl;
192  cout << "center of the circle " << circle->estimate().head<2>().transpose() << endl;
193  cout << "radius of the cirlce " << circle->estimate()(2) << endl;
194  cout << "error " << errorOfSolution(numPoints, points, circle->estimate()) << endl;
195  cout << endl;
196 
197  // solve by linear least squares
198  // Let (a, b) be the center of the circle and r the radius of the circle.
199  // For a point (x, y) on the circle we have:
200  // (x - a)^2 + (y - b)^2 = r^2
201  // This leads to
202  // (-2x -2y 1)^T * (a b c) = -x^2 - y^2 (1)
203  // where c = a^2 + b^2 - r^2.
204  // Since we have a bunch of points, we accumulate Eqn (1) in a matrix and
205  // compute the normal equation to obtain a solution for (a b c).
206  // Afterwards the radius r is recovered.
207  Eigen::MatrixXd A(numPoints, 3);
208  Eigen::VectorXd b(numPoints);
209  for (int i = 0; i < numPoints; ++i) {
210  A(i, 0) = -2*points[i].x();
211  A(i, 1) = -2*points[i].y();
212  A(i, 2) = 1;
213  b(i) = -pow(points[i].x(), 2) - pow(points[i].y(), 2);
214  }
215  Eigen::Vector3d solution = (A.transpose()*A).ldlt().solve(A.transpose() * b);
216  // calculate the radius of the circle given the solution so far
217  solution(2) = sqrt(pow(solution(0), 2) + pow(solution(1), 2) - solution(2));
218  cout << "Linear least squares solution" << endl;
219  cout << "center of the circle " << solution.head<2>().transpose() << endl;
220  cout << "radius of the cirlce " << solution(2) << endl;
221  cout << "error " << errorOfSolution(numPoints, points, solution) << endl;
222 
223  // clean up
224  delete[] points;
225 
226  return 0;
227 }
Command line parsing of argc and argv.
Definition: command_args.h:46
static double gaussRand(double mean, double sigma)
Definition: sampler.h:86
Implementation of the Levenberg Algorithm.
static void seedRand()
Definition: sampler.h:107
int optimize(int iterations, bool online=false)
measurement for a point on the circle
Definition: circle_fit.cpp:99
virtual void setMeasurement(const Measurement &m)
Definition: base_edge.h:76
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 ...
static double uniformRand(double lowerBndr, double upperBndr)
Definition: sampler.h:100
bool parseArgs(int argc, char **argv, bool exitOnError=true)
a circle located at x,y with radius r
Definition: circle_fit.cpp:60
void setVerbose(bool verbose)
linear solver which uses CSparse
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)
void setEstimate(const EstimateType &et)
set the estimate for the vertex also calls updateCache()
Definition: base_vertex.h:101
const EstimateType & estimate() const
return the current estimate of the vertex
Definition: base_vertex.h:99
Implementation of a solver operating on the blocks of the Hessian.
Definition: block_solver.h:96
virtual bool initializeOptimization(HyperGraph::EdgeSet &eset)
double errorOfSolution(int numPoints, Eigen::Vector2d *points, const Eigen::Vector3d &circle)
Definition: circle_fit.cpp:45
virtual bool addEdge(HyperGraph::Edge *e)
virtual bool addVertex(HyperGraph::Vertex *v, Data *userData)
#define M_PI
Definition: misc.h:34