g2o
Loading...
Searching...
No Matches
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 <Eigen/Core>
22#include <iostream>
23
28using 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 && \
34 ((QGLVIEWER_VERSION & 0x00ff00) >> 8) >= 6)
35#define qglv_real qreal
36#else
37#define qglv_real float
38#endif
39
40// Again, some API changes in QGLViewer which produce annoying text in the
41// console if the old API is used.
42#if (((QGLVIEWER_VERSION & 0xff0000) >> 16) >= 2 && \
43 ((QGLVIEWER_VERSION & 0x00ff00) >> 8) >= 5)
44#define QGLVIEWER_DEPRECATED_MOUSEBINDING
45#endif
46
47namespace g2o {
48
49namespace {
50
54class StandardCamera : public qglviewer::Camera {
55 public:
56 StandardCamera() : _standard(true){};
57
58 qglv_real zNear() const {
59 if (_standard)
60 return 0.001f;
61 else
62 return Camera::zNear();
63 }
64
65 qglv_real zFar() const {
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
79void drawSE2(const VertexSE2* v) {
80 static const double len = 0.2;
81 static Eigen::Vector2d p1(0.75 * len, 0.);
82 static Eigen::Vector2d p2(-0.25 * len, 0.5 * len);
83 static Eigen::Vector2d p3(-0.25 * len, -0.5 * len);
84
85 const SE2& pose = v->estimate();
86
87 Eigen::Vector2d aux = pose * p1;
88 glVertex3f(aux[0], aux[1], 0.f);
89 aux = pose * p2;
90 glVertex3f(aux[0], aux[1], 0.f);
91 aux = pose * p3;
92 glVertex3f(aux[0], aux[1], 0.f);
93}
94
95template <typename Derived>
96void drawCov(const Eigen::Vector2d& p, const Eigen::MatrixBase<Derived>& cov) {
97 const double scalingFactor = 1.;
98
99 glPushMatrix();
100 glTranslatef(p.x(), p.y(), 0.f);
101
102 const typename Derived::Scalar& a = cov(0, 0);
103 const typename Derived::Scalar& b = cov(0, 1);
104 const typename Derived::Scalar& d = cov(1, 1);
105
106 /* get eigen-values */
107 double D = a * d - b * b; // determinant of the matrix
108 double T = a + d; // Trace of the matrix
109 double h = sqrt(0.25 * (T * T) - D);
110 double lambda1 =
111 0.5 * T + h; // solving characteristic polynom using p-q-formula
112 double lambda2 = 0.5 * T - h;
113
114 double theta = 0.5 * atan2(2.0 * b, a - d);
115 double majorAxis = 3.0 * sqrt(lambda1);
116 double minorAxis = 3.0 * sqrt(lambda2);
117
118 glRotatef(RAD2DEG(theta), 0.f, 0.f, 1.f);
119 glScalef(majorAxis * scalingFactor, minorAxis * scalingFactor, 1.f);
120 glColor4f(1.0f, 1.f, 0.f, 0.4f);
121 opengl::drawDisk(1.f);
122 glColor4f(0.f, 0.f, 0.f, 1.0f);
124 glPopMatrix();
125}
126
127} // end anonymous namespace
128
129Slam2DViewer::Slam2DViewer(QWidget* parent, const QGLWidget* shareWidget)
130 : QGLViewer(parent, shareWidget), graph(0), drawCovariance(false) {}
131
133
135 if (!graph) return;
136
137 // drawing the graph
138 glColor4f(0.00f, 0.67f, 1.00f, 1.f);
139 glBegin(GL_TRIANGLES);
140 for (SparseOptimizer::VertexIDMap::iterator it = graph->vertices().begin();
141 it != graph->vertices().end(); ++it) {
142 VertexSE2* v = dynamic_cast<VertexSE2*>(it->second);
143 if (v) {
144 drawSE2(v);
145 }
146 }
147 glEnd();
148
149 glColor4f(1.00f, 0.67f, 0.00f, 1.f);
150 glPointSize(2.f);
151 glBegin(GL_POINTS);
152 for (SparseOptimizer::VertexIDMap::iterator it = graph->vertices().begin();
153 it != graph->vertices().end(); ++it) {
154 VertexPointXY* v = dynamic_cast<VertexPointXY*>(it->second);
155 if (v) {
156 glVertex3f(v->estimate()(0), v->estimate()(1), 0.f);
157 }
158 }
159 glEnd();
160 glPointSize(1.f);
161
162 if (drawCovariance) {
163 for (const auto& vertex_index : graph->vertices()) {
164 VertexSE2* v = dynamic_cast<VertexSE2*>(vertex_index.second);
165 if (!v || v->fixed()) continue;
166 const g2o::MatrixX* covariance =
168 if (!covariance) continue;
169 drawCov(v->estimate().translation(), *covariance);
170 }
171 }
172}
173
175 QGLViewer::init();
176
177 // some default settings i like
178 glEnable(GL_LINE_SMOOTH);
179 glEnable(GL_BLEND);
180 glEnable(GL_DEPTH_TEST);
181 glShadeModel(GL_SMOOTH);
182 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
183
184 setAxisIsDrawn();
185
186 // don't save state
187 setStateFileName(QString());
188
189 // mouse bindings
190#ifdef QGLVIEWER_DEPRECATED_MOUSEBINDING
191 setMouseBinding(Qt::NoModifier, Qt::RightButton, CAMERA, ZOOM);
192 setMouseBinding(Qt::NoModifier, Qt::MiddleButton, CAMERA, TRANSLATE);
193#else
194 setMouseBinding(Qt::RightButton, CAMERA, ZOOM);
195 setMouseBinding(Qt::MidButton, CAMERA, TRANSLATE);
196#endif
197
198 // keyboard shortcuts
199 setShortcut(CAMERA_MODE, 0);
200 setShortcut(EXIT_VIEWER, 0);
201 // setShortcut(SAVE_SCREENSHOT, 0);
202
203 // replace camera
204 qglviewer::Camera* oldcam = camera();
205 qglviewer::Camera* cam = new StandardCamera();
206 setCamera(cam);
207 cam->setPosition(qglviewer::Vec(0., 0., 75.));
208 cam->setUpVector(qglviewer::Vec(0., 1., 0.));
209 cam->lookAt(qglviewer::Vec(0., 0., 0.));
210 delete oldcam;
211}
212
213} // namespace g2o
const EstimateType & estimate() const
return the current estimate of the vertex
const VertexIDMap & vertices() const
bool fixed() const
true => this node is fixed during the optimization
const Vector2 & translation() const
translational component
Definition se2.h:57
Slam2DViewer(QWidget *parent=NULL, const QGLWidget *shareWidget=0)
SparseOptimizer * graph
g2o::SparseBlockMatrix< g2o::MatrixX > covariances
virtual void draw()
SparseMatrixBlock * block(int r, int c, bool alloc=false)
2D pose Vertex, (x,y,theta)
Definition vertex_se2.h:41
bool _standard
#define qglv_real
#define RAD2DEG(x)
Definition macros.h:35
void drawDisk(GLfloat radius)
void drawCircle(GLfloat radius, int segments)
MatrixN< Eigen::Dynamic > MatrixX
Definition eigen_types.h:74
Definition jet.h:876