g2o
Public Types | Public Member Functions | Protected Member Functions | Protected Attributes | List of all members
g2o::G2oSlamInterface Class Reference

#include <g2o_slam_interface.h>

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

Public Types

enum  SolveResult { SOLVED, SOLVED_BATCH, NOOP, ERROR }
 

Public Member Functions

 G2oSlamInterface (SparseOptimizerOnline *optimizer)
 
bool addNode (const std::string &tag, int id, int dimension, const std::vector< double > &values)
 
bool addEdge (const std::string &tag, int id, int dimension, int v1, int v2, const std::vector< double > &measurement, const std::vector< double > &information)
 
bool fixNode (const std::vector< int > &nodes)
 
bool queryState (const std::vector< int > &nodes)
 
bool solveState ()
 
SolveResult solve ()
 
int updatedGraphEachN () const
 
void setUpdateGraphEachN (int n)
 
int batchSolveEachN () const
 
void setBatchSolveEachN (int n)
 

Protected Member Functions

OptimizableGraph::VertexaddVertex (int dimension, int id)
 
bool printVertex (OptimizableGraph::Vertex *v)
 

Protected Attributes

SparseOptimizerOnline_optimizer
 
bool _firstOptimization
 
int _nodesAdded
 
int _incIterations
 
int _updateGraphEachN
 
int _batchEveryN
 
int _lastBatchStep
 
bool _initSolverDone
 
HyperGraph::VertexSet _verticesAdded
 
HyperGraph::EdgeSet _edgesAdded
 

Detailed Description

Definition at line 41 of file g2o_slam_interface.h.

Member Enumeration Documentation

Constructor & Destructor Documentation

g2o::G2oSlamInterface::G2oSlamInterface ( SparseOptimizerOnline optimizer)

Member Function Documentation

bool g2o::G2oSlamInterface::addEdge ( const std::string &  tag,
int  id,
int  dimension,
int  v1,
int  v2,
const std::vector< double > &  measurement,
const std::vector< double > &  information 
)
virtual

adding an edge to the SLAM engine.

Parameters
tagthe tag specifying the type of the vertex
idthe unique id of the edge.
dimensionthe dimension of the edge.
v1the unique id of the edge of the first vertex
v2the unique id of the edge of the second vertex
measurementthe measurement of the constraint
informationthe information matrix (inverse of the covariance) representing the uncertainty of the measurement (row-major upper triangular and diagonal)
Returns
true, if adding was successful

Implements SlamParser::AbstractSlamInterface.

Definition at line 133 of file g2o_slam_interface.cpp.

References __PRETTY_FUNCTION__, _edgesAdded, _nodesAdded, _optimizer, _verticesAdded, g2o::OptimizableGraph::addEdge(), addVertex(), g2o::JacobianWorkspace::allocate(), g2o::HyperGraph::edges(), g2o::internal::fromVectorET(), g2o::internal::fromVectorQT(), g2o::HyperGraph::Vertex::id(), g2o::OnlineEdgeSE3::initialEstimate(), g2o::OnlineEdgeSE2::initialEstimate(), g2o::EdgeSE3::initialEstimatePossible(), g2o::EdgeSE2::initialEstimatePossible(), g2o::jac_quat3_euler3(), g2o::OptimizableGraph::jacobianWorkspace(), g2o::internal::normalize(), g2o::BaseEdge< D, E >::setInformation(), g2o::EdgeSE3::setMeasurement(), g2o::EdgeSE2::setMeasurement(), g2o::OptimizableGraph::vertex(), and g2o::HyperGraph::Edge::vertices().

Referenced by main().

