g2o
slam2d_viewer.cpp
Go to the documentation of this file.
1 // g2o - General Graph Optimization
2 // Copyright (C) 2011 R. Kuemmerle, G. Grisetti, W. Burgard
3 //
4 // This file is part of g2o.
5 //
6 // g2o is free software: you can redistribute it and/or modify
7 // it under the terms of the GNU General Public License as published by
8 // the Free Software Foundation, either version 3 of the License, or
9 // (at your option) any later version.
10 //
11 // g2o is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
15 //
16 // You should have received a copy of the GNU General Public License
17 // along with g2o. If not, see <http://www.gnu.org/licenses/>.
18 
19 #include "slam2d_viewer.h"
20 
21 #include "draw_helpers.h"
25 
26 #include <Eigen/Core>
27 #include <iostream>
28 using namespace std;
29 
30 // some macro helpers for identifying the version number of QGLViewer
31 // QGLViewer changed some parts of its API in version 2.6.
32 // The following preprocessor hack accounts for this. THIS SUCKS!!!
33 #if (((QGLVIEWER_VERSION & 0xff0000) >> 16) >= 2 && ((QGLVIEWER_VERSION & 0x00ff00) >> 8) >= 6)
34 #define qglv_real qreal
35 #else
36 #define qglv_real float
37 #endif
38 
39 // Again, some API changes in QGLViewer which produce annoying text in the console
40 // if the old API is used.
41 #if (((QGLVIEWER_VERSION & 0xff0000) >> 16) >= 2 && ((QGLVIEWER_VERSION & 0x00ff00) >> 8) >= 5)
42 #define QGLVIEWER_DEPRECATED_MOUSEBINDING
43 #endif
44 
45 namespace g2o {
46 
47 namespace {
48 
52  class StandardCamera : public qglviewer::Camera
53  {
54  public:
55  StandardCamera() : _standard(true) {};
56 
57  qglv_real zNear() const {
58  if (_standard)
59  return 0.001f;
60  else
61  return Camera::zNear();
62  }
63 
64  qglv_real zFar() const
65  {
66  if (_standard)
67  return 1000.0f;
68  else
69  return Camera::zFar();
70  }
71 
72  const bool& standard() const {return _standard;}
73  bool& standard() {return _standard;}
74 
75  private:
76  bool _standard;
77  };
78 
79  void drawSE2(const VertexSE2* v)
80  {
81  static const double len = 0.2;
82  static Eigen::Vector2d p1( 0.75 * len, 0.);
83  static Eigen::Vector2d p2(-0.25 * len, 0.5 * len);
84  static Eigen::Vector2d p3(-0.25 * len, -0.5 * len);
85 
86  const SE2& pose = v->estimate();
87 
88  Eigen::Vector2d aux = pose * p1;
89  glVertex3f(aux[0], aux[1], 0.f);
90  aux = pose * p2;
91  glVertex3f(aux[0], aux[1], 0.f);
92  aux = pose * p3;
93  glVertex3f(aux[0], aux[1], 0.f);
94  }
95 
96  template <typename Derived>
97  void drawCov(const Eigen::Vector2d& p, const Eigen::MatrixBase<Derived>& cov)
98  {
99  const double scalingFactor = 1.;
100 
101  glPushMatrix();
102  glTranslatef(p.x(), p.y(), 0.f);
103 
104  const typename Derived::Scalar& a = cov(0, 0);
105  const typename Derived::Scalar& b = cov(0, 1);
106  const typename Derived::Scalar& d = cov(1, 1);
107 
108  /* get eigen-values */
109  double D = a*d - b*b; // determinant of the matrix
110  double T = a+d; // Trace of the matrix
111  double h = sqrt(0.25*(T*T) - D);
112  double lambda1 = 0.5*T + h; // solving characteristic polynom using p-q-formula
113  double lambda2 = 0.5*T - h;
114 
115  double theta = 0.5 * atan2(2.0 * b, a - d);
116  double majorAxis = 3.0 * sqrt(lambda1);
117  double minorAxis = 3.0 * sqrt(lambda2);
118 
119 
120  glRotatef(RAD2DEG(theta), 0.f, 0.f, 1.f);
121  glScalef(majorAxis * scalingFactor, minorAxis * scalingFactor, 1.f);
122  glColor4f(1.0f, 1.f, 0.f, 0.4f);
123  drawDisk(1.f);
124  glColor4f(0.f, 0.f, 0.f, 1.0f);
125  drawCircle(1.f);
126  glPopMatrix();
127  }
128 
129 } // end anonymous namespace
130 
131 Slam2DViewer::Slam2DViewer(QWidget* parent, const QGLWidget* shareWidget, Qt::WFlags flags) :
132  QGLViewer(parent, shareWidget, flags),
133  graph(0), drawCovariance(false)
134 {
135 }
136 
138 {
139 }
140 
142 {
143  if (! graph)
144  return;
145 
146  // drawing the graph
147  glColor4f(0.00f, 0.67f, 1.00f, 1.f);
148  glBegin(GL_TRIANGLES);
149  for (SparseOptimizer::VertexIDMap::iterator it = graph->vertices().begin(); it != graph->vertices().end(); ++it) {
150  VertexSE2* v = dynamic_cast<VertexSE2*>(it->second);
151  if (v) {
152  drawSE2(v);
153  }
154  }
155  glEnd();
156 
157  glColor4f(1.00f, 0.67f, 0.00f, 1.f);
158  glPointSize(2.f);
159  glBegin(GL_POINTS);
160  for (SparseOptimizer::VertexIDMap::iterator it = graph->vertices().begin(); it != graph->vertices().end(); ++it) {
161  VertexPointXY* v = dynamic_cast<VertexPointXY*>(it->second);
162  if (v) {
163  glVertex3f(v->estimate()(0), v->estimate()(1), 0.f);
164  }
165  }
166  glEnd();
167  glPointSize(1.f);
168 
169  if (drawCovariance) {
170  for (SparseOptimizer::VertexIDMap::iterator it = graph->vertices().begin(); it != graph->vertices().end(); ++it) {
171  VertexSE2* v = dynamic_cast<VertexSE2*>(it->second);
172  if (v) {
173  // TODO
174  //drawCov(v->estimate().translation(), v->uncertainty());
175  }
176  }
177  }
178 }
179 
181 {
182  QGLViewer::init();
183 
184  // some default settings i like
185  glEnable(GL_LINE_SMOOTH);
186  glEnable(GL_BLEND);
187  glEnable(GL_DEPTH_TEST);
188  glShadeModel(GL_SMOOTH);
189  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
190 
191  setAxisIsDrawn();
192 
193  // don't save state
194  setStateFileName(QString::null);
195 
196  // mouse bindings
197 #ifdef QGLVIEWER_DEPRECATED_MOUSEBINDING
198  setMouseBinding(Qt::NoModifier, Qt::RightButton, CAMERA, ZOOM);
199  setMouseBinding(Qt::NoModifier, Qt::MidButton, CAMERA, TRANSLATE);
200 #else
201  setMouseBinding(Qt::RightButton, CAMERA, ZOOM);
202  setMouseBinding(Qt::MidButton, CAMERA, TRANSLATE);
203 #endif
204 
205  // keyboard shortcuts
206  setShortcut(CAMERA_MODE, 0);
207  setShortcut(EXIT_VIEWER, 0);
208  //setShortcut(SAVE_SCREENSHOT, 0);
209 
210  // replace camera
211  qglviewer::Camera* oldcam = camera();
212  qglviewer::Camera* cam = new StandardCamera();
213  setCamera(cam);
214  cam->setPosition(qglviewer::Vec(0., 0., 75.));
215  cam->setUpVector(qglviewer::Vec(0., 1., 0.));
216  cam->lookAt(qglviewer::Vec(0., 0., 0.));
217  delete oldcam;
218 }
219 
220 } // end namespace
SparseOptimizer * graph
Definition: slam2d_viewer.h:37
void drawDisk(GLfloat radius)
2D pose Vertex, (x,y,theta)
Definition: vertex_se2.h:41
void drawCircle(GLfloat radius, int segments)
const VertexIDMap & vertices() const
Definition: hyper_graph.h:225
virtual void draw()
#define qglv_real
const EstimateType & estimate() const
return the current estimate of the vertex
Definition: base_vertex.h:99
#define RAD2DEG(x)
Definition: macros.h:35
Protocol The SLAM executable accepts such as solving the and retrieving or vertices in the graph
Definition: protocol.txt:7
bool _standard