30 #include "ui_mainWindow.h"
73 #include <QtGui/QCloseEvent>
74 #include <QtGui/QPixmap>
75 #include <QtCore/QDir>
76 #include <QtCore/QFile>
77 #include <QtCore/QTextStream>
78 #include <QtCore/QFileInfo>
79 #include <QMessageBox>
80 #include <QFileDialog>
81 #include <QGraphicsEllipseItem>
82 #include <QDockWidget>
83 #include <QtCore/QBuffer>
84 #include <QtCore/QTimer>
85 #include <QtCore/QTime>
86 #include <QActionGroup>
87 #include <QtGui/QDesktopServices>
88 #include <QtCore/QStringList>
89 #include <QtCore/QProcess>
90 #include <QSplashScreen>
91 #include <QInputDialog>
92 #include <QToolButton>
108 #include <pcl/visualization/cloud_viewer.h>
109 #include <pcl/common/transforms.h>
110 #include <pcl/common/common.h>
111 #include <pcl/io/pcd_io.h>
112 #include <pcl/io/ply_io.h>
113 #include <pcl/filters/filter.h>
114 #include <pcl/search/kdtree.h>
118 #ifdef RTABMAP_OCTOMAP
122 #ifdef RTABMAP_GRIDMAP
126 #ifdef HAVE_OPENCV_ARUCO
127 #include <opencv2/aruco.hpp>
130 #define LOG_FILE_NAME "LogRtabmap.txt"
131 #define SHARE_SHOW_LOG_FILE "share/rtabmap/showlogs.m"
132 #define SHARE_GET_PRECISION_RECALL_FILE "share/rtabmap/getPrecisionRecall.m"
133 #define SHARE_IMPORT_FILE "share/rtabmap/importfile.m"
149 _preferencesDialog(0),
151 _exportCloudsDialog(0),
152 _exportBundlerDialog(0),
156 _processingStatistics(
false),
157 _processingDownloadedMap(
false),
159 _odometryReceived(
false),
160 _newDatabasePath(
""),
161 _newDatabasePathOutput(
""),
162 _openedDatabasePath(
""),
163 _databaseUpdated(
false),
164 _odomImageShow(
true),
165 _odomImageDepthShow(
false),
166 _savedMaximized(
false),
168 _cachedMemoryUsage(0),
169 _createdCloudsMemoryUsage(0),
173 _odometryCorrection(
Transform::getIdentity()),
174 _processingOdometry(
false),
180 _rawLikelihoodCurve(0),
181 _exportPosesFrame(0),
182 _autoScreenCaptureOdomSync(
false),
183 _autoScreenCaptureRAM(
false),
184 _autoScreenCapturePNG(
false),
186 _progressCanceled(
false)
193 QSplashScreen * splash = 0;
194 if (showSplashScreen)
196 QPixmap pixmap(
":images/RTAB-Map.png");
197 splash =
new QSplashScreen(pixmap);
199 splash->showMessage(tr(
"Loading..."));
200 QApplication::processEvents();
215 _ui =
new Ui_mainWindow();
231 UDEBUG(
"Setup ui... end");
233 QString title(
"RTAB-Map[*]");
234 this->setWindowTitle(title);
235 this->setWindowIconText(tr(
"RTAB-Map"));
236 this->setObjectName(
"MainWindow");
241 _ui->widget_mainWindow->setVisible(
false);
257 bool statusBarShown =
false;
274 #ifdef RTABMAP_OCTOMAP
277 #ifdef RTABMAP_GRIDMAP
285 _ui->label_elapsedTime->setText(
"00:00:00");
291 _ui->imageView_source->setBackgroundColor(
_ui->imageView_source->getDefaultBackgroundColor());
292 _ui->imageView_loopClosure->setBackgroundColor(
_ui->imageView_loopClosure->getDefaultBackgroundColor());
293 _ui->imageView_odometry->setBackgroundColor(
_ui->imageView_odometry->getDefaultBackgroundColor());
294 _ui->imageView_odometry->setAlpha(200);
302 _ui->posteriorPlot->showLegend(
false);
303 _ui->posteriorPlot->setFixedYAxis(0,1);
310 _ui->likelihoodPlot->showLegend(
false);
314 _ui->rawLikelihoodPlot->showLegend(
false);
323 connect(
_ui->widget_mapVisibility, SIGNAL(visibilityChanged(
int,
bool)),
this, SLOT(
updateNodeVisibility(
int,
bool)));
326 connect(
_ui->actionExit, SIGNAL(triggered()),
this, SLOT(close()));
327 qRegisterMetaType<MainWindow::State>(
"MainWindow::State");
330 qRegisterMetaType<rtabmap::RtabmapEvent3DMap>(
"rtabmap::RtabmapEvent3DMap");
332 qRegisterMetaType<rtabmap::RtabmapGlobalPathEvent>(
"rtabmap::RtabmapGlobalPathEvent");
338 _ui->menuShow_view->addAction(
_ui->dockWidget_imageView->toggleViewAction());
339 _ui->menuShow_view->addAction(
_ui->dockWidget_posterior->toggleViewAction());
340 _ui->menuShow_view->addAction(
_ui->dockWidget_likelihood->toggleViewAction());
341 _ui->menuShow_view->addAction(
_ui->dockWidget_rawlikelihood->toggleViewAction());
342 _ui->menuShow_view->addAction(
_ui->dockWidget_statsV2->toggleViewAction());
343 _ui->menuShow_view->addAction(
_ui->dockWidget_console->toggleViewAction());
344 _ui->menuShow_view->addAction(
_ui->dockWidget_cloudViewer->toggleViewAction());
345 _ui->menuShow_view->addAction(
_ui->dockWidget_loopClosureViewer->toggleViewAction());
346 _ui->menuShow_view->addAction(
_ui->dockWidget_mapVisibility->toggleViewAction());
347 _ui->menuShow_view->addAction(
_ui->dockWidget_graphViewer->toggleViewAction());
348 _ui->menuShow_view->addAction(
_ui->dockWidget_odometry->toggleViewAction());
349 _ui->menuShow_view->addAction(
_ui->dockWidget_multiSessionLoc->toggleViewAction());
350 _ui->menuShow_view->addAction(
_ui->toolBar->toggleViewAction());
351 _ui->toolBar->setWindowTitle(tr(
"File toolbar"));
352 _ui->menuShow_view->addAction(
_ui->toolBar_2->toggleViewAction());
353 _ui->toolBar_2->setWindowTitle(tr(
"Control toolbar"));
354 QAction *
a =
_ui->menuShow_view->addAction(
"Progress dialog");
355 a->setCheckable(
false);
357 QAction * statusBarAction =
_ui->menuShow_view->addAction(
"Status bar");
358 statusBarAction->setCheckable(
true);
359 statusBarAction->setChecked(statusBarShown);
360 connect(statusBarAction, SIGNAL(toggled(
bool)), this->statusBar(), SLOT(setVisible(
bool)));
363 connect(
_ui->actionSave_GUI_config, SIGNAL(triggered()),
this, SLOT(
saveConfigGUI()));
364 connect(
_ui->actionNew_database, SIGNAL(triggered()),
this, SLOT(
newDatabase()));
365 connect(
_ui->actionOpen_database, SIGNAL(triggered()),
this, SLOT(
openDatabase()));
366 connect(
_ui->actionClose_database, SIGNAL(triggered()),
this, SLOT(
closeDatabase()));
367 connect(
_ui->actionEdit_database, SIGNAL(triggered()),
this, SLOT(
editDatabase()));
371 connect(
_ui->actionDump_the_memory, SIGNAL(triggered()),
this, SLOT(
dumpTheMemory()));
372 connect(
_ui->actionDump_the_prediction_matrix, SIGNAL(triggered()),
this, SLOT(
dumpThePrediction()));
373 connect(
_ui->actionSend_goal, SIGNAL(triggered()),
this, SLOT(
sendGoal()));
374 connect(
_ui->actionSend_waypoints, SIGNAL(triggered()),
this, SLOT(
sendWaypoints()));
375 connect(
_ui->actionCancel_goal, SIGNAL(triggered()),
this, SLOT(
cancelGoal()));
376 connect(
_ui->actionLabel_current_location, SIGNAL(triggered()),
this, SLOT(
label()));
377 connect(
_ui->actionRemove_label, SIGNAL(triggered()),
this, SLOT(
removeLabel()));
378 connect(
_ui->actionClear_cache, SIGNAL(triggered()),
this, SLOT(
clearTheCache()));
380 connect(
_ui->actionHelp, SIGNAL(triggered()),
this , SLOT(
openHelp()));
381 connect(
_ui->actionPrint_loop_closure_IDs_to_console, SIGNAL(triggered()),
this, SLOT(
printLoopClosureIds()));
383 connect(
_ui->actionRaw_format_txt, SIGNAL(triggered()),
this , SLOT(
exportPosesRaw()));
387 connect(
_ui->actionKITTI_format_txt, SIGNAL(triggered()),
this , SLOT(
exportPosesKITTI()));
390 connect(
_ui->actionDelete_memory, SIGNAL(triggered()),
this , SLOT(
deleteMemory()));
396 connect(
_ui->actionDefault_views, SIGNAL(triggered(
bool)),
this, SLOT(
setDefaultViews()));
398 connect(
_ui->actionScreenshot, SIGNAL(triggered()),
this, SLOT(
takeScreenshot()));
408 connect(
_ui->actionSave_point_cloud, SIGNAL(triggered()),
this, SLOT(
exportClouds()));
409 connect(
_ui->actionExport_2D_Grid_map_bmp_png, SIGNAL(triggered()),
this, SLOT(
exportGridMap()));
410 connect(
_ui->actionExport_images_RGB_jpg_Depth_png, SIGNAL(triggered()),
this , SLOT(
exportImages()));
411 connect(
_ui->actionExport_cameras_in_Bundle_format_out, SIGNAL(triggered()), SLOT(
exportBundlerFormat()));
412 connect(
_ui->actionExport_octomap, SIGNAL(triggered()),
this, SLOT(
exportOctomap()));
413 connect(
_ui->actionView_high_res_point_cloud, SIGNAL(triggered()),
this, SLOT(
viewClouds()));
414 connect(
_ui->actionReset_Odometry, SIGNAL(triggered()),
this, SLOT(
resetOdometry()));
415 connect(
_ui->actionTrigger_a_new_map, SIGNAL(triggered()),
this, SLOT(
triggerNewMap()));
416 connect(
_ui->actionData_recorder, SIGNAL(triggered()),
this, SLOT(
dataRecorder()));
418 connect(
_ui->actionDepth_Calibration, SIGNAL(triggered()),
this, SLOT(
depthCalibration()));
420 _ui->actionPause->setShortcut(Qt::Key_Space);
421 _ui->actionSave_GUI_config->setShortcut(QKeySequence::Save);
424 this->addAction(
_ui->actionSave_GUI_config);
425 _ui->actionReset_Odometry->setEnabled(
false);
426 _ui->actionPost_processing->setEnabled(
false);
427 _ui->actionAnchor_clouds_to_ground_truth->setEnabled(
false);
429 QToolButton* toolButton =
new QToolButton(
this);
430 toolButton->setMenu(
_ui->menuSelect_source);
431 toolButton->setPopupMode(QToolButton::InstantPopup);
432 toolButton->setIcon(QIcon(
":images/kinect_xbox_360.png"));
433 toolButton->setToolTip(
"Select sensor driver");
434 _ui->toolBar->addWidget(toolButton)->setObjectName(
"toolbar_source");
436 #if defined(Q_WS_MAC) || defined(Q_WS_WIN)
439 _ui->menuEdit->removeAction(
_ui->actionOpen_working_directory);
444 connect(
_ui->actionOpenNI_PCL, SIGNAL(triggered()),
this, SLOT(
selectOpenni()));
445 connect(
_ui->actionOpenNI_PCL_ASUS, SIGNAL(triggered()),
this, SLOT(
selectOpenni()));
447 connect(
_ui->actionOpenNI_CV, SIGNAL(triggered()),
this, SLOT(
selectOpenniCv()));
449 connect(
_ui->actionOpenNI2, SIGNAL(triggered()),
this, SLOT(
selectOpenni2()));
450 connect(
_ui->actionOpenNI2_kinect, SIGNAL(triggered()),
this, SLOT(
selectOpenni2()));
451 connect(
_ui->actionOpenNI2_orbbec, SIGNAL(triggered()),
this, SLOT(
selectOpenni2()));
452 connect(
_ui->actionOpenNI2_sense, SIGNAL(triggered()),
this, SLOT(
selectOpenni2()));
454 connect(
_ui->actionKinect_for_Windows_SDK_v2, SIGNAL(triggered()),
this, SLOT(
selectK4W2()));
455 connect(
_ui->actionKinect_for_Azure, SIGNAL(triggered()),
this, SLOT(
selectK4A()));
456 connect(
_ui->actionRealSense_R200, SIGNAL(triggered()),
this, SLOT(
selectRealSense()));
457 connect(
_ui->actionRealSense_ZR300, SIGNAL(triggered()),
this, SLOT(
selectRealSense()));
468 connect(
_ui->actionMYNT_EYE_S_SDK, SIGNAL(triggered()),
this, SLOT(
selectMyntEyeS()));
473 connect(
_ui->actionVelodyne_VLP_16, SIGNAL(triggered()),
this, SLOT(
selectVLP16()));
506 QActionGroup * modeGrp =
new QActionGroup(
this);
507 modeGrp->addAction(
_ui->actionSLAM_mode);
508 modeGrp->addAction(
_ui->actionLocalization_mode);
516 qRegisterMetaType<PreferencesDialog::PANEL_FLAGS>(
"PreferencesDialog::PANEL_FLAGS");
518 qRegisterMetaType<rtabmap::ParametersMap>(
"rtabmap::ParametersMap");
536 connect(
_ui->toolBar->toggleViewAction(), SIGNAL(toggled(
bool)),
this, SLOT(
configGUIModified()));
537 connect(
_ui->toolBar, SIGNAL(orientationChanged(Qt::Orientation)),
this, SLOT(
configGUIModified()));
538 connect(statusBarAction, SIGNAL(toggled(
bool)),
this, SLOT(
configGUIModified()));
539 QList<QDockWidget*> dockWidgets = this->findChildren<QDockWidget*>();
540 for(
int i=0;
i<dockWidgets.size(); ++
i)
542 connect(dockWidgets[
i], SIGNAL(dockLocationChanged(Qt::DockWidgetArea)),
this, SLOT(
configGUIModified()));
543 connect(dockWidgets[
i]->toggleViewAction(), SIGNAL(toggled(
bool)),
this, SLOT(
configGUIModified()));
545 connect(
_ui->dockWidget_graphViewer->toggleViewAction(), SIGNAL(triggered()),
this, SLOT(
updateGraphView()));
547 _ui->dockWidget_posterior->installEventFilter(
this);
548 _ui->dockWidget_likelihood->installEventFilter(
this);
549 _ui->dockWidget_rawlikelihood->installEventFilter(
this);
550 _ui->dockWidget_statsV2->installEventFilter(
this);
551 _ui->dockWidget_console->installEventFilter(
this);
552 _ui->dockWidget_loopClosureViewer->installEventFilter(
this);
553 _ui->dockWidget_mapVisibility->installEventFilter(
this);
554 _ui->dockWidget_graphViewer->installEventFilter(
this);
555 _ui->dockWidget_odometry->installEventFilter(
this);
556 _ui->dockWidget_cloudViewer->installEventFilter(
this);
557 _ui->dockWidget_imageView->installEventFilter(
this);
558 _ui->dockWidget_multiSessionLoc->installEventFilter(
this);
572 qRegisterMetaType<rtabmap::Statistics>(
"rtabmap::Statistics");
575 qRegisterMetaType<rtabmap::SensorCaptureInfo>(
"rtabmap::SensorCaptureInfo");
578 qRegisterMetaType<rtabmap::OdometryEvent>(
"rtabmap::OdometryEvent");
587 _ui->statsToolBox->setNewFigureMaxItems(50);
601 if(
_ui->statsToolBox->findChildren<
StatItem*>().size() == 0)
604 for(std::map<std::string, float>::const_iterator
iter = statistics.begin();
iter != statistics.end(); ++
iter)
607 if(!QString((*iter).first.c_str()).contains(
"Gt/"))
609 _ui->statsToolBox->updateStat(QString((*iter).first.c_str()).replace(
'_',
' '),
false);
614 _ui->statsToolBox->updateStat(
"Planning/From/",
false);
615 _ui->statsToolBox->updateStat(
"Planning/Time/ms",
false);
616 _ui->statsToolBox->updateStat(
"Planning/Goal/",
false);
617 _ui->statsToolBox->updateStat(
"Planning/Poses/",
false);
618 _ui->statsToolBox->updateStat(
"Planning/Length/m",
false);
620 _ui->statsToolBox->updateStat(
"Camera/Time capturing/ms",
false);
621 _ui->statsToolBox->updateStat(
"Camera/Time deskewing/ms",
false);
622 _ui->statsToolBox->updateStat(
"Camera/Time undistort depth/ms",
false);
623 _ui->statsToolBox->updateStat(
"Camera/Time bilateral filtering/ms",
false);
624 _ui->statsToolBox->updateStat(
"Camera/Time decimation/ms",
false);
625 _ui->statsToolBox->updateStat(
"Camera/Time disparity/ms",
false);
626 _ui->statsToolBox->updateStat(
"Camera/Time mirroring/ms",
false);
627 _ui->statsToolBox->updateStat(
"Camera/Time histogram equalization/ms",
false);
628 _ui->statsToolBox->updateStat(
"Camera/Time exposure compensation/ms",
false);
629 _ui->statsToolBox->updateStat(
"Camera/Time scan from depth/ms",
false);
630 _ui->statsToolBox->updateStat(
"Camera/Time total/ms",
false);
632 _ui->statsToolBox->updateStat(
"Odometry/ID/",
false);
633 _ui->statsToolBox->updateStat(
"Odometry/Features/",
false);
634 _ui->statsToolBox->updateStat(
"Odometry/Matches/",
false);
635 _ui->statsToolBox->updateStat(
"Odometry/MatchesRatio/",
false);
636 _ui->statsToolBox->updateStat(
"Odometry/Inliers/",
false);
637 _ui->statsToolBox->updateStat(
"Odometry/InliersMeanDistance/m",
false);
638 _ui->statsToolBox->updateStat(
"Odometry/InliersDistribution/",
false);
639 _ui->statsToolBox->updateStat(
"Odometry/InliersRatio/",
false);
640 _ui->statsToolBox->updateStat(
"Odometry/ICPInliersRatio/",
false);
641 _ui->statsToolBox->updateStat(
"Odometry/ICPRotation/rad",
false);
642 _ui->statsToolBox->updateStat(
"Odometry/ICPTranslation/m",
false);
643 _ui->statsToolBox->updateStat(
"Odometry/ICPStructuralComplexity/",
false);
644 _ui->statsToolBox->updateStat(
"Odometry/ICPStructuralDistribution/",
false);
645 _ui->statsToolBox->updateStat(
"Odometry/ICPCorrespondences/",
false);
646 _ui->statsToolBox->updateStat(
"Odometry/ICPRMS/",
false);
647 _ui->statsToolBox->updateStat(
"Odometry/StdDevLin/m",
false);
648 _ui->statsToolBox->updateStat(
"Odometry/StdDevAng/rad",
false);
649 _ui->statsToolBox->updateStat(
"Odometry/VarianceLin/",
false);
650 _ui->statsToolBox->updateStat(
"Odometry/VarianceAng/",
false);
651 _ui->statsToolBox->updateStat(
"Odometry/TimeDeskewing/ms",
false);
652 _ui->statsToolBox->updateStat(
"Odometry/TimeEstimation/ms",
false);
653 _ui->statsToolBox->updateStat(
"Odometry/TimeFiltering/ms",
false);
654 _ui->statsToolBox->updateStat(
"Odometry/GravityRollError/deg",
false);
655 _ui->statsToolBox->updateStat(
"Odometry/GravityPitchError/deg",
false);
656 _ui->statsToolBox->updateStat(
"Odometry/LocalMapSize/",
false);
657 _ui->statsToolBox->updateStat(
"Odometry/LocalScanMapSize/",
false);
658 _ui->statsToolBox->updateStat(
"Odometry/LocalKeyFrames/",
false);
659 _ui->statsToolBox->updateStat(
"Odometry/localBundleOutliers/",
false);
660 _ui->statsToolBox->updateStat(
"Odometry/localBundleConstraints/",
false);
661 _ui->statsToolBox->updateStat(
"Odometry/localBundleTime/ms",
false);
662 _ui->statsToolBox->updateStat(
"Odometry/KeyFrameAdded/",
false);
663 _ui->statsToolBox->updateStat(
"Odometry/Interval/ms",
false);
664 _ui->statsToolBox->updateStat(
"Odometry/Speed/kph",
false);
665 _ui->statsToolBox->updateStat(
"Odometry/Speed/mph",
false);
666 _ui->statsToolBox->updateStat(
"Odometry/Speed/mps",
false);
667 _ui->statsToolBox->updateStat(
"Odometry/SpeedGuess/kph",
false);
668 _ui->statsToolBox->updateStat(
"Odometry/SpeedGuess/mph",
false);
669 _ui->statsToolBox->updateStat(
"Odometry/SpeedGuess/mps",
false);
670 _ui->statsToolBox->updateStat(
"Odometry/Distance/m",
false);
671 _ui->statsToolBox->updateStat(
"Odometry/T/m",
false);
672 _ui->statsToolBox->updateStat(
"Odometry/Tx/m",
false);
673 _ui->statsToolBox->updateStat(
"Odometry/Ty/m",
false);
674 _ui->statsToolBox->updateStat(
"Odometry/Tz/m",
false);
675 _ui->statsToolBox->updateStat(
"Odometry/Troll/deg",
false);
676 _ui->statsToolBox->updateStat(
"Odometry/Tpitch/deg",
false);
677 _ui->statsToolBox->updateStat(
"Odometry/Tyaw/deg",
false);
678 _ui->statsToolBox->updateStat(
"Odometry/Px/m",
false);
679 _ui->statsToolBox->updateStat(
"Odometry/Py/m",
false);
680 _ui->statsToolBox->updateStat(
"Odometry/Pz/m",
false);
681 _ui->statsToolBox->updateStat(
"Odometry/Proll/deg",
false);
682 _ui->statsToolBox->updateStat(
"Odometry/Ppitch/deg",
false);
683 _ui->statsToolBox->updateStat(
"Odometry/Pyaw/deg",
false);
685 _ui->statsToolBox->updateStat(
"GUI/Refresh odom/ms",
false);
686 _ui->statsToolBox->updateStat(
"GUI/RGB-D cloud/ms",
false);
687 _ui->statsToolBox->updateStat(
"GUI/Graph Update/ms",
false);
688 #ifdef RTABMAP_OCTOMAP
689 _ui->statsToolBox->updateStat(
"GUI/Octomap Update/ms",
false);
690 _ui->statsToolBox->updateStat(
"GUI/Octomap Rendering/ms",
false);
692 #ifdef RTABMAP_GRIDMAP
693 _ui->statsToolBox->updateStat(
"GUI/Elevation Update/ms",
false);
694 _ui->statsToolBox->updateStat(
"GUI/Elevation Rendering/ms",
false);
696 _ui->statsToolBox->updateStat(
"GUI/Grid Update/ms",
false);
697 _ui->statsToolBox->updateStat(
"GUI/Grid Rendering/ms",
false);
698 _ui->statsToolBox->updateStat(
"GUI/Refresh stats/ms",
false);
699 _ui->statsToolBox->updateStat(
"GUI/Cache Data Size/MB",
false);
700 _ui->statsToolBox->updateStat(
"GUI/Cache Clouds Size/MB",
false);
701 #ifdef RTABMAP_OCTOMAP
702 _ui->statsToolBox->updateStat(
"GUI/Octomap Size/MB",
false);
730 #ifdef RTABMAP_OCTOMAP
733 #ifdef RTABMAP_GRIDMAP
744 qobject_cast<QHBoxLayout *>(
_ui->layout_imageview->layout())->setDirection(QBoxLayout::TopToBottom);
748 qobject_cast<QHBoxLayout *>(
_ui->layout_imageview->layout())->setDirection(QBoxLayout::LeftToRight);
754 return _ui->widget_mapVisibility->getVisiblePoses();
792 bool processStopped =
true;
805 processStopped =
false;
813 if(this->isWindowModified())
815 QMessageBox::Button
b=QMessageBox::question(
this,
817 tr(
"There are unsaved changed settings. Save them?"),
818 QMessageBox::Save | QMessageBox::Cancel | QMessageBox::Discard);
819 if(
b == QMessageBox::Save)
823 else if(
b != QMessageBox::Discard)
835 _ui->statsToolBox->closeFigures();
837 _ui->dockWidget_imageView->close();
838 _ui->dockWidget_likelihood->close();
839 _ui->dockWidget_rawlikelihood->close();
840 _ui->dockWidget_posterior->close();
841 _ui->dockWidget_statsV2->close();
842 _ui->dockWidget_console->close();
843 _ui->dockWidget_cloudViewer->close();
844 _ui->dockWidget_loopClosureViewer->close();
845 _ui->dockWidget_mapVisibility->close();
846 _ui->dockWidget_graphViewer->close();
847 _ui->dockWidget_odometry->close();
848 _ui->dockWidget_multiSessionLoc->close();
852 UERROR(
"Camera must be already deleted here!");
863 UERROR(
"OdomThread must be already deleted here!");
883 else if(anEvent->
getClassName().compare(
"RtabmapEvent") == 0)
887 int highestHypothesisId =
int(
uValue(
stats.data(), Statistics::kLoopHighest_hypothesis_id(), 0.0f));
888 int proximityClosureId =
int(
uValue(
stats.data(), Statistics::kProximitySpace_last_detection_id(), 0.0f));
889 bool rejectedHyp = bool(
uValue(
stats.data(), Statistics::kLoopRejectedHypothesis(), 0.0f));
890 float highestHypothesisValue =
uValue(
stats.data(), Statistics::kLoopHighest_hypothesis_value(), 0.0f);
891 if((
stats.loopClosureId() > 0 &&
892 _ui->actionPause_on_match->isChecked())
894 (
stats.loopClosureId() == 0 &&
895 highestHypothesisId > 0 &&
897 _ui->actionPause_when_a_loop_hypothesis_is_rejected->isChecked() &&
900 (proximityClosureId > 0 &&
901 _ui->actionPause_on_local_loop_detection->isChecked()))
907 QMetaObject::invokeMethod(
this,
"beep");
919 else if(anEvent->
getClassName().compare(
"RtabmapEventInit") == 0)
927 else if(anEvent->
getClassName().compare(
"RtabmapEvent3DMap") == 0)
932 else if(anEvent->
getClassName().compare(
"RtabmapGlobalPathEvent") == 0)
937 else if(anEvent->
getClassName().compare(
"RtabmapLabelErrorEvent") == 0)
942 else if(anEvent->
getClassName().compare(
"RtabmapGoalStatusEvent") == 0)
946 else if(anEvent->
getClassName().compare(
"SensorEvent") == 0)
953 QMetaObject::invokeMethod(
this,
"beep");
977 else if(anEvent->
getClassName().compare(
"OdometryEvent") == 0)
996 else if(anEvent->
getClassName().compare(
"ULogEvent") == 0)
1001 QMetaObject::invokeMethod(
_ui->dockWidget_console,
"show");
1008 QMetaObject::invokeMethod(
this,
"beep");
1055 if(
_ui->imageView_odometry->toolTip().isEmpty())
1057 _ui->imageView_odometry->setToolTip(
1058 "Background Color Code:\n"
1059 " Dark Red = Odometry Lost\n"
1060 " Dark Yellow = Low Inliers\n"
1061 "Feature Color code:\n"
1062 " Green = Inliers\n"
1063 " Yellow = Not matched features from previous frame(s)\n"
1069 bool lostStateChanged =
false;
1076 _ui->imageView_odometry->setBackgroundColor(Qt::darkRed);
1088 _ui->imageView_odometry->setBackgroundColor(Qt::darkYellow);
1095 _ui->imageView_odometry->setBackgroundColor(
_ui->imageView_odometry->getDefaultBackgroundColor());
1098 if(!pose.
isNull() && (
_ui->dockWidget_cloudViewer->isVisible() ||
_ui->graphicsView_graphView->isVisible()))
1106 if(!
data->imageRaw().empty() &&
1108 (
_ui->dockWidget_odometry->isVisible() && (
_ui->imageView_odometry->isImageShown() ||
_ui->imageView_odometry->isImageDepthShown()))))
1112 bool imagesAlreadyRectified = Parameters::defaultRtabmapImagesAlreadyRectified();
1113 Parameters::parse(allParameters, Parameters::kRtabmapImagesAlreadyRectified(), imagesAlreadyRectified);
1114 if(!imagesAlreadyRectified)
1116 rectifiedData = odom.
data();
1117 if(
data->cameraModels().size())
1120 UASSERT(
int((
data->imageRaw().cols/
data->cameraModels().size())*
data->cameraModels().size()) ==
data->imageRaw().cols);
1121 int subImageWidth =
data->imageRaw().cols/
data->cameraModels().size();
1122 cv::Mat rectifiedImages =
data->imageRaw().clone();
1128 for(
unsigned int i=0;
i<
data->cameraModels().
size(); ++
i)
1130 if(
data->cameraModels()[
i].isValidForRectification())
1137 UWARN(
"Initializing rectification maps for camera %d (only done for the first image received)...",
i);
1139 UWARN(
"Initializing rectification maps for camera %d (only done for the first image received)... done!",
i);
1144 cv::Mat rectifiedImage =
_rectCameraModelsOdom[
i].rectifyImage(cv::Mat(
data->imageRaw(), cv::Rect(subImageWidth*
i, 0, subImageWidth,
data->imageRaw().rows)));
1145 rectifiedImage.copyTo(cv::Mat(rectifiedImages, cv::Rect(subImageWidth*
i, 0, subImageWidth,
data->imageRaw().rows)));
1149 UWARN(
"Camera %d of data %d is not valid for rectification (%dx%d).",
1151 data->cameraModels()[
i].imageWidth(),
1152 data->cameraModels()[
i].imageHeight());
1157 else if(!
data->rightRaw().empty() &&
data->stereoCameraModels().size())
1159 UASSERT(
int((
data->imageRaw().cols/
data->stereoCameraModels().size())*
data->stereoCameraModels().size()) ==
data->imageRaw().cols);
1160 int subImageWidth =
data->imageRaw().cols/
data->stereoCameraModels().size();
1161 cv::Mat rectifiedLeftImages =
data->imageRaw().clone();
1162 cv::Mat rectifiedRightImages =
data->imageRaw().clone();
1168 for(
unsigned int i=0;
i<
data->stereoCameraModels().
size(); ++
i)
1170 if(
data->stereoCameraModels()[
i].isValidForRectification())
1178 UWARN(
"Initializing rectification maps for stereo camera %d (only done for the first image received)...",
i);
1181 UWARN(
"Initializing rectification maps for stereo camera %d (only done for the first image received)... done!",
i);
1188 cv::Mat rectifiedLeftImage =
_rectCameraModelsOdom[
i*2].rectifyImage(cv::Mat(
data->imageRaw(), cv::Rect(subImageWidth*
i, 0, subImageWidth,
data->imageRaw().rows)));
1189 cv::Mat rectifiedRightImage =
_rectCameraModelsOdom[
i*2+1].rectifyImage(cv::Mat(
data->rightRaw(), cv::Rect(subImageWidth*
i, 0, subImageWidth,
data->rightRaw().rows)));
1190 rectifiedLeftImage.copyTo(cv::Mat(rectifiedLeftImages, cv::Rect(subImageWidth*
i, 0, subImageWidth,
data->imageRaw().rows)));
1191 rectifiedRightImage.copyTo(cv::Mat(rectifiedRightImages, cv::Rect(subImageWidth*
i, 0, subImageWidth,
data->rightRaw().rows)));
1195 UWARN(
"Stereo camera %d of data %d is not valid for rectification (%dx%d).",
1197 data->stereoCameraModels()[
i].left().imageWidth(),
1198 data->stereoCameraModels()[
i].right().imageHeight());
1201 rectifiedData.
setStereoImage(rectifiedLeftImages, rectifiedRightImages,
data->stereoCameraModels());
1203 UDEBUG(
"Time rectification: %fs",
time.ticks());
1204 data = &rectifiedData;
1208 if(
_ui->dockWidget_cloudViewer->isVisible())
1210 bool cloudUpdated =
false;
1211 bool scanUpdated =
false;
1212 bool featuresUpdated =
false;
1213 bool filteredGravityUpdated =
false;
1214 bool accelerationUpdated =
false;
1218 if(!
data->imageRaw().empty() &&
1219 !
data->depthOrRightRaw().empty() &&
1220 (
data->cameraModels().size() ||
data->stereoCameraModels().size()) &&
1223 pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud;
1224 pcl::IndicesPtr
indices(
new std::vector<int>);
1240 pcl::PointCloud<pcl::PointXYZRGB>::Ptr output(
new pcl::PointCloud<pcl::PointXYZRGB>);
1244 Eigen::Vector3f viewpoint(0.0
f,0.0
f,0.0
f);
1245 if(
data->cameraModels().size() && !
data->cameraModels()[0].localTransform().isNull())
1247 viewpoint[0] =
data->cameraModels()[0].localTransform().x();
1248 viewpoint[1] =
data->cameraModels()[0].localTransform().y();
1249 viewpoint[2] =
data->cameraModels()[0].localTransform().z();
1251 else if(
data->stereoCameraModels().size() && !
data->stereoCameraModels()[0].localTransform().isNull())
1253 viewpoint[0] =
data->stereoCameraModels()[0].localTransform().x();
1254 viewpoint[1] =
data->stereoCameraModels()[0].localTransform().y();
1255 viewpoint[2] =
data->stereoCameraModels()[0].localTransform().z();
1262 Eigen::Vector3f(pose.
x(), pose.
y(), pose.
z()) + viewpoint);
1267 pcl::TextureMesh::Ptr textureMesh(
new pcl::TextureMesh);
1268 pcl::toPCLPointCloud2(*cloud, textureMesh->cloud);
1269 textureMesh->tex_polygons.push_back(polygons);
1270 int w = cloud->width;
1271 int h = cloud->height;
1273 textureMesh->tex_coordinates.resize(1);
1274 int nPoints = (
int)(textureMesh->cloud.data.size()/textureMesh->cloud.point_step);
1275 textureMesh->tex_coordinates[0].resize(nPoints);
1276 for(
int i=0;
i<nPoints; ++
i)
1279 textureMesh->tex_coordinates[0][
i] = Eigen::Vector2f(
1280 float(
i %
w) /
float(
w),
1281 float(
h -
i /
w) /
float(
h));
1284 pcl::TexMaterial mesh_material;
1285 mesh_material.tex_d = 1.0f;
1286 mesh_material.tex_Ns = 75.0f;
1287 mesh_material.tex_illum = 1;
1289 mesh_material.tex_name =
"material_odom";
1290 mesh_material.tex_file =
"";
1291 textureMesh->tex_materials.push_back(mesh_material);
1295 UERROR(
"Adding cloudOdom to viewer failed!");
1300 UERROR(
"Adding cloudOdom to viewer failed!");
1308 UERROR(
"Adding cloudOdom to viewer failed!");
1316 cloudUpdated =
true;
1328 bool scanAdded =
false;
1357 UERROR(
"Adding scanMapOdom to viewer failed!");
1370 if(!
data->laserScanRaw().isEmpty())
1384 bool scanAdded =
false;
1388 pcl::PointCloud<pcl::PointXYZINormal>::Ptr cloud;
1398 pcl::PointCloud<pcl::PointNormal>::Ptr cloud;
1408 pcl::PointCloud<pcl::PointXYZI>::Ptr cloud;
1418 pcl::PointCloud<pcl::PointXYZ>::Ptr cloud;
1429 UERROR(
"Adding scanOdom to viewer failed!");
1447 pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud(
new pcl::PointCloud<pcl::PointXYZRGB>);
1455 (*cloud)[
i].x =
iter->second.x;
1456 (*cloud)[
i].y =
iter->second.y;
1457 (*cloud)[
i].z =
iter->second.z;
1461 (*cloud)[
i].r = inlier?0:255;
1462 (*cloud)[
i].g = 255;
1476 featuresUpdated =
true;
1482 for(QMap<std::string, Transform>::iterator
iter = addedFrustums.begin();
iter!=addedFrustums.end(); ++
iter)
1485 if(splitted.size() == 2)
1487 int id = std::atoi(splitted.back().c_str());
1489 if(splitted.front().compare(
"f_odom_") == 0 &&
1499 std::string frustumId =
uFormat(
"f_odom_%d",
iter->first*10);
1502 for(
size_t i=0;
i<10; ++
i)
1504 std::string subFrustumId =
uFormat(
"f_odom_%d",
iter->first*10+
i);
1511 for(
size_t i=0;
i<models.size(); ++
i)
1516 QColor color = Qt::yellow;
1517 std::string subFrustumId =
uFormat(
"f_odom_%d",
iter->first*10+
i);
1525 (
data->imu().orientation().val[0]!=0 ||
1526 data->imu().orientation().val[1]!=0 ||
1527 data->imu().orientation().val[2]!=0 ||
1528 data->imu().orientation().val[3]!=0))
1533 _cloudViewer->
addOrUpdateLine(
"odom_imu_orientation",
_odometryCorrection*pose, (
_odometryCorrection*pose).
translation()*
Transform(gravity[0], gravity[1], gravity[2], 0, 0, 0)*pose.
rotation().
inverse(), Qt::yellow,
true,
true);
1534 filteredGravityUpdated =
true;
1537 (
data->imu().linearAcceleration().val[0]!=0 ||
1538 data->imu().linearAcceleration().val[1]!=0 ||
1539 data->imu().linearAcceleration().val[2]!=0))
1541 Eigen::Vector3f gravity(
1542 -
data->imu().linearAcceleration().val[0],
1543 -
data->imu().linearAcceleration().val[1],
1544 -
data->imu().linearAcceleration().val[2]);
1546 gravity =
data->imu().localTransform().toEigen3f()*gravity;
1547 _cloudViewer->
addOrUpdateLine(
"odom_imu_acc",
_odometryCorrection*pose,
_odometryCorrection*pose*
Transform(gravity[0], gravity[1], gravity[2], 0, 0, 0), Qt::red,
true,
true);
1548 accelerationUpdated =
true;
1578 UDEBUG(
"Time 3D Rendering: %fs",
time.ticks());
1585 if(
data->cameraModels().size() &&
data->cameraModels()[0].isValidForProjection())
1589 else if(
data->stereoCameraModels().size() &&
data->stereoCameraModels()[0].isValidForProjection())
1593 else if(!
data->laserScanRaw().isEmpty() ||
1594 !
data->laserScanCompressed().isEmpty())
1597 if(!
data->laserScanRaw().isEmpty())
1599 scanLocalTransform =
data->laserScanRaw().localTransform();
1603 scanLocalTransform =
data->laserScanCompressed().localTransform();
1617 #if PCL_VERSION_COMPARE(>=, 1, 7, 2)
1628 UDEBUG(
"Time Update Pose: %fs",
time.ticks());
1632 if(
_ui->graphicsView_graphView->isVisible())
1637 _ui->graphicsView_graphView->update();
1638 UDEBUG(
"Time Update graphview: %fs",
time.ticks());
1642 if(
_ui->dockWidget_odometry->isVisible() &&
1643 !
data->imageRaw().empty())
1645 if(
_ui->imageView_odometry->isFeaturesShown())
1651 std::multimap<int, cv::KeyPoint> kpInliers;
1652 for(
unsigned int i=0;
i<odom.
info().reg.inliersIDs.size(); ++
i)
1656 _ui->imageView_odometry->setFeatures(
1663 _ui->imageView_odometry->setFeatures(
1676 std::vector<cv::KeyPoint> kpts;
1678 _ui->imageView_odometry->setFeatures(
1686 bool monoInitialization =
false;
1689 monoInitialization =
true;
1692 _ui->imageView_odometry->clearLines();
1693 if(lost && !monoInitialization)
1695 if(lostStateChanged)
1701 _ui->imageView_odometry->setImageDepth(
data->imageRaw());
1702 _ui->imageView_odometry->setImageShown(
true);
1703 _ui->imageView_odometry->setImageDepthShown(
true);
1707 if(lostStateChanged)
1715 if(
_ui->imageView_odometry->isImageDepthShown() && !
data->depthOrRightRaw().empty())
1717 _ui->imageView_odometry->setImageDepth(
data->depthOrRightRaw());
1728 for(
unsigned int i=0;
i<odom.
info().reg.matchesIDs.size(); ++
i)
1732 for(
unsigned int i=0;
i<odom.
info().reg.inliersIDs.size(); ++
i)
1742 if(
_ui->imageView_odometry->isFeaturesShown() ||
_ui->imageView_odometry->isLinesShown())
1747 int subImageWidth = 0;
1748 if(
data->cameraModels().size()>1 ||
data->stereoCameraModels().size()>1)
1750 subImageWidth =
data->cameraModels().size()?
data->cameraModels()[0].imageWidth():
data->stereoCameraModels()[0].left().imageWidth();
1752 for(
unsigned int i=0;
i<odom.
info().refCorners.size(); ++
i)
1754 if(
_ui->imageView_odometry->isFeaturesShown() && inliers.find(
i) != inliers.end())
1756 _ui->imageView_odometry->setFeatureColor(
i, Qt::green);
1758 if(
_ui->imageView_odometry->isLinesShown())
1763 _ui->imageView_odometry->addLine(
1768 inliers.find(
i) != inliers.end()?Qt::blue:Qt::yellow);
1775 if(!
data->imageRaw().empty())
1777 _ui->imageView_odometry->setSceneRect(QRectF(0,0,(
float)
data->imageRaw().cols, (
float)
data->imageRaw().rows));
1780 _ui->imageView_odometry->update();
1782 UDEBUG(
"Time update imageview: %fs",
time.ticks());
1919 if(!
data->groundTruth().isNull())
1936 UDEBUG(
"Time updating Stats toolbox: %fs",
time.ticks());
1947 QElapsedTimer
time, totalTime;
1957 int refMapId = -1, loopMapId = -1;
1962 int highestHypothesisId =
static_cast<float>(
uValue(stat.
data(), Statistics::kLoopHighest_hypothesis_id(), 0.0f));
1969 _ui->label_refId->setText(QString(
"New ID = %1 [%2]").arg(stat.
refImageId()).arg(refMapId));
1973 float totalTime =
static_cast<float>(
uValue(stat.
data(), Statistics::kTimingTotal(), 0.0f));
1980 bool highestHypothesisIsSaved = (bool)
uValue(stat.
data(), Statistics::kLoopHypothesis_reactivated(), 0.0f);
1982 bool smallMovement = (bool)
uValue(stat.
data(), Statistics::kMemorySmall_movement(), 0.0f);
1984 bool fastMovement = (bool)
uValue(stat.
data(), Statistics::kMemoryFast_movement(), 0.0f);
1986 int rehearsalMerged = (
int)
uValue(stat.
data(), Statistics::kMemoryRehearsal_merged(), 0.0f);
1994 else if(rehearsalMerged>0 &&
2001 if(signature.
id()!=0)
2006 _ui->imageView_source->isVisible() ||
2015 cv::Mat tmpRgb, tmpDepth, tmpG, tmpO, tmpE;
2018 uncompressImages?&tmpRgb:0,
2020 uncompressScan?&tmpScan:0,
2021 0, &tmpG, &tmpO, &tmpE);
2027 if(smallMovement || fastMovement)
2035 unsigned int count = 0;
2038 for(std::multimap<int, int>::const_iterator jter=signature.
getWords().upper_bound(-1); jter!=signature.
getWords().end(); ++jter)
2056 if(signature.
id() !=
iter->first &&
2058 (
_cachedSignatures.value(
iter->first).sensorData().imageCompressed().empty() && !
iter->second.sensorData().imageCompressed().empty())))
2062 unsigned int count = 0;
2063 if(!
iter->second.getWords3().empty())
2065 for(std::multimap<int, int>::const_iterator jter=
iter->second.getWords().upper_bound(-1); jter!=
iter->second.getWords().end(); ++jter)
2074 UINFO(
"Added node data %d [map=%d] to cache",
iter->first,
iter->second.mapId());
2077 if(!
iter->second.getGroundTruthPose().isNull())
2087 _ui->imageView_source->clear();
2088 _ui->imageView_loopClosure->clear();
2093 _ui->imageView_source->setSceneRect(QRect(0,0,640,480));
2096 _ui->imageView_source->setBackgroundColor(
_ui->imageView_source->getDefaultBackgroundColor());
2097 _ui->imageView_loopClosure->setBackgroundColor(
_ui->imageView_loopClosure->getDefaultBackgroundColor());
2099 _ui->label_matchId->clear();
2101 bool rehearsedSimilarity = (
float)
uValue(stat.
data(), Statistics::kMemoryRehearsal_id(), 0.0f) != 0.0
f;
2102 int proximityTimeDetections = (
int)
uValue(stat.
data(), Statistics::kProximityTime_detections(), 0.0f);
2103 bool scanMatchingSuccess = (bool)
uValue(stat.
data(), Statistics::kNeighborLinkRefiningAccepted(), 0.0f);
2104 _ui->label_stats_imageNumber->setText(QString(
"%1 [%2]").arg(stat.
refImageId()).arg(refMapId));
2106 if(rehearsalMerged > 0)
2108 _ui->imageView_source->setBackgroundColor(Qt::blue);
2110 else if(proximityTimeDetections > 0)
2112 _ui->imageView_source->setBackgroundColor(Qt::darkYellow);
2114 else if(scanMatchingSuccess)
2116 _ui->imageView_source->setBackgroundColor(Qt::darkCyan);
2118 else if(rehearsedSimilarity)
2120 _ui->imageView_source->setBackgroundColor(Qt::darkBlue);
2122 else if(smallMovement)
2124 _ui->imageView_source->setBackgroundColor(Qt::gray);
2126 else if(fastMovement)
2128 _ui->imageView_source->setBackgroundColor(Qt::magenta);
2131 if(
_ui->label_refId->toolTip().isEmpty())
2133 _ui->label_refId->setToolTip(
2134 "Background Color Code:\n"
2135 " Blue = Weight Update Merged\n"
2136 " Dark Blue = Weight Update\n"
2137 " Dark Yellow = Proximity Detection in Time\n"
2138 " Dark Cyan = Neighbor Link Refined\n"
2139 " Gray = Small Movement\n"
2140 " Magenta = Fast Movement\n"
2141 "Feature Color code:\n"
2143 " Yellow = New but Not Unique\n"
2144 " Red = In Vocabulary\n"
2145 " Blue = In Vocabulary and in Previous Signature\n"
2146 " Pink = In Vocabulary and in Loop Closure Signature\n"
2147 " Gray = Not Quantized to Vocabulary");
2150 if(
_ui->label_matchId->toolTip().isEmpty())
2152 _ui->label_matchId->setToolTip(
2153 "Background Color Code:\n"
2154 " Green = Accepted Loop Closure Detection\n"
2155 " Red = Rejected Loop Closure Detection\n"
2156 " Yellow = Proximity Detection in Space\n"
2157 "Feature Color code:\n"
2158 " Red = In Vocabulary\n"
2159 " Pink = In Vocabulary and in Loop Closure Signature\n"
2160 " Gray = Not Quantized to Vocabulary");
2163 int rejectedHyp = bool(
uValue(stat.
data(), Statistics::kLoopRejectedHypothesis(), 0.0f));
2164 float highestHypothesisValue =
uValue(stat.
data(), Statistics::kLoopHighest_hypothesis_value(), 0.0f);
2165 int landmarkId =
static_cast<int>(
uValue(stat.
data(), Statistics::kLoopLandmark_detected(), 0.0f));
2166 int landmarkNodeRef =
static_cast<int>(
uValue(stat.
data(), Statistics::kLoopLandmark_detected_node_ref(), 0.0f));
2169 int shownLoopId = 0;
2175 _ui->imageView_loopClosure->setBackgroundColor(Qt::green);
2176 _ui->label_stats_loopClosuresDetected->setText(QString::number(
_ui->label_stats_loopClosuresDetected->text().toInt() + 1));
2177 if(highestHypothesisIsSaved)
2179 _ui->label_stats_loopClosuresReactivatedDetected->setText(QString::number(
_ui->label_stats_loopClosuresReactivatedDetected->text().toInt() + 1));
2181 _ui->label_matchId->setText(QString(
"Match ID = %1 [%2]").arg(stat.
loopClosureId()).arg(loopMapId));
2186 _ui->imageView_loopClosure->setBackgroundColor(Qt::yellow);
2187 _ui->label_matchId->setText(QString(
"Local match = %1 [%2]").arg(stat.
proximityDetectionId()).arg(loopMapId));
2190 else if(landmarkId!=0)
2192 highestHypothesisId = landmarkNodeRef;
2198 _ui->imageView_loopClosure->setBackgroundColor(Qt::red);
2199 _ui->label_stats_loopClosuresRejected->setText(QString::number(
_ui->label_stats_loopClosuresRejected->text().toInt() + 1));
2200 _ui->label_matchId->setText(QString(
"Landmark rejected = %1 with %2").arg(landmarkId).arg(landmarkNodeRef));
2205 _ui->imageView_loopClosure->setBackgroundColor(QColor(
"orange"));
2206 _ui->label_matchId->setText(QString(
"Landmark match = %1 with %2").arg(landmarkId).arg(landmarkNodeRef));
2207 matchId = landmarkNodeRef;
2215 _ui->imageView_loopClosure->setBackgroundColor(Qt::red);
2216 _ui->label_stats_loopClosuresRejected->setText(QString::number(
_ui->label_stats_loopClosuresRejected->text().toInt() + 1));
2217 _ui->label_matchId->setText(QString(
"Loop hypothesis %1 rejected!").arg(highestHypothesisId));
2225 _ui->label_matchId->setText(QString(
"Highest hypothesis (%1)").arg(highestHypothesisId));
2231 shownLoopId = matchId>0?matchId:highestHypothesisId;
2238 _ui->imageView_source->isVisible() ||
2243 if(uncompressImages || uncompressScan)
2245 cv::Mat tmpRGB, tmpDepth;
2248 uncompressImages?&tmpRGB:0,
2249 uncompressImages?&tmpDepth:0,
2250 uncompressScan?&tmpScan:0);
2261 UDEBUG(
"time= %d ms (update detection ui)",
time.restart());
2277 if(refImage.channels() == 1)
2280 cvtColor(refImage, imgColor, cv::COLOR_GRAY2BGR);
2281 refImage = imgColor;
2285 refImage = refImage.clone();
2291 if(loopImage.channels() == 1)
2294 cv::cvtColor(loopImage, imgColor, cv::COLOR_GRAY2BGR);
2295 loopImage = imgColor;
2299 loopImage = loopImage.clone();
2307 qimageThread.
start();
2308 qimageLoopThread.
start();
2309 qimageThread.
join();
2310 qimageLoopThread.
join();
2312 QImage lcImg = qimageLoopThread.
getQImage();
2313 UDEBUG(
"time= %d ms (convert image to qt)",
time.restart());
2317 _ui->imageView_source->setImage(
img);
2342 if(sceneRect.isValid())
2344 _ui->imageView_source->setSceneRect(sceneRect);
2349 _ui->imageView_loopClosure->setImage(lcImg);
2355 if(
_ui->imageView_loopClosure->sceneRect().isNull())
2357 _ui->imageView_loopClosure->setSceneRect(
_ui->imageView_source->sceneRect());
2360 else if(
_ui->imageView_loopClosure->sceneRect().isNull() &&
2361 !
_ui->imageView_source->sceneRect().isNull())
2363 _ui->imageView_loopClosure->setSceneRect(
_ui->imageView_source->sceneRect());
2366 UDEBUG(
"time= %d ms (update detection imageviews)",
time.restart());
2369 std::multimap<int, cv::KeyPoint> wordsA;
2370 std::multimap<int, cv::KeyPoint> wordsB;
2373 wordsA.insert(wordsA.end(), std::make_pair(
iter->first, signature.
getWordsKpts()[
iter->second]));
2377 wordsB.insert(wordsB.end(), std::make_pair(
iter->first, loopSignature.
getWordsKpts()[
iter->second]));
2381 UDEBUG(
"time= %d ms (draw keypoints)",
time.restart());
2390 signature.
setPose(loopClosureTransform);
2392 if(
_ui->dockWidget_loopClosureViewer->isVisible())
2396 UINFO(
"Updating loop closure cloud view time=%fs", loopTimer.
elapsed());
2403 UDEBUG(
"time= %d ms (update loop closure viewer)",
time.restart());
2408 if(!stat.
posterior().empty() &&
_ui->dockWidget_posterior->isVisible())
2417 if(!stat.
likelihood().empty() &&
_ui->dockWidget_likelihood->isVisible())
2421 if(!stat.
rawLikelihood().empty() &&
_ui->dockWidget_rawlikelihood->isVisible())
2425 UDEBUG(
"time= %d ms (update likelihood and posterior)",
time.restart());
2430 const std::map<std::string, float> & statistics = stat.
data();
2431 std::string odomStr =
"Odometry/";
2432 for(std::map<std::string, float>::const_iterator
iter = statistics.begin();
iter != statistics.end(); ++
iter)
2435 if((*iter).first.size()<odomStr.size() || (*iter).first.substr(0, odomStr.size()).compare(odomStr)!=0)
2442 UDEBUG(
"time= %d ms (update stats toolbox)",
time.restart());
2452 if(stat.
poses().size())
2466 _ui->graphicsView_graphView->getWorldMapRotation()==0.0f &&
2472 _ui->graphicsView_graphView->setWorldMapRotation(gpsRotationOffset);
2475 _ui->graphicsView_graphView->getWorldMapRotation() != 0.0f)
2477 _ui->graphicsView_graphView->setWorldMapRotation(0.0
f);
2481 std::map<int, Transform> poses = stat.
poses();
2483 UDEBUG(
"time= %d ms (update gt-gps stuff)",
time.restart());
2485 UDEBUG(
"%d %d %d", poses.size(), poses.size()?poses.rbegin()->first:0, stat.
refImageId());
2525 if(
_ui->graphicsView_graphView->isVisible())
2527 _ui->graphicsView_graphView->updateReferentialPosition(poses.rbegin()->second);
2533 if(poses.find(stat.
refImageId())!=poses.end())
2535 poses.insert(std::make_pair(0, poses.at(stat.
refImageId())));
2538 if(groundTruth.find(stat.
refImageId())!=groundTruth.end())
2540 groundTruth.insert(std::make_pair(0, groundTruth.at(stat.
refImageId())));
2545 std::map<std::string, float> updateCloudSats;
2559 UDEBUG(
"time= %d ms (update map cloud)",
time.restart());
2563 for(std::map<std::string, float>::iterator
iter=updateCloudSats.begin();
iter!=updateCloudSats.end(); ++
iter)
2569 #if PCL_VERSION_COMPARE(>=, 1, 7, 2)
2592 if(
_ui->graphicsView_graphView->isVisible())
2598 _ui->graphicsView_graphView->updatePosterior(stat.
posterior());
2615 std::map<int, float> colors;
2616 colors.insert(std::make_pair(stat.
odomCachePoses().rbegin()->first, 240));
2621 uInsert(colors, std::pair<int,float>(
iter->second.from()>
iter->second.to()?
iter->second.from():
iter->second.to(), 120));
2628 colors.insert(std::make_pair(
iter->first, 240));
2631 _ui->graphicsView_graphView->updatePosterior(colors, 240);
2634 _ui->graphicsView_graphView->updateLocalPath(stat.
localPath());
2638 _ui->graphicsView_graphView->setGlobalPath(std::vector<std::pair<int, Transform> >());
2645 UDEBUG(
"time= %d ms (update graph view)",
time.restart());
2660 s.sensorData().clearRawData();
2661 s.sensorData().clearOccupancyGridRaw();
2672 std::vector<int> missingIds;
2673 bool ignoreNewData = smallMovement || fastMovement || signature.
getWeight()<0;
2680 for(std::set<int>::const_iterator
iter=ids.lower_bound(1);
iter!=ids.end(); ++
iter)
2686 (ster.value().getWeight() >=0 &&
2687 ster.value().sensorData().imageCompressed().empty() &&
2688 ster.value().sensorData().depthOrRightCompressed().empty() &&
2689 ster.value().sensorData().laserScanCompressed().empty()))
2691 missingIds.push_back(*
iter);
2695 if(!missingIds.empty())
2702 UDEBUG(
"time= %d ms (update cache)",
time.restart());
2706 _ui->label_stats_loopClosuresDetected->setText(QString::number(
_ui->label_stats_loopClosuresDetected->text().toInt() + 1));
2711 _ui->label_matchId->clear();
2713 float elapsedTime =
static_cast<float>(totalTime.elapsed());
2714 UINFO(
"Updating GUI time = %fs", elapsedTime/1000.0
f);
2734 #ifdef RTABMAP_OCTOMAP
2751 const std::map<int, Transform> & posesIn,
2752 const std::multimap<int, Link> & constraints,
2753 const std::map<int, int> & mapIdsIn,
2754 const std::map<int, std::string> & labels,
2755 const std::map<int, Transform> & groundTruths,
2756 const std::map<int, Transform> & odomCachePoses,
2757 const std::multimap<int, Link> & odomCacheConstraints,
2758 bool verboseProgress,
2759 std::map<std::string, float> * stats)
2762 std::map<int, Transform> nodePoses(posesIn.lower_bound(0), posesIn.end());
2763 UDEBUG(
"nodes=%d landmarks=%d constraints=%d mapIdsIn=%d labelsIn=%d",
2764 (
int)nodePoses.size(), (
int)(posesIn.size() - nodePoses.size()), (
int)constraints.size(), (
int)mapIdsIn.size(), (
int)
labels.size());
2783 std::map<int, Transform> poses;
2784 std::map<int, int> mapIds;
2789 bool hasZero = nodePoses.find(0) != nodePoses.end();
2792 std::map<int, Transform> posesInTmp = nodePoses;
2793 posesInTmp.erase(0);
2800 for(std::map<int, Transform>::iterator
iter= poses.begin();
iter!=poses.end(); ++
iter)
2802 std::map<int, int>::const_iterator jter = mapIdsIn.find(
iter->first);
2803 if(jter!=mapIdsIn.end())
2805 mapIds.insert(*jter);
2811 poses.insert(*nodePoses.find(0));
2817 QApplication::processEvents();
2826 std::map<int, bool> posesMask;
2827 for(std::map<int, Transform>::const_iterator
iter = nodePoses.begin();
iter!=nodePoses.end(); ++
iter)
2829 posesMask.insert(posesMask.end(), std::make_pair(
iter->first, poses.find(
iter->first) != poses.end()));
2831 _ui->widget_mapVisibility->setMap(nodePoses, posesMask);
2833 if(groundTruths.size() &&
_ui->actionAnchor_clouds_to_ground_truth->isChecked())
2835 for(std::map<int, Transform>::iterator
iter = poses.begin();
iter!=poses.end(); ++
iter)
2837 std::map<int, Transform>::const_iterator gtIter = groundTruths.find(
iter->first);
2838 if(gtIter!=groundTruths.end())
2840 iter->second = gtIter->second;
2844 UWARN(
"Not found ground truth pose for node %d",
iter->first);
2850 _ui->actionAnchor_clouds_to_ground_truth->setChecked(
false);
2855 if((maxNodes > 0 || altitudeDelta>0.0) && poses.size()>1)
2857 Transform currentPose = poses.rbegin()->second;
2858 if(poses.find(0) != poses.end())
2860 currentPose = poses.at(0);
2863 std::map<int, Transform> nearestPoses;
2869 if(altitudeDelta<=0.0 ||
2870 fabs(poses.at(
iter->first).z()-currentPose.
z())<altitudeDelta)
2872 nearestPoses.insert(*poses.find(
iter->first));
2878 for(std::map<int, Transform>::const_iterator
iter=poses.begin();
iter!=poses.end(); ++
iter)
2880 if(
fabs(
iter->second.z()-currentPose.
z())<altitudeDelta)
2882 nearestPoses.insert(*
iter);
2888 if(poses.find(0) != poses.end())
2890 nearestPoses.insert(*poses.find(0));
2896 UDEBUG(
"Update map with %d locations", poses.size());
2900 for(std::map<int, Transform>::const_iterator
iter = poses.begin();
iter!=poses.end(); ++
iter)
2902 if(!
iter->second.isNull())
2904 std::string cloudName =
uFormat(
"cloud%d",
iter->first);
2906 if(
iter->first == 0)
2908 viewerClouds.remove(cloudName);
2917 if(viewerClouds.contains(cloudName))
2922 if(tCloud.
isNull() ||
iter->second != tCloud)
2926 UERROR(
"Updating pose cloud %d failed!",
iter->first);
2945 else if(viewerClouds.contains(cloudName))
2951 std::string scanName =
uFormat(
"scan%d",
iter->first);
2952 if(
iter->first == 0)
2954 viewerClouds.remove(scanName);
2959 if(viewerClouds.contains(scanName))
2968 UERROR(
"Updating pose scan %d failed!",
iter->first);
2979 if(!jter->sensorData().laserScanCompressed().isEmpty() || !jter->sensorData().laserScanRaw().isEmpty())
2985 else if(viewerClouds.contains(scanName))
2991 bool updateGridMap =
2992 ((
_ui->graphicsView_graphView->isVisible() &&
_ui->graphicsView_graphView->isGridMapVisible()) ||
2995 bool updateOctomap =
false;
2996 bool updateElevationMap =
false;
2997 #ifdef RTABMAP_OCTOMAP
3003 #ifdef RTABMAP_GRIDMAP
3004 updateElevationMap =
3009 if(updateGridMap || updateOctomap || updateElevationMap)
3018 jter->sensorData().uncompressDataConst(0, 0, 0, 0, &ground, &obstacles, &
empty);
3020 double resolution = jter->sensorData().gridCellSize();
3027 if(ground.channels() == 2)
3031 if(obstacles.channels() == 2)
3035 if(
empty.channels() == 2)
3046 std::string featuresName =
uFormat(
"features%d",
iter->first);
3047 if(
iter->first == 0)
3049 viewerClouds.remove(featuresName);
3054 if(viewerClouds.contains(featuresName))
3059 if(tFeatures.
isNull() ||
iter->second != tFeatures)
3063 UERROR(
"Updating pose features %d failed!",
iter->first);
3072 if(!jter->getWords3().empty())
3078 else if(viewerClouds.contains(featuresName))
3084 std::string gravityName =
uFormat(
"gravity%d",
iter->first);
3085 if(
iter->first == 0)
3087 viewerLines.erase(gravityName);
3093 if(linkIter != constraints.end())
3095 Transform gravityT = linkIter->second.transform();
3098 _cloudViewer->
addOrUpdateLine(gravityName,
iter->second, (
iter->second).translation()*
Transform(gravity[0], gravity[1], gravity[2], 0, 0, 0)*
iter->second.rotation().inverse(), Qt::yellow,
false,
false);
3101 else if(viewerLines.find(gravityName)!=viewerLines.end())
3110 if(poses.size() < 200 ||
i % 100 == 0)
3112 QApplication::processEvents();
3125 for(QMap<std::string, Transform>::iterator
iter = viewerClouds.begin();
iter!=viewerClouds.end(); ++
iter)
3129 if(splitted.size() == 2)
3131 id = std::atoi(splitted.back().c_str());
3132 if(poses.find(
id) == poses.end())
3143 for(std::set<std::string>::iterator
iter = viewerLines.begin();
iter!=viewerLines.end(); ++
iter)
3147 if(splitted.size() == 2)
3149 id = std::atoi(splitted.back().c_str());
3150 if(poses.find(
id) == poses.end())
3161 stats->insert(std::make_pair(
"GUI/RGB-D cloud/ms", (
float)
timer.
restart()*1000.0f));
3170 for(QMap<std::string, Transform>::iterator
iter = addedFrustums.begin();
iter!=addedFrustums.end(); ++
iter)
3173 if(splitted.size() == 2)
3175 if((splitted.front().compare(
"f_") == 0 || splitted.front().compare(
"f_gt_") == 0))
3189 std::map<int, Transform> posesWithOdomCache;
3191 if(
_ui->graphicsView_graphView->isVisible() ||
3194 posesWithOdomCache = posesIn;
3195 for(std::map<int, Transform>::const_iterator
iter=odomCachePoses.begin();
iter!=odomCachePoses.end(); ++
iter)
3205 std::map<int, pcl::PointCloud<pcl::PointXYZ>::Ptr > graphs;
3206 for(std::map<int, Transform>::iterator
iter=posesWithOdomCache.lower_bound(1);
iter!=posesWithOdomCache.end(); ++
iter)
3213 std::map<int, pcl::PointCloud<pcl::PointXYZ>::Ptr >
::iterator kter = graphs.find(mapId);
3214 if(kter == graphs.end())
3216 kter = graphs.insert(std::make_pair(mapId, pcl::PointCloud<pcl::PointXYZ>::Ptr(
new pcl::PointCloud<pcl::PointXYZ>))).first;
3218 pcl::PointXYZ pt(
iter->second.x(),
iter->second.y(),
iter->second.z());
3219 kter->second->push_back(pt);
3225 std::string frustumId =
uFormat(
"f_%d",
iter->first);
3234 if(
s.sensorData().cameraModels().size() == 1 ||
s.sensorData().stereoCameraModels().size()==1)
3236 const CameraModel &
model =
s.sensorData().stereoCameraModels().size()?
s.sensorData().stereoCameraModels()[0].left():
s.sensorData().cameraModels()[0];
3240 QColor color = (Qt::GlobalColor)((mapId+3) % 12 + 7 );
3245 std::string gtFrustumId =
uFormat(
"f_gt_%d",
iter->first);
3263 std::map<int, pcl::PointCloud<pcl::PointXYZ>::Ptr >
::iterator kter = graphs.find(mapId);
3264 if(kter == graphs.end())
3266 kter = graphs.insert(std::make_pair(mapId, pcl::PointCloud<pcl::PointXYZ>::Ptr(
new pcl::PointCloud<pcl::PointXYZ>))).first;
3269 pcl::PointXYZ pt(
t.
x(),
t.
y(),
t.z());
3270 kter->second->push_back(pt);
3275 for(std::map<
int, pcl::PointCloud<pcl::PointXYZ>::Ptr >::
iterator iter=graphs.begin();
iter!=graphs.end(); ++
iter)
3277 QColor color = Qt::gray;
3278 if(
iter->first >= 0)
3280 color = (Qt::GlobalColor)((
iter->first+3) % 12 + 7 );
3288 UDEBUG(
"remove not used frustums");
3289 for(QMap<std::string, Transform>::iterator
iter = addedFrustums.begin();
iter!=addedFrustums.end(); ++
iter)
3292 if(splitted.size() == 2)
3294 int id = std::atoi(splitted.back().c_str());
3295 if((splitted.front().compare(
"f_") == 0 || splitted.front().compare(
"f_gt_") == 0) &&
3296 posesWithOdomCache.find(
id) == posesWithOdomCache.end())
3315 if(nodePoses.find(
iter->first)!=nodePoses.end())
3317 int mapId =
uValue(mapIdsIn,
iter->first, -1);
3318 QColor color = Qt::gray;
3321 color = (Qt::GlobalColor)((mapId+3) % 12 + 7 );
3336 stats->insert(std::make_pair(
"GUI/Graph Update/ms", (
float)
timer.
restart()*1000.0f));
3339 #ifdef RTABMAP_OCTOMAP
3347 UINFO(
"Octomap update time = %fs",
time.ticks());
3351 stats->insert(std::make_pair(
"GUI/Octomap Update/ms", (
float)
timer.
restart()*1000.0f));
3363 pcl::IndicesPtr obstacles(
new std::vector<int>);
3365 if(obstacles->size())
3371 UINFO(
"Octomap show 3d map time = %fs",
time.ticks());
3376 stats->insert(std::make_pair(
"GUI/Octomap Rendering/ms", (
float)
timer.
restart()*1000.0f));
3380 #ifdef RTABMAP_GRIDMAP
3388 UINFO(
"Elevation map update time = %fs",
time.ticks());
3392 stats->insert(std::make_pair(
"GUI/Elevation Update/ms", (
float)
timer.
restart()*1000.0f));
3400 float xMin, yMin, cellSize;
3410 if(mesh->cloud.data.size())
3415 UINFO(
"Show elevation map time = %fs",
time.ticks());
3420 stats->insert(std::make_pair(
"GUI/Elevation Rendering/ms", (
float)
timer.
restart()*1000.0f));
3425 #if PCL_VERSION_COMPARE(>=, 1, 7, 2)
3430 for(std::map<int, Transform>::const_iterator
iter=posesIn.begin();
iter!=posesIn.end() &&
iter->first<0; ++
iter)
3432 #if PCL_VERSION_COMPARE(>=, 1, 7, 2)
3439 std::string(
"landmark_str_") + num,
3449 if(
_ui->graphicsView_graphView->isVisible())
3451 std::multimap<int, Link> constraintsWithOdomCache;
3452 constraintsWithOdomCache = constraints;
3453 constraintsWithOdomCache.insert(odomCacheConstraints.begin(), odomCacheConstraints.end());
3454 _ui->graphicsView_graphView->updateGraph(posesWithOdomCache, constraintsWithOdomCache, mapIdsIn, std::map<int, int>(),
uKeysSet(odomCachePoses));
3458 for(std::map<int, Transform>::iterator
iter=gtPoses.begin();
iter!=gtPoses.end(); ++
iter)
3460 iter->second = mapToGt *
iter->second;
3462 _ui->graphicsView_graphView->updateGTGraph(gtPoses);
3470 if((
_ui->graphicsView_graphView->isVisible() &&
_ui->graphicsView_graphView->isGridMapVisible()) ||
3476 #ifdef RTABMAP_OCTOMAP
3490 stats->insert(std::make_pair(
"GUI/Grid Update/ms", (
float)
timer.
restart()*1000.0f));
3504 if(
_ui->graphicsView_graphView->isVisible() &&
_ui->graphicsView_graphView->isGridMapVisible())
3506 _ui->graphicsView_graphView->updateMap(map8U, resolution, xMin, yMin);
3510 _ui->graphicsView_graphView->update();
3517 stats->insert(std::make_pair(
"GUI/Grid Rendering/ms", (
float)
timer.
restart()*1000.0f));
3526 if(viewerClouds.contains(
"cloudOdom"))
3542 if(viewerClouds.contains(
"scanOdom"))
3558 if(viewerClouds.contains(
"scanMapOdom"))
3574 if(viewerClouds.contains(
"featuresOdom"))
3595 #ifdef RTABMAP_OCTOMAP
3598 _ui->actionExport_octomap->setEnabled(
false);
3610 std::string cloudName =
uFormat(
"cloud%d", nodeId);
3611 std::pair<pcl::PointCloud<pcl::PointXYZRGB>::Ptr, pcl::IndicesPtr> outputPair;
3614 UERROR(
"Cloud %d already added to map.", nodeId);
3621 UERROR(
"Node %d is not in the cache.", nodeId);
3627 if((!
iter->sensorData().imageCompressed().empty() || !
iter->sensorData().imageRaw().empty()) &&
3628 (!
iter->sensorData().depthOrRightCompressed().empty() || !
iter->sensorData().depthOrRightRaw().empty()))
3630 cv::Mat image, depth;
3632 data.uncompressData(&image, &depth, 0);
3634 bool rectifyOnlyFeatures = Parameters::defaultRtabmapRectifyOnlyFeatures();
3635 bool imagesAlreadyRectified = Parameters::defaultRtabmapImagesAlreadyRectified();
3636 Parameters::parse(allParameters, Parameters::kRtabmapRectifyOnlyFeatures(), rectifyOnlyFeatures);
3637 Parameters::parse(allParameters, Parameters::kRtabmapImagesAlreadyRectified(), imagesAlreadyRectified);
3638 if(rectifyOnlyFeatures && !imagesAlreadyRectified)
3640 if(
data.cameraModels().size())
3644 UASSERT(
int((
data.imageRaw().cols/
data.cameraModels().size())*
data.cameraModels().size()) ==
data.imageRaw().cols);
3645 int subImageWidth =
data.imageRaw().cols/
data.cameraModels().size();
3646 cv::Mat rectifiedImages =
data.imageRaw().clone();
3652 for(
unsigned int i=0;
i<
data.cameraModels().
size(); ++
i)
3654 if(
data.cameraModels()[
i].isValidForRectification())
3661 UWARN(
"Initializing rectification maps for camera %d (only done for the first image received)...",
i);
3663 UWARN(
"Initializing rectification maps for camera %d (only done for the first image received)... done!",
i);
3668 cv::Mat rectifiedImage =
_rectCameraModels[
i].rectifyImage(cv::Mat(
data.imageRaw(), cv::Rect(subImageWidth*
i, 0, subImageWidth,
data.imageRaw().rows)));
3669 rectifiedImage.copyTo(cv::Mat(rectifiedImages, cv::Rect(subImageWidth*
i, 0, subImageWidth,
data.imageRaw().rows)));
3673 UWARN(
"Camera %d of data %d is not valid for rectification (%dx%d).",
3675 data.cameraModels()[
i].imageWidth(),
3676 data.cameraModels()[
i].imageHeight());
3679 UINFO(
"Time rectification: %fs",
time.ticks());
3680 data.setRGBDImage(rectifiedImages,
data.depthOrRightRaw(),
data.cameraModels());
3681 image = rectifiedImages;
3685 pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud;
3686 pcl::IndicesPtr
indices(
new std::vector<int>);
3699 Eigen::Vector3f viewPoint(0.0
f,0.0
f,0.0
f);
3700 if(
data.cameraModels().size() && !
data.cameraModels()[0].localTransform().isNull())
3702 viewPoint[0] =
data.cameraModels()[0].localTransform().x();
3703 viewPoint[1] =
data.cameraModels()[0].localTransform().y();
3704 viewPoint[2] =
data.cameraModels()[0].localTransform().z();
3706 else if(
data.stereoCameraModels().size() && !
data.stereoCameraModels()[0].localTransform().isNull())
3708 viewPoint[0] =
data.stereoCameraModels()[0].localTransform().x();
3709 viewPoint[1] =
data.stereoCameraModels()[0].localTransform().y();
3710 viewPoint[2] =
data.stereoCameraModels()[0].localTransform().z();
3718 indices->resize(cloud->size());
3719 for(
unsigned int i=0;
i<cloud->size(); ++
i)
3752 pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr cloudWithNormals(
new pcl::PointCloud<pcl::PointXYZRGBNormal>);
3757 pcl::IndicesPtr beforeFiltering =
indices;
3758 if( cloud->size() &&
3781 pcl::concatenateFields(*cloud, *normals, *cloudWithNormals);
3785 UWARN(
"Cloud subtraction with angle filtering is activated but "
3786 "cloud normal K search is 0. Subtraction is done with angle.");
3790 if(cloudWithNormals->size() &&
3817 UINFO(
"Time subtract filtering %d from %d -> %d (%fs)",
3819 (
int)beforeFiltering->size(),
3833 pcl::PointCloud<pcl::PointXYZRGB>::Ptr output;
3849 pcl::PointCloud<pcl::PointXYZRGB>::Ptr outputFiltered(
new pcl::PointCloud<pcl::PointXYZRGB>);
3850 std::vector<pcl::Vertices> outputPolygons;
3855 pcl::TextureMesh::Ptr textureMesh(
new pcl::TextureMesh);
3856 pcl::toPCLPointCloud2(*outputFiltered, textureMesh->cloud);
3857 textureMesh->tex_polygons.push_back(outputPolygons);
3858 int w = cloud->width;
3859 int h = cloud->height;
3861 textureMesh->tex_coordinates.resize(1);
3862 int nPoints = (
int)outputFiltered->size();
3863 textureMesh->tex_coordinates[0].resize(nPoints);
3864 for(
int i=0;
i<nPoints; ++
i)
3867 UASSERT(
i < (
int)denseToOrganizedIndices.size());
3868 int originalVertex = denseToOrganizedIndices[
i];
3869 textureMesh->tex_coordinates[0][
i] = Eigen::Vector2f(
3870 float(originalVertex %
w) /
float(
w),
3871 float(
h - originalVertex /
w) /
float(
h));
3874 pcl::TexMaterial mesh_material;
3875 mesh_material.tex_d = 1.0f;
3876 mesh_material.tex_Ns = 75.0f;
3877 mesh_material.tex_illum = 1;
3879 std::stringstream tex_name;
3880 tex_name <<
"material_" << nodeId;
3881 tex_name >> mesh_material.tex_name;
3883 mesh_material.tex_file =
"";
3885 textureMesh->tex_materials.push_back(mesh_material);
3889 UERROR(
"Adding texture mesh %d to viewer failed!", nodeId);
3898 UERROR(
"Adding mesh cloud %d to viewer failed!", nodeId);
3910 UWARN(
"Online meshing is activated but the generated cloud is "
3911 "dense (voxel filtering is used or multiple cameras are used). Disable "
3912 "online meshing in Preferences->3D Rendering to hide this warning.");
3918 pcl::concatenateFields(*cloud, *normals, *cloudWithNormals);
3921 QColor color = Qt::gray;
3924 color = (Qt::GlobalColor)(mapId+3 % 12 + 7 );
3929 if(cloudWithNormals->size())
3931 pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr outputWithNormals;
3936 UERROR(
"Adding cloud %d to viewer failed!", nodeId);
3947 UERROR(
"Adding cloud %d to viewer failed!", nodeId);
3957 outputPair.first = output;
3984 std::string scanName =
uFormat(
"scan%d", nodeId);
3987 UERROR(
"Scan %d already added to map.", nodeId);
3994 UERROR(
"Node %d is not in the cache.", nodeId);
3998 if(!
iter->sensorData().laserScanCompressed().isEmpty() || !
iter->sensorData().laserScanRaw().isEmpty())
4001 iter->sensorData().uncompressData(0, 0, &scan);
4013 pcl::PointCloud<pcl::PointXYZ>::Ptr cloud;
4014 pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloudRGB;
4015 pcl::PointCloud<pcl::PointXYZI>::Ptr cloudI;
4016 pcl::PointCloud<pcl::PointNormal>::Ptr cloudWithNormals;
4017 pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr cloudRGBWithNormals;
4018 pcl::PointCloud<pcl::PointXYZINormal>::Ptr cloudIWithNormals;
4061 if((!scan.
is2d()) &&
4065 if(cloudRGBWithNormals.get())
4078 if(cloudIWithNormals.get())
4091 if(cloudWithNormals.get())
4145 if( (cloud.get() || cloudRGB.get() || cloudI.get()) &&
4148 Eigen::Vector3f scanViewpoint(
4153 pcl::PointCloud<pcl::Normal>::Ptr normals;
4154 if(cloud.get() && cloud->size())
4164 cloudWithNormals.reset(
new pcl::PointCloud<pcl::PointNormal>);
4165 pcl::concatenateFields(*cloud, *normals, *cloudWithNormals);
4168 else if(cloudRGB.get() && cloudRGB->size())
4172 cloudRGBWithNormals.reset(
new pcl::PointCloud<pcl::PointXYZRGBNormal>);
4173 pcl::concatenateFields(*cloudRGB, *normals, *cloudRGBWithNormals);
4176 else if(cloudI.get())
4186 cloudIWithNormals.reset(
new pcl::PointCloud<pcl::PointXYZINormal>);
4187 pcl::concatenateFields(*cloudI, *normals, *cloudIWithNormals);
4192 QColor color = Qt::gray;
4195 color = (Qt::GlobalColor)(mapId+3 % 12 + 7 );
4198 if(cloudRGBWithNormals.get())
4201 if(added && nodeId > 0)
4206 else if(cloudIWithNormals.get())
4209 if(added && nodeId > 0)
4221 else if(cloudWithNormals.get())
4224 if(added && nodeId > 0)
4236 else if(cloudRGB.get())
4239 if(added && nodeId > 0)
4244 else if(cloudI.get())
4247 if(added && nodeId > 0)
4263 if(added && nodeId > 0)
4277 UERROR(
"Adding cloud %d to viewer failed!", nodeId);
4297 std::string cloudName =
uFormat(
"features%d", nodeId);
4300 UERROR(
"Features cloud %d already added to map.", nodeId);
4307 UERROR(
"Node %d is not in the cache.", nodeId);
4313 UDEBUG(
"Features cloud %d already created.");
4317 if(
iter->getWords3().size())
4319 UINFO(
"Create cloud from 3D words");
4320 QColor color = Qt::gray;
4323 color = (Qt::GlobalColor)(mapId+3 % 12 + 7 );
4327 if(!
iter->sensorData().imageCompressed().empty() || !
iter->sensorData().imageRaw().empty())
4330 data.uncompressData(&rgb, 0, 0);
4333 pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud(
new pcl::PointCloud<pcl::PointXYZRGB>);
4334 cloud->resize(
iter->getWords3().size());
4338 UDEBUG(
"rgb.channels()=%d");
4339 if(!
iter->getWords3().empty() && !
iter->getWordsKpts().empty())
4342 if(
iter.
value().sensorData().cameraModels().size() == 1 &&
4343 iter.
value().sensorData().cameraModels().at(0).isValidForProjection())
4345 invLocalTransform =
iter.
value().sensorData().cameraModels()[0].localTransform().inverse();
4347 else if(
iter.
value().sensorData().stereoCameraModels().size() == 1 &&
4348 iter.
value().sensorData().stereoCameraModels()[0].isValidForProjection())
4350 invLocalTransform =
iter.
value().sensorData().stereoCameraModels()[0].left().localTransform().inverse();
4353 for(std::multimap<int, int>::const_iterator jter=
iter->getWords().begin(); jter!=
iter->getWords().end(); ++jter)
4355 const cv::Point3f & pt =
iter->getWords3()[jter->second];
4357 (maxDepth == 0.0
f ||
4359 (
iter.
value().sensorData().cameraModels().size()<=1 &&
4362 (*cloud)[oi].x = pt.x;
4363 (*cloud)[oi].y = pt.y;
4364 (*cloud)[oi].z = pt.z;
4365 const cv::KeyPoint & kpt =
iter->getWordsKpts()[jter->second];
4366 int u = kpt.pt.x+0.5;
4367 int v = kpt.pt.y+0.5;
4372 if(rgb.channels() == 1)
4374 (*cloud)[oi].r = (*cloud)[oi].g = (*cloud)[oi].b = rgb.at<
unsigned char>(
v, u);
4378 cv::Vec3b bgr = rgb.at<cv::Vec3b>(
v, u);
4379 (*cloud)[oi].b = bgr.val[0];
4380 (*cloud)[oi].g = bgr.val[1];
4381 (*cloud)[oi].r = bgr.val[2];
4386 (*cloud)[oi].r = (*cloud)[oi].g = (*cloud)[oi].b = 255;
4395 UERROR(
"Adding features cloud %d to viewer failed!", nodeId);
4412 const std::map<int, Transform> & poses,
4413 const std::map<int, Transform> & groundTruth)
4416 if(groundTruth.size() && poses.size())
4418 float translational_rmse = 0.0f;
4419 float translational_mean = 0.0f;
4420 float translational_median = 0.0f;
4421 float translational_std = 0.0f;
4422 float translational_min = 0.0f;
4423 float translational_max = 0.0f;
4424 float rotational_rmse = 0.0f;
4425 float rotational_mean = 0.0f;
4426 float rotational_median = 0.0f;
4427 float rotational_std = 0.0f;
4428 float rotational_min = 0.0f;
4429 float rotational_max = 0.0f;
4436 translational_median,
4448 UINFO(
"translational_rmse=%f", translational_rmse);
4449 UINFO(
"translational_mean=%f", translational_mean);
4450 UINFO(
"translational_median=%f", translational_median);
4451 UINFO(
"translational_std=%f", translational_std);
4452 UINFO(
"translational_min=%f", translational_min);
4453 UINFO(
"translational_max=%f", translational_max);
4455 UINFO(
"rotational_rmse=%f", rotational_rmse);
4456 UINFO(
"rotational_mean=%f", rotational_mean);
4457 UINFO(
"rotational_median=%f", rotational_median);
4458 UINFO(
"rotational_std=%f", rotational_std);
4459 UINFO(
"rotational_min=%f", rotational_min);
4460 UINFO(
"rotational_max=%f", rotational_max);
4467 UINFO(
"Update visibility %d", nodeId);
4471 _ui->actionAnchor_clouds_to_ground_truth->isChecked() &&
4481 if(!pose.
isNull() || !visible)
4485 std::string cloudName =
uFormat(
"cloud%d", nodeId);
4486 if(visible && !viewerClouds.contains(cloudName) &&
_cachedSignatures.contains(nodeId))
4490 else if(viewerClouds.contains(cloudName))
4503 std::string scanName =
uFormat(
"scan%d", nodeId);
4504 if(visible && !viewerClouds.contains(scanName) &&
_cachedSignatures.contains(nodeId))
4508 else if(viewerClouds.contains(scanName))
4525 if(
_ui->dockWidget_graphViewer->isVisible())
4527 UDEBUG(
"Graph visible!");
4577 bool removed =
true;
4588 QMessageBox::information(
this, tr(
"Database saved!"), QString(
msg.c_str()));
4592 std::string
msg =
uFormat(
"Failed to rename temporary database from \"%s\" to \"%s\".",
4595 QMessageBox::critical(
this, tr(
"Closing failed!"), QString(
msg.c_str()));
4600 std::string
msg =
uFormat(
"Failed to overwrite the database \"%s\". The temporary database is still correctly saved at \"%s\".",
4603 QMessageBox::critical(
this, tr(
"Closing failed!"), QString(
msg.c_str()));
4620 QMessageBox::information(
this, tr(
"Database updated!"), QString(
msg.c_str()));
4640 if(applicationClosing)
4655 msg.prepend(tr(
"[ERROR] "));
4673 UERROR(
"Map received with code error %d!", event.
getCode());
4681 UINFO(
"Received map!");
4687 QApplication::processEvents();
4689 int addedSignatures = 0;
4690 std::map<int, int> mapIds;
4691 std::map<int, Transform> groundTruth;
4692 std::map<int, std::string>
labels;
4693 for(std::map<int, Signature>::const_iterator
iter = event.
getSignatures().begin();
4697 mapIds.insert(std::make_pair(
iter->first,
iter->second.mapId()));
4698 if(!
iter->second.getGroundTruthPose().isNull())
4700 groundTruth.insert(std::make_pair(
iter->first,
iter->second.getGroundTruthPose()));
4702 if(!
iter->second.getLabel().empty())
4704 labels.insert(std::make_pair(
iter->first,
iter->second.getLabel()));
4707 (
_cachedSignatures.value(
iter->first).sensorData().imageCompressed().empty() && !
iter->second.sensorData().imageCompressed().empty()))
4711 unsigned int count = 0;
4712 if(!
iter->second.getWords3().empty())
4714 for(std::multimap<int, int>::const_iterator jter=
iter->second.getWords().upper_bound(-1); jter!=
iter->second.getWords().end(); ++jter)
4726 QApplication::processEvents();
4730 QApplication::processEvents();
4740 QApplication::processEvents();
4741 std::map<int, Transform> poses =
event.getPoses();
4744 if(
_ui->graphicsView_graphView->isVisible() &&
4757 UINFO(
"Map received is empty! Cannot update the map cloud...");
4787 _ui->graphicsView_graphView->setGlobalPath(event.
getPoses());
4803 QMessageBox * warn =
new QMessageBox(
4804 QMessageBox::Warning,
4805 tr(
"Setting goal failed!"),
4806 tr(
"Setting goal to location %1%2 failed. "
4808 "1) the robot is not yet localized in the map,\n"
4809 "2) the location doesn't exist in the map,\n"
4810 "3) the location is not linked to the global map or\n"
4811 "4) the location is too near of the current location (goal already reached).")
4816 warn->setAttribute(Qt::WA_DeleteOnClose,
true);
4821 QMessageBox *
info =
new QMessageBox(
4822 QMessageBox::Information,
4823 tr(
"Goal detected!"),
4824 tr(
"Global path computed to %1%2 (%3 poses, %4 m).")
4831 info->setAttribute(Qt::WA_DeleteOnClose,
true);
4838 QTimer::singleShot(1000,
this, SLOT(
postGoal()));
4844 QMessageBox * warn =
new QMessageBox(
4845 QMessageBox::Warning,
4846 tr(
"Setting label failed!"),
4847 tr(
"Setting label %1 to location %2 failed. "
4849 "1) the location doesn't exist in the map,\n"
4850 "2) the location has already a label.").
arg(
label).
arg(
id),
4853 warn->setAttribute(Qt::WA_DeleteOnClose,
true);
4892 UDEBUG(
"General settings changed...");
4900 _ui->graphicsView_graphView->clearPosterior();
4906 UDEBUG(
"Cloud rendering settings changed...");
4920 UDEBUG(
"Logging settings changed...");
4939 if(parameters.size())
4941 for(rtabmap::ParametersMap::const_iterator
iter = parameters.begin();
iter!=parameters.end(); ++
iter)
4943 UDEBUG(
"Parameter changed: Key=%s Value=%s",
iter->first.c_str(),
iter->second.c_str());
4948 if(
uContains(parameters, Parameters::kRtabmapWorkingDirectory()))
4968 if(
uContains(parameters, Parameters::kRGBDLocalRadius()))
4970 _ui->graphicsView_graphView->setLocalRadius(
uStr2Float(parameters.at(Parameters::kRGBDLocalRadius())));
4990 _ui->imageView_source->clearFeatures();
4992 for(std::multimap<int, cv::KeyPoint>::const_iterator
iter = refWords.begin();
iter != refWords.end(); ++
iter )
4994 int id =
iter->first;
5004 color = Qt::magenta;
5016 else if(refWords.count(
id) > 1)
5026 _ui->imageView_source->addFeature(
iter->first,
iter->second, 0, color);
5032 QList<QPair<cv::Point2f, cv::Point2f> > uniqueCorrespondences;
5033 if(loopWords.size())
5035 _ui->imageView_loopClosure->clearFeatures();
5037 for(std::multimap<int, cv::KeyPoint>::const_iterator
iter = loopWords.begin();
iter != loopWords.end(); ++
iter )
5039 int id =
iter->first;
5049 color = Qt::magenta;
5053 const cv::KeyPoint &
a = refWords.find(
id)->second;
5054 const cv::KeyPoint &
b =
iter->second;
5055 uniqueCorrespondences.push_back(QPair<cv::Point2f, cv::Point2f>(
a.pt,
b.pt));
5063 else if(refWords.count(
id) > 1)
5073 _ui->imageView_loopClosure->addFeature(
iter->first,
iter->second, 0, color);
5078 if(refWords.size()>0)
5080 if((*refWords.rbegin()).first >
_lastId)
5084 std::list<int> kpts =
uKeysList(refWords);
5085 #if QT_VERSION >= QT_VERSION_CHECK(5, 15, 3)
5086 _lastIds = QSet<int>(kpts.begin(), kpts.end());
5088 _lastIds = QSet<int>::fromList(QList<int>::fromStdList(kpts));
5093 float scaleSource =
_ui->imageView_source->viewScale();
5094 float scaleLoop =
_ui->imageView_loopClosure->viewScale();
5095 UDEBUG(
"scale source=%f loop=%f", scaleSource, scaleLoop);
5097 float sourceMarginX = (
_ui->imageView_source->width() -
_ui->imageView_source->sceneRect().width()*scaleSource)/2.0
f;
5098 float sourceMarginY = (
_ui->imageView_source->height() -
_ui->imageView_source->sceneRect().height()*scaleSource)/2.0
f;
5099 float loopMarginX = (
_ui->imageView_loopClosure->width() -
_ui->imageView_loopClosure->sceneRect().width()*scaleLoop)/2.0
f;
5100 float loopMarginY = (
_ui->imageView_loopClosure->height() -
_ui->imageView_loopClosure->sceneRect().height()*scaleLoop)/2.0
f;
5107 deltaY =
_ui->label_matchId->height() +
_ui->imageView_source->height();
5111 deltaX =
_ui->imageView_source->width();
5114 if(refWords.size() && loopWords.size())
5116 _ui->imageView_source->clearLines();
5117 _ui->imageView_loopClosure->clearLines();
5120 for(QList<QPair<cv::Point2f, cv::Point2f> >::
iterator iter = uniqueCorrespondences.begin();
5121 iter!=uniqueCorrespondences.end();
5125 _ui->imageView_source->addLine(
5128 (
iter->second.x*scaleLoop+loopMarginX+deltaX-sourceMarginX)/scaleSource,
5129 (
iter->second.y*scaleLoop+loopMarginY+deltaY-sourceMarginY)/scaleSource,
5130 _ui->imageView_source->getDefaultMatchingLineColor());
5132 _ui->imageView_loopClosure->addLine(
5133 (
iter->first.x*scaleSource+sourceMarginX-deltaX-loopMarginX)/scaleLoop,
5134 (
iter->first.y*scaleSource+sourceMarginY-deltaY-loopMarginY)/scaleLoop,
5137 _ui->imageView_loopClosure->getDefaultMatchingLineColor());
5139 _ui->imageView_source->update();
5140 _ui->imageView_loopClosure->update();
5159 if(
model.isValidForProjection())
5162 cv::Vec3d rvec, tvec;
5163 tvec.val[0] =
t.
x();
5164 tvec.val[1] =
t.
y();
5165 tvec.val[2] =
t.z();
5171 t.rotationMatrix().convertTo(
R, CV_64F);
5172 cv::Rodrigues(
R, rvec);
5177 std::vector< cv::Point3f > axisPoints;
5179 axisPoints.push_back(cv::Point3f(0, 0, 0));
5180 axisPoints.push_back(cv::Point3f(
length, 0, 0));
5181 axisPoints.push_back(cv::Point3f(0,
length, 0));
5182 axisPoints.push_back(cv::Point3f(0, 0,
length));
5183 std::vector< cv::Point2f > imagePoints;
5184 projectPoints(axisPoints, rvec, tvec,
model.K(),
model.D(), imagePoints);
5190 if(
model.imageWidth() <= 0)
5193 UWARN(
"Cannot draw correctly landmark %d with provided camera model %d (missing image width)", -
iter->first, (
int)
i);
5197 for(
int j=0;
j<4; ++
j)
5199 imagePoints[
j].x +=
i*
model.imageWidth();
5206 cv::line(image, imagePoints[0], imagePoints[1], cv::Scalar(0, 0, 255), 3);
5207 cv::line(image, imagePoints[0], imagePoints[2], cv::Scalar(0, 255, 0), 3);
5208 cv::line(image, imagePoints[0], imagePoints[3], cv::Scalar(255, 0, 0), 3);
5209 cv::putText(image,
uNumber2Str(-
iter->first), imagePoints[0], cv::FONT_HERSHEY_SIMPLEX, 0.75, cv::Scalar(0, 255, 255), 2);
5225 if(this->isVisible())
5238 if(this->isVisible())
5247 if((event->modifiers() & Qt::ControlModifier) && event->key() == Qt::Key_S)
5255 if (event->type() == QEvent::Resize && qobject_cast<QDockWidget*>(obj))
5257 this->setWindowModified(
true);
5259 else if(event->type() == QEvent::FileOpen )
5263 return QWidget::eventFilter(obj, event);
5268 _ui->actionMore_options->setChecked(
5332 QString
name = (QDateTime::currentDateTime().toString(
"yyMMddhhmmsszzz") + (png?
".png":
".jpg"));
5333 _ui->statusbar->clearMessage();
5334 QPixmap figure = this->grab();
5340 msg = tr(
"Screen captured \"%1\"").arg(
name);
5343 buffer.open(QIODevice::WriteOnly);
5344 figure.save(&
buffer, png?
"PNG":
"JPEG");
5350 if(!dir.exists(targetDir))
5352 dir.mkdir(targetDir);
5354 targetDir += QDir::separator();
5355 targetDir +=
"Main_window";
5356 if(!dir.exists(targetDir))
5358 dir.mkdir(targetDir);
5360 targetDir += QDir::separator();
5362 figure.save(targetDir +
name);
5363 msg = tr(
"Screen captured \"%1\"").arg(targetDir +
name);
5366 _ui->widget_console->appendMsg(
msg);
5368 return targetDir +
name;
5373 QApplication::beep();
5384 this->setWindowModified(
true);
5389 if(parameters.size())
5391 for(ParametersMap::const_iterator
iter= parameters.begin();
iter!=parameters.end(); ++
iter)
5393 QString
msg = tr(
"Parameter update \"%1\"=\"%2\"")
5394 .arg(
iter->first.c_str())
5395 .arg(
iter->second.c_str());
5396 _ui->widget_console->appendMsg(
msg);
5399 QMessageBox::StandardButton button = QMessageBox::question(
this,
5401 tr(
"Some parameters have been set on command line, do you "
5402 "want to set all other RTAB-Map's parameters to default?"),
5403 QMessageBox::Yes | QMessageBox::No,
5428 this->setWindowModified(
false);
5435 UERROR(
"This method can be called only in IDLE state.");
5451 if(QFile::exists(databasePath.c_str()))
5453 int r = QMessageBox::question(
this,
5454 tr(
"Creating temporary database"),
5455 tr(
"Cannot create a new database because the temporary database \"%1\" already exists. "
5456 "There may be another instance of RTAB-Map running with the same Working Directory or "
5457 "the last time RTAB-Map was not closed correctly. "
5458 "Do you want to recover the database (click Ignore to delete it and create a new one)?").
arg(databasePath.c_str()),
5459 QMessageBox::Yes | QMessageBox::No | QMessageBox::Ignore, QMessageBox::No);
5461 if(r == QMessageBox::Ignore)
5463 if(QFile::remove(databasePath.c_str()))
5465 UINFO(
"Deleted temporary database \"%s\".", databasePath.c_str());
5469 UERROR(
"Temporary database \"%s\" could not be deleted!", databasePath.c_str());
5473 else if(r == QMessageBox::Yes)
5475 std::string errorMsg;
5487 QString newPath = QFileDialog::getSaveFileName(
this, tr(
"Save recovered database"),
_preferencesDialog->
getWorkingDirectory()+QDir::separator()+QString(
"recovered.db"), tr(
"RTAB-Map database files (*.db)"));
5488 if(newPath.isEmpty())
5492 if(QFileInfo(newPath).suffix() ==
"")
5496 if(QFile::exists(newPath))
5498 QFile::remove(newPath);
5500 QFile::rename(databasePath.c_str(), newPath);
5507 QMessageBox::warning(
this,
"Database recovery", tr(
"Database recovery failed: \"%1\".").
arg(errorMsg.c_str()));
5534 UERROR(
"Database can only be opened in IDLE state.");
5559 if(parameters.size())
5564 parameters.insert(*
iter);
5567 uInsert(parameters, overridedParameters);
5571 for(ParametersMap::iterator
iter=parameters.begin();
iter!=parameters.end(); ++
iter)
5573 ParametersMap::iterator jter = currentParameters.find(
iter->first);
5574 if(jter!=currentParameters.end() &&
5575 iter->second.compare(jter->second) != 0 &&
5576 iter->first.compare(Parameters::kRtabmapWorkingDirectory()) != 0)
5578 bool different =
true;
5596 differentParameters.insert(*
iter);
5597 QString
msg = tr(
"Parameter \"%1\": %2=\"%3\" Preferences=\"%4\"")
5598 .arg(
iter->first.c_str())
5599 .arg(overridedParameters.find(
iter->first) != overridedParameters.end()?
"Arguments":
"Database")
5600 .arg(
iter->second.c_str())
5601 .arg(jter->second.c_str());
5602 _ui->widget_console->appendMsg(
msg);
5608 if(differentParameters.size())
5610 int r = QMessageBox::question(
this,
5611 tr(
"Update parameters..."),
5612 tr(
"The %1 using %2 different parameter(s) than "
5613 "those currently set in Preferences. Do you want "
5614 "to use those parameters?")
5615 .
arg(overridedParameters.empty()?tr(
"database is"):tr(
"database and input arguments are"))
5616 .
arg(differentParameters.size()),
5617 QMessageBox::Yes | QMessageBox::No,
5619 if(r == QMessageBox::Yes)
5640 UERROR(
"This method can be called only in INITIALIZED state.");
5647 QMessageBox::Button
b = QMessageBox::question(
this,
5648 tr(
"Save database"),
5649 tr(
"Save the new database?"),
5650 QMessageBox::Save | QMessageBox::Cancel | QMessageBox::Discard,
5653 if(
b == QMessageBox::Save)
5656 QString newName = QDateTime::currentDateTime().toString(
"yyMMdd-hhmmss");
5659 newPath = QFileDialog::getSaveFileName(
this, tr(
"Save database"), newPath, tr(
"RTAB-Map database files (*.db)"));
5660 if(newPath.isEmpty())
5665 if(QFileInfo(newPath).suffix() ==
"")
5672 else if(
b != QMessageBox::Discard)
5686 UERROR(
"This method can be called only in IDLE state.");
5696 dbSettingsIn.beginGroup(
"DatabaseViewer");
5697 dbSettingsOut.beginGroup(
"DatabaseViewer");
5698 QStringList
keys = dbSettingsIn.childKeys();
5703 dbSettingsIn.endGroup();
5704 dbSettingsOut.endGroup();
5708 viewer->setWindowModality(Qt::WindowModal);
5709 viewer->setAttribute(Qt::WA_DeleteOnClose,
true);
5714 viewer->showMaximized();
5740 float detectionRate =
uStr2Float(parameters.at(Parameters::kRtabmapDetectionRate()));
5741 int bufferingSize =
uStr2Float(parameters.at(Parameters::kRtabmapImageBufferSize()));
5742 if(((detectionRate!=0.0
f && detectionRate <= inputRate) || (detectionRate > 0.0
f && inputRate == 0.0
f)) &&
5745 int button = QMessageBox::question(
this,
5746 tr(
"Incompatible frame rates!"),
5747 tr(
"\"Source/Input rate\" (%1 Hz) is equal to/higher than \"RTAB-Map/Detection rate\" (%2 Hz). As the "
5748 "source input is a directory of images/video/database, some images may be "
5749 "skipped by the detector. You may want to increase the \"RTAB-Map/Detection rate\" over "
5750 "the \"Source/Input rate\" to guaranty that all images are processed. Would you want to "
5751 "start the detection anyway?").
arg(inputRate).
arg(detectionRate),
5752 QMessageBox::Yes | QMessageBox::No);
5753 if(button == QMessageBox::No)
5760 if(bufferingSize != 0)
5762 int button = QMessageBox::question(
this,
5763 tr(
"Some images may be skipped!"),
5764 tr(
"\"RTAB-Map/Images buffer size\" is not infinite (size=%1). As the "
5765 "source input is a directory of images/video/database, some images may be "
5766 "skipped by the detector if the \"Source/Input rate\" (which is %2 Hz) is higher than the "
5767 "rate at which RTAB-Map can process the images. You may want to set the "
5768 "\"RTAB-Map/Images buffer size\" to 0 (infinite) to guaranty that all "
5769 "images are processed. Would you want to start the detection "
5770 "anyway?").
arg(bufferingSize).
arg(inputRate),
5771 QMessageBox::Yes | QMessageBox::No);
5772 if(button == QMessageBox::No)
5777 else if(inputRate == 0)
5779 int button = QMessageBox::question(
this,
5780 tr(
"Large number of images may be buffered!"),
5781 tr(
"\"RTAB-Map/Images buffer size\" is infinite. As the "
5782 "source input is a directory of images/video/database and "
5783 "that \"Source/Input rate\" is infinite too, a lot of images "
5784 "could be buffered at the same time (e.g., reading all images "
5785 "of a directory at once). This could make the GUI not responsive. "
5786 "You may want to set \"Source/Input rate\" at the rate at "
5787 "which the images have been recorded. "
5788 "Would you want to start the detection "
5789 "anyway?").
arg(bufferingSize).
arg(inputRate),
5790 QMessageBox::Yes | QMessageBox::No);
5791 if(button == QMessageBox::No)
5804 QMessageBox::warning(
this,
5806 tr(
"A camera is running, stop it first."));
5807 UWARN(
"_sensorCapture is not null... it must be stopped first");
5816 QMessageBox::warning(
this,
5818 tr(
"No sources are selected. See Preferences->Source panel."));
5819 UWARN(
"No sources are selected. See Preferences->Source panel.");
5825 double poseTimeOffset = 0.0;
5826 float scaleFactor = 0.0f;
5827 double waitTime = 0.1;
5866 UINFO(
"Create Odom Sensor %d (camera = %d)",
5880 UINFO(
"The camera is also the odometry sensor (camera=%d odom=%d).",
5926 if(
uStr2Bool(parameters.at(Parameters::kRGBDEnabled()).c_str()))
5931 UWARN(
"Camera is not calibrated!");
5936 int button = QMessageBox::question(
this,
5937 tr(
"Camera is not calibrated!"),
5938 tr(
"RTAB-Map in metric SLAM mode cannot run with an uncalibrated camera. Do you want to calibrate the camera now?"),
5939 QMessageBox::Yes | QMessageBox::No);
5940 if(button == QMessageBox::Yes)
5950 UERROR(
"OdomThread must be already deleted here?!");
5957 UERROR(
"ImuThread must be already deleted here?!");
5969 odomParameters.erase(Parameters::kRtabmapPublishRAMUsage());
5970 int odomStrategy = Parameters::defaultOdomStrategy();
5973 UDEBUG(
"Odom gravitySigma=%f", gravitySigma);
5974 if(gravitySigma >= 0.0)
5978 if(odomStrategy != 1)
5981 odomParameters.erase(Parameters::kVisCorType());
5996 QMessageBox::warning(
this, tr(
"Source IMU Path"),
6031 _ui->actionReset_Odometry->setEnabled(
true);
6036 QMessageBox::information(
this,
6038 tr(
"Note that publishing statistics is disabled, "
6039 "progress will not be shown in the GUI."));
6053 #ifdef RTABMAP_OCTOMAP
6058 #ifdef RTABMAP_GRIDMAP
6078 if(
_state ==
kPaused && (QApplication::keyboardModifiers() & Qt::ShiftModifier))
6098 UINFO(
"Sending pause event!");
6103 UINFO(
"Sending unpause event!");
6118 QMessageBox::StandardButton button = QMessageBox::question(
this, tr(
"Stopping process..."), tr(
"Are you sure you want to stop the process?"), QMessageBox::Yes|QMessageBox::No, QMessageBox::No);
6120 if(button != QMessageBox::Yes)
6140 _ui->actionReset_Odometry->setEnabled(
false);
6172 QMessageBox::information(
this,
6173 tr(
"No more images..."),
6174 tr(
"The camera has reached the end of the stream."));
6179 _ui->dockWidget_console->show();
6184 msgRef.append(QString::number(
_refIds[
i]));
6189 msgLoop.append(
" ");
6192 _ui->widget_console->appendMsg(QString(
"IDs = [%1];").
arg(msgRef));
6193 _ui->widget_console->appendMsg(QString(
"LoopIDs = [%1];").
arg(msgLoop));
6204 int id = QInputDialog::getInt(
this, tr(
"Around which location?"), tr(
"Location ID (0=full map)"), 0, 0, 999999, 0, &ok);
6210 margin = QInputDialog::getInt(
this, tr(
"Depth around the location?"), tr(
"Margin"), 4, 1, 100, 1, &ok);
6215 QString
path = QFileDialog::getSaveFileName(
this, tr(
"Save File"),
_graphSavingFileName, tr(
"Graphiz file (*.dot)"));
6221 _ui->dockWidget_console->show();
6261 std::map<int, Transform> localTransforms;
6263 items.push_back(
"Robot (base frame)");
6264 items.push_back(
"Camera");
6265 items.push_back(
"Scan");
6267 QString item = QInputDialog::getItem(
this, tr(
"Export Poses"), tr(
"Frame: "), items,
_exportPosesFrame,
false, &ok);
6268 if(!ok || item.isEmpty())
6272 if(item.compare(
"Robot (base frame)") != 0)
6274 bool cameraFrame = item.compare(
"Camera") == 0;
6291 localTransform =
_cachedSignatures[
iter->first].sensorData().stereoCameraModels()[0].localTransform();
6296 UWARN(
"Multi-camera is not supported (node %d)",
iter->first);
6300 UWARN(
"Missing calibration for node %d",
iter->first);
6309 else if(!
_cachedSignatures[
iter->first].sensorData().laserScanCompressed().localTransform().isNull())
6311 localTransform =
_cachedSignatures[
iter->first].sensorData().laserScanCompressed().localTransform();
6315 UWARN(
"Missing scan info for node %d",
iter->first);
6318 if(!localTransform.
isNull())
6320 localTransforms.insert(std::make_pair(
iter->first, localTransform));
6325 UWARN(
"Did not find node %d in cache",
iter->first);
6328 if(localTransforms.empty())
6330 QMessageBox::warning(
this,
6332 tr(
"Could not find any \"%1\" frame, exporting in Robot frame instead.").
arg(item));
6340 std::map<int, Transform> poses;
6341 std::multimap<int, Link> links;
6342 if(localTransforms.empty())
6350 for(std::map<int, Transform>::iterator
iter=localTransforms.begin();
iter!=localTransforms.end(); ++
iter)
6358 std::multimap<int, Link>::iterator inserted = links.insert(*
iter);
6359 int from =
iter->second.from();
6360 int to =
iter->second.to();
6361 inserted->second.setTransform(localTransforms.at(from).inverse()*
iter->second.transform()*localTransforms.at(to));
6366 if(
format != 4 &&
format != 11 && !poses.empty() && poses.begin()->first<0)
6368 UWARN(
"Only g2o format (4) and RGBD format with ID format can export landmarks, they are ignored with format %d",
format);
6369 for(std::map<int, Transform>::iterator
iter=poses.begin();
iter!=poses.end() &&
iter->first < 0;)
6371 poses.erase(
iter++);
6373 for(std::multimap<int, Link>::iterator
iter=links.begin();
iter!=links.end();)
6375 if(
iter->second.from() < 0 ||
iter->second.to() < 0)
6377 links.erase(
iter++);
6386 std::map<int, double> stamps;
6389 for(std::map<int, Transform>::iterator
iter=poses.begin();
iter!=poses.end(); ++
iter)
6393 stamps.insert(std::make_pair(
iter->first, 0));
6400 if(stamps.size()!=poses.size())
6402 QMessageBox::warning(
this, tr(
"Export poses..."), tr(
"RGB-D SLAM format: Poses (%1) and stamps (%2) have not the same size! Try again after updating the cache.")
6403 .
arg(poses.size()).
arg(stamps.size()));
6413 QString
path = QFileDialog::getSaveFileName(
6417 format == 3?tr(
"TORO file (*.graph)"):
format==4?tr(
"g2o file (*.g2o)"):tr(
"Text file (*.txt)"));
6421 if(QFileInfo(
path).suffix() ==
"")
6442 QMessageBox::information(
this,
6443 tr(
"Export poses..."),
6444 tr(
"%1 saved to \"%2\".")
6450 QMessageBox::information(
this,
6451 tr(
"Export poses..."),
6452 tr(
"Failed to save %1 to \"%2\"!")
6484 bool refineNeighborLinks,
6485 bool refineLoopClosureLinks,
6486 bool detectMoreLoopClosures,
6487 double clusterRadius,
6488 double clusterAngle,
6496 double sbaRematchFeatures,
6497 bool abortIfDataMissing)
6501 QMessageBox::warning(
this,
6502 tr(
"Post-processing..."),
6503 tr(
"Signatures must be cached in the GUI for post-processing. "
6504 "Check the option in Preferences->General Settings (GUI), then "
6505 "refresh the cache."));
6509 if(!detectMoreLoopClosures && !refineNeighborLinks && !refineLoopClosureLinks && !sba)
6511 UWARN(
"No post-processing selection...");
6517 UWARN(
"No nodes to process...");
6522 std::map<int, Transform> odomPoses;
6523 bool allDataAvailable =
true;
6532 allDataAvailable =
false;
6534 else if(!jter.value().getPose().isNull())
6536 odomPoses.insert(std::make_pair(
iter->first, jter.value().getPose()));
6540 if(!allDataAvailable)
6542 QString
msg = tr(
"Some data missing in the cache to respect the constraints chosen. "
6543 "Try \"Edit->Download all clouds\" to update the cache and try again.");
6545 if(abortIfDataMissing)
6547 QMessageBox::warning(
this, tr(
"Not all data available in the GUI..."),
msg);
6560 if(refineNeighborLinks)
6564 if(refineLoopClosureLinks)
6577 bool optimizeFromGraphEnd = Parameters::defaultRGBDOptimizeFromGraphEnd();
6578 float optimizeMaxError = Parameters::defaultRGBDOptimizeMaxError();
6579 int optimizeIterations = Parameters::defaultOptimizerIterations();
6580 bool reextractFeatures = Parameters::defaultRGBDLoopClosureReextractFeatures();
6581 Parameters::parse(parameters, Parameters::kRGBDOptimizeFromGraphEnd(), optimizeFromGraphEnd);
6582 Parameters::parse(parameters, Parameters::kRGBDOptimizeMaxError(), optimizeMaxError);
6583 Parameters::parse(parameters, Parameters::kOptimizerIterations(), optimizeIterations);
6584 Parameters::parse(parameters, Parameters::kRGBDLoopClosureReextractFeatures(), reextractFeatures);
6587 int loopClosuresAdded = 0;
6588 std::multimap<int, int> checkedLoopClosures;
6589 if(detectMoreLoopClosures)
6593 bool loopCovLimited = Parameters::defaultRGBDLoopCovLimited();
6594 Parameters::parse(parameters, Parameters::kRGBDLoopCovLimited(), loopCovLimited);
6595 std::vector<double> odomMaxInf;
6604 _progressDialog->
appendText(tr(
"Looking for more loop closures, clustering poses... (iteration=%1/%2, radius=%3 m angle=%4 degrees)")
6605 .
arg(
n+1).
arg(iterations).
arg(clusterRadius).
arg(clusterAngle));
6610 clusterAngle*CV_PI/180.0);
6614 QApplication::processEvents();
6617 std::set<int> addedLinks;
6620 int from =
iter->first;
6621 int to =
iter->second;
6624 from =
iter->second;
6631 if((interSession && mapIdFrom != mapIdTo) ||
6632 (intraSession && mapIdFrom == mapIdTo))
6634 bool alreadyChecked =
false;
6635 for(std::multimap<int, int>::iterator jter = checkedLoopClosures.lower_bound(from);
6636 !alreadyChecked && jter!=checkedLoopClosures.end() && jter->first == from;
6639 if(to == jter->second)
6641 alreadyChecked =
true;
6648 if(addedLinks.find(from) == addedLinks.end() &&
6649 addedLinks.find(to) == addedLinks.end() &&
6654 if(
delta.getNorm() < clusterRadius)
6656 checkedLoopClosures.insert(std::make_pair(from, to));
6660 UERROR(
"Didn't find signature %d", from);
6664 UERROR(
"Didn't find signature %d", to);
6676 if(parameters.find(Parameters::kRegStrategy()) != parameters.end() &&
6677 parameters.at(Parameters::kRegStrategy()).compare(
"1") == 0)
6683 if(reextractFeatures)
6691 UWARN(
"\"%s\" is false and signatures (%d and %d) don't have raw "
6692 "images. Update the cache.",
6693 Parameters::kRGBDLoopClosureReextractFeatures().
c_str());
6698 signatureFrom.
sensorData().
setFeatures(std::vector<cv::KeyPoint>(), std::vector<cv::Point3f>(), cv::Mat());
6700 signatureTo.
sensorData().
setFeatures(std::vector<cv::KeyPoint>(), std::vector<cv::Point3f>(), cv::Mat());
6703 else if(!reextractFeatures && signatureFrom.
getWords().empty() && signatureTo.
getWords().empty())
6705 UWARN(
"\"%s\" is false and signatures (%d and %d) don't have words, "
6706 "registration will not be possible. Set \"%s\" to true.",
6707 Parameters::kRGBDLoopClosureReextractFeatures().
c_str(),
6710 Parameters::kRGBDLoopClosureReextractFeatures().c_str());
6713 delete registration;
6717 bool updateConstraint =
true;
6718 cv::Mat information =
info.covariance.inv();
6719 if(odomMaxInf.size() == 6 && information.cols==6 && information.rows==6)
6721 for(
int i=0;
i<6; ++
i)
6723 if(information.at<
double>(
i,
i) > odomMaxInf[
i])
6725 information.at<
double>(
i,
i) = odomMaxInf[
i];
6729 if(optimizeMaxError > 0.0
f && optimizeIterations > 0)
6738 fromId =
iter->first;
6744 const Link * maxLinearLink = 0;
6745 const Link * maxAngularLink = 0;
6746 float maxLinearError = 0.0f;
6747 float maxAngularError = 0.0f;
6748 std::map<int, Transform> poses;
6749 std::multimap<int, Link> links;
6754 UASSERT(poses.find(fromId) != poses.end());
6755 UASSERT_MSG(poses.find(from) != poses.end(),
uFormat(
"id=%d poses=%d links=%d", from, (
int)poses.size(), (
int)links.size()).c_str());
6756 UASSERT_MSG(poses.find(to) != poses.end(),
uFormat(
"id=%d poses=%d links=%d", to, (
int)poses.size(), (
int)links.size()).c_str());
6758 poses = optimizer->
optimize(fromId, poses, links);
6762 float maxLinearErrorRatio = 0.0f;
6763 float maxAngularErrorRatio = 0.0f;
6767 maxLinearErrorRatio,
6768 maxAngularErrorRatio,
6775 UINFO(
"Max optimization linear error = %f m (link %d->%d)", maxLinearError, maxLinearLink->
from(), maxLinearLink->
to());
6776 if(maxLinearErrorRatio > optimizeMaxError)
6778 msg =
uFormat(
"Rejecting edge %d->%d because "
6779 "graph error is too large after optimization (%f m for edge %d->%d with ratio %f > std=%f m). "
6784 maxLinearLink->
from(),
6785 maxLinearLink->
to(),
6786 maxLinearErrorRatio,
6788 Parameters::kRGBDOptimizeMaxError().c_str(),
6792 else if(maxAngularLink)
6794 UINFO(
"Max optimization angular error = %f deg (link %d->%d)", maxAngularError*180.0
f/
M_PI, maxAngularLink->
from(), maxAngularLink->
to());
6795 if(maxAngularErrorRatio > optimizeMaxError)
6797 msg =
uFormat(
"Rejecting edge %d->%d because "
6798 "graph error is too large after optimization (%f deg for edge %d->%d with ratio %f > std=%f deg). "
6802 maxAngularError*180.0
f/
M_PI,
6803 maxAngularLink->
from(),
6804 maxAngularLink->
to(),
6805 maxAngularErrorRatio,
6807 Parameters::kRGBDOptimizeMaxError().c_str(),
6814 msg =
uFormat(
"Rejecting edge %d->%d because graph optimization has failed!",
6822 QApplication::processEvents();
6823 updateConstraint =
false;
6831 if(updateConstraint)
6833 UINFO(
"Added new loop closure between %d and %d.", from, to);
6834 addedLinks.insert(from);
6835 addedLinks.insert(to);
6838 ++loopClosuresAdded;
6848 QApplication::processEvents();
6852 if(addedLinks.size() == 0)
6857 if(
n+1 < iterations)
6861 QApplication::processEvents();
6865 std::map<int, rtabmap::Transform> posesOut;
6866 std::multimap<int, rtabmap::Link> linksOut;
6867 std::map<int, rtabmap::Transform> optimizedPoses;
6875 optimizedPoses = optimizer->
optimize(fromId, posesOut, linksOut);
6880 UINFO(
"Added %d loop closures.", loopClosuresAdded);
6887 if(refineLoopClosureLinks)
6893 QApplication::processEvents();
6901 int from =
iter->second.from();
6902 int to =
iter->second.to();
6909 QApplication::processEvents();
6913 UERROR(
"Didn't find signature %d",from);
6917 UERROR(
"Didn't find signature %d", to);
6937 iter->second = newLink;
6941 QString
str = tr(
"Cannot refine link %1->%2 (%3").arg(from).arg(to).arg(
info.rejectedMsg.c_str());
6943 UWARN(
"%s",
str.toStdString().c_str());
6952 str = tr(
"Cannot refine link %1->%2 (Intermediate node detected!)").arg(from).arg(to);
6956 str = tr(
"Cannot refine link %1->%2 (scans empty!)").arg(from).arg(to);
6960 UWARN(
"%s",
str.toStdString().c_str());
6974 std::map<int, rtabmap::Transform> posesOut;
6975 std::multimap<int, rtabmap::Link> linksOut;
6976 std::map<int, rtabmap::Transform> optimizedPoses;
6984 optimizedPoses = optimizer->
optimize(fromId, posesOut, linksOut);
6992 .
arg(optimizedPoses.size()).
arg(linksOut.size()).arg(sbaIterations));
6993 QApplication::processEvents();
6995 QApplication::processEvents();
6998 uInsert(parametersSBA, std::make_pair(Parameters::kOptimizerIterations(),
uNumber2Str(sbaIterations)));
6999 uInsert(parametersSBA, std::make_pair(Parameters::kg2oPixelVariance(),
uNumber2Str(sbaVariance)));
7001 std::map<int, Transform> newPoses = sbaOptimizer->
optimizeBA(optimizedPoses.begin()->first, optimizedPoses, linksOut,
_cachedSignatures.toStdMap(), sbaRematchFeatures);
7002 delete sbaOptimizer;
7005 optimizedPoses = newPoses;
7023 std::map<int, Transform>(),
7024 std::multimap<int, Link>(),
7053 QMessageBox::warning(
this, tr(
"Depth Calibration"), tr(
"No data in cache. Try to refresh the cache."));
7059 QMessageBox::StandardButton button;
7062 button = QMessageBox::question(
this,
7063 tr(
"Deleting memory..."),
7064 tr(
"The remote database and log files will be deleted. Are you sure you want to continue? (This cannot be reverted)"),
7065 QMessageBox::Yes|QMessageBox::No,
7070 button = QMessageBox::question(
this,
7071 tr(
"Deleting memory..."),
7072 tr(
"The current database and log files will be deleted. Are you sure you want to continue? (This cannot be reverted)"),
7073 QMessageBox::Yes|QMessageBox::No,
7077 if(button != QMessageBox::Yes)
7098 #if defined(Q_WS_MAC)
7101 args <<
"tell application \"Finder\"";
7105 args <<
"select POSIX file \""+filePath+
"\"";
7108 QProcess::startDetached(
"osascript",
args);
7109 #elif defined(Q_WS_WIN)
7111 args <<
"/select," << QDir::toNativeSeparators(filePath);
7112 QProcess::startDetached(
"explorer",
args);
7114 UERROR(
"Only works on Mac and Windows");
7263 UINFO(
"Sending a goal...");
7265 QString
text = QInputDialog::getText(
this, tr(
"Send a goal"), tr(
"Goal location ID or label: "), QLineEdit::Normal,
"", &ok);
7266 if(ok && !
text.isEmpty())
7277 UINFO(
"Sending waypoints...");
7279 QString
text = QInputDialog::getText(
this, tr(
"Send waypoints"), tr(
"Waypoint IDs or labels (separated by spaces): "), QLineEdit::Normal,
"", &ok);
7280 if(ok && !
text.isEmpty())
7282 QStringList wp =
text.split(
' ');
7285 QMessageBox::warning(
this, tr(
"Send waypoints"), tr(
"At least two waypoints should be set. For only one goal, use send goal action."));
7309 int id = goal.toInt(&ok);
7310 _ui->graphicsView_graphView->setGlobalPath(std::vector<std::pair<int, Transform> >());
7311 UINFO(
"Posting event with goal %s", goal.toStdString().c_str());
7325 UINFO(
"Cancelling goal...");
7333 UINFO(
"Labelling current location...");
7335 QString
label = QInputDialog::getText(
this, tr(
"Label current location"), tr(
"Label: "), QLineEdit::Normal,
"", &ok);
7336 if(ok && !
label.isEmpty())
7344 UINFO(
"Removing label...");
7346 QString
label = QInputDialog::getText(
this, tr(
"Remove label"), tr(
"Label: "), QLineEdit::Normal,
"", &ok);
7347 if(ok && !
label.isEmpty())
7356 QString
path = QFileDialog::getOpenFileName(
this, tr(
"Select file"), dir, tr(
"RTAB-Map database files (*.db)"));
7370 UINFO(
"Update cache...");
7378 std::list<Signature*> signaturesList;
7379 driver->
loadSignatures(std::list<int>(ids.begin(), ids.end()), signaturesList);
7380 std::map<int, Signature> signatures;
7382 for(std::list<Signature *>::iterator
iter=signaturesList.begin();
iter!=signaturesList.end(); ++
iter)
7384 signatures.insert(std::make_pair((*iter)->id(), *(*
iter)));
7397 QMessageBox::warning(
this, tr(
"Update cache"), tr(
"Failed to open database \"%1\"").
arg(
path));
7406 items.append(
"Local map optimized");
7407 items.append(
"Local map not optimized");
7408 items.append(
"Global map optimized");
7409 items.append(
"Global map not optimized");
7412 QString item = QInputDialog::getItem(
this, tr(
"Download map"), tr(
"Options:"), items, 0,
false, &ok);
7415 bool optimized=
false, global=
false;
7416 if(item.compare(
"Local map optimized") == 0)
7420 else if(item.compare(
"Local map not optimized") == 0)
7424 else if(item.compare(
"Global map optimized") == 0)
7429 else if(item.compare(
"Global map not optimized") == 0)
7435 UFATAL(
"Item \"%s\" not found?!?", item.toStdString().c_str());
7438 UINFO(
"Download clouds...");
7442 .
arg(global?
"true":
"false").
arg(optimized?
"true":
"false"));
7450 items.append(
"Local map optimized");
7451 items.append(
"Local map not optimized");
7452 items.append(
"Global map optimized");
7453 items.append(
"Global map not optimized");
7456 QString item = QInputDialog::getItem(
this, tr(
"Download graph"), tr(
"Options:"), items, 0,
false, &ok);
7459 bool optimized=
false, global=
false;
7460 if(item.compare(
"Local map optimized") == 0)
7464 else if(item.compare(
"Local map not optimized") == 0)
7468 else if(item.compare(
"Global map optimized") == 0)
7473 else if(item.compare(
"Global map not optimized") == 0)
7479 UFATAL(
"Item \"%s\" not found?!?", item.toStdString().c_str());
7482 UINFO(
"Download the graph...");
7486 .
arg(global?
"true":
"false").
arg(optimized?
"true":
"false"));
7519 _ui->widget_mapVisibility->clear();
7527 _ui->statsToolBox->clear();
7529 _ui->actionExport_2D_Grid_map_bmp_png->setEnabled(
false);
7530 _ui->actionPost_processing->setEnabled(
false);
7531 _ui->actionSave_point_cloud->setEnabled(
false);
7532 _ui->actionExport_cameras_in_Bundle_format_out->setEnabled(
false);
7533 _ui->actionDepth_Calibration->setEnabled(
false);
7534 _ui->actionExport_images_RGB_jpg_Depth_png->setEnabled(
false);
7535 _ui->actionExport_octomap->setEnabled(
false);
7536 _ui->actionView_high_res_point_cloud->setEnabled(
false);
7543 _ui->label_stats_loopClosuresDetected->setText(
"0");
7544 _ui->label_stats_loopClosuresReactivatedDetected->setText(
"0");
7545 _ui->label_stats_loopClosuresRejected->setText(
"0");
7549 _ui->label_refId->clear();
7550 _ui->label_matchId->clear();
7551 _ui->graphicsView_graphView->clearAll();
7552 _ui->imageView_source->clear();
7553 _ui->imageView_loopClosure->clear();
7554 _ui->imageView_odometry->clear();
7555 _ui->imageView_source->setBackgroundColor(
_ui->imageView_source->getDefaultBackgroundColor());
7556 _ui->imageView_loopClosure->setBackgroundColor(
_ui->imageView_loopClosure->getDefaultBackgroundColor());
7557 _ui->imageView_odometry->setBackgroundColor(
_ui->imageView_odometry->getDefaultBackgroundColor());
7560 #ifdef RTABMAP_OCTOMAP
7574 QDesktopServices::openUrl(QUrl(
"http://wiki.ros.org/rtabmap_ros"));
7578 QDesktopServices::openUrl(QUrl(
"https://github.com/introlab/rtabmap/wiki"));
7586 QString
format =
"hh:mm:ss";
7587 _ui->label_elapsedTime->setText((QTime().fromString(
_ui->label_elapsedTime->text(),
format).addMSecs(
_elapsedTime->restart())).toString(
format));
7593 QList<int> curvesPerFigure;
7594 QStringList curveNames;
7595 QStringList curveThresholds;
7596 _ui->statsToolBox->getFiguresSetup(curvesPerFigure, curveNames, curveThresholds);
7598 QStringList curvesPerFigureStr;
7599 for(
int i=0;
i<curvesPerFigure.size(); ++
i)
7601 curvesPerFigureStr.append(QString::number(curvesPerFigure[
i]));
7603 for(
int i=0;
i<curveNames.size(); ++
i)
7605 curveNames[
i].replace(
' ',
'_');
7618 if(!curvesPerFigure.isEmpty())
7620 QStringList curvesPerFigureList = curvesPerFigure.split(
" ");
7621 QStringList curvesNamesList = curveNames.split(
" ");
7622 QStringList curveThresholdsList = curveThresholds.split(
" ");
7623 if(curveThresholdsList[0].isEmpty()) {
7624 curveThresholdsList.clear();
7626 UASSERT(curveThresholdsList.isEmpty() || curveThresholdsList.size() == curvesNamesList.size());
7629 for(
int i=0;
i<curvesPerFigureList.size(); ++
i)
7632 int count = curvesPerFigureList[
i].toInt(&ok);
7635 QMessageBox::warning(
this,
"Loading failed",
"Corrupted figures setup...");
7640 _ui->statsToolBox->addCurve(curvesNamesList[
j++].replace(
'_',
' '));
7641 for(
int k=1; k<
count &&
j<curveNames.size(); ++k)
7643 if(curveThresholdsList.size())
7646 double thresholdValue = curveThresholdsList[
j].toDouble(&ok);
7649 _ui->statsToolBox->addThreshold(curvesNamesList[
j++].replace(
'_',
' '), thresholdValue);
7653 _ui->statsToolBox->addCurve(curvesNamesList[
j++].replace(
'_',
' '),
false);
7658 _ui->statsToolBox->addCurve(curvesNamesList[
j++].replace(
'_',
' '),
false);
7682 _ui->dockWidget_posterior->setVisible(
false);
7683 _ui->dockWidget_likelihood->setVisible(
false);
7684 _ui->dockWidget_rawlikelihood->setVisible(
false);
7685 _ui->dockWidget_statsV2->setVisible(
false);
7686 _ui->dockWidget_console->setVisible(
false);
7687 _ui->dockWidget_loopClosureViewer->setVisible(
false);
7688 _ui->dockWidget_mapVisibility->setVisible(
false);
7689 _ui->dockWidget_graphViewer->setVisible(
false);
7690 _ui->dockWidget_odometry->setVisible(
true);
7691 _ui->dockWidget_cloudViewer->setVisible(
true);
7692 _ui->dockWidget_imageView->setVisible(
true);
7693 _ui->dockWidget_multiSessionLoc->setVisible(
false);
7695 _ui->toolBar_2->setVisible(
true);
7696 _ui->statusbar->setVisible(
false);
7708 items << QString(
"Synchronize with map update") << QString(
"Synchronize with odometry update");
7710 QString item = QInputDialog::getItem(
this, tr(
"Select synchronization behavior"), tr(
"Sync:"), items, 0,
false, &ok);
7711 if(ok && !item.isEmpty())
7713 if(item.compare(
"Synchronize with map update") == 0)
7724 int r = QMessageBox::question(
this, tr(
"Hard drive or RAM?"), tr(
"Save in RAM? Images will be saved on disk when clicking auto screen capture again."), QMessageBox::Yes | QMessageBox::No, QMessageBox::No);
7725 if(r == QMessageBox::No || r == QMessageBox::Yes)
7731 _ui->actionAuto_screen_capture->setChecked(
false);
7734 r = QMessageBox::question(
this, tr(
"Save in JPEG?"), tr(
"Save in JPEG format? Otherwise they are saved in PNG."), QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
7735 if(r == QMessageBox::No || r == QMessageBox::Yes)
7741 _ui->actionAuto_screen_capture->setChecked(
false);
7747 _ui->actionAuto_screen_capture->setChecked(
false);
7754 if(!dir.exists(targetDir))
7756 dir.mkdir(targetDir);
7758 targetDir += QDir::separator();
7759 targetDir +=
"Main_window";
7760 if(!dir.exists(targetDir))
7762 dir.mkdir(targetDir);
7764 targetDir += QDir::separator();
7778 QApplication::processEvents();
7788 QDesktopServices::openUrl(QUrl::fromLocalFile(this->
captureScreen()));
7793 QRect rect = this->geometry();
7797 if(
float(rect.width())/
float(rect.height()) >
float(
w)/
float(
h))
7799 rect.setWidth(
w*(rect.height()/
h));
7800 rect.setHeight((rect.height()/
h)*
h);
7804 rect.setHeight(
h*(rect.width()/
w));
7805 rect.setWidth((rect.width()/
w)*
w);
7814 this->setGeometry(rect);
7860 int width = QInputDialog::getInt(
this, tr(
"Aspect ratio"), tr(
"Width (pixels):"), this->geometry().width(), 100, 10000, 100, &ok);
7863 int height = QInputDialog::getInt(
this, tr(
"Aspect ratio"), tr(
"Height (pixels):"), this->geometry().height(), 100, 10000, 100, &ok);
7873 float gridCellSize = 0.05f;
7875 gridCellSize = (
float)QInputDialog::getDouble(
this, tr(
"Grid cell size"), tr(
"Size (m):"), (double)gridCellSize, 0.01, 1, 2, &ok);
7882 float xMin=0.0f, yMin=0.0f;
7884 #ifdef RTABMAP_OCTOMAP
7898 cv::Mat map8U(pixels.rows, pixels.cols, CV_8U);
7900 for (
int i = 0;
i < pixels.rows; ++
i)
7902 for (
int j = 0;
j < pixels.cols; ++
j)
7904 char v = pixels.at<
char>(
i,
j);
7918 map8U.at<
unsigned char>(
i,
j) = gray;
7924 QString
path = QFileDialog::getSaveFileName(
this, tr(
"Save to ..."),
"grid.png", tr(
"Image (*.png *.bmp)"));
7927 if(QFileInfo(
path).suffix() !=
"png" && QFileInfo(
path).suffix() !=
"bmp")
7933 QImage
img = image.mirrored(
false,
true).transformed(QTransform().
rotate(-90));
7934 QPixmap::fromImage(
img).save(
path);
7936 QDesktopServices::openUrl(QUrl::fromLocalFile(
path));
7948 std::map<int, Transform> poses =
_ui->widget_mapVisibility->getVisiblePoses();
7953 for(std::map<int, Transform>::iterator
iter = poses.begin();
iter!=poses.end(); ++
iter)
7958 iter->second = gtIter->second;
7962 UWARN(
"Not found ground truth pose for node %d",
iter->first);
7985 std::map<int, Transform> poses =
_ui->widget_mapVisibility->getVisiblePoses();
7990 for(std::map<int, Transform>::iterator
iter = poses.begin();
iter!=poses.end(); ++
iter)
7995 iter->second = gtIter->second;
7999 UWARN(
"Not found ground truth pose for node %d",
iter->first);
8018 #ifdef RTABMAP_OCTOMAP
8021 QString
path = QFileDialog::getSaveFileName(
8025 tr(
"Octomap file (*.bt)"));
8031 QMessageBox::information(
this,
8032 tr(
"Export octomap..."),
8033 tr(
"Octomap successfully saved to \"%1\".")
8038 QMessageBox::information(
this,
8039 tr(
"Export octomap..."),
8040 tr(
"Failed to save octomap to \"%1\"!")
8047 UERROR(
"Empty octomap.");
8050 UERROR(
"Cannot export octomap, RTAB-Map is not built with it.");
8058 QMessageBox::warning(
this, tr(
"Export images..."), tr(
"Cannot export images, the cache is empty!"));
8061 std::map<int, Transform> poses =
_ui->widget_mapVisibility->getVisiblePoses();
8065 QMessageBox::warning(
this, tr(
"Export images..."), tr(
"There is no map!"));
8069 QStringList formats;
8070 formats.push_back(
"id.jpg");
8071 formats.push_back(
"id.png");
8072 formats.push_back(
"timestamp.jpg");
8073 formats.push_back(
"timestamp.png");
8075 QString
format = QInputDialog::getItem(
this, tr(
"Which RGB format?"), tr(
"Format:"), formats, 0,
false, &ok);
8080 QString ext =
format.split(
'.').back();
8081 bool useStamp =
format.split(
'.').front().compare(
"timestamp") == 0;
8083 QMap<int, double> stamps;
8084 QString
path = QFileDialog::getExistingDirectory(
this, tr(
"Select directory where to save images..."), this->
getWorkingDirectory());
8091 data.uncompressData();
8098 unsigned int saved = 0;
8099 bool calibrationSaved =
false;
8100 for(std::map<int, Transform>::iterator
iter=poses.begin();
iter!=poses.end(); ++
iter)
8102 QString
id = QString::number(
iter->first);
8108 data.uncompressData();
8110 if(!calibrationSaved)
8112 if(!
data.imageRaw().empty() && !
data.rightRaw().empty())
8115 dir.mkdir(QString(
"%1/left").
arg(
path));
8116 dir.mkdir(QString(
"%1/right").
arg(
path));
8117 if(
data.stereoCameraModels().size() > 1)
8119 UERROR(
"Only one stereo camera calibration can be saved at this time (%d detected)", (
int)
data.stereoCameraModels().size());
8121 else if(
data.stereoCameraModels().size() == 1 &&
data.stereoCameraModels().front().isValidForProjection())
8123 std::string cameraName =
"calibration";
8126 data.imageRaw().size(),
8127 data.stereoCameraModels()[0].left().K(),
8128 data.stereoCameraModels()[0].left().D(),
8129 data.stereoCameraModels()[0].left().R(),
8130 data.stereoCameraModels()[0].left().P(),
8131 data.rightRaw().size(),
8132 data.stereoCameraModels()[0].right().K(),
8133 data.stereoCameraModels()[0].right().D(),
8134 data.stereoCameraModels()[0].right().R(),
8135 data.stereoCameraModels()[0].right().P(),
8136 data.stereoCameraModels()[0].R(),
8137 data.stereoCameraModels()[0].T(),
8138 data.stereoCameraModels()[0].E(),
8139 data.stereoCameraModels()[0].F(),
8140 data.stereoCameraModels()[0].left().localTransform());
8143 calibrationSaved =
true;
8144 UINFO(
"Saved stereo calibration \"%s\"", (
path.toStdString()+
"/"+cameraName).c_str());
8148 UERROR(
"Failed saving calibration \"%s\"", (
path.toStdString()+
"/"+cameraName).c_str());
8152 else if(!
data.imageRaw().empty())
8154 if(!
data.depthRaw().empty())
8157 dir.mkdir(QString(
"%1/rgb").
arg(
path));
8158 dir.mkdir(QString(
"%1/depth").
arg(
path));
8161 if(
data.cameraModels().size() > 1)
8163 UERROR(
"Only one camera calibration can be saved at this time (%d detected)", (
int)
data.cameraModels().size());
8165 else if(
data.cameraModels().size() == 1 &&
data.cameraModels().front().isValidForProjection())
8167 std::string cameraName =
"calibration";
8169 data.imageRaw().size(),
8170 data.cameraModels().front().K(),
8171 data.cameraModels().front().D(),
8172 data.cameraModels().front().R(),
8173 data.cameraModels().front().P(),
8174 data.cameraModels().front().localTransform());
8177 calibrationSaved =
true;
8178 UINFO(
"Saved calibration \"%s\"", (
path.toStdString()+
"/"+cameraName).c_str());
8182 UERROR(
"Failed saving calibration \"%s\"", (
path.toStdString()+
"/"+cameraName).c_str());
8188 if(!
data.imageRaw().empty() && useStamp)
8193 UWARN(
"Node %d has null timestamp! Using id instead!",
iter->first);
8197 id = QString::number(stamp,
'f');
8203 if(!
data.imageRaw().empty() && !
data.rightRaw().empty())
8205 if(!cv::imwrite(QString(
"%1/left/%2.%3").
arg(
path).
arg(
id).
arg(ext).toStdString(),
data.imageRaw()))
8207 if(!cv::imwrite(QString(
"%1/right/%2.%3").
arg(
path).
arg(
id).
arg(ext).toStdString(),
data.rightRaw()))
8209 info = tr(
"Saved left/%1.%2 and right/%1.%2.").arg(
id).arg(ext);
8211 else if(!
data.imageRaw().empty() && !
data.depthRaw().empty())
8213 if(!cv::imwrite(QString(
"%1/rgb/%2.%3").
arg(
path).
arg(
id).
arg(ext).toStdString(),
data.imageRaw()))
8216 UWARN(
"Failed saving \"%s\"", QString(
"%1/depth/%2.png").
arg(
path).
arg(
id).toStdString().
c_str());
8217 info = tr(
"Saved rgb/%1.%2 and depth/%1.png.").arg(
id).arg(ext);
8219 else if(!
data.imageRaw().empty())
8221 if(!cv::imwrite(QString(
"%1/%2.%3").
arg(
path).
arg(
id).
arg(ext).toStdString(),
data.imageRaw()))
8224 info = tr(
"Saved %1.%2.").arg(
id).arg(ext);
8228 info = tr(
"No images saved for node %1!").arg(
id);
8234 QApplication::processEvents();
8237 if(saved!=poses.size())
8247 if(!calibrationSaved)
8249 QMessageBox::warning(
this,
8250 tr(
"Export images..."),
8251 tr(
"Data in the cache don't seem to have valid calibration. Calibration file will not be saved. Try refreshing the cache (with clouds)."));
8265 std::map<int, Transform> posesIn =
_ui->widget_mapVisibility->getVisiblePoses();
8270 for(std::map<int, Transform>::iterator
iter = posesIn.begin();
iter!=posesIn.end(); ++
iter)
8275 iter->second = gtIter->second;
8279 UWARN(
"Not found ground truth pose for node %d",
iter->first);
8284 std::map<int, Transform> poses;
8285 for(std::map<int, Transform>::iterator
iter=posesIn.begin();
iter!=posesIn.end(); ++
iter)
8292 UWARN(
"Missing image in cache for node %d",
iter->first);
8299 poses.insert(*
iter);
8303 UWARN(
"Missing calibration for node %d",
iter->first);
8308 UWARN(
"Did not find node %d in cache",
iter->first);
8322 QMessageBox::warning(
this, tr(
"Exporting cameras..."), tr(
"No poses exported because of missing images. Try refreshing the cache (with clouds)."));
8328 UINFO(
"reset odometry");
8334 UINFO(
"trigger a new map");
8345 int r = QMessageBox::question(
this, tr(
"Hard drive or RAM?"), tr(
"Save in RAM?"), QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
8347 if(r == QMessageBox::No || r == QMessageBox::Yes)
8349 bool recordInRAM = r == QMessageBox::Yes;
8365 _ui->actionData_recorder->setEnabled(
false);
8369 QMessageBox::warning(
this, tr(
""), tr(
"Cannot initialize the data recorder!"));
8370 UERROR(
"Cannot initialize the data recorder!");
8379 UERROR(
"Only one recorder at the same time.");
8385 _ui->actionData_recorder->setEnabled(
true);
8403 _ui->label_source->setVisible(!monitoring);
8404 _ui->label_stats_source->setVisible(!monitoring);
8405 _ui->actionNew_database->setVisible(!monitoring);
8406 _ui->actionOpen_database->setVisible(!monitoring);
8407 _ui->actionClose_database->setVisible(!monitoring);
8408 _ui->actionEdit_database->setVisible(!monitoring);
8409 _ui->actionStart->setVisible(!monitoring);
8410 _ui->actionStop->setVisible(!monitoring);
8411 _ui->actionDump_the_memory->setVisible(!monitoring);
8412 _ui->actionDump_the_prediction_matrix->setVisible(!monitoring);
8413 _ui->actionGenerate_map->setVisible(!monitoring);
8414 _ui->actionUpdate_cache_from_database->setVisible(monitoring);
8415 _ui->actionData_recorder->setVisible(!monitoring);
8416 _ui->menuSelect_source->menuAction()->setVisible(!monitoring);
8417 _ui->doubleSpinBox_stats_imgRate->setVisible(!monitoring);
8418 _ui->doubleSpinBox_stats_imgRate_label->setVisible(!monitoring);
8420 if(wasMonitoring != monitoring)
8422 _ui->toolBar->setVisible(!monitoring);
8423 _ui->toolBar->toggleViewAction()->setVisible(!monitoring);
8425 QList<QAction*> actions =
_ui->menuTools->actions();
8426 for(
int i=0;
i<actions.size(); ++
i)
8428 if(actions.at(
i)->isSeparator())
8430 actions.at(
i)->setVisible(!monitoring);
8433 actions =
_ui->menuFile->actions();
8434 if(actions.size()==16)
8436 if(actions.at(2)->isSeparator())
8438 actions.at(2)->setVisible(!monitoring);
8442 UWARN(
"Menu File separators have not the same order.");
8444 if(actions.at(12)->isSeparator())
8446 actions.at(12)->setVisible(!monitoring);
8450 UWARN(
"Menu File separators have not the same order.");
8455 UWARN(
"Menu File actions size has changed (%d)", actions.size());
8457 actions =
_ui->menuProcess->actions();
8458 if(actions.size()>=2)
8460 if(actions.at(1)->isSeparator())
8462 actions.at(1)->setVisible(!monitoring);
8466 UWARN(
"Menu File separators have not the same order.");
8471 UWARN(
"Menu File separators have not the same order.");
8479 _ui->actionNew_database->setEnabled(
true);
8480 _ui->actionOpen_database->setEnabled(
true);
8481 _ui->actionClose_database->setEnabled(
false);
8482 _ui->actionEdit_database->setEnabled(
true);
8483 _ui->actionStart->setEnabled(
false);
8484 _ui->actionPause->setEnabled(
false);
8485 _ui->actionPause->setChecked(
false);
8486 _ui->actionPause->setToolTip(tr(
"Pause"));
8487 _ui->actionStop->setEnabled(
false);
8488 _ui->actionPause_on_match->setEnabled(
true);
8489 _ui->actionPause_on_local_loop_detection->setEnabled(
true);
8490 _ui->actionPause_when_a_loop_hypothesis_is_rejected->setEnabled(
true);
8491 _ui->actionDump_the_memory->setEnabled(
false);
8492 _ui->actionDump_the_prediction_matrix->setEnabled(
false);
8493 _ui->actionDelete_memory->setEnabled(
false);
8496 _ui->actionGenerate_map->setEnabled(
false);
8501 #ifdef RTABMAP_OCTOMAP
8504 _ui->actionExport_octomap->setEnabled(
false);
8508 _ui->actionDownload_all_clouds->setEnabled(
false);
8509 _ui->actionDownload_graph->setEnabled(
false);
8510 _ui->menuSelect_source->setEnabled(
true);
8511 _ui->actionLabel_current_location->setEnabled(
false);
8512 _ui->actionSend_goal->setEnabled(
false);
8513 _ui->actionCancel_goal->setEnabled(
false);
8514 _ui->toolBar->findChild<QAction*>(
"toolbar_source")->setEnabled(
true);
8515 _ui->actionTrigger_a_new_map->setEnabled(
false);
8516 _ui->doubleSpinBox_stats_imgRate->setEnabled(
true);
8517 _ui->statusbar->clearMessage();
8524 _ui->actionStart->setEnabled(
false);
8525 _ui->actionPause->setEnabled(
false);
8526 _ui->actionStop->setEnabled(
false);
8531 _ui->actionNew_database->setEnabled(
false);
8532 _ui->actionOpen_database->setEnabled(
false);
8533 _ui->actionClose_database->setEnabled(
false);
8534 _ui->actionEdit_database->setEnabled(
false);
8539 _ui->actionNew_database->setEnabled(
false);
8540 _ui->actionOpen_database->setEnabled(
false);
8541 _ui->actionClose_database->setEnabled(
true);
8542 _ui->actionEdit_database->setEnabled(
false);
8543 _ui->actionStart->setEnabled(
true);
8544 _ui->actionPause->setEnabled(
false);
8545 _ui->actionPause->setChecked(
false);
8546 _ui->actionPause->setToolTip(tr(
"Pause"));
8547 _ui->actionStop->setEnabled(
false);
8548 _ui->actionPause_on_match->setEnabled(
true);
8549 _ui->actionPause_on_local_loop_detection->setEnabled(
true);
8550 _ui->actionPause_when_a_loop_hypothesis_is_rejected->setEnabled(
true);
8551 _ui->actionDump_the_memory->setEnabled(
true);
8552 _ui->actionDump_the_prediction_matrix->setEnabled(
true);
8556 _ui->actionGenerate_map->setEnabled(
true);
8561 #ifdef RTABMAP_OCTOMAP
8564 _ui->actionExport_octomap->setEnabled(
false);
8568 _ui->actionDownload_all_clouds->setEnabled(
true);
8569 _ui->actionDownload_graph->setEnabled(
true);
8570 _ui->menuSelect_source->setEnabled(
true);
8571 _ui->actionLabel_current_location->setEnabled(
true);
8572 _ui->actionSend_goal->setEnabled(
true);
8573 _ui->actionCancel_goal->setEnabled(
true);
8574 _ui->toolBar->findChild<QAction*>(
"toolbar_source")->setEnabled(
true);
8575 _ui->actionTrigger_a_new_map->setEnabled(
true);
8576 _ui->doubleSpinBox_stats_imgRate->setEnabled(
true);
8577 _ui->statusbar->clearMessage();
8583 _ui->actionStart->setEnabled(
false);
8588 _ui->actionNew_database->setEnabled(
false);
8589 _ui->actionOpen_database->setEnabled(
false);
8590 _ui->actionClose_database->setEnabled(
false);
8591 _ui->actionEdit_database->setEnabled(
false);
8592 _ui->actionStart->setEnabled(
false);
8593 _ui->actionPause->setEnabled(
true);
8594 _ui->actionPause->setChecked(
false);
8595 _ui->actionPause->setToolTip(tr(
"Pause"));
8596 _ui->actionStop->setEnabled(
true);
8597 _ui->actionPause_on_match->setEnabled(
true);
8598 _ui->actionPause_on_local_loop_detection->setEnabled(
true);
8599 _ui->actionPause_when_a_loop_hypothesis_is_rejected->setEnabled(
true);
8600 _ui->actionDump_the_memory->setEnabled(
false);
8601 _ui->actionDump_the_prediction_matrix->setEnabled(
false);
8602 _ui->actionDelete_memory->setEnabled(
false);
8603 _ui->actionPost_processing->setEnabled(
false);
8604 _ui->actionExport_images_RGB_jpg_Depth_png->setEnabled(
false);
8605 _ui->actionGenerate_map->setEnabled(
false);
8606 _ui->menuExport_poses->setEnabled(
false);
8607 _ui->actionSave_point_cloud->setEnabled(
false);
8608 _ui->actionView_high_res_point_cloud->setEnabled(
false);
8609 _ui->actionExport_2D_Grid_map_bmp_png->setEnabled(
false);
8610 _ui->actionExport_octomap->setEnabled(
false);
8611 _ui->actionExport_cameras_in_Bundle_format_out->setEnabled(
false);
8612 _ui->actionDepth_Calibration->setEnabled(
false);
8613 _ui->actionDownload_all_clouds->setEnabled(
false);
8614 _ui->actionDownload_graph->setEnabled(
false);
8615 _ui->menuSelect_source->setEnabled(
false);
8616 _ui->actionLabel_current_location->setEnabled(
true);
8617 _ui->actionSend_goal->setEnabled(
true);
8618 _ui->actionCancel_goal->setEnabled(
true);
8619 _ui->toolBar->findChild<QAction*>(
"toolbar_source")->setEnabled(
false);
8620 _ui->actionTrigger_a_new_map->setEnabled(
true);
8621 _ui->doubleSpinBox_stats_imgRate->setEnabled(
true);
8622 _ui->statusbar->showMessage(tr(
"Detecting..."));
8624 _ui->label_elapsedTime->setText(
"00:00:00");
8644 _ui->actionPause->setToolTip(tr(
"Pause"));
8645 _ui->actionPause->setChecked(
false);
8646 _ui->statusbar->showMessage(tr(
"Detecting..."));
8647 _ui->actionDump_the_memory->setEnabled(
false);
8648 _ui->actionDump_the_prediction_matrix->setEnabled(
false);
8649 _ui->actionDelete_memory->setEnabled(
false);
8650 _ui->actionPost_processing->setEnabled(
false);
8651 _ui->actionExport_images_RGB_jpg_Depth_png->setEnabled(
false);
8652 _ui->actionGenerate_map->setEnabled(
false);
8653 _ui->menuExport_poses->setEnabled(
false);
8654 _ui->actionSave_point_cloud->setEnabled(
false);
8655 _ui->actionView_high_res_point_cloud->setEnabled(
false);
8656 _ui->actionExport_2D_Grid_map_bmp_png->setEnabled(
false);
8657 _ui->actionExport_octomap->setEnabled(
false);
8658 _ui->actionExport_cameras_in_Bundle_format_out->setEnabled(
false);
8659 _ui->actionDepth_Calibration->setEnabled(
false);
8660 _ui->actionDownload_all_clouds->setEnabled(
false);
8661 _ui->actionDownload_graph->setEnabled(
false);
8678 _ui->actionPause->setToolTip(tr(
"Continue (shift-click for step-by-step)"));
8679 _ui->actionPause->setChecked(
true);
8680 _ui->statusbar->showMessage(tr(
"Paused..."));
8681 _ui->actionDump_the_memory->setEnabled(
true);
8682 _ui->actionDump_the_prediction_matrix->setEnabled(
true);
8683 _ui->actionDelete_memory->setEnabled(
false);
8686 _ui->actionGenerate_map->setEnabled(
true);
8691 #ifdef RTABMAP_OCTOMAP
8694 _ui->actionExport_octomap->setEnabled(
false);
8698 _ui->actionDownload_all_clouds->setEnabled(
true);
8699 _ui->actionDownload_graph->setEnabled(
true);
8715 _ui->actionPause->setEnabled(
true);
8716 _ui->actionPause->setChecked(
false);
8717 _ui->actionPause->setToolTip(tr(
"Pause"));
8718 _ui->actionPause_on_match->setEnabled(
true);
8719 _ui->actionPause_on_local_loop_detection->setEnabled(
true);
8720 _ui->actionPause_when_a_loop_hypothesis_is_rejected->setEnabled(
true);
8721 _ui->actionReset_Odometry->setEnabled(
true);
8722 _ui->actionPost_processing->setEnabled(
false);
8723 _ui->actionExport_images_RGB_jpg_Depth_png->setEnabled(
false);
8724 _ui->menuExport_poses->setEnabled(
false);
8725 _ui->actionSave_point_cloud->setEnabled(
false);
8726 _ui->actionView_high_res_point_cloud->setEnabled(
false);
8727 _ui->actionExport_2D_Grid_map_bmp_png->setEnabled(
false);
8728 _ui->actionExport_octomap->setEnabled(
false);
8729 _ui->actionExport_cameras_in_Bundle_format_out->setEnabled(
false);
8730 _ui->actionDepth_Calibration->setEnabled(
false);
8731 _ui->actionDelete_memory->setEnabled(
true);
8732 _ui->actionDownload_all_clouds->setEnabled(
true);
8733 _ui->actionDownload_graph->setEnabled(
true);
8734 _ui->actionTrigger_a_new_map->setEnabled(
true);
8735 _ui->actionLabel_current_location->setEnabled(
true);
8736 _ui->actionSend_goal->setEnabled(
true);
8737 _ui->actionCancel_goal->setEnabled(
true);
8738 _ui->statusbar->showMessage(tr(
"Monitoring..."));
8745 _ui->actionPause->setToolTip(tr(
"Continue"));
8746 _ui->actionPause->setChecked(
true);
8747 _ui->actionPause->setEnabled(
true);
8748 _ui->actionPause_on_match->setEnabled(
true);
8749 _ui->actionPause_on_local_loop_detection->setEnabled(
true);
8750 _ui->actionPause_when_a_loop_hypothesis_is_rejected->setEnabled(
true);
8751 _ui->actionReset_Odometry->setEnabled(
true);
8758 #ifdef RTABMAP_OCTOMAP
8761 _ui->actionExport_octomap->setEnabled(
false);
8765 _ui->actionDelete_memory->setEnabled(
true);
8766 _ui->actionDownload_all_clouds->setEnabled(
true);
8767 _ui->actionDownload_graph->setEnabled(
true);
8768 _ui->actionTrigger_a_new_map->setEnabled(
true);
8769 _ui->actionLabel_current_location->setEnabled(
true);
8770 _ui->actionSend_goal->setEnabled(
true);
8771 _ui->actionCancel_goal->setEnabled(
true);
8772 _ui->statusbar->showMessage(tr(
"Monitoring paused..."));