134 {
135  (void) tag;
136  (void) id;
137  size_t oldEdgesSize = _optimizer->edges().size();
138 
139  if (dimension == 3) {
140 
141  SE2 transf(measurement[0], measurement[1], measurement[2]);
142  Eigen::Matrix3d infMat;
143  int idx = 0;
144  for (int r = 0; r < 3; ++r)
145  for (int c = r; c < 3; ++c, ++idx) {
146  assert(idx < (int)information.size());
147  infMat(r,c) = infMat(c,r) = information[idx];
148  }
149  //cerr << PVAR(infMat) << endl;
150 
151  int doInit = 0;
154  if (! v1) {
155  OptimizableGraph::Vertex* v = v1 = addVertex(dimension, v1Id);
156  _verticesAdded.insert(v);
157  doInit = 1;
158  ++_nodesAdded;
159  }
160 
161  if (! v2) {
162  OptimizableGraph::Vertex* v = v2 = addVertex(dimension, v2Id);
163  _verticesAdded.insert(v);
164  doInit = 2;
165  ++_nodesAdded;
166  }
167 
168  if (_optimizer->edges().size() == 0) {
169  cerr << "FIRST EDGE ";
170  if (v1->id() < v2->id()) {
171  cerr << "fixing " << v1->id() << endl;
172  v1->setFixed(true);
173  }
174  else {
175  cerr << "fixing " << v2->id() << endl;
176  v2->setFixed(true);
177  }
178  }
179 
180  OnlineEdgeSE2* e = new OnlineEdgeSE2;
181  e->vertices()[0] = v1;
182  e->vertices()[1] = v2;
183  e->setMeasurement(transf);
184  e->setInformation(infMat);
185  _optimizer->addEdge(e);
186  _edgesAdded.insert(e);
187 
188  if (doInit) {
189  OptimizableGraph::Vertex* from = static_cast<OptimizableGraph::Vertex*>(e->vertices()[0]);
190  OptimizableGraph::Vertex* to = static_cast<OptimizableGraph::Vertex*>(e->vertices()[1]);
191  switch (doInit){
192  case 1: // initialize v1 from v2
193  {
194  HyperGraph::VertexSet toSet;
195  toSet.insert(to);
196  if (e->initialEstimatePossible(toSet, from) > 0.) {
197  e->initialEstimate(toSet, from);
198  }
199  break;
200  }
201  case 2:
202  {
203  HyperGraph::VertexSet fromSet;
204  fromSet.insert(from);
205  if (e->initialEstimatePossible(fromSet, to) > 0.) {
206  e->initialEstimate(fromSet, to);
207  }
208  break;
209  }
210  default: cerr << "doInit wrong value\n";
211  }
212  }
213 
214  }
215  else if (dimension == 6) {
216 
217  Eigen::Isometry3d transf;
218  Matrix<double, 6, 6> infMat;
219 
220  if (measurement.size() == 7) { // measurement is a Quaternion
221  Vector7d meas;
222  for (int i=0; i<7; ++i)
223  meas(i) = measurement[i];
224  // normalize the quaternion to recover numerical precision lost by storing as human readable text
225  Vector4d::MapType(meas.data()+3).normalize();
226  transf = internal::fromVectorQT(meas);
227 
228  for (int i = 0, idx = 0; i < infMat.rows(); ++i)
229  for (int j = i; j < infMat.cols(); ++j){
230  infMat(i,j) = information[idx++];
231  if (i != j)
232  infMat(j,i)=infMat(i,j);
233  }
234  } else { // measurement consists of Euler angles
235  Vector6d aux;
236  aux << measurement[0], measurement[1], measurement[2],measurement[3], measurement[4], measurement[5];
237  transf = internal::fromVectorET(aux);
238  Matrix<double, 6, 6> infMatEuler;
239  int idx = 0;
240  for (int r = 0; r < 6; ++r)
241  for (int c = r; c < 6; ++c, ++idx) {
242  assert(idx < (int)information.size());
243  infMatEuler(r,c) = infMatEuler(c,r) = information[idx];
244  }
245  // convert information matrix to our internal representation
246  Matrix<double, 6, 6> J;
247  SE3Quat transfAsSe3(transf.matrix().topLeftCorner<3,3>(), transf.translation());
248  jac_quat3_euler3(J, transfAsSe3);
249  infMat.noalias() = J.transpose() * infMatEuler * J;
250  //cerr << PVAR(transf.matrix()) << endl;
251  //cerr << PVAR(infMat) << endl;
252  }
253 
254  int doInit = 0;
257  if (! v1) {
258  OptimizableGraph::Vertex* v = v1 = addVertex(dimension, v1Id);
259  _verticesAdded.insert(v);
260  doInit = 1;
261  ++_nodesAdded;
262  }
263 
264  if (! v2) {
265  OptimizableGraph::Vertex* v = v2 = addVertex(dimension, v2Id);
266  _verticesAdded.insert(v);
267  doInit = 2;
268  ++_nodesAdded;
269  }
270 
271  if (_optimizer->edges().size() == 0) {
272  cerr << "FIRST EDGE ";
273  if (v1->id() < v2->id()) {
274  cerr << "fixing " << v1->id() << endl;
275  v1->setFixed(true);
276  }
277  else {
278  cerr << "fixing " << v2->id() << endl;
279  v2->setFixed(true);
280  }
281  }
282 
283  OnlineEdgeSE3* e = new OnlineEdgeSE3;
284  e->vertices()[0] = v1;
285  e->vertices()[1] = v2;
286  e->setMeasurement(transf);
287  e->setInformation(infMat);
288  _optimizer->addEdge(e);
289  _edgesAdded.insert(e);
290 
291  if (doInit) {
292  OptimizableGraph::Vertex* from = static_cast<OptimizableGraph::Vertex*>(e->vertices()[0]);
293  OptimizableGraph::Vertex* to = static_cast<OptimizableGraph::Vertex*>(e->vertices()[1]);
294  switch (doInit){
295  case 1: // initialize v1 from v2
296  {
297  HyperGraph::VertexSet toSet;
298  toSet.insert(to);
299  if (e->initialEstimatePossible(toSet, from) > 0.) {
300  e->initialEstimate(toSet, from);
301  }
302  break;
303  }
304  case 2:
305  {
306  HyperGraph::VertexSet fromSet;
307  fromSet.insert(from);
308  if (e->initialEstimatePossible(fromSet, to) > 0.) {
309  e->initialEstimate(fromSet, to);
310  }
311  break;
312  }
313  default: cerr << "doInit wrong value\n";
314  }
315  }
316 
317  }
318  else {
319  cerr << __PRETTY_FUNCTION__ << " not implemented for this dimension" << endl;
320  return false;
321  }
322 
323  if (oldEdgesSize == 0) {
325  }
326 
327  return true;
328 }
#define __PRETTY_FUNCTION__
Definition: macros.h:89
Isometry3D fromVectorQT(const Vector7d &v)
HyperGraph::VertexSet _verticesAdded
std::set< Vertex * > VertexSet
Definition: hyper_graph.h:136
Eigen::Matrix< double, 7, 1 > Vector7d
Definition: sim3.h:35
Vertex * vertex(int id)
returns the vertex number id appropriately casted
JacobianWorkspace & jacobianWorkspace()
the workspace for storing the Jacobians of the graph
class G2O_CORE_API Vertex
const EdgeSet & edges() const
Definition: hyper_graph.h:230
Eigen::Quaterniond & normalize(Eigen::Quaterniond &q)
SparseOptimizerOnline * _optimizer
static void jac_quat3_euler3(Eigen::Matrix< double, 6, 6, Eigen::ColMajor > &J, const Isometry3D &t)
Eigen::Matrix< double, 6, 1 > Vector6d
OptimizableGraph::Vertex * addVertex(int dimension, int id)
virtual bool addEdge(HyperGraph::Edge *e)
HyperGraph::EdgeSet _edgesAdded
Isometry3D fromVectorET(const Vector6d &v)
bool g2o::G2oSlamInterface::addNode ( const std::string &  tag,
int  id,
int  dimension,
const std::vector< double > &  values 
)
virtual

