DebugDrawerTopic.h
Go to the documentation of this file.
1#pragma once
2
3#include <chrono>
4#include <functional>
5#include <thread>
6
7#include <Eigen/Geometry>
8
9#include <RobotAPI/interface/visualization/DebugDrawerInterface.h>
10
11namespace Eigen
12{
13 /**
14 * @brief A 3x2 matrix.
15 *
16 * Useful to represent axis-aligned bounding boxes (AABBs). When used as a
17 * AABB, column 0 contains the minimal x, y, z values and column 1 the
18 * maximal x, y, z values.
19 * Accordingly, the rows each contain the limits in x, y, z direction.
20 */
22} // namespace Eigen
23
24namespace VirtualRobot
25{
26 class TriMeshModel;
27 class BoundingBox;
28} // namespace VirtualRobot
29
30namespace armarx
31{
32 // forward declaration
33 class ManagedIceObject;
34
35 /**
36 * @brief The `DebugDrawerTopic` wraps a `DebugDrawerInterfacePrx` and
37 * provides a more useful interface than the Ice interface.
38 *
39 * The methods by `DebugDrawerTopic` take "raw" types, such as Eigen or PCL
40 * types, and take care of conversion to Ice variants or data structures.
41 * In addition, this class provides useful overloads for different use cases.
42 *
43 * Drawing is enabled if the internal topic proxy is set and an optional
44 * enabled flag is set (true by default). All methods check whether drawing
45 * is enabled and do nothing if drawing is disabled. To disable
46 * visualization by this class completely, use `setEnabled(true/false)` or
47 * just do not set the topic. To check whether visualization is enabled,
48 * use `enabled()` or just convert `*this` to bool:
49 * @code
50 * DebugDrawerTopic debugDrawer;
51 * if (debugDrawer) // Equivalent: if (debugDrawer.enabled())
52 * {
53 * // Do stuff if visualization is enabled.
54 * }
55 * @endcode
56 *
57 * The `DebugDrawerTopic` allows to set a layer on constructor or via
58 * `setLayer()`. This layer will be used if none is passed to a drawing
59 * method. If no layer is passed or set, `DebugDrawerTopic::DEFAULT_LAYER`
60 * is used.
61 *
62 *
63 * @par Initialisation by Offering and Getting Topic
64 *
65 * A `DebugDrawerTopic` needs an underlying `DebugDrawerInterfacePrx` topic proxy.
66 * This proxy can be passed on construction or set via `setTopic()`.
67 * In a component (or any other `ManagedIceObject`), `DebugDrawerTopic`
68 * provides convenience functions to register and fetch the topics.
69 *
70 * In `onInitComponent()` (or equivalent method), call:
71 * @code
72 * debugDrawer.offeringTopic(*this);
73 * @endcode
74 * In `onConnectComponent()` (or equivalent), call:
75 * @code
76 * debugDrawer.getTopic(*this);
77 * @endcode
78 * where `*this` is a `ManagedIceObject`.
79 *
80 * This will call `this->offeringTopic("...")` and `this->getTopic("...")`
81 * with the correct topic name (`DebugDrawerTopic::TOPIC_NAME`) and
82 * enable the `DebugDrawerTopic`.
83 *
84 *
85 * @par Scaling
86 *
87 * `DebugDrawerTopic` supports length scaling and pose scaling.
88 *
89 * If a length scale is set, all visualizations will be scaled up or down
90 * by this value. This scaling affects positions, sizes / extents, and
91 * distances / lengths. This is useful when drawing quantities of
92 * different sources using different scalings (such as meters vs
93 * millimeters).
94 * Length scale can be set via `setPoseScale()` or the short hands
95 * `setPoseScaleMetersToMillimeters()` and `setPoseScaleMillimetersToMeters()`.
96 *
97 * All applicable methods offer a final argument called
98 * `ignoreLengthScaling` (false by default, expect for robots, see below),
99 * which can be set to true to ignore the set length scale for this
100 * method call.
101 *
102 * @note Robots are always drawn in their native size (the
103 * `DebugDrawerInterface` offers no size scaling for robots).
104 * (That is, robots are drawn in millimeters most of the time.)
105 *
106 *
107 * In addition, this class allows to set a pose scale, which will be used
108 * for all drawn poses (if no other value is passed to drawPose()).
109 * This is useful when working with geometries scaled in meters, in which
110 * case a pose scale of 0.001 can be used.
111 *
112 *
113 * @par Argument Pattern
114 *
115 * All drawing methods take a `VisuID` as first argument, which specifies
116 * the name of the visualization and the layer to draw on.
117 * There are different ways to specify the first argument.
118 * For example, to specify a only the name for a pose, pass just the name:
119 *
120 * @code
121 * Eigen::Matrix4f pose = Eigen::Matrix4f::Identity();
122 * std::string name = "pose";
123 * debugDrawer.drawPose(name, pose);
124 * debugDrawer.drawPose({name}, pose); // equivalent to the line above
125 * @endcode
126 *
127 * This will draw a pose on the preset layer (i.e. the layer passed to the
128 * constructor or set via `setLayer()`, or "debug" by default).
129 * To specify both name and layer of a single visualization, pass both in
130 * an initializer list:
131 *
132 * @code
133 * Eigen::Matrix4f pose = Eigen::Matrix4f::Identity();
134 * std::string layer = "layer";
135 * std::string name = "pose";
136 * debugDrawer.drawPose({layer, name}, pose);
137 * @endcode
138 *
139 *
140 * After the VisuID, usually the essential geometric parameters follow,
141 * (e.g. position, size, length, point list, ...), depending on the type
142 * of visualization.
143 * Finally, decorative parameters like colors and width can be passed.
144 * Most of the time, they have sensible default values and can be omitted
145 * for quick-and-dirty drawing.
146 *
147 * (Added methods should adhere to this pattern.)
148 *
149 * @see `DebugDrawerTopic::VisuID`
150 */
152 {
153 public:
154 /**
155 * @brief A visualisation ID.
156 *
157 * This constructor can be called in the following ways
158 * (with `draw(const VisuID& id, ...)` being any drawing method):
159 *
160 * @code
161 * std::string name = "pose";
162 * std::string layer = "layer";
163 * draw(name, ...); // just the name, implicit call
164 * draw({name}, ...); // just the name, call with initializer list
165 * draw({layer, name}, ...); // layer and name, with initializer list
166 * @endcode
167 *
168 * (And of course by an explicit call if you want to be really verbose.)
169 * Not passing a layer will cause DebugDrawerTopic to use the
170 * preset layer.
171 */
172 struct VisuID
173 {
174 public:
175 /// Empty constructor.
176 VisuID();
177
178 /// Construct a VisuID with given name (for drawing to the preset layer).
179 VisuID(const std::string& name);
180 /// Construct a VisuID with given name and layer.
181 VisuID(const std::string& layer, const std::string& name);
182
183 /// Construct a VisuID from a non-std::string source (e.g. char[]).
184 template <typename Source>
185 VisuID(const Source& name) : VisuID(std::string(name))
186 {
187 }
188
189 /// Get a `VisuID` with the given name and same layer as `*this.
190 VisuID withName(const std::string& name) const;
191
192 /// Streams a short human-readable description of `rhs` to `os`.
193 friend std::ostream& operator<<(std::ostream& os, const VisuID& rhs);
194
195 public:
196 std::string layer = ""; ///< The layer name (empty by default).
197 std::string name = ""; ///< The visu name (empty by default).
198 };
199
200 /// Default values for drawing functions.
201 struct Defaults
202 {
203 DrawColor colorText{0, 0, 0, 1};
204
205 DrawColor colorArrow{1, .5, 0, 1};
206 DrawColor colorBox{1, 0, 0, 1};
207 DrawColor colorCylinder{0, 1, 0, 1};
208 DrawColor colorLine{.5, 0, 0, 1};
209 DrawColor colorSphere{0, 0, 1, 1};
210
211 DrawColor colorPolygonFace{0, 1, 1, 1};
212 DrawColor colorPolygonEdge{.75, .75, .75, 1};
213
214 DrawColor colorFloor{.1f, .1f, .1f, 1};
215
216 DrawColor colorPointCloud{.5, .5, .5, 1.};
217
218 // Default value of DebugDrawerColoredPointCloud etc.
220
221 float lineWidth = 2;
222
223 DrawColor boxEdgesColor{0, 1, 1, 1};
224 float boxEdgesWidth = 2;
225 };
226
227 static const Defaults DEFAULTS;
228
229
230 public:
231 // CONSTRUCTION & SETUP
232
233 /// Construct without topic, and optional layer.
234 DebugDrawerTopic(const std::string& layer = DEFAULT_LAYER);
235 /// Construct with given topic and optional layer.
237 const std::string& layer = DEFAULT_LAYER);
238
239
240 /// Set the topic.
241 void setTopic(const DebugDrawerInterfacePrx& topic);
242 /// Get the topic.
244
245 /**
246 * @brief Set whether drawing is enabled.
247 * Visualization is only truly enabled if the topic is set.
248 */
249 void setEnabled(bool enabled);
250 /// Indicate whether visualization is enabled, i.e. a topic is set and enabled flag is set.
251 bool enabled() const;
252
253 /**
254 * @brief Call offeringTopic([topicName]) on the given component.
255 * @param component The component (`*this` when called from a component).
256 * @param topicNameOverride Optional override for the topic name. If left empty (default),
257 * uses the standard topic name (see `TOPIC_NAME`).
258 */
260 const std::string& topicNameOverride = "") const;
261 /**
262 * @brief Get the topic by calling getTopic([topicName]) on the given component.
263 * @param component The component (`*this` when called from a component).
264 * @param topicNameOverride Optional override for the topic name. If left empty (default),
265 * uses the standard topic name (see `TOPIC_NAME`).
266 */
267 void getTopic(ManagedIceObject& component, const std::string& topicNameOverride = "");
268
269 /// Get the default layer (used if no layer is passed to a method).
270 const std::string& getLayer() const;
271 /// Set the default layer (used if no layer is passed to a method).
272 void setLayer(const std::string& layer);
273
274 /// Get the scaling for positions, lengths and distances.
275 float getLengthScale() const;
276 /// Set the scale for positions, lengths and distances.
277 void setLengthScale(float scale);
278 /// Set the scale for positions, lengths and distances to 1000.
280 /// Set the scale for positions, lengths and distances to 0.001.
282
283 /// Get the scale for pose visualization.
284 float getPoseScale() const;
285 /// Set the scale for pose visualization.
286 /// This value will be used for all successive calls to drawPose().
287 void setPoseScale(float scale);
288 /// Set the pose scale to 0.001 (good when drawing in meters).
289 void setPoseScaleMeters();
290 /// Set the pose scale to 1 (good when drawing in millimeters).
292
293
294 // SLEEP
295
296 /// Sleep for the `shortSleepDuration`. Useful after clearing.
297 void shortSleep();
298
299 /// If enabled, sleep for the given duration (e.g. a chrono duration).
300 template <typename DurationT>
301 void sleepFor(const DurationT& duration);
302
303 /// Set the duration for "short sleeps".
304 template <typename DurationT>
305 void setShortSleepDuration(const DurationT& duration);
306
307
308 // CLEAR
309
310 /// Clear all layers.
311 /// @param sleep If true, do a short sleep clearing.
312 void clearAll(bool sleep = false);
313
314 /// Clear the (set default) layer.
315 /// @param sleep If true, do a short sleep clearing.
316 void clearLayer(bool sleep = false);
317
318 /// Clear the given layer.
319 /// @param sleep If true, do a short sleep clearing.
320 void clearLayer(const std::string& layer, bool sleep = false);
321
322
323 // PRIMITIVES
324
325 /**
326 * @brief Draw text at the specified position.
327 * @param size the text size (in pixels, not affected by length scaling)
328 */
329 void drawText(const VisuID& id,
330 const Eigen::Vector3f& position,
331 const std::string& text,
332 int size = 10,
333 const DrawColor color = DEFAULTS.colorText,
334 bool ignoreLengthScale = false);
335
336
337 /// Draw a box.
338 void drawBox(const VisuID& id,
339 const Eigen::Vector3f& position,
340 const Eigen::Quaternionf& orientation,
341 const Eigen::Vector3f& extents,
342 const DrawColor& color = DEFAULTS.colorBox,
343 bool ignoreLengthScale = false);
344 /// Draw a box.
345 void drawBox(const VisuID& id,
346 const Eigen::Matrix4f& pose,
347 const Eigen::Vector3f& extents,
348 const DrawColor& color = DEFAULTS.colorBox,
349 bool ignoreLengthScale = false);
350
351 /// Draw an axis aligned bounding box.
352 void drawBox(const VisuID& id,
353 const VirtualRobot::BoundingBox& boundingBox,
354 const DrawColor& color = DEFAULTS.colorBox,
355 bool ignoreLengthScale = false);
356
357 /// Draw a locally axis aligned bounding box, transformed by the given pose.
358 void drawBox(const VisuID& id,
359 const VirtualRobot::BoundingBox& boundingBox,
360 const Eigen::Matrix4f& pose,
361 const DrawColor& color = DEFAULTS.colorBox,
362 bool ignoreLengthScale = false);
363
364
365 /// Remove a box.
366 void removeBox(const VisuID& id);
367
368
369 /// Draw box edges (as a line set).
370 void drawBoxEdges(const VisuID& id,
371 const Eigen::Vector3f& position,
372 const Eigen::Quaternionf& orientation,
373 const Eigen::Vector3f& extents,
374 float width = DEFAULTS.boxEdgesWidth,
375 const DrawColor& color = DEFAULTS.boxEdgesColor,
376 bool ignoreLengthScale = false);
377
378 /// Draw box edges (as a line set).
379 void drawBoxEdges(const VisuID& id,
380 const Eigen::Matrix4f& pose,
381 const Eigen::Vector3f& extents,
382 float width = DEFAULTS.boxEdgesWidth,
383 const DrawColor& color = DEFAULTS.boxEdgesColor,
384 bool ignoreLengthScale = false);
385
386 /// Draw edges of an axis aligned bounding box (as a line set).
387 void drawBoxEdges(const VisuID& id,
388 const VirtualRobot::BoundingBox& boundingBox,
389 float width = DEFAULTS.boxEdgesWidth,
390 const DrawColor& color = DEFAULTS.boxEdgesColor,
391 bool ignoreLengthScale = false);
392
393 /// Draw edges of an axis aligned bounding box (as a line set).
394 void drawBoxEdges(const VisuID& id,
395 const Eigen::Matrix32f& aabb,
396 float width = DEFAULTS.boxEdgesWidth,
397 const DrawColor& color = DEFAULTS.boxEdgesColor,
398 bool ignoreLengthScale = false);
399
400 /// Draw edges of a locally axis-aligned bounding box, transformed by the given pose (as a line set).
401 void drawBoxEdges(const VisuID& id,
402 const VirtualRobot::BoundingBox& boundingBox,
403 const Eigen::Matrix4f& pose,
404 float width = DEFAULTS.boxEdgesWidth,
405 const DrawColor& color = DEFAULTS.boxEdgesColor,
406 bool ignoreLengthScale = false);
407
408 /// Draw edges of a locally axis-aligned bounding box, transformed by the given pose (as a line set).
409 void drawBoxEdges(const VisuID& id,
410 const Eigen::Matrix32f& aabb,
411 const Eigen::Matrix4f& pose,
412 float width = DEFAULTS.boxEdgesWidth,
413 const DrawColor& color = DEFAULTS.boxEdgesColor,
414 bool ignoreLengthScale = false);
415
416 /// Remove box edges (as a line set).
417 void removeboxEdges(const VisuID& id);
418
419
420 /**
421 * @brief Draw a cylinder with center and direction.
422 * @param length The full length (not half-length).
423 */
424 void drawCylinder(const VisuID& id,
425 const Eigen::Vector3f& center,
426 const Eigen::Vector3f& direction,
427 float length,
428 float radius,
429 const DrawColor& color = DEFAULTS.colorCylinder,
430 bool ignoreLengthScale = false);
431
432 /**
433 * @brief Draw a cylinder with center and orientation.
434 * An identity orientation represents a cylinder with an axis aligned to the Y-axis.
435 * @param length The full length (not half-length).
436 */
437 void drawCylinder(const VisuID& id,
438 const Eigen::Vector3f& center,
439 const Eigen::Quaternionf& orientation,
440 float length,
441 float radius,
442 const DrawColor& color = DEFAULTS.colorCylinder,
443 bool ignoreLengthScale = false);
444
445 /// Draw a cylinder from start to end.
446 void drawCylinderFromTo(const VisuID& id,
447 const Eigen::Vector3f& from,
448 const Eigen::Vector3f& to,
449 float radius,
450 const DrawColor& color = DEFAULTS.colorCylinder,
451 bool ignoreLengthScale = false);
452
453 /// Remove a cylinder.
454 void removeCylinder(const VisuID& id);
455
456
457 /// Draw a sphere.
458 void drawSphere(const VisuID& id,
459 const Eigen::Vector3f& center,
460 float radius,
461 const DrawColor& color = DEFAULTS.colorSphere,
462 bool ignoreLengthScale = false);
463
464 /// Remove a sphere.
465 void removeSphere(const VisuID& id);
466
467
468 /// Draw an arrow with position (start) and direction.
469 void drawArrow(const VisuID& id,
470 const Eigen::Vector3f& position,
471 const Eigen::Vector3f& direction,
472 float length,
473 float width,
474 const DrawColor& color = DEFAULTS.colorArrow,
475 bool ignoreLengthScale = false);
476
477 /// Draw an arrow with start and end.
478 void drawArrowFromTo(const VisuID& id,
479 const Eigen::Vector3f& from,
480 const Eigen::Vector3f& to,
481 float width,
482 const DrawColor& color = DEFAULTS.colorArrow,
483 bool ignoreLengthScale = false);
484
485 /// Remove an arrow.
486 void removeArrow(const VisuID& id);
487
488
489 /// Draw a polygon.
490 void drawPolygon(const VisuID& id,
491 const std::vector<Eigen::Vector3f>& points,
492 const DrawColor& colorFace,
493 float lineWidth = 0,
494 const DrawColor& colorEdge = DEFAULTS.colorPolygonEdge,
495 bool ignoreLengthScale = false);
496
497 /// Remove a polygon.
498 void removePolygon(const VisuID& id);
499
500
501 /// Draw a line from start to end.
502 void drawLine(const VisuID& id,
503 const Eigen::Vector3f& from,
504 const Eigen::Vector3f& to,
505 float width,
506 const DrawColor& color = DEFAULTS.colorLine,
507 bool ignoreLengthScale = false);
508
509 /// Remove a line.
510 void removeLine(const VisuID& id);
511
512
513 /// Draw a line set.
514 void drawLineSet(const VisuID& id,
515 const DebugDrawerLineSet& lineSet,
516 bool ignoreLengthScale = false);
517
518 /**
519 * @brief Draw a set of lines with constant color.
520 * @param points List of start and end points [ s1, e1, s2, e2, ..., sn, en ].
521 */
522 void drawLineSet(const VisuID& id,
523 const std::vector<Eigen::Vector3f>& points,
524 float width,
525 const DrawColor& color = DEFAULTS.colorLine,
526 bool ignoreLengthScale = false);
527
528 /**
529 * @brief Draw a set of lines with constant color.
530 * @param points List of start and end points [ s1, e1, s2, e2, ..., sn, en ].
531 * @param colors List of line colors [ c1, c2, ..., cn ].
532 */
533 void drawLineSet(const VisuID& id,
534 const std::vector<Eigen::Vector3f>& points,
535 float width,
536 const DrawColor& colorA,
537 const DrawColor& colorB,
538 const std::vector<float>& intensitiesB,
539 bool ignoreLengthScale = false);
540
541 /// Remove a line set.
542 void removeLineSet(const VisuID& id);
543
544
545 // POSE
546
547 /// Draw a pose (with the preset scale).
548 void
549 drawPose(const VisuID& id, const Eigen::Matrix4f& pose, bool ignoreLengthScale = false);
550 /// Draw a pose (with the preset scale).
551 void drawPose(const VisuID& id,
552 const Eigen::Vector3f& pos,
553 const Eigen::Quaternionf& ori,
554 bool ignoreLengthScale = false);
555
556 /// Draw a pose with the given scale.
557 void drawPose(const VisuID& id,
558 const Eigen::Matrix4f& pose,
559 float scale,
560 bool ignoreLengthScale = false);
561 /// Draw a pose with the given scale.
562 void drawPose(const VisuID& id,
563 const Eigen::Vector3f& pos,
564 const Eigen::Quaternionf& ori,
565 float scale,
566 bool ignoreLengthScale = false);
567
568 /// Remove a pose.
569 void removePose(const VisuID& id);
570
571
572 // ROBOT
573
574 /**
575 * @brief Draw a robot.
576 * Afterwards, `updateRobot*()` methods can be used with the same VisuID.
577 *
578 * @param robotFile The robot file. Either an absolute path, or a path
579 * relative to the data directory of the ArmarX project specified by `armarxProject`.
580 * @param armarxProject The name of the ArmarX project keeping the robot model.
581 * @param drawStyle The draw style (full or collision model).
582 */
583 void drawRobot(const VisuID& id,
584 const std::string& robotFile,
585 const std::string& armarxProject,
586 armarx::DrawStyle drawStyle = armarx::DrawStyle::FullModel);
587
588 /// Update / set the robot pose.
589 void
590 updateRobotPose(const VisuID& id, const Eigen::Matrix4f& pose, bool ignoreScale = false);
591
592 /// Update / set the robot pose.
593 void updateRobotPose(const VisuID& id,
594 const Eigen::Vector3f& pos,
595 const Eigen::Quaternionf& ori,
596 bool ignoreScale = false);
597
598 /// Update / set the robot configuration (joint angles).
599 void updateRobotConfig(const VisuID& id, const std::map<std::string, float>& config);
600
601 /// Update / set the robot color.
602 void updateRobotColor(const VisuID& id, const DrawColor& color);
603 /// Update / set the color of a robot node.
604 void
605 updateRobotNodeColor(const VisuID& id, const std::string& nodeName, const DrawColor& color);
606
607 /// Remove a robot visualization.
608 void removeRobot(const VisuID& id);
609
610
611 // TRI MESH
612
613 /// Draw a TriMeshModel as DebugDrawerTriMesh.
614 void drawTriMesh(const VisuID& id,
615 const VirtualRobot::TriMeshModel& triMesh,
616 const DrawColor& color = {.5, .5, .5, 1},
617 bool ignoreLengthScale = false);
618
619 /// Draw a TriMeshModel as individual polygons.
620 void drawTriMeshAsPolygons(const VisuID& id,
621 const VirtualRobot::TriMeshModel& trimesh,
622 const DrawColor& colorFace = DEFAULTS.colorPolygonFace,
623 float lineWidth = 0,
624 const DrawColor& colorEdge = DEFAULTS.colorPolygonEdge,
625 bool ignoreLengthScale = false);
626
627 /// Draw a TriMeshModel as individual polygons, transformed by the given pose.
628 void drawTriMeshAsPolygons(const VisuID& id,
629 const VirtualRobot::TriMeshModel& trimesh,
630 const Eigen::Matrix4f& pose,
631 const DrawColor& colorFace = DEFAULTS.colorPolygonFace,
632 float lineWidth = 0,
633 const DrawColor& colorEdge = DEFAULTS.colorPolygonEdge,
634 bool ignoreLengthScale = false);
635
636 /// Draw a TriMeshModel as individual polygons with individual face colors.
637 void drawTriMeshAsPolygons(const VisuID& id,
638 const VirtualRobot::TriMeshModel& trimesh,
639 const std::vector<DrawColor>& faceColorsInner,
640 float lineWidth = 0,
641 const DrawColor& colorEdge = DEFAULTS.colorPolygonEdge,
642 bool ignoreLengthScale = false);
643
644
645 // POINT CLOUD
646 /* (By templating these functions, we can make them usable for PCL
647 * point clouds without a dependency on PCL.)
648 */
649
650 /**
651 * @brief Draw a unicolored point cloud.
652 *
653 * `pointCloud` must be iterable and its elements must provide members `x, y, z`.
654 */
655 template <class PointCloudT>
656 void drawPointCloud(const VisuID& id,
657 const PointCloudT& pointCloud,
658 const DrawColor& color = DEFAULTS.colorPointCloud,
659 float pointSize = DEFAULTS.pointCloudPointSize,
660 bool ignoreLengthScale = false);
661
662 /**
663 * @brief Draw a colored point cloud with RGBA information.
664 *
665 * `pointCloud` must be iterable and its elements must provide
666 * members `x, y, z, r, g, b, a`.
667 */
668 template <class PointCloudT>
669 void drawPointCloudRGBA(const VisuID& id,
670 const PointCloudT& pointCloud,
671 float pointSize = DEFAULTS.pointCloudPointSize,
672 bool ignoreLengthScale = false);
673
674 /**
675 * @brief Draw a colored point cloud with colors according to labels.
676 *
677 * `pointCloud` must be iterable and its elements must provide
678 * members `x, y, z, label`.
679 */
680 template <class PointCloudT>
681 void drawPointCloudLabeled(const VisuID& id,
682 const PointCloudT& pointCloud,
683 float pointSize = DEFAULTS.pointCloudPointSize,
684 bool ignoreLengthScale = false);
685
686 /**
687 * @brief Draw a colored point cloud with custom colors.
688 *
689 * `pointCloud` must be iterable and its elements must provide
690 * members `x, y, z`.
691 * The color of a point is specified by `colorFunc`, which must be
692 * a callable taking an element of `pointCloud` and returning its
693 * color as `armarx::DrawColor`.
694 */
695 template <class PointCloudT, class ColorFuncT>
696 void drawPointCloud(const VisuID& id,
697 const PointCloudT& pointCloud,
698 const ColorFuncT& colorFunc,
699 float pointSize = DEFAULTS.pointCloudPointSize,
700 bool ignoreLengthScale = false);
701
702
703 // Debug Drawer Point Cloud Types
704
705 /// Draw a non-colored point cloud.
706 void drawPointCloud(const VisuID& id, const DebugDrawerPointCloud& pointCloud);
707
708 /// Draw a colored point cloud.
709 void drawPointCloud(const VisuID& id, const DebugDrawerColoredPointCloud& pointCloud);
710
711 /// Draw a 24 bit colored point cloud.
712 void drawPointCloud(const VisuID& id, const DebugDrawer24BitColoredPointCloud& pointCloud);
713
714
715 /// Forces the "deletion" of a point cloud by drawing an empty one.
716 void clearColoredPointCloud(const VisuID& id);
717
718
719 // CUSTOM
720
721 /**
722 * @brief Draw a quad representing the floor.
723 * @param at the quad'S center
724 * @param up the up direction (normal of the floor plane)
725 * @param size the quad's edge length
726 */
727 void drawFloor(const VisuID& id = {"floor"},
728 const Eigen::Vector3f& at = Eigen::Vector3f::Zero(),
729 const Eigen::Vector3f& up = Eigen::Vector3f::UnitZ(),
730 float size = 5,
731 const DrawColor& color = DEFAULTS.colorFloor,
732 bool ignoreLengthScale = false);
733
734
735 // OPERATORS
736
737 /// Indicate whether visualization is enabled.
738 /// @see `enabled()`
739 operator bool() const;
740
741 /// Conversion operator to DebugDrawerInterfacePrx.
742 operator DebugDrawerInterfacePrx&();
743 operator const DebugDrawerInterfacePrx&() const;
744
745 /// Pointer member access operator to access the raw debug drawer proxy.
747 const DebugDrawerInterfacePrx& operator->() const;
748
749
750 public: // STATIC
751 /**
752 * @brief Convert a RGB color to HSV.
753 * @param rgb RGB color as [r, g, b] with r, g, b in [0, 1].
754 * @return HSV color as [h, s, v] with h in [0 deg, 360 deg] and s, v in [0, 1].
755 */
756 static Eigen::Vector3f rgb2hsv(const Eigen::Vector3f& rgb);
757
758 /**
759 * @brief Convert a HSV color RGB.
760 * @param HSV color as [h, s, v] with h in [0 deg, 360 deg] and s, v in [0, 1].
761 * @return RGB color as [r, g, b] with r, g, b in [0, 1].
762 */
763 static Eigen::Vector3f hsv2rgb(const Eigen::Vector3f& hsv);
764
765
766 /**
767 * @brief Construct a DrawColor from the given color type.
768 *
769 * The used color type must have members named `r`, `g` and `b`.
770 * Applicable types include:
771 * - pcl::RGB (byteToFloat = true)
772 * - armarx::DrawColor (useful to get a color with a different alpha)
773 *
774 * @param alpha the alpha (default: 1)
775 * @param byteToFloat If true, scale from range [0, 255] to [0, 1]
776 */
777 template <class ColorT>
778 static DrawColor
779 toDrawColor(const ColorT& color, float alpha = 1, bool byteToFloat = false);
780
781
782 /// Get a color from the Glasbey look-up-table.
783 static DrawColor getGlasbeyLUTColor(int id, float alpha = 1.f);
784 static DrawColor getGlasbeyLUTColor(uint32_t id, float alpha = 1.f);
785 static DrawColor getGlasbeyLUTColor(std::size_t id, float alpha = 1.f);
786
787
788 private:
789 /// Get the layer to draw on. (passedLayer if not empty, _layer otherwise).
790 const std::string& layer(const std::string& passedLayer) const;
791
792 /// Get the layer to draw on. (id.layer if not empty, _layer otherwise).
793 const std::string& layer(const VisuID& id) const;
794
795
796 /// Return _lengthScale if ignore is false (default), 1 otherwise.
797 float lengthScale(bool ignore = false) const;
798
799 /// Scale the value.
800 static float scaled(float scale, float value);
801 /// Scale the given vector and return it as Vector3 pointer.
802 static Vector3BasePtr scaled(float scale, const Eigen::Vector3f& vector);
803 /// Scale the translation of the given pose and return it as Pose pointer.
804 static PoseBasePtr scaled(float scale, const Eigen::Matrix4f& pose);
805
806 /// Scale the given vector and return it as `ScaledT`.
807 /// The constructor of `ScaledT` must take the x, y and z coordinates.
808 template <class ScaledT>
809 static ScaledT scaledT(float scale, const Eigen::Vector3f& vector);
810
811 /// Scale a value with .x, .y and .z attributes in-place.
812 template <class XYZT>
813 static void scaleXYZ(float scale, XYZT& xyz);
814
815
816 private:
817 /// The name of the debug drawer topic.
818 static const std::string TOPIC_NAME;
819 /// The default layer ("debug").
820 static const std::string DEFAULT_LAYER;
821
822
823 /// The debug drawer topic.
824 DebugDrawerInterfacePrx topic = nullptr;
825
826 /// Whether drawing is enabled. (In comination with `topic`.
827 bool _enabled = true;
828
829 /// The default layer (used if none is passed to the method).
830 std::string _layer = DEFAULT_LAYER;
831
832 /// Scaling for positions, lengths and distances.
833 float _lengthScale = 1;
834
835 /// Scaling for pose visualization (1 is good when drawing in millimeters).
836 float _poseScale = 1;
837
838 /// The duration for shortSleep().
839 std::chrono::milliseconds _shortSleepDuration{100};
840 };
841
842 template <typename DurationT>
843 void
844 DebugDrawerTopic::sleepFor(const DurationT& duration)
845 {
846 if (enabled())
847 {
848 std::this_thread::sleep_for(duration);
849 }
850 }
851
852 template <typename DurationT>
853 void
855 {
856 this->_shortSleepDuration = std::chrono::duration_cast<std::chrono::milliseconds>(duration);
857 }
858
859 template <class ColorT>
860 DrawColor
861 DebugDrawerTopic::toDrawColor(const ColorT& color, float alpha, bool byteToFloat)
862 {
863 const float scale = byteToFloat ? (1 / 255.f) : 1;
864 return {color.r * scale, color.g * scale, color.b * scale, alpha};
865 }
866
867 template <class PointCloudT>
868 void
870 const PointCloudT& pointCloud,
871 const DrawColor& color,
872 float pointSize,
873 bool ignoreLengthScale)
874 {
876 id, pointCloud, [&color](const auto&) { return color; }, pointSize, ignoreLengthScale);
877 }
878
879 template <class PointCloudT>
880 void
882 const PointCloudT& pointCloud,
883 float pointSize,
884 bool ignoreLengthScale)
885 {
887 id,
888 pointCloud,
889 [](const auto& p) { return toDrawColor(p, p.a); },
890 pointSize,
891 ignoreLengthScale);
892 }
893
894 template <class PointCloudT>
895 void
897 const PointCloudT& pointCloud,
898 float pointSize,
899 bool ignoreLengthScale)
900 {
902 id,
903 pointCloud,
904 [](const auto& p) { return getGlasbeyLUTColor(p.label); },
905 pointSize,
906 ignoreLengthScale);
907 }
908
909 template <class PointCloudT, class ColorFuncT>
910 void
912 const PointCloudT& pointCloud,
913 const ColorFuncT& colorFn,
914 float pointSize,
915 bool ignoreLengthScale)
916 {
917 if (!enabled())
918 {
919 return;
920 }
921
922 const float lf = ignoreLengthScale ? 1.0 : _lengthScale;
923
924 DebugDrawerColoredPointCloud dd;
925 dd.points.reserve(pointCloud.size());
926
927 dd.pointSize = pointSize;
928
929 for (const auto& p : pointCloud)
930 {
931 dd.points.push_back(
932 DebugDrawerColoredPointCloudElement{lf * p.x, lf * p.y, lf * p.z, colorFn(p)});
933 }
934
935 drawPointCloud(id, dd);
936 }
937
938 template <class ScaledT>
939 ScaledT
940 DebugDrawerTopic::scaledT(float scale, const Eigen::Vector3f& vector)
941 {
942 auto scaled = vector * scale;
943 return {scaled.x(), scaled.y(), scaled.z()};
944 }
945
946 template <class XYZT>
947 void
948 DebugDrawerTopic::scaleXYZ(float scale, XYZT& xyz)
949 {
950 xyz.x *= scale;
951 xyz.y *= scale;
952 xyz.z *= scale;
953 }
954
955} // namespace armarx
void removeLine(const VisuID &id)
Remove a line.
void drawLine(const VisuID &id, const Eigen::Vector3f &from, const Eigen::Vector3f &to, float width, const DrawColor &color=DEFAULTS.colorLine, bool ignoreLengthScale=false)
Draw a line from start to end.
void updateRobotColor(const VisuID &id, const DrawColor &color)
Update / set the robot color.
void shortSleep()
Sleep for the shortSleepDuration. Useful after clearing.
static DrawColor getGlasbeyLUTColor(int id, float alpha=1.f)
Get a color from the Glasbey look-up-table.
static DrawColor toDrawColor(const ColorT &color, float alpha=1, bool byteToFloat=false)
Construct a DrawColor from the given color type.
void setShortSleepDuration(const DurationT &duration)
Set the duration for "short sleeps".
void drawCylinderFromTo(const VisuID &id, const Eigen::Vector3f &from, const Eigen::Vector3f &to, float radius, const DrawColor &color=DEFAULTS.colorCylinder, bool ignoreLengthScale=false)
Draw a cylinder from start to end.
void setEnabled(bool enabled)
Set whether drawing is enabled.
void drawPointCloudLabeled(const VisuID &id, const PointCloudT &pointCloud, float pointSize=DEFAULTS.pointCloudPointSize, bool ignoreLengthScale=false)
Draw a colored point cloud with colors according to labels.
const std::string & getLayer() const
Get the default layer (used if no layer is passed to a method).
float getLengthScale() const
Get the scaling for positions, lengths and distances.
DebugDrawerTopic(const std::string &layer=DEFAULT_LAYER)
Construct without topic, and optional layer.
void removeSphere(const VisuID &id)
Remove a sphere.
void drawPolygon(const VisuID &id, const std::vector< Eigen::Vector3f > &points, const DrawColor &colorFace, float lineWidth=0, const DrawColor &colorEdge=DEFAULTS.colorPolygonEdge, bool ignoreLengthScale=false)
Draw a polygon.
void removePolygon(const VisuID &id)
Remove a polygon.
void drawArrow(const VisuID &id, const Eigen::Vector3f &position, const Eigen::Vector3f &direction, float length, float width, const DrawColor &color=DEFAULTS.colorArrow, bool ignoreLengthScale=false)
Draw an arrow with position (start) and direction.
void sleepFor(const DurationT &duration)
If enabled, sleep for the given duration (e.g. a chrono duration).
void setLayer(const std::string &layer)
Set the default layer (used if no layer is passed to a method).
void setPoseScaleMeters()
Set the pose scale to 0.001 (good when drawing in meters).
void drawTriMeshAsPolygons(const VisuID &id, const VirtualRobot::TriMeshModel &trimesh, const DrawColor &colorFace=DEFAULTS.colorPolygonFace, float lineWidth=0, const DrawColor &colorEdge=DEFAULTS.colorPolygonEdge, bool ignoreLengthScale=false)
Draw a TriMeshModel as individual polygons.
void removeArrow(const VisuID &id)
Remove an arrow.
void drawFloor(const VisuID &id={"floor"}, const Eigen::Vector3f &at=Eigen::Vector3f::Zero(), const Eigen::Vector3f &up=Eigen::Vector3f::UnitZ(), float size=5, const DrawColor &color=DEFAULTS.colorFloor, bool ignoreLengthScale=false)
Draw a quad representing the floor.
void drawPointCloud(const VisuID &id, const PointCloudT &pointCloud, const DrawColor &color=DEFAULTS.colorPointCloud, float pointSize=DEFAULTS.pointCloudPointSize, bool ignoreLengthScale=false)
Draw a unicolored point cloud.
void removePose(const VisuID &id)
Remove a pose.
void clearLayer(bool sleep=false)
Clear the (set default) layer.
void updateRobotNodeColor(const VisuID &id, const std::string &nodeName, const DrawColor &color)
Update / set the color of a robot node.
void drawLineSet(const VisuID &id, const DebugDrawerLineSet &lineSet, bool ignoreLengthScale=false)
Draw a line set.
void drawArrowFromTo(const VisuID &id, const Eigen::Vector3f &from, const Eigen::Vector3f &to, float width, const DrawColor &color=DEFAULTS.colorArrow, bool ignoreLengthScale=false)
Draw an arrow with start and end.
void drawPose(const VisuID &id, const Eigen::Matrix4f &pose, bool ignoreLengthScale=false)
Draw a pose (with the preset scale).
void drawSphere(const VisuID &id, const Eigen::Vector3f &center, float radius, const DrawColor &color=DEFAULTS.colorSphere, bool ignoreLengthScale=false)
Draw a sphere.
void drawCylinder(const VisuID &id, const Eigen::Vector3f &center, const Eigen::Vector3f &direction, float length, float radius, const DrawColor &color=DEFAULTS.colorCylinder, bool ignoreLengthScale=false)
Draw a cylinder with center and direction.
void setLengthScaleMetersToMillimeters()
Set the scale for positions, lengths and distances to 1000.
void setPoseScale(float scale)
Set the scale for pose visualization. This value will be used for all successive calls to drawPose().
void setPoseScaleMillimeters()
Set the pose scale to 1 (good when drawing in millimeters).
static const Defaults DEFAULTS
void removeboxEdges(const VisuID &id)
Remove box edges (as a line set).
void drawPointCloudRGBA(const VisuID &id, const PointCloudT &pointCloud, float pointSize=DEFAULTS.pointCloudPointSize, bool ignoreLengthScale=false)
Draw a colored point cloud with RGBA information.
DebugDrawerInterfacePrx getTopic() const
Get the topic.
void drawText(const VisuID &id, const Eigen::Vector3f &position, const std::string &text, int size=10, const DrawColor color=DEFAULTS.colorText, bool ignoreLengthScale=false)
Draw text at the specified position.
void removeBox(const VisuID &id)
Remove a box.
void drawBoxEdges(const VisuID &id, const Eigen::Vector3f &position, const Eigen::Quaternionf &orientation, const Eigen::Vector3f &extents, float width=DEFAULTS.boxEdgesWidth, const DrawColor &color=DEFAULTS.boxEdgesColor, bool ignoreLengthScale=false)
Draw box edges (as a line set).
void removeCylinder(const VisuID &id)
Remove a cylinder.
void setTopic(const DebugDrawerInterfacePrx &topic)
Set the topic.
void updateRobotPose(const VisuID &id, const Eigen::Matrix4f &pose, bool ignoreScale=false)
Update / set the robot pose.
void removeLineSet(const VisuID &id)
Remove a line set.
void removeRobot(const VisuID &id)
Remove a robot visualization.
void clearColoredPointCloud(const VisuID &id)
Forces the "deletion" of a point cloud by drawing an empty one.
void clearAll(bool sleep=false)
Clear all layers.
void setLengthScale(float scale)
Set the scale for positions, lengths and distances.
static Eigen::Vector3f hsv2rgb(const Eigen::Vector3f &hsv)
Convert a HSV color RGB.
static Eigen::Vector3f rgb2hsv(const Eigen::Vector3f &rgb)
Convert a RGB color to HSV.
float getPoseScale() const
Get the scale for pose visualization.
void updateRobotConfig(const VisuID &id, const std::map< std::string, float > &config)
Update / set the robot configuration (joint angles).
DebugDrawerInterfacePrx & operator->()
Pointer member access operator to access the raw debug drawer proxy.
void drawRobot(const VisuID &id, const std::string &robotFile, const std::string &armarxProject, armarx::DrawStyle drawStyle=armarx::DrawStyle::FullModel)
Draw a robot.
bool enabled() const
Indicate whether visualization is enabled, i.e. a topic is set and enabled flag is set.
void drawTriMesh(const VisuID &id, const VirtualRobot::TriMeshModel &triMesh, const DrawColor &color={.5,.5,.5, 1}, bool ignoreLengthScale=false)
Draw a TriMeshModel as DebugDrawerTriMesh.
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.
void offeringTopic(ManagedIceObject &component, const std::string &topicNameOverride="") const
Call offeringTopic([topicName]) on the given component.
void setLengthScaleMillimetersToMeters()
Set the scale for positions, lengths and distances to 0.001.
The ManagedIceObject is the base class for all ArmarX objects.
Quaternion< float, 0 > Quaternionf
Matrix< float, 3, 2 > Matrix32f
A 3x2 matrix.
This file offers overloads of toIce() and fromIce() functions for STL container types.
pcl::PointCloud< PointT > PointCloudT
Definition Common.h:32
::IceInternal::ProxyHandle<::IceProxy::armarx::DebugDrawerInterface > DebugDrawerInterfacePrx
Default values for drawing functions.
VisuID(const Source &name)
Construct a VisuID from a non-std::string source (e.g. char[]).
VisuID withName(const std::string &name) const
Get a VisuID with the given name and same layer as `*this.
std::string layer
The layer name (empty by default).
std::string name
The visu name (empty by default).
friend std::ostream & operator<<(std::ostream &os, const VisuID &rhs)
Streams a short human-readable description of rhs to os.