g2o
Public Member Functions | Protected Member Functions | List of all members
g2o::SolverSLAM2DLinear Class Reference

Implementation of a linear approximation for 2D pose graph SLAM. More...

#include <solver_slam2d_linear.h>

Inheritance diagram for g2o::SolverSLAM2DLinear:
Inheritance graph
[legend]
Collaboration diagram for g2o::SolverSLAM2DLinear:
Collaboration graph
[legend]

Public Member Functions

 SolverSLAM2DLinear (Solver *solver)
 
virtual ~SolverSLAM2DLinear ()
 
virtual OptimizationAlgorithm::SolverResult solve (int iteration, bool online=false)
 
- Public Member Functions inherited from g2o::OptimizationAlgorithmGaussNewton
 OptimizationAlgorithmGaussNewton (Solver *solver)
 
virtual ~OptimizationAlgorithmGaussNewton ()
 
virtual void printVerbose (std::ostream &os) const
 
- Public Member Functions inherited from g2o::OptimizationAlgorithmWithHessian
 OptimizationAlgorithmWithHessian (Solver *solver)
 
virtual ~OptimizationAlgorithmWithHessian ()
 
virtual bool init (bool online=false)
 
virtual bool computeMarginals (SparseBlockMatrix< MatrixXD > &spinv, const std::vector< std::pair< int, int > > &blockIndices)
 
virtual bool buildLinearStructure ()
 
virtual void updateLinearSystem ()
 
virtual bool updateStructure (const std::vector< HyperGraph::Vertex * > &vset, const HyperGraph::EdgeSet &edges)
 
Solversolver ()
 return the underlying solver used to solve the linear system More...
 
virtual void setWriteDebug (bool writeDebug)
 
virtual bool writeDebug () const
 
- Public Member Functions inherited from g2o::OptimizationAlgorithm
 OptimizationAlgorithm ()
 
virtual ~OptimizationAlgorithm ()
 
const SparseOptimizeroptimizer () const
 return the optimizer operating on More...
 
SparseOptimizeroptimizer ()
 
void setOptimizer (SparseOptimizer *optimizer)
 
const PropertyMapproperties () const
 return the properties of the solver More...
 
bool updatePropertiesFromString (const std::string &propString)
 
void printProperties (std::ostream &os) const
 

Protected Member Functions

bool solveOrientation ()
 

Additional Inherited Members

- Protected Attributes inherited from g2o::OptimizationAlgorithmWithHessian
Solver_solver
 
Property< bool > * _writeDebug
 
- Protected Attributes inherited from g2o::OptimizationAlgorithm
SparseOptimizer_optimizer
 the optimizer the solver is working on More...
 
PropertyMap _properties
 the properties of your solver, use this to store the parameters of your solver More...
 

Detailed Description

Implementation of a linear approximation for 2D pose graph SLAM.

Needs to operate on the full graph, whereas the nodes connected by odometry are 0 -> 1 -> 2 -> ... Furthermore excactly one node should be the fixed vertex. Within the first iteration the orientation of the nodes is computed. In the subsequent iterations full non-linear GN is carried out. The linear approximation is correct, if the covariance of the constraints is a diagonal matrix.

More or less the solver is an implementation of the approach described by Carlone et al, RSS'11.

Definition at line 52 of file solver_slam2d_linear.h.

Constructor & Destructor Documentation

g2o::SolverSLAM2DLinear::SolverSLAM2DLinear ( Solver solver)
explicit

Construct a Solver for solving 2D pose graphs. Within the first iteration the rotations are solved and afterwards standard non-linear Gauss Newton is carried out.

Definition at line 73 of file solver_slam2d_linear.cpp.

73  :
75  {
76  }
Solver * solver()
return the underlying solver used to solve the linear system
g2o::SolverSLAM2DLinear::~SolverSLAM2DLinear ( )
virtual

Definition at line 78 of file solver_slam2d_linear.cpp.

79  {
80  }

Member Function Documentation

OptimizationAlgorithm::SolverResult g2o::SolverSLAM2DLinear::solve ( int  iteration,
bool  online = false 
)
virtual

Solve one iteration. The SparseOptimizer running on-top will call this for the given number of iterations.

Parameters
iterationindicates the current iteration

Reimplemented from g2o::OptimizationAlgorithmGaussNewton.

Definition at line 82 of file solver_slam2d_linear.cpp.