adding a node to the SLAM engine.

Parameters
tagthe tag specifying the type of the vertex
idthe unique id of the node.
dimensionthe dimension of the node.
valuesthe pose of the node, may be empty (i.e., the engine should initialize the node itself)
Returns
true, if adding was successful

Implements SlamParser::AbstractSlamInterface.

Definition at line 117 of file g2o_slam_interface.cpp.

References _batchEveryN, _initSolverDone, _optimizer, and g2o::SparseOptimizerOnline::initSolver().

Referenced by main().

118 {
119  // allocating the desired solver + testing whether the solver is okay
120  if (! _initSolverDone) {
121  _initSolverDone = true;
122  _optimizer->initSolver(dimension, _batchEveryN);
123  }
124 
125  // we add the node when we are asked to add the according edge
126  (void) tag;
127  (void) id;
128  (void) dimension;
129  (void) values;
130  return true;
131 }
Protocol The SLAM executable accepts such as solving the and retrieving or vertices in the explicitly state the reprensentation poses are represented by poses by VERTEX_XYZRPY In the Quaternions and other representations could be but note that it is up to the SLAM algorithm to choose the internal representation of the angles The keyword is followed by a unique vertex ID and an optional initialization of the values
Definition: protocol.txt:7
SparseOptimizerOnline * _optimizer
virtual bool initSolver(int dimension, int batchEveryN)
OptimizableGraph::Vertex * g2o::G2oSlamInterface::addVertex ( int  dimension,
int  id 
)
protected

Definition at line 369 of file g2o_slam_interface.cpp.

References _optimizer, g2o::OptimizableGraph::addVertex(), and g2o::OptimizableGraph::Vertex::setId().

Referenced by addEdge().

370 {
371  if (dimension == 3) {
372  OnlineVertexSE2* v = new OnlineVertexSE2;
373  v->setId(id); // estimate will be set later when the edge is added
374  _optimizer->addVertex(v);
375  return v;
376  }
377  else if (dimension == 6) {
378  OnlineVertexSE3* v = new OnlineVertexSE3;
379  v->setId(id); // estimate will be set later when the edge is added
380  _optimizer->addVertex(v);
381  return v;
382  }
383  else {
384  return 0;
385  }
386 }
SparseOptimizerOnline * _optimizer
virtual bool addVertex(HyperGraph::Vertex *v, Data *userData)
int g2o::G2oSlamInterface::batchSolveEachN ( ) const
inline

Definition at line 64 of file g2o_slam_interface.h.

bool g2o::G2oSlamInterface::fixNode ( const std::vector< int > &  nodes)
virtual

set some nodes to a fixed position

Parameters
nodesthe list of vertex IDs to fix
Returns
true, if successful

Implements SlamParser::AbstractSlamInterface.

Definition at line 330 of file g2o_slam_interface.cpp.

References _optimizer, g2o::OptimizableGraph::Vertex::setFixed(), and g2o::OptimizableGraph::vertex().

331 {
332  for (size_t i = 0; i < nodes.size(); ++i) {
334  if (v)
335  v->setFixed(true);
336  }
337  return true;
338 }
Vertex * vertex(int id)
returns the vertex number id appropriately casted
class G2O_CORE_API Vertex
SparseOptimizerOnline * _optimizer
void setFixed(bool fixed)
true => this node should be considered fixed during the optimization
bool g2o::G2oSlamInterface::printVertex ( OptimizableGraph::Vertex v)
protected

Definition at line 388 of file g2o_slam_interface.cpp.

References g2o::OptimizableGraph::Vertex::dimension(), g2o::HyperGraph::Vertex::id(), modp_dtoa(), modp_itoa10(), g2o::SE2::rotation(), g2o::internal::toEuler(), g2o::SE2::translation(), g2o::OnlineVertexSE3::updatedEstimate, and g2o::OnlineVertexSE2::updatedEstimate.

Referenced by queryState().

389 {
390  static char buffer[10000]; // that should be more than enough
391  int vdim = v->dimension();
392  if (vdim == 3) {
393  char* s = buffer;
394  OnlineVertexSE2* v2 = static_cast<OnlineVertexSE2*>(v);
395  memcpy(s, "VERTEX_XYT ", 11);
396  s += 11;
397  s += modp_itoa10(v->id(), s);
398  *s++ = ' ';
399  s += modp_dtoa(v2->updatedEstimate.translation().x(), s, 6);
400  *s++ = ' ';
401  s += modp_dtoa(v2->updatedEstimate.translation().y(), s, 6);
402  *s++ = ' ';
403  s += modp_dtoa(v2->updatedEstimate.rotation().angle(), s, 6);
404  *s++ = '\n';
405  cout.write(buffer, s - buffer);
406  return true;
407  }
408  else if (vdim == 6) {
409  char* s = buffer;
410  OnlineVertexSE3* v3 = static_cast<OnlineVertexSE3*>(v);
411  Vector3d eulerAngles = internal::toEuler(v3->updatedEstimate.matrix().topLeftCorner<3,3>());
412  const double& roll = eulerAngles(0);
413  const double& pitch = eulerAngles(1);
414  const double& yaw = eulerAngles(2);
415  memcpy(s, "VERTEX_XYZRPY ", 14);
416  s += 14;
417  s += modp_itoa10(v->id(), s);
418  *s++ = ' ';
419  s += modp_dtoa(v3->updatedEstimate.translation().x(), s, 6);
420  *s++ = ' ';
421  s += modp_dtoa(v3->updatedEstimate.translation().y(), s, 6);
422  *s++ = ' ';
423  s += modp_dtoa(v3->updatedEstimate.translation().z(), s, 6);
424  *s++ = ' ';
425  s += modp_dtoa(roll, s, 6);
426  *s++ = ' ';
427  s += modp_dtoa(pitch, s, 6);
428  *s++ = ' ';
429  s += modp_dtoa(yaw, s, 6);
430  *s++ = '\n';
431  cout.write(buffer, s - buffer);
432  return true;
433  }
434  return false;
435 }
Vector3D toEuler(const Matrix3D &R)
int modp_itoa10(int32_t value, char *str)
Definition: fast_output.h:166
int modp_dtoa(double value, char *str, int prec)
Definition: fast_output.h:55
bool g2o::G2oSlamInterface::queryState ( const std::vector< int > &  nodes)
virtual

Ask the SLAM engine to print the current estimate of the variables

Parameters
nodesthe list of vertex IDs to print, if empty print all variables
Returns
true, if successful

Implements SlamParser::AbstractSlamInterface.

Definition at line 340 of file g2o_slam_interface.cpp.

References _optimizer, printVertex(), g2o::OptimizableGraph::vertex(), and g2o::HyperGraph::vertices().

341 {
342  //return true;
343  cout << "BEGIN" << endl;
344 #if 1
345  if (nodes.size() == 0) {
346  for (OptimizableGraph::VertexIDMap::const_iterator it = _optimizer->vertices().begin(); it != _optimizer->vertices().end(); ++it) {
347  OptimizableGraph::Vertex* v = static_cast<OptimizableGraph::Vertex*>(it->second);
348  printVertex(v);
349  }
350  } else {
351  for (size_t i = 0; i < nodes.size(); ++i) {
353  if (v)
354  printVertex(v);
355  }
356  }
357 #endif
358  cout << "END" << endl << flush;
359 
360  return true;
361 }
const VertexIDMap & vertices() const
Definition: hyper_graph.h:225
Vertex * vertex(int id)
returns the vertex number id appropriately casted
bool printVertex(OptimizableGraph::Vertex *v)
class G2O_CORE_API Vertex
SparseOptimizerOnline * _optimizer
void g2o::G2oSlamInterface::setBatchSolveEachN ( int  n)

Definition at line 478 of file g2o_slam_interface.cpp.

References _batchEveryN.

Referenced by main().

479 {
480  _batchEveryN = n;
481 }
void g2o::G2oSlamInterface::setUpdateGraphEachN ( int  n)

Definition at line 437 of file g2o_slam_interface.cpp.

References _updateGraphEachN.

Referenced by main().

438 {
439  _updateGraphEachN = n;
440 }
G2oSlamInterface::SolveResult g2o::G2oSlamInterface::solve ( )

Definition at line 442 of file g2o_slam_interface.cpp.

References _batchEveryN, _edgesAdded, _firstOptimization, _incIterations, _lastBatchStep, _nodesAdded, _optimizer, _updateGraphEachN, _verticesAdded, g2o::SparseOptimizerOnline::batchStep, ERROR, g2o::SparseOptimizer::initializeOptimization(), NOOP, g2o::SparseOptimizerOnline::optimize(), SOLVED, SOLVED_BATCH, g2o::SparseOptimizerOnline::updateInitialization(), and g2o::HyperGraph::vertices().

Referenced by main(), and solveState().

443 {
445 
446  // decide on batch step or normal step
447  _optimizer->batchStep = false;
448  if ((int)_optimizer->vertices().size() - _lastBatchStep >= _batchEveryN) {
449  _lastBatchStep = _optimizer->vertices().size();
450  _optimizer->batchStep = true;
451  }
452 
453  if (_firstOptimization) {
455  cerr << "initialization failed" << endl;
456  return ERROR;
457  }
458  } else {
460  cerr << "updating initialization failed" << endl;
461  return ERROR;
462  }
463  }
464 
465  int currentIt = _optimizer->optimize(_incIterations, !_firstOptimization); (void) currentIt;
466  _firstOptimization = false;
467  _nodesAdded = 0;
468  _verticesAdded.clear();
469  _edgesAdded.clear();
470  if (_optimizer->batchStep)
471  return SOLVED_BATCH;
472  return SOLVED;
473  }
474 
475  return NOOP;
476 }
HyperGraph::VertexSet _verticesAdded
const VertexIDMap & vertices() const
Definition: hyper_graph.h:225
int optimize(int iterations, bool online=false)
SparseOptimizerOnline * _optimizer
virtual bool initializeOptimization(HyperGraph::EdgeSet &eset)
virtual bool updateInitialization(HyperGraph::VertexSet &vset, HyperGraph::EdgeSet &eset)
HyperGraph::EdgeSet _edgesAdded
bool g2o::G2oSlamInterface::solveState ( )
virtual

ask the engine to solve

Returns
true, if successful

Implements SlamParser::AbstractSlamInterface.

Definition at line 363 of file g2o_slam_interface.cpp.

References ERROR, and solve().

364 {
365  SolveResult state = solve();
366  return state != ERROR;
367 }
int g2o::G2oSlamInterface::updatedGraphEachN ( ) const
inline

Definition at line 61 of file g2o_slam_interface.h.

Member Data Documentation

int g2o::G2oSlamInterface::_batchEveryN
protected

Definition at line 73 of file g2o_slam_interface.h.

Referenced by addNode(), setBatchSolveEachN(), and solve().

HyperGraph::EdgeSet g2o::G2oSlamInterface::_edgesAdded
protected

Definition at line 78 of file g2o_slam_interface.h.

Referenced by addEdge(), and solve().

bool g2o::G2oSlamInterface::_firstOptimization
protected

Definition at line 69 of file g2o_slam_interface.h.

Referenced by solve().

int g2o::G2oSlamInterface::_incIterations
protected

Definition at line 71 of file g2o_slam_interface.h.

Referenced by solve().

bool g2o::G2oSlamInterface::_initSolverDone
protected

Definition at line 75 of file g2o_slam_interface.h.

Referenced by addNode().

int g2o::G2oSlamInterface::_lastBatchStep
protected

Definition at line 74 of file g2o_slam_interface.h.

Referenced by solve().

int g2o::G2oSlamInterface::_nodesAdded
protected

Definition at line 70 of file g2o_slam_interface.h.

Referenced by addEdge(), and solve().

SparseOptimizerOnline* g2o::G2oSlamInterface::_optimizer
protected

Definition at line 68 of file g2o_slam_interface.h.

Referenced by addEdge(), addNode(), addVertex(), fixNode(), queryState(), and solve().

int g2o::G2oSlamInterface::_updateGraphEachN
protected

Definition at line 72 of file g2o_slam_interface.h.

Referenced by setUpdateGraphEachN(), and solve().

HyperGraph::VertexSet g2o::G2oSlamInterface::_verticesAdded
protected

Definition at line 77 of file g2o_slam_interface.h.

Referenced by addEdge(), and solve().


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