30 #include <QGraphicsView>
31 #include <QVBoxLayout>
32 #include <QGraphicsScene>
33 #include <QGraphicsEllipseItem>
34 #include <QGraphicsRectItem>
35 #include <QtGui/QWheelEvent>
36 #include <QGraphicsSceneHoverEvent>
38 #include <QtGui/QDesktopServices>
39 #include <QtGui/QContextMenuEvent>
40 #include <QColorDialog>
42 #include <QFileDialog>
44 #include <QtSvg/QSvgGenerator>
46 #include <QInputDialog>
47 #include <QMessageBox>
50 #include <QtCore/QDir>
51 #include <QtCore/QDateTime>
52 #include <QtCore/QUrl>
62 #if QT_VERSION >= 0x050000
63 #include <QStandardPaths>
75 QGraphicsEllipseItem(QRectF(-radius*100.0
f,-radius*100.0
f,radius*100.0
f*2.0
f,radius*100.0
f*2.0
f)),
83 this->setBrush(pen().color());
84 this->setAcceptHoverEvents(
true);
89 QPen pen =
_line->pen();
90 pen.setWidth(linkWidth*100.0
f);
100 QBrush
b = this->brush();
104 QPen pen =
_line->pen();
105 pen.setColor(QColor(255-color.red(), 255-color.green(), 255-color.blue()));
114 this->setRect(-radius, -radius, radius*2.0
f, radius*2.0
f);
125 this->setPos(
pose.
x()*100.0f,-
pose.
z()*100.0f);
128 this->setPos(
pose.
y()*100.0f,-
pose.
z()*100.0f);
131 this->setPos(-
pose.
y()*100.0f,-
pose.
x()*100.0f);
139 float radius = this->rect().width()/2.0f;
156 QGraphicsEllipseItem::hoverEnterEvent(event);
162 QGraphicsEllipseItem::hoverEnterEvent(event);
185 this->setToolTip(QString(
"%1 [%2] %3\n"
186 "longitude=%4 latitude=%5 altitude=%6m error=%7m bearing=%8deg")
190 QGraphicsEllipseItem::hoverEnterEvent(event);
209 this->setAcceptHoverEvents(
true);
215 QPen
p = this->pen();
225 this->setLine(poseA.
x()*100.0f, -poseA.
z()*100.0f, poseB.
x()*100.0f, -poseB.
z()*100.0f);
228 this->setLine(poseA.
y()*100.0f, -poseA.
z()*100.0f, poseB.
y()*100.0f, -poseB.
z()*100.0f);
231 this->setLine(-poseA.
y()*100.0f, -poseA.
x()*100.0f, -poseB.
y()*100.0f, -poseB.
x()*100.0f);
260 this->setToolTip(
str);
261 QPen pen = this->pen();
262 pen.setWidthF(pen.widthF()+2);
264 QGraphicsLineItem::hoverEnterEvent(event);
269 QPen pen = this->pen();
270 pen.setWidthF(pen.widthF()-2);
272 QGraphicsLineItem::hoverEnterEvent(event);
285 QGraphicsView(parent),
286 _nodeColor(Qt::blue),
287 _nodeOdomCacheColor(Qt::darkGreen),
288 _currentGoalColor(Qt::darkMagenta),
289 _neighborColor(Qt::blue),
290 _loopClosureColor(Qt::red),
291 _loopClosureLocalColor(Qt::yellow),
292 _loopClosureUserColor(Qt::red),
293 _loopClosureVirtualColor(Qt::magenta),
294 _neighborMergedColor(QColor(255,170,0)),
295 _landmarkColor(Qt::darkGreen),
296 _loopClosureRejectedColor(Qt::black),
297 _localPathColor(Qt::cyan),
298 _globalPathColor(Qt::darkMagenta),
299 _gtPathColor(Qt::gray),
300 _gpsPathColor(Qt::darkCyan),
301 _loopIntraSessionColor(Qt::red),
302 _loopInterSessionColor(Qt::green),
303 _intraInterSessionColors(
false),
304 _worldMapRotation(0.0
f),
314 _originReferential(0),
317 _loopClosureOutlierThr(0),
318 _maxLinkLength(0.02
f),
319 _orientationENU(
false),
320 _mouseTracking(
false),
322 _ensureFrameVisible(
true)
324 this->setScene(
new QGraphicsScene(
this));
325 this->setDragMode(QGraphicsView::ScrollHandDrag);
328 this->scene()->clear();
329 _world = (QGraphicsItem *)this->scene()->addEllipse(QRectF(-0.0001,-0.0001,0.0001,0.0001));
330 _root = (QGraphicsItem *)this->scene()->addEllipse(QRectF(-0.0001,-0.0001,0.0001,0.0001));
334 QGraphicsLineItem * item;
341 item = this->scene()->addLine(0,0,0,-100, QPen(QBrush(Qt::red),
_linkWidth));
343 item->setParentItem(
_root);
345 item = this->scene()->addLine(0,0,-100,0, QPen(QBrush(Qt::green),
_linkWidth));
347 item->setParentItem(
_root);
354 item = this->scene()->addLine(0,0,100,0, QPen(QBrush(Qt::red),
_linkWidth));
356 item->setParentItem(
_root);
358 item = this->scene()->addLine(0,0,0,-100, QPen(QBrush(Qt::blue),
_linkWidth));
360 item->setParentItem(
_root);
368 item = this->scene()->addLine(0,0,100,0, QPen(QBrush(Qt::green),
_linkWidth));
370 item->setParentItem(
_root);
372 item = this->scene()->addLine(0,0,0,-100, QPen(QBrush(Qt::blue),
_linkWidth));
374 item->setParentItem(
_root);
389 item = this->scene()->addLine(0,0,0,-50, QPen(QBrush(Qt::red),
_linkWidth));
390 item->setZValue(100);
391 item->setParentItem(
_root);
393 item = this->scene()->addLine(0,0,-50,0, QPen(QBrush(Qt::green),
_linkWidth));
394 item->setZValue(100);
395 item->setParentItem(
_root);
402 item = this->scene()->addLine(0,0,50,0, QPen(QBrush(Qt::red),
_linkWidth));
403 item->setZValue(100);
404 item->setParentItem(
_root);
406 item = this->scene()->addLine(0,0,0,-50, QPen(QBrush(Qt::blue),
_linkWidth));
407 item->setZValue(100);
408 item->setParentItem(
_root);
416 item = this->scene()->addLine(0,0,50,0, QPen(QBrush(Qt::green),
_linkWidth));
417 item->setZValue(100);
418 item->setParentItem(
_root);
420 item = this->scene()->addLine(0,0,0,-50, QPen(QBrush(Qt::blue),
_linkWidth));
421 item->setZValue(100);
422 item->setParentItem(
_root);
430 _localRadius = this->scene()->addEllipse(-0.0001,-0.0001,0.0001,0.0001);
436 _gridMap = this->scene()->addPixmap(QPixmap());
440 _graphRoot = (QGraphicsItem *)this->scene()->addEllipse(QRectF(-0.0001,-0.0001,0.0001,0.0001));
444 _globalPathRoot = (QGraphicsItem *)this->scene()->addEllipse(QRectF(-0.0001,-0.0001,0.0001,0.0001));
448 _localPathRoot = (QGraphicsItem *)this->scene()->addEllipse(QRectF(-0.0001,-0.0001,0.0001,0.0001));
452 _gtGraphRoot = (QGraphicsItem *)this->scene()->addEllipse(QRectF(-0.0001,-0.0001,0.0001,0.0001));
456 _gpsGraphRoot = (QGraphicsItem *)this->scene()->addEllipse(QRectF(-0.0001,-0.0001,0.0001,0.0001));
468 this->fitInView(this->sceneRect(), Qt::KeepAspectRatio);
482 const std::multimap<int, Link> & constraints,
483 const std::map<int, int> & mapIds,
484 const std::map<int, int> & weights,
485 const std::set<int> & odomCacheIds)
492 UDEBUG(
"poses=%d constraints=%d", (
int)poses.size(), (
int)constraints.size());
497 bool isOdomCache = odomCacheIds.find(
iter.key()) != odomCacheIds.end();
500 color = QColor(255-color.red(), 255-color.green(), 255-color.blue());
515 for(std::map<int, Transform>::const_iterator
iter=poses.begin();
iter!=poses.end(); ++
iter)
517 if(!
iter->second.isNull())
519 QMap<int, NodeItem*>::iterator itemIter =
_nodeItems.find(
iter->first);
523 itemIter.value()->show();
529 bool isOdomCache = odomCacheIds.find(
iter->first) != odomCacheIds.end();
532 color = QColor(255-color.red(), 255-color.green(), 255-color.blue());
540 this->scene()->addItem(item);
541 item->setZValue(
iter->first<0?21:20);
550 for(std::multimap<int, Link>::const_iterator
iter=constraints.begin();
iter!=constraints.end(); ++
iter)
556 std::map<int, Transform>::const_iterator jterA = poses.find(idFrom);
557 std::map<int, Transform>::const_iterator jterB = poses.find(idTo);
559 if(jterA != poses.end() && jterB != poses.end() &&
565 QMultiMap<int, LinkItem*>::iterator itemIter =
_linkItems.end();
569 while(itemIter.key() == idFrom && itemIter !=
_linkItems.end())
571 if(itemIter.value()->to() == idTo && itemIter.value()->type() ==
iter->second.type())
573 itemIter.value()->setPoses(poseA, poseB,
_viewPlane);
574 itemIter.value()->show();
575 linkItem = itemIter.value();
582 bool interSessionClosure =
false;
585 interSessionClosure = mapIds.at(jterA->first) != mapIds.at(jterB->first);
588 bool isLinkedToOdomCachePoses =
589 odomCacheIds.find(idFrom)!=odomCacheIds.end() ||
590 odomCacheIds.find(idTo)!=odomCacheIds.end();
592 if(isLinkedToOdomCachePoses)
594 _nodeItems.value(idFrom)->setZValue(odomCacheIds.find(idFrom)!=odomCacheIds.end()?24:23);
595 _nodeItems.value(idTo)->setZValue(odomCacheIds.find(idTo)!=odomCacheIds.end()?24:23);
604 QPen
p = linkItem->pen();
607 linkItem->setZValue(isLinkedToOdomCachePoses?22:10);
608 this->scene()->addItem(linkItem);
613 else if(linkItem && itemIter !=
_linkItems.end())
656 linkItem->setZValue(isLinkedToOdomCachePoses?22:interSessionClosure?6:7);
661 linkItem->setZValue(isLinkedToOdomCachePoses?22:7);
669 linkItem->setZValue(isLinkedToOdomCachePoses?22:interSessionClosure?8:9);
674 linkItem->setZValue(isLinkedToOdomCachePoses?22:9);
682 if(
iter->second.to() != idTo)
689 float linearError =
fabs(
iter->second.transform().getNorm() -
t.getNorm());
731 this->scene()->setSceneRect(this->scene()->itemsBoundingRect());
733 if(!odomCacheIds.empty())
740 QRectF rect = this->scene()->itemsBoundingRect();
741 this->fitInView(rect.adjusted(-rect.width()/2.0f, -rect.height()/2.0f, rect.width()/2.0f, rect.height()/2.0f), Qt::KeepAspectRatio);
755 UDEBUG(
"poses=%d", (
int)poses.size());
767 for(std::map<int, Transform>::const_iterator
iter=poses.begin();
iter!=poses.end(); ++
iter)
769 if(!
iter->second.isNull())
775 itemIter.value()->show();
782 this->scene()->addItem(item);
790 if(
iter!=poses.begin())
792 std::map<int, Transform>::const_iterator iterPrevious =
iter;
794 Transform previousPose = iterPrevious->second;
798 QMultiMap<int, LinkItem*>::iterator linkIter =
_gtLinkItems.end();
802 while(linkIter.key() == iterPrevious->first && linkIter !=
_gtLinkItems.end())
804 if(linkIter.value()->to() ==
iter->first)
806 linkIter.value()->setPoses(previousPose, currentPose,
_viewPlane);
807 linkIter.value()->show();
808 linkItem = linkIter.value();
816 bool linkFound =
iter->first - iterPrevious->first == 1;
817 for(QMultiMap<int, LinkItem*>::iterator kter =
_linkItems.find(iterPrevious->first);
818 kter!=
_linkItems.end() && kter.key()==iterPrevious->first && !linkFound;
821 if(kter.value()->from() == iterPrevious->first && kter.value()->to() ==
iter->first)
831 QPen
p = linkItem->pen();
834 linkItem->setZValue(10);
835 this->scene()->addItem(linkItem);
876 this->scene()->setSceneRect(this->scene()->itemsBoundingRect());
880 QRectF rect = this->scene()->itemsBoundingRect();
881 this->fitInView(rect.adjusted(-rect.width()/2.0f, -rect.height()/2.0f, rect.width()/2.0f, rect.height()/2.0f), Qt::KeepAspectRatio);
891 const std::map<int, Transform> & poses,
892 const std::map<int, GPS> & gpsValues)
898 UDEBUG(
"poses=%d", (
int)poses.size());
910 for(std::map<int, Transform>::const_iterator
iter=poses.begin();
iter!=poses.end(); ++
iter)
912 if(!
iter->second.isNull())
918 itemIter.value()->show();
924 UASSERT(gpsValues.find(
iter->first) != gpsValues.end());
926 this->scene()->addItem(item);
934 if(
iter!=poses.begin())
936 std::map<int, Transform>::const_iterator iterPrevious =
iter;
938 Transform previousPose = iterPrevious->second;
942 QMultiMap<int, LinkItem*>::iterator linkIter =
_gpsLinkItems.end();
946 while(linkIter.key() == iterPrevious->first && linkIter !=
_gpsLinkItems.end())
948 if(linkIter.value()->to() ==
iter->first)
950 linkIter.value()->setPoses(previousPose, currentPose,
_viewPlane);
951 linkIter.value()->show();
952 linkItem = linkIter.value();
962 QPen
p = linkItem->pen();
965 linkItem->setZValue(10);
966 this->scene()->addItem(linkItem);
1006 this->scene()->setSceneRect(this->scene()->itemsBoundingRect());
1010 QRectF rect = this->scene()->itemsBoundingRect();
1011 this->fitInView(rect.adjusted(-rect.width()/2.0f, -rect.height()/2.0f, rect.width()/2.0f, rect.height()/2.0f), Qt::KeepAspectRatio);
1023 qt.translate(-
t.o24()*100.0f, -
t.o14()*100.0f);
1025 qt.rotateRadians(-
t.theta());
1042 UASSERT(map8U.empty() || (!map8U.empty() && resolution > 0.0f));
1048 _gridMap->setTransform(QTransform::fromScale(resolution*100.0
f, -resolution*100.0
f),
true);
1050 _gridMap->setPixmap(QPixmap::fromImage(image));
1051 _gridMap->setPos(-yMin*100.0
f, -xMin*100.0
f);
1053 this->scene()->setSceneRect(this->scene()->itemsBoundingRect());
1066 for(std::map<int, float>::const_iterator
iter = posterior.begin();
iter!=posterior.end(); ++
iter)
1078 std::map<int,float>::const_iterator jter = posterior.find(
iter.key());
1079 if(jter != posterior.end())
1081 float v = jter->second>
max?
max:jter->second;
1082 iter.
value()->setColor(QColor::fromHsvF((1-
v/
max)*240.0
f/360.0
f, 1, 1, 1));
1091 UDEBUG(
"Set global path size=%d", (
int)globalPath.size());
1095 if(globalPath.size() >= 2)
1097 for(
unsigned int i=0;
i<globalPath.size()-1; ++
i)
1100 int idFrom = globalPath[
i].first;
1101 int idTo = globalPath[
i+1].first;
1103 QPen
p = item->pen();
1107 this->scene()->addItem(item);
1108 item->setZValue(15);
1124 UWARN(
"Current goal %d not found in the graph",
id);
1141 _localRadius->setRect(-radius*100, -radius*100, radius*200, radius*200);
1154 if(localPath.size() > 1)
1156 for(
unsigned int i=0;
i<localPath.size()-1; ++
i)
1158 int idFrom = localPath[
i]<localPath[
i+1]?localPath[
i]:localPath[
i+1];
1159 int idTo = localPath[
i]<localPath[
i+1]?localPath[
i+1]:localPath[
i];
1168 if(itemIter.value()->to() == idTo)
1171 itemIter.value()->show();
1182 QPen
p = item->pen();
1186 this->scene()->addItem(item);
1187 item->setZValue(16);
1230 _root->resetTransform();
1234 this->scene()->setSceneRect(this->scene()->itemsBoundingRect());
1241 this->scene()->setSceneRect(this->scene()->itemsBoundingRect());
1260 if(!group.isEmpty())
1262 settings.beginGroup(group);
1264 settings.setValue(
"node_radius", (
double)this->
getNodeRadius());
1265 settings.setValue(
"link_width", (
double)this->
getLinkWidth());
1278 settings.setValue(
"gt_color", this->
getGTColor());
1279 settings.setValue(
"gps_color", this->
getGPSColor());
1296 settings.setValue(
"view_plane", (
int)this->
getViewPlane());
1298 if(!group.isEmpty())
1300 settings.endGroup();
1306 if(!group.isEmpty())
1308 settings.beginGroup(group);
1310 this->
setNodeRadius(settings.value(
"node_radius",
this->getNodeRadius()).toDouble());
1311 this->
setLinkWidth(settings.value(
"link_width",
this->getLinkWidth()).toDouble());
1312 this->
setNodeColor(settings.value(
"node_color",
this->getNodeColor()).value<QColor>());
1315 this->
setNeighborColor(settings.value(
"neighbor_color",
this->getNeighborColor()).value<QColor>());
1322 this->
setLocalPathColor(settings.value(
"local_path_color",
this->getLocalPathColor()).value<QColor>());
1323 this->
setGlobalPathColor(settings.value(
"global_path_color",
this->getGlobalPathColor()).value<QColor>());
1324 this->
setGTColor(settings.value(
"gt_color",
this->getGTColor()).value<QColor>());
1325 this->
setGPSColor(settings.value(
"gps_color",
this->getGPSColor()).value<QColor>());
1334 this->
setMaxLinkLength(settings.value(
"max_link_length",
this->getMaxLinkLength()).toDouble());
1344 if(!group.isEmpty())
1346 settings.endGroup();
1442 QList<QGraphicsItem*> items = this->scene()->items();
1443 for(
int i=0;
i<items.size(); ++
i)
1445 QGraphicsLineItem * line = qgraphicsitem_cast<QGraphicsLineItem *>(items[
i]);
1448 QPen pen = line->pen();
1658 UWARN(
"Grid map can be shown only with view plane is XY.");
1710 UWARN(
"ENU orientation can be set only with view plane is XY.");
1723 this->scene()->setSceneRect(this->scene()->itemsBoundingRect());
1754 this->scene()->setSceneRect(this->scene()->itemsBoundingRect());
1784 if(event->angleDelta().y() < 0)
1786 this->
scale(0.95, 0.95);
1790 this->
scale(1.05, 1.05);
1796 QPointF scenePoint = mapToScene(event->pos());
1799 #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
1800 QToolTip::showText(event->globalPosition().toPoint(), QString(
"%1m %2m").
arg(-scenePoint.y()/100.0).
arg(-scenePoint.x()/100.0));
1802 QToolTip::showText(event->globalPos(), QString(
"%1m %2m").
arg(-scenePoint.y()/100.0).
arg(-scenePoint.x()/100.0));
1807 QToolTip::hideText();
1809 QGraphicsView::mouseMoveEvent(event);
1814 QGraphicsItem *item = this->scene()->itemAt(mapToScene(event->pos()), QTransform());
1817 NodeItem *nodeItem = qgraphicsitem_cast<NodeItem*>(item);
1818 LinkItem *linkItem = qgraphicsitem_cast<LinkItem*>(item);
1819 if(nodeItem && nodeItem->parentItem() ==
_graphRoot && nodeItem->
id() != 0)
1823 else if(linkItem && linkItem->parentItem() ==
_graphRoot && linkItem->
from() != 0 && linkItem->
to() != 0)
1829 QGraphicsView::mouseDoubleClickEvent(event);
1834 QGraphicsView::mouseDoubleClickEvent(event);
1840 QPixmap pixmap(50, 50);
1842 return QIcon(pixmap);
1848 QAction * aScreenShot = menu.addAction(tr(
"Take a screenshot..."));
1849 QAction * aExportGridMap = menu.addAction(tr(
"Export grid map..."));
1850 aExportGridMap->setEnabled(!
_gridMap->pixmap().isNull());
1851 menu.addSeparator();
1856 aChangeNodeColor->setIconVisibleInMenu(
true);
1857 aChangeNodeOdomCacheColor->setIconVisibleInMenu(
true);
1858 aChangeCurrentGoalColor->setIconVisibleInMenu(
true);
1861 QMenu * menuLink = menu.addMenu(tr(
"Set link color..."));
1862 QAction * aChangeNeighborColor = menuLink->addAction(tr(
"Neighbor"));
1863 QAction * aChangeGlobalLoopColor = menuLink->addAction(tr(
"Global loop closure"));
1864 QAction * aChangeLocalLoopColor = menuLink->addAction(tr(
"Local loop closure"));
1865 QAction * aChangeUserLoopColor = menuLink->addAction(tr(
"User loop closure"));
1866 QAction * aChangeVirtualLoopColor = menuLink->addAction(tr(
"Virtual loop closure"));
1867 QAction * aChangeNeighborMergedColor = menuLink->addAction(tr(
"Neighbor merged"));
1868 QAction * aChangeLandmarkColor = menuLink->addAction(tr(
"Landmark"));
1869 QAction * aChangeRejectedLoopColor = menuLink->addAction(tr(
"Outlier loop closure"));
1870 QAction * aChangeRejectedLoopThr = menuLink->addAction(tr(
"Set outlier threshold..."));
1871 QAction * aChangeLocalPathColor = menuLink->addAction(tr(
"Local path"));
1872 QAction * aChangeGlobalPathColor = menuLink->addAction(tr(
"Global path"));
1873 QAction * aChangeGTColor = menuLink->addAction(tr(
"Ground truth"));
1874 QAction * aChangeGPSColor = menuLink->addAction(tr(
"GPS"));
1875 menuLink->addSeparator();
1876 QAction * aSetIntraInterSessionColors = menuLink->addAction(tr(
"Enable intra/inter-session colors"));
1877 QAction * aChangeIntraSessionLoopColor = menuLink->addAction(tr(
"Intra-session loop closure"));
1878 QAction * aChangeInterSessionLoopColor = menuLink->addAction(tr(
"Inter-session loop closure"));
1893 aChangeNeighborColor->setIconVisibleInMenu(
true);
1894 aChangeGlobalLoopColor->setIconVisibleInMenu(
true);
1895 aChangeLocalLoopColor->setIconVisibleInMenu(
true);
1896 aChangeUserLoopColor->setIconVisibleInMenu(
true);
1897 aChangeVirtualLoopColor->setIconVisibleInMenu(
true);
1898 aChangeNeighborMergedColor->setIconVisibleInMenu(
true);
1899 aChangeRejectedLoopColor->setIconVisibleInMenu(
true);
1900 aChangeLocalPathColor->setIconVisibleInMenu(
true);
1901 aChangeGlobalPathColor->setIconVisibleInMenu(
true);
1902 aChangeGTColor->setIconVisibleInMenu(
true);
1903 aChangeGPSColor->setIconVisibleInMenu(
true);
1904 aChangeIntraSessionLoopColor->setIconVisibleInMenu(
true);
1905 aChangeInterSessionLoopColor->setIconVisibleInMenu(
true);
1906 aSetIntraInterSessionColors->setCheckable(
true);
1909 menu.addSeparator();
1910 QAction * aSetNodeSize = menu.addAction(tr(
"Set node radius..."));
1911 QAction * aSetLinkSize = menu.addAction(tr(
"Set link width..."));
1912 QAction * aChangeMaxLinkLength = menu.addAction(tr(
"Set maximum link length..."));
1913 menu.addSeparator();
1914 QAction * aEnsureFrameVisible;
1915 QAction * aShowHideGridMap;
1916 QAction * aShowHideGraph;
1917 QAction * aShowHideGraphNodes;
1918 QAction * aShowHideOrigin;
1919 QAction * aShowHideReferential;
1920 QAction * aShowHideLocalRadius;
1921 QAction * aShowHideGlobalPath;
1922 QAction * aShowHideLocalPath;
1923 QAction * aShowHideGtGraph;
1924 QAction * aShowHideGPSGraph;
1925 QAction * aShowHideOdomCacheOverlay;
1926 QAction * aOrientationENU;
1927 QAction * aMouseTracking;
1928 QAction * aViewPlaneXY;
1929 QAction * aViewPlaneXZ;
1930 QAction * aViewPlaneYZ;
1931 aEnsureFrameVisible = menu.addAction(tr(
"Ensure Frame Visible"));
1932 aEnsureFrameVisible->setCheckable(
true);
1936 aShowHideGridMap = menu.addAction(tr(
"Hide grid map"));
1940 aShowHideGridMap = menu.addAction(tr(
"Show grid map"));
1945 aShowHideOrigin = menu.addAction(tr(
"Hide origin referential"));
1949 aShowHideOrigin = menu.addAction(tr(
"Show origin referential"));
1953 aShowHideReferential = menu.addAction(tr(
"Hide current referential"));
1957 aShowHideReferential = menu.addAction(tr(
"Show current referential"));
1961 aShowHideLocalRadius = menu.addAction(tr(
"Hide local radius"));
1965 aShowHideLocalRadius = menu.addAction(tr(
"Show local radius"));
1969 aShowHideGraph = menu.addAction(tr(
"Hide graph"));
1973 aShowHideGraph = menu.addAction(tr(
"Show graph"));
1977 aShowHideGraphNodes = menu.addAction(tr(
"Hide graph nodes"));
1981 aShowHideGraphNodes = menu.addAction(tr(
"Show graph nodes"));
1985 aShowHideGlobalPath = menu.addAction(tr(
"Hide global path"));
1989 aShowHideGlobalPath = menu.addAction(tr(
"Show global path"));
1993 aShowHideLocalPath = menu.addAction(tr(
"Hide local path"));
1997 aShowHideLocalPath = menu.addAction(tr(
"Show local path"));
2001 aShowHideGtGraph = menu.addAction(tr(
"Hide ground truth graph"));
2005 aShowHideGtGraph = menu.addAction(tr(
"Show ground truth graph"));
2009 aShowHideGPSGraph = menu.addAction(tr(
"Hide GPS graph"));
2013 aShowHideGPSGraph = menu.addAction(tr(
"Show GPS graph"));
2017 aShowHideOdomCacheOverlay = menu.addAction(tr(
"Hide odom cache overlay"));
2021 aShowHideOdomCacheOverlay = menu.addAction(tr(
"Show odom cache overlay"));
2023 aOrientationENU = menu.addAction(tr(
"ENU Orientation"));
2024 aOrientationENU->setCheckable(
true);
2026 aMouseTracking = menu.addAction(tr(
"Show mouse cursor position (m)"));
2027 aMouseTracking->setCheckable(
true);
2038 QMenu * viewPlaneMenu = menu.addMenu(
"View Plane...");
2039 aViewPlaneXY = viewPlaneMenu->addAction(
"XY");
2040 aViewPlaneXY->setCheckable(
true);
2042 aViewPlaneXZ = viewPlaneMenu->addAction(
"XZ");
2043 aViewPlaneXZ->setCheckable(
true);
2045 aViewPlaneYZ = viewPlaneMenu->addAction(
"YZ");
2046 aViewPlaneYZ->setCheckable(
true);
2049 menu.addSeparator();
2050 QAction * aRestoreDefaults = menu.addAction(tr(
"Restore defaults"));
2052 QAction * r = menu.exec(event->globalPos());
2053 if(r == aScreenShot)
2058 #if QT_VERSION >= 0x050000
2059 filePath = QStandardPaths::writableLocation(QStandardPaths::PicturesLocation);
2062 if(!dir.exists(filePath))
2064 filePath = QDir::homePath();
2066 filePath +=
"/graph.png";
2069 filePath = QFileDialog::getSaveFileName(
this, tr(
"Save figure to ..."), filePath,
"*.png *.xpm *.jpg *.pdf *.svg");
2071 filePath = QFileDialog::getSaveFileName(
this, tr(
"Save figure to ..."), filePath,
"*.png *.xpm *.jpg *.pdf");
2073 if(!filePath.isEmpty())
2075 if(QFileInfo(filePath).suffix() ==
"")
2090 this->scene()->clearSelection();
2091 this->scene()->setSceneRect(this->scene()->itemsBoundingRect());
2092 QSize sceneSize = this->scene()->sceneRect().size().toSize();
2094 if(QFileInfo(filePath).suffix().
compare(
"pdf") == 0)
2096 QPrinter printer(QPrinter::HighResolution);
2097 printer.setPageOrientation(QPageLayout::Portrait);
2098 printer.setOutputFileName( filePath );
2099 QPainter
p(&printer);
2100 scene()->render(&
p);
2103 else if(QFileInfo(filePath).suffix().
compare(
"svg") == 0)
2106 QSvgGenerator svgGen;
2108 svgGen.setFileName( filePath );
2109 svgGen.setSize(sceneSize);
2111 int borderH = sceneSize.width()/100;
2112 int borderV = sceneSize.height()/100;
2113 svgGen.setViewBox(QRect(-borderH, -borderV, sceneSize.width()+borderH*2, sceneSize.height()+borderV*2));
2114 svgGen.setTitle(tr(
"RTAB-Map graph"));
2115 svgGen.setDescription(tr(
"RTAB-Map map and graph"));
2117 QPainter painter( &svgGen );
2119 this->scene()->render(&painter);
2121 UERROR(
"RTAB-MAp is not built with Qt's SVG library, cannot save picture in svg format.");
2126 QImage image(sceneSize, QImage::Format_ARGB32);
2127 image.fill(Qt::transparent);
2128 QPainter painter(&image);
2130 this->scene()->render(&painter);
2133 image.save(filePath);
2137 QMessageBox::warning(
this,
2139 tr(
"Could not export in PNG (the scene may be too large %1x%2), try saving in SVG.").
arg(sceneSize.width()).
arg(sceneSize.height()));
2145 this->scene()->setSceneRect(this->scene()->itemsBoundingRect());
2148 QDesktopServices::openUrl(QUrl::fromLocalFile(filePath));
2153 else if(r == aExportGridMap)
2155 float xMin, yMin, cellSize;
2161 QString
path = QFileDialog::getSaveFileName(
2169 if(QFileInfo(
path).suffix() ==
"")
2176 QString yaml =
info.absolutePath() +
"/" +
info.baseName() +
".yaml";
2178 float occupancyThr = Parameters::defaultGridGlobalOccupancyThr();
2181 file.open (yaml.toStdString());
2182 file <<
"image: " <<
info.baseName().toStdString() <<
".pgm" << std::endl;
2183 file <<
"resolution: " << cellSize << std::endl;
2184 file <<
"origin: [" << xMin <<
", " << yMin <<
", 0.0]" << std::endl;
2185 file <<
"negate: 0" << std::endl;
2186 file <<
"occupied_thresh: " << occupancyThr << std::endl;
2187 file <<
"free_thresh: 0.196" << std::endl;
2192 QMessageBox::information(
this, tr(
"Export 2D map"), tr(
"Exported %1 and %2!").
arg(
path).
arg(yaml));
2195 else if(r == aSetIntraInterSessionColors)
2199 else if(r == aChangeRejectedLoopThr)
2202 double value = QInputDialog::getDouble(
this, tr(
"Loop closure outlier threshold"), tr(
"Value (m)"),
_loopClosureOutlierThr, 0.0, 1000.0, 2, &ok);
2208 else if(r == aChangeMaxLinkLength)
2211 double value = QInputDialog::getDouble(
this, tr(
"Maximum link length to be shown"), tr(
"Value (m)"),
_maxLinkLength, 0.0, 1000.0, 3, &ok);
2217 else if(r == aChangeNodeColor ||
2218 r == aChangeNodeOdomCacheColor ||
2219 r == aChangeCurrentGoalColor ||
2220 r == aChangeNeighborColor ||
2221 r == aChangeGlobalLoopColor ||
2222 r == aChangeLocalLoopColor ||
2223 r == aChangeUserLoopColor ||
2224 r == aChangeVirtualLoopColor ||
2225 r == aChangeNeighborMergedColor ||
2226 r == aChangeRejectedLoopColor ||
2227 r == aChangeLocalPathColor ||
2228 r == aChangeGlobalPathColor ||
2229 r == aChangeGTColor ||
2230 r == aChangeGPSColor ||
2231 r == aChangeIntraSessionLoopColor ||
2232 r == aChangeInterSessionLoopColor)
2235 if(r == aChangeNodeColor)
2239 else if(r == aChangeNodeOdomCacheColor)
2243 else if(r == aChangeCurrentGoalColor)
2247 else if(r == aChangeGlobalLoopColor)
2251 else if(r == aChangeLocalLoopColor)
2255 else if(r == aChangeUserLoopColor)
2259 else if(r == aChangeVirtualLoopColor)
2263 else if(r == aChangeNeighborMergedColor)
2267 else if(r == aChangeLandmarkColor)
2271 else if(r == aChangeRejectedLoopColor)
2275 else if(r == aChangeLocalPathColor)
2279 else if(r == aChangeGlobalPathColor)
2283 else if(r == aChangeGTColor)
2287 else if(r == aChangeGPSColor)
2291 else if(r == aChangeIntraSessionLoopColor)
2295 else if(r == aChangeInterSessionLoopColor)
2303 color = QColorDialog::getColor(color,
this);
2307 if(r == aChangeNodeColor)
2311 else if(r == aChangeNodeOdomCacheColor)
2315 else if(r == aChangeCurrentGoalColor)
2319 else if(r == aChangeGlobalLoopColor)
2323 else if(r == aChangeLocalLoopColor)
2327 else if(r == aChangeUserLoopColor)
2331 else if(r == aChangeVirtualLoopColor)
2335 else if(r == aChangeNeighborMergedColor)
2339 else if(r == aChangeLandmarkColor)
2343 else if(r == aChangeRejectedLoopColor)
2347 else if(r == aChangeLocalPathColor)
2351 else if(r == aChangeGlobalPathColor)
2355 else if(r == aChangeGTColor)
2359 else if(r == aChangeGPSColor)
2363 else if(r == aChangeIntraSessionLoopColor)
2367 else if(r == aChangeInterSessionLoopColor)
2381 else if(r == aSetNodeSize)
2384 double value = QInputDialog::getDouble(
this, tr(
"Node radius"), tr(
"Radius (m)"),
_nodeRadius, 0.001, 100, 3, &ok);
2390 else if(r == aSetLinkSize)
2393 double value = QInputDialog::getDouble(
this, tr(
"Link width"), tr(
"Width (m)"),
_linkWidth, 0, 100, 2, &ok);
2399 else if(r == aEnsureFrameVisible)
2403 else if(r == aShowHideGridMap)
2411 else if(r == aShowHideOrigin)
2415 else if(r == aShowHideReferential)
2419 else if(r == aShowHideLocalRadius)
2423 else if(r == aRestoreDefaults)
2427 else if(r == aShowHideGraph)
2431 else if(r == aShowHideGraphNodes)
2435 else if(r == aShowHideGlobalPath)
2439 else if(r == aShowHideLocalPath)
2443 else if(r == aShowHideGtGraph)
2447 else if(r == aShowHideGPSGraph)
2451 else if(r == aShowHideOdomCacheOverlay)
2455 else if(r == aOrientationENU)
2459 else if(r == aMouseTracking)
2463 else if(r == aViewPlaneXY)
2467 else if(r == aViewPlaneXZ)
2471 else if(r == aViewPlaneYZ)