References g2o::OptimizationAlgorithmGaussNewton::solve(), and solveOrientation().

83  {
84  if (iteration == 0) {
85  bool status = solveOrientation();
86  if (! status)
87  return OptimizationAlgorithm::Fail;
88  }
89 
90  return OptimizationAlgorithmGaussNewton::solve(iteration, online);
91  }
virtual SolverResult solve(int iteration, bool online=false)
bool g2o::SolverSLAM2DLinear::solveOrientation ( )
protected

Definition at line 93 of file solver_slam2d_linear.cpp.

References __PRETTY_FUNCTION__, g2o::OptimizationAlgorithm::_optimizer, g2o::SparseOptimizer::activeEdges(), g2o::HyperDijkstra::adjacencyMap(), g2o::HyperDijkstra::computeTree(), g2o::OptimizableGraph::Vertex::fixed(), g2o::OptimizableGraph::Vertex::hessianIndex(), g2o::SparseOptimizer::indexMapping(), g2o::BaseEdge< D, E >::information(), g2o::LinearSolverCSparse< MatrixType >::init(), g2o::BaseEdge< D, E >::measurement(), g2o::normalize_theta(), g2o::SE2::rotation(), g2o::BaseVertex< D, T >::setEstimate(), g2o::HyperDijkstra::shortestPaths(), g2o::OptimizableGraph::vertex(), g2o::HyperGraph::Edge::vertices(), g2o::HyperGraph::vertices(), and g2o::HyperDijkstra::visitAdjacencyMap().

Referenced by solve().

94  {
95  assert(_optimizer->indexMapping().size() + 1 == _optimizer->vertices().size() && "Needs to operate on full graph");
96  assert(_optimizer->vertex(0)->fixed() && "Graph is not fixed by vertex 0");
97  VectorXD b, x; // will be used for theta and x/y update
98  b.setZero(_optimizer->indexMapping().size());
99  x.setZero(_optimizer->indexMapping().size());
100 
101  typedef Eigen::Matrix<double, 1, 1, Eigen::ColMajor> ScalarMatrix;
102 
103  ScopedArray<int> blockIndeces(new int[_optimizer->indexMapping().size()]);
104  for (size_t i = 0; i < _optimizer->indexMapping().size(); ++i)
105  blockIndeces[i] = i+1;
106 
107  SparseBlockMatrix<ScalarMatrix> H(blockIndeces.get(), blockIndeces.get(), _optimizer->indexMapping().size(), _optimizer->indexMapping().size());
108 
109  // building the structure, diagonal for each active vertex
110  for (size_t i = 0; i < _optimizer->indexMapping().size(); ++i) {
112  int poseIdx = v->hessianIndex();
113  ScalarMatrix* m = H.block(poseIdx, poseIdx, true);
114  m->setZero();
115  }
116 
117  HyperGraph::VertexSet fixedSet;
118 
119  // off diagonal for each edge
120  for (SparseOptimizer::EdgeContainer::const_iterator it = _optimizer->activeEdges().begin(); it != _optimizer->activeEdges().end(); ++it) {
121 # ifndef NDEBUG
122  EdgeSE2* e = dynamic_cast<EdgeSE2*>(*it);
123  assert(e && "Active edges contain non-odometry edge"); //
124 # else
125  EdgeSE2* e = static_cast<EdgeSE2*>(*it);
126 # endif
127  OptimizableGraph::Vertex* from = static_cast<OptimizableGraph::Vertex*>(e->vertices()[0]);
128  OptimizableGraph::Vertex* to = static_cast<OptimizableGraph::Vertex*>(e->vertices()[1]);
129 
130  int ind1 = from->hessianIndex();
131  int ind2 = to->hessianIndex();
132  if (ind1 == -1 || ind2 == -1) {
133  if (ind1 == -1) fixedSet.insert(from); // collect the fixed vertices
134  if (ind2 == -1) fixedSet.insert(to);
135  continue;
136  }
137 
138  bool transposedBlock = ind1 > ind2;
139  if (transposedBlock){ // make sure, we allocate the upper triangle block
140  std::swap(ind1, ind2);
141  }
142 
143  ScalarMatrix* m = H.block(ind1, ind2, true);
144  m->setZero();
145  }
146 
147  // walk along the Minimal Spanning Tree to compute the guess for the robot orientation
148  assert(fixedSet.size() == 1);
149  VertexSE2* root = static_cast<VertexSE2*>(*fixedSet.begin());
150  VectorXD thetaGuess;
151  thetaGuess.setZero(_optimizer->indexMapping().size());
152  UniformCostFunction uniformCost;
153  HyperDijkstra hyperDijkstra(_optimizer);
154  hyperDijkstra.shortestPaths(root, &uniformCost);
155 
156  HyperDijkstra::computeTree(hyperDijkstra.adjacencyMap());
157  ThetaTreeAction thetaTreeAction(thetaGuess.data());
158  HyperDijkstra::visitAdjacencyMap(hyperDijkstra.adjacencyMap(), &thetaTreeAction);
159 
160  // construct for the orientation
161  for (SparseOptimizer::EdgeContainer::const_iterator it = _optimizer->activeEdges().begin(); it != _optimizer->activeEdges().end(); ++it) {
162  EdgeSE2* e = static_cast<EdgeSE2*>(*it);
163  VertexSE2* from = static_cast<VertexSE2*>(e->vertices()[0]);
164  VertexSE2* to = static_cast<VertexSE2*>(e->vertices()[1]);
165 
166  double omega = e->information()(2,2);
167 
168  double fromThetaGuess = from->hessianIndex() < 0 ? 0. : thetaGuess[from->hessianIndex()];
169  double toThetaGuess = to->hessianIndex() < 0 ? 0. : thetaGuess[to->hessianIndex()];
170  double error = normalize_theta(-e->measurement().rotation().angle() + toThetaGuess - fromThetaGuess);
171 
172  bool fromNotFixed = !(from->fixed());
173  bool toNotFixed = !(to->fixed());
174 
175  if (fromNotFixed || toNotFixed) {
176  double omega_r = - omega * error;
177  if (fromNotFixed) {
178  b(from->hessianIndex()) -= omega_r;
179  (*H.block(from->hessianIndex(), from->hessianIndex()))(0,0) += omega;
180  if (toNotFixed) {
181  if (from->hessianIndex() > to->hessianIndex())
182  (*H.block(to->hessianIndex(), from->hessianIndex()))(0,0) -= omega;
183  else
184  (*H.block(from->hessianIndex(), to->hessianIndex()))(0,0) -= omega;
185  }
186  }
187  if (toNotFixed ) {
188  b(to->hessianIndex()) += omega_r;
189  (*H.block(to->hessianIndex(), to->hessianIndex()))(0,0) += omega;
190  }
191  }
192  }
193 
194  // solve orientation
195  typedef LinearSolverCSparse<ScalarMatrix> SystemSolver;
196  SystemSolver linearSystemSolver;
197  linearSystemSolver.init();
198  bool ok = linearSystemSolver.solve(H, x.data(), b.data());
199  if (!ok) {
200  cerr << __PRETTY_FUNCTION__ << "Failure while solving linear system" << endl;
201  return false;
202  }
203 
204  // update the orientation of the 2D poses and set translation to 0, GN shall solve that
205  root->setToOrigin();
206  for (size_t i = 0; i < _optimizer->indexMapping().size(); ++i) {
207  VertexSE2* v = static_cast<VertexSE2*>(_optimizer->indexMapping()[i]);
208  int poseIdx = v->hessianIndex();
209  SE2 poseUpdate(0, 0, normalize_theta(thetaGuess(poseIdx) + x(poseIdx)));
210  v->setEstimate(poseUpdate);
211  }
212 
213  return true;
214  }
#define __PRETTY_FUNCTION__
Definition: macros.h:89
static void computeTree(AdjacencyMap &amap)
std::set< Vertex * > VertexSet
Definition: hyper_graph.h:136
const EdgeContainer & activeEdges() const
the edges active in the current optimization
const VertexIDMap & vertices() const
Definition: hyper_graph.h:225
Vertex * vertex(int id)
returns the vertex number id appropriately casted
static void visitAdjacencyMap(AdjacencyMap &amap, TreeAction *action, bool useDistance=false)
class G2O_CORE_API Vertex
SparseOptimizer * _optimizer
the optimizer the solver is working on
const VertexContainer & indexMapping() const
the index mapping of the vertices
double normalize_theta(double theta)
Definition: misc.h:94
Eigen::Matrix< double, Eigen::Dynamic, 1, Eigen::ColMajor > VectorXD
Definition: eigen_types.h:48
bool fixed() const
true => this node is fixed during the optimization

The documentation for this class was generated from the following files: