27 #include <VirtualRobot/MathTools.h>
38 #include <QHBoxLayout>
42 #include <QPushButton>
53 #include <unordered_set>
55 #include <MemoryX/gui-plugins/GraphVisualizerPlugin/ui_GraphVisualizerConfigDialog.h>
64 #define DEFAULT_PRIOR_KNOWLEDGE_NAME "PriorKnowledge"
65 #define DEFAULT_DEBUG_DRAWER_NAME "DebugDrawerUpdates"
66 #define DEFAULT_DEBUG_DRAWER_LAYER_NAME "DebugDrawerUpdates_Graph"
80 static const ::armarx::DrawColor COLOR_DEFAULT = {0.5f, 0.5f, 1.f, 0.2f};
84 static const ::armarx::DrawColor COLOR_HIGHLIGHT = {1.f, 0.0f, 0.f, 1.f};
89 static const float SCENE_SCALE_FACTOR = 2;
93 static const float SCENE_NODES_SCALE_FACTOR = 3 * SCENE_SCALE_FACTOR;
97 static const float SCENE_LINE_SCALE_FACTOR = SCENE_SCALE_FACTOR;
108 static const float VIEW_ROTATE_STEP_SIZE_CC = 45;
110 static const QString SETTING_LAST_SCENE =
"lastScene";
121 s <<
"edge_" << edge.first <<
"_" << edge.second;
139 addWidget<GraphVisualizerWidget>();
149 settings{
"KIT",
"GraphVisualizerGuiPlugin"}
151 loadAutomaticSettings();
152 editStartNodeNext =
true;
155 ui.setupUi(getWidget());
157 std::unique_ptr<QGraphicsScene> scenePtr{
new QGraphicsScene};
158 scene = scenePtr.get();
159 ui.graphicsViewGraph->setScene(scenePtr.release());
161 ui.graphicsViewGraph->installEventFilter(mep);
185 debugDrawer = getTopic<armarx::DebugDrawerInterfacePrx>(debugDrawerTopicName);
186 priorKnowledgePrx = getProxy<memoryx::PriorKnowledgeInterfacePrx>(priorKnowledgeProxyName);
187 getProxy(gnpr,
"GraphNodePoseResolver");
189 if (priorKnowledgePrx->hasGraphSegment())
192 graphSeg = priorKnowledgePrx->getGraphSegment();
193 ui.sceneGroupBox->setEnabled(
true);
194 ui.sceneGroupBox->setTitle(
"Scenes from graph memory segment");
196 ui.b->setEnabled(
true);
200 ui.sceneGroupBox->setEnabled(
false);
201 ui.sceneGroupBox->setTitle(
202 "Scenes from graph memory segment (No graph memory segment available)");
204 ui.b->setEnabled(
false);
207 ui.tableWidgetNodes->horizontalHeader()->setResizeMode(QHeaderView::ResizeToContents);
208 ui.tableWidgetEdges->horizontalHeader()->setResizeMode(QHeaderView::Stretch);
210 ui.tableWidgetNodes->setContextMenuPolicy(Qt::CustomContextMenu);
211 ui.tableWidgetEdges->setContextMenuPolicy(Qt::CustomContextMenu);
214 QObject::connect(
ui.b, SIGNAL(clicked()),
this, SLOT(addKitchenGraph()), Qt::UniqueConnection);
217 QObject::connect(
ui.tableWidgetNodes,
218 SIGNAL(cellDoubleClicked(
int,
int)),
220 SLOT(nodeTableDoubleClicked(
int,
int)),
221 Qt::UniqueConnection);
222 QObject::connect(
ui.tableWidgetNodes,
223 SIGNAL(customContextMenuRequested(QPoint)),
226 Qt::UniqueConnection);
227 QObject::connect(
ui.tableWidgetEdges,
228 SIGNAL(cellDoubleClicked(
int,
int)),
230 SLOT(edgeTableDoubleClicked(
int,
int)),
231 Qt::UniqueConnection);
232 QObject::connect(
ui.tableWidgetEdges,
233 SIGNAL(customContextMenuRequested(QPoint)),
236 Qt::UniqueConnection);
239 ui.btnAdd, SIGNAL(clicked()),
this, SLOT(addNewGraphNode()), Qt::UniqueConnection);
241 ui.btnAddEdge, SIGNAL(clicked()),
this, SLOT(addNewEdgeBoth()), Qt::UniqueConnection);
242 QObject::connect(
ui.btnAddEdgeStartEnd,
245 SLOT(addNewEdgeStartEnd()),
246 Qt::UniqueConnection);
247 QObject::connect(
ui.btnAddEdgeEndStart,
250 SLOT(addNewEdgeEndStart()),
251 Qt::UniqueConnection);
253 ui.btnEdit, SIGNAL(clicked()),
this, SLOT(editGraphNode()), Qt::UniqueConnection);
256 QObject::connect(
ui.viewZoomFactor,
257 SIGNAL(valueChanged(
double)),
259 SLOT(transformView()),
260 Qt::UniqueConnection);
262 QObject::connect(
ui.buttonRotateClock,
265 SLOT(viewRotatedClock()),
266 Qt::UniqueConnection);
267 QObject::connect(
ui.buttonRotateCounterClock,
270 SLOT(viewRotatedCounterClock()),
271 Qt::UniqueConnection);
274 ui.buttonRedraw, SIGNAL(clicked()),
this, SLOT(
redraw()), Qt::UniqueConnection);
276 ui.buttonClear, SIGNAL(clicked()),
this, SLOT(
clearGraph()), Qt::UniqueConnection);
279 ui.buttonAutoAdjust, SIGNAL(clicked()),
this, SLOT(adjustView()), Qt::UniqueConnection);
281 QObject::connect(
ui.refreshScenesButton,
284 SLOT(updateSceneList()),
285 Qt::UniqueConnection);
286 QObject::connect(
ui.drawSceneButton,
290 Qt::UniqueConnection);
291 QObject::connect(
ui.scenesComboBox,
292 SIGNAL(currentIndexChanged(
int)),
294 SLOT(selectedSceneChanged(
int)),
295 Qt::UniqueConnection);
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);
325 debugDrawerTopicName = dialog->ui->editDebugDrawerProxyName->text().toStdString();
326 debugDrawerLayerName = dialog->ui->editDebugDrawerLayerName->text().toStdString();
327 priorKnowledgeProxyName = dialog->ui->editPriorKnowledgeProxyName->text().toStdString();
333 debugDrawerTopicName =
334 settings->value(
"debugDrawerTopicName", QString::fromStdString(debugDrawerTopicName))
337 debugDrawerLayerName =
338 settings->value(
"debugDrawerLayerName", QString::fromStdString(debugDrawerLayerName))
346 settings->setValue(
"debugDrawerTopicName", QString::fromStdString(debugDrawerTopicName));
347 settings->setValue(
"debugDrawerLayerName", QString::fromStdString(debugDrawerLayerName));
353 lastSelectedSceneName = settings.value(SETTING_LAST_SCENE, lastSelectedSceneName).toString();
359 settings.setValue(SETTING_LAST_SCENE, lastSelectedSceneName);
364 const std::string& node2Id,
369 ARMARX_WARNING <<
"Edge: " << node1Id <<
", " << node2Id <<
" can't be created! Node "
370 << node1Id <<
" does not exist.";
376 ARMARX_WARNING <<
"Edge: " << node1Id <<
", " << node2Id <<
" can't be created! Node "
377 << node2Id <<
" does not exist.";
381 auto node1dat = nodes.at(node1Id);
382 auto node2dat = nodes.at(node2Id);
387 ARMARX_WARNING <<
"Edge: '" << node1dat.node->getName() <<
"' -> '"
388 << node2dat.node->getName() <<
"' already exists.";
392 auto edgeId = toEdge(node1Id, node2Id);
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())});
404 QGraphicsLineItem* graphicsItem =
dynamic_cast<QGraphicsLineItem*
>(
407 node1dat.pose->position->x,
408 -node1dat.pose->position->y,
409 node2dat.pose->position->x,
410 -node2dat.pose->position->y});
413 scene->addItem(graphicsItem);
415 dynamic_cast<QGraphicsItem*
>(graphicsItem)
416 ->setToolTip(QString{
"Edge:"} + QString::fromStdString(node1dat.node->getName()) +
417 QString{
" <-> "} + QString::fromStdString(node2dat.node->getName()));
419 EdgeData
data{graphicsItem, row,
false};
420 edges[edgeId] =
data;
429 auto nodeId = node->getId();
434 globalNodePose = armarx::FramedPosePtr::dynamicCast(gnpr->resolveToGlobalPose(node));
443 NodeData& oldNode = nodes.at(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);
451 ui.tableWidgetNodes->setItem(
452 oldNode.tableWidgetNodesIndex,
454 new QTableWidgetItem{QString::number(globalNodePose->position->x)});
455 ui.tableWidgetNodes->setItem(
456 oldNode.tableWidgetNodesIndex,
458 new QTableWidgetItem{QString::number(globalNodePose->position->y)});
459 ui.tableWidgetNodes->setItem(
460 oldNode.tableWidgetNodesIndex,
462 new QTableWidgetItem{QString::number(getYawAngle(globalNodePose))});
465 oldNode.pose = globalNodePose;
468 for (
const auto& edge : edges)
470 if ((edge.first.first == nodeId) || (edge.first.second == nodeId))
472 updateEdge(edge.first);
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))});
491 QGraphicsEllipseItem* graphicsItem =
dynamic_cast<QGraphicsEllipseItem*
>(
494 globalNodePose->position->x,
495 -globalNodePose->position->y,
499 scene->addItem(graphicsItem);
502 dynamic_cast<QGraphicsItem*
>(graphicsItem)
503 ->setToolTip(QString{
"Node:"} + QString::fromStdString(node->getName()));
506 NodeData
data{node, globalNodePose, graphicsItem, row,
false};
507 nodes.insert({nodeId,
data});
516 for (
auto& edge : edges)
519 scene->removeItem(edge.second.graphicsItem);
520 delete edge.second.graphicsItem;
522 debugDrawer->removePoseVisu(debugDrawerLayerName,
iceName(edge.first));
526 ui.tableWidgetEdges->clearContents();
527 ui.tableWidgetEdges->setRowCount(0);
536 for (
auto& edge : edges)
538 debugDrawer->removeLineVisu(debugDrawerLayerName,
iceName(edge.first));
541 for (
auto& node : nodes)
543 debugDrawer->removeArrowVisu(debugDrawerLayerName,
iceName(node.first));
544 debugDrawer->removeTextVisu(debugDrawerLayerName,
iceName(node.first) +
"text");
545 debugDrawer->removePoseVisu(debugDrawerLayerName,
iceName(node.first));
551 ui.tableWidgetEdges->clearContents();
552 ui.tableWidgetEdges->setRowCount(0);
553 ui.tableWidgetNodes->clearContents();
554 ui.tableWidgetNodes->setRowCount(0);
564 for (
auto& edge : edges)
566 if (edge.second.highlighted)
568 edge.second.highlighted =
false;
569 updateEdge(edge.first);
573 for (
auto& node : nodes)
575 if (node.second.highlighted)
577 node.second.highlighted =
false;
578 updateNode(node.first);
584 GraphVisualizerWidget::updateEdge(
const EdgeId&
id)
586 const EdgeData&
data = edges.at(
id);
587 auto color = (
data.highlighted) ? COLOR_HIGHLIGHT : COLOR_DEFAULT;
589 qColor.setRedF(color.r);
590 qColor.setGreenF(color.g);
591 qColor.setBlueF(color.b);
593 auto lineWidth = (
data.highlighted) ? LINE_WIDTH_SELECTED : LINE_WIDTH_DEFAULT;
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;
601 debugDrawer->setLineVisu(debugDrawerLayerName,
iceName(
id), posStart, posEnd, lineWidth, color);
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);
610 pen.setWidthF(lineWidth * SCENE_LINE_SCALE_FACTOR);
611 data.graphicsItem->setPen(pen);
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);
622 GraphVisualizerWidget::updateNode(
const NodeId&
id)
624 NodeData&
data = nodes.at(
id);
626 if (editStartNodeNext)
628 ui.editStartNodeId->setText(QString::fromStdString(
data.node->getId()));
629 ui.editStartNodeName->setText(QString::fromStdString(
data.node->getName()));
633 ui.editEndNodeId->setText(QString::fromStdString(
data.node->getId()));
634 ui.editEndNodeName->setText(QString::fromStdString(
data.node->getName()));
639 editStartNodeNext = !editStartNodeNext;
641 auto color = (
data.highlighted) ? COLOR_HIGHLIGHT : COLOR_DEFAULT;
643 qColor.setRedF(color.r);
644 qColor.setGreenF(color.g);
645 qColor.setBlueF(color.b);
647 auto lineWidth = (
data.highlighted) ? LINE_WIDTH_SELECTED : LINE_WIDTH_DEFAULT;
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,
658 armarx::DrawColor{0, 0, 1, 1},
661 debugDrawer->setTextVisu(debugDrawerLayerName,
663 data.node->getName(),
665 armarx::DrawColor{0, 0, 1, 1},
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);
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);
688 std::vector<GraphNodeBasePtr> highlightedNodes;
689 for (
const auto& nodeData : nodes)
691 if (nodeData.second.highlighted)
693 highlightedNodes.push_back(nodeData.second.node);
697 for (
auto& edge : edges)
699 if (edge.second.highlighted)
701 edge.second.highlighted =
false;
702 updateEdge(edge.first);
706 for (
const auto& nodeFrom : highlightedNodes)
708 for (
const auto& nodeTo : highlightedNodes)
710 const auto nodeFromId = nodeFrom->getId();
711 const auto nodeToId = nodeTo->getId();
712 if (
hasEdge(nodeFromId, nodeToId))
714 auto edgeId = toEdge(nodeFromId, nodeToId);
715 auto& edge = edges[edgeId];
716 edge.highlighted =
true;
724 GraphVisualizerWidget::getYawAngle(
const armarx::PoseBasePtr& pose)
const
728 VirtualRobot::MathTools::eigen4f2rpy(p->toEigen(), rpy);
729 return VirtualRobot::MathTools::rad2deg(rpy[2]);
734 const std::string& node2Id,
738 if (!
hasEdge(node1Id, node2Id))
740 ARMARX_WARNING <<
"No edge for: " << node1Id <<
" and " << node2Id <<
" [file: " << __FILE__
741 <<
" | line: " << __LINE__ <<
" | function: " << __PRETTY_FUNCTION__ <<
"]";
745 EdgeId edge = toEdge(node1Id, node2Id);
747 if (edges.at(edge).highlighted != highlighted)
749 edges.at(edge).highlighted = highlighted;
761 ARMARX_WARNING <<
"No node: " << nodeId <<
" [pushBfile: " << __FILE__
762 <<
" | line: " << __LINE__ <<
" | function: " << __PRETTY_FUNCTION__ <<
"]";
766 if (nodes.at(nodeId).highlighted != highlighted)
768 nodes.at(nodeId).highlighted = highlighted;
774 GraphVisualizerWidget::nodeTableDoubleClicked(
int row,
int)
776 auto nodeIt = std::find_if(nodes.cbegin(),
778 [&](
const std::pair<std::string, NodeData>& d)
781 return d.second.tableWidgetNodesIndex == row;
783 auto nodeId = nodeIt->second.node->getId();
784 nodeDoubleClicked(nodeId);
788 GraphVisualizerWidget::edgeTableDoubleClicked(
int row,
int)
790 auto edgeIt = std::find_if(edges.cbegin(),
792 [&](
const std::pair<EdgeId, EdgeData>& d)
793 { return d.second.tableWidgetEdgesIndex == row; });
795 edgeDoubleClicked(edgeIt->first);
799 GraphVisualizerWidget::nodeDoubleClicked(NodeId
id)
801 nodes.at(
id).highlighted ^=
true;
806 GraphVisualizerWidget::edgeDoubleClicked(
EdgeId 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);
824 GraphVisualizerWidget::setEditFields(
const NodeData& nodeData)
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));
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);
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]));
851 GraphVisualizerWidget::transformView()
853 double d =
ui.viewZoomFactor->value();
854 ui.graphicsViewGraph->setTransform(QTransform::fromScale(d, d).rotate(viewAngle));
858 GraphVisualizerWidget::viewRotatedClock()
860 viewAngle = std::fmod(viewAngle + VIEW_ROTATE_STEP_SIZE_CC, 360);
865 GraphVisualizerWidget::viewRotatedCounterClock()
867 viewAngle = std::fmod(viewAngle + 360 - VIEW_ROTATE_STEP_SIZE_CC, 360);
872 GraphVisualizerWidget::adjustView()
880 for (
const auto& node : nodes)
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;
888 auto deltaX = maxX - minX;
889 auto deltaY = maxY - minY;
892 if (std::signbit(deltaX / deltaY - 1) ==
893 std::signbit(
ui.graphicsViewGraph->width() /
ui.graphicsViewGraph->height() - 1))
896 viewAngle = (viewAngle <
std::abs(180 - viewAngle)) ? 0 : 180;
898 ui.viewZoomFactor->setValue(
std::min(
ui.graphicsViewGraph->width() / deltaX,
899 ui.graphicsViewGraph->height() / deltaY) *
905 viewAngle = (
std::abs(90 - viewAngle) <
std::abs(270 - viewAngle)) ? 90 : 270;
907 ui.viewZoomFactor->setValue(
std::min(
ui.graphicsViewGraph->width() / deltaY,
908 ui.graphicsViewGraph->height() / deltaX) *
914 GraphVisualizerWidget::addNewEdge(
const std::string& fromId,
const std::string& toId)
916 std::string errorMsg;
918 if (!graphSeg->hasEntityById(fromId))
920 errorMsg =
"start node with Id '" + fromId +
"' not found in segment";
922 else if (!graphSeg->hasEntityById(toId))
924 errorMsg =
"end node with Id '" + toId +
"' not found in segment";
926 else if (fromId == toId)
928 errorMsg =
"starting and ending node are the same";
932 auto fromNode = graphSeg->getNodeById(fromId);
933 for (
const auto& adjacent : fromNode->getAdjacentNodes())
935 if (toId == adjacent->getId())
937 errorMsg =
"edge '" + fromNode->getName() +
"' -> '" + adjacent->getName() +
944 if (errorMsg.empty())
946 ui.labelAddEdgeStatus->setText(QString::fromStdString(
"Ok"));
947 graphSeg->addEdge(fromId, toId);
948 gnpr->forceRefetch(fromId);
949 gnpr->forceRefetch(toId);
953 ui.labelAddEdgeStatus->setStyleSheet(
"QLabel { background-color : lime; }");
958 ui.labelAddEdgeStatus->setText(QString::fromStdString(errorMsg));
959 ui.labelAddEdgeStatus->setStyleSheet(
"QLabel { background-color : orange; }");
962 return errorMsg.empty();
966 GraphVisualizerWidget::addNewEdgeBoth()
968 std::string startId =
ui.editStartNodeId->text().toStdString();
969 std::string endId =
ui.editEndNodeId->text().toStdString();
970 addNewEdge(startId, endId);
971 addNewEdge(endId, startId);
975 GraphVisualizerWidget::addNewEdgeStartEnd()
977 std::string startId =
ui.editStartNodeId->text().toStdString();
978 std::string endId =
ui.editEndNodeId->text().toStdString();
979 addNewEdge(startId, endId);
983 GraphVisualizerWidget::addNewEdgeEndStart()
985 std::string startId =
ui.editEndNodeId->text().toStdString();
986 std::string endId =
ui.editStartNodeId->text().toStdString();
987 addNewEdge(startId, endId);
991 GraphVisualizerWidget::selectedSceneChanged(
int i)
993 const auto current =
ui.scenesComboBox->currentText();
994 if (!current.isEmpty())
996 lastSelectedSceneName = current;
1001 GraphVisualizerWidget::updateSceneList()
1003 auto scenes = graphSeg->getScenes();
1004 ui.scenesComboBox->clear();
1007 for (std::size_t i = 0; i < scenes.size(); i++)
1009 const auto currentScene = QString::fromStdString(scenes[i]);
1010 ui.scenesComboBox->addItem(currentScene);
1012 if (currentScene == lastSelectedSceneName)
1018 ui.scenesComboBox->setCurrentIndex(idx);
1022 GraphVisualizerWidget::drawScene()
1024 std::vector<std::string> highlightedNodes;
1025 for (
const auto& nodeData : nodes)
1028 ui.scenesComboBox->currentText().toStdString() == nodeData.second.node->getScene();
1029 if (nodeData.second.highlighted && sameScene)
1031 highlightedNodes.push_back(nodeData.first);
1036 auto graphNodes = graphSeg->getNodesByScene(
ui.scenesComboBox->currentText().toStdString());
1039 for (
auto& node : graphNodes)
1041 auto pos = armarx::FramedPosePtr::dynamicCast(node->getPose());
1043 if (!pos || node->isMetaEntity())
1052 for (
auto& node : graphNodes)
1054 auto nodeId = node->getId();
1056 for (
int i = 0; i < node->getOutdegree(); i++)
1059 memoryx::GraphNodeBasePtr::dynamicCast(node->getAdjacentNode(i)->getEntity());
1061 auto adjacentId = adjacent->getId();
1067 for (
const auto& nodeId : highlightedNodes)
1069 auto nodeIt = std::find_if(nodes.begin(),
1071 [&](
const std::pair<std::string, NodeData>& d)
1072 { return d.first == nodeId; });
1074 if (nodeIt != nodes.end())
1076 nodeIt->second.highlighted =
true;
1077 updateNode(nodeIt->first);
1085 GraphVisualizerWidget::selectScene()
1093 GraphVisualizerWidget::loadScene(
const std::string& xmlFile)
1098 std::ifstream in(xmlFile.c_str());
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();
1123 GraphVisualizerWidget::addKitchenGraph()
1125 std::string scene{
"GraphKitchen"};
1126 graphSeg->clearScene(scene);
1129 auto addNode = [&](
const std::string& name,
float x,
float y,
float angle)
1132 ARMARX_INFO_S <<
"added node '" << name <<
"' at (" << x <<
", " << y <<
", " <<
angle
1137 [&](
const std::string& nodeFromName,
const std::string& nodeToName,
bool bidirectional)
1139 auto nodeFrom = graphSeg->getNodeFromSceneByName(scene, nodeFromName);
1140 auto nodeTo = graphSeg->getNodeFromSceneByName(scene, nodeToName);
1143 ARMARX_INFO_S <<
"'" << nodeFrom->getName() <<
"' -> '" << nodeTo->getName()
1144 <<
"', status: " << graphSeg->addEdge(nodeFrom->getId(), nodeTo->getId());
1147 ARMARX_INFO_S <<
"'" << nodeTo->getName() <<
"' -> '" << nodeFrom->getName()
1148 <<
"', status: " << graphSeg->addEdge(nodeTo->getId(), nodeFrom->getId());
1153 addNode(
"initialnode", 2900, 7000, 0);
1154 addNode(
"sideboard", 3400, 7000, 0);
1155 addEdges(
"initialnode",
"sideboard",
true);
1159 GraphVisualizerWidget::addNewGraphNode()
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);
1170 mat,
ui.editFrameName->text().toStdString(),
ui.editAgentName->text().toStdString());
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())
1178 ui.editNodeId->setText(QString::fromStdString(entityId));
1184 GraphVisualizerWidget::editGraphNode()
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);
1195 mat,
ui.editFrameName->text().toStdString(),
ui.editAgentName->text().toStdString());
1197 pose,
ui.editNodeName->text().toStdString(),
ui.editSceneName->text().toStdString());
1198 auto id =
ui.editNodeId->text().toStdString();
1201 graphSeg->updateEntity(
id, node);
1202 gnpr->forceRefetch(
id);
1203 if (
ui.scenesComboBox->currentText().toStdString() ==
ui.editSceneName->text().toStdString())
1212 int row =
ui.tableWidgetNodes->rowAt(pos.y());
1213 auto nodeIt = std::find_if(nodes.begin(),
1215 [&](
const std::pair<std::string, NodeData>& d)
1216 { return d.second.tableWidgetNodesIndex == row; });
1218 QAction* deleteAction = menu.addAction(
"Delete Node");
1220 if (menu.exec(QCursor::pos()) == deleteAction)
1223 graphSeg->removeNode(nodeIt->second.node->getId());
1231 int row =
ui.tableWidgetEdges->rowAt(pos.y());
1232 auto edgeIt = std::find_if(edges.begin(),
1234 [&](
const std::pair<EdgeId, EdgeData>& d)
1235 { return d.second.tableWidgetEdgesIndex == row; });
1237 QAction* deleteAction = menu.addAction(
"Delete Edge");
1239 if (menu.exec(QCursor::pos()) == deleteAction)
1242 graphSeg->removeEdge(edgeIt->first.first, edgeIt->first.second);
1250 if (obj ==
gvw->
ui.graphicsViewGraph && event->type() == QEvent::MouseButtonPress)
1252 QMouseEvent* me =
static_cast<QMouseEvent*
>(event);
1253 if (me->button() == Qt::LeftButton)
1255 QPointF scenePoint =
gvw->
ui.graphicsViewGraph->mapToScene(me->pos());
1256 scenePoint.setY(-scenePoint.y());
1259 auto bestIt =
gvw->nodes.cend();
1261 for (
auto it =
gvw->nodes.cbegin(); it !=
gvw->nodes.cend(); ++it)
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);
1274 if (bestIt !=
gvw->nodes.cend())
1276 gvw->nodeDoubleClicked(bestIt->first);
1280 else if (event->type() == QEvent::Resize)
1284 return QObject::eventFilter(obj, event);