g2o
Loading...
Searching...
No Matches
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 (std::unique_ptr< Solver > solver)
 
virtual ~SolverSLAM2DLinear ()
 
virtual OptimizationAlgorithm::SolverResult solve (int iteration, bool online=false)
 
- Public Member Functions inherited from g2o::OptimizationAlgorithmGaussNewton
 OptimizationAlgorithmGaussNewton (std::unique_ptr< 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< MatrixX > &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
 
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
 
SparseOptimizeroptimizer ()
 
void setOptimizer (SparseOptimizer *optimizer)
 
const PropertyMapproperties () const
 return the properties of the solver
 
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
 
PropertyMap _properties
 

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 exactly 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 49 of file solver_slam2d_linear.h.

Constructor & Destructor Documentation

◆ SolverSLAM2DLinear()

g2o::SolverSLAM2DLinear::SolverSLAM2DLinear ( std::unique_ptr< 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 75 of file solver_slam2d_linear.cpp.

OptimizationAlgorithmGaussNewton(std::unique_ptr< Solver > solver)
Solver & solver()
return the underlying solver used to solve the linear system

◆ ~SolverSLAM2DLinear()

g2o::SolverSLAM2DLinear::~SolverSLAM2DLinear ( )
virtual

Definition at line 78 of file solver_slam2d_linear.cpp.

78{}

Member Function Documentation

◆ solve()

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 80 of file solver_slam2d_linear.cpp.

81 {
82 if (iteration == 0) {
83 bool status = solveOrientation();
84 if (!status) return OptimizationAlgorithm::Fail;
85 }
86
87 return OptimizationAlgorithmGaussNewton::solve(iteration, online);
88}
virtual SolverResult solve(int iteration, bool online=false)

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

◆ solveOrientation()

bool g2o::SolverSLAM2DLinear::solveOrientation ( )
protected

Definition at line 90 of file solver_slam2d_linear.cpp.

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

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

Referenced by solve().


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