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> 49 #include <QtCore/QDir> 50 #include <QtCore/QDateTime> 51 #include <QtCore/QUrl> 61 #if QT_VERSION >= 0x050000 62 #include <QStandardPaths> 72 QGraphicsEllipseItem(QRectF(-radius*100.0
f,-radius*100.0
f,radius*100.0
f*2.0
f,radius*100.0
f*2.0
f)),
80 this->setBrush(pen().color());
81 this->setAcceptHoverEvents(
true);
85 _line =
new QGraphicsLineItem(0,0,-radius*
sin(yaw),-radius*
cos(yaw),
this);
86 QPen pen =
_line->pen();
87 pen.setWidth(linkWidth*100.0
f);
97 QBrush b = this->brush();
101 QPen pen =
_line->pen();
102 pen.setColor(QColor(255-color.red(), 255-color.green(), 255-color.blue()));
111 this->setRect(-radius, -radius, radius*2.0
f, radius*2.0f);
112 _line->setLine(0,0,-radius*
sin(yaw),-radius*
cos(yaw));
122 this->setPos(pose.
x()*100.0f,-pose.
z()*100.0f);
125 this->setPos(pose.
y()*100.0f,-pose.
z()*100.0f);
128 this->setPos(-pose.
y()*100.0f,-pose.
x()*100.0f);
146 QGraphicsEllipseItem::hoverEnterEvent(event);
152 QGraphicsEllipseItem::hoverEnterEvent(event);
167 NodeItem(id, mapId, pose, radius, -1, plane, linkWidth),
175 this->setToolTip(QString(
"%1 [%2] %3\n" 176 "longitude=%4 latitude=%5 altitude=%6m error=%7m bearing=%8deg")
177 .arg(
id()).arg(
mapId()).arg(
pose().prettyPrint().c_str())
178 .arg(_gps.longitude()).arg(_gps.latitude()).arg(_gps.altitude()).arg(_gps.error()).arg(_gps.bearing()));
180 QGraphicsEllipseItem::hoverEnterEvent(event);
196 _interSession(interSessionClosure)
198 this->setPoses(poseA, poseB, plane);
199 this->setAcceptHoverEvents(
true);
205 QPen p = this->pen();
215 this->setLine(poseA.
x()*100.0f, -poseA.
z()*100.0f, poseB.
x()*100.0f, -poseB.
z()*100.0f);
218 this->setLine(poseA.
y()*100.0f, -poseA.
z()*100.0f, poseB.
y()*100.0f, -poseB.
z()*100.0f);
221 this->setLine(-poseA.
y()*100.0f, -poseA.
x()*100.0f, -poseB.
y()*100.0f, -poseB.
x()*100.0f);
239 int from()
const {
return _from;}
240 int to()
const {
return _to;}
245 QString str = QString(
"%1->%2 (%3 m)").arg(_from).arg(_to).arg(_poseA.getDistance(_poseB));
246 if(!_link.transform().isNull())
248 str.append(QString(
"\n%1\n%2 %3").arg(_link.transform().prettyPrint().c_str()).arg(_link.transVariance()).arg(_link.rotVariance()));
250 this->setToolTip(str);
251 QPen pen = this->pen();
252 pen.setWidthF(pen.widthF()+2);
254 QGraphicsLineItem::hoverEnterEvent(event);
259 QPen pen = this->pen();
260 pen.setWidthF(pen.widthF()-2);
262 QGraphicsLineItem::hoverEnterEvent(event);
275 QGraphicsView(parent),
276 _nodeColor(Qt::blue),
277 _nodeOdomCacheColor(Qt::darkGreen),
278 _currentGoalColor(Qt::darkMagenta),
279 _neighborColor(Qt::blue),
280 _loopClosureColor(Qt::red),
281 _loopClosureLocalColor(Qt::yellow),
282 _loopClosureUserColor(Qt::red),
283 _loopClosureVirtualColor(Qt::magenta),
284 _neighborMergedColor(QColor(255,170,0)),
285 _landmarkColor(Qt::darkGreen),
286 _loopClosureRejectedColor(Qt::black),
287 _localPathColor(Qt::cyan),
288 _globalPathColor(Qt::darkMagenta),
289 _gtPathColor(Qt::gray),
290 _gpsPathColor(Qt::darkCyan),
291 _loopIntraSessionColor(Qt::red),
292 _loopInterSessionColor(Qt::green),
293 _intraInterSessionColors(
false),
294 _worldMapRotation(0.0
f),
304 _originReferential(0),
307 _loopClosureOutlierThr(0),
308 _maxLinkLength(0.02
f),
309 _orientationENU(
false),
311 _ensureFrameVisible(
true)
313 this->setScene(
new QGraphicsScene(
this));
314 this->setDragMode(QGraphicsView::ScrollHandDrag);
317 this->scene()->clear();
318 _world = (QGraphicsItem *)this->scene()->addEllipse(QRectF(-0.0001,-0.0001,0.0001,0.0001));
319 _root = (QGraphicsItem *)this->scene()->addEllipse(QRectF(-0.0001,-0.0001,0.0001,0.0001));
323 QGraphicsLineItem * item;
330 item = this->scene()->addLine(0,0,0,-100, QPen(QBrush(Qt::red),
_linkWidth));
332 item->setParentItem(
_root);
334 item = this->scene()->addLine(0,0,-100,0, QPen(QBrush(Qt::green),
_linkWidth));
336 item->setParentItem(
_root);
343 item = this->scene()->addLine(0,0,100,0, QPen(QBrush(Qt::red),
_linkWidth));
345 item->setParentItem(
_root);
347 item = this->scene()->addLine(0,0,0,-100, QPen(QBrush(Qt::blue),
_linkWidth));
349 item->setParentItem(
_root);
357 item = this->scene()->addLine(0,0,100,0, QPen(QBrush(Qt::green),
_linkWidth));
359 item->setParentItem(
_root);
361 item = this->scene()->addLine(0,0,0,-100, QPen(QBrush(Qt::blue),
_linkWidth));
363 item->setParentItem(
_root);
378 item = this->scene()->addLine(0,0,0,-50, QPen(QBrush(Qt::red),
_linkWidth));
379 item->setZValue(100);
380 item->setParentItem(
_root);
382 item = this->scene()->addLine(0,0,-50,0, QPen(QBrush(Qt::green),
_linkWidth));
383 item->setZValue(100);
384 item->setParentItem(
_root);
391 item = this->scene()->addLine(0,0,50,0, QPen(QBrush(Qt::red),
_linkWidth));
392 item->setZValue(100);
393 item->setParentItem(
_root);
395 item = this->scene()->addLine(0,0,0,-50, QPen(QBrush(Qt::blue),
_linkWidth));
396 item->setZValue(100);
397 item->setParentItem(
_root);
405 item = this->scene()->addLine(0,0,50,0, QPen(QBrush(Qt::green),
_linkWidth));
406 item->setZValue(100);
407 item->setParentItem(
_root);
409 item = this->scene()->addLine(0,0,0,-50, QPen(QBrush(Qt::blue),
_linkWidth));
410 item->setZValue(100);
411 item->setParentItem(
_root);
419 _localRadius = this->scene()->addEllipse(-0.0001,-0.0001,0.0001,0.0001);
425 _gridMap = this->scene()->addPixmap(QPixmap());
429 _graphRoot = (QGraphicsItem *)this->scene()->addEllipse(QRectF(-0.0001,-0.0001,0.0001,0.0001));
433 _globalPathRoot = (QGraphicsItem *)this->scene()->addEllipse(QRectF(-0.0001,-0.0001,0.0001,0.0001));
437 _localPathRoot = (QGraphicsItem *)this->scene()->addEllipse(QRectF(-0.0001,-0.0001,0.0001,0.0001));
441 _gtGraphRoot = (QGraphicsItem *)this->scene()->addEllipse(QRectF(-0.0001,-0.0001,0.0001,0.0001));
445 _gpsGraphRoot = (QGraphicsItem *)this->scene()->addEllipse(QRectF(-0.0001,-0.0001,0.0001,0.0001));
457 this->fitInView(this->sceneRect(), Qt::KeepAspectRatio);
471 const std::multimap<int, Link> & constraints,
472 const std::map<int, int> & mapIds,
473 const std::map<int, int> & weights,
474 const std::set<int> & odomCacheIds)
481 UDEBUG(
"poses=%d constraints=%d", (
int)poses.size(), (int)constraints.size());
486 bool isOdomCache = odomCacheIds.find(iter.key()) != odomCacheIds.end();
489 color = QColor(255-color.red(), 255-color.green(), 255-color.blue());
495 iter.value()->hide();
496 iter.value()->setColor(color);
497 iter.value()->setZValue(iter.key()<0?21:20);
499 for(QMultiMap<int, LinkItem*>::iterator iter =
_linkItems.begin(); iter!=
_linkItems.end(); ++iter)
501 iter.value()->hide();
504 for(std::map<int, Transform>::const_iterator iter=poses.begin(); iter!=poses.end(); ++iter)
506 if(!iter->second.isNull())
508 QMap<int, NodeItem*>::iterator itemIter =
_nodeItems.find(iter->first);
511 itemIter.value()->setPose(iter->second,
_viewPlane);
512 itemIter.value()->show();
518 bool isOdomCache = odomCacheIds.find(iter->first) != odomCacheIds.end();
521 color = QColor(255-color.red(), 255-color.green(), 255-color.blue());
529 this->scene()->addItem(item);
530 item->setZValue(iter->first<0?21:20);
539 for(std::multimap<int, Link>::const_iterator iter=constraints.begin(); iter!=constraints.end(); ++iter)
542 int idFrom = iter->first<iter->second.to()?iter->first:iter->second.to();
543 int idTo = iter->first<iter->second.to()?iter->second.to():iter->first;
545 std::map<int, Transform>::const_iterator jterA = poses.find(idFrom);
546 std::map<int, Transform>::const_iterator jterB = poses.find(idTo);
548 if(jterA != poses.end() && jterB != poses.end() &&
554 QMultiMap<int, LinkItem*>::iterator itemIter =
_linkItems.end();
558 while(itemIter.key() == idFrom && itemIter !=
_linkItems.end())
560 if(itemIter.value()->to() == idTo)
562 itemIter.value()->setPoses(poseA, poseB,
_viewPlane);
563 itemIter.value()->show();
564 linkItem = itemIter.value();
571 bool interSessionClosure =
false;
574 interSessionClosure = mapIds.at(jterA->first) != mapIds.at(jterB->first);
577 bool isLinkedToOdomCachePoses =
578 odomCacheIds.find(idFrom)!=odomCacheIds.end() ||
579 odomCacheIds.find(idTo)!=odomCacheIds.end();
581 if(isLinkedToOdomCachePoses)
583 _nodeItems.value(idFrom)->setZValue(odomCacheIds.find(idFrom)!=odomCacheIds.end()?24:23);
584 _nodeItems.value(idTo)->setZValue(odomCacheIds.find(idTo)!=odomCacheIds.end()?24:23);
592 linkItem =
new LinkItem(idFrom, idTo, poseA, poseB, iter->second, interSessionClosure,
_viewPlane);
593 QPen p = linkItem->pen();
596 linkItem->setZValue(isLinkedToOdomCachePoses?22:10);
597 this->scene()->addItem(linkItem);
602 else if(linkItem && itemIter !=
_linkItems.end())
645 linkItem->setZValue(isLinkedToOdomCachePoses?22:interSessionClosure?6:7);
650 linkItem->setZValue(isLinkedToOdomCachePoses?22:7);
658 linkItem->setZValue(isLinkedToOdomCachePoses?22:interSessionClosure?8:9);
663 linkItem->setZValue(isLinkedToOdomCachePoses?22:9);
671 if(iter->second.to() != idTo)
678 float linearError = fabs(iter->second.transform().getNorm() - t.
getNorm());
692 if(!iter.value()->isVisible())
704 if(!iter.value()->isVisible())
720 this->scene()->setSceneRect(this->scene()->itemsBoundingRect());
722 if(!odomCacheIds.empty())
729 QRectF rect = this->scene()->itemsBoundingRect();
730 this->fitInView(rect.adjusted(-rect.width()/2.0f, -rect.height()/2.0f, rect.width()/2.0f, rect.height()/2.0f), Qt::KeepAspectRatio);
744 UDEBUG(
"poses=%d", (
int)poses.size());
748 iter.value()->hide();
753 iter.value()->hide();
756 for(std::map<int, Transform>::const_iterator iter=poses.begin(); iter!=poses.end(); ++iter)
758 if(!iter->second.isNull())
760 QMap<int, NodeItem*>::iterator itemIter =
_gtNodeItems.find(iter->first);
763 itemIter.value()->setPose(iter->second,
_viewPlane);
764 itemIter.value()->show();
771 this->scene()->addItem(item);
779 if(iter!=poses.begin())
781 std::map<int, Transform>::const_iterator iterPrevious = iter;
783 Transform previousPose = iterPrevious->second;
787 QMultiMap<int, LinkItem*>::iterator linkIter =
_gtLinkItems.end();
791 while(linkIter.key() == iterPrevious->first && linkIter !=
_gtLinkItems.end())
793 if(linkIter.value()->to() == iter->first)
795 linkIter.value()->setPoses(previousPose, currentPose,
_viewPlane);
796 linkIter.value()->show();
797 linkItem = linkIter.value();
805 bool linkFound = iter->first - iterPrevious->first == 1;
806 for(QMultiMap<int, LinkItem*>::iterator kter =
_linkItems.find(iterPrevious->first);
807 kter!=
_linkItems.end() && kter.key()==iterPrevious->first && !linkFound;
810 if(kter.value()->from() == iterPrevious->first && kter.value()->to() == iter->first)
819 linkItem =
new LinkItem(iterPrevious->first, iter->first, previousPose, currentPose,
Link(), 1,
_viewPlane);
820 QPen p = linkItem->pen();
823 linkItem->setZValue(10);
824 this->scene()->addItem(linkItem);
840 if(!iter.value()->isVisible())
852 if(!iter.value()->isVisible())
865 this->scene()->setSceneRect(this->scene()->itemsBoundingRect());
869 QRectF rect = this->scene()->itemsBoundingRect();
870 this->fitInView(rect.adjusted(-rect.width()/2.0f, -rect.height()/2.0f, rect.width()/2.0f, rect.height()/2.0f), Qt::KeepAspectRatio);
880 const std::map<int, Transform> & poses,
881 const std::map<int, GPS> & gpsValues)
887 UDEBUG(
"poses=%d", (
int)poses.size());
891 iter.value()->hide();
896 iter.value()->hide();
899 for(std::map<int, Transform>::const_iterator iter=poses.begin(); iter!=poses.end(); ++iter)
901 if(!iter->second.isNull())
903 QMap<int, NodeItem*>::iterator itemIter =
_gpsNodeItems.find(iter->first);
906 itemIter.value()->setPose(iter->second,
_viewPlane);
907 itemIter.value()->show();
913 UASSERT(gpsValues.find(iter->first) != gpsValues.end());
915 this->scene()->addItem(item);
923 if(iter!=poses.begin())
925 std::map<int, Transform>::const_iterator iterPrevious = iter;
927 Transform previousPose = iterPrevious->second;
931 QMultiMap<int, LinkItem*>::iterator linkIter =
_gpsLinkItems.end();
935 while(linkIter.key() == iterPrevious->first && linkIter !=
_gpsLinkItems.end())
937 if(linkIter.value()->to() == iter->first)
939 linkIter.value()->setPoses(previousPose, currentPose,
_viewPlane);
940 linkIter.value()->show();
941 linkItem = linkIter.value();
950 linkItem =
new LinkItem(iterPrevious->first, iter->first, previousPose, currentPose,
Link(), 1,
_viewPlane);
951 QPen p = linkItem->pen();
954 linkItem->setZValue(10);
955 this->scene()->addItem(linkItem);
970 if(!iter.value()->isVisible())
982 if(!iter.value()->isVisible())
995 this->scene()->setSceneRect(this->scene()->itemsBoundingRect());
999 QRectF rect = this->scene()->itemsBoundingRect();
1000 this->fitInView(rect.adjusted(-rect.width()/2.0f, -rect.height()/2.0f, rect.width()/2.0f, rect.height()/2.0f), Qt::KeepAspectRatio);
1012 qt.translate(-t.
o24()*100.0f, -t.
o14()*100.0f);
1014 qt.rotateRadians(-t.
theta());
1031 UASSERT(map8U.empty() || (!map8U.empty() && resolution > 0.0f));
1037 _gridMap->setTransform(QTransform::fromScale(resolution*100.0
f, -resolution*100.0f),
true);
1039 _gridMap->setPixmap(QPixmap::fromImage(image));
1040 _gridMap->setPos(-yMin*100.0f, -xMin*100.0f);
1042 this->scene()->setSceneRect(this->scene()->itemsBoundingRect());
1055 for(std::map<int, float>::const_iterator iter = posterior.begin(); iter!=posterior.end(); ++iter)
1057 if(iter->first > 0 && iter->second>max)
1067 std::map<int,float>::const_iterator jter = posterior.find(iter.key());
1068 if(jter != posterior.end())
1070 float v = jter->second>max?
max:jter->second;
1071 iter.value()->setColor(QColor::fromHsvF((1-v/max)*240.0
f/360.0
f, 1, 1, 1));
1072 iter.value()->setZValue(iter.value()->zValue()+zValueOffset);
1080 UDEBUG(
"Set global path size=%d", (
int)globalPath.size());
1084 if(globalPath.size() >= 2)
1086 for(
unsigned int i=0; i<globalPath.size()-1; ++i)
1089 int idFrom = globalPath[i].first;
1090 int idTo = globalPath[i+1].first;
1092 QPen p = item->pen();
1096 this->scene()->addItem(item);
1097 item->setZValue(15);
1113 UWARN(
"Current goal %d not found in the graph",
id);
1123 iter.value()->setPoses(t*iter.value()->getPoseA(), t*iter.value()->getPoseB(),
_viewPlane);
1130 _localRadius->setRect(-radius*100, -radius*100, radius*200, radius*200);
1140 iter.value()->hide();
1143 if(localPath.size() > 1)
1145 for(
unsigned int i=0; i<localPath.size()-1; ++i)
1147 int idFrom = localPath[i]<localPath[i+1]?localPath[i]:localPath[i+1];
1148 int idTo = localPath[i]<localPath[i+1]?localPath[i+1]:localPath[i];
1151 bool updated =
false;
1157 if(itemIter.value()->to() == idTo)
1160 itemIter.value()->show();
1171 QPen p = item->pen();
1175 this->scene()->addItem(item);
1176 item->setZValue(16);
1187 if(!iter.value()->isVisible())
1189 delete iter.value();
1219 _root->resetTransform();
1223 this->scene()->setSceneRect(this->scene()->itemsBoundingRect());
1230 this->scene()->setSceneRect(this->scene()->itemsBoundingRect());
1237 iter.value()->setColor(Qt::blue);
1249 if(!group.isEmpty())
1251 settings.beginGroup(group);
1253 settings.setValue(
"node_radius", (
double)this->
getNodeRadius());
1254 settings.setValue(
"link_width", (
double)this->
getLinkWidth());
1267 settings.setValue(
"gt_color", this->
getGTColor());
1268 settings.setValue(
"gps_color", this->
getGPSColor());
1285 settings.setValue(
"view_plane", (
int)this->
getViewPlane());
1287 if(!group.isEmpty())
1289 settings.endGroup();
1295 if(!group.isEmpty())
1297 settings.beginGroup(group);
1299 this->
setNodeRadius(settings.value(
"node_radius", this->getNodeRadius()).toDouble());
1300 this->
setLinkWidth(settings.value(
"link_width", this->getLinkWidth()).toDouble());
1301 this->
setNodeColor(settings.value(
"node_color", this->getNodeColor()).value<QColor>());
1302 this->
setNodeOdomCacheColor(settings.value(
"node_odom_cache_color", this->getNodeOdomCacheColor()).value<QColor>());
1303 this->
setCurrentGoalColor(settings.value(
"current_goal_color", this->getCurrentGoalColor()).value<QColor>());
1304 this->
setNeighborColor(settings.value(
"neighbor_color", this->getNeighborColor()).value<QColor>());
1309 this->
setNeighborMergedColor(settings.value(
"neighbor_merged_color", this->getNeighborMergedColor()).value<QColor>());
1311 this->
setLocalPathColor(settings.value(
"local_path_color", this->getLocalPathColor()).value<QColor>());
1312 this->
setGlobalPathColor(settings.value(
"global_path_color", this->getGlobalPathColor()).value<QColor>());
1313 this->
setGTColor(settings.value(
"gt_color", this->getGTColor()).value<QColor>());
1314 this->
setGPSColor(settings.value(
"gps_color", this->getGPSColor()).value<QColor>());
1315 this->
setIntraSessionLoopColor(settings.value(
"intra_session_color", this->getIntraSessionLoopColor()).value<QColor>());
1316 this->
setInterSessionLoopColor(settings.value(
"inter_session_color", this->getInterSessionLoopColor()).value<QColor>());
1317 this->
setGridMapVisible(settings.value(
"grid_visible", this->isGridMapVisible()).toBool());
1318 this->
setOriginVisible(settings.value(
"origin_visible", this->isOriginVisible()).toBool());
1319 this->
setReferentialVisible(settings.value(
"referential_visible", this->isReferentialVisible()).toBool());
1320 this->
setLocalRadiusVisible(settings.value(
"local_radius_visible", this->isLocalRadiusVisible()).toBool());
1322 this->
setLoopClosureOutlierThr(settings.value(
"loop_closure_outlier_thr", this->getLoopClosureOutlierThr()).toDouble());
1323 this->
setMaxLinkLength(settings.value(
"max_link_length", this->getMaxLinkLength()).toDouble());
1324 this->
setGraphVisible(settings.value(
"graph_visible", this->isGraphVisible()).toBool());
1325 this->
setGlobalPathVisible(settings.value(
"global_path_visible", this->isGlobalPathVisible()).toBool());
1326 this->
setLocalPathVisible(settings.value(
"local_path_visible", this->isLocalPathVisible()).toBool());
1327 this->
setGtGraphVisible(settings.value(
"gt_graph_visible", this->isGtGraphVisible()).toBool());
1328 this->
setGPSGraphVisible(settings.value(
"gps_graph_visible", this->isGPSGraphVisible()).toBool());
1330 this->
setOrientationENU(settings.value(
"orientation_ENU", this->isOrientationENU()).toBool());
1332 this->
setEnsureFrameVisible(settings.value(
"ensure_frame_visible", this->isEnsureFrameVisible()).toBool());
1333 if(!group.isEmpty())
1335 settings.endGroup();
1431 QList<QGraphicsItem*> items = this->scene()->items();
1432 for(
int i=0; i<items.size(); ++i)
1434 QGraphicsLineItem * line = qgraphicsitem_cast<QGraphicsLineItem *>(items[i]);
1437 QPen pen = line->pen();
1456 if(iter.value()->zValue() == 24)
1469 for(QMultiMap<int, LinkItem*>::iterator iter=
_linkItems.begin(); iter!=
_linkItems.end(); ++iter)
1482 for(QMultiMap<int, LinkItem*>::iterator iter=
_linkItems.begin(); iter!=
_linkItems.end(); ++iter)
1487 iter.value()->setZValue(10);
1497 for(QMultiMap<int, LinkItem*>::iterator iter=
_linkItems.begin(); iter!=
_linkItems.end(); ++iter)
1503 iter.value()->setZValue(10);
1511 for(QMultiMap<int, LinkItem*>::iterator iter=
_linkItems.begin(); iter!=
_linkItems.end(); ++iter)
1522 for(QMultiMap<int, LinkItem*>::iterator iter=
_linkItems.begin(); iter!=
_linkItems.end(); ++iter)
1533 for(QMultiMap<int, LinkItem*>::iterator iter=
_linkItems.begin(); iter!=
_linkItems.end(); ++iter)
1544 for(QMultiMap<int, LinkItem*>::iterator iter=
_linkItems.begin(); iter!=
_linkItems.end(); ++iter)
1593 for(QMultiMap<int, LinkItem*>::iterator iter=
_linkItems.begin(); iter!=
_linkItems.end(); ++iter)
1599 !iter.value()->isInterSession())
1602 iter.value()->setZValue(9);
1612 for(QMultiMap<int, LinkItem*>::iterator iter=
_linkItems.begin(); iter!=
_linkItems.end(); ++iter)
1618 iter.value()->isInterSession())
1621 iter.value()->setZValue(8);
1647 UWARN(
"Grid map can be shown only with view plane is XY.");
1699 UWARN(
"ENU orientation can be set only with view plane is XY.");
1711 _root->setTransform(t);
1715 _root->resetTransform();
1719 this->scene()->setSceneRect(this->scene()->itemsBoundingRect());
1734 iter.value()->setPose(iter.value()->pose(),
_viewPlane);
1736 for(QMultiMap<int, LinkItem*>::iterator iter=
_linkItems.begin(); iter!=
_linkItems.end(); ++iter)
1738 iter.value()->setPoses(iter.value()->getPoseA(), iter.value()->getPoseB(),
_viewPlane);
1750 this->scene()->setSceneRect(this->scene()->itemsBoundingRect());
1780 if(event->delta() < 0)
1782 this->
scale(0.95, 0.95);
1786 this->
scale(1.05, 1.05);
1792 QPixmap pixmap(50, 50);
1794 return QIcon(pixmap);
1800 QAction * aScreenShot = menu.addAction(tr(
"Take a screenshot..."));
1801 menu.addSeparator();
1806 aChangeNodeColor->setIconVisibleInMenu(
true);
1807 aChangeNodeOdomCacheColor->setIconVisibleInMenu(
true);
1808 aChangeCurrentGoalColor->setIconVisibleInMenu(
true);
1811 QMenu * menuLink = menu.addMenu(tr(
"Set link color..."));
1812 QAction * aChangeNeighborColor = menuLink->addAction(tr(
"Neighbor"));
1813 QAction * aChangeGlobalLoopColor = menuLink->addAction(tr(
"Global loop closure"));
1814 QAction * aChangeLocalLoopColor = menuLink->addAction(tr(
"Local loop closure"));
1815 QAction * aChangeUserLoopColor = menuLink->addAction(tr(
"User loop closure"));
1816 QAction * aChangeVirtualLoopColor = menuLink->addAction(tr(
"Virtual loop closure"));
1817 QAction * aChangeNeighborMergedColor = menuLink->addAction(tr(
"Neighbor merged"));
1818 QAction * aChangeLandmarkColor = menuLink->addAction(tr(
"Landmark"));
1819 QAction * aChangeRejectedLoopColor = menuLink->addAction(tr(
"Outlier loop closure"));
1820 QAction * aChangeRejectedLoopThr = menuLink->addAction(tr(
"Set outlier threshold..."));
1821 QAction * aChangeLocalPathColor = menuLink->addAction(tr(
"Local path"));
1822 QAction * aChangeGlobalPathColor = menuLink->addAction(tr(
"Global path"));
1823 QAction * aChangeGTColor = menuLink->addAction(tr(
"Ground truth"));
1824 QAction * aChangeGPSColor = menuLink->addAction(tr(
"GPS"));
1825 menuLink->addSeparator();
1826 QAction * aSetIntraInterSessionColors = menuLink->addAction(tr(
"Enable intra/inter-session colors"));
1827 QAction * aChangeIntraSessionLoopColor = menuLink->addAction(tr(
"Intra-session loop closure"));
1828 QAction * aChangeInterSessionLoopColor = menuLink->addAction(tr(
"Inter-session loop closure"));
1843 aChangeNeighborColor->setIconVisibleInMenu(
true);
1844 aChangeGlobalLoopColor->setIconVisibleInMenu(
true);
1845 aChangeLocalLoopColor->setIconVisibleInMenu(
true);
1846 aChangeUserLoopColor->setIconVisibleInMenu(
true);
1847 aChangeVirtualLoopColor->setIconVisibleInMenu(
true);
1848 aChangeNeighborMergedColor->setIconVisibleInMenu(
true);
1849 aChangeRejectedLoopColor->setIconVisibleInMenu(
true);
1850 aChangeLocalPathColor->setIconVisibleInMenu(
true);
1851 aChangeGlobalPathColor->setIconVisibleInMenu(
true);
1852 aChangeGTColor->setIconVisibleInMenu(
true);
1853 aChangeGPSColor->setIconVisibleInMenu(
true);
1854 aChangeIntraSessionLoopColor->setIconVisibleInMenu(
true);
1855 aChangeInterSessionLoopColor->setIconVisibleInMenu(
true);
1856 aSetIntraInterSessionColors->setCheckable(
true);
1859 menu.addSeparator();
1860 QAction * aSetNodeSize = menu.addAction(tr(
"Set node radius..."));
1861 QAction * aSetLinkSize = menu.addAction(tr(
"Set link width..."));
1862 QAction * aChangeMaxLinkLength = menu.addAction(tr(
"Set maximum link length..."));
1863 menu.addSeparator();
1864 QAction * aEnsureFrameVisible;
1865 QAction * aShowHideGridMap;
1866 QAction * aShowHideGraph;
1867 QAction * aShowHideGraphNodes;
1868 QAction * aShowHideOrigin;
1869 QAction * aShowHideReferential;
1870 QAction * aShowHideLocalRadius;
1871 QAction * aShowHideGlobalPath;
1872 QAction * aShowHideLocalPath;
1873 QAction * aShowHideGtGraph;
1874 QAction * aShowHideGPSGraph;
1875 QAction * aShowHideOdomCacheOverlay;
1876 QAction * aOrientationENU;
1877 QAction * aViewPlaneXY;
1878 QAction * aViewPlaneXZ;
1879 QAction * aViewPlaneYZ;
1880 aEnsureFrameVisible = menu.addAction(tr(
"Ensure Frame Visible"));
1881 aEnsureFrameVisible->setCheckable(
true);
1885 aShowHideGridMap = menu.addAction(tr(
"Hide grid map"));
1889 aShowHideGridMap = menu.addAction(tr(
"Show grid map"));
1894 aShowHideOrigin = menu.addAction(tr(
"Hide origin referential"));
1898 aShowHideOrigin = menu.addAction(tr(
"Show origin referential"));
1902 aShowHideReferential = menu.addAction(tr(
"Hide current referential"));
1906 aShowHideReferential = menu.addAction(tr(
"Show current referential"));
1910 aShowHideLocalRadius = menu.addAction(tr(
"Hide local radius"));
1914 aShowHideLocalRadius = menu.addAction(tr(
"Show local radius"));
1918 aShowHideGraph = menu.addAction(tr(
"Hide graph"));
1922 aShowHideGraph = menu.addAction(tr(
"Show graph"));
1926 aShowHideGraphNodes = menu.addAction(tr(
"Hide graph nodes"));
1930 aShowHideGraphNodes = menu.addAction(tr(
"Show graph nodes"));
1934 aShowHideGlobalPath = menu.addAction(tr(
"Hide global path"));
1938 aShowHideGlobalPath = menu.addAction(tr(
"Show global path"));
1942 aShowHideLocalPath = menu.addAction(tr(
"Hide local path"));
1946 aShowHideLocalPath = menu.addAction(tr(
"Show local path"));
1950 aShowHideGtGraph = menu.addAction(tr(
"Hide ground truth graph"));
1954 aShowHideGtGraph = menu.addAction(tr(
"Show ground truth graph"));
1958 aShowHideGPSGraph = menu.addAction(tr(
"Hide GPS graph"));
1962 aShowHideGPSGraph = menu.addAction(tr(
"Show GPS graph"));
1966 aShowHideOdomCacheOverlay = menu.addAction(tr(
"Hide odom cache overlay"));
1970 aShowHideOdomCacheOverlay = menu.addAction(tr(
"Show odom cache overlay"));
1972 aOrientationENU = menu.addAction(tr(
"ENU Orientation"));
1973 aOrientationENU->setCheckable(
true);
1983 QMenu * viewPlaneMenu = menu.addMenu(
"View Plane...");
1984 aViewPlaneXY = viewPlaneMenu->addAction(
"XY");
1985 aViewPlaneXY->setCheckable(
true);
1987 aViewPlaneXZ = viewPlaneMenu->addAction(
"XZ");
1988 aViewPlaneXZ->setCheckable(
true);
1990 aViewPlaneYZ = viewPlaneMenu->addAction(
"YZ");
1991 aViewPlaneYZ->setCheckable(
true);
1994 menu.addSeparator();
1995 QAction * aRestoreDefaults = menu.addAction(tr(
"Restore defaults"));
1997 QAction * r = menu.exec(event->globalPos());
1998 if(r == aScreenShot)
2003 #if QT_VERSION >= 0x050000 2004 filePath = QStandardPaths::writableLocation(QStandardPaths::PicturesLocation);
2007 if(!dir.exists(filePath))
2009 filePath = QDir::homePath();
2011 filePath +=
"/graph.png";
2014 filePath = QFileDialog::getSaveFileName(
this, tr(
"Save figure to ..."), filePath,
"*.png *.xpm *.jpg *.pdf *.svg");
2016 filePath = QFileDialog::getSaveFileName(
this, tr(
"Save figure to ..."), filePath,
"*.png *.xpm *.jpg *.pdf");
2018 if(!filePath.isEmpty())
2020 if(QFileInfo(filePath).suffix() ==
"")
2032 _root->setScale(this->transform().m11());
2035 this->scene()->clearSelection();
2036 this->scene()->setSceneRect(this->scene()->itemsBoundingRect());
2037 QSize sceneSize = this->scene()->sceneRect().size().toSize();
2039 if(QFileInfo(filePath).suffix().compare(
"pdf") == 0)
2041 QPrinter printer(QPrinter::HighResolution);
2042 printer.setOrientation(QPrinter::Portrait);
2043 printer.setOutputFileName( filePath );
2044 QPainter p(&printer);
2045 scene()->render(&p);
2048 else if(QFileInfo(filePath).suffix().compare(
"svg") == 0)
2051 QSvgGenerator svgGen;
2053 svgGen.setFileName( filePath );
2054 svgGen.setSize(sceneSize);
2056 int borderH = sceneSize.width()/100;
2057 int borderV = sceneSize.height()/100;
2058 svgGen.setViewBox(QRect(-borderH, -borderV, sceneSize.width()+borderH*2, sceneSize.height()+borderV*2));
2059 svgGen.setTitle(tr(
"RTAB-Map graph"));
2060 svgGen.setDescription(tr(
"RTAB-Map map and graph"));
2062 QPainter painter( &svgGen );
2064 this->scene()->render(&painter);
2066 UERROR(
"RTAB-MAp is not built with Qt's SVG library, cannot save picture in svg format.");
2071 QImage image(sceneSize, QImage::Format_ARGB32);
2072 image.fill(Qt::transparent);
2073 QPainter painter(&image);
2075 this->scene()->render(&painter);
2078 image.save(filePath);
2082 QMessageBox::warning(
this,
2084 tr(
"Could not export in PNG (the scene may be too large %1x%2), try saving in SVG.").arg(sceneSize.width()).arg(sceneSize.height()));
2090 this->scene()->setSceneRect(this->scene()->itemsBoundingRect());
2093 QDesktopServices::openUrl(QUrl::fromLocalFile(filePath));
2098 else if(r == aSetIntraInterSessionColors)
2102 else if(r == aChangeRejectedLoopThr)
2105 double value = QInputDialog::getDouble(
this, tr(
"Loop closure outlier threshold"), tr(
"Value (m)"),
_loopClosureOutlierThr, 0.0, 1000.0, 2, &ok);
2111 else if(r == aChangeMaxLinkLength)
2114 double value = QInputDialog::getDouble(
this, tr(
"Maximum link length to be shown"), tr(
"Value (m)"),
_maxLinkLength, 0.0, 1000.0, 3, &ok);
2120 else if(r == aChangeNodeColor ||
2121 r == aChangeNodeOdomCacheColor ||
2122 r == aChangeCurrentGoalColor ||
2123 r == aChangeNeighborColor ||
2124 r == aChangeGlobalLoopColor ||
2125 r == aChangeLocalLoopColor ||
2126 r == aChangeUserLoopColor ||
2127 r == aChangeVirtualLoopColor ||
2128 r == aChangeNeighborMergedColor ||
2129 r == aChangeRejectedLoopColor ||
2130 r == aChangeLocalPathColor ||
2131 r == aChangeGlobalPathColor ||
2132 r == aChangeGTColor ||
2133 r == aChangeGPSColor ||
2134 r == aChangeIntraSessionLoopColor ||
2135 r == aChangeInterSessionLoopColor)
2138 if(r == aChangeNodeColor)
2142 else if(r == aChangeNodeOdomCacheColor)
2146 else if(r == aChangeCurrentGoalColor)
2150 else if(r == aChangeGlobalLoopColor)
2154 else if(r == aChangeLocalLoopColor)
2158 else if(r == aChangeUserLoopColor)
2162 else if(r == aChangeVirtualLoopColor)
2166 else if(r == aChangeNeighborMergedColor)
2170 else if(r == aChangeLandmarkColor)
2174 else if(r == aChangeRejectedLoopColor)
2178 else if(r == aChangeLocalPathColor)
2182 else if(r == aChangeGlobalPathColor)
2186 else if(r == aChangeGTColor)
2190 else if(r == aChangeGPSColor)
2194 else if(r == aChangeIntraSessionLoopColor)
2198 else if(r == aChangeInterSessionLoopColor)
2206 color = QColorDialog::getColor(color,
this);
2210 if(r == aChangeNodeColor)
2214 else if(r == aChangeNodeOdomCacheColor)
2218 else if(r == aChangeCurrentGoalColor)
2222 else if(r == aChangeGlobalLoopColor)
2226 else if(r == aChangeLocalLoopColor)
2230 else if(r == aChangeUserLoopColor)
2234 else if(r == aChangeVirtualLoopColor)
2238 else if(r == aChangeNeighborMergedColor)
2242 else if(r == aChangeLandmarkColor)
2246 else if(r == aChangeRejectedLoopColor)
2250 else if(r == aChangeLocalPathColor)
2254 else if(r == aChangeGlobalPathColor)
2258 else if(r == aChangeGTColor)
2262 else if(r == aChangeGPSColor)
2266 else if(r == aChangeIntraSessionLoopColor)
2270 else if(r == aChangeInterSessionLoopColor)
2284 else if(r == aSetNodeSize)
2287 double value = QInputDialog::getDouble(
this, tr(
"Node radius"), tr(
"Radius (m)"),
_nodeRadius, 0.001, 100, 3, &ok);
2293 else if(r == aSetLinkSize)
2296 double value = QInputDialog::getDouble(
this, tr(
"Link width"), tr(
"Width (m)"),
_linkWidth, 0, 100, 2, &ok);
2302 else if(r == aEnsureFrameVisible)
2306 else if(r == aShowHideGridMap)
2314 else if(r == aShowHideOrigin)
2318 else if(r == aShowHideReferential)
2322 else if(r == aShowHideLocalRadius)
2326 else if(r == aRestoreDefaults)
2330 else if(r == aShowHideGraph)
2334 else if(r == aShowHideGraphNodes)
2338 else if(r == aShowHideGlobalPath)
2342 else if(r == aShowHideLocalPath)
2346 else if(r == aShowHideGtGraph)
2350 else if(r == aShowHideGPSGraph)
2354 else if(r == aShowHideOdomCacheOverlay)
2358 else if(r == aOrientationENU)
2362 else if(r == aViewPlaneXY)
2366 else if(r == aViewPlaneXZ)
2370 else if(r == aViewPlaneYZ)
void setViewPlane(ViewPlane plane)
void setLoopClosureOutlierThr(float value)
virtual void hoverEnterEvent(QGraphicsSceneHoverEvent *event)
QGraphicsItem * _gpsGraphRoot
QColor _loopClosureLocalColor
const QColor & getLocalPathColor() const
void updateGraph(const std::map< int, Transform > &poses, const std::multimap< int, Link > &constraints, const std::map< int, int > &mapIds, const std::map< int, int > &weights=std::map< int, int >(), const std::set< int > &odomCacheIds=std::set< int >())
QColor _loopClosureVirtualColor
void setGlobalPathColor(const QColor &color)
bool isInterSession() const
virtual void hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
QGraphicsItem * _localPathRoot
void setCurrentGoalID(int id, const Transform &pose=Transform())
void setGridMapVisible(bool visible)
bool isLocalPathVisible() const
QColor _neighborMergedColor
const QColor & getIntraSessionLoopColor() const
void setMaxLinkLength(float value)
QGraphicsEllipseItem * _localRadius
QGraphicsItemGroup * _referential
const Transform & pose() const
virtual void hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
virtual void hoverEnterEvent(QGraphicsSceneHoverEvent *event)
void setRadius(float radius)
void setWorkingDirectory(const QString &path)
bool isOriginVisible() const
void setColor(const QColor &color)
void setIntraInterSessionColorsEnabled(bool enabled)
void updateReferentialPosition(const Transform &t)
void setGlobalPathVisible(bool visible)
const QColor & getLocalLoopClosureColor() const
QImage uCvMat2QImage(const cv::Mat &image, bool isBgr=true, uCvQtDepthColorMap colorMap=uCvQtDepthWhiteToBlack, float depthMin=0, float depthMax=0)
void setNeighborColor(const QColor &color)
const QColor & getCurrentGoalColor() const
void setLandmarkColor(const QColor &color)
bool _intraInterSessionColors
float getMaxLinkLength() const
virtual void wheelEvent(QWheelEvent *event)
QGraphicsPixmapItem * _gridMap
void updateLocalPath(const std::vector< int > &localPath)
void setGPSGraphVisible(bool visible)
void setOdomCacheOverlayVisible(bool visible)
void setReferentialVisible(bool visible)
Link::Type linkType() const
void setGPSColor(const QColor &color)
void setGlobalPath(const std::vector< std::pair< int, Transform > > &globalPath)
void setPose(const Transform &pose, GraphViewer::ViewPlane plane)
QMultiMap< int, LinkItem * > _gpsLinkItems
QGraphicsItem * _graphRoot
const QColor & getGlobalPathColor() const
const QColor & getGPSColor() const
bool isOdomCacheOverlayVisible() const
QGraphicsItemGroup * _referentialXY
const QColor & getInterSessionLoopColor() const
float getNodeRadius() const
QColor _loopInterSessionColor
#define UASSERT(condition)
GLM_FUNC_DECL genType cos(genType const &angle)
Wrappers of STL for convenient functions.
const QColor & getRejectedLoopClosureColor() const
QColor _loopClosureRejectedColor
GLM_FUNC_DECL genType sin(genType const &angle)
void setGtGraphVisible(bool visible)
void setColor(const QColor &color)
QColor _loopIntraSessionColor
const QColor & getNodeOdomCacheColor() const
NodeItem(int id, int mapId, const Transform &pose, float radius, int weight, GraphViewer::ViewPlane plane, float linkWidth)
QMultiMap< int, LinkItem * > _globalPathLinkItems
float getLinkWidth() const
void setNeighborMergedColor(const QColor &color)
QGraphicsItemGroup * _originReferential
virtual void hoverEnterEvent(QGraphicsSceneHoverEvent *event)
void setPoses(const Transform &poseA, const Transform &poseB, GraphViewer::ViewPlane plane)
const QColor & getUserLoopClosureColor() const
const QColor & getNeighborMergedColor() const
void setLocalLoopClosureColor(const QColor &color)
const QColor & getNodeColor() const
ViewPlane getViewPlane() const
const Transform & getPoseB() const
QMultiMap< int, LinkItem * > _gtLinkItems
QGraphicsItem * _gtGraphRoot
GraphViewer(QWidget *parent=0)
void setNodeOdomCacheColor(const QColor &color)
QColor _nodeOdomCacheColor
bool isEnsureFrameVisible() const
QGraphicsItemGroup * _originReferentialXZ
void setInterSessionLoopColor(const QColor &color)
float _loopClosureOutlierThr
void setUserLoopClosureColor(const QColor &color)
const QColor & getNeighborColor() const
bool isGlobalPathVisible() const
void setOrientationENU(bool enabled)
void updateMap(const cv::Mat &map8U, float resolution, float xMin, float yMin)
bool uContains(const std::list< V > &list, const V &value)
void setGlobalLoopClosureColor(const QColor &color)
void setEnsureFrameVisible(bool visible)
LinkItem(int from, int to, const Transform &poseA, const Transform &poseB, const Link &link, bool interSessionClosure, GraphViewer::ViewPlane plane)
void setLocalPathColor(const QColor &color)
QMultiMap< int, LinkItem * > _localPathLinkItems
QGraphicsItem * _globalPathRoot
QMap< int, NodeItem * > _gpsNodeItems
bool isGPSGraphVisible() const
void setVirtualLoopClosureColor(const QColor &color)
void setWorldMapRotation(const float &theta)
GLM_FUNC_DECL genType max(genType const &x, genType const &y)
void setIntraSessionLoopColor(const QColor &color)
void setNodeRadius(float radius)
QIcon createIcon(const QColor &color)
QColor _loopClosureUserColor
const QColor & getGlobalLoopClosureColor() const
void updateGTGraph(const std::map< int, Transform > &poses)
const Transform & getPoseA() const
void setGTColor(const QColor &color)
void setGraphVisible(bool visible)
void setNodeColor(const QColor &color)
void setNodeVisible(bool visible)
ULogger class and convenient macros.
QString _workingDirectory
QMultiMap< int, LinkItem * > _linkItems
QGraphicsItemGroup * _referentialXZ
bool isGraphVisible() const
GLM_FUNC_DECL T yaw(detail::tquat< T, P > const &x)
NodeGPSItem(int id, int mapId, const Transform &pose, float radius, const GPS &gps, GraphViewer::ViewPlane plane, float linkWidth)
void updateGPSGraph(const std::map< int, Transform > &gpsMapPoses, const std::map< int, GPS > &gpsValues)
void loadSettings(QSettings &settings, const QString &group="")
bool isOrientationENU() const
void updatePosterior(const std::map< int, float > &posterior, float fixedMax=0.0f, int zValueOffset=0)
void setLocalRadius(float radius)
bool isReferentialVisible() const
bool isIntraInterSessionColorsEnabled() const
virtual void contextMenuEvent(QContextMenuEvent *event)
QMap< int, NodeItem * > _nodeItems
QGraphicsLineItem * _line
QMap< int, NodeItem * > _gtNodeItems
const QColor & getVirtualLoopClosureColor() const
QGraphicsItemGroup * _originReferentialYZ
QGraphicsRectItem * _odomCacheOverlay
void setLocalPathVisible(bool visible)
QGraphicsItemGroup * _originReferentialXY
float getLoopClosureOutlierThr() const
void setOriginVisible(bool visible)
void setCurrentGoalColor(const QColor &color)
void setLocalRadiusVisible(bool visible)
QGraphicsItemGroup * _referentialYZ
void saveSettings(QSettings &settings, const QString &group="") const
bool isGridMapVisible() const
bool isLocalRadiusVisible() const
void setRejectedLoopClosureColor(const QColor &color)
void setLinkWidth(float width)
const QColor & getGTColor() const
bool isGtGraphVisible() const