OcTreeDrawer.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of OctoMap - An Efficient Probabilistic 3D Mapping
3  * Framework Based on Octrees
4  * http://octomap.github.io
5  *
6  * Copyright (c) 2009-2014, K.M. Wurm and A. Hornung, University of Freiburg
7  * All rights reserved. License for the viewer octovis: GNU GPL v2
8  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
9  *
10  *
11  * This program is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation; either version 2 of the License, or
14  * (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful, but
17  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
18  * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19  * for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program. If not, see http://www.gnu.org/licenses/.
23  */
24 
25 #include <octovis/OcTreeDrawer.h>
26 #undef GL_GLEXT_VERSION // Previously defined by glu
27 #include <qglviewer.h>
28 
29 #define OTD_RAD2DEG 57.2957795
30 
31 namespace octomap {
32 
34  m_occupiedThresSize(0), m_freeThresSize(0),
35  m_occupiedSize(0), m_freeSize(0), m_selectionSize(0),
36  octree_grid_vertex_size(0), m_alphaOccupied(0.8), map_id(0)
37  {
39  m_drawOccupied = true;
40  m_drawOcTreeGrid = false;
41  m_drawFree = false;
42  m_drawSelection = true;
43  m_displayAxes = false;
44  m_update = true;
45  m_alternativeDrawing = false;
46 
47  m_occupiedArray = NULL;
48  m_freeArray = NULL;
49  m_occupiedThresArray = NULL;
50  m_freeThresArray = NULL;
51  m_occupiedColorArray = NULL;
53  m_selectionArray = NULL;
54 
55  // origin and movement
56  initial_origin = octomap::pose6d(0,0,0,0,0,0);
58  }
59 
61  clear();
62  }
63 
64  void OcTreeDrawer::draw() const {
65  static int gl_list_index = -1;
66  if(m_alternativeDrawing && gl_list_index < 0){
67  gl_list_index = glGenLists(1);
68  m_update = true;
69  }
70  if(!m_alternativeDrawing && gl_list_index != -1){//Free video card memory
71  //std::cerr << "Freeing VRAM\n";
72  glDeleteLists(gl_list_index,1);
73  gl_list_index = -1;
74  }
76  {
78  std::cout << "Preparing batch rendering, please wait ...\n";
79  glNewList(gl_list_index, GL_COMPILE_AND_EXECUTE);
80  }
81 
82  // push current status
83  glPushMatrix();
84  // octomap::pose6d relative_transform = origin * initial_origin.inv();
85 
86  octomap::pose6d relative_transform = origin;// * initial_origin;
87 
88  // apply relative transform
89  const octomath::Quaternion& q = relative_transform.rot();
90  glTranslatef(relative_transform.x(), relative_transform.y(), relative_transform.z());
91 
92  // convert quaternion to angle/axis notation
93  float scale = sqrt(q.x() * q.x() + q.y() * q.y() + q.z() * q.z());
94  if (scale) {
95  float axis_x = q.x() / scale;
96  float axis_y = q.y() / scale;
97  float axis_z = q.z() / scale;
98  float angle = acos(q.u()) * 2.0f * OTD_RAD2DEG; // opengl expects DEG
99  glRotatef(angle, axis_x, axis_y, axis_z);
100  }
101 
102  glEnableClientState(GL_VERTEX_ARRAY);
103 
104  if (m_drawSelection) // Drawing voxels in descending alpha-channel magnitude avoids (most) artifacts
105  drawSelection();
106  if (m_drawOccupied)
108  if (m_drawFree)
109  drawFreeVoxels();
110  if (m_drawOcTreeGrid)
111  drawOctreeGrid();
112 
113  if (m_displayAxes) {
114  drawAxes();
115  }
116 
117  glDisableClientState(GL_VERTEX_ARRAY);
118 
119  // reset previous status
120  glPopMatrix();
122  glEndList();
123  std::cout << "Finished preparation of batch rendering.\n";
124  }
125  m_update = false;
126  }
127  else
128  {
129  glCallList(gl_list_index);
130  }
131 
132  }
133 
134  void OcTreeDrawer::setAlphaOccupied(double alpha){
135  m_update = true;
136  m_alphaOccupied = alpha;
137  }
138 
139 
140  void OcTreeDrawer::setOcTree(const AbstractOcTree& in_tree, const pose6d& in_origin, int map_id_) {
141 
142  const OcTree& octree = (const OcTree&) in_tree;
143  this->map_id = map_id_;
144 
145  // save origin used during cube generation
146  this->initial_origin = octomap::pose6d(octomap::point3d(0,0,0), in_origin.rot());
147 
148  // origin is in global coords
149  this->origin = in_origin;
150 
151  // maximum size to prevent crashes on large maps: (should be checked in a better way than a constant)
152  bool showAll = (octree.size() < 5 * 1e6);
153  bool uses_origin = ( (origin.rot().x() != 0.) && (origin.rot().y() != 0.)
154  && (origin.rot().z() != 0.) && (origin.rot().u() != 1.) );
155 
156  // walk the tree one to find the number of nodes in each category
157  // (this is used to set up the OpenGL arrays)
158  // TODO: this step may be left out, if we maintained the GLArrays in std::vectors instead...
159  unsigned int cnt_occupied(0), cnt_occupied_thres(0), cnt_free(0), cnt_free_thres(0);
160  for(OcTree::tree_iterator it = octree.begin_tree(this->m_max_tree_depth),
161  end=octree.end_tree(); it!= end; ++it) {
162  if (it.isLeaf()) {
163  if (octree.isNodeOccupied(*it)){ // occupied voxels
164  if (octree.isNodeAtThreshold(*it)) ++cnt_occupied_thres;
165  else ++cnt_occupied;
166  }
167  else if (showAll) { // freespace voxels
168  if (octree.isNodeAtThreshold(*it)) ++cnt_free_thres;
169  else ++cnt_free;
170  }
171  }
172  }
173  // setup GL arrays for cube quads and cube colors
176  initGLArrays(cnt_free , m_freeSize , &m_freeArray, NULL);
177  initGLArrays(cnt_free_thres , m_freeThresSize , &m_freeThresArray, NULL);
178 
179  double minX, minY, minZ, maxX, maxY, maxZ;
180  octree.getMetricMin(minX, minY, minZ);
181  octree.getMetricMax(maxX, maxY, maxZ);
182 
183  // set min/max Z for color height map
184  m_zMin = minZ;
185  m_zMax = maxZ;
186 
187  std::vector<octomath::Vector3> cube_template;
188  initCubeTemplate(origin, cube_template);
189 
190  unsigned int idx_occupied(0), idx_occupied_thres(0), idx_free(0), idx_free_thres(0);
191  unsigned int color_idx_occupied(0), color_idx_occupied_thres(0);
192 
193  m_grid_voxels.clear();
194  OcTreeVolume voxel; // current voxel, possibly transformed
195  for(OcTree::tree_iterator it = octree.begin_tree(this->m_max_tree_depth),
196  end=octree.end_tree(); it!= end; ++it) {
197 
198  if (it.isLeaf()) { // voxels for leaf nodes
199  if (uses_origin)
200  voxel = OcTreeVolume(origin.rot().rotate(it.getCoordinate()), it.getSize());
201  else
202  voxel = OcTreeVolume(it.getCoordinate(), it.getSize());
203 
204  if (octree.isNodeOccupied(*it)){ // occupied voxels
205  if (octree.isNodeAtThreshold(*it)) {
206  idx_occupied_thres = generateCube(voxel, cube_template, idx_occupied_thres, &m_occupiedThresArray);
207  color_idx_occupied_thres = setCubeColorHeightmap(voxel, color_idx_occupied_thres, &m_occupiedThresColorArray);
208  }
209  else {
210  idx_occupied = generateCube(voxel, cube_template, idx_occupied, &m_occupiedArray);
211  color_idx_occupied = setCubeColorHeightmap(voxel, color_idx_occupied, &m_occupiedColorArray);
212  }
213  }
214  else if (showAll) { // freespace voxels
215  if (octree.isNodeAtThreshold(*it)) {
216  idx_free_thres = generateCube(voxel, cube_template, idx_free_thres, &m_freeThresArray);
217  }
218  else {
219  idx_free = generateCube(voxel, cube_template, idx_free, &m_freeArray);
220  }
221  }
222  }
223 
224  else { // inner node voxels (for grid structure only)
225  if (showAll) {
226  if (uses_origin)
227  voxel = OcTreeVolume(origin.rot().rotate(it.getCoordinate()), it.getSize());
228  else
229  voxel = OcTreeVolume(it.getCoordinate(), it.getSize());
230  m_grid_voxels.push_back(voxel);
231  }
232  }
233  } // end for all voxels
234 
236 
237  if(m_drawOcTreeGrid)
239  }
240 
241  void OcTreeDrawer::setOcTreeSelection(const std::list<octomap::OcTreeVolume>& selectedVoxels){
242  m_update = true;
243 
244  // init selectedVoxels GLarray
245  initGLArrays(selectedVoxels.size(), m_selectionSize, &m_selectionArray, NULL);
246 
247  generateCubes(selectedVoxels, &m_selectionArray, m_selectionSize, this->origin);
248  }
249 
251  m_update = true;
253  }
254 
255  void OcTreeDrawer::initGLArrays(const unsigned int& num_cubes,
256  unsigned int& glArraySize,
257  GLfloat*** glArray, GLfloat** glColorArray) {
258 
259  clearCubes(glArray, glArraySize, glColorArray);
260 
261  // store size of GL arrays for drawing
262  glArraySize = num_cubes * 4 * 3;
263 
264  // allocate cube arrays, 6 quads per cube
265  *glArray = new GLfloat* [6];
266  for (unsigned i = 0; i<6; ++i){
267  (*glArray)[i] = new GLfloat[glArraySize];
268  }
269  // setup quad color array, if given
270  if (glColorArray != NULL)
271  *glColorArray = new GLfloat[glArraySize * 4 *4];
272  }
273 
275  std::vector<octomath::Vector3>& cube_template) {
276  cube_template.clear();
277  cube_template.reserve(24);
278 
279  cube_template.push_back(octomath::Vector3( 1, 1,-1));
280  cube_template.push_back(octomath::Vector3( 1,-1,-1));
281  cube_template.push_back(octomath::Vector3( 1, 1,-1));
282  cube_template.push_back(octomath::Vector3(-1, 1,-1));
283  cube_template.push_back(octomath::Vector3( 1, 1,-1));
284  cube_template.push_back(octomath::Vector3( 1, 1, 1));
285 
286  cube_template.push_back(octomath::Vector3(-1, 1,-1));
287  cube_template.push_back(octomath::Vector3(-1,-1,-1));
288  cube_template.push_back(octomath::Vector3( 1, 1, 1));
289  cube_template.push_back(octomath::Vector3(-1, 1, 1));
290  cube_template.push_back(octomath::Vector3( 1,-1,-1));
291  cube_template.push_back(octomath::Vector3( 1,-1, 1));
292 
293  cube_template.push_back(octomath::Vector3(-1, 1, 1));
294  cube_template.push_back(octomath::Vector3(-1,-1, 1));
295  cube_template.push_back(octomath::Vector3( 1,-1, 1));
296  cube_template.push_back(octomath::Vector3(-1,-1, 1));
297  cube_template.push_back(octomath::Vector3(-1,-1,-1));
298  cube_template.push_back(octomath::Vector3(-1,-1, 1));
299 
300  cube_template.push_back(octomath::Vector3( 1, 1, 1));
301  cube_template.push_back(octomath::Vector3( 1,-1, 1));
302  cube_template.push_back(octomath::Vector3( 1,-1,-1));
303  cube_template.push_back(octomath::Vector3(-1,-1,-1));
304  cube_template.push_back(octomath::Vector3(-1, 1,-1));
305  cube_template.push_back(octomath::Vector3(-1, 1, 1));
306  }
307 
309  const std::vector<octomath::Vector3>& cube_template,
310  const unsigned int& current_array_idx,
311  GLfloat*** glArray) {
312 
313  // epsilon to be substracted from cube size so that neighboring planes don't overlap
314  // seems to introduce strange artifacts nevertheless...
315  double eps = 1e-5;
316 
318 
319  double half_cube_size = GLfloat(v.second /2.0 -eps);
320  unsigned int i = current_array_idx;
321  // Cube surfaces are in gl_array in order: back, front, top, down, left, right.
322  // Arrays are filled in parallel (increasing i for all at once)
323  // One color array for all surfaces is filled when requested
324 
325  p = v.first + cube_template[0] * half_cube_size;
326  (*glArray)[0][i] = p.x();
327  (*glArray)[0][i+1] = p.y();
328  (*glArray)[0][i+2] = p.z();
329 
330  p = v.first + cube_template[1] * half_cube_size;
331  (*glArray)[1][i] = p.x();
332  (*glArray)[1][i+1] = p.y();
333  (*glArray)[1][i+2] = p.z();
334 
335  p = v.first + cube_template[2] * half_cube_size;
336  (*glArray)[2][i] = p.x();
337  (*glArray)[2][i+1] = p.y();
338  (*glArray)[2][i+2] = p.z();
339 
340  p = v.first + cube_template[3] * half_cube_size;
341  (*glArray)[3][i] = p.x();
342  (*glArray)[3][i+1] = p.y();
343  (*glArray)[3][i+2] = p.z();
344 
345  p = v.first + cube_template[4] * half_cube_size;
346  (*glArray)[4][i] = p.x();
347  (*glArray)[4][i+1] = p.y();
348  (*glArray)[4][i+2] = p.z();
349 
350  p = v.first + cube_template[5] * half_cube_size;
351  (*glArray)[5][i] = p.x();
352  (*glArray)[5][i+1] = p.y();
353  (*glArray)[5][i+2] = p.z();
354  i+= 3; //-------------------
355 
356  p = v.first + cube_template[6] * half_cube_size;
357  (*glArray)[0][i] = p.x();
358  (*glArray)[0][i+1] = p.y();
359  (*glArray)[0][i+2] = p.z();
360 
361  p = v.first + cube_template[7] * half_cube_size;
362  (*glArray)[1][i] = p.x();
363  (*glArray)[1][i+1] = p.y();
364  (*glArray)[1][i+2] = p.z();
365 
366  p = v.first + cube_template[8] * half_cube_size;
367  (*glArray)[2][i] = p.x();
368  (*glArray)[2][i+1] = p.y();
369  (*glArray)[2][i+2] = p.z();
370 
371  p = v.first + cube_template[9] * half_cube_size;
372  (*glArray)[3][i] = p.x();
373  (*glArray)[3][i+1] = p.y();
374  (*glArray)[3][i+2] = p.z();
375 
376  p = v.first + cube_template[10] * half_cube_size;
377  (*glArray)[4][i] = p.x();
378  (*glArray)[4][i+1] = p.y();
379  (*glArray)[4][i+2] = p.z();
380 
381  p = v.first + cube_template[11] * half_cube_size;
382  (*glArray)[5][i] = p.x();
383  (*glArray)[5][i+1] = p.y();
384  (*glArray)[5][i+2] = p.z();
385  i+= 3; //-------------------
386 
387  p = v.first + cube_template[12] * half_cube_size;
388  (*glArray)[0][i] = p.x();
389  (*glArray)[0][i+1] = p.y();
390  (*glArray)[0][i+2] = p.z();
391 
392  p = v.first + cube_template[13] * half_cube_size;
393  (*glArray)[1][i] = p.x();
394  (*glArray)[1][i+1] = p.y();
395  (*glArray)[1][i+2] = p.z();
396 
397  p = v.first + cube_template[14] * half_cube_size;
398  (*glArray)[2][i] = p.x();
399  (*glArray)[2][i+1] = p.y();
400  (*glArray)[2][i+2] = p.z();
401 
402  p = v.first + cube_template[15] * half_cube_size;
403  (*glArray)[3][i] = p.x();
404  (*glArray)[3][i+1] = p.y();
405  (*glArray)[3][i+2] = p.z();
406 
407  p = v.first + cube_template[16] * half_cube_size;
408  (*glArray)[4][i] = p.x();
409  (*glArray)[4][i+1] = p.y();
410  (*glArray)[4][i+2] = p.z();
411 
412  p = v.first + cube_template[17] * half_cube_size;
413  (*glArray)[5][i] = p.x();
414  (*glArray)[5][i+1] = p.y();
415  (*glArray)[5][i+2] = p.z();
416  i+= 3; //-------------------
417 
418  p = v.first + cube_template[18] * half_cube_size;
419  (*glArray)[0][i] = p.x();
420  (*glArray)[0][i+1] = p.y();
421  (*glArray)[0][i+2] = p.z();
422 
423  p = v.first + cube_template[19] * half_cube_size;
424  (*glArray)[1][i] = p.x();
425  (*glArray)[1][i+1] = p.y();
426  (*glArray)[1][i+2] = p.z();
427 
428  p = v.first + cube_template[20] * half_cube_size;
429  (*glArray)[2][i] = p.x();
430  (*glArray)[2][i+1] = p.y();
431  (*glArray)[2][i+2] = p.z();
432 
433  p = v.first + cube_template[21] * half_cube_size;
434  (*glArray)[3][i] = p.x();
435  (*glArray)[3][i+1] = p.y();
436  (*glArray)[3][i+2] = p.z();
437 
438  p = v.first + cube_template[22] * half_cube_size;
439  (*glArray)[4][i] = p.x();
440  (*glArray)[4][i+1] = p.y();
441  (*glArray)[4][i+2] = p.z();
442 
443  p = v.first + cube_template[23] * half_cube_size;
444  (*glArray)[5][i] = p.x();
445  (*glArray)[5][i+1] = p.y();
446  (*glArray)[5][i+2] = p.z();
447  i += 3; //-------------------
448 
449  return i; // updated array idx
450  }
451 
452 
454  const unsigned int& current_array_idx,
455  GLfloat** glColorArray) {
456 
457  if (glColorArray == NULL) return current_array_idx;
458 
459  unsigned int colorIdx = current_array_idx;
460  // color for all 4 vertices (same height)
461  for (int k = 0; k < 4; ++k) {
463  SceneObject::heightMapGray(v.first.z(), *glColorArray + colorIdx); // sets r,g,b
464  else
465  SceneObject::heightMapColor(v.first.z(), *glColorArray + colorIdx); // sets r,g,b
466  // set Alpha value:
467  (*glColorArray)[colorIdx + 3] = m_alphaOccupied;
468  colorIdx += 4;
469  }
470  return colorIdx;
471  }
472 
473  unsigned int OcTreeDrawer::setCubeColorRGBA(const unsigned char& r,
474  const unsigned char& g,
475  const unsigned char& b,
476  const unsigned char& a,
477  const unsigned int& current_array_idx,
478  GLfloat** glColorArray) {
479 
480  if (glColorArray == NULL) return current_array_idx;
481  unsigned int colorIdx = current_array_idx;
482  // set color for next 4 vertices (=one quad)
483  for (int k = 0; k < 4; ++k) {
484  (*glColorArray)[colorIdx ] = (double) r/255.;
485  (*glColorArray)[colorIdx + 1] = (double) g/255.;
486  (*glColorArray)[colorIdx + 2] = (double) b/255.;
487  (*glColorArray)[colorIdx + 3] = (double) a/255.;
488  colorIdx += 4;
489  }
490  return colorIdx;
491  }
492 
493 
494  void OcTreeDrawer::clearCubes(GLfloat*** glArray,
495  unsigned int& glArraySize,
496  GLfloat** glColorArray) {
497  if (glArraySize != 0) {
498  for (unsigned i = 0; i < 6; ++i) {
499  delete[] (*glArray)[i];
500  }
501  delete[] *glArray;
502  *glArray = NULL;
503  glArraySize = 0;
504  }
505  if (glColorArray != NULL && *glColorArray != NULL) {
506  delete[] *glColorArray;
507  *glColorArray = NULL;
508  }
509  }
510 
511 
512  // still used for "selection" nodes
513  void OcTreeDrawer::generateCubes(const std::list<octomap::OcTreeVolume>& voxels,
514  GLfloat*** glArray, unsigned int& glArraySize,
515  octomath::Pose6D& origin,
516  GLfloat** glColorArray) {
517  unsigned int i = 0;
518  unsigned int colorIdx = 0;
519 
520  std::vector<octomath::Vector3> cube_template;
521  initCubeTemplate(origin, cube_template);
522 
523  for (std::list<octomap::OcTreeVolume>::const_iterator it=voxels.begin();
524  it != voxels.end(); it++) {
525  i = generateCube(*it, cube_template, i, glArray);
526  }
527 
528  if (glColorArray != NULL) {
529  for (std::list<octomap::OcTreeVolume>::const_iterator it=voxels.begin();
530  it != voxels.end(); it++) {
531  colorIdx = setCubeColorHeightmap(*it, colorIdx, glColorArray);
532  }
533  }
534  }
535 
537 
538  if (m_octree_grid_vis_initialized) return;
539 
541  // allocate arrays for octree grid visualization
542  octree_grid_vertex_size = m_grid_voxels.size() * 12 * 2 * 3;
544 
545  // generate the cubes, 12 lines each
546  std::list<octomap::OcTreeVolume>::iterator it_rec;
547  unsigned int i = 0;
548  double x,y,z;
549  for (it_rec=m_grid_voxels.begin(); it_rec != m_grid_voxels.end(); it_rec++) {
550 
551  x = it_rec->first.x();
552  y = it_rec->first.y();
553  z = it_rec->first.z();
554 
555  double half_voxel_size = it_rec->second / 2.0;
556 
557  // ----
558  octree_grid_vertex_array[i] = x + half_voxel_size;
559  octree_grid_vertex_array[i+1] = y + half_voxel_size;
560  octree_grid_vertex_array[i+2] = z - half_voxel_size;
561  i+= 3;
562  octree_grid_vertex_array[i] = x - half_voxel_size;
563  octree_grid_vertex_array[i+1] = y + half_voxel_size;
564  octree_grid_vertex_array[i+2] = z - half_voxel_size;
565  i+= 3;
566  octree_grid_vertex_array[i] = x - half_voxel_size;
567  octree_grid_vertex_array[i+1] = y + half_voxel_size;
568  octree_grid_vertex_array[i+2] = z - half_voxel_size;
569  i += 3;
570  octree_grid_vertex_array[i] = x - half_voxel_size;
571  octree_grid_vertex_array[i+1] = y + half_voxel_size;
572  octree_grid_vertex_array[i+2] = z + half_voxel_size;
573  i+= 3;
574  octree_grid_vertex_array[i] = x - half_voxel_size;
575  octree_grid_vertex_array[i+1] = y + half_voxel_size;
576  octree_grid_vertex_array[i+2] = z + half_voxel_size;
577  i+= 3;
578  octree_grid_vertex_array[i] = x + half_voxel_size;
579  octree_grid_vertex_array[i+1] = y + half_voxel_size;
580  octree_grid_vertex_array[i+2] = z + half_voxel_size;
581  i+= 3;
582  octree_grid_vertex_array[i] = x + half_voxel_size;
583  octree_grid_vertex_array[i+1] = y + half_voxel_size;
584  octree_grid_vertex_array[i+2] = z + half_voxel_size;
585  i+= 3;
586  octree_grid_vertex_array[i] = x + half_voxel_size;
587  octree_grid_vertex_array[i+1] = y + half_voxel_size;
588  octree_grid_vertex_array[i+2] = z - half_voxel_size;
589  i+= 3;
590  // ----
591  octree_grid_vertex_array[i] = x + half_voxel_size;
592  octree_grid_vertex_array[i+1] = y - half_voxel_size;
593  octree_grid_vertex_array[i+2] = z + half_voxel_size;
594  i+= 3;
595  octree_grid_vertex_array[i] = x - half_voxel_size;
596  octree_grid_vertex_array[i+1] = y - half_voxel_size;
597  octree_grid_vertex_array[i+2] = z + half_voxel_size;
598  i+= 3;
599  octree_grid_vertex_array[i] = x - half_voxel_size;
600  octree_grid_vertex_array[i+1] = y - half_voxel_size;
601  octree_grid_vertex_array[i+2] = z + half_voxel_size;
602  i+= 3;
603  octree_grid_vertex_array[i] = x - half_voxel_size;
604  octree_grid_vertex_array[i+1] = y - half_voxel_size;
605  octree_grid_vertex_array[i+2] = z - half_voxel_size;
606  i+= 3;
607  octree_grid_vertex_array[i] = x - half_voxel_size;
608  octree_grid_vertex_array[i+1] = y - half_voxel_size;
609  octree_grid_vertex_array[i+2] = z - half_voxel_size;
610  i+= 3;
611  octree_grid_vertex_array[i] = x + half_voxel_size;
612  octree_grid_vertex_array[i+1] = y - half_voxel_size;
613  octree_grid_vertex_array[i+2] = z - half_voxel_size;
614  i+= 3;
615  octree_grid_vertex_array[i] = x + half_voxel_size;
616  octree_grid_vertex_array[i+1] = y - half_voxel_size;
617  octree_grid_vertex_array[i+2] = z - half_voxel_size;
618  i+= 3;
619  octree_grid_vertex_array[i] = x + half_voxel_size;
620  octree_grid_vertex_array[i+1] = y - half_voxel_size;
621  octree_grid_vertex_array[i+2] = z + half_voxel_size;
622  i+= 3;
623  // ----
624  octree_grid_vertex_array[i] = x + half_voxel_size;
625  octree_grid_vertex_array[i+1] = y + half_voxel_size;
626  octree_grid_vertex_array[i+2] = z - half_voxel_size;
627  i+= 3;
628  octree_grid_vertex_array[i] = x + half_voxel_size;
629  octree_grid_vertex_array[i+1] = y - half_voxel_size;
630  octree_grid_vertex_array[i+2] = z - half_voxel_size;
631  i+= 3;
632  octree_grid_vertex_array[i] = x - half_voxel_size;
633  octree_grid_vertex_array[i+1] = y + half_voxel_size;
634  octree_grid_vertex_array[i+2] = z - half_voxel_size;
635  i+= 3;
636  octree_grid_vertex_array[i] = x - half_voxel_size;
637  octree_grid_vertex_array[i+1] = y - half_voxel_size;
638  octree_grid_vertex_array[i+2] = z - half_voxel_size;
639  i+= 3;
640  octree_grid_vertex_array[i] = x - half_voxel_size;
641  octree_grid_vertex_array[i+1] = y + half_voxel_size;
642  octree_grid_vertex_array[i+2] = z + half_voxel_size;
643  i+= 3;
644  octree_grid_vertex_array[i] = x - half_voxel_size;
645  octree_grid_vertex_array[i+1] = y - half_voxel_size;
646  octree_grid_vertex_array[i+2] = z + half_voxel_size;
647  i+= 3;
648  octree_grid_vertex_array[i] = x + half_voxel_size;
649  octree_grid_vertex_array[i+1] = y + half_voxel_size;
650  octree_grid_vertex_array[i+2] = z + half_voxel_size;
651  i+= 3;
652  octree_grid_vertex_array[i] = x + half_voxel_size;
653  octree_grid_vertex_array[i+1] = y - half_voxel_size;
654  octree_grid_vertex_array[i+2] = z + half_voxel_size;
655  i+= 3;
656  // ----
657  }
659  }
660 
662  if (octree_grid_vertex_size != 0) {
663  delete[] octree_grid_vertex_array;
665  }
667  }
668 
670  //clearOcTree();
677  }
678 
679 
681 
682  if (m_colorMode == CM_SEMANTIC) {
683  // hardcoded mapping id -> colors
684  if (this->map_id == 0) { // background
685  glColor3f(0.784f, 0.66f, 0); // gold
686  }
687  else if (this->map_id == 1) { // table
688  glColor3f(0.68f, 0., 0.62f); // purple
689  }
690  else { // object
691  glColor3f(0., 0.784f, 0.725f); // cyan
692  }
694  }
695  else {
696  // colors for printout mode:
697  if (m_colorMode == CM_PRINTOUT) {
698  if (!m_drawFree) { // gray on white background
699  glColor3f(0.6f, 0.6f, 0.6f);
700  }
701  else {
702  glColor3f(0.1f, 0.1f, 0.1f);
703  }
704  }
705 
706  // draw binary occupied cells
707  if (m_occupiedThresSize != 0) {
708  if (m_colorMode != CM_PRINTOUT) glColor4f(0.0f, 0.0f, 1.0f, m_alphaOccupied);
710  }
711 
712  // draw delta occupied cells
713  if (m_occupiedSize != 0) {
714  if (m_colorMode != CM_PRINTOUT) glColor4f(0.2f, 0.7f, 1.0f, m_alphaOccupied);
716  }
717  }
718  }
719 
720 
722 
723  if (m_colorMode == CM_PRINTOUT) {
724  if (!m_drawOccupied) { // gray on white background
725  glColor3f(0.5f, 0.5f, 0.5f);
726  }
727  else {
728  glColor3f(0.9f, 0.9f, 0.9f);
729  }
730  }
731 
732  // draw binary freespace cells
733  if (m_freeThresSize != 0) {
734  if (m_colorMode != CM_PRINTOUT) glColor4f(0.0f, 1.0f, 0.0f, 0.3f);
736  }
737 
738  // draw delta freespace cells
739  if (m_freeSize != 0) {
740  if (m_colorMode != CM_PRINTOUT) glColor4f(0.5f, 1.0f, 0.1f, 0.3f);
742  }
743  }
744 
746  if (m_selectionSize != 0) {
747  glColor4f(1.0, 0.0, 0.0, 1.0);
749  }
750  }
751 
752  void OcTreeDrawer::drawCubes(GLfloat** cubeArray, unsigned int cubeArraySize,
753  GLfloat* cubeColorArray) const {
754  if (cubeArraySize == 0 || cubeArray == NULL){
755  std::cerr << "Warning: GLfloat array to draw cubes appears to be empty, nothing drawn.\n";
756  return;
757  }
758 
759  // save current color
760  GLfloat* curcol = new GLfloat[4];
761  glGetFloatv(GL_CURRENT_COLOR, curcol);
762 
763  // enable color pointer when heightColorMode is enabled:
764 
765  if ((m_colorMode == CM_COLOR_HEIGHT || m_colorMode == CM_GRAY_HEIGHT) && (cubeColorArray != NULL)){
766  glEnableClientState(GL_COLOR_ARRAY);
767  glColorPointer(4, GL_FLOAT, 0, cubeColorArray);
768  }
769 
770  // top surfaces:
771  glNormal3f(0.0f, 1.0f, 0.0f);
772  glVertexPointer(3, GL_FLOAT, 0, cubeArray[0]);
773  glDrawArrays(GL_QUADS, 0, cubeArraySize / 3);
774  // bottom surfaces:
775  glNormal3f(0.0f, -1.0f, 0.0f);
776  glVertexPointer(3, GL_FLOAT, 0, cubeArray[1]);
777  glDrawArrays(GL_QUADS, 0, cubeArraySize / 3);
778  // right surfaces:
779  glNormal3f(1.0f, 0.0f, 0.0f);
780  glVertexPointer(3, GL_FLOAT, 0, cubeArray[2]);
781  glDrawArrays(GL_QUADS, 0, cubeArraySize / 3);
782  // left surfaces:
783  glNormal3f(-1.0f, 0.0f, 0.0f);
784  glVertexPointer(3, GL_FLOAT, 0, cubeArray[3]);
785  glDrawArrays(GL_QUADS, 0, cubeArraySize / 3);
786  // back surfaces:
787  glNormal3f(0.0f, 0.0f, -1.0f);
788  glVertexPointer(3, GL_FLOAT, 0, cubeArray[4]);
789  glDrawArrays(GL_QUADS, 0, cubeArraySize / 3);
790  // front surfaces:
791  glNormal3f(0.0f, 0.0f, 1.0f);
792  glVertexPointer(3, GL_FLOAT, 0, cubeArray[5]);
793  glDrawArrays(GL_QUADS, 0, cubeArraySize / 3);
794 
796  && (cubeColorArray != NULL)){
797  glDisableClientState(GL_COLOR_ARRAY);
798  }
799 
800  // draw bounding linies of cubes in printout:
801  if (m_colorMode == CM_PRINTOUT){
802  glDisable(GL_LIGHTING);
803  glHint (GL_LINE_SMOOTH_HINT, GL_NICEST);
804  glEnable (GL_LINE_SMOOTH);
805  glPolygonMode (GL_FRONT_AND_BACK, GL_LINE); // Draw Polygons only as Wireframes
806  glLineWidth(2.0f);
807  glColor3f(0.0f, 0.0f, 0.0f);
808  glCullFace(GL_FRONT_AND_BACK); // Don't draw any Polygons faces
809  //glDepthFunc (GL_LEQUAL);
810 
811  // top meshes:
812  glNormal3f(0.0f, 1.0f, 0.0f);
813  glVertexPointer(3, GL_FLOAT, 0, cubeArray[0]);
814  glDrawArrays(GL_QUADS, 0, cubeArraySize / 3);
815  // bottom meshes:
816  glNormal3f(0.0f, -1.0f, 0.0f);
817  glVertexPointer(3, GL_FLOAT, 0, cubeArray[1]);
818  glDrawArrays(GL_QUADS, 0, cubeArraySize / 3);
819  // right meshes:
820  glNormal3f(1.0f, 0.0f, 0.0f);
821  glVertexPointer(3, GL_FLOAT, 0, cubeArray[2]);
822  glDrawArrays(GL_QUADS, 0, cubeArraySize / 3);
823  // left meshes:
824  glNormal3f(-1.0f, 0.0f, 0.0f);
825  glVertexPointer(3, GL_FLOAT, 0, cubeArray[3]);
826  glDrawArrays(GL_QUADS, 0, cubeArraySize / 3);
827 
828  // restore defaults:
829  glCullFace(GL_BACK);
830  //glDepthFunc(GL_LESS);
831  glDisable(GL_LINE_SMOOTH);
832  glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
833  glEnable(GL_LIGHTING);
834  }
835  // reset color
836  glColor4fv(curcol);
837  delete[] curcol;
838  }
839 
841  if (!m_octree_grid_vis_initialized) return;
842  if (octree_grid_vertex_size == 0) return;
843 
844  glDisable(GL_LIGHTING);
845  glEnable(GL_LINE_SMOOTH);
846 
847  glLineWidth(1.);
848  glVertexPointer(3, GL_FLOAT, 0, octree_grid_vertex_array);
849  glColor3f(0.0, 0.0, 0.0);
850  glDrawArrays(GL_LINES, 0, octree_grid_vertex_size / 3);
851 
852  glDisable(GL_LINE_SMOOTH);
853  glEnable(GL_LIGHTING);
854  }
855 
856  void OcTreeDrawer::enableOcTree(bool enabled) {
857  m_update = true;
858  m_drawOcTreeGrid = enabled;
861  }
862  }
863 
864 
866  origin = t;
867  std::cout << "OcTreeDrawer: setting new global origin: " << t << std::endl;
868 
869  octomap::pose6d relative_transform = origin * initial_origin.inv();
870 
871  std::cout << "origin : " << origin << std::endl;
872  std::cout << "inv init orig : " << initial_origin.inv() << std::endl;
873  std::cout << "relative trans: " << relative_transform << std::endl;
874  }
875 
876  void OcTreeDrawer::drawAxes() const {
877 
878  octomap::pose6d relative_transform = origin * initial_origin.inv();
879 
880  glPushMatrix();
881 
882  float length = 0.15f;
883 
884  GLboolean lighting, colorMaterial;
885  glGetBooleanv(GL_LIGHTING, &lighting);
886  glGetBooleanv(GL_COLOR_MATERIAL, &colorMaterial);
887 
888  glDisable(GL_COLOR_MATERIAL);
889 
890  double angle= 2 * acos(initial_origin.rot().u());
891  double scale = sqrt (initial_origin.rot().x()*initial_origin.rot().x()
893  + initial_origin.rot().z()*initial_origin.rot().z());
894  double ax= initial_origin.rot().x() / scale;
895  double ay= initial_origin.rot().y() / scale;
896  double az= initial_origin.rot().z() / scale;
897 
898  if (angle > 0) glRotatef(OTD_RAD2DEG*angle, ax, ay, az);
899 
900  float color[4];
901  color[0] = 0.7f; color[1] = 0.7f; color[2] = 1.0f; color[3] = 1.0f;
902  glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, color);
903  QGLViewer::drawArrow(length, 0.01*length);
904 
905  color[0] = 1.0f; color[1] = 0.7f; color[2] = 0.7f; color[3] = 1.0f;
906  glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, color);
907  glPushMatrix();
908  glRotatef(90.0, 0.0, 1.0, 0.0);
909  QGLViewer::drawArrow(length, 0.01*length);
910  glPopMatrix();
911 
912  color[0] = 0.7f; color[1] = 1.0f; color[2] = 0.7f; color[3] = 1.0f;
913  glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, color);
914  glPushMatrix();
915  glRotatef(-90.0, 1.0, 0.0, 0.0);
916  QGLViewer::drawArrow(length, 0.01*length);
917  glPopMatrix();
918 
919  glTranslatef(relative_transform.trans().x(), relative_transform.trans().y(), relative_transform.trans().z());
920 
921  if (colorMaterial)
922  glEnable(GL_COLOR_MATERIAL);
923  if (!lighting)
924  glDisable(GL_LIGHTING);
925 
926  glPopMatrix();
927  }
928 
929 } // namespace
octomath::Pose6D::x
float & x()
octomap::OcTreeDrawer::drawFreeVoxels
void drawFreeVoxels() const
Definition: OcTreeDrawer.cpp:721
octomap::OcTreeDrawer::setAlphaOccupied
void setAlphaOccupied(double alpha)
sets alpha level for occupied cells
Definition: OcTreeDrawer.cpp:134
QGLViewer::drawArrow
static void drawArrow(qreal length=1.0, qreal radius=-1.0, int nbSubdivisions=12)
Definition: qglviewer.cpp:3207
octomap::OcTreeDrawer::m_drawOccupied
bool m_drawOccupied
Definition: OcTreeDrawer.h:144
octomap::OcTreeDrawer::m_drawFree
bool m_drawFree
Definition: OcTreeDrawer.h:146
OcTreeBaseImpl< OcTreeNode, AbstractOccupancyOcTree >::size
virtual size_t size() const
octomap::OcTreeVolume
std::pair< point3d, double > OcTreeVolume
octomap::OcTreeDrawer::setOrigin
void setOrigin(octomap::pose6d t)
Definition: OcTreeDrawer.cpp:865
octomap::OcTreeDrawer::m_octree_grid_vis_initialized
bool m_octree_grid_vis_initialized
Definition: OcTreeDrawer.h:148
octomath::Quaternion::x
float & x()
octomap::OcTreeDrawer::clearCubes
void clearCubes(GLfloat ***glArray, unsigned int &glArraySize, GLfloat **glColorArray=NULL)
clear OpenGL visualization
Definition: OcTreeDrawer.cpp:494
octomap::OcTreeDrawer::m_occupiedThresArray
GLfloat ** m_occupiedThresArray
OpenGL representation of Octree cells (cubes)
Definition: OcTreeDrawer.h:122
octomap::SceneObject::m_zMax
double m_zMax
Definition: SceneObject.h:86
octomap::OcTreeDrawer::m_occupiedSize
unsigned int m_occupiedSize
Definition: OcTreeDrawer.h:127
octomath::Pose6D::z
float & z()
octomap::OcTreeDrawer::setCubeColorHeightmap
unsigned int setCubeColorHeightmap(const octomap::OcTreeVolume &v, const unsigned int &current_array_idx, GLfloat **glColorArray)
Definition: OcTreeDrawer.cpp:453
octomap::OcTreeDrawer::map_id
int map_id
Definition: OcTreeDrawer.h:159
OcTreeBaseImpl< OcTreeNode, AbstractOccupancyOcTree >::getMetricMax
virtual void getMetricMax(double &x, double &y, double &z)
octomap::OcTreeDrawer::m_freeThresArray
GLfloat ** m_freeThresArray
Definition: OcTreeDrawer.h:124
octomap::OcTreeDrawer::m_drawSelection
bool m_drawSelection
Definition: OcTreeDrawer.h:147
octomap::SceneObject
Definition: SceneObject.h:48
OcTreeDrawer.h
octomap::OcTreeDrawer::clearOcTreeSelection
void clearOcTreeSelection()
clear the visualization of the OcTree selection
Definition: OcTreeDrawer.cpp:250
octomap::SceneObject::CM_GRAY_HEIGHT
@ CM_GRAY_HEIGHT
Definition: SceneObject.h:54
octomap::SceneObject::heightMapGray
void heightMapGray(double h, GLfloat *glArrayPos) const
Definition: SceneObject.cpp:92
octomap::OcTreeDrawer::m_occupiedColorArray
GLfloat * m_occupiedColorArray
Definition: OcTreeDrawer.h:135
octomap::OcTreeDrawer::initCubeTemplate
void initCubeTemplate(const octomath::Pose6D &origin, std::vector< octomath::Vector3 > &cube_template)
setup cube template
Definition: OcTreeDrawer.cpp:274
octomath::Pose6D::y
float & y()
octomath::Vector3
octomap::OcTreeDrawer::drawOccupiedVoxels
void drawOccupiedVoxels() const
Definition: OcTreeDrawer.cpp:680
octomap::OcTreeDrawer::m_selectionArray
GLfloat ** m_selectionArray
Definition: OcTreeDrawer.h:130
octomap::OcTree
octomath::Quaternion::rotate
Vector3 rotate(const Vector3 &v) const
OcTreeBaseImpl< OcTreeNode, AbstractOccupancyOcTree >::end_tree
const tree_iterator end_tree() const
octomap::OcTreeDrawer::draw
void draw() const
Definition: OcTreeDrawer.cpp:64
octomap::OcTreeDrawer::m_occupiedThresSize
unsigned int m_occupiedThresSize
Definition: OcTreeDrawer.h:123
octomap::SceneObject::CM_SEMANTIC
@ CM_SEMANTIC
Definition: SceneObject.h:55
octomap::SceneObject::m_colorMode
ColorMode m_colorMode
Definition: SceneObject.h:87
octomap::AbstractOcTree
octomap::OcTreeDrawer::setCubeColorRGBA
unsigned int setCubeColorRGBA(const unsigned char &r, const unsigned char &g, const unsigned char &b, const unsigned char &a, const unsigned int &current_array_idx, GLfloat **glColorArray)
Definition: OcTreeDrawer.cpp:473
octomap::OcTreeDrawer::~OcTreeDrawer
virtual ~OcTreeDrawer()
Definition: OcTreeDrawer.cpp:60
octomap::OcTreeDrawer::drawSelection
void drawSelection() const
Definition: OcTreeDrawer.cpp:745
octomap::OcTreeDrawer::m_freeThresSize
unsigned int m_freeThresSize
Definition: OcTreeDrawer.h:125
octomap::OcTreeDrawer::m_drawOcTreeGrid
bool m_drawOcTreeGrid
Definition: OcTreeDrawer.h:145
octomap::OcTreeDrawer::initial_origin
octomap::pose6d initial_origin
Definition: OcTreeDrawer.h:157
octomap::OcTreeDrawer::clear
void clear()
Definition: OcTreeDrawer.cpp:669
octomap::OcTreeDrawer::m_grid_voxels
std::list< octomap::OcTreeVolume > m_grid_voxels
Definition: OcTreeDrawer.h:142
octomap::OcTreeDrawer::OcTreeDrawer
OcTreeDrawer()
Definition: OcTreeDrawer.cpp:33
octomap::OcTreeDrawer::clearOcTreeStructure
void clearOcTreeStructure()
Definition: OcTreeDrawer.cpp:661
octomap::OcTreeDrawer::drawOctreeGrid
void drawOctreeGrid() const
Definition: OcTreeDrawer.cpp:840
octomap::SceneObject::CM_PRINTOUT
@ CM_PRINTOUT
Definition: SceneObject.h:52
octomap::OcTreeDrawer::m_selectionSize
unsigned int m_selectionSize
Definition: OcTreeDrawer.h:131
octomath::Quaternion::y
float & y()
octomap::SceneObject::m_zMin
double m_zMin
Definition: SceneObject.h:85
octomap::OcTreeDrawer::m_displayAxes
bool m_displayAxes
Definition: OcTreeDrawer.h:149
octomap::OcTreeDrawer::m_occupiedThresColorArray
GLfloat * m_occupiedThresColorArray
Color array for occupied cells (height)
Definition: OcTreeDrawer.h:134
octomap::AbstractOccupancyOcTree::isNodeOccupied
bool isNodeOccupied(const OcTreeNode &occupancyNode) const
octomap::OcTreeDrawer::m_occupiedArray
GLfloat ** m_occupiedArray
Definition: OcTreeDrawer.h:126
octomap::OcTreeDrawer::generateCubes
void generateCubes(const std::list< octomap::OcTreeVolume > &voxels, GLfloat ***glArray, unsigned int &glArraySize, octomath::Pose6D &origin, GLfloat **glColorArray=NULL)
Definition: OcTreeDrawer.cpp:513
octomap::OcTreeDrawer::initOctreeGridVis
void initOctreeGridVis()
Definition: OcTreeDrawer.cpp:536
qglviewer.h
octomap::AbstractOccupancyOcTree::isNodeAtThreshold
bool isNodeAtThreshold(const OcTreeNode &occupancyNode) const
octomap::OcTreeDrawer::m_alternativeDrawing
bool m_alternativeDrawing
Definition: OcTreeDrawer.h:150
OcTreeBaseImpl< OcTreeNode, AbstractOccupancyOcTree >::begin_tree
tree_iterator begin_tree(unsigned char maxDepth=0) const
octomath::Quaternion::u
float & u()
octomap::OcTreeDrawer::setOcTreeSelection
void setOcTreeSelection(const std::list< octomap::OcTreeVolume > &selectedPoints)
sets a new selection of the current OcTree to be drawn
Definition: OcTreeDrawer.cpp:241
octomap::OcTreeDrawer::origin
octomap::pose6d origin
Definition: OcTreeDrawer.h:156
octomath::Vector3::y
float & y()
octomath::Pose6D::rot
Quaternion & rot()
octomap::SceneObject::CM_COLOR_HEIGHT
@ CM_COLOR_HEIGHT
Definition: SceneObject.h:53
octomap::OcTreeDrawer::generateCube
unsigned int generateCube(const octomap::OcTreeVolume &v, const std::vector< octomath::Vector3 > &cube_template, const unsigned int &current_array_idx, GLfloat ***glArray)
add one cube to arrays
Definition: OcTreeDrawer.cpp:308
octomap::OcTreeDrawer::m_alphaOccupied
double m_alphaOccupied
Definition: OcTreeDrawer.h:154
octomap::OcTreeDrawer::drawAxes
void drawAxes() const
Definition: OcTreeDrawer.cpp:876
octomap::OcTreeDrawer::initGLArrays
void initGLArrays(const unsigned int &num_cubes, unsigned int &glArraySize, GLfloat ***glArray, GLfloat **glColorArray)
setup OpenGL arrays
Definition: OcTreeDrawer.cpp:255
octomap::OcTreeDrawer::m_update
bool m_update
Definition: OcTreeDrawer.h:151
octomap
octomap::SceneObject::heightMapColor
void heightMapColor(double h, GLfloat *glArrayPos) const
Definition: SceneObject.cpp:38
octomath::Pose6D
octomath::Quaternion::z
float & z()
octomath::Vector3::z
float & z()
octomap::OcTreeDrawer::enableOcTree
void enableOcTree(bool enabled=true)
Definition: OcTreeDrawer.cpp:856
octomap::OcTreeDrawer::octree_grid_vertex_size
unsigned int octree_grid_vertex_size
Definition: OcTreeDrawer.h:140
octomap::OcTreeDrawer::m_freeSize
unsigned int m_freeSize
Definition: OcTreeDrawer.h:129
octomath::Vector3::x
float & x()
octomap::OcTreeDrawer::drawCubes
void drawCubes(GLfloat **cubeArray, unsigned int cubeArraySize, GLfloat *cubeColorArray=NULL) const
Definition: OcTreeDrawer.cpp:752
OTD_RAD2DEG
#define OTD_RAD2DEG
Definition: OcTreeDrawer.cpp:29
octomath::Quaternion
octomap::OcTreeDrawer::octree_grid_vertex_array
GLfloat * octree_grid_vertex_array
OpenGL representation of Octree (grid structure)
Definition: OcTreeDrawer.h:139
octomath::Pose6D::inv
Pose6D inv() const
octomap::OcTreeDrawer::m_freeArray
GLfloat ** m_freeArray
Definition: OcTreeDrawer.h:128
octomap::pose6d
octomath::Pose6D pose6d
octomath::Pose6D::trans
Vector3 & trans()
octomap::OcTreeDrawer::setOcTree
void setOcTree(const AbstractOcTree &octree)
sets a new OcTree that should be drawn by this drawer
Definition: OcTreeDrawer.h:43
OcTreeBaseImpl< OcTreeNode, AbstractOccupancyOcTree >::getMetricMin
virtual void getMetricMin(double &x, double &y, double &z)


octovis
Author(s): Kai M. Wurm , Armin Hornung
autogenerated on Mon Apr 21 2025 02:39:54