GraphVisualizerGuiPlugin.cpp
Go to the documentation of this file.
1/*
2 * This file is part of ArmarX.
3 *
4 * Copyright (C) 2011-2016, High Performance Humanoid Technologies (H2T), Karlsruhe Institute of Technology (KIT), all rights reserved.
5 *
6 * ArmarX is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 *
10 * ArmarX is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 *
18 * @package
19 * @author
20 * @date
21 * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
22 * GNU General Public License
23 */
24
26
27#include <VirtualRobot/MathTools.h>
28
30
31
32//armar
34
36
37// Qt headers
38#include <QHBoxLayout>
39#include <QLabel>
40#include <QLineEdit>
41#include <QMenu>
42#include <QPushButton>
43#include <Qt>
44#include <QtGlobal>
45
46
47//std
48#include <filesystem>
49#include <fstream>
50#include <memory>
51#include <sstream>
52#include <tuple>
53#include <unordered_set>
54
55#include <MemoryX/gui-plugins/GraphVisualizerPlugin/ui_GraphVisualizerConfigDialog.h>
56
57//#include <VirtualRobot/VirtualRobotCommon.h>
58
59using namespace memoryx;
60
61using namespace VirtualRobot;
62
63//static values and helper functions
64#define DEFAULT_PRIOR_KNOWLEDGE_NAME "PriorKnowledge"
65#define DEFAULT_DEBUG_DRAWER_NAME "DebugDrawerUpdates"
66#define DEFAULT_DEBUG_DRAWER_LAYER_NAME "DebugDrawerUpdates_Graph"
67
68/**
69 * @brief The default width of lines drawn onto the debug layer and scene.
70 */
71static const ::Ice::Float LINE_WIDTH_DEFAULT = 5;
72/**
73 * @brief The width of selected lines drawn onto the debug layer and scene.
74 */
75static const ::Ice::Float LINE_WIDTH_SELECTED = 10;
76
77/**
78 * @brief The default color of lines drawn onto the debug layer and scene.
79 */
80static const ::armarx::DrawColor COLOR_DEFAULT = {0.5f, 0.5f, 1.f, 0.2f};
81/**
82 * @brief The color of highlighted lines drawn onto the debug layer and scene.
83 */
84static const ::armarx::DrawColor COLOR_HIGHLIGHT = {1.f, 0.0f, 0.f, 1.f};
85
86/**
87 * @brief The scale factor for elements drawn onto the scene.
88 */
89static const float SCENE_SCALE_FACTOR = 2;
90/**
91 * @brief The scale factor for nodes drawn onto the scene.
92 */
93static const float SCENE_NODES_SCALE_FACTOR = 3 * SCENE_SCALE_FACTOR;
94/**
95 * @brief The scale factor for edges drawn onto the scene.
96 */
97static const float SCENE_LINE_SCALE_FACTOR = SCENE_SCALE_FACTOR;
98
99/**
100 * @brief The increment used when a rotation button is pressed.
101 *
102 * A positive rotation is counter clockwise.
103 * This value should be positive.
104 *
105 * rotation buttons: GraphVisualizerWidget::ui.buttonRotateClock and
106 * GraphVisualizerWidget::ui.buttonRotateCounterClock
107 */
108static const float VIEW_ROTATE_STEP_SIZE_CC = 45;
109
110static const QString SETTING_LAST_SCENE = "lastScene";
111
112/**
113 * @brief Returns the name used on the debug layer.
114 * @param edge The edge.
115 * @return The name used on the debug layer.
116 */
117inline std::string
119{
120 std::stringstream s;
121 s << "edge_" << edge.first << "_" << edge.second;
122 return s.str();
123}
124
125/**
126 * @brief iceName Returns the name used on the debug layer.
127 * @param nodeName The node.
128 * @return The name used on the debug layer.
129 */
130inline std::string
132{
133 return nodeName;
134}
135
136//gui plugin
141
142//widget
143
145 debugDrawerTopicName{DEFAULT_DEBUG_DRAWER_NAME},
146 viewAngle{0},
147 debugDrawerLayerName{DEFAULT_DEBUG_DRAWER_LAYER_NAME},
148 priorKnowledgeProxyName{DEFAULT_PRIOR_KNOWLEDGE_NAME},
149 settings{"KIT", "GraphVisualizerGuiPlugin"}
150{
152 editStartNodeNext = true;
153
154 // init gui
155 ui.setupUi(getWidget());
156 //add scene
157 std::unique_ptr<QGraphicsScene> scenePtr{new QGraphicsScene};
158 scene = scenePtr.get();
159 ui.graphicsViewGraph->setScene(scenePtr.release());
161 ui.graphicsViewGraph->installEventFilter(mep);
162 //transform view
163 transformView();
164}
165
170
171void
173{
174 ARMARX_VERBOSE << "init start";
175 usingProxy(priorKnowledgeProxyName);
176 usingProxy("GraphNodePoseResolver");
177 offeringTopic(debugDrawerTopicName);
178 ARMARX_VERBOSE << "init done";
179}
180
181void
183{
184 ARMARX_VERBOSE << "connecting";
185 debugDrawer = getTopic<armarx::DebugDrawerInterfacePrx>(debugDrawerTopicName);
186 priorKnowledgePrx = getProxy<memoryx::PriorKnowledgeInterfacePrx>(priorKnowledgeProxyName);
187 getProxy(gnpr, "GraphNodePoseResolver");
188
189 if (priorKnowledgePrx->hasGraphSegment())
190 {
191 ARMARX_VERBOSE << "get Proxy to graph segment";
192 graphSeg = priorKnowledgePrx->getGraphSegment();
193 ui.sceneGroupBox->setEnabled(true);
194 ui.sceneGroupBox->setTitle("Scenes from graph memory segment");
195
196 ui.b->setEnabled(true);
197 }
198 else
199 {
200 ui.sceneGroupBox->setEnabled(false);
201 ui.sceneGroupBox->setTitle(
202 "Scenes from graph memory segment (No graph memory segment available)");
203
204 ui.b->setEnabled(false);
205 }
206
207 ui.tableWidgetNodes->horizontalHeader()->setResizeMode(QHeaderView::ResizeToContents);
208 ui.tableWidgetEdges->horizontalHeader()->setResizeMode(QHeaderView::Stretch);
209
210 ui.tableWidgetNodes->setContextMenuPolicy(Qt::CustomContextMenu);
211 ui.tableWidgetEdges->setContextMenuPolicy(Qt::CustomContextMenu);
212
213 //todo remove test function
214 QObject::connect(ui.b, SIGNAL(clicked()), this, SLOT(addKitchenGraph()), Qt::UniqueConnection);
215
216 //tables
217 QObject::connect(ui.tableWidgetNodes,
218 SIGNAL(cellDoubleClicked(int, int)),
219 this,
220 SLOT(nodeTableDoubleClicked(int, int)),
221 Qt::UniqueConnection);
222 QObject::connect(ui.tableWidgetNodes,
223 SIGNAL(customContextMenuRequested(QPoint)),
224 this,
226 Qt::UniqueConnection);
227 QObject::connect(ui.tableWidgetEdges,
228 SIGNAL(cellDoubleClicked(int, int)),
229 this,
230 SLOT(edgeTableDoubleClicked(int, int)),
231 Qt::UniqueConnection);
232 QObject::connect(ui.tableWidgetEdges,
233 SIGNAL(customContextMenuRequested(QPoint)),
234 this,
236 Qt::UniqueConnection);
237
238 QObject::connect(
239 ui.btnAdd, SIGNAL(clicked()), this, SLOT(addNewGraphNode()), Qt::UniqueConnection);
240 QObject::connect(
241 ui.btnAddEdge, SIGNAL(clicked()), this, SLOT(addNewEdgeBoth()), Qt::UniqueConnection);
242 QObject::connect(ui.btnAddEdgeStartEnd,
243 SIGNAL(clicked()),
244 this,
245 SLOT(addNewEdgeStartEnd()),
246 Qt::UniqueConnection);
247 QObject::connect(ui.btnAddEdgeEndStart,
248 SIGNAL(clicked()),
249 this,
250 SLOT(addNewEdgeEndStart()),
251 Qt::UniqueConnection);
252 QObject::connect(
253 ui.btnEdit, SIGNAL(clicked()), this, SLOT(editGraphNode()), Qt::UniqueConnection);
254
255 //zoom
256 QObject::connect(ui.viewZoomFactor,
257 SIGNAL(valueChanged(double)),
258 this,
259 SLOT(transformView()),
260 Qt::UniqueConnection);
261 //rota
262 QObject::connect(ui.buttonRotateClock,
263 SIGNAL(clicked()),
264 this,
265 SLOT(viewRotatedClock()),
266 Qt::UniqueConnection);
267 QObject::connect(ui.buttonRotateCounterClock,
268 SIGNAL(clicked()),
269 this,
270 SLOT(viewRotatedCounterClock()),
271 Qt::UniqueConnection);
272 //redraw+clear
273 QObject::connect(
274 ui.buttonRedraw, SIGNAL(clicked()), this, SLOT(redraw()), Qt::UniqueConnection);
275 QObject::connect(
276 ui.buttonClear, SIGNAL(clicked()), this, SLOT(clearGraph()), Qt::UniqueConnection);
277 //auto adjust
278 QObject::connect(
279 ui.buttonAutoAdjust, SIGNAL(clicked()), this, SLOT(adjustView()), Qt::UniqueConnection);
280 //memory
281 QObject::connect(ui.refreshScenesButton,
282 SIGNAL(clicked()),
283 this,
284 SLOT(updateSceneList()),
285 Qt::UniqueConnection);
286 QObject::connect(ui.drawSceneButton,
287 SIGNAL(clicked()),
288 this,
289 SLOT(drawScene()),
290 Qt::UniqueConnection); //BUTTON LOAD
291 QObject::connect(ui.scenesComboBox,
292 SIGNAL(currentIndexChanged(int)),
293 this,
294 SLOT(selectedSceneChanged(int)),
295 Qt::UniqueConnection);
296
297 ARMARX_VERBOSE << "connected";
298
299 updateSceneList();
300}
301
302void
306
307QPointer<QDialog>
309{
310 if (!dialog)
311 {
312 dialog = new GraphVisualizerConfigDialog(parent);
313 }
314
315 dialog->ui->editDebugDrawerProxyName->setText(QString::fromStdString(debugDrawerTopicName));
316 dialog->ui->editDebugDrawerLayerName->setText(QString::fromStdString(debugDrawerLayerName));
317 dialog->ui->editPriorKnowledgeProxyName->setText(
318 QString::fromStdString(priorKnowledgeProxyName));
319 return qobject_cast<GraphVisualizerConfigDialog*>(dialog);
320}
321
322void
324{
325 debugDrawerTopicName = dialog->ui->editDebugDrawerProxyName->text().toStdString();
326 debugDrawerLayerName = dialog->ui->editDebugDrawerLayerName->text().toStdString();
327 priorKnowledgeProxyName = dialog->ui->editPriorKnowledgeProxyName->text().toStdString();
328}
329
330void
332{
333 debugDrawerTopicName =
334 settings->value("debugDrawerTopicName", QString::fromStdString(debugDrawerTopicName))
335 .toString()
336 .toStdString();
337 debugDrawerLayerName =
338 settings->value("debugDrawerLayerName", QString::fromStdString(debugDrawerLayerName))
339 .toString()
340 .toStdString();
341}
342
343void
345{
346 settings->setValue("debugDrawerTopicName", QString::fromStdString(debugDrawerTopicName));
347 settings->setValue("debugDrawerLayerName", QString::fromStdString(debugDrawerLayerName));
348}
349
350void
352{
353 lastSelectedSceneName = settings.value(SETTING_LAST_SCENE, lastSelectedSceneName).toString();
354}
355
356void
358{
359 settings.setValue(SETTING_LAST_SCENE, lastSelectedSceneName);
360}
361
362void
363GraphVisualizerWidget::addEdge(const std::string& node1Id,
364 const std::string& node2Id,
365 const Ice::Current&)
366{
367 if (!hasNode(node1Id))
368 {
369 ARMARX_WARNING << "Edge: " << node1Id << ", " << node2Id << " can't be created! Node "
370 << node1Id << " does not exist.";
371 return;
372 }
373
374 if (!hasNode(node2Id))
375 {
376 ARMARX_WARNING << "Edge: " << node1Id << ", " << node2Id << " can't be created! Node "
377 << node2Id << " does not exist.";
378 return;
379 }
380
381 auto node1dat = nodes.at(node1Id);
382 auto node2dat = nodes.at(node2Id);
383
384 if (hasEdge(node1Id, node2Id))
385 {
386 //nothing needs to be updated
387 ARMARX_WARNING << "Edge: '" << node1dat.node->getName() << "' -> '"
388 << node2dat.node->getName() << "' already exists.";
389 return;
390 }
391
392 auto edgeId = toEdge(node1Id, node2Id);
393
394 //add
395 //table
396 int row = ui.tableWidgetEdges->rowCount();
397 ui.tableWidgetEdges->setRowCount(row + 1);
398 ui.tableWidgetEdges->setItem(
399 row, 0, new QTableWidgetItem{QString::fromStdString(node1dat.node->getName())});
400 ui.tableWidgetEdges->setItem(
401 row, 1, new QTableWidgetItem{QString::fromStdString(node2dat.node->getName())});
402 //debug layer will be done later
403 //scene
404 QGraphicsLineItem* graphicsItem = dynamic_cast<QGraphicsLineItem*>(
406 edgeId,
407 node1dat.pose->position->x,
408 -node1dat.pose->position->y,
409 node2dat.pose->position->x,
410 -node2dat.pose->position->y});
411 //auto graphicsItem= scene->addLine(node1dat.pos->x,-node1dat.pos->y,
412 // node2dat.pos->x,-node2dat.pos->y);
413 scene->addItem(graphicsItem);
414 //setToolTip on graphicsItem does not work
415 dynamic_cast<QGraphicsItem*>(graphicsItem)
416 ->setToolTip(QString{"Edge:"} + QString::fromStdString(node1dat.node->getName()) +
417 QString{" <-> "} + QString::fromStdString(node2dat.node->getName()));
418 //data
419 EdgeData data{graphicsItem, row, false};
420 edges[edgeId] = data;
421
422 updateEdge(edgeId);
423}
424
425void
426GraphVisualizerWidget::addNode(const GraphNodeBasePtr& node, const Ice::Current&)
427{
429 auto nodeId = node->getId();
430
431 armarx::FramedPosePtr globalNodePose;
432 try
433 {
434 globalNodePose = armarx::FramedPosePtr::dynamicCast(gnpr->resolveToGlobalPose(node));
435 }
436 catch (...)
437 {
438 return;
439 }
440
441 if (hasNode(nodeId))
442 {
443 NodeData& oldNode = nodes.at(nodeId);
444 ARMARX_VERBOSE << "Node: " << nodeId
445 << " was overwritten! Old: " << oldNode.pose->position->x << ", "
446 << oldNode.pose->position->y << ", " << getYawAngle(oldNode.pose)
447 << "| New: " << globalNodePose->position->x << ", "
448 << globalNodePose->position->y << ", " << getYawAngle(globalNodePose);
449 //update node data
450 //table
451 ui.tableWidgetNodes->setItem(
452 oldNode.tableWidgetNodesIndex,
453 1,
454 new QTableWidgetItem{QString::number(globalNodePose->position->x)});
455 ui.tableWidgetNodes->setItem(
456 oldNode.tableWidgetNodesIndex,
457 2,
458 new QTableWidgetItem{QString::number(globalNodePose->position->y)});
459 ui.tableWidgetNodes->setItem(
460 oldNode.tableWidgetNodesIndex,
461 3,
462 new QTableWidgetItem{QString::number(getYawAngle(globalNodePose))});
463
464 //data
465 oldNode.pose = globalNodePose;
466
467 //update connected edges
468 for (const auto& edge : edges)
469 {
470 if ((edge.first.first == nodeId) || (edge.first.second == nodeId))
471 {
472 updateEdge(edge.first);
473 }
474 }
475 }
476 else
477 {
478 //add&draw node
479 //table
480 int row = ui.tableWidgetNodes->rowCount();
481 ui.tableWidgetNodes->setRowCount(row + 1);
482 ui.tableWidgetNodes->setItem(
483 row, 0, new QTableWidgetItem{QString::fromStdString(node->getName())});
484 ui.tableWidgetNodes->setItem(
485 row, 1, new QTableWidgetItem{QString::number(globalNodePose->position->x)});
486 ui.tableWidgetNodes->setItem(
487 row, 2, new QTableWidgetItem{QString::number(globalNodePose->position->y)});
488 ui.tableWidgetNodes->setItem(
489 row, 3, new QTableWidgetItem{QString::number(getYawAngle(globalNodePose))});
490 //scene
491 QGraphicsEllipseItem* graphicsItem = dynamic_cast<QGraphicsEllipseItem*>(
493 node->getName(),
494 globalNodePose->position->x,
495 -globalNodePose->position->y,
496 0,
497 0});
498 //auto graphicsItem= scene->addEllipse(node->x,-node->y,0,0);
499 scene->addItem(graphicsItem);
500 //setToolTip on graphicsItem does not work
501 graphicsItem->setZValue(std::numeric_limits<qreal>::max());
502 dynamic_cast<QGraphicsItem*>(graphicsItem)
503 ->setToolTip(QString{"Node:"} + QString::fromStdString(node->getName()));
504
505 //data
506 NodeData data{node, globalNodePose, graphicsItem, row, false};
507 nodes.insert({nodeId, data});
508 }
509
510 updateNode(nodeId);
511}
512
513void
515{
516 for (auto& edge : edges)
517 {
518 //remove from graphics scene
519 scene->removeItem(edge.second.graphicsItem);
520 delete edge.second.graphicsItem;
521 //remove from debug layer
522 debugDrawer->removePoseVisu(debugDrawerLayerName, iceName(edge.first));
523 }
524
525 //clear table widget
526 ui.tableWidgetEdges->clearContents();
527 ui.tableWidgetEdges->setRowCount(0);
528 //clear data structures
529 edges.clear();
530}
531
532void
534{
535 //remove from debug layer
536 for (auto& edge : edges)
537 {
538 debugDrawer->removeLineVisu(debugDrawerLayerName, iceName(edge.first));
539 }
540
541 for (auto& node : nodes)
542 {
543 debugDrawer->removeArrowVisu(debugDrawerLayerName, iceName(node.first));
544 debugDrawer->removeTextVisu(debugDrawerLayerName, iceName(node.first) + "text");
545 debugDrawer->removePoseVisu(debugDrawerLayerName, iceName(node.first));
546 }
547
548 //clear scene
549 scene->clear();
550 //clear table widgets
551 ui.tableWidgetEdges->clearContents();
552 ui.tableWidgetEdges->setRowCount(0);
553 ui.tableWidgetNodes->clearContents();
554 ui.tableWidgetNodes->setRowCount(0);
555 //clear data structures
556
557 edges.clear();
558 nodes.clear();
559}
560
561void
563{
564 for (auto& edge : edges)
565 {
566 if (edge.second.highlighted)
567 {
568 edge.second.highlighted = false;
569 updateEdge(edge.first);
570 }
571 }
572
573 for (auto& node : nodes)
574 {
575 if (node.second.highlighted)
576 {
577 node.second.highlighted = false;
578 updateNode(node.first);
579 }
580 }
581}
582
583void
584GraphVisualizerWidget::updateEdge(const EdgeId& id)
585{
586 const EdgeData& data = edges.at(id);
587 auto color = (data.highlighted) ? COLOR_HIGHLIGHT : COLOR_DEFAULT;
588 QColor qColor;
589 qColor.setRedF(color.r);
590 qColor.setGreenF(color.g);
591 qColor.setBlueF(color.b);
592
593 auto lineWidth = (data.highlighted) ? LINE_WIDTH_SELECTED : LINE_WIDTH_DEFAULT;
594 armarx::Vector3Ptr posStart = new armarx::Vector3(
595 armarx::Vector3Ptr::dynamicCast(nodes.at(id.first).pose->position)->toEigen());
596 posStart->z += posStart->z < 1 ? 10 : 0;
598 armarx::Vector3Ptr::dynamicCast(nodes.at(id.second).pose->position)->toEigen());
599 posEnd->z += posEnd->z < 1 ? 10 : 0;
600 //debug layer
601 debugDrawer->setLineVisu(debugDrawerLayerName, iceName(id), posStart, posEnd, lineWidth, color);
602
603 data.graphicsItem->setLine(nodes[id.first].pose->position->x,
604 -nodes[id.first].pose->position->y,
605 nodes[id.second].pose->position->x,
606 -nodes[id.second].pose->position->y);
607
608 //scene
609 QPen pen{qColor};
610 pen.setWidthF(lineWidth * SCENE_LINE_SCALE_FACTOR);
611 data.graphicsItem->setPen(pen);
612 //table
613 QFont font{};
614 font.setBold(data.highlighted);
615 ui.tableWidgetEdges->item(data.tableWidgetEdgesIndex, 0)->setData(Qt::BackgroundRole, qColor);
616 ui.tableWidgetEdges->item(data.tableWidgetEdgesIndex, 0)->setFont(font);
617 ui.tableWidgetEdges->item(data.tableWidgetEdgesIndex, 1)->setData(Qt::BackgroundRole, qColor);
618 ui.tableWidgetEdges->item(data.tableWidgetEdgesIndex, 1)->setFont(font);
619}
620
621void
622GraphVisualizerWidget::updateNode(const NodeId& id)
623{
624 NodeData& data = nodes.at(id);
625
626 if (editStartNodeNext)
627 {
628 ui.editStartNodeId->setText(QString::fromStdString(data.node->getId()));
629 ui.editStartNodeName->setText(QString::fromStdString(data.node->getName()));
630 }
631 else
632 {
633 ui.editEndNodeId->setText(QString::fromStdString(data.node->getId()));
634 ui.editEndNodeName->setText(QString::fromStdString(data.node->getName()));
635 }
636
637 setEditFields(data);
638
639 editStartNodeNext = !editStartNodeNext;
640
641 auto color = (data.highlighted) ? COLOR_HIGHLIGHT : COLOR_DEFAULT;
642 QColor qColor;
643 qColor.setRedF(color.r);
644 qColor.setGreenF(color.g);
645 qColor.setBlueF(color.b);
646
647 auto lineWidth = (data.highlighted) ? LINE_WIDTH_SELECTED : LINE_WIDTH_DEFAULT;
648
649 //debug layer
650 float yaw = getYawAngle(data.pose) / 180 * M_PI;
651 Eigen::AngleAxisf aa(yaw, Eigen::Vector3f(0, 0, 1));
652 Eigen::Vector3f dir{0, 1, 0};
653 dir = aa.toRotationMatrix() * dir;
654 debugDrawer->setArrowVisu(debugDrawerLayerName,
655 iceName(id),
656 data.pose->position,
657 new armarx::Vector3(dir),
658 armarx::DrawColor{0, 0, 1, 1},
659 100,
660 lineWidth);
661 debugDrawer->setTextVisu(debugDrawerLayerName,
662 iceName(id) + "text",
663 data.node->getName(),
664 data.pose->position,
665 armarx::DrawColor{0, 0, 1, 1},
666 10);
667
668 //scene
669 data.graphicsItem->setPen(QPen{qColor});
670 data.graphicsItem->setBrush(QBrush{qColor});
671 data.graphicsItem->setRect(data.pose->position->x - lineWidth * SCENE_NODES_SCALE_FACTOR / 2,
672 -data.pose->position->y - lineWidth * SCENE_NODES_SCALE_FACTOR / 2,
673 lineWidth * SCENE_NODES_SCALE_FACTOR,
674 lineWidth * SCENE_NODES_SCALE_FACTOR);
675 //table
676 QFont font{};
677 font.setBold(data.highlighted);
678 ui.tableWidgetNodes->item(data.tableWidgetNodesIndex, 0)->setData(Qt::BackgroundRole, qColor);
679 ui.tableWidgetNodes->item(data.tableWidgetNodesIndex, 0)->setFont(font);
680 ui.tableWidgetNodes->item(data.tableWidgetNodesIndex, 1)->setData(Qt::BackgroundRole, qColor);
681 ui.tableWidgetNodes->item(data.tableWidgetNodesIndex, 1)->setFont(font);
682 ui.tableWidgetNodes->item(data.tableWidgetNodesIndex, 2)->setData(Qt::BackgroundRole, qColor);
683 ui.tableWidgetNodes->item(data.tableWidgetNodesIndex, 2)->setFont(font);
684 ui.tableWidgetNodes->item(data.tableWidgetNodesIndex, 3)->setData(Qt::BackgroundRole, qColor);
685 ui.tableWidgetNodes->item(data.tableWidgetNodesIndex, 3)->setFont(font);
686
687 //highlight all edges between highlighted nodes
688 std::vector<GraphNodeBasePtr> highlightedNodes;
689 for (const auto& nodeData : nodes)
690 {
691 if (nodeData.second.highlighted)
692 {
693 highlightedNodes.push_back(nodeData.second.node);
694 }
695 }
696
697 for (auto& edge : edges)
698 {
699 if (edge.second.highlighted)
700 {
701 edge.second.highlighted = false;
702 updateEdge(edge.first);
703 }
704 }
705
706 for (const auto& nodeFrom : highlightedNodes)
707 {
708 for (const auto& nodeTo : highlightedNodes)
709 {
710 const auto nodeFromId = nodeFrom->getId();
711 const auto nodeToId = nodeTo->getId();
712 if (hasEdge(nodeFromId, nodeToId))
713 {
714 auto edgeId = toEdge(nodeFromId, nodeToId);
715 auto& edge = edges[edgeId];
716 edge.highlighted = true;
717 updateEdge(edgeId);
718 }
719 }
720 }
721}
722
723float
724GraphVisualizerWidget::getYawAngle(const armarx::PoseBasePtr& pose) const
725{
726 Eigen::Vector3f rpy;
727 armarx::PosePtr p = armarx::PosePtr::dynamicCast(pose);
728 VirtualRobot::MathTools::eigen4f2rpy(p->toEigen(), rpy);
729 return VirtualRobot::MathTools::rad2deg(rpy[2]);
730}
731
732void
733GraphVisualizerWidget::highlightEdge(const std::string& node1Id,
734 const std::string& node2Id,
735 bool highlighted,
736 const Ice::Current&)
737{
738 if (!hasEdge(node1Id, node2Id))
739 {
740 ARMARX_WARNING << "No edge for: " << node1Id << " and " << node2Id << " [file: " << __FILE__
741 << " | line: " << __LINE__ << " | function: " << __PRETTY_FUNCTION__ << "]";
742 return;
743 }
744
745 EdgeId edge = toEdge(node1Id, node2Id);
746
747 if (edges.at(edge).highlighted != highlighted)
748 {
749 edges.at(edge).highlighted = highlighted;
750 updateEdge(edge);
751 }
752}
753
754void
755GraphVisualizerWidget::highlightNode(const std::string& nodeId,
756 bool highlighted,
757 const Ice::Current&)
758{
759 if (!hasNode(nodeId))
760 {
761 ARMARX_WARNING << "No node: " << nodeId << " [pushBfile: " << __FILE__
762 << " | line: " << __LINE__ << " | function: " << __PRETTY_FUNCTION__ << "]";
763 return;
764 }
765
766 if (nodes.at(nodeId).highlighted != highlighted)
767 {
768 nodes.at(nodeId).highlighted = highlighted;
769 updateNode(nodeId);
770 }
771}
772
773void
774GraphVisualizerWidget::nodeTableDoubleClicked(int row, int)
775{
776 auto nodeIt = std::find_if(nodes.cbegin(),
777 nodes.cend(),
778 [&](const std::pair<std::string, NodeData>& d)
779 {
780 // return d.second.node->getName() == ui.tableWidgetNodes->item(row, 0)->text().toStdString();
781 return d.second.tableWidgetNodesIndex == row;
782 });
783 auto nodeId = nodeIt->second.node->getId();
784 nodeDoubleClicked(nodeId);
785}
786
787void
788GraphVisualizerWidget::edgeTableDoubleClicked(int row, int)
789{
790 auto edgeIt = std::find_if(edges.cbegin(),
791 edges.cend(),
792 [&](const std::pair<EdgeId, EdgeData>& d)
793 { return d.second.tableWidgetEdgesIndex == row; });
794
795 edgeDoubleClicked(edgeIt->first);
796}
797
798void
799GraphVisualizerWidget::nodeDoubleClicked(NodeId id)
800{
801 nodes.at(id).highlighted ^= true;
802 updateNode(id);
803}
804
805void
806GraphVisualizerWidget::edgeDoubleClicked(EdgeId id)
807{
808 // edges.at(id).highlighted ^= true;
809 // updateEdge(id);
810 bool highlight = !nodes.at(id.first).highlighted && !nodes.at(id.second).highlighted;
811 nodes.at(id.first).highlighted = highlight;
812 nodes.at(id.second).highlighted = highlight;
813 updateNode(id.first);
814 updateNode(id.second);
815}
816
817void
819{
820 drawScene();
821}
822
823void
824GraphVisualizerWidget::setEditFields(const NodeData& nodeData)
825{
826 ui.editNodeId->setText(QString::fromStdString(nodeData.node->getId()));
827 ui.editSceneName->setText(QString::fromStdString(nodeData.node->getScene()));
828 ui.editNodeName->setText(QString::fromStdString(nodeData.node->getName()));
829 ui.editFrameName->setText(QString::fromStdString(nodeData.pose->frame));
830 ui.editAgentName->setText(QString::fromStdString(nodeData.pose->agent));
831
832 Eigen::Vector3f rpy;
833 VirtualRobot::MathTools::eigen4f2rpy(nodeData.pose->toEigen(), rpy);
834 ui.spinBoxX->setValue(nodeData.pose->position->x);
835 ui.spinBoxY->setValue(nodeData.pose->position->y);
836 ui.spinBoxZ->setValue(nodeData.pose->position->z);
837
838 ui.spinBoxRoll->setValue(VirtualRobot::MathTools::rad2deg(rpy[0]));
839 ui.spinBoxPitch->setValue(VirtualRobot::MathTools::rad2deg(rpy[1]));
840 ui.spinBoxYaw->setValue(VirtualRobot::MathTools::rad2deg(rpy[2]));
841}
842
843void
845{
846 clearGraph();
847 drawScene();
848}
849
850void
851GraphVisualizerWidget::transformView()
852{
853 double d = ui.viewZoomFactor->value();
854 ui.graphicsViewGraph->setTransform(QTransform::fromScale(d, d).rotate(viewAngle));
855}
856
857void
858GraphVisualizerWidget::viewRotatedClock()
859{
860 viewAngle = std::fmod(viewAngle + VIEW_ROTATE_STEP_SIZE_CC, 360);
861 transformView();
862}
863
864void
865GraphVisualizerWidget::viewRotatedCounterClock()
866{
867 viewAngle = std::fmod(viewAngle + 360 - VIEW_ROTATE_STEP_SIZE_CC, 360);
868 transformView();
869}
870
871void
872GraphVisualizerWidget::adjustView()
873{
874 float maxX = std::numeric_limits<float>::min();
875 float minX = std::numeric_limits<float>::max();
876 float maxY = std::numeric_limits<float>::min();
877 float minY = std::numeric_limits<float>::max();
878
879 //search bounding box
880 for (const auto& node : nodes)
881 {
882 maxX = (maxX < node.second.pose->position->x) ? node.second.pose->position->x : maxX;
883 minX = (minX > node.second.pose->position->x) ? node.second.pose->position->x : minX;
884 maxY = (maxY < node.second.pose->position->y) ? node.second.pose->position->y : maxY;
885 minY = (minY > node.second.pose->position->y) ? node.second.pose->position->y : minY;
886 }
887
888 auto deltaX = maxX - minX; //>=0
889 auto deltaY = maxY - minY; //>=0
890
891 //compare ratio of graph and view. if both horizontal (vertical) ->rotate to 0 or 180 (90,270)
892 if (std::signbit(deltaX / deltaY - 1) ==
893 std::signbit(ui.graphicsViewGraph->width() / ui.graphicsViewGraph->height() - 1))
894 {
895 //same => rotate to 0 or 180
896 viewAngle = (viewAngle < std::abs(180 - viewAngle)) ? 0 : 180;
897 //set zoom => update
898 ui.viewZoomFactor->setValue(std::min(ui.graphicsViewGraph->width() / deltaX,
899 ui.graphicsViewGraph->height() / deltaY) *
900 0.9);
901 }
902 else
903 {
904 //different rotate to 90 or 270
905 viewAngle = (std::abs(90 - viewAngle) < std::abs(270 - viewAngle)) ? 90 : 270;
906 //set zoom => update
907 ui.viewZoomFactor->setValue(std::min(ui.graphicsViewGraph->width() / deltaY,
908 ui.graphicsViewGraph->height() / deltaX) *
909 0.9);
910 }
911}
912
913bool
914GraphVisualizerWidget::addNewEdge(const std::string& fromId, const std::string& toId)
915{
916 std::string errorMsg;
917
918 if (!graphSeg->hasEntityById(fromId))
919 {
920 errorMsg = "start node with Id '" + fromId + "' not found in segment";
921 }
922 else if (!graphSeg->hasEntityById(toId))
923 {
924 errorMsg = "end node with Id '" + toId + "' not found in segment";
925 }
926 else if (fromId == toId)
927 {
928 errorMsg = "starting and ending node are the same";
929 }
930 else
931 {
932 auto fromNode = graphSeg->getNodeById(fromId);
933 for (const auto& adjacent : fromNode->getAdjacentNodes())
934 {
935 if (toId == adjacent->getId())
936 {
937 errorMsg = "edge '" + fromNode->getName() + "' -> '" + adjacent->getName() +
938 "' already exists";
939 break;
940 }
941 }
942 }
943
944 if (errorMsg.empty())
945 {
946 ui.labelAddEdgeStatus->setText(QString::fromStdString("Ok"));
947 graphSeg->addEdge(fromId, toId);
948 gnpr->forceRefetch(fromId);
949 gnpr->forceRefetch(toId);
950 addEdge(fromId, toId);
951 updateNode(fromId);
952 updateNode(toId);
953 ui.labelAddEdgeStatus->setStyleSheet("QLabel { background-color : lime; }");
954 }
955 else
956 {
957 ARMARX_WARNING << errorMsg;
958 ui.labelAddEdgeStatus->setText(QString::fromStdString(errorMsg));
959 ui.labelAddEdgeStatus->setStyleSheet("QLabel { background-color : orange; }");
960 }
961
962 return errorMsg.empty();
963}
964
965void
966GraphVisualizerWidget::addNewEdgeBoth()
967{
968 std::string startId = ui.editStartNodeId->text().toStdString();
969 std::string endId = ui.editEndNodeId->text().toStdString();
970 addNewEdge(startId, endId);
971 addNewEdge(endId, startId);
972}
973
974void
975GraphVisualizerWidget::addNewEdgeStartEnd()
976{
977 std::string startId = ui.editStartNodeId->text().toStdString();
978 std::string endId = ui.editEndNodeId->text().toStdString();
979 addNewEdge(startId, endId);
980}
981
982void
983GraphVisualizerWidget::addNewEdgeEndStart()
984{
985 std::string startId = ui.editEndNodeId->text().toStdString();
986 std::string endId = ui.editStartNodeId->text().toStdString();
987 addNewEdge(startId, endId);
988}
989
990void
991GraphVisualizerWidget::selectedSceneChanged(int i)
992{
993 const auto current = ui.scenesComboBox->currentText();
994 if (!current.isEmpty())
995 {
996 lastSelectedSceneName = current;
997 }
998}
999
1000void
1001GraphVisualizerWidget::updateSceneList()
1002{
1003 auto scenes = graphSeg->getScenes();
1004 ui.scenesComboBox->clear();
1005 int idx = -1;
1006
1007 for (std::size_t i = 0; i < scenes.size(); i++)
1008 {
1009 const auto currentScene = QString::fromStdString(scenes[i]);
1010 ui.scenesComboBox->addItem(currentScene);
1011
1012 if (currentScene == lastSelectedSceneName)
1013 {
1014 idx = i;
1015 }
1016 }
1017
1018 ui.scenesComboBox->setCurrentIndex(idx);
1019}
1020
1021void
1022GraphVisualizerWidget::drawScene()
1023{
1024 std::vector<std::string> highlightedNodes;
1025 for (const auto& nodeData : nodes)
1026 {
1027 bool sameScene =
1028 ui.scenesComboBox->currentText().toStdString() == nodeData.second.node->getScene();
1029 if (nodeData.second.highlighted && sameScene)
1030 {
1031 highlightedNodes.push_back(nodeData.first);
1032 }
1033 }
1034
1035 clearGraph();
1036 auto graphNodes = graphSeg->getNodesByScene(ui.scenesComboBox->currentText().toStdString());
1037
1038 //add nodes
1039 for (auto& node : graphNodes)
1040 {
1041 auto pos = armarx::FramedPosePtr::dynamicCast(node->getPose());
1042
1043 if (!pos || node->isMetaEntity())
1044 {
1045 continue;
1046 }
1047
1048 addNode(node);
1049 }
1050
1051 //add edges
1052 for (auto& node : graphNodes)
1053 {
1054 auto nodeId = node->getId();
1055
1056 for (int i = 0; i < node->getOutdegree(); i++)
1057 {
1058 auto adjacent =
1059 memoryx::GraphNodeBasePtr::dynamicCast(node->getAdjacentNode(i)->getEntity());
1060 ARMARX_CHECK_EXPRESSION(adjacent);
1061 auto adjacentId = adjacent->getId();
1062
1063 addEdge(nodeId, adjacentId);
1064 }
1065 }
1066
1067 for (const auto& nodeId : highlightedNodes)
1068 {
1069 auto nodeIt = std::find_if(nodes.begin(),
1070 nodes.end(),
1071 [&](const std::pair<std::string, NodeData>& d)
1072 { return d.first == nodeId; });
1073
1074 if (nodeIt != nodes.end())
1075 {
1076 nodeIt->second.highlighted = true;
1077 updateNode(nodeIt->first);
1078 }
1079 }
1080
1081 adjustView();
1082}
1083
1084void
1085GraphVisualizerWidget::selectScene()
1086{
1087 //QString fi = QFileDialog::getOpenFileName(this, tr("Open Scene File"), QString(), tr("XML Files (*.xml)"));
1088 // std::string xmlSceneFile = std::string(fi.toLatin1());
1089 // loadScene(xmlSceneFile);
1090}
1091
1092void
1093GraphVisualizerWidget::loadScene(const std::string& xmlFile)
1094{
1095 // VirtualRobot::ScenePtr SceneIO::loadScene(const std::string& xmlFile)
1096 // {
1097 // load file
1098 std::ifstream in(xmlFile.c_str());
1099
1100 if (!in.is_open())
1101 {
1102 ARMARX_WARNING << "Could not open XML file:" << xmlFile;
1103 return;
1104 }
1105
1106 std::stringstream buffer;
1107 buffer << in.rdbuf();
1108 std::string sceneXML(buffer.str());
1109 std::filesystem::path filenameBaseComplete(xmlFile);
1110 std::filesystem::path filenameBasePath = filenameBaseComplete.parent_path();
1111 std::string basePath = filenameBasePath.string();
1112
1113 in.close();
1114
1115 // VirtualRobot::ScenePtr res = createSceneFromString(robotXML, basePath);
1116 // THROW_VR_EXCEPTION_IF(!res, "Error while parsing file " << xmlFile);
1117
1118 // return res;
1119 // }
1120}
1121
1122void
1123GraphVisualizerWidget::addKitchenGraph()
1124{
1125 std::string scene{"GraphKitchen"};
1126 graphSeg->clearScene(scene);
1127
1128 //if you insist on hardcoding scenes, use these convenience functions for improved readability:
1129 auto addNode = [&](const std::string& name, float x, float y, float angle)
1130 {
1131 graphSeg->addNode(new ::memoryx::GraphNode{x, y, angle, name, scene});
1132 ARMARX_INFO_S << "added node '" << name << "' at (" << x << ", " << y << ", " << angle
1133 << "rad)";
1134 };
1135
1136 auto addEdges =
1137 [&](const std::string& nodeFromName, const std::string& nodeToName, bool bidirectional)
1138 {
1139 auto nodeFrom = graphSeg->getNodeFromSceneByName(scene, nodeFromName);
1140 auto nodeTo = graphSeg->getNodeFromSceneByName(scene, nodeToName);
1141 ARMARX_CHECK_EXPRESSION(nodeFrom);
1143 ARMARX_INFO_S << "'" << nodeFrom->getName() << "' -> '" << nodeTo->getName()
1144 << "', status: " << graphSeg->addEdge(nodeFrom->getId(), nodeTo->getId());
1145 if (bidirectional)
1146 {
1147 ARMARX_INFO_S << "'" << nodeTo->getName() << "' -> '" << nodeFrom->getName()
1148 << "', status: " << graphSeg->addEdge(nodeTo->getId(), nodeFrom->getId());
1149 }
1150 };
1151
1152 //ex
1153 addNode("initialnode", 2900, 7000, 0);
1154 addNode("sideboard", 3400, 7000, 0);
1155 addEdges("initialnode", "sideboard", true);
1156}
1157
1158void
1159GraphVisualizerWidget::addNewGraphNode()
1160{
1161 Eigen::Matrix4f mat;
1162 Eigen::Vector3f rpy;
1163 Eigen::Vector3f pos;
1164 rpy << VirtualRobot::MathTools::deg2rad(ui.spinBoxRoll->value()),
1165 VirtualRobot::MathTools::deg2rad(ui.spinBoxPitch->value()),
1166 VirtualRobot::MathTools::deg2rad(ui.spinBoxYaw->value());
1167 pos << ui.spinBoxX->value(), ui.spinBoxY->value(), ui.spinBoxZ->value();
1168 VirtualRobot::MathTools::posrpy2eigen4f(pos, rpy, mat);
1169 armarx::FramedPosePtr pose = new armarx::FramedPose(
1170 mat, ui.editFrameName->text().toStdString(), ui.editAgentName->text().toStdString());
1171 GraphNodePtr node = new GraphNode(
1172 pose, ui.editNodeName->text().toStdString(), ui.editSceneName->text().toStdString());
1173 auto entityId = graphSeg->addNode(node);
1174 gnpr->forceRefetch(entityId);
1175 node->setId(entityId);
1176 if (ui.scenesComboBox->currentText().toStdString() == ui.editSceneName->text().toStdString())
1177 {
1178 ui.editNodeId->setText(QString::fromStdString(entityId));
1179 addNode(node);
1180 }
1181}
1182
1183void
1184GraphVisualizerWidget::editGraphNode()
1185{
1186 Eigen::Matrix4f mat;
1187 Eigen::Vector3f rpy;
1188 Eigen::Vector3f pos;
1189 rpy << VirtualRobot::MathTools::deg2rad(ui.spinBoxRoll->value()),
1190 VirtualRobot::MathTools::deg2rad(ui.spinBoxPitch->value()),
1191 VirtualRobot::MathTools::deg2rad(ui.spinBoxYaw->value());
1192 pos << ui.spinBoxX->value(), ui.spinBoxY->value(), ui.spinBoxZ->value();
1193 VirtualRobot::MathTools::posrpy2eigen4f(pos, rpy, mat);
1194 armarx::FramedPosePtr pose = new armarx::FramedPose(
1195 mat, ui.editFrameName->text().toStdString(), ui.editAgentName->text().toStdString());
1196 GraphNodePtr node = new GraphNode(
1197 pose, ui.editNodeName->text().toStdString(), ui.editSceneName->text().toStdString());
1198 auto id = ui.editNodeId->text().toStdString();
1199
1200 node->setId(id);
1201 graphSeg->updateEntity(id, node);
1202 gnpr->forceRefetch(id);
1203 if (ui.scenesComboBox->currentText().toStdString() == ui.editSceneName->text().toStdString())
1204 {
1205 addNode(node);
1206 }
1207}
1208
1209void
1211{
1212 int row = ui.tableWidgetNodes->rowAt(pos.y());
1213 auto nodeIt = std::find_if(nodes.begin(),
1214 nodes.end(),
1215 [&](const std::pair<std::string, NodeData>& d)
1216 { return d.second.tableWidgetNodesIndex == row; });
1217 QMenu menu;
1218 QAction* deleteAction = menu.addAction("Delete Node");
1219
1220 if (menu.exec(QCursor::pos()) == deleteAction)
1221 {
1222 ARMARX_CHECK_EXPRESSION(nodeIt != nodes.end());
1223 graphSeg->removeNode(nodeIt->second.node->getId());
1224 drawScene();
1225 }
1226}
1227
1228void
1230{
1231 int row = ui.tableWidgetEdges->rowAt(pos.y());
1232 auto edgeIt = std::find_if(edges.begin(),
1233 edges.end(),
1234 [&](const std::pair<EdgeId, EdgeData>& d)
1235 { return d.second.tableWidgetEdgesIndex == row; });
1236 QMenu menu;
1237 QAction* deleteAction = menu.addAction("Delete Edge");
1238
1239 if (menu.exec(QCursor::pos()) == deleteAction)
1240 {
1241 ARMARX_CHECK_EXPRESSION(edgeIt != edges.end());
1242 graphSeg->removeEdge(edgeIt->first.first, edgeIt->first.second);
1243 drawScene();
1244 }
1245}
1246
1247bool
1248MouseEventProcessor::eventFilter(QObject* obj, QEvent* event)
1249{
1250 if (obj == gvw->ui.graphicsViewGraph && event->type() == QEvent::MouseButtonPress)
1251 {
1252 QMouseEvent* me = static_cast<QMouseEvent*>(event);
1253 if (me->button() == Qt::LeftButton)
1254 {
1255 QPointF scenePoint = gvw->ui.graphicsViewGraph->mapToScene(me->pos());
1256 scenePoint.setY(-scenePoint.y()); //not sure why
1257
1258 float minDist = std::numeric_limits<float>::max();
1259 auto bestIt = gvw->nodes.cend();
1260
1261 for (auto it = gvw->nodes.cbegin(); it != gvw->nodes.cend(); ++it)
1262 {
1263 float deltaX = it->second.pose->position->x - scenePoint.x();
1264 float deltaY = it->second.pose->position->y - scenePoint.y();
1265 float dist = std::sqrt(deltaX * deltaX + deltaY * deltaY);
1266
1267 if (dist < minDist)
1268 {
1269 minDist = dist;
1270 bestIt = it;
1271 }
1272 }
1273
1274 if (bestIt != gvw->nodes.cend())
1275 {
1276 gvw->nodeDoubleClicked(bestIt->first);
1277 }
1278 }
1279 }
1280 else if (event->type() == QEvent::Resize)
1281 {
1282 gvw->adjustView();
1283 }
1284 return QObject::eventFilter(obj, event);
1285}
uint8_t data[1]
#define DEFAULT_DEBUG_DRAWER_LAYER_NAME
std::string iceName(const GraphVisualizerWidget::EdgeId &edge)
Returns the name used on the debug layer.
#define DEFAULT_PRIOR_KNOWLEDGE_NAME
#define DEFAULT_DEBUG_DRAWER_NAME
#define M_PI
Definition MathTools.h:17
std::enable_if<!HasGetWidgetName< ArmarXWidgetType >::value >::type addWidget()
virtual QPointer< QWidget > getWidget()
getWidget returns a pointer to the a widget of this controller.
void offeringTopic(const std::string &name)
Registers a topic for retrival after initialization.
TopicProxyType getTopic(const std::string &name)
Returns a proxy of the specified topic.
bool usingProxy(const std::string &name, const std::string &endpoints="")
Registers a proxy for retrieval after initialization and adds it to the dependency list.
Ice::ObjectPrx getProxy(long timeoutMs=0, bool waitForScheduler=true) const
Returns the proxy of this object (optionally it waits for the proxy)
The Vector3 class.
Definition Pose.h:113
void onInitComponent() override
Pure virtual hook for the subclass.
void clearGraph(const Ice::Current &=Ice::emptyCurrent) override
void redraw(const Ice::Current &=Ice::emptyCurrent) override
Ui::GraphVisualizerGuiPlugin ui
Contains the ui.
void resetHighlight(const Ice::Current &=Ice::emptyCurrent) override
bool hasNode(const std::string &id, const Ice::Current &=Ice::emptyCurrent) override
const std::pair< const std::string, const std::string > EdgeId
The type of edge ids.
void loadSettings(QSettings *settings) override
Implement to load the settings that are part of the GUI configuration.
void highlightEdge(const std::string &node1Id, const std::string &node2Id, bool highlighted=true, const Ice::Current &=Ice::emptyCurrent) override
void saveSettings(QSettings *settings) override
Implement to save the settings as part of the GUI configuration.
void clearEdges(const Ice::Current &=Ice::emptyCurrent) override
QPointer< QDialog > getConfigDialog(QWidget *parent=0) override
getConfigDialog returns a pointer to the a configuration widget of this controller.
void onConnectComponent() override
Pure virtual hook for the subclass.
void configured() override
This function must be implemented by the user, if he supplies a config dialog.
void addEdge(const std::string &node1Id, const std::string &node2Id, const Ice::Current &=Ice::emptyCurrent) override
bool hasEdge(const std::string &node1, const std::string &node2, const Ice::Current &=Ice::emptyCurrent) override
void onExitComponent() override
Hook for subclass.
const std::string NodeId
The type of node ids.
void addNode(const GraphNodeBasePtr &node, const Ice::Current &=Ice::emptyCurrent) override
void highlightNode(const std::string &nodeId, bool highlighted=true, const Ice::Current &=Ice::emptyCurrent) override
bool eventFilter(QObject *obj, QEvent *event) override
#define ARMARX_CHECK_EXPRESSION(expression)
This macro evaluates the expression and if it turns out to be false it will throw an ExpressionExcept...
#define ARMARX_INFO_S
Definition Logging.h:202
#define ARMARX_WARNING
The logging level for unexpected behaviour, but not a serious problem.
Definition Logging.h:193
#define ARMARX_VERBOSE
The logging level for verbose information.
Definition Logging.h:187
IceInternal::Handle< Vector3 > Vector3Ptr
Definition Pose.h:165
IceInternal::Handle< Pose > PosePtr
Definition Pose.h:306
IceInternal::Handle< FramedPose > FramedPosePtr
Definition FramedPose.h:272
const armarx::VariantTypeId GraphNode
Definition GraphNode.h:40
VirtualRobot headers.
IceInternal::Handle< GraphNode > GraphNodePtr
Definition GraphNode.h:47
double angle(const Point &a, const Point &b, const Point &c)
Definition point.hpp:109