Visualizer.hpp
Go to the documentation of this file.
1 /*
2  * This file is part of ArmarX.
3  *
4  * Copyright (C) 2012-2016, High Performance Humanoid Technologies (H2T),
5  * Karlsruhe Institute of Technology (KIT), all rights reserved.
6  *
7  * ArmarX is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License version 2 as
9  * published by the Free Software Foundation.
10  *
11  * ArmarX is distributed in the hope that it will be useful, but
12  * 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 this program. If not, see <http://www.gnu.org/licenses/>.
18  *
19  * @author Rainer Kartmann (rainer dot kartmann at student dot kit dot edu)
20  * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
21  * GNU General Public License
22  */
23 
24 #pragma once
25 
26 #include <thread>
27 
28 #include <Eigen/Geometry>
29 
30 #include <VirtualRobot/math/Helpers.h>
31 
33 
34 #include "VoxelGrid.hpp"
35 
36 
37 namespace visionx::voxelgrid
38 {
39 
40  /**
41  * Visualizer for voxel grids of with voxel type VoxelT.
42  */
43  template <typename VoxelT>
44  class Visualizer
45  {
46  public:
47 
48  /// Default constructor.
49  Visualizer();
50  /// Initialize with debug drawer and voxel grid.
51  Visualizer(const armarx::DebugDrawerTopic& drawer, const std::string& voxelLayer = "VoxelGrid");
52 
53  /// Virtual destructor.
54  virtual ~Visualizer() {}
55 
56 
57  /// Clear the layer.
58  void clearLayer();
59  /// Clear the voxel layer.
60  void clearVoxelLayer(bool sleep = false);
61 
62  /// Draw the voxel grid.
63  void draw(const VoxelGrid<VoxelT>& grid);
64 
65  /// Draw the bounding edges of the voxel grid.
66  void drawBoundingEdges(const VoxelGrid<VoxelT>& grid);
67 
68  /// Draw the bounding edges of the voxel grid.
69  void drawStructure(const VoxelGrid<VoxelT>& grid,
70  float lineWidth = 1,
71  const armarx::DrawColor& colorEdges = {0, .5, 1, 1},
72  const armarx::DrawColor& colorStructure = {0, 1, 1, 1},
73  bool drawOriginVoxel = false);
74 
75 
76  /// Set the debug drawer.
78  {
79  this->_debugDrawer = debugDrawer;
80  }
81  /// Set the layer name.
82  void setLayer(const std::string& layer)
83  {
84  this->_layer = layer;
85  }
86 
87  operator bool() const
88  {
89  return _debugDrawer.operator bool();
90  }
91 
92 
93  protected:
94 
95  /// Information about a voxel about to-be-drawn.
97  {
98  const VoxelGrid<VoxelT>& grid; /// The voxel grid.
99  const std::string& name; /// A unique visu name for this voxel.
100 
101  std::size_t index; /// The voxel's index.
102  const VoxelT& voxel; /// The voxel.
103 
104  const Eigen::Vector3f& pos; /// The voxel's position.
105  const Eigen::Quaternionf& ori; /// The voxel's orientation.
106  const Eigen::Vector3f& extents; /// The voxel extents.
107  };
108 
109 
110  /// Indicate whether a voxel shall be drawn.
111  /// Voxels for which this method returns false are not passed to drawVoxel().
112  virtual bool isVisible(const VoxelVisuData& visu) const
113  {
114  (void) visu;
115  return true;
116  }
117 
118  /// Draw a voxel.
119  virtual void drawVoxel(const VoxelVisuData& visu);
120 
121  /// Get the debug drawer.
123  {
124  return _debugDrawer;
125  }
127  {
128  return _debugDrawer;
129  }
130 
131  /// Get the layer name.
132  std::string getVoxelLayer() const
133  {
134  return _layer + "_voxels";
135  }
136 
137 
138  private:
139 
140  /// The debug drawer.
141  armarx::DebugDrawerTopic _debugDrawer;
142 
143  /// The layer name.
144  std::string _layer;
145 
146  };
147 
148 
149 
150  // IMPLEMENTATION
151 
152 
153  template <typename VT>
155  {}
156 
157  template <typename VT>
159  const armarx::DebugDrawerTopic& debugDrawer, const std::string& layer) :
160  _debugDrawer(debugDrawer), _layer(layer)
161  {
162  using namespace std::chrono_literals;
163  _debugDrawer.setLayer(layer);
164  _debugDrawer.setShortSleepDuration(100ms);
165  }
166 
167  template <typename VT>
169  {
170  _debugDrawer.clearLayer(_layer);
171  }
172 
173  template <typename VT>
175  {
176  _debugDrawer.clearLayer(getVoxelLayer(), sleep);
177  }
178 
179  template <typename VT>
181  {
182  if (!_debugDrawer)
183  {
184  return;
185  }
186 
187  std::vector<Eigen::Vector3f> points;
188  float width = 0.025f;
189  armarx::DrawColor color {0, 1, 1, 1};
190 
191  const Eigen::Matrix32f bb = grid.getLocalBoundingBox();
192  const Eigen::Matrix4f pose = grid.getPose();
193 
194  auto addLine = [&](int x1, int y1, int z1, int x2, int y2, int z2)
195  {
196  Eigen::Vector3f start = { bb.col(x1).x(), bb.col(y1).y(), bb.col(z1).z() };
197  Eigen::Vector3f end = { bb.col(x2).x(), bb.col(y2).y(), bb.col(z2).z() };
198 
199  start = math::Helpers::TransformPosition(pose, start);
200  end = math::Helpers::TransformPosition(pose, end);
201 
202  points.push_back({ start.x(), start.y(), start.z() });
203  points.push_back({ end.x(), end.y(), end.z() });
204  };
205 
206  /* 001 +-----+ 011
207  * /| 111/|
208  * 101 +-----+ |
209  * | +---|-+ 010
210  * |/000 |/
211  * 100 +-----+ 110
212  */
213 
214  // 000 -> 100, 010, 001
215  addLine(0, 0, 0, 1, 0, 0);
216  addLine(0, 0, 0, 0, 1, 0);
217  addLine(0, 0, 0, 0, 0, 1);
218 
219  // 111 -> 011, 101, 110
220  addLine(1, 1, 1, 0, 1, 1);
221  addLine(1, 1, 1, 1, 0, 1);
222  addLine(1, 1, 1, 1, 1, 0);
223 
224  // 100 -> 101, 110
225  addLine(1, 0, 0, 1, 0, 1);
226  addLine(1, 0, 0, 1, 1, 0);
227 
228  // 010 -> 110, 011
229  addLine(0, 1, 0, 1, 1, 0);
230  addLine(0, 1, 0, 0, 1, 1);
231 
232  // 001 -> 101, 011
233  addLine(0, 0, 1, 1, 0, 1);
234  addLine(0, 0, 1, 0, 1, 1);
235 
236  _debugDrawer.drawLineSet({_layer, "edges"}, points, width, color);
237  }
238 
239 
240  template <typename VT>
242  float lineWidth,
243  const armarx::DrawColor& colorEdges,
244  const armarx::DrawColor& colorStructure,
245  bool drawOriginVoxel)
246  {
247  if (!_debugDrawer)
248  {
249  return;
250  }
251 
252  armarx::DebugDrawerLineSet lines;
253  lines.lineWidth = lineWidth;
254  lines.colorNoIntensity = colorStructure;
255  lines.colorFullIntensity = colorEdges;
256 
257  const Eigen::Matrix32f bb = grid.getLocalBoundingBox();
258  const Eigen::Matrix4f pose = grid.getPose();
259 
260  auto addLine = [&](
261  const Eigen::Vector3f & startLocal, const Eigen::Vector3f & endLocal,
262  float intensity = 1)
263  {
264  const Eigen::Vector3f start = math::Helpers::TransformPosition(pose, startLocal);
265  const Eigen::Vector3f end = math::Helpers::TransformPosition(pose, endLocal);
266 
267  lines.points.push_back({ start.x(), start.y(), start.z() });
268  lines.points.push_back({ end.x(), end.y(), end.z() });
269 
270  lines.intensities.push_back(intensity);
271  };
272 
273  auto addEdge = [&](int x1, int y1, int z1, int x2, int y2, int z2)
274  {
275  const Eigen::Vector3f start = { bb.col(x1).x(), bb.col(y1).y(), bb.col(z1).z() };
276  const Eigen::Vector3f end = { bb.col(x2).x(), bb.col(y2).y(), bb.col(z2).z() };
277  addLine(start, end, 1);
278  };
279 
280  /* 001 +-----+ 011
281  * /| 111/|
282  * 101 +-----+ |
283  * | +---|-+ 010
284  * |/000 |/
285  * 100 +-----+ 110
286  */
287 
288  // 000 -> 100, 010, 001
289  addEdge(0, 0, 0, 1, 0, 0);
290  addEdge(0, 0, 0, 0, 1, 0);
291  addEdge(0, 0, 0, 0, 0, 1);
292 
293  // 111 -> 011, 101, 110
294  addEdge(1, 1, 1, 0, 1, 1);
295  addEdge(1, 1, 1, 1, 0, 1);
296  addEdge(1, 1, 1, 1, 1, 0);
297 
298  // 100 -> 101, 110
299  addEdge(1, 0, 0, 1, 0, 1);
300  addEdge(1, 0, 0, 1, 1, 0);
301 
302  // 010 -> 110, 011
303  addEdge(0, 1, 0, 1, 1, 0);
304  addEdge(0, 1, 0, 0, 1, 1);
305 
306  // 001 -> 101, 011
307  addEdge(0, 0, 1, 1, 0, 1);
308  addEdge(0, 0, 1, 0, 1, 1);
309 
310  const auto min = bb.col(0);
311  const auto max = bb.col(1);
312 
313  auto addQuad = [&](const Eigen::Vector3f & center, int h1, int h2, float intensity = 0)
314  {
315  /* -/+ D----^----C +/+
316  * | h2| |
317  * | +---->
318  * | c h1 |
319  * -/- A---------B +/-
320  */
321 
322  Eigen::Vector3f A, B, C, D;
323  A = B = C = D = center;
324 
325  A(h1) = min(h1);
326  A(h2) = min(h2);
327 
328  B(h1) = max(h1);
329  B(h2) = min(h2);
330 
331  C(h1) = max(h1);
332  C(h2) = max(h2);
333 
334  D(h1) = min(h1);
335  D(h2) = max(h2);
336 
337  addLine(A, B, intensity);
338  addLine(B, C, intensity);
339  addLine(C, D, intensity);
340  addLine(D, A, intensity);
341  };
342 
343 
344  Eigen::Vector3i index = index.Zero();
345  Eigen::Vector3f center = center.Zero();
346 
347  const Eigen::Vector3i indicesMinMax[2] = { grid.getVoxelGridIndexMin(), grid.getVoxelGridIndexMax() };
348 
349  for (int i = 0; i < 3; ++i)
350  {
351  int h1 = (i + 1) % 3;
352  int h2 = (i + 2) % 3;
353 
354  for (int mm :
355  {
356  0, 1
357  }) // min / max
358  {
359  index(i) = indicesMinMax[mm](i);
360  center(i) = grid.getVoxelCenter(index, true)(i);
361 
362  // Shift: min => -size, max => +size
363  float shift = (mm == 0 ? -1 : +1) * grid.getVoxelSizes()(i);
364 
365  // Add quad at bounding edge (shift one voxel to center).
366  // (min => +shift, max => -shift)
367  center(i) -= shift;
368  addQuad(center, h1, h2);
369 
370  // Add quad at origin (at +- size/2 around origin).
371  center(i) = shift / 2;
372  addQuad(center, h1, h2);
373  }
374  if (grid.getGridSizes()(i) % 2 == 0)
375  {
376  // Also add a quad at origin for min of voxels at -1.
377  center(i) = - 1.5 * grid.getVoxelSizes()(i);
378  addQuad(center, h1, h2);
379  }
380  }
381 
382  _debugDrawer.drawLineSet({_layer, "structure"}, lines);
383 
384  if (drawOriginVoxel)
385  {
386  _debugDrawer.drawBox({_layer, "origin_voxel"},
387  grid.getOrigin(), grid.getOrientation(), grid.getVoxelSizes(),
388  _debugDrawer.toDrawColor(colorEdges, .25));
389  }
390  }
391 
392 
393  template<typename VoxelT>
395  {
396  if (!_debugDrawer)
397  {
398  return;
399  }
400 
401  for (std::size_t i = 0; i < grid.numVoxels(); ++i)
402  {
403  const VoxelT& voxel = grid.getVoxels()[i];
404  const Eigen::Vector3f center = grid.getVoxelCenter(i);
405 
406  VoxelVisuData visu { grid, "voxel_" + std::to_string(i), i, voxel,
407  center, grid.getOrientation(), grid.getVoxelSizes() };
408 
409  if (isVisible(visu))
410  {
411  drawVoxel(visu);
412  }
413  }
414  }
415 
416  template<typename VoxelT>
417  void Visualizer<VoxelT>::drawVoxel(const VoxelVisuData& visu)
418  {
419  const armarx::DrawColor color { .5, .5, .5, 1 };
420  drawer().drawBox({getVoxelLayer(), visu.name}, visu.pos, visu.ori, visu.extents, color);
421  }
422 
423 }
visionx::voxelgrid::VoxelGrid< VoxelT >
armarx::DebugDrawerTopic
The DebugDrawerTopic wraps a DebugDrawerInterfacePrx and provides a more useful interface than the Ic...
Definition: DebugDrawerTopic.h:152
visionx::voxelgrid::Visualizer::clearVoxelLayer
void clearVoxelLayer(bool sleep=false)
Clear the voxel layer.
Definition: Visualizer.hpp:174
visionx::voxelgrid::Visualizer::VoxelVisuData
Information about a voxel about to-be-drawn.
Definition: Visualizer.hpp:96
index
uint8_t index
Definition: EtherCATFrame.h:59
visionx::voxelgrid::VoxelGrid::getVoxelSizes
Eigen::Vector3f getVoxelSizes() const
Get the voxel size.
Definition: VoxelGrid.hpp:195
visionx::voxelgrid::Visualizer::VoxelVisuData::pos
const Eigen::Vector3f & pos
The voxel.
Definition: Visualizer.hpp:104
visionx::voxelgrid::VoxelGrid::getPose
Eigen::Matrix4f getPose() const
Get the grid pose in the world frame.
Definition: VoxelGrid.hpp:320
visionx::voxelgrid::Visualizer::drawer
armarx::DebugDrawerTopic & drawer()
Get the debug drawer.
Definition: Visualizer.hpp:122
visionx::voxelgrid::Visualizer::VoxelVisuData::ori
const Eigen::Quaternionf & ori
The voxel's position.
Definition: Visualizer.hpp:105
visionx::voxelgrid::Visualizer
Visualizer for voxel grids of with voxel type VoxelT.
Definition: Visualizer.hpp:44
visionx::voxelgrid::Visualizer::drawBoundingEdges
void drawBoundingEdges(const VoxelGrid< VoxelT > &grid)
Draw the bounding edges of the voxel grid.
Definition: Visualizer.hpp:180
visionx::voxelgrid::Visualizer::drawStructure
void drawStructure(const VoxelGrid< VoxelT > &grid, float lineWidth=1, const armarx::DrawColor &colorEdges={0,.5, 1, 1}, const armarx::DrawColor &colorStructure={0, 1, 1, 1}, bool drawOriginVoxel=false)
Draw the bounding edges of the voxel grid.
Definition: Visualizer.hpp:241
visionx::voxelgrid
Definition: exceptions.cpp:8
DebugDrawerTopic.h
visionx::voxelgrid::VoxelGrid::numVoxels
std::size_t numVoxels() const
Get the number of voxels in the grid.
Definition: VoxelGrid.hpp:165
visionx::voxelgrid::Visualizer::clearLayer
void clearLayer()
Clear the layer.
Definition: Visualizer.hpp:168
visionx::voxelgrid::Visualizer::VoxelVisuData::index
std::size_t index
A unique visu name for this voxel.
Definition: Visualizer.hpp:101
visionx::voxelgrid::Visualizer::getVoxelLayer
std::string getVoxelLayer() const
Get the layer name.
Definition: Visualizer.hpp:132
visionx::voxelgrid::Visualizer::VoxelVisuData::voxel
const VoxelT & voxel
The voxel's index.
Definition: Visualizer.hpp:102
visionx::voxelgrid::Visualizer::VoxelVisuData::grid
const VoxelGrid< VoxelT > & grid
Definition: Visualizer.hpp:98
visionx::voxelgrid::Visualizer::isVisible
virtual bool isVisible(const VoxelVisuData &visu) const
Indicate whether a voxel shall be drawn.
Definition: Visualizer.hpp:112
armarx::DebugDrawerTopic::drawBox
void drawBox(const VisuID &id, const Eigen::Vector3f &position, const Eigen::Quaternionf &orientation, const Eigen::Vector3f &extents, const DrawColor &color=DEFAULTS.colorBox, bool ignoreLengthScale=false)
Draw a box.
Definition: DebugDrawerTopic.cpp:179
max
T max(T t1, T t2)
Definition: gdiam.h:48
visionx::voxelgrid::VoxelGrid::getVoxelGridIndexMax
Eigen::Vector3i getVoxelGridIndexMax() const
Get the maximal (along each axis) voxel grid index.
Definition: VoxelGrid.hpp:245
visionx::voxelgrid::VoxelGrid::getOrientation
Eigen::Quaternionf getOrientation() const
Get the grid orienation in the world frame.
Definition: VoxelGrid.hpp:283
armarx::to_string
const std::string & to_string(const std::string &s)
Definition: StringHelpers.h:40
visionx::voxelgrid::Visualizer::Visualizer
Visualizer()
Default constructor.
Definition: Visualizer.hpp:154
visionx::voxelgrid::Visualizer::setLayer
void setLayer(const std::string &layer)
Set the layer name.
Definition: Visualizer.hpp:82
visionx::voxelgrid::VoxelGrid::getOrigin
Eigen::Vector3f getOrigin() const
Get the grid origin in the world frame (center of voxel [0 0 0]).
Definition: VoxelGrid.hpp:270
A
class A(deque< T, A >)) ARMARX_OVERLOAD_STD_HASH_FOR_ITERABLE((class T
Enables hashing of std::list.
visionx::voxelgrid::Visualizer::VoxelVisuData::extents
const Eigen::Vector3f & extents
The voxel's orientation.
Definition: Visualizer.hpp:106
visionx::voxelgrid::Visualizer::drawer
const armarx::DebugDrawerTopic & drawer() const
Definition: Visualizer.hpp:126
GfxTL::Matrix4f
MatrixXX< 4, 4, float > Matrix4f
Definition: MatrixXX.h:601
armarx::Quaternion< float, 0 >
visionx::voxelgrid::Visualizer::draw
void draw(const VoxelGrid< VoxelT > &grid)
Draw the voxel grid.
Definition: Visualizer.hpp:394
IceInternal::ProxyHandle<::IceProxy::armarx::DebugDrawerInterface >
visionx::voxelgrid::Visualizer::setDebugDrawer
void setDebugDrawer(const armarx::DebugDrawerInterfacePrx &debugDrawer)
Set the debug drawer.
Definition: Visualizer.hpp:77
visionx::voxelgrid::Visualizer::drawVoxel
virtual void drawVoxel(const VoxelVisuData &visu)
Draw a voxel.
Definition: Visualizer.hpp:417
visionx::voxelgrid::VoxelGrid::getVoxels
const std::vector< VoxelT > & getVoxels() const
Get the voxels.
Definition: VoxelGrid.hpp:147
visionx::voxelgrid::VoxelGrid::getGridSizes
Eigen::Vector3i getGridSizes() const
Get the grid size.
Definition: VoxelGrid.hpp:177
Eigen::Matrix
Definition: EigenForwardDeclarations.h:27
visionx::voxelgrid::VoxelGrid::getVoxelCenter
Eigen::Vector3f getVoxelCenter(std::size_t index, bool local=false) const
Get the center of the voxel with the given index.
Definition: VoxelGrid.hpp:251
min
T min(T t1, T t2)
Definition: gdiam.h:42
visionx::voxelgrid::Visualizer::~Visualizer
virtual ~Visualizer()
Virtual destructor.
Definition: Visualizer.hpp:54
visionx::voxelgrid::VoxelGrid::getLocalBoundingBox
Eigen::Matrix32f getLocalBoundingBox() const
Get the local axis aligned bounding box of the grid (minimal/maximal values in columns).
Definition: VoxelGrid.hpp:356
VoxelGrid.hpp
visionx::voxelgrid::VoxelGrid::getVoxelGridIndexMin
Eigen::Vector3i getVoxelGridIndexMin() const
Get the minimal (along each axis) voxel grid index.
Definition: VoxelGrid.hpp:240
visionx::voxelgrid::Visualizer::VoxelVisuData::name
const std::string & name
The voxel grid.
Definition: Visualizer.hpp:99