30 #include "ui_mainWindow.h" 74 #include <QtGui/QCloseEvent> 75 #include <QtGui/QPixmap> 76 #include <QtCore/QDir> 77 #include <QtCore/QFile> 78 #include <QtCore/QTextStream> 79 #include <QtCore/QFileInfo> 80 #include <QMessageBox> 81 #include <QFileDialog> 82 #include <QGraphicsEllipseItem> 83 #include <QDockWidget> 84 #include <QtCore/QBuffer> 85 #include <QtCore/QTimer> 86 #include <QtCore/QTime> 87 #include <QActionGroup> 88 #include <QtGui/QDesktopServices> 89 #include <QtCore/QStringList> 90 #include <QtCore/QProcess> 91 #include <QSplashScreen> 92 #include <QInputDialog> 93 #include <QToolButton> 109 #include <pcl/visualization/cloud_viewer.h> 110 #include <pcl/common/transforms.h> 111 #include <pcl/common/common.h> 112 #include <pcl/io/pcd_io.h> 113 #include <pcl/io/ply_io.h> 114 #include <pcl/filters/filter.h> 115 #include <pcl/search/kdtree.h> 117 #ifdef RTABMAP_OCTOMAP 121 #ifdef HAVE_OPENCV_ARUCO 122 #include <opencv2/aruco.hpp> 125 #define LOG_FILE_NAME "LogRtabmap.txt" 126 #define SHARE_SHOW_LOG_FILE "share/rtabmap/showlogs.m" 127 #define SHARE_GET_PRECISION_RECALL_FILE "share/rtabmap/getPrecisionRecall.m" 128 #define SHARE_IMPORT_FILE "share/rtabmap/importfile.m" 144 _preferencesDialog(0),
146 _exportCloudsDialog(0),
147 _exportBundlerDialog(0),
151 _processingStatistics(
false),
152 _processingDownloadedMap(
false),
154 _odometryReceived(
false),
155 _newDatabasePath(
""),
156 _newDatabasePathOutput(
""),
157 _openedDatabasePath(
""),
158 _databaseUpdated(
false),
159 _odomImageShow(
true),
160 _odomImageDepthShow(
false),
161 _savedMaximized(
false),
163 _cachedMemoryUsage(0),
164 _createdCloudsMemoryUsage(0),
167 _odometryCorrection(
Transform::getIdentity()),
168 _processingOdometry(
false),
173 _rawLikelihoodCurve(0),
174 _exportPosesFrame(0),
175 _autoScreenCaptureOdomSync(
false),
176 _autoScreenCaptureRAM(
false),
177 _autoScreenCapturePNG(
false),
179 _progressCanceled(
false)
186 QSplashScreen * splash = 0;
187 if (showSplashScreen)
189 QPixmap pixmap(
":images/RTAB-Map.png");
190 splash =
new QSplashScreen(pixmap);
192 splash->showMessage(tr(
"Loading..."));
193 QApplication::processEvents();
208 _ui =
new Ui_mainWindow();
224 UDEBUG(
"Setup ui... end");
226 QString title(
"RTAB-Map[*]");
227 this->setWindowTitle(title);
228 this->setWindowIconText(tr(
"RTAB-Map"));
229 this->setObjectName(
"MainWindow");
234 _ui->widget_mainWindow->setVisible(
false);
250 bool statusBarShown =
false;
262 #ifdef RTABMAP_OCTOMAP 270 _ui->label_elapsedTime->setText(
"00:00:00");
276 _ui->imageView_source->setBackgroundColor(
_ui->imageView_source->getDefaultBackgroundColor());
277 _ui->imageView_loopClosure->setBackgroundColor(
_ui->imageView_loopClosure->getDefaultBackgroundColor());
278 _ui->imageView_odometry->setBackgroundColor(
_ui->imageView_odometry->getDefaultBackgroundColor());
279 _ui->imageView_odometry->setAlpha(200);
287 _ui->posteriorPlot->showLegend(
false);
288 _ui->posteriorPlot->setFixedYAxis(0,1);
295 _ui->likelihoodPlot->showLegend(
false);
299 _ui->rawLikelihoodPlot->showLegend(
false);
308 connect(
_ui->widget_mapVisibility, SIGNAL(visibilityChanged(
int,
bool)),
this, SLOT(
updateNodeVisibility(
int,
bool)));
311 connect(
_ui->actionExit, SIGNAL(triggered()),
this, SLOT(close()));
312 qRegisterMetaType<MainWindow::State>(
"MainWindow::State");
315 qRegisterMetaType<rtabmap::RtabmapEvent3DMap>(
"rtabmap::RtabmapEvent3DMap");
317 qRegisterMetaType<rtabmap::RtabmapGlobalPathEvent>(
"rtabmap::RtabmapGlobalPathEvent");
323 _ui->menuShow_view->addAction(
_ui->dockWidget_imageView->toggleViewAction());
324 _ui->menuShow_view->addAction(
_ui->dockWidget_posterior->toggleViewAction());
325 _ui->menuShow_view->addAction(
_ui->dockWidget_likelihood->toggleViewAction());
326 _ui->menuShow_view->addAction(
_ui->dockWidget_rawlikelihood->toggleViewAction());
327 _ui->menuShow_view->addAction(
_ui->dockWidget_statsV2->toggleViewAction());
328 _ui->menuShow_view->addAction(
_ui->dockWidget_console->toggleViewAction());
329 _ui->menuShow_view->addAction(
_ui->dockWidget_cloudViewer->toggleViewAction());
330 _ui->menuShow_view->addAction(
_ui->dockWidget_loopClosureViewer->toggleViewAction());
331 _ui->menuShow_view->addAction(
_ui->dockWidget_mapVisibility->toggleViewAction());
332 _ui->menuShow_view->addAction(
_ui->dockWidget_graphViewer->toggleViewAction());
333 _ui->menuShow_view->addAction(
_ui->dockWidget_odometry->toggleViewAction());
334 _ui->menuShow_view->addAction(
_ui->dockWidget_multiSessionLoc->toggleViewAction());
335 _ui->menuShow_view->addAction(
_ui->toolBar->toggleViewAction());
336 _ui->toolBar->setWindowTitle(tr(
"File toolbar"));
337 _ui->menuShow_view->addAction(
_ui->toolBar_2->toggleViewAction());
338 _ui->toolBar_2->setWindowTitle(tr(
"Control toolbar"));
339 QAction * a =
_ui->menuShow_view->addAction(
"Progress dialog");
340 a->setCheckable(
false);
342 QAction * statusBarAction =
_ui->menuShow_view->addAction(
"Status bar");
343 statusBarAction->setCheckable(
true);
344 statusBarAction->setChecked(statusBarShown);
345 connect(statusBarAction, SIGNAL(toggled(
bool)), this->statusBar(), SLOT(setVisible(
bool)));
348 connect(
_ui->actionSave_GUI_config, SIGNAL(triggered()),
this, SLOT(
saveConfigGUI()));
349 connect(
_ui->actionNew_database, SIGNAL(triggered()),
this, SLOT(
newDatabase()));
350 connect(
_ui->actionOpen_database, SIGNAL(triggered()),
this, SLOT(
openDatabase()));
351 connect(
_ui->actionClose_database, SIGNAL(triggered()),
this, SLOT(
closeDatabase()));
352 connect(
_ui->actionEdit_database, SIGNAL(triggered()),
this, SLOT(
editDatabase()));
356 connect(
_ui->actionDump_the_memory, SIGNAL(triggered()),
this, SLOT(
dumpTheMemory()));
357 connect(
_ui->actionDump_the_prediction_matrix, SIGNAL(triggered()),
this, SLOT(
dumpThePrediction()));
358 connect(
_ui->actionSend_goal, SIGNAL(triggered()),
this, SLOT(
sendGoal()));
359 connect(
_ui->actionSend_waypoints, SIGNAL(triggered()),
this, SLOT(
sendWaypoints()));
360 connect(
_ui->actionCancel_goal, SIGNAL(triggered()),
this, SLOT(
cancelGoal()));
361 connect(
_ui->actionLabel_current_location, SIGNAL(triggered()),
this, SLOT(
label()));
362 connect(
_ui->actionRemove_label, SIGNAL(triggered()),
this, SLOT(
removeLabel()));
363 connect(
_ui->actionClear_cache, SIGNAL(triggered()),
this, SLOT(
clearTheCache()));
364 connect(
_ui->actionAbout, SIGNAL(triggered()),
_aboutDialog , SLOT(exec()));
365 connect(
_ui->actionHelp, SIGNAL(triggered()),
this , SLOT(
openHelp()));
366 connect(
_ui->actionPrint_loop_closure_IDs_to_console, SIGNAL(triggered()),
this, SLOT(
printLoopClosureIds()));
368 connect(
_ui->actionRaw_format_txt, SIGNAL(triggered()),
this , SLOT(
exportPosesRaw()));
372 connect(
_ui->actionKITTI_format_txt, SIGNAL(triggered()),
this , SLOT(
exportPosesKITTI()));
375 connect(
_ui->actionDelete_memory, SIGNAL(triggered()),
this , SLOT(
deleteMemory()));
381 connect(
_ui->actionDefault_views, SIGNAL(triggered(
bool)),
this, SLOT(
setDefaultViews()));
383 connect(
_ui->actionScreenshot, SIGNAL(triggered()),
this, SLOT(
takeScreenshot()));
393 connect(
_ui->actionSave_point_cloud, SIGNAL(triggered()),
this, SLOT(
exportClouds()));
394 connect(
_ui->actionExport_2D_Grid_map_bmp_png, SIGNAL(triggered()),
this, SLOT(
exportGridMap()));
395 connect(
_ui->actionExport_images_RGB_jpg_Depth_png, SIGNAL(triggered()),
this , SLOT(
exportImages()));
396 connect(
_ui->actionExport_cameras_in_Bundle_format_out, SIGNAL(triggered()), SLOT(
exportBundlerFormat()));
397 connect(
_ui->actionExport_octomap, SIGNAL(triggered()),
this, SLOT(
exportOctomap()));
398 connect(
_ui->actionView_high_res_point_cloud, SIGNAL(triggered()),
this, SLOT(
viewClouds()));
399 connect(
_ui->actionReset_Odometry, SIGNAL(triggered()),
this, SLOT(
resetOdometry()));
400 connect(
_ui->actionTrigger_a_new_map, SIGNAL(triggered()),
this, SLOT(
triggerNewMap()));
401 connect(
_ui->actionData_recorder, SIGNAL(triggered()),
this, SLOT(
dataRecorder()));
403 connect(
_ui->actionDepth_Calibration, SIGNAL(triggered()),
this, SLOT(
depthCalibration()));
405 _ui->actionPause->setShortcut(Qt::Key_Space);
406 _ui->actionSave_GUI_config->setShortcut(QKeySequence::Save);
409 this->addAction(
_ui->actionSave_GUI_config);
410 _ui->actionReset_Odometry->setEnabled(
false);
411 _ui->actionPost_processing->setEnabled(
false);
412 _ui->actionAnchor_clouds_to_ground_truth->setEnabled(
false);
414 QToolButton* toolButton =
new QToolButton(
this);
415 toolButton->setMenu(
_ui->menuSelect_source);
416 toolButton->setPopupMode(QToolButton::InstantPopup);
417 toolButton->setIcon(QIcon(
":images/kinect_xbox_360.png"));
418 toolButton->setToolTip(
"Select sensor driver");
419 _ui->toolBar->addWidget(toolButton)->setObjectName(
"toolbar_source");
421 #if defined(Q_WS_MAC) || defined(Q_WS_WIN) 424 _ui->menuEdit->removeAction(
_ui->actionOpen_working_directory);
429 connect(
_ui->actionUsbCamera, SIGNAL(triggered()),
this, SLOT(
selectStream()));
430 connect(
_ui->actionOpenNI_PCL, SIGNAL(triggered()),
this, SLOT(
selectOpenni()));
431 connect(
_ui->actionOpenNI_PCL_ASUS, SIGNAL(triggered()),
this, SLOT(
selectOpenni()));
433 connect(
_ui->actionOpenNI_CV, SIGNAL(triggered()),
this, SLOT(
selectOpenniCv()));
435 connect(
_ui->actionOpenNI2, SIGNAL(triggered()),
this, SLOT(
selectOpenni2()));
436 connect(
_ui->actionOpenNI2_kinect, SIGNAL(triggered()),
this, SLOT(
selectOpenni2()));
437 connect(
_ui->actionOpenNI2_orbbec, SIGNAL(triggered()),
this, SLOT(
selectOpenni2()));
438 connect(
_ui->actionOpenNI2_sense, SIGNAL(triggered()),
this, SLOT(
selectOpenni2()));
440 connect(
_ui->actionKinect_for_Windows_SDK_v2, SIGNAL(triggered()),
this, SLOT(
selectK4W2()));
441 connect(
_ui->actionKinect_for_Azure, SIGNAL(triggered()),
this, SLOT(
selectK4A()));
442 connect(
_ui->actionRealSense_R200, SIGNAL(triggered()),
this, SLOT(
selectRealSense()));
443 connect(
_ui->actionRealSense_ZR300, SIGNAL(triggered()),
this, SLOT(
selectRealSense()));
454 connect(
_ui->actionMYNT_EYE_S_SDK, SIGNAL(triggered()),
this, SLOT(
selectMyntEyeS()));
485 QActionGroup * modeGrp =
new QActionGroup(
this);
486 modeGrp->addAction(
_ui->actionSLAM_mode);
487 modeGrp->addAction(
_ui->actionLocalization_mode);
495 qRegisterMetaType<PreferencesDialog::PANEL_FLAGS>(
"PreferencesDialog::PANEL_FLAGS");
497 qRegisterMetaType<rtabmap::ParametersMap>(
"rtabmap::ParametersMap");
515 connect(
_ui->toolBar->toggleViewAction(), SIGNAL(toggled(
bool)),
this, SLOT(
configGUIModified()));
516 connect(
_ui->toolBar, SIGNAL(orientationChanged(Qt::Orientation)),
this, SLOT(
configGUIModified()));
517 connect(statusBarAction, SIGNAL(toggled(
bool)),
this, SLOT(
configGUIModified()));
518 QList<QDockWidget*> dockWidgets = this->findChildren<QDockWidget*>();
519 for(
int i=0; i<dockWidgets.size(); ++i)
521 connect(dockWidgets[i], SIGNAL(dockLocationChanged(Qt::DockWidgetArea)),
this, SLOT(
configGUIModified()));
522 connect(dockWidgets[i]->toggleViewAction(), SIGNAL(toggled(
bool)),
this, SLOT(
configGUIModified()));
524 connect(
_ui->dockWidget_graphViewer->toggleViewAction(), SIGNAL(triggered()),
this, SLOT(
updateGraphView()));
526 _ui->dockWidget_posterior->installEventFilter(
this);
527 _ui->dockWidget_likelihood->installEventFilter(
this);
528 _ui->dockWidget_rawlikelihood->installEventFilter(
this);
529 _ui->dockWidget_statsV2->installEventFilter(
this);
530 _ui->dockWidget_console->installEventFilter(
this);
531 _ui->dockWidget_loopClosureViewer->installEventFilter(
this);
532 _ui->dockWidget_mapVisibility->installEventFilter(
this);
533 _ui->dockWidget_graphViewer->installEventFilter(
this);
534 _ui->dockWidget_odometry->installEventFilter(
this);
535 _ui->dockWidget_cloudViewer->installEventFilter(
this);
536 _ui->dockWidget_imageView->installEventFilter(
this);
537 _ui->dockWidget_multiSessionLoc->installEventFilter(
this);
551 qRegisterMetaType<rtabmap::Statistics>(
"rtabmap::Statistics");
554 qRegisterMetaType<rtabmap::CameraInfo>(
"rtabmap::CameraInfo");
557 qRegisterMetaType<rtabmap::OdometryEvent>(
"rtabmap::OdometryEvent");
566 _ui->statsToolBox->setNewFigureMaxItems(50);
580 if(
_ui->statsToolBox->findChildren<
StatItem*>().size() == 0)
583 for(std::map<std::string, float>::const_iterator iter = statistics.begin(); iter != statistics.end(); ++iter)
586 if(!QString((*iter).first.c_str()).
contains(
"Gt/"))
588 _ui->statsToolBox->updateStat(QString((*iter).first.c_str()).replace(
'_',
' '),
false);
593 _ui->statsToolBox->updateStat(
"Planning/From/",
false);
594 _ui->statsToolBox->updateStat(
"Planning/Time/ms",
false);
595 _ui->statsToolBox->updateStat(
"Planning/Goal/",
false);
596 _ui->statsToolBox->updateStat(
"Planning/Poses/",
false);
597 _ui->statsToolBox->updateStat(
"Planning/Length/m",
false);
599 _ui->statsToolBox->updateStat(
"Camera/Time capturing/ms",
false);
600 _ui->statsToolBox->updateStat(
"Camera/Time decimation/ms",
false);
601 _ui->statsToolBox->updateStat(
"Camera/Time disparity/ms",
false);
602 _ui->statsToolBox->updateStat(
"Camera/Time mirroring/ms",
false);
603 _ui->statsToolBox->updateStat(
"Camera/Time scan from depth/ms",
false);
605 _ui->statsToolBox->updateStat(
"Odometry/ID/",
false);
606 _ui->statsToolBox->updateStat(
"Odometry/Features/",
false);
607 _ui->statsToolBox->updateStat(
"Odometry/Matches/",
false);
608 _ui->statsToolBox->updateStat(
"Odometry/MatchesRatio/",
false);
609 _ui->statsToolBox->updateStat(
"Odometry/Inliers/",
false);
610 _ui->statsToolBox->updateStat(
"Odometry/InliersMeanDistance/m",
false);
611 _ui->statsToolBox->updateStat(
"Odometry/InliersDistribution/",
false);
612 _ui->statsToolBox->updateStat(
"Odometry/InliersRatio/",
false);
613 _ui->statsToolBox->updateStat(
"Odometry/ICPInliersRatio/",
false);
614 _ui->statsToolBox->updateStat(
"Odometry/ICPRotation/rad",
false);
615 _ui->statsToolBox->updateStat(
"Odometry/ICPTranslation/m",
false);
616 _ui->statsToolBox->updateStat(
"Odometry/ICPStructuralComplexity/",
false);
617 _ui->statsToolBox->updateStat(
"Odometry/ICPStructuralDistribution/",
false);
618 _ui->statsToolBox->updateStat(
"Odometry/ICPCorrespondences/",
false);
619 _ui->statsToolBox->updateStat(
"Odometry/ICPRMS/",
false);
620 _ui->statsToolBox->updateStat(
"Odometry/StdDevLin/m",
false);
621 _ui->statsToolBox->updateStat(
"Odometry/StdDevAng/rad",
false);
622 _ui->statsToolBox->updateStat(
"Odometry/VarianceLin/",
false);
623 _ui->statsToolBox->updateStat(
"Odometry/VarianceAng/",
false);
624 _ui->statsToolBox->updateStat(
"Odometry/TimeEstimation/ms",
false);
625 _ui->statsToolBox->updateStat(
"Odometry/TimeFiltering/ms",
false);
626 _ui->statsToolBox->updateStat(
"Odometry/GravityRollError/deg",
false);
627 _ui->statsToolBox->updateStat(
"Odometry/GravityPitchError/deg",
false);
628 _ui->statsToolBox->updateStat(
"Odometry/LocalMapSize/",
false);
629 _ui->statsToolBox->updateStat(
"Odometry/LocalScanMapSize/",
false);
630 _ui->statsToolBox->updateStat(
"Odometry/LocalKeyFrames/",
false);
631 _ui->statsToolBox->updateStat(
"Odometry/localBundleOutliers/",
false);
632 _ui->statsToolBox->updateStat(
"Odometry/localBundleConstraints/",
false);
633 _ui->statsToolBox->updateStat(
"Odometry/localBundleTime/ms",
false);
634 _ui->statsToolBox->updateStat(
"Odometry/KeyFrameAdded/",
false);
635 _ui->statsToolBox->updateStat(
"Odometry/Interval/ms",
false);
636 _ui->statsToolBox->updateStat(
"Odometry/Speed/kph",
false);
637 _ui->statsToolBox->updateStat(
"Odometry/Speed/mph",
false);
638 _ui->statsToolBox->updateStat(
"Odometry/Speed/mps",
false);
639 _ui->statsToolBox->updateStat(
"Odometry/SpeedGuess/kph",
false);
640 _ui->statsToolBox->updateStat(
"Odometry/SpeedGuess/mph",
false);
641 _ui->statsToolBox->updateStat(
"Odometry/SpeedGuess/mps",
false);
642 _ui->statsToolBox->updateStat(
"Odometry/Distance/m",
false);
643 _ui->statsToolBox->updateStat(
"Odometry/T/m",
false);
644 _ui->statsToolBox->updateStat(
"Odometry/Tx/m",
false);
645 _ui->statsToolBox->updateStat(
"Odometry/Ty/m",
false);
646 _ui->statsToolBox->updateStat(
"Odometry/Tz/m",
false);
647 _ui->statsToolBox->updateStat(
"Odometry/Troll/deg",
false);
648 _ui->statsToolBox->updateStat(
"Odometry/Tpitch/deg",
false);
649 _ui->statsToolBox->updateStat(
"Odometry/Tyaw/deg",
false);
650 _ui->statsToolBox->updateStat(
"Odometry/Px/m",
false);
651 _ui->statsToolBox->updateStat(
"Odometry/Py/m",
false);
652 _ui->statsToolBox->updateStat(
"Odometry/Pz/m",
false);
653 _ui->statsToolBox->updateStat(
"Odometry/Proll/deg",
false);
654 _ui->statsToolBox->updateStat(
"Odometry/Ppitch/deg",
false);
655 _ui->statsToolBox->updateStat(
"Odometry/Pyaw/deg",
false);
657 _ui->statsToolBox->updateStat(
"GUI/Refresh odom/ms",
false);
658 _ui->statsToolBox->updateStat(
"GUI/RGB-D cloud/ms",
false);
659 _ui->statsToolBox->updateStat(
"GUI/Graph Update/ms",
false);
660 #ifdef RTABMAP_OCTOMAP 661 _ui->statsToolBox->updateStat(
"GUI/Octomap Update/ms",
false);
662 _ui->statsToolBox->updateStat(
"GUI/Octomap Rendering/ms",
false);
664 _ui->statsToolBox->updateStat(
"GUI/Grid Update/ms",
false);
665 _ui->statsToolBox->updateStat(
"GUI/Grid Rendering/ms",
false);
666 _ui->statsToolBox->updateStat(
"GUI/Refresh stats/ms",
false);
667 _ui->statsToolBox->updateStat(
"GUI/Cache Data Size/MB",
false);
668 _ui->statsToolBox->updateStat(
"GUI/Cache Clouds Size/MB",
false);
669 #ifdef RTABMAP_OCTOMAP 670 _ui->statsToolBox->updateStat(
"GUI/Octomap Size/MB",
false);
697 #ifdef RTABMAP_OCTOMAP 708 qobject_cast<QHBoxLayout *>(
_ui->layout_imageview->layout())->setDirection(QBoxLayout::TopToBottom);
712 qobject_cast<QHBoxLayout *>(
_ui->layout_imageview->layout())->setDirection(QBoxLayout::LeftToRight);
718 return _ui->widget_mapVisibility->getVisiblePoses();
756 bool processStopped =
true;
769 processStopped =
false;
777 if(this->isWindowModified())
779 QMessageBox::Button b=QMessageBox::question(
this,
781 tr(
"There are unsaved changed settings. Save them?"),
782 QMessageBox::Save | QMessageBox::Cancel | QMessageBox::Discard);
783 if(b == QMessageBox::Save)
787 else if(b != QMessageBox::Discard)
799 _ui->statsToolBox->closeFigures();
801 _ui->dockWidget_imageView->close();
802 _ui->dockWidget_likelihood->close();
803 _ui->dockWidget_rawlikelihood->close();
804 _ui->dockWidget_posterior->close();
805 _ui->dockWidget_statsV2->close();
806 _ui->dockWidget_console->close();
807 _ui->dockWidget_cloudViewer->close();
808 _ui->dockWidget_loopClosureViewer->close();
809 _ui->dockWidget_mapVisibility->close();
810 _ui->dockWidget_graphViewer->close();
811 _ui->dockWidget_odometry->close();
812 _ui->dockWidget_multiSessionLoc->close();
816 UERROR(
"Camera must be already deleted here!");
827 UERROR(
"OdomThread must be already deleted here!");
847 else if(anEvent->
getClassName().compare(
"RtabmapEvent") == 0)
851 int highestHypothesisId = int(
uValue(stats.
data(), Statistics::kLoopHighest_hypothesis_id(), 0.0f));
852 int proximityClosureId = int(
uValue(stats.
data(), Statistics::kProximitySpace_last_detection_id(), 0.0f));
853 bool rejectedHyp = bool(
uValue(stats.
data(), Statistics::kLoopRejectedHypothesis(), 0.0f));
854 float highestHypothesisValue =
uValue(stats.
data(), Statistics::kLoopHighest_hypothesis_value(), 0.0f);
856 _ui->actionPause_on_match->isChecked())
859 highestHypothesisId > 0 &&
861 _ui->actionPause_when_a_loop_hypothesis_is_rejected->isChecked() &&
864 (proximityClosureId > 0 &&
865 _ui->actionPause_on_local_loop_detection->isChecked()))
871 QMetaObject::invokeMethod(
this,
"beep");
883 else if(anEvent->
getClassName().compare(
"RtabmapEventInit") == 0)
891 else if(anEvent->
getClassName().compare(
"RtabmapEvent3DMap") == 0)
896 else if(anEvent->
getClassName().compare(
"RtabmapGlobalPathEvent") == 0)
901 else if(anEvent->
getClassName().compare(
"RtabmapLabelErrorEvent") == 0)
906 else if(anEvent->
getClassName().compare(
"RtabmapGoalStatusEvent") == 0)
910 else if(anEvent->
getClassName().compare(
"CameraEvent") == 0)
917 QMetaObject::invokeMethod(
this,
"beep");
941 else if(anEvent->
getClassName().compare(
"OdometryEvent") == 0)
960 else if(anEvent->
getClassName().compare(
"ULogEvent") == 0)
965 QMetaObject::invokeMethod(
_ui->dockWidget_console,
"show");
972 QMetaObject::invokeMethod(
this,
"beep");
1016 if(
_ui->imageView_odometry->toolTip().isEmpty())
1018 _ui->imageView_odometry->setToolTip(
1019 "Background Color Code:\n" 1020 " Dark Red = Odometry Lost\n" 1021 " Dark Yellow = Low Inliers\n" 1022 "Feature Color code:\n" 1023 " Green = Inliers\n" 1024 " Yellow = Not matched features from previous frame(s)\n" 1030 bool lostStateChanged =
false;
1037 _ui->imageView_odometry->setBackgroundColor(Qt::darkRed);
1049 _ui->imageView_odometry->setBackgroundColor(Qt::darkYellow);
1056 _ui->imageView_odometry->setBackgroundColor(
_ui->imageView_odometry->getDefaultBackgroundColor());
1059 if(!pose.
isNull() && (
_ui->dockWidget_cloudViewer->isVisible() ||
_ui->graphicsView_graphView->isVisible()))
1069 (
_ui->dockWidget_odometry->isVisible() && (
_ui->imageView_odometry->isImageShown() ||
_ui->imageView_odometry->isImageDepthShown()))))
1073 bool imagesAlreadyRectified = Parameters::defaultRtabmapImagesAlreadyRectified();
1074 Parameters::parse(allParameters, Parameters::kRtabmapImagesAlreadyRectified(), imagesAlreadyRectified);
1075 if(!imagesAlreadyRectified)
1077 rectifiedData = odom.
data();
1083 cv::Mat rectifiedImages = data->
imageRaw().clone();
1089 for(
unsigned int i=0; i<data->
cameraModels().size(); ++i)
1098 UWARN(
"Initializing rectification maps for camera %d (only done for the first image received)...", i);
1100 UWARN(
"Initializing rectification maps for camera %d (only done for the first image received)... done!", i);
1106 rectifiedImage.copyTo(cv::Mat(rectifiedImages, cv::Rect(subImageWidth*i, 0, subImageWidth, data->
imageRaw().rows)));
1110 UWARN(
"Camera %d of data %d is not valid for rectification (%dx%d).",
1122 cv::Mat rectifiedLeftImages = data->
imageRaw().clone();
1123 cv::Mat rectifiedRightImages = data->
imageRaw().clone();
1139 UWARN(
"Initializing rectification maps for stereo camera %d (only done for the first image received)...", i);
1142 UWARN(
"Initializing rectification maps for stereo camera %d (only done for the first image received)... done!", i);
1151 rectifiedLeftImage.copyTo(cv::Mat(rectifiedLeftImages, cv::Rect(subImageWidth*i, 0, subImageWidth, data->
imageRaw().rows)));
1152 rectifiedRightImage.copyTo(cv::Mat(rectifiedRightImages, cv::Rect(subImageWidth*i, 0, subImageWidth, data->
rightRaw().rows)));
1156 UWARN(
"Stereo camera %d of data %d is not valid for rectification (%dx%d).",
1165 data = &rectifiedData;
1169 if(
_ui->dockWidget_cloudViewer->isVisible())
1171 bool cloudUpdated =
false;
1172 bool scanUpdated =
false;
1173 bool featuresUpdated =
false;
1174 bool filteredGravityUpdated =
false;
1175 bool accelerationUpdated =
false;
1184 pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud;
1185 pcl::IndicesPtr indices(
new std::vector<int>);
1201 pcl::PointCloud<pcl::PointXYZRGB>::Ptr output(
new pcl::PointCloud<pcl::PointXYZRGB>);
1205 Eigen::Vector3f viewpoint(0.0
f,0.0
f,0.0
f);
1208 viewpoint[0] = data->
cameraModels()[0].localTransform().x();
1209 viewpoint[1] = data->
cameraModels()[0].localTransform().y();
1210 viewpoint[2] = data->
cameraModels()[0].localTransform().z();
1223 Eigen::Vector3f(pose.
x(), pose.
y(), pose.
z()) + viewpoint);
1228 pcl::TextureMesh::Ptr textureMesh(
new pcl::TextureMesh);
1229 pcl::toPCLPointCloud2(*cloud, textureMesh->cloud);
1230 textureMesh->tex_polygons.push_back(polygons);
1231 int w = cloud->width;
1232 int h = cloud->height;
1234 textureMesh->tex_coordinates.resize(1);
1235 int nPoints = (int)(textureMesh->cloud.data.size()/textureMesh->cloud.point_step);
1236 textureMesh->tex_coordinates[0].resize(nPoints);
1237 for(
int i=0; i<nPoints; ++i)
1240 textureMesh->tex_coordinates[0][i] = Eigen::Vector2f(
1241 float(i % w) /
float(w),
1242 float(h - i / w) /
float(h));
1245 pcl::TexMaterial mesh_material;
1246 mesh_material.tex_d = 1.0f;
1247 mesh_material.tex_Ns = 75.0f;
1248 mesh_material.tex_illum = 1;
1250 mesh_material.tex_name =
"material_odom";
1251 mesh_material.tex_file =
"";
1252 textureMesh->tex_materials.push_back(mesh_material);
1256 UERROR(
"Adding cloudOdom to viewer failed!");
1261 UERROR(
"Adding cloudOdom to viewer failed!");
1269 UERROR(
"Adding cloudOdom to viewer failed!");
1277 cloudUpdated =
true;
1289 bool scanAdded =
false;
1318 UERROR(
"Adding scanMapOdom to viewer failed!");
1345 bool scanAdded =
false;
1349 pcl::PointCloud<pcl::PointXYZINormal>::Ptr cloud;
1359 pcl::PointCloud<pcl::PointNormal>::Ptr cloud;
1369 pcl::PointCloud<pcl::PointXYZI>::Ptr cloud;
1379 pcl::PointCloud<pcl::PointXYZ>::Ptr cloud;
1390 UERROR(
"Adding scanOdom to viewer failed!");
1408 pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud(
new pcl::PointCloud<pcl::PointXYZRGB>);
1411 for(std::map<int, cv::Point3f>::const_iterator iter=odom.
info().
localMap.begin(); iter!=odom.
info().
localMap.end(); ++iter)
1416 (*cloud)[i].x = iter->second.x;
1417 (*cloud)[i].y = iter->second.y;
1418 (*cloud)[i].z = iter->second.z;
1422 (*cloud)[i].r = inlier?0:255;
1423 (*cloud)[i].g = 255;
1437 featuresUpdated =
true;
1443 for(QMap<std::string, Transform>::iterator iter = addedFrustums.begin(); iter!=addedFrustums.end(); ++iter)
1445 std::list<std::string> splitted =
uSplitNumChar(iter.key());
1446 if(splitted.size() == 2)
1448 int id = std::atoi(splitted.back().c_str());
1450 if(splitted.front().compare(
"f_odom_") == 0 &&
1460 std::string frustumId =
uFormat(
"f_odom_%d", iter->first*10);
1463 for(
size_t i=0; i<10; ++i)
1465 std::string subFrustumId =
uFormat(
"f_odom_%d", iter->first*10+i);
1472 for(
size_t i=0; i<models.size(); ++i)
1474 Transform t = models[i].localTransform();
1477 QColor color = Qt::yellow;
1478 std::string subFrustumId =
uFormat(
"f_odom_%d", iter->first*10+i);
1494 _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);
1495 filteredGravityUpdated =
true;
1502 Eigen::Vector3f gravity(
1508 _cloudViewer->
addOrUpdateLine(
"odom_imu_acc",
_odometryCorrection*pose,
_odometryCorrection*pose*
Transform(gravity[0], gravity[1], gravity[2], 0, 0, 0), Qt::red,
true,
true);
1509 accelerationUpdated =
true;
1578 #if PCL_VERSION_COMPARE(>=, 1, 7, 2) 1593 if(
_ui->graphicsView_graphView->isVisible())
1598 _ui->graphicsView_graphView->update();
1599 UDEBUG(
"Time Update graphview: %fs", time.
ticks());
1603 if(
_ui->dockWidget_odometry->isVisible() &&
1606 if(
_ui->imageView_odometry->isFeaturesShown())
1612 std::multimap<int, cv::KeyPoint> kpInliers;
1617 _ui->imageView_odometry->setFeatures(
1624 _ui->imageView_odometry->setFeatures(
1637 std::vector<cv::KeyPoint> kpts;
1639 _ui->imageView_odometry->setFeatures(
1647 bool monoInitialization =
false;
1650 monoInitialization =
true;
1653 _ui->imageView_odometry->clearLines();
1654 if(lost && !monoInitialization)
1656 if(lostStateChanged)
1662 _ui->imageView_odometry->setImageDepth(data->
imageRaw());
1663 _ui->imageView_odometry->setImageShown(
true);
1664 _ui->imageView_odometry->setImageDepthShown(
true);
1668 if(lostStateChanged)
1703 if(
_ui->imageView_odometry->isFeaturesShown() ||
_ui->imageView_odometry->isLinesShown())
1710 if(
_ui->imageView_odometry->isFeaturesShown() && inliers.find(i) != inliers.end())
1712 _ui->imageView_odometry->setFeatureColor(i, Qt::green);
1714 if(
_ui->imageView_odometry->isLinesShown())
1716 _ui->imageView_odometry->addLine(
1721 inliers.find(i) != inliers.end()?Qt::blue:Qt::yellow);
1729 _ui->imageView_odometry->setSceneRect(QRectF(0,0,(
float)data->
imageRaw().cols, (float)data->
imageRaw().rows));
1732 _ui->imageView_odometry->update();
1734 UDEBUG(
"Time update imageview: %fs", time.
ticks());
1885 UDEBUG(
"Time updating Stats toolbox: %fs", time.
ticks());
1896 QTime time, totalTime;
1906 int refMapId = -1, loopMapId = -1;
1911 int highestHypothesisId =
static_cast<float>(
uValue(stat.
data(), Statistics::kLoopHighest_hypothesis_id(), 0.0f));
1918 _ui->label_refId->setText(QString(
"New ID = %1 [%2]").arg(stat.
refImageId()).arg(refMapId));
1922 float totalTime =
static_cast<float>(
uValue(stat.
data(), Statistics::kTimingTotal(), 0.0f));
1929 bool highestHypothesisIsSaved = (bool)
uValue(stat.
data(), Statistics::kLoopHypothesis_reactivated(), 0.0f);
1931 bool smallMovement = (bool)
uValue(stat.
data(), Statistics::kMemorySmall_movement(), 0.0f);
1933 bool fastMovement = (bool)
uValue(stat.
data(), Statistics::kMemoryFast_movement(), 0.0f);
1935 int rehearsalMerged = (int)
uValue(stat.
data(), Statistics::kMemoryRehearsal_merged(), 0.0f);
1943 else if(rehearsalMerged>0 &&
1950 if(signature.
id()!=0)
1955 _ui->imageView_source->isVisible() ||
1964 cv::Mat tmpRgb, tmpDepth, tmpG, tmpO, tmpE;
1967 uncompressImages?&tmpRgb:0,
1969 uncompressScan?&tmpScan:0,
1970 0, &tmpG, &tmpO, &tmpE);
1976 if(smallMovement || fastMovement)
1984 unsigned int count = 0;
1987 for(std::multimap<int, int>::const_iterator jter=signature.
getWords().upper_bound(-1); jter!=signature.
getWords().end(); ++jter)
2001 for(std::map<int, Signature>::const_iterator iter = stat.
getSignaturesData().begin();
2005 if(signature.
id() != iter->first &&
2007 (
_cachedSignatures.value(iter->first).sensorData().imageCompressed().empty() && !iter->second.sensorData().imageCompressed().empty())))
2011 unsigned int count = 0;
2012 if(!iter->second.getWords3().empty())
2014 for(std::multimap<int, int>::const_iterator jter=iter->second.getWords().upper_bound(-1); jter!=iter->second.getWords().end(); ++jter)
2023 UINFO(
"Added node data %d [map=%d] to cache", iter->first, iter->second.mapId());
2025 _currentMapIds.insert(std::make_pair(iter->first, iter->second.mapId()));
2026 if(!iter->second.getGroundTruthPose().isNull())
2028 _currentGTPosesMap.insert(std::make_pair(iter->first, iter->second.getGroundTruthPose()));
2036 _ui->imageView_source->clear();
2037 _ui->imageView_loopClosure->clear();
2042 _ui->imageView_source->setSceneRect(QRect(0,0,640,480));
2045 _ui->imageView_source->setBackgroundColor(
_ui->imageView_source->getDefaultBackgroundColor());
2046 _ui->imageView_loopClosure->setBackgroundColor(
_ui->imageView_loopClosure->getDefaultBackgroundColor());
2048 _ui->label_matchId->clear();
2050 bool rehearsedSimilarity = (float)
uValue(stat.
data(), Statistics::kMemoryRehearsal_id(), 0.0f) != 0.0
f;
2051 int proximityTimeDetections = (int)
uValue(stat.
data(), Statistics::kProximityTime_detections(), 0.0f);
2052 bool scanMatchingSuccess = (bool)
uValue(stat.
data(), Statistics::kNeighborLinkRefiningAccepted(), 0.0f);
2053 _ui->label_stats_imageNumber->setText(QString(
"%1 [%2]").arg(stat.
refImageId()).arg(refMapId));
2055 if(rehearsalMerged > 0)
2057 _ui->imageView_source->setBackgroundColor(Qt::blue);
2059 else if(proximityTimeDetections > 0)
2061 _ui->imageView_source->setBackgroundColor(Qt::darkYellow);
2063 else if(scanMatchingSuccess)
2065 _ui->imageView_source->setBackgroundColor(Qt::darkCyan);
2067 else if(rehearsedSimilarity)
2069 _ui->imageView_source->setBackgroundColor(Qt::darkBlue);
2071 else if(smallMovement)
2073 _ui->imageView_source->setBackgroundColor(Qt::gray);
2075 else if(fastMovement)
2077 _ui->imageView_source->setBackgroundColor(Qt::magenta);
2080 if(
_ui->label_refId->toolTip().isEmpty())
2082 _ui->label_refId->setToolTip(
2083 "Background Color Code:\n" 2084 " Blue = Weight Update Merged\n" 2085 " Dark Blue = Weight Update\n" 2086 " Dark Yellow = Proximity Detection in Time\n" 2087 " Dark Cyan = Neighbor Link Refined\n" 2088 " Gray = Small Movement\n" 2089 " Magenta = Fast Movement\n" 2090 "Feature Color code:\n" 2092 " Yellow = New but Not Unique\n" 2093 " Red = In Vocabulary\n" 2094 " Blue = In Vocabulary and in Previous Signature\n" 2095 " Pink = In Vocabulary and in Loop Closure Signature\n" 2096 " Gray = Not Quantized to Vocabulary");
2099 if(
_ui->label_matchId->toolTip().isEmpty())
2101 _ui->label_matchId->setToolTip(
2102 "Background Color Code:\n" 2103 " Green = Accepted Loop Closure Detection\n" 2104 " Red = Rejected Loop Closure Detection\n" 2105 " Yellow = Proximity Detection in Space\n" 2106 "Feature Color code:\n" 2107 " Red = In Vocabulary\n" 2108 " Pink = In Vocabulary and in Loop Closure Signature\n" 2109 " Gray = Not Quantized to Vocabulary");
2112 int rejectedHyp = bool(
uValue(stat.
data(), Statistics::kLoopRejectedHypothesis(), 0.0f));
2113 float highestHypothesisValue =
uValue(stat.
data(), Statistics::kLoopHighest_hypothesis_value(), 0.0f);
2114 int landmarkId =
static_cast<int>(
uValue(stat.
data(), Statistics::kLoopLandmark_detected(), 0.0f));
2115 int landmarkNodeRef =
static_cast<int>(
uValue(stat.
data(), Statistics::kLoopLandmark_detected_node_ref(), 0.0f));
2118 int shownLoopId = 0;
2124 _ui->imageView_loopClosure->setBackgroundColor(Qt::green);
2125 _ui->label_stats_loopClosuresDetected->setText(QString::number(
_ui->label_stats_loopClosuresDetected->text().toInt() + 1));
2126 if(highestHypothesisIsSaved)
2128 _ui->label_stats_loopClosuresReactivatedDetected->setText(QString::number(
_ui->label_stats_loopClosuresReactivatedDetected->text().toInt() + 1));
2130 _ui->label_matchId->setText(QString(
"Match ID = %1 [%2]").arg(stat.
loopClosureId()).arg(loopMapId));
2135 _ui->imageView_loopClosure->setBackgroundColor(Qt::yellow);
2136 _ui->label_matchId->setText(QString(
"Local match = %1 [%2]").arg(stat.
proximityDetectionId()).arg(loopMapId));
2139 else if(landmarkId!=0)
2141 highestHypothesisId = landmarkNodeRef;
2147 _ui->imageView_loopClosure->setBackgroundColor(Qt::red);
2148 _ui->label_stats_loopClosuresRejected->setText(QString::number(
_ui->label_stats_loopClosuresRejected->text().toInt() + 1));
2149 _ui->label_matchId->setText(QString(
"Landmark rejected = %1 with %2").arg(landmarkId).arg(landmarkNodeRef));
2154 _ui->imageView_loopClosure->setBackgroundColor(QColor(
"orange"));
2155 _ui->label_matchId->setText(QString(
"Landmark match = %1 with %2").arg(landmarkId).arg(landmarkNodeRef));
2156 matchId = landmarkNodeRef;
2164 _ui->imageView_loopClosure->setBackgroundColor(Qt::red);
2165 _ui->label_stats_loopClosuresRejected->setText(QString::number(
_ui->label_stats_loopClosuresRejected->text().toInt() + 1));
2166 _ui->label_matchId->setText(QString(
"Loop hypothesis %1 rejected!").arg(highestHypothesisId));
2174 _ui->label_matchId->setText(QString(
"Highest hypothesis (%1)").arg(highestHypothesisId));
2180 shownLoopId = matchId>0?matchId:highestHypothesisId;
2185 loopSignature = iter.value();
2187 _ui->imageView_source->isVisible() ||
2192 if(uncompressImages || uncompressScan)
2194 cv::Mat tmpRGB, tmpDepth;
2197 uncompressImages?&tmpRGB:0,
2198 uncompressImages?&tmpDepth:0,
2199 uncompressScan?&tmpScan:0);
2210 UDEBUG(
"time= %d ms (update detection ui)", time.restart());
2224 if(refImage.channels() == 1)
2227 cvtColor(refImage, imgColor, cv::COLOR_GRAY2BGR);
2228 refImage = imgColor;
2232 refImage = refImage.clone();
2238 if(loopImage.channels() == 1)
2241 cv::cvtColor(loopImage, imgColor, cv::COLOR_GRAY2BGR);
2242 loopImage = imgColor;
2246 loopImage = loopImage.clone();
2254 qimageThread.
start();
2255 qimageLoopThread.
start();
2256 qimageThread.
join();
2257 qimageLoopThread.
join();
2259 QImage lcImg = qimageLoopThread.
getQImage();
2260 UDEBUG(
"time= %d ms (convert image to qt)", time.restart());
2264 _ui->imageView_source->setImage(img);
2289 if(sceneRect.isValid())
2291 _ui->imageView_source->setSceneRect(sceneRect);
2296 _ui->imageView_loopClosure->setImage(lcImg);
2302 if(
_ui->imageView_loopClosure->sceneRect().isNull())
2304 _ui->imageView_loopClosure->setSceneRect(
_ui->imageView_source->sceneRect());
2307 else if(
_ui->imageView_loopClosure->sceneRect().isNull() &&
2308 !
_ui->imageView_source->sceneRect().isNull())
2310 _ui->imageView_loopClosure->setSceneRect(
_ui->imageView_source->sceneRect());
2313 UDEBUG(
"time= %d ms (update detection imageviews)", time.restart());
2316 std::multimap<int, cv::KeyPoint> wordsA;
2317 std::multimap<int, cv::KeyPoint> wordsB;
2318 for(std::map<int, int>::const_iterator iter=signature.
getWords().begin(); iter!=signature.
getWords().end(); ++iter)
2320 wordsA.insert(wordsA.end(), std::make_pair(iter->first, signature.
getWordsKpts()[iter->second]));
2322 for(std::map<int, int>::const_iterator iter=loopSignature.
getWords().begin(); iter!=loopSignature.
getWords().end(); ++iter)
2324 wordsB.insert(wordsB.end(), std::make_pair(iter->first, loopSignature.
getWordsKpts()[iter->second]));
2328 UDEBUG(
"time= %d ms (draw keypoints)", time.restart());
2337 signature.
setPose(loopClosureTransform);
2339 if(
_ui->dockWidget_loopClosureViewer->isVisible())
2343 UINFO(
"Updating loop closure cloud view time=%fs", loopTimer.
elapsed());
2350 UDEBUG(
"time= %d ms (update loop closure viewer)", time.restart());
2355 if(!stat.
posterior().empty() &&
_ui->dockWidget_posterior->isVisible())
2364 if(!stat.
likelihood().empty() &&
_ui->dockWidget_likelihood->isVisible())
2368 if(!stat.
rawLikelihood().empty() &&
_ui->dockWidget_rawlikelihood->isVisible())
2372 UDEBUG(
"time= %d ms (update likelihood and posterior)", time.restart());
2377 const std::map<std::string, float> & statistics = stat.
data();
2378 std::string odomStr =
"Odometry/";
2379 for(std::map<std::string, float>::const_iterator iter = statistics.begin(); iter != statistics.end(); ++iter)
2382 if((*iter).first.size()<odomStr.size() || (*iter).first.substr(0, odomStr.size()).compare(odomStr)!=0)
2389 UDEBUG(
"time= %d ms (update stats toolbox)", time.restart());
2396 if(stat.
poses().size())
2410 _ui->graphicsView_graphView->getWorldMapRotation()==0.0f &&
2416 _ui->graphicsView_graphView->setWorldMapRotation(gpsRotationOffset);
2419 _ui->graphicsView_graphView->getWorldMapRotation() != 0.0f)
2421 _ui->graphicsView_graphView->setWorldMapRotation(0.0
f);
2425 std::map<int, Transform> poses = stat.
poses();
2427 UDEBUG(
"time= %d ms (update gt-gps stuff)", time.restart());
2429 UDEBUG(
"%d %d %d", poses.size(), poses.size()?poses.rbegin()->first:0, stat.
refImageId());
2469 if(
_ui->graphicsView_graphView->isVisible())
2471 _ui->graphicsView_graphView->updateReferentialPosition(poses.rbegin()->second);
2477 if(poses.find(stat.
refImageId())!=poses.end())
2479 poses.insert(std::make_pair(0, poses.at(stat.
refImageId())));
2482 if(groundTruth.find(stat.
refImageId())!=groundTruth.end())
2484 groundTruth.insert(std::make_pair(0, groundTruth.at(stat.
refImageId())));
2489 std::map<std::string, float> updateCloudSats;
2503 UDEBUG(
"time= %d ms (update map cloud)", time.restart());
2507 for(std::map<std::string, float>::iterator iter=updateCloudSats.begin(); iter!=updateCloudSats.end(); ++iter)
2513 #if PCL_VERSION_COMPARE(>=, 1, 7, 2) 2536 if(
_ui->graphicsView_graphView->isVisible())
2542 _ui->graphicsView_graphView->updatePosterior(stat.
posterior());
2559 std::map<int, float> colors;
2560 colors.insert(std::make_pair(stat.
odomCachePoses().rbegin()->first, 240));
2565 uInsert(colors, std::pair<int,float>(iter->second.from()>iter->second.to()?iter->second.from():iter->second.to(), 120));
2570 if(stat.
poses().find(iter->first) == stat.
poses().end())
2572 colors.insert(std::make_pair(iter->first, 240));
2575 _ui->graphicsView_graphView->updatePosterior(colors, 240);
2578 _ui->graphicsView_graphView->updateLocalPath(stat.
localPath());
2582 _ui->graphicsView_graphView->setGlobalPath(std::vector<std::pair<int, Transform> >());
2589 UDEBUG(
"time= %d ms (update graph view)", time.restart());
2616 std::vector<int> missingIds;
2617 bool ignoreNewData = smallMovement || fastMovement || signature.
getWeight()<0;
2618 for(std::map<int, Transform>::const_iterator iter=stat.
poses().begin(); iter!=stat.
poses().end(); ++iter)
2620 if(!ignoreNewData || stat.
refImageId() != iter->first)
2624 (ster.value().getWeight() >=0 &&
2625 ster.value().sensorData().imageCompressed().empty() &&
2626 ster.value().sensorData().depthOrRightCompressed().empty() &&
2627 ster.value().sensorData().laserScanCompressed().empty()))
2629 missingIds.push_back(iter->first);
2633 if(!missingIds.empty())
2640 UDEBUG(
"time= %d ms (update cache)", time.restart());
2644 _ui->label_stats_loopClosuresDetected->setText(QString::number(
_ui->label_stats_loopClosuresDetected->text().toInt() + 1));
2645 _ui->label_matchId->setText(QString(
"Match ID = %1 [%2]").arg(stat.
loopClosureId()).arg(loopMapId));
2649 _ui->label_matchId->clear();
2651 float elapsedTime =
static_cast<float>(totalTime.elapsed());
2652 UINFO(
"Updating GUI time = %fs", elapsedTime/1000.0
f);
2672 #ifdef RTABMAP_OCTOMAP 2689 const std::map<int, Transform> & posesIn,
2690 const std::multimap<int, Link> & constraints,
2691 const std::map<int, int> & mapIdsIn,
2692 const std::map<int, std::string> & labels,
2693 const std::map<int, Transform> & groundTruths,
2694 const std::map<int, Transform> & odomCachePoses,
2695 const std::multimap<int, Link> & odomCacheConstraints,
2696 bool verboseProgress,
2697 std::map<std::string, float> * stats)
2700 std::map<int, Transform> nodePoses(posesIn.lower_bound(0), posesIn.end());
2701 UDEBUG(
"nodes=%d landmarks=%d constraints=%d mapIdsIn=%d labelsIn=%d",
2702 (
int)nodePoses.size(), (int)(posesIn.size() - nodePoses.size()), (
int)constraints.size(), (int)mapIdsIn.size(), (int)labels.size());
2721 std::map<int, Transform> poses;
2722 std::map<int, int> mapIds;
2727 bool hasZero = nodePoses.find(0) != nodePoses.end();
2730 std::map<int, Transform> posesInTmp = nodePoses;
2731 posesInTmp.erase(0);
2738 for(std::map<int, Transform>::iterator iter= poses.begin(); iter!=poses.end(); ++iter)
2740 std::map<int, int>::const_iterator jter = mapIdsIn.find(iter->first);
2741 if(jter!=mapIdsIn.end())
2743 mapIds.insert(*jter);
2749 poses.insert(*nodePoses.find(0));
2754 _progressDialog->
appendText(tr(
"Map update: %1 nodes shown of %2 (cloud filtering is on)").arg(poses.size()).arg(nodePoses.size()));
2755 QApplication::processEvents();
2764 std::map<int, bool> posesMask;
2765 for(std::map<int, Transform>::const_iterator iter = nodePoses.begin(); iter!=nodePoses.end(); ++iter)
2767 posesMask.insert(posesMask.end(), std::make_pair(iter->first, poses.find(iter->first) != poses.end()));
2769 _ui->widget_mapVisibility->setMap(nodePoses, posesMask);
2771 if(groundTruths.size() &&
_ui->actionAnchor_clouds_to_ground_truth->isChecked())
2773 for(std::map<int, Transform>::iterator iter = poses.begin(); iter!=poses.end(); ++iter)
2775 std::map<int, Transform>::const_iterator gtIter = groundTruths.find(iter->first);
2776 if(gtIter!=groundTruths.end())
2778 iter->second = gtIter->second;
2782 UWARN(
"Not found ground truth pose for node %d", iter->first);
2788 _ui->actionAnchor_clouds_to_ground_truth->setChecked(
false);
2793 if((maxNodes > 0 || altitudeDelta>0.0) && poses.size()>1)
2795 Transform currentPose = poses.rbegin()->second;
2796 if(poses.find(0) != poses.end())
2798 currentPose = poses.at(0);
2801 std::map<int, Transform> nearestPoses;
2805 for(std::map<int, float>::iterator iter=nodes.begin(); iter!=nodes.end(); ++iter)
2807 if(altitudeDelta<=0.0 ||
2808 fabs(poses.at(iter->first).z()-currentPose.
z())<altitudeDelta)
2810 nearestPoses.insert(*poses.find(iter->first));
2816 for(std::map<int, Transform>::const_iterator iter=poses.begin(); iter!=poses.end(); ++iter)
2818 if(fabs(iter->second.z()-currentPose.
z())<altitudeDelta)
2820 nearestPoses.insert(*iter);
2826 if(poses.find(0) != poses.end())
2828 nearestPoses.insert(*poses.find(0));
2834 UDEBUG(
"Update map with %d locations", poses.size());
2838 for(std::map<int, Transform>::const_iterator iter = poses.begin(); iter!=poses.end(); ++iter)
2840 if(!iter->second.isNull())
2842 std::string cloudName =
uFormat(
"cloud%d", iter->first);
2844 if(iter->first == 0)
2846 viewerClouds.remove(cloudName);
2855 if(viewerClouds.contains(cloudName))
2860 if(tCloud.
isNull() || iter->second != tCloud)
2864 UERROR(
"Updating pose cloud %d failed!", iter->first);
2876 std::pair<pcl::PointCloud<pcl::PointXYZRGB>::Ptr, pcl::IndicesPtr> createdCloud = this->
createAndAddCloudToMap(iter->first, iter->second,
uValue(mapIds, iter->first, -1));
2883 else if(viewerClouds.contains(cloudName))
2889 std::string scanName =
uFormat(
"scan%d", iter->first);
2890 if(iter->first == 0)
2892 viewerClouds.remove(scanName);
2897 if(viewerClouds.contains(scanName))
2902 if(tScan.
isNull() || iter->second != tScan)
2906 UERROR(
"Updating pose scan %d failed!", iter->first);
2917 if(!jter->sensorData().laserScanCompressed().isEmpty() || !jter->sensorData().laserScanRaw().isEmpty())
2923 else if(viewerClouds.contains(scanName))
2929 bool updateGridMap =
2930 ((
_ui->graphicsView_graphView->isVisible() &&
_ui->graphicsView_graphView->isGridMapVisible()) ||
2933 bool updateOctomap =
false;
2934 #ifdef RTABMAP_OCTOMAP 2940 if(updateGridMap || updateOctomap)
2949 jter->sensorData().uncompressDataConst(0, 0, 0, 0, &ground, &obstacles, &empty);
2953 #ifdef RTABMAP_OCTOMAP 2956 if((ground.empty() || ground.channels() > 2) &&
2957 (obstacles.empty() || obstacles.channels() > 2))
2959 cv::Point3f viewpoint = jter->sensorData().gridViewPoint();
2962 else if(!ground.empty() || !obstacles.empty())
2964 UWARN(
"Node %d: Cannot update octomap with 2D occupancy grids.", iter->first);
2972 std::string featuresName =
uFormat(
"features%d", iter->first);
2973 if(iter->first == 0)
2975 viewerClouds.remove(featuresName);
2980 if(viewerClouds.contains(featuresName))
2985 if(tFeatures.
isNull() || iter->second != tFeatures)
2989 UERROR(
"Updating pose features %d failed!", iter->first);
2998 if(!jter->getWords3().empty())
3004 else if(viewerClouds.contains(featuresName))
3010 std::string gravityName =
uFormat(
"gravity%d", iter->first);
3011 if(iter->first == 0)
3013 viewerLines.erase(gravityName);
3019 if(linkIter != constraints.end())
3021 Transform gravityT = linkIter->second.transform();
3023 gravity = (gravityT.
rotation()*(iter->second).
rotation().inverse()).toEigen3f()*gravity;
3024 _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);
3027 else if(viewerLines.find(gravityName)!=viewerLines.end())
3036 if(poses.size() < 200 || i % 100 == 0)
3038 QApplication::processEvents();
3051 for(QMap<std::string, Transform>::iterator iter = viewerClouds.begin(); iter!=viewerClouds.end(); ++iter)
3053 std::list<std::string> splitted =
uSplitNumChar(iter.key());
3055 if(splitted.size() == 2)
3057 id = std::atoi(splitted.back().c_str());
3058 if(poses.find(
id) == poses.end())
3062 UDEBUG(
"Hide %s", iter.key().c_str());
3069 for(std::set<std::string>::iterator iter = viewerLines.begin(); iter!=viewerLines.end(); ++iter)
3073 if(splitted.size() == 2)
3075 id = std::atoi(splitted.back().c_str());
3076 if(poses.find(
id) == poses.end())
3078 UDEBUG(
"Remove %s", iter->c_str());
3087 stats->insert(std::make_pair(
"GUI/RGB-D cloud/ms", (
float)timer.
restart()*1000.0f));
3096 for(QMap<std::string, Transform>::iterator iter = addedFrustums.begin(); iter!=addedFrustums.end(); ++iter)
3098 std::list<std::string> splitted =
uSplitNumChar(iter.key());
3099 if(splitted.size() == 2)
3101 if((splitted.front().compare(
"f_") == 0 || splitted.front().compare(
"f_gt_") == 0))
3115 std::map<int, Transform> posesWithOdomCache;
3117 if(
_ui->graphicsView_graphView->isVisible() ||
3120 posesWithOdomCache = posesIn;
3121 for(std::map<int, Transform>::const_iterator iter=odomCachePoses.begin(); iter!=odomCachePoses.end(); ++iter)
3131 std::map<int, pcl::PointCloud<pcl::PointXYZ>::Ptr > graphs;
3132 for(std::map<int, Transform>::iterator iter=posesWithOdomCache.lower_bound(1); iter!=posesWithOdomCache.end(); ++iter)
3139 std::map<int, pcl::PointCloud<pcl::PointXYZ>::Ptr >::iterator kter = graphs.find(mapId);
3140 if(kter == graphs.end())
3142 kter = graphs.insert(std::make_pair(mapId, pcl::PointCloud<pcl::PointXYZ>::Ptr(
new pcl::PointCloud<pcl::PointXYZ>))).first;
3144 pcl::PointXYZ pt(iter->second.x(), iter->second.y(), iter->second.z());
3145 kter->second->push_back(pt);
3151 std::string frustumId =
uFormat(
"f_%d", iter->first);
3166 QColor color = (Qt::GlobalColor)((mapId+3) % 12 + 7 );
3171 std::string gtFrustumId =
uFormat(
"f_gt_%d", iter->first);
3189 std::map<int, pcl::PointCloud<pcl::PointXYZ>::Ptr >::iterator kter = graphs.find(mapId);
3190 if(kter == graphs.end())
3192 kter = graphs.insert(std::make_pair(mapId, pcl::PointCloud<pcl::PointXYZ>::Ptr(
new pcl::PointCloud<pcl::PointXYZ>))).first;
3195 pcl::PointXYZ pt(t.
x(), t.
y(), t.
z());
3196 kter->second->push_back(pt);
3201 for(std::map<
int, pcl::PointCloud<pcl::PointXYZ>::Ptr >::iterator iter=graphs.begin(); iter!=graphs.end(); ++iter)
3203 QColor color = Qt::gray;
3204 if(iter->first >= 0)
3206 color = (Qt::GlobalColor)((iter->first+3) % 12 + 7 );
3214 UDEBUG(
"remove not used frustums");
3215 for(QMap<std::string, Transform>::iterator iter = addedFrustums.begin(); iter!=addedFrustums.end(); ++iter)
3217 std::list<std::string> splitted =
uSplitNumChar(iter.key());
3218 if(splitted.size() == 2)
3220 int id = std::atoi(splitted.back().c_str());
3221 if((splitted.front().compare(
"f_") == 0 || splitted.front().compare(
"f_gt_") == 0) &&
3222 posesWithOdomCache.find(
id) == posesWithOdomCache.end())
3233 UDEBUG(
"labels.size()=%d", (
int)labels.size());
3239 for(std::map<int, std::string>::const_iterator iter=labels.begin(); iter!=labels.end(); ++iter)
3241 if(nodePoses.find(iter->first)!=nodePoses.end())
3243 int mapId =
uValue(mapIdsIn, iter->first, -1);
3244 QColor color = Qt::gray;
3247 color = (Qt::GlobalColor)((mapId+3) % 12 + 7 );
3262 stats->insert(std::make_pair(
"GUI/Graph Update/ms", (
float)timer.
restart()*1000.0f));
3265 #ifdef RTABMAP_OCTOMAP 3273 UINFO(
"Octomap update time = %fs", time.
ticks());
3277 stats->insert(std::make_pair(
"GUI/Octomap Update/ms", (
float)timer.
restart()*1000.0f));
3289 pcl::IndicesPtr obstacles(
new std::vector<int>);
3291 if(obstacles->size())
3297 UINFO(
"Octomap show 3d map time = %fs", time.
ticks());
3302 stats->insert(std::make_pair(
"GUI/Octomap Rendering/ms", (
float)timer.
restart()*1000.0f));
3307 #if PCL_VERSION_COMPARE(>=, 1, 7, 2) 3312 for(std::map<int, Transform>::const_iterator iter=posesIn.begin(); iter!=posesIn.end() && iter->first<0; ++iter)
3314 #if PCL_VERSION_COMPARE(>=, 1, 7, 2) 3321 std::string(
"landmark_str_") + num,
3331 if(
_ui->graphicsView_graphView->isVisible())
3333 std::multimap<int, Link> constraintsWithOdomCache;
3334 constraintsWithOdomCache = constraints;
3335 constraintsWithOdomCache.insert(odomCacheConstraints.begin(), odomCacheConstraints.end());
3336 _ui->graphicsView_graphView->updateGraph(posesWithOdomCache, constraintsWithOdomCache, mapIdsIn, std::map<int, int>(),
uKeysSet(odomCachePoses));
3340 for(std::map<int, Transform>::iterator iter=gtPoses.begin(); iter!=gtPoses.end(); ++iter)
3342 iter->second = mapToGt * iter->second;
3344 _ui->graphicsView_graphView->updateGTGraph(gtPoses);
3357 #ifdef RTABMAP_OCTOMAP 3372 stats->insert(std::make_pair(
"GUI/Grid Update/ms", (
float)timer.
restart()*1000.0f));
3386 if(
_ui->graphicsView_graphView->isVisible())
3388 _ui->graphicsView_graphView->updateMap(map8U, resolution, xMin, yMin);
3392 _ui->graphicsView_graphView->update();
3397 stats->insert(std::make_pair(
"GUI/Grid Rendering/ms", (
float)timer.
restart()*1000.0f));
3406 if(viewerClouds.contains(
"cloudOdom"))
3422 if(viewerClouds.contains(
"scanOdom"))
3438 if(viewerClouds.contains(
"scanMapOdom"))
3454 if(viewerClouds.contains(
"featuresOdom"))
3475 #ifdef RTABMAP_OCTOMAP 3478 _ui->actionExport_octomap->setEnabled(
false);
3490 std::string cloudName =
uFormat(
"cloud%d", nodeId);
3491 std::pair<pcl::PointCloud<pcl::PointXYZRGB>::Ptr, pcl::IndicesPtr> outputPair;
3494 UERROR(
"Cloud %d already added to map.", nodeId);
3501 UERROR(
"Node %d is not in the cache.", nodeId);
3507 if((!iter->sensorData().imageCompressed().empty() || !iter->sensorData().imageRaw().empty()) &&
3508 (!iter->sensorData().depthOrRightCompressed().empty() || !iter->sensorData().depthOrRightRaw().empty()))
3510 cv::Mat image, depth;
3514 bool rectifyOnlyFeatures = Parameters::defaultRtabmapRectifyOnlyFeatures();
3515 bool imagesAlreadyRectified = Parameters::defaultRtabmapImagesAlreadyRectified();
3516 Parameters::parse(allParameters, Parameters::kRtabmapRectifyOnlyFeatures(), rectifyOnlyFeatures);
3517 Parameters::parse(allParameters, Parameters::kRtabmapImagesAlreadyRectified(), imagesAlreadyRectified);
3518 if(rectifyOnlyFeatures && !imagesAlreadyRectified)
3526 cv::Mat rectifiedImages = data.
imageRaw().clone();
3532 for(
unsigned int i=0; i<data.
cameraModels().size(); ++i)
3541 UWARN(
"Initializing rectification maps for camera %d (only done for the first image received)...", i);
3543 UWARN(
"Initializing rectification maps for camera %d (only done for the first image received)... done!", i);
3549 rectifiedImage.copyTo(cv::Mat(rectifiedImages, cv::Rect(subImageWidth*i, 0, subImageWidth, data.
imageRaw().rows)));
3553 UWARN(
"Camera %d of data %d is not valid for rectification (%dx%d).",
3559 UINFO(
"Time rectification: %fs", time.
ticks());
3561 image = rectifiedImages;
3565 pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud;
3566 pcl::IndicesPtr indices(
new std::vector<int>);
3567 UASSERT_MSG(nodeId == 0 || nodeId == data.
id(),
uFormat(
"nodeId=%d data.id()=%d", nodeId, data.
id()).c_str());
3579 Eigen::Vector3f viewPoint(0.0
f,0.0
f,0.0
f);
3582 viewPoint[0] = data.
cameraModels()[0].localTransform().x();
3583 viewPoint[1] = data.
cameraModels()[0].localTransform().y();
3584 viewPoint[2] = data.
cameraModels()[0].localTransform().z();
3598 indices->resize(cloud->size());
3599 for(
unsigned int i=0; i<cloud->size(); ++i)
3606 if(indices->size() &&
3621 if(indices->size() &&
3632 pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr cloudWithNormals(
new pcl::PointCloud<pcl::PointXYZRGBNormal>);
3637 pcl::IndicesPtr beforeFiltering = indices;
3638 if( cloud->size() &&
3661 pcl::concatenateFields(*cloud, *normals, *cloudWithNormals);
3665 UWARN(
"Cloud subtraction with angle filtering is activated but " 3666 "cloud normal K search is 0. Subtraction is done with angle.");
3670 if(cloudWithNormals->size() &&
3697 UINFO(
"Time subtract filtering %d from %d -> %d (%fs)",
3699 (int)beforeFiltering->size(),
3700 (int)indices->size(),
3713 pcl::PointCloud<pcl::PointXYZRGB>::Ptr output;
3729 pcl::PointCloud<pcl::PointXYZRGB>::Ptr outputFiltered(
new pcl::PointCloud<pcl::PointXYZRGB>);
3730 std::vector<pcl::Vertices> outputPolygons;
3735 pcl::TextureMesh::Ptr textureMesh(
new pcl::TextureMesh);
3736 pcl::toPCLPointCloud2(*outputFiltered, textureMesh->cloud);
3737 textureMesh->tex_polygons.push_back(outputPolygons);
3738 int w = cloud->width;
3739 int h = cloud->height;
3741 textureMesh->tex_coordinates.resize(1);
3742 int nPoints = (int)outputFiltered->size();
3743 textureMesh->tex_coordinates[0].resize(nPoints);
3744 for(
int i=0; i<nPoints; ++i)
3747 UASSERT(i < (
int)denseToOrganizedIndices.size());
3748 int originalVertex = denseToOrganizedIndices[i];
3749 textureMesh->tex_coordinates[0][i] = Eigen::Vector2f(
3750 float(originalVertex % w) /
float(w),
3751 float(h - originalVertex / w) /
float(h));
3754 pcl::TexMaterial mesh_material;
3755 mesh_material.tex_d = 1.0f;
3756 mesh_material.tex_Ns = 75.0f;
3757 mesh_material.tex_illum = 1;
3759 std::stringstream tex_name;
3760 tex_name <<
"material_" << nodeId;
3761 tex_name >> mesh_material.tex_name;
3763 mesh_material.tex_file =
"";
3765 textureMesh->tex_materials.push_back(mesh_material);
3769 UERROR(
"Adding texture mesh %d to viewer failed!", nodeId);
3778 UERROR(
"Adding mesh cloud %d to viewer failed!", nodeId);
3790 UWARN(
"Online meshing is activated but the generated cloud is " 3791 "dense (voxel filtering is used or multiple cameras are used). Disable " 3792 "online meshing in Preferences->3D Rendering to hide this warning.");
3798 pcl::concatenateFields(*cloud, *normals, *cloudWithNormals);
3801 QColor color = Qt::gray;
3804 color = (Qt::GlobalColor)(mapId+3 % 12 + 7 );
3809 if(cloudWithNormals->size())
3811 pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr outputWithNormals;
3816 UERROR(
"Adding cloud %d to viewer failed!", nodeId);
3827 UERROR(
"Adding cloud %d to viewer failed!", nodeId);
3837 outputPair.first = output;
3838 outputPair.second = indices;
3864 std::string scanName =
uFormat(
"scan%d", nodeId);
3867 UERROR(
"Scan %d already added to map.", nodeId);
3874 UERROR(
"Node %d is not in the cache.", nodeId);
3878 if(!iter->sensorData().laserScanCompressed().isEmpty() || !iter->sensorData().laserScanRaw().isEmpty())
3881 iter->sensorData().uncompressData(0, 0, &scan);
3893 pcl::PointCloud<pcl::PointXYZ>::Ptr cloud;
3894 pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloudRGB;
3895 pcl::PointCloud<pcl::PointXYZI>::Ptr cloudI;
3896 pcl::PointCloud<pcl::PointNormal>::Ptr cloudWithNormals;
3897 pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr cloudRGBWithNormals;
3898 pcl::PointCloud<pcl::PointXYZINormal>::Ptr cloudIWithNormals;
3941 if((!scan.
is2d()) &&
3945 if(cloudRGBWithNormals.get())
3958 if(cloudIWithNormals.get())
3971 if(cloudWithNormals.get())
4025 if( (cloud.get() || cloudRGB.get() || cloudI.get()) &&
4028 Eigen::Vector3f scanViewpoint(
4033 pcl::PointCloud<pcl::Normal>::Ptr normals;
4034 if(cloud.get() && cloud->size())
4044 cloudWithNormals.reset(
new pcl::PointCloud<pcl::PointNormal>);
4045 pcl::concatenateFields(*cloud, *normals, *cloudWithNormals);
4048 else if(cloudRGB.get() && cloudRGB->size())
4052 cloudRGBWithNormals.reset(
new pcl::PointCloud<pcl::PointXYZRGBNormal>);
4053 pcl::concatenateFields(*cloudRGB, *normals, *cloudRGBWithNormals);
4056 else if(cloudI.get())
4066 cloudIWithNormals.reset(
new pcl::PointCloud<pcl::PointXYZINormal>);
4067 pcl::concatenateFields(*cloudI, *normals, *cloudIWithNormals);
4072 QColor color = Qt::gray;
4075 color = (Qt::GlobalColor)(mapId+3 % 12 + 7 );
4078 if(cloudRGBWithNormals.get())
4081 if(added && nodeId > 0)
4086 else if(cloudIWithNormals.get())
4089 if(added && nodeId > 0)
4101 else if(cloudWithNormals.get())
4104 if(added && nodeId > 0)
4116 else if(cloudRGB.get())
4119 if(added && nodeId > 0)
4124 else if(cloudI.get())
4127 if(added && nodeId > 0)
4143 if(added && nodeId > 0)
4157 UERROR(
"Adding cloud %d to viewer failed!", nodeId);
4177 std::string cloudName =
uFormat(
"features%d", nodeId);
4180 UERROR(
"Features cloud %d already added to map.", nodeId);
4187 UERROR(
"Node %d is not in the cache.", nodeId);
4193 UDEBUG(
"Features cloud %d already created.");
4197 if(iter->getWords3().size())
4199 UINFO(
"Create cloud from 3D words");
4200 QColor color = Qt::gray;
4203 color = (Qt::GlobalColor)(mapId+3 % 12 + 7 );
4207 if(!iter->sensorData().imageCompressed().empty() || !iter->sensorData().imageRaw().empty())
4213 pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud(
new pcl::PointCloud<pcl::PointXYZRGB>);
4214 cloud->resize(iter->getWords3().size());
4216 UASSERT(iter->getWords().size() == iter->getWords3().size());
4218 UDEBUG(
"rgb.channels()=%d");
4219 if(!iter->getWords3().empty() && !iter->getWordsKpts().empty())
4222 if(iter.value().sensorData().cameraModels().size() == 1 &&
4223 iter.value().sensorData().cameraModels().at(0).isValidForProjection())
4225 invLocalTransform = iter.value().sensorData().cameraModels()[0].localTransform().
inverse();
4227 else if(iter.value().sensorData().stereoCameraModels().size() == 1 &&
4228 iter.value().sensorData().stereoCameraModels()[0].isValidForProjection())
4230 invLocalTransform = iter.value().sensorData().stereoCameraModels()[0].left().localTransform().
inverse();
4233 for(std::multimap<int, int>::const_iterator jter=iter->getWords().begin(); jter!=iter->getWords().end(); ++jter)
4235 const cv::Point3f & pt = iter->getWords3()[jter->second];
4237 (maxDepth == 0.0
f ||
4239 (iter.value().sensorData().cameraModels().size()<=1 &&
4242 (*cloud)[oi].
x = pt.x;
4243 (*cloud)[oi].y = pt.y;
4244 (*cloud)[oi].z = pt.z;
4245 const cv::KeyPoint & kpt = iter->getWordsKpts()[jter->second];
4246 int u = kpt.pt.x+0.5;
4247 int v = kpt.pt.y+0.5;
4252 if(rgb.channels() == 1)
4254 (*cloud)[oi].r = (*cloud)[oi].g = (*cloud)[oi].b = rgb.at<
unsigned char>(v, u);
4258 cv::Vec3b bgr = rgb.at<cv::Vec3b>(v, u);
4259 (*cloud)[oi].b = bgr.val[0];
4260 (*cloud)[oi].g = bgr.val[1];
4261 (*cloud)[oi].r = bgr.val[2];
4266 (*cloud)[oi].r = (*cloud)[oi].g = (*cloud)[oi].b = 255;
4275 UERROR(
"Adding features cloud %d to viewer failed!", nodeId);
4292 const std::map<int, Transform> & poses,
4293 const std::map<int, Transform> & groundTruth)
4296 if(groundTruth.size() && poses.size())
4298 float translational_rmse = 0.0f;
4299 float translational_mean = 0.0f;
4300 float translational_median = 0.0f;
4301 float translational_std = 0.0f;
4302 float translational_min = 0.0f;
4303 float translational_max = 0.0f;
4304 float rotational_rmse = 0.0f;
4305 float rotational_mean = 0.0f;
4306 float rotational_median = 0.0f;
4307 float rotational_std = 0.0f;
4308 float rotational_min = 0.0f;
4309 float rotational_max = 0.0f;
4316 translational_median,
4328 UINFO(
"translational_rmse=%f", translational_rmse);
4329 UINFO(
"translational_mean=%f", translational_mean);
4330 UINFO(
"translational_median=%f", translational_median);
4331 UINFO(
"translational_std=%f", translational_std);
4332 UINFO(
"translational_min=%f", translational_min);
4333 UINFO(
"translational_max=%f", translational_max);
4335 UINFO(
"rotational_rmse=%f", rotational_rmse);
4336 UINFO(
"rotational_mean=%f", rotational_mean);
4337 UINFO(
"rotational_median=%f", rotational_median);
4338 UINFO(
"rotational_std=%f", rotational_std);
4339 UINFO(
"rotational_min=%f", rotational_min);
4340 UINFO(
"rotational_max=%f", rotational_max);
4347 UINFO(
"Update visibility %d", nodeId);
4351 _ui->actionAnchor_clouds_to_ground_truth->isChecked() &&
4361 if(!pose.
isNull() || !visible)
4365 std::string cloudName =
uFormat(
"cloud%d", nodeId);
4366 if(visible && !viewerClouds.contains(cloudName) &&
_cachedSignatures.contains(nodeId))
4370 else if(viewerClouds.contains(cloudName))
4383 std::string scanName =
uFormat(
"scan%d", nodeId);
4384 if(visible && !viewerClouds.contains(scanName) &&
_cachedSignatures.contains(nodeId))
4388 else if(viewerClouds.contains(scanName))
4405 if(
_ui->dockWidget_graphViewer->isVisible())
4407 UDEBUG(
"Graph visible!");
4457 bool removed =
true;
4468 QMessageBox::information(
this, tr(
"Database saved!"), QString(msg.c_str()));
4472 std::string msg =
uFormat(
"Failed to rename temporary database from \"%s\" to \"%s\".",
4475 QMessageBox::critical(
this, tr(
"Closing failed!"), QString(msg.c_str()));
4480 std::string msg =
uFormat(
"Failed to overwrite the database \"%s\". The temporary database is still correctly saved at \"%s\".",
4483 QMessageBox::critical(
this, tr(
"Closing failed!"), QString(msg.c_str()));
4500 QMessageBox::information(
this, tr(
"Database updated!"), QString(msg.c_str()));
4520 if(applicationClosing)
4535 msg.prepend(tr(
"[ERROR] "));
4553 UERROR(
"Map received with code error %d!", event.
getCode());
4561 UINFO(
"Received map!");
4567 QApplication::processEvents();
4569 int addedSignatures = 0;
4570 std::map<int, int> mapIds;
4571 std::map<int, Transform> groundTruth;
4572 std::map<int, std::string> labels;
4573 for(std::map<int, Signature>::const_iterator iter = event.
getSignatures().begin();
4574 iter!=
event.getSignatures().end();
4577 mapIds.insert(std::make_pair(iter->first, iter->second.mapId()));
4578 if(!iter->second.getGroundTruthPose().isNull())
4580 groundTruth.insert(std::make_pair(iter->first, iter->second.getGroundTruthPose()));
4582 if(!iter->second.getLabel().empty())
4584 labels.insert(std::make_pair(iter->first, iter->second.getLabel()));
4587 (
_cachedSignatures.value(iter->first).sensorData().imageCompressed().empty() && !iter->second.sensorData().imageCompressed().empty()))
4591 unsigned int count = 0;
4592 if(!iter->second.getWords3().empty())
4594 for(std::multimap<int, int>::const_iterator jter=iter->second.getWords().upper_bound(-1); jter!=iter->second.getWords().end(); ++jter)
4606 QApplication::processEvents();
4610 QApplication::processEvents();
4620 QApplication::processEvents();
4621 std::map<int, Transform> poses =
event.getPoses();
4622 this->
updateMapCloud(poses, event.
getConstraints(), mapIds, labels, groundTruth, std::map<int, Transform>(), std::multimap<int, Link>(),
true);
4624 if(
_ui->graphicsView_graphView->isVisible() &&
4637 UINFO(
"Map received is empty! Cannot update the map cloud...");
4667 _ui->graphicsView_graphView->setGlobalPath(event.
getPoses());
4683 QMessageBox * warn =
new QMessageBox(
4684 QMessageBox::Warning,
4685 tr(
"Setting goal failed!"),
4686 tr(
"Setting goal to location %1%2 failed. " 4688 "1) the robot is not yet localized in the map,\n" 4689 "2) the location doesn't exist in the map,\n" 4690 "3) the location is not linked to the global map or\n" 4691 "4) the location is too near of the current location (goal already reached).")
4696 warn->setAttribute(Qt::WA_DeleteOnClose,
true);
4701 QMessageBox * info =
new QMessageBox(
4702 QMessageBox::Information,
4703 tr(
"Goal detected!"),
4704 tr(
"Global path computed to %1%2 (%3 poses, %4 m).")
4711 info->setAttribute(Qt::WA_DeleteOnClose,
true);
4718 QTimer::singleShot(1000,
this, SLOT(
postGoal()));
4724 QMessageBox * warn =
new QMessageBox(
4725 QMessageBox::Warning,
4726 tr(
"Setting label failed!"),
4727 tr(
"Setting label %1 to location %2 failed. " 4729 "1) the location doesn't exist in the map,\n" 4730 "2) the location has already a label.").arg(label).arg(
id),
4733 warn->setAttribute(Qt::WA_DeleteOnClose,
true);
4739 _ui->widget_console->appendMsg(tr(
"Goal status received=%1").arg(status),
ULogger::kInfo);
4772 UDEBUG(
"General settings changed...");
4780 _ui->graphicsView_graphView->clearPosterior();
4786 UDEBUG(
"Cloud rendering settings changed...");
4800 UDEBUG(
"Logging settings changed...");
4820 if(parameters.size())
4822 for(rtabmap::ParametersMap::const_iterator iter = parameters.begin(); iter!=parameters.end(); ++iter)
4824 UDEBUG(
"Parameter changed: Key=%s Value=%s", iter->first.c_str(), iter->second.c_str());
4829 if(
uContains(parameters, Parameters::kRtabmapWorkingDirectory()))
4849 if(
uContains(parameters, Parameters::kRGBDLocalRadius()))
4851 _ui->graphicsView_graphView->setLocalRadius(
uStr2Float(parameters.at(Parameters::kRGBDLocalRadius())));
4871 _ui->imageView_source->clearFeatures();
4873 for(std::multimap<int, cv::KeyPoint>::const_iterator iter = refWords.begin(); iter != refWords.end(); ++iter )
4875 int id = iter->first;
4885 color = Qt::magenta;
4897 else if(refWords.count(
id) > 1)
4907 _ui->imageView_source->addFeature(iter->first, iter->second, 0, color);
4913 QList<QPair<cv::Point2f, cv::Point2f> > uniqueCorrespondences;
4914 if(loopWords.size())
4916 _ui->imageView_loopClosure->clearFeatures();
4918 for(std::multimap<int, cv::KeyPoint>::const_iterator iter = loopWords.begin(); iter != loopWords.end(); ++iter )
4920 int id = iter->first;
4930 color = Qt::magenta;
4932 if(
uValues(refWords,
id).size() == 1 &&
uValues(loopWords,
id).size() == 1)
4934 const cv::KeyPoint & a = refWords.find(
id)->second;
4935 const cv::KeyPoint & b = iter->second;
4936 uniqueCorrespondences.push_back(QPair<cv::Point2f, cv::Point2f>(a.pt, b.pt));
4944 else if(refWords.count(
id) > 1)
4954 _ui->imageView_loopClosure->addFeature(iter->first, iter->second, 0, color);
4959 if(refWords.size()>0)
4961 if((*refWords.rbegin()).first >
_lastId)
4963 _lastId = (*refWords.rbegin()).first;
4969 float scaleSource =
_ui->imageView_source->viewScale();
4970 float scaleLoop =
_ui->imageView_loopClosure->viewScale();
4971 UDEBUG(
"scale source=%f loop=%f", scaleSource, scaleLoop);
4973 float sourceMarginX = (
_ui->imageView_source->width() -
_ui->imageView_source->sceneRect().width()*scaleSource)/2.0
f;
4974 float sourceMarginY = (
_ui->imageView_source->height() -
_ui->imageView_source->sceneRect().height()*scaleSource)/2.0
f;
4975 float loopMarginX = (
_ui->imageView_loopClosure->width() -
_ui->imageView_loopClosure->sceneRect().width()*scaleLoop)/2.0
f;
4976 float loopMarginY = (
_ui->imageView_loopClosure->height() -
_ui->imageView_loopClosure->sceneRect().height()*scaleLoop)/2.0
f;
4983 deltaY =
_ui->label_matchId->height() +
_ui->imageView_source->height();
4987 deltaX =
_ui->imageView_source->width();
4990 if(refWords.size() && loopWords.size())
4992 _ui->imageView_source->clearLines();
4993 _ui->imageView_loopClosure->clearLines();
4996 for(QList<QPair<cv::Point2f, cv::Point2f> >::iterator iter = uniqueCorrespondences.begin();
4997 iter!=uniqueCorrespondences.end();
5001 _ui->imageView_source->addLine(
5004 (iter->second.x*scaleLoop+loopMarginX+deltaX-sourceMarginX)/scaleSource,
5005 (iter->second.y*scaleLoop+loopMarginY+deltaY-sourceMarginY)/scaleSource,
5006 _ui->imageView_source->getDefaultMatchingLineColor());
5008 _ui->imageView_loopClosure->addLine(
5009 (iter->first.x*scaleSource+sourceMarginX-deltaX-loopMarginX)/scaleLoop,
5010 (iter->first.y*scaleSource+sourceMarginY-deltaY-loopMarginY)/scaleLoop,
5013 _ui->imageView_loopClosure->getDefaultMatchingLineColor());
5015 _ui->imageView_source->update();
5016 _ui->imageView_loopClosure->update();
5021 for(std::map<int, Link>::const_iterator iter=signature.
getLandmarks().begin(); iter!=signature.
getLandmarks().end(); ++iter)
5038 cv::Vec3d rvec, tvec;
5039 tvec.val[0] = t.
x();
5040 tvec.val[1] = t.
y();
5041 tvec.val[2] = t.
z();
5048 cv::Rodrigues(R, rvec);
5053 std::vector< cv::Point3f > axisPoints;
5055 axisPoints.push_back(cv::Point3f(0, 0, 0));
5056 axisPoints.push_back(cv::Point3f(length, 0, 0));
5057 axisPoints.push_back(cv::Point3f(0, length, 0));
5058 axisPoints.push_back(cv::Point3f(0, 0, length));
5059 std::vector< cv::Point2f > imagePoints;
5060 projectPoints(axisPoints, rvec, tvec, model.
K(), model.
D(), imagePoints);
5069 UWARN(
"Cannot draw correctly landmark %d with provided camera model %d (missing image width)", -iter->first, (
int)i);
5073 for(
int j=0; j<4; ++j)
5082 cv::line(image, imagePoints[0], imagePoints[1], cv::Scalar(0, 0, 255), 3);
5083 cv::line(image, imagePoints[0], imagePoints[2], cv::Scalar(0, 255, 0), 3);
5084 cv::line(image, imagePoints[0], imagePoints[3], cv::Scalar(255, 0, 0), 3);
5085 cv::putText(image,
uNumber2Str(-iter->first), imagePoints[0], cv::FONT_HERSHEY_SIMPLEX, 0.75, cv::Scalar(0, 255, 255), 2);
5101 if(this->isVisible())
5114 if(this->isVisible())
5123 if((event->modifiers() & Qt::ControlModifier) && event->key() == Qt::Key_S)
5131 if (event->type() == QEvent::Resize && qobject_cast<QDockWidget*>(obj))
5133 this->setWindowModified(
true);
5135 else if(event->type() == QEvent::FileOpen )
5139 return QWidget::eventFilter(obj, event);
5146 _ui->actionMore_options->setChecked(
5206 QString
name = (QDateTime::currentDateTime().toString(
"yyMMddhhmmsszzz") + (png?
".png":
".jpg"));
5207 _ui->statusbar->clearMessage();
5208 QPixmap figure = QPixmap::grabWidget(
this);
5214 msg = tr(
"Screen captured \"%1\"").arg(name);
5216 QBuffer buffer(&bytes);
5217 buffer.open(QIODevice::WriteOnly);
5218 figure.save(&buffer, png?
"PNG":
"JPEG");
5224 if(!dir.exists(targetDir))
5226 dir.mkdir(targetDir);
5228 targetDir += QDir::separator();
5229 targetDir +=
"Main_window";
5230 if(!dir.exists(targetDir))
5232 dir.mkdir(targetDir);
5234 targetDir += QDir::separator();
5236 figure.save(targetDir + name);
5237 msg = tr(
"Screen captured \"%1\"").arg(targetDir + name);
5240 _ui->widget_console->appendMsg(msg);
5242 return targetDir + name;
5247 QApplication::beep();
5258 this->setWindowModified(
true);
5263 if(parameters.size())
5265 for(ParametersMap::const_iterator iter= parameters.begin(); iter!=parameters.end(); ++iter)
5267 QString msg = tr(
"Parameter update \"%1\"=\"%2\"")
5268 .arg(iter->first.c_str())
5269 .arg(iter->second.c_str());
5270 _ui->widget_console->appendMsg(msg);
5271 UWARN(msg.toStdString().c_str());
5273 QMessageBox::StandardButton button = QMessageBox::question(
this,
5275 tr(
"Some parameters have been set on command line, do you " 5276 "want to set all other RTAB-Map's parameters to default?"),
5277 QMessageBox::Yes | QMessageBox::No,
5302 this->setWindowModified(
false);
5309 UERROR(
"This method can be called only in IDLE state.");
5325 if(QFile::exists(databasePath.c_str()))
5327 int r = QMessageBox::question(
this,
5328 tr(
"Creating temporary database"),
5329 tr(
"Cannot create a new database because the temporary database \"%1\" already exists. " 5330 "There may be another instance of RTAB-Map running with the same Working Directory or " 5331 "the last time RTAB-Map was not closed correctly. " 5332 "Do you want to recover the database (click Ignore to delete it and create a new one)?").arg(databasePath.c_str()),
5333 QMessageBox::Yes | QMessageBox::No | QMessageBox::Ignore, QMessageBox::No);
5335 if(r == QMessageBox::Ignore)
5337 if(QFile::remove(databasePath.c_str()))
5339 UINFO(
"Deleted temporary database \"%s\".", databasePath.c_str());
5343 UERROR(
"Temporary database \"%s\" could not be deleted!", databasePath.c_str());
5347 else if(r == QMessageBox::Yes)
5349 std::string errorMsg;
5351 progressDialog->setAttribute(Qt::WA_DeleteOnClose);
5353 progressDialog->show();
5361 QString newPath = QFileDialog::getSaveFileName(
this, tr(
"Save recovered database"),
_preferencesDialog->
getWorkingDirectory()+QDir::separator()+QString(
"recovered.db"), tr(
"RTAB-Map database files (*.db)"));
5362 if(newPath.isEmpty())
5366 if(QFileInfo(newPath).suffix() ==
"")
5370 if(QFile::exists(newPath))
5372 QFile::remove(newPath);
5374 QFile::rename(databasePath.c_str(), newPath);
5381 QMessageBox::warning(
this,
"Database recovery", tr(
"Database recovery failed: \"%1\".").arg(errorMsg.c_str()));
5408 UERROR(
"Database can only be opened in IDLE state.");
5412 std::string value = path.toStdString();
5433 if(parameters.size())
5438 parameters.insert(*iter);
5441 uInsert(parameters, overridedParameters);
5445 for(ParametersMap::iterator iter=parameters.begin(); iter!=parameters.end(); ++iter)
5447 ParametersMap::iterator jter = currentParameters.find(iter->first);
5448 if(jter!=currentParameters.end() &&
5449 iter->second.compare(jter->second) != 0 &&
5450 iter->first.compare(Parameters::kRtabmapWorkingDirectory()) != 0)
5452 bool different =
true;
5470 differentParameters.insert(*iter);
5471 QString msg = tr(
"Parameter \"%1\": %2=\"%3\" Preferences=\"%4\"")
5472 .arg(iter->first.c_str())
5473 .arg(overridedParameters.find(iter->first) != overridedParameters.end()?
"Arguments":
"Database")
5474 .arg(iter->second.c_str())
5475 .arg(jter->second.c_str());
5476 _ui->widget_console->appendMsg(msg);
5477 UWARN(msg.toStdString().c_str());
5482 if(differentParameters.size())
5484 int r = QMessageBox::question(
this,
5485 tr(
"Update parameters..."),
5486 tr(
"The %1 using %2 different parameter(s) than " 5487 "those currently set in Preferences. Do you want " 5488 "to use those parameters?")
5489 .arg(overridedParameters.empty()?tr(
"database is"):tr(
"database and input arguments are"))
5490 .arg(differentParameters.size()),
5491 QMessageBox::Yes | QMessageBox::No,
5493 if(r == QMessageBox::Yes)
5506 UERROR(
"File \"%s\" not valid.", value.c_str());
5514 UERROR(
"This method can be called only in INITIALIZED state.");
5521 QMessageBox::Button b = QMessageBox::question(
this,
5522 tr(
"Save database"),
5523 tr(
"Save the new database?"),
5524 QMessageBox::Save | QMessageBox::Cancel | QMessageBox::Discard,
5527 if(b == QMessageBox::Save)
5530 QString newName = QDateTime::currentDateTime().toString(
"yyMMdd-hhmmss");
5533 newPath = QFileDialog::getSaveFileName(
this, tr(
"Save database"), newPath, tr(
"RTAB-Map database files (*.db)"));
5534 if(newPath.isEmpty())
5539 if(QFileInfo(newPath).suffix() ==
"")
5546 else if(b != QMessageBox::Discard)
5560 UERROR(
"This method can be called only in IDLE state.");
5570 dbSettingsIn.beginGroup(
"DatabaseViewer");
5571 dbSettingsOut.beginGroup(
"DatabaseViewer");
5572 QStringList keys = dbSettingsIn.childKeys();
5573 for(QStringList::iterator iter = keys.begin(); iter!=keys.end(); ++iter)
5575 dbSettingsOut.setValue(*iter, dbSettingsIn.value(*iter));
5577 dbSettingsIn.endGroup();
5578 dbSettingsOut.endGroup();
5582 viewer->setWindowModality(Qt::WindowModal);
5583 viewer->setAttribute(Qt::WA_DeleteOnClose,
true);
5588 viewer->showMaximized();
5602 double & odomSensorTimeOffset,
5603 float & odomSensorScaleFactor)
5613 UINFO(
"Create Odom Sensor %d (camera = %d)",
5637 float detectionRate =
uStr2Float(parameters.at(Parameters::kRtabmapDetectionRate()));
5638 int bufferingSize =
uStr2Float(parameters.at(Parameters::kRtabmapImageBufferSize()));
5639 if(((detectionRate!=0.0
f && detectionRate <= inputRate) || (detectionRate > 0.0
f && inputRate == 0.0
f)) &&
5642 int button = QMessageBox::question(
this,
5643 tr(
"Incompatible frame rates!"),
5644 tr(
"\"Source/Input rate\" (%1 Hz) is equal to/higher than \"RTAB-Map/Detection rate\" (%2 Hz). As the " 5645 "source input is a directory of images/video/database, some images may be " 5646 "skipped by the detector. You may want to increase the \"RTAB-Map/Detection rate\" over " 5647 "the \"Source/Input rate\" to guaranty that all images are processed. Would you want to " 5648 "start the detection anyway?").arg(inputRate).arg(detectionRate),
5649 QMessageBox::Yes | QMessageBox::No);
5650 if(button == QMessageBox::No)
5657 if(bufferingSize != 0)
5659 int button = QMessageBox::question(
this,
5660 tr(
"Some images may be skipped!"),
5661 tr(
"\"RTAB-Map/Images buffer size\" is not infinite (size=%1). As the " 5662 "source input is a directory of images/video/database, some images may be " 5663 "skipped by the detector if the \"Source/Input rate\" (which is %2 Hz) is higher than the " 5664 "rate at which RTAB-Map can process the images. You may want to set the " 5665 "\"RTAB-Map/Images buffer size\" to 0 (infinite) to guaranty that all " 5666 "images are processed. Would you want to start the detection " 5667 "anyway?").arg(bufferingSize).arg(inputRate),
5668 QMessageBox::Yes | QMessageBox::No);
5669 if(button == QMessageBox::No)
5674 else if(inputRate == 0)
5676 int button = QMessageBox::question(
this,
5677 tr(
"Large number of images may be buffered!"),
5678 tr(
"\"RTAB-Map/Images buffer size\" is infinite. As the " 5679 "source input is a directory of images/video/database and " 5680 "that \"Source/Input rate\" is infinite too, a lot of images " 5681 "could be buffered at the same time (e.g., reading all images " 5682 "of a directory at once). This could make the GUI not responsive. " 5683 "You may want to set \"Source/Input rate\" at the rate at " 5684 "which the images have been recorded. " 5685 "Would you want to start the detection " 5686 "anyway?").arg(bufferingSize).arg(inputRate),
5687 QMessageBox::Yes | QMessageBox::No);
5688 if(button == QMessageBox::No)
5701 QMessageBox::warning(
this,
5703 tr(
"A camera is running, stop it first."));
5704 UWARN(
"_camera is not null... it must be stopped first");
5712 QMessageBox::warning(
this,
5714 tr(
"No sources are selected. See Preferences->Source panel."));
5715 UWARN(
"No sources are selected. See Preferences->Source panel.");
5721 double poseTimeOffset = 0.0;
5722 float scaleFactor = 0.0f;
5725 Camera * camera = this->
createCamera(&odomSensor, extrinsics, poseTimeOffset, scaleFactor);
5770 if(
uStr2Bool(parameters.at(Parameters::kRGBDEnabled()).c_str()))
5775 UWARN(
"Camera is not calibrated!");
5780 int button = QMessageBox::question(
this,
5781 tr(
"Camera is not calibrated!"),
5782 tr(
"RTAB-Map in metric SLAM mode cannot run with an uncalibrated camera. Do you want to calibrate the camera now?"),
5783 QMessageBox::Yes | QMessageBox::No);
5784 if(button == QMessageBox::Yes)
5794 UERROR(
"OdomThread must be already deleted here?!");
5801 UERROR(
"ImuThread must be already deleted here?!");
5813 odomParameters.erase(Parameters::kRtabmapPublishRAMUsage());
5814 int odomStrategy = Parameters::defaultOdomStrategy();
5817 UDEBUG(
"Odom gravitySigma=%f", gravitySigma);
5818 if(gravitySigma >= 0.0)
5822 if(odomStrategy != 1)
5825 odomParameters.erase(Parameters::kVisCorType());
5838 QMessageBox::warning(
this, tr(
"Source IMU Path"),
5839 tr(
"IMU path is set but odometry chosen doesn't support asynchronous IMU, ignoring IMU..."), QMessageBox::Ok);
5846 QMessageBox::warning(
this, tr(
"Source IMU Path"),
5882 _ui->actionReset_Odometry->setEnabled(
true);
5887 QMessageBox::information(
this,
5889 tr(
"Note that publishing statistics is disabled, " 5890 "progress will not be shown in the GUI."));
5896 #ifdef RTABMAP_OCTOMAP 5917 if(
_state ==
kPaused && (QApplication::keyboardModifiers() & Qt::ShiftModifier))
5937 UINFO(
"Sending pause event!");
5942 UINFO(
"Sending unpause event!");
5957 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);
5959 if(button != QMessageBox::Yes)
5979 _ui->actionReset_Odometry->setEnabled(
false);
6011 QMessageBox::information(
this,
6012 tr(
"No more images..."),
6013 tr(
"The camera has reached the end of the stream."));
6018 _ui->dockWidget_console->show();
6021 for(
int i = 0; i<
_refIds.size(); ++i)
6023 msgRef.append(QString::number(
_refIds[i]));
6028 msgLoop.append(
" ");
6031 _ui->widget_console->appendMsg(QString(
"IDs = [%1];").arg(msgRef));
6032 _ui->widget_console->appendMsg(QString(
"LoopIDs = [%1];").arg(msgLoop));
6043 int id = QInputDialog::getInt(
this, tr(
"Around which location?"), tr(
"Location ID (0=full map)"), 0, 0, 999999, 0, &ok);
6049 margin = QInputDialog::getInt(
this, tr(
"Depth around the location?"), tr(
"Margin"), 4, 1, 100, 1, &ok);
6054 QString path = QFileDialog::getSaveFileName(
this, tr(
"Save File"),
_graphSavingFileName, tr(
"Graphiz file (*.dot)"));
6060 _ui->dockWidget_console->show();
6061 _ui->widget_console->appendMsg(QString(
"Graph saved... Tip:\nneato -Tpdf \"%1\" -o out.pdf").arg(
_graphSavingFileName));
6100 std::map<int, Transform> localTransforms;
6102 items.push_back(
"Robot (base frame)");
6103 items.push_back(
"Camera");
6104 items.push_back(
"Scan");
6106 QString item = QInputDialog::getItem(
this, tr(
"Export Poses"), tr(
"Frame: "), items,
_exportPosesFrame,
false, &ok);
6107 if(!ok || item.isEmpty())
6111 if(item.compare(
"Robot (base frame)") != 0)
6113 bool cameraFrame = item.compare(
"Camera") == 0;
6123 !
_cachedSignatures[iter->first].sensorData().cameraModels().at(0).localTransform().isNull())
6125 localTransform =
_cachedSignatures[iter->first].sensorData().cameraModels().at(0).localTransform();
6127 else if(
_cachedSignatures[iter->first].sensorData().stereoCameraModels().size() == 1 &&
6128 !
_cachedSignatures[iter->first].sensorData().stereoCameraModels()[0].localTransform().isNull())
6130 localTransform =
_cachedSignatures[iter->first].sensorData().stereoCameraModels()[0].localTransform();
6135 UWARN(
"Multi-camera is not supported (node %d)", iter->first);
6139 UWARN(
"Missing calibration for node %d", iter->first);
6144 if(!
_cachedSignatures[iter->first].sensorData().laserScanRaw().localTransform().isNull())
6146 localTransform =
_cachedSignatures[iter->first].sensorData().laserScanRaw().localTransform();
6148 else if(!
_cachedSignatures[iter->first].sensorData().laserScanCompressed().localTransform().isNull())
6150 localTransform =
_cachedSignatures[iter->first].sensorData().laserScanCompressed().localTransform();
6154 UWARN(
"Missing scan info for node %d", iter->first);
6157 if(!localTransform.
isNull())
6159 localTransforms.insert(std::make_pair(iter->first, localTransform));
6164 UWARN(
"Did not find node %d in cache", iter->first);
6167 if(localTransforms.empty())
6169 QMessageBox::warning(
this,
6171 tr(
"Could not find any \"%1\" frame, exporting in Robot frame instead.").arg(item));
6179 std::map<int, Transform> poses;
6180 std::multimap<int, Link> links;
6181 if(localTransforms.empty())
6189 for(std::map<int, Transform>::iterator iter=localTransforms.begin(); iter!=localTransforms.end(); ++iter)
6191 poses.insert(std::make_pair(iter->first,
_currentPosesMap.at(iter->first) * iter->second));
6197 std::multimap<int, Link>::iterator inserted = links.insert(*iter);
6198 int from = iter->second.from();
6199 int to = iter->second.to();
6200 inserted->second.setTransform(localTransforms.at(from).inverse()*iter->second.transform()*localTransforms.at(to));
6205 if(format != 4 && !poses.empty() && poses.begin()->first<0)
6207 UWARN(
"Only g2o format (4) can export landmarks, they are ignored with format %d", format);
6208 std::map<int, Transform>::iterator iter=poses.begin();
6209 while(iter!=poses.end() && iter->first < 0)
6211 poses.erase(iter++);
6215 std::map<int, double> stamps;
6216 if(format == 1 || format == 10 || format == 11)
6218 for(std::map<int, Transform>::iterator iter=poses.begin(); iter!=poses.end(); ++iter)
6222 stamps.insert(std::make_pair(iter->first,
_cachedSignatures.value(iter->first).getStamp()));
6225 if(stamps.size()!=poses.size())
6227 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.")
6228 .arg(poses.size()).arg(stamps.size()));
6238 QString path = QFileDialog::getSaveFileName(
6242 format == 3?tr(
"TORO file (*.graph)"):format==4?tr(
"g2o file (*.g2o)"):tr(
"Text file (*.txt)"));
6246 if(QFileInfo(path).suffix() ==
"")
6267 QMessageBox::information(
this,
6268 tr(
"Export poses..."),
6269 tr(
"%1 saved to \"%2\".")
6270 .arg(format == 3?
"TORO graph":format == 4?
"g2o graph":
"Poses")
6275 QMessageBox::information(
this,
6276 tr(
"Export poses..."),
6277 tr(
"Failed to save %1 to \"%2\"!")
6278 .arg(format == 3?
"TORO graph":format == 4?
"g2o graph":
"poses")
6309 bool refineNeighborLinks,
6310 bool refineLoopClosureLinks,
6311 bool detectMoreLoopClosures,
6312 double clusterRadius,
6313 double clusterAngle,
6321 double sbaRematchFeatures,
6322 bool abortIfDataMissing)
6326 QMessageBox::warning(
this,
6327 tr(
"Post-processing..."),
6328 tr(
"Signatures must be cached in the GUI for post-processing. " 6329 "Check the option in Preferences->General Settings (GUI), then " 6330 "refresh the cache."));
6334 if(!detectMoreLoopClosures && !refineNeighborLinks && !refineLoopClosureLinks && !sba)
6336 UWARN(
"No post-processing selection...");
6342 UWARN(
"No nodes to process...");
6347 std::map<int, Transform> odomPoses;
6348 bool allDataAvailable =
true;
6349 for(std::map<int, Transform>::iterator iter =
_currentPosesMap.lower_bound(1);
6356 UWARN(
"Node %d missing.", iter->first);
6357 allDataAvailable =
false;
6359 else if(!jter.value().getPose().isNull())
6361 odomPoses.insert(std::make_pair(iter->first, jter.value().getPose()));
6365 if(!allDataAvailable)
6367 QString msg = tr(
"Some data missing in the cache to respect the constraints chosen. " 6368 "Try \"Edit->Download all clouds\" to update the cache and try again.");
6369 UWARN(msg.toStdString().c_str());
6370 if(abortIfDataMissing)
6372 QMessageBox::warning(
this, tr(
"Not all data available in the GUI..."), msg);
6385 if(refineNeighborLinks)
6389 if(refineLoopClosureLinks)
6402 bool optimizeFromGraphEnd = Parameters::defaultRGBDOptimizeFromGraphEnd();
6403 float optimizeMaxError = Parameters::defaultRGBDOptimizeMaxError();
6404 int optimizeIterations = Parameters::defaultOptimizerIterations();
6405 bool reextractFeatures = Parameters::defaultRGBDLoopClosureReextractFeatures();
6406 Parameters::parse(parameters, Parameters::kRGBDOptimizeFromGraphEnd(), optimizeFromGraphEnd);
6407 Parameters::parse(parameters, Parameters::kRGBDOptimizeMaxError(), optimizeMaxError);
6408 Parameters::parse(parameters, Parameters::kOptimizerIterations(), optimizeIterations);
6409 Parameters::parse(parameters, Parameters::kRGBDLoopClosureReextractFeatures(), reextractFeatures);
6412 int loopClosuresAdded = 0;
6413 std::multimap<int, int> checkedLoopClosures;
6414 if(detectMoreLoopClosures)
6418 bool loopCovLimited = Parameters::defaultRGBDLoopCovLimited();
6419 Parameters::parse(parameters, Parameters::kRGBDLoopCovLimited(), loopCovLimited);
6420 std::vector<double> odomMaxInf;
6429 _progressDialog->
appendText(tr(
"Looking for more loop closures, clustering poses... (iteration=%1/%2, radius=%3 m angle=%4 degrees)")
6430 .arg(n+1).arg(iterations).arg(clusterRadius).arg(clusterAngle));
6435 clusterAngle*CV_PI/180.0);
6438 _progressDialog->
appendText(tr(
"Looking for more loop closures, clustering poses... found %1 clusters.").arg(clusters.size()));
6439 QApplication::processEvents();
6442 std::set<int> addedLinks;
6443 for(std::multimap<int, int>::iterator iter=clusters.begin(); iter!= clusters.end() && !
_progressCanceled; ++iter, ++i)
6445 int from = iter->first;
6446 int to = iter->second;
6447 if(iter->first < iter->second)
6449 from = iter->second;
6456 if((interSession && mapIdFrom != mapIdTo) ||
6457 (intraSession && mapIdFrom == mapIdTo))
6459 bool alreadyChecked =
false;
6460 for(std::multimap<int, int>::iterator jter = checkedLoopClosures.lower_bound(from);
6461 !alreadyChecked && jter!=checkedLoopClosures.end() && jter->first == from;
6464 if(to == jter->second)
6466 alreadyChecked =
true;
6473 if(addedLinks.find(from) == addedLinks.end() &&
6474 addedLinks.find(to) == addedLinks.end() &&
6479 if(delta.
getNorm() < clusterRadius)
6481 checkedLoopClosures.insert(std::make_pair(from, to));
6485 UERROR(
"Didn't find signature %d", from);
6489 UERROR(
"Didn't find signature %d", to);
6501 if(parameters.find(Parameters::kRegStrategy()) != parameters.end() &&
6502 parameters.at(Parameters::kRegStrategy()).compare(
"1") == 0)
6508 if(reextractFeatures)
6516 UWARN(
"\"%s\" is false and signatures (%d and %d) don't have raw " 6517 "images. Update the cache.",
6518 Parameters::kRGBDLoopClosureReextractFeatures().c_str());
6523 signatureFrom.
sensorData().
setFeatures(std::vector<cv::KeyPoint>(), std::vector<cv::Point3f>(), cv::Mat());
6525 signatureTo.
sensorData().
setFeatures(std::vector<cv::KeyPoint>(), std::vector<cv::Point3f>(), cv::Mat());
6528 else if(!reextractFeatures && signatureFrom.
getWords().empty() && signatureTo.
getWords().empty())
6530 UWARN(
"\"%s\" is false and signatures (%d and %d) don't have words, " 6531 "registration will not be possible. Set \"%s\" to true.",
6532 Parameters::kRGBDLoopClosureReextractFeatures().c_str(),
6535 Parameters::kRGBDLoopClosureReextractFeatures().c_str());
6538 delete registration;
6539 if(!transform.isNull())
6542 bool updateConstraint =
true;
6544 if(odomMaxInf.size() == 6 && information.cols==6 && information.rows==6)
6546 for(
int i=0; i<6; ++i)
6548 if(information.at<
double>(i,i) > odomMaxInf[i])
6550 information.at<
double>(i,i) = odomMaxInf[i];
6554 if(optimizeMaxError > 0.0
f && optimizeIterations > 0)
6563 fromId = iter->first;
6569 const Link * maxLinearLink = 0;
6570 const Link * maxAngularLink = 0;
6571 float maxLinearError = 0.0f;
6572 float maxAngularError = 0.0f;
6573 std::map<int, Transform> poses;
6574 std::multimap<int, Link> links;
6579 UASSERT(poses.find(fromId) != poses.end());
6580 UASSERT_MSG(poses.find(from) != poses.end(),
uFormat(
"id=%d poses=%d links=%d", from, (
int)poses.size(), (int)links.size()).c_str());
6581 UASSERT_MSG(poses.find(to) != poses.end(),
uFormat(
"id=%d poses=%d links=%d", to, (
int)poses.size(), (int)links.size()).c_str());
6583 poses = optimizer->
optimize(fromId, poses, links);
6587 float maxLinearErrorRatio = 0.0f;
6588 float maxAngularErrorRatio = 0.0f;
6592 maxLinearErrorRatio,
6593 maxAngularErrorRatio,
6600 UINFO(
"Max optimization linear error = %f m (link %d->%d)", maxLinearError, maxLinearLink->
from(), maxLinearLink->
to());
6601 if(maxLinearErrorRatio > optimizeMaxError)
6603 msg =
uFormat(
"Rejecting edge %d->%d because " 6604 "graph error is too large after optimization (%f m for edge %d->%d with ratio %f > std=%f m). " 6609 maxLinearLink->
from(),
6610 maxLinearLink->
to(),
6611 maxLinearErrorRatio,
6613 Parameters::kRGBDOptimizeMaxError().c_str(),
6617 else if(maxAngularLink)
6619 UINFO(
"Max optimization angular error = %f deg (link %d->%d)", maxAngularError*180.0
f/
M_PI, maxAngularLink->
from(), maxAngularLink->
to());
6620 if(maxAngularErrorRatio > optimizeMaxError)
6622 msg =
uFormat(
"Rejecting edge %d->%d because " 6623 "graph error is too large after optimization (%f deg for edge %d->%d with ratio %f > std=%f deg). " 6627 maxAngularError*180.0
f/
M_PI,
6628 maxAngularLink->
from(),
6629 maxAngularLink->
to(),
6630 maxAngularErrorRatio,
6632 Parameters::kRGBDOptimizeMaxError().c_str(),
6639 msg =
uFormat(
"Rejecting edge %d->%d because graph optimization has failed!",
6645 UWARN(
"%s", msg.c_str());
6647 QApplication::processEvents();
6648 updateConstraint =
false;
6656 if(updateConstraint)
6658 UINFO(
"Added new loop closure between %d and %d.", from, to);
6659 addedLinks.insert(from);
6660 addedLinks.insert(to);
6663 ++loopClosuresAdded;
6664 _progressDialog->
appendText(tr(
"Detected loop closure %1->%2! (%3/%4)").arg(from).arg(to).arg(i+1).arg(clusters.size()));
6673 QApplication::processEvents();
6676 _progressDialog->
appendText(tr(
"Iteration %1/%2: Detected %3 loop closures!").arg(n+1).arg(iterations).arg(addedLinks.size()/2));
6677 if(addedLinks.size() == 0)
6682 if(n+1 < iterations)
6686 QApplication::processEvents();
6690 std::map<int, rtabmap::Transform> posesOut;
6691 std::multimap<int, rtabmap::Link> linksOut;
6692 std::map<int, rtabmap::Transform> optimizedPoses;
6700 optimizedPoses = optimizer->
optimize(fromId, posesOut, linksOut);
6705 UINFO(
"Added %d loop closures.", loopClosuresAdded);
6712 if(refineLoopClosureLinks)
6718 QApplication::processEvents();
6725 int type = iter->second.type();
6726 int from = iter->second.from();
6727 int to = iter->second.to();
6734 QApplication::processEvents();
6738 UERROR(
"Didn't find signature %d",from);
6742 UERROR(
"Didn't find signature %d", to);
6761 Link newLink(from, to, iter->second.type(), transform, info.
covariance.inv());
6762 iter->second = newLink;
6766 QString str = tr(
"Cannot refine link %1->%2 (%3").arg(from).arg(to).arg(info.
rejectedMsg.c_str());
6768 UWARN(
"%s", str.toStdString().c_str());
6777 str = tr(
"Cannot refine link %1->%2 (Intermediate node detected!)").arg(from).arg(to);
6781 str = tr(
"Cannot refine link %1->%2 (scans empty!)").arg(from).arg(to);
6785 UWARN(
"%s", str.toStdString().c_str());
6799 std::map<int, rtabmap::Transform> posesOut;
6800 std::multimap<int, rtabmap::Link> linksOut;
6801 std::map<int, rtabmap::Transform> optimizedPoses;
6809 optimizedPoses = optimizer->
optimize(fromId, posesOut, linksOut);
6817 .arg(optimizedPoses.size()).arg(linksOut.size()).arg(sbaIterations));
6818 QApplication::processEvents();
6820 QApplication::processEvents();
6823 uInsert(parametersSBA, std::make_pair(Parameters::kOptimizerIterations(),
uNumber2Str(sbaIterations)));
6824 uInsert(parametersSBA, std::make_pair(Parameters::kg2oPixelVariance(),
uNumber2Str(sbaVariance)));
6826 std::map<int, Transform> newPoses = sbaOptimizer->
optimizeBA(optimizedPoses.begin()->first, optimizedPoses, linksOut,
_cachedSignatures.toStdMap(), sbaRematchFeatures);
6827 delete sbaOptimizer;
6830 optimizedPoses = newPoses;
6848 std::map<int, Transform>(),
6849 std::multimap<int, Link>(),
6878 QMessageBox::warning(
this, tr(
"Depth Calibration"), tr(
"No data in cache. Try to refresh the cache."));
6884 QMessageBox::StandardButton button;
6887 button = QMessageBox::question(
this,
6888 tr(
"Deleting memory..."),
6889 tr(
"The remote database and log files will be deleted. Are you sure you want to continue? (This cannot be reverted)"),
6890 QMessageBox::Yes|QMessageBox::No,
6895 button = QMessageBox::question(
this,
6896 tr(
"Deleting memory..."),
6897 tr(
"The current database and log files will be deleted. Are you sure you want to continue? (This cannot be reverted)"),
6898 QMessageBox::Yes|QMessageBox::No,
6902 if(button != QMessageBox::Yes)
6923 #if defined(Q_WS_MAC) 6926 args <<
"tell application \"Finder\"";
6930 args <<
"select POSIX file \""+filePath+
"\"";
6933 QProcess::startDetached(
"osascript", args);
6934 #elif defined(Q_WS_WIN) 6936 args <<
"/select," << QDir::toNativeSeparators(filePath);
6937 QProcess::startDetached(
"explorer", args);
6939 UERROR(
"Only works on Mac and Windows");
7078 UINFO(
"Sending a goal...");
7080 QString text = QInputDialog::getText(
this, tr(
"Send a goal"), tr(
"Goal location ID or label: "), QLineEdit::Normal,
"", &ok);
7081 if(ok && !text.isEmpty())
7092 UINFO(
"Sending waypoints...");
7094 QString text = QInputDialog::getText(
this, tr(
"Send waypoints"), tr(
"Waypoint IDs or labels (separated by spaces): "), QLineEdit::Normal,
"", &ok);
7095 if(ok && !text.isEmpty())
7097 QStringList wp = text.split(
' ');
7100 QMessageBox::warning(
this, tr(
"Send waypoints"), tr(
"At least two waypoints should be set. For only one goal, use send goal action."));
7124 int id = goal.toInt(&ok);
7125 _ui->graphicsView_graphView->setGlobalPath(std::vector<std::pair<int, Transform> >());
7126 UINFO(
"Posting event with goal %s", goal.toStdString().c_str());
7140 UINFO(
"Cancelling goal...");
7148 UINFO(
"Labelling current location...");
7150 QString
label = QInputDialog::getText(
this, tr(
"Label current location"), tr(
"Label: "), QLineEdit::Normal,
"", &ok);
7151 if(ok && !label.isEmpty())
7159 UINFO(
"Removing label...");
7161 QString
label = QInputDialog::getText(
this, tr(
"Remove label"), tr(
"Label: "), QLineEdit::Normal,
"", &ok);
7162 if(ok && !label.isEmpty())
7171 QString path = QFileDialog::getOpenFileName(
this, tr(
"Select file"), dir, tr(
"RTAB-Map database files (*.db)"));
7185 UINFO(
"Update cache...");
7193 std::list<Signature*> signaturesList;
7194 driver->
loadSignatures(std::list<int>(ids.begin(), ids.end()), signaturesList);
7195 std::map<int, Signature> signatures;
7197 for(std::list<Signature *>::iterator iter=signaturesList.begin(); iter!=signaturesList.end(); ++iter)
7199 signatures.insert(std::make_pair((*iter)->id(), *(*iter)));
7207 QMessageBox::warning(
this, tr(
"Update cache"), tr(
"Failed to open database \"%1\"").arg(path));
7216 items.append(
"Local map optimized");
7217 items.append(
"Local map not optimized");
7218 items.append(
"Global map optimized");
7219 items.append(
"Global map not optimized");
7222 QString item = QInputDialog::getItem(
this, tr(
"Download map"), tr(
"Options:"), items, 0,
false, &ok);
7225 bool optimized=
false, global=
false;
7226 if(item.compare(
"Local map optimized") == 0)
7230 else if(item.compare(
"Local map not optimized") == 0)
7234 else if(item.compare(
"Global map optimized") == 0)
7239 else if(item.compare(
"Global map not optimized") == 0)
7245 UFATAL(
"Item \"%s\" not found?!?", item.toStdString().c_str());
7248 UINFO(
"Download clouds...");
7252 .arg(global?
"true":
"false").arg(optimized?
"true":
"false"));
7260 items.append(
"Local map optimized");
7261 items.append(
"Local map not optimized");
7262 items.append(
"Global map optimized");
7263 items.append(
"Global map not optimized");
7266 QString item = QInputDialog::getItem(
this, tr(
"Download graph"), tr(
"Options:"), items, 0,
false, &ok);
7269 bool optimized=
false, global=
false;
7270 if(item.compare(
"Local map optimized") == 0)
7274 else if(item.compare(
"Local map not optimized") == 0)
7278 else if(item.compare(
"Global map optimized") == 0)
7283 else if(item.compare(
"Global map not optimized") == 0)
7289 UFATAL(
"Item \"%s\" not found?!?", item.toStdString().c_str());
7292 UINFO(
"Download the graph...");
7296 .arg(global?
"true":
"false").arg(optimized?
"true":
"false"));
7329 _ui->widget_mapVisibility->clear();
7337 _ui->statsToolBox->clear();
7339 _ui->actionExport_2D_Grid_map_bmp_png->setEnabled(
false);
7340 _ui->actionPost_processing->setEnabled(
false);
7341 _ui->actionSave_point_cloud->setEnabled(
false);
7342 _ui->actionExport_cameras_in_Bundle_format_out->setEnabled(
false);
7343 _ui->actionDepth_Calibration->setEnabled(
false);
7344 _ui->actionExport_images_RGB_jpg_Depth_png->setEnabled(
false);
7345 _ui->actionExport_octomap->setEnabled(
false);
7346 _ui->actionView_high_res_point_cloud->setEnabled(
false);
7353 _ui->label_stats_loopClosuresDetected->setText(
"0");
7354 _ui->label_stats_loopClosuresReactivatedDetected->setText(
"0");
7355 _ui->label_stats_loopClosuresRejected->setText(
"0");
7359 _ui->label_refId->clear();
7360 _ui->label_matchId->clear();
7361 _ui->graphicsView_graphView->clearAll();
7362 _ui->imageView_source->clear();
7363 _ui->imageView_loopClosure->clear();
7364 _ui->imageView_odometry->clear();
7365 _ui->imageView_source->setBackgroundColor(
_ui->imageView_source->getDefaultBackgroundColor());
7366 _ui->imageView_loopClosure->setBackgroundColor(
_ui->imageView_loopClosure->getDefaultBackgroundColor());
7367 _ui->imageView_odometry->setBackgroundColor(
_ui->imageView_odometry->getDefaultBackgroundColor());
7369 #ifdef RTABMAP_OCTOMAP 7384 QDesktopServices::openUrl(QUrl(
"http://wiki.ros.org/rtabmap_ros"));
7388 QDesktopServices::openUrl(QUrl(
"https://github.com/introlab/rtabmap/wiki"));
7396 QString format =
"hh:mm:ss";
7397 _ui->label_elapsedTime->setText((QTime().fromString(
_ui->label_elapsedTime->text(), format).addMSecs(
_elapsedTime->restart())).toString(format));
7403 QList<int> curvesPerFigure;
7404 QStringList curveNames;
7405 _ui->statsToolBox->getFiguresSetup(curvesPerFigure, curveNames);
7407 QStringList curvesPerFigureStr;
7408 for(
int i=0; i<curvesPerFigure.size(); ++i)
7410 curvesPerFigureStr.append(QString::number(curvesPerFigure[i]));
7412 for(
int i=0; i<curveNames.size(); ++i)
7414 curveNames[i].replace(
' ',
'_');
7425 if(!curvesPerFigure.isEmpty())
7427 QStringList curvesPerFigureList = curvesPerFigure.split(
" ");
7428 QStringList curvesNamesList = curveNames.split(
" ");
7431 for(
int i=0; i<curvesPerFigureList.size(); ++i)
7434 int count = curvesPerFigureList[i].toInt(&ok);
7437 QMessageBox::warning(
this,
"Loading failed",
"Corrupted figures setup...");
7442 _ui->statsToolBox->addCurve(curvesNamesList[j++].replace(
'_',
' '));
7443 for(
int k=1; k<count && j<curveNames.size(); ++k)
7445 _ui->statsToolBox->addCurve(curvesNamesList[j++].replace(
'_',
' '),
false);
7468 _ui->dockWidget_posterior->setVisible(
false);
7469 _ui->dockWidget_likelihood->setVisible(
false);
7470 _ui->dockWidget_rawlikelihood->setVisible(
false);
7471 _ui->dockWidget_statsV2->setVisible(
false);
7472 _ui->dockWidget_console->setVisible(
false);
7473 _ui->dockWidget_loopClosureViewer->setVisible(
false);
7474 _ui->dockWidget_mapVisibility->setVisible(
false);
7475 _ui->dockWidget_graphViewer->setVisible(
false);
7476 _ui->dockWidget_odometry->setVisible(
true);
7477 _ui->dockWidget_cloudViewer->setVisible(
true);
7478 _ui->dockWidget_imageView->setVisible(
true);
7479 _ui->dockWidget_multiSessionLoc->setVisible(
false);
7481 _ui->toolBar_2->setVisible(
true);
7482 _ui->statusbar->setVisible(
false);
7494 items << QString(
"Synchronize with map update") << QString(
"Synchronize with odometry update");
7496 QString item = QInputDialog::getItem(
this, tr(
"Select synchronization behavior"), tr(
"Sync:"), items, 0,
false, &ok);
7497 if(ok && !item.isEmpty())
7499 if(item.compare(
"Synchronize with map update") == 0)
7510 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);
7511 if(r == QMessageBox::No || r == QMessageBox::Yes)
7517 _ui->actionAuto_screen_capture->setChecked(
false);
7520 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);
7521 if(r == QMessageBox::No || r == QMessageBox::Yes)
7527 _ui->actionAuto_screen_capture->setChecked(
false);
7533 _ui->actionAuto_screen_capture->setChecked(
false);
7540 if(!dir.exists(targetDir))
7542 dir.mkdir(targetDir);
7544 targetDir += QDir::separator();
7545 targetDir +=
"Main_window";
7546 if(!dir.exists(targetDir))
7548 dir.mkdir(targetDir);
7550 targetDir += QDir::separator();
7564 QApplication::processEvents();
7574 QDesktopServices::openUrl(QUrl::fromLocalFile(this->
captureScreen()));
7579 QRect rect = this->geometry();
7583 if(
float(rect.width())/
float(rect.height()) >
float(w)/float(h))
7585 rect.setWidth(w*(rect.height()/h));
7586 rect.setHeight((rect.height()/h)*h);
7590 rect.setHeight(h*(rect.width()/w));
7591 rect.setWidth((rect.width()/w)*w);
7600 this->setGeometry(rect);
7646 int width = QInputDialog::getInt(
this, tr(
"Aspect ratio"), tr(
"Width (pixels):"), this->geometry().width(), 100, 10000, 100, &ok);
7649 int height = QInputDialog::getInt(
this, tr(
"Aspect ratio"), tr(
"Height (pixels):"), this->geometry().height(), 100, 10000, 100, &ok);
7659 float gridCellSize = 0.05f;
7661 gridCellSize = (float)QInputDialog::getDouble(
this, tr(
"Grid cell size"), tr(
"Size (m):"), (double)gridCellSize, 0.01, 1, 2, &ok);
7668 float xMin=0.0f, yMin=0.0f;
7670 #ifdef RTABMAP_OCTOMAP 7684 cv::Mat map8U(pixels.rows, pixels.cols, CV_8U);
7686 for (
int i = 0; i < pixels.rows; ++i)
7688 for (
int j = 0; j < pixels.cols; ++j)
7690 char v = pixels.at<
char>(i, j);
7704 map8U.at<
unsigned char>(i, j) = gray;
7710 QString path = QFileDialog::getSaveFileName(
this, tr(
"Save to ..."),
"grid.png", tr(
"Image (*.png *.bmp)"));
7713 if(QFileInfo(path).suffix() !=
"png" && QFileInfo(path).suffix() !=
"bmp")
7719 QImage img = image.mirrored(
false,
true).transformed(QTransform().
rotate(-90));
7720 QPixmap::fromImage(img).save(path);
7722 QDesktopServices::openUrl(QUrl::fromLocalFile(path));
7734 std::map<int, Transform> poses =
_ui->widget_mapVisibility->getVisiblePoses();
7739 for(std::map<int, Transform>::iterator iter = poses.begin(); iter!=poses.end(); ++iter)
7744 iter->second = gtIter->second;
7748 UWARN(
"Not found ground truth pose for node %d", iter->first);
7771 std::map<int, Transform> poses =
_ui->widget_mapVisibility->getVisiblePoses();
7776 for(std::map<int, Transform>::iterator iter = poses.begin(); iter!=poses.end(); ++iter)
7781 iter->second = gtIter->second;
7785 UWARN(
"Not found ground truth pose for node %d", iter->first);
7804 #ifdef RTABMAP_OCTOMAP 7807 QString path = QFileDialog::getSaveFileName(
7811 tr(
"Octomap file (*.bt)"));
7817 QMessageBox::information(
this,
7818 tr(
"Export octomap..."),
7819 tr(
"Octomap successfully saved to \"%1\".")
7824 QMessageBox::information(
this,
7825 tr(
"Export octomap..."),
7826 tr(
"Failed to save octomap to \"%1\"!")
7833 UERROR(
"Empty octomap.");
7836 UERROR(
"Cannot export octomap, RTAB-Map is not built with it.");
7844 QMessageBox::warning(
this, tr(
"Export images..."), tr(
"Cannot export images, the cache is empty!"));
7847 std::map<int, Transform> poses =
_ui->widget_mapVisibility->getVisiblePoses();
7851 QMessageBox::warning(
this, tr(
"Export images..."), tr(
"There is no map!"));
7855 QStringList formats;
7856 formats.push_back(
"id.jpg");
7857 formats.push_back(
"id.png");
7858 formats.push_back(
"timestamp.jpg");
7859 formats.push_back(
"timestamp.png");
7861 QString format = QInputDialog::getItem(
this, tr(
"Which RGB format?"), tr(
"Format:"), formats, 0,
false, &ok);
7866 QString ext = format.split(
'.').back();
7867 bool useStamp = format.split(
'.').front().compare(
"timestamp") == 0;
7869 QMap<int, double> stamps;
7870 QString path = QFileDialog::getExistingDirectory(
this, tr(
"Select directory where to save images..."), this->
getWorkingDirectory());
7884 unsigned int saved = 0;
7885 bool calibrationSaved =
false;
7886 for(std::map<int, Transform>::iterator iter=poses.begin(); iter!=poses.end(); ++iter)
7888 QString
id = QString::number(iter->first);
7896 if(!calibrationSaved)
7901 dir.mkdir(QString(
"%1/left").arg(path));
7902 dir.mkdir(QString(
"%1/right").arg(path));
7905 UERROR(
"Only one stereo camera calibration can be saved at this time (%d detected)", (
int)data.
stereoCameraModels().size());
7909 std::string cameraName =
"calibration";
7927 if(
model.save(path.toStdString()))
7929 calibrationSaved =
true;
7930 UINFO(
"Saved stereo calibration \"%s\"", (path.toStdString()+
"/"+cameraName).c_str());
7934 UERROR(
"Failed saving calibration \"%s\"", (path.toStdString()+
"/"+cameraName).c_str());
7943 dir.mkdir(QString(
"%1/rgb").arg(path));
7944 dir.mkdir(QString(
"%1/depth").arg(path));
7949 UERROR(
"Only one camera calibration can be saved at this time (%d detected)", (
int)data.
cameraModels().size());
7953 std::string cameraName =
"calibration";
7961 if(
model.save(path.toStdString()))
7963 calibrationSaved =
true;
7964 UINFO(
"Saved calibration \"%s\"", (path.toStdString()+
"/"+cameraName).c_str());
7968 UERROR(
"Failed saving calibration \"%s\"", (path.toStdString()+
"/"+cameraName).c_str());
7974 if(!data.
imageRaw().empty() && useStamp)
7979 UWARN(
"Node %d has null timestamp! Using id instead!", iter->first);
7983 id = QString::number(stamp,
'f');
7991 if(!cv::imwrite(QString(
"%1/left/%2.%3").arg(path).arg(
id).arg(ext).toStdString(), data.
imageRaw()))
7992 UWARN(
"Failed saving \"%s\"", QString(
"%1/left/%2.%3").arg(path).arg(
id).arg(ext).toStdString().c_str());
7993 if(!cv::imwrite(QString(
"%1/right/%2.%3").arg(path).arg(
id).arg(ext).toStdString(), data.
rightRaw()))
7994 UWARN(
"Failed saving \"%s\"", QString(
"%1/right/%2.%3").arg(path).arg(
id).arg(ext).toStdString().c_str());
7995 info = tr(
"Saved left/%1.%2 and right/%1.%2.").arg(
id).arg(ext);
7999 if(!cv::imwrite(QString(
"%1/rgb/%2.%3").arg(path).arg(
id).arg(ext).toStdString(), data.
imageRaw()))
8000 UWARN(
"Failed saving \"%s\"", QString(
"%1/rgb/%2.%3").arg(path).arg(
id).arg(ext).toStdString().c_str());
8002 UWARN(
"Failed saving \"%s\"", QString(
"%1/depth/%2.png").arg(path).arg(
id).toStdString().c_str());
8003 info = tr(
"Saved rgb/%1.%2 and depth/%1.png.").arg(
id).arg(ext);
8007 if(!cv::imwrite(QString(
"%1/%2.%3").arg(path).arg(
id).arg(ext).toStdString(), data.
imageRaw()))
8008 UWARN(
"Failed saving \"%s\"", QString(
"%1/%2.%3").arg(path).arg(
id).arg(ext).toStdString().c_str());
8010 info = tr(
"Saved %1.%2.").arg(
id).arg(ext);
8014 info = tr(
"No images saved for node %1!").arg(
id);
8020 QApplication::processEvents();
8023 if(saved!=poses.size())
8033 if(!calibrationSaved)
8035 QMessageBox::warning(
this,
8036 tr(
"Export images..."),
8037 tr(
"Data in the cache don't seem to have valid calibration. Calibration file will not be saved. Try refreshing the cache (with clouds)."));
8051 std::map<int, Transform> posesIn =
_ui->widget_mapVisibility->getVisiblePoses();
8056 for(std::map<int, Transform>::iterator iter = posesIn.begin(); iter!=posesIn.end(); ++iter)
8061 iter->second = gtIter->second;
8065 UWARN(
"Not found ground truth pose for node %d", iter->first);
8070 std::map<int, Transform> poses;
8071 for(std::map<int, Transform>::iterator iter=posesIn.begin(); iter!=posesIn.end(); ++iter)
8078 UWARN(
"Missing image in cache for node %d", iter->first);
8080 else if((
_cachedSignatures[iter->first].sensorData().cameraModels().size() == 1 &&
8081 _cachedSignatures[iter->first].sensorData().cameraModels().at(0).isValidForProjection()) ||
8082 (
_cachedSignatures[iter->first].sensorData().stereoCameraModels().size() == 1 &&
8083 _cachedSignatures[iter->first].sensorData().stereoCameraModels()[0].isValidForProjection()))
8085 poses.insert(*iter);
8089 UWARN(
"Missing calibration for node %d", iter->first);
8094 UWARN(
"Did not find node %d in cache", iter->first);
8108 QMessageBox::warning(
this, tr(
"Exporting cameras..."), tr(
"No poses exported because of missing images. Try refreshing the cache (with clouds)."));
8114 UINFO(
"reset odometry");
8120 UINFO(
"trigger a new map");
8131 int r = QMessageBox::question(
this, tr(
"Hard drive or RAM?"), tr(
"Save in RAM?"), QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
8133 if(r == QMessageBox::No || r == QMessageBox::Yes)
8135 bool recordInRAM = r == QMessageBox::Yes;
8140 _dataRecorder->setWindowTitle(tr(
"Data recorder (%1)").arg(path));
8151 _ui->actionData_recorder->setEnabled(
false);
8155 QMessageBox::warning(
this, tr(
""), tr(
"Cannot initialize the data recorder!"));
8156 UERROR(
"Cannot initialize the data recorder!");
8165 UERROR(
"Only one recorder at the same time.");
8171 _ui->actionData_recorder->setEnabled(
true);
8189 _ui->label_source->setVisible(!monitoring);
8190 _ui->label_stats_source->setVisible(!monitoring);
8191 _ui->actionNew_database->setVisible(!monitoring);
8192 _ui->actionOpen_database->setVisible(!monitoring);
8193 _ui->actionClose_database->setVisible(!monitoring);
8194 _ui->actionEdit_database->setVisible(!monitoring);
8195 _ui->actionStart->setVisible(!monitoring);
8196 _ui->actionStop->setVisible(!monitoring);
8197 _ui->actionDump_the_memory->setVisible(!monitoring);
8198 _ui->actionDump_the_prediction_matrix->setVisible(!monitoring);
8199 _ui->actionGenerate_map->setVisible(!monitoring);
8200 _ui->actionUpdate_cache_from_database->setVisible(monitoring);
8201 _ui->actionData_recorder->setVisible(!monitoring);
8202 _ui->menuSelect_source->menuAction()->setVisible(!monitoring);
8203 _ui->doubleSpinBox_stats_imgRate->setVisible(!monitoring);
8204 _ui->doubleSpinBox_stats_imgRate_label->setVisible(!monitoring);
8206 if(wasMonitoring != monitoring)
8208 _ui->toolBar->setVisible(!monitoring);
8209 _ui->toolBar->toggleViewAction()->setVisible(!monitoring);
8211 QList<QAction*> actions =
_ui->menuTools->actions();
8212 for(
int i=0; i<actions.size(); ++i)
8214 if(actions.at(i)->isSeparator())
8216 actions.at(i)->setVisible(!monitoring);
8219 actions =
_ui->menuFile->actions();
8220 if(actions.size()==16)
8222 if(actions.at(2)->isSeparator())
8224 actions.at(2)->setVisible(!monitoring);
8228 UWARN(
"Menu File separators have not the same order.");
8230 if(actions.at(12)->isSeparator())
8232 actions.at(12)->setVisible(!monitoring);
8236 UWARN(
"Menu File separators have not the same order.");
8241 UWARN(
"Menu File actions size has changed (%d)", actions.size());
8243 actions =
_ui->menuProcess->actions();
8244 if(actions.size()>=2)
8246 if(actions.at(1)->isSeparator())
8248 actions.at(1)->setVisible(!monitoring);
8252 UWARN(
"Menu File separators have not the same order.");
8257 UWARN(
"Menu File separators have not the same order.");
8265 _ui->actionNew_database->setEnabled(
true);
8266 _ui->actionOpen_database->setEnabled(
true);
8267 _ui->actionClose_database->setEnabled(
false);
8268 _ui->actionEdit_database->setEnabled(
true);
8269 _ui->actionStart->setEnabled(
false);
8270 _ui->actionPause->setEnabled(
false);
8271 _ui->actionPause->setChecked(
false);
8272 _ui->actionPause->setToolTip(tr(
"Pause"));
8273 _ui->actionStop->setEnabled(
false);
8274 _ui->actionPause_on_match->setEnabled(
true);
8275 _ui->actionPause_on_local_loop_detection->setEnabled(
true);
8276 _ui->actionPause_when_a_loop_hypothesis_is_rejected->setEnabled(
true);
8277 _ui->actionDump_the_memory->setEnabled(
false);
8278 _ui->actionDump_the_prediction_matrix->setEnabled(
false);
8279 _ui->actionDelete_memory->setEnabled(
false);
8282 _ui->actionGenerate_map->setEnabled(
false);
8287 #ifdef RTABMAP_OCTOMAP 8290 _ui->actionExport_octomap->setEnabled(
false);
8294 _ui->actionDownload_all_clouds->setEnabled(
false);
8295 _ui->actionDownload_graph->setEnabled(
false);
8296 _ui->menuSelect_source->setEnabled(
true);
8297 _ui->actionLabel_current_location->setEnabled(
false);
8298 _ui->actionSend_goal->setEnabled(
false);
8299 _ui->actionCancel_goal->setEnabled(
false);
8300 _ui->toolBar->findChild<QAction*>(
"toolbar_source")->setEnabled(
true);
8301 _ui->actionTrigger_a_new_map->setEnabled(
false);
8302 _ui->doubleSpinBox_stats_imgRate->setEnabled(
true);
8303 _ui->statusbar->clearMessage();
8310 _ui->actionStart->setEnabled(
false);
8311 _ui->actionPause->setEnabled(
false);
8312 _ui->actionStop->setEnabled(
false);
8317 _ui->actionNew_database->setEnabled(
false);
8318 _ui->actionOpen_database->setEnabled(
false);
8319 _ui->actionClose_database->setEnabled(
false);
8320 _ui->actionEdit_database->setEnabled(
false);
8325 _ui->actionNew_database->setEnabled(
false);
8326 _ui->actionOpen_database->setEnabled(
false);
8327 _ui->actionClose_database->setEnabled(
true);
8328 _ui->actionEdit_database->setEnabled(
false);
8329 _ui->actionStart->setEnabled(
true);
8330 _ui->actionPause->setEnabled(
false);
8331 _ui->actionPause->setChecked(
false);
8332 _ui->actionPause->setToolTip(tr(
"Pause"));
8333 _ui->actionStop->setEnabled(
false);
8334 _ui->actionPause_on_match->setEnabled(
true);
8335 _ui->actionPause_on_local_loop_detection->setEnabled(
true);
8336 _ui->actionPause_when_a_loop_hypothesis_is_rejected->setEnabled(
true);
8337 _ui->actionDump_the_memory->setEnabled(
true);
8338 _ui->actionDump_the_prediction_matrix->setEnabled(
true);
8342 _ui->actionGenerate_map->setEnabled(
true);
8347 #ifdef RTABMAP_OCTOMAP 8350 _ui->actionExport_octomap->setEnabled(
false);
8354 _ui->actionDownload_all_clouds->setEnabled(
true);
8355 _ui->actionDownload_graph->setEnabled(
true);
8356 _ui->menuSelect_source->setEnabled(
true);
8357 _ui->actionLabel_current_location->setEnabled(
true);
8358 _ui->actionSend_goal->setEnabled(
true);
8359 _ui->actionCancel_goal->setEnabled(
true);
8360 _ui->toolBar->findChild<QAction*>(
"toolbar_source")->setEnabled(
true);
8361 _ui->actionTrigger_a_new_map->setEnabled(
true);
8362 _ui->doubleSpinBox_stats_imgRate->setEnabled(
true);
8363 _ui->statusbar->clearMessage();
8369 _ui->actionStart->setEnabled(
false);
8374 _ui->actionNew_database->setEnabled(
false);
8375 _ui->actionOpen_database->setEnabled(
false);
8376 _ui->actionClose_database->setEnabled(
false);
8377 _ui->actionEdit_database->setEnabled(
false);
8378 _ui->actionStart->setEnabled(
false);
8379 _ui->actionPause->setEnabled(
true);
8380 _ui->actionPause->setChecked(
false);
8381 _ui->actionPause->setToolTip(tr(
"Pause"));
8382 _ui->actionStop->setEnabled(
true);
8383 _ui->actionPause_on_match->setEnabled(
true);
8384 _ui->actionPause_on_local_loop_detection->setEnabled(
true);
8385 _ui->actionPause_when_a_loop_hypothesis_is_rejected->setEnabled(
true);
8386 _ui->actionDump_the_memory->setEnabled(
false);
8387 _ui->actionDump_the_prediction_matrix->setEnabled(
false);
8388 _ui->actionDelete_memory->setEnabled(
false);
8389 _ui->actionPost_processing->setEnabled(
false);
8390 _ui->actionExport_images_RGB_jpg_Depth_png->setEnabled(
false);
8391 _ui->actionGenerate_map->setEnabled(
false);
8392 _ui->menuExport_poses->setEnabled(
false);
8393 _ui->actionSave_point_cloud->setEnabled(
false);
8394 _ui->actionView_high_res_point_cloud->setEnabled(
false);
8395 _ui->actionExport_2D_Grid_map_bmp_png->setEnabled(
false);
8396 _ui->actionExport_octomap->setEnabled(
false);
8397 _ui->actionExport_cameras_in_Bundle_format_out->setEnabled(
false);
8398 _ui->actionDepth_Calibration->setEnabled(
false);
8399 _ui->actionDownload_all_clouds->setEnabled(
false);
8400 _ui->actionDownload_graph->setEnabled(
false);
8401 _ui->menuSelect_source->setEnabled(
false);
8402 _ui->actionLabel_current_location->setEnabled(
true);
8403 _ui->actionSend_goal->setEnabled(
true);
8404 _ui->actionCancel_goal->setEnabled(
true);
8405 _ui->toolBar->findChild<QAction*>(
"toolbar_source")->setEnabled(
false);
8406 _ui->actionTrigger_a_new_map->setEnabled(
true);
8407 _ui->doubleSpinBox_stats_imgRate->setEnabled(
true);
8408 _ui->statusbar->showMessage(tr(
"Detecting..."));
8410 _ui->label_elapsedTime->setText(
"00:00:00");
8430 _ui->actionPause->setToolTip(tr(
"Pause"));
8431 _ui->actionPause->setChecked(
false);
8432 _ui->statusbar->showMessage(tr(
"Detecting..."));
8433 _ui->actionDump_the_memory->setEnabled(
false);
8434 _ui->actionDump_the_prediction_matrix->setEnabled(
false);
8435 _ui->actionDelete_memory->setEnabled(
false);
8436 _ui->actionPost_processing->setEnabled(
false);
8437 _ui->actionExport_images_RGB_jpg_Depth_png->setEnabled(
false);
8438 _ui->actionGenerate_map->setEnabled(
false);
8439 _ui->menuExport_poses->setEnabled(
false);
8440 _ui->actionSave_point_cloud->setEnabled(
false);
8441 _ui->actionView_high_res_point_cloud->setEnabled(
false);
8442 _ui->actionExport_2D_Grid_map_bmp_png->setEnabled(
false);
8443 _ui->actionExport_octomap->setEnabled(
false);
8444 _ui->actionExport_cameras_in_Bundle_format_out->setEnabled(
false);
8445 _ui->actionDepth_Calibration->setEnabled(
false);
8446 _ui->actionDownload_all_clouds->setEnabled(
false);
8447 _ui->actionDownload_graph->setEnabled(
false);
8464 _ui->actionPause->setToolTip(tr(
"Continue (shift-click for step-by-step)"));
8465 _ui->actionPause->setChecked(
true);
8466 _ui->statusbar->showMessage(tr(
"Paused..."));
8467 _ui->actionDump_the_memory->setEnabled(
true);
8468 _ui->actionDump_the_prediction_matrix->setEnabled(
true);
8469 _ui->actionDelete_memory->setEnabled(
false);
8472 _ui->actionGenerate_map->setEnabled(
true);
8477 #ifdef RTABMAP_OCTOMAP 8480 _ui->actionExport_octomap->setEnabled(
false);
8484 _ui->actionDownload_all_clouds->setEnabled(
true);
8485 _ui->actionDownload_graph->setEnabled(
true);
8501 _ui->actionPause->setEnabled(
true);
8502 _ui->actionPause->setChecked(
false);
8503 _ui->actionPause->setToolTip(tr(
"Pause"));
8504 _ui->actionPause_on_match->setEnabled(
true);
8505 _ui->actionPause_on_local_loop_detection->setEnabled(
true);
8506 _ui->actionPause_when_a_loop_hypothesis_is_rejected->setEnabled(
true);
8507 _ui->actionReset_Odometry->setEnabled(
true);
8508 _ui->actionPost_processing->setEnabled(
false);
8509 _ui->actionExport_images_RGB_jpg_Depth_png->setEnabled(
false);
8510 _ui->menuExport_poses->setEnabled(
false);
8511 _ui->actionSave_point_cloud->setEnabled(
false);
8512 _ui->actionView_high_res_point_cloud->setEnabled(
false);
8513 _ui->actionExport_2D_Grid_map_bmp_png->setEnabled(
false);
8514 _ui->actionExport_octomap->setEnabled(
false);
8515 _ui->actionExport_cameras_in_Bundle_format_out->setEnabled(
false);
8516 _ui->actionDepth_Calibration->setEnabled(
false);
8517 _ui->actionDelete_memory->setEnabled(
true);
8518 _ui->actionDownload_all_clouds->setEnabled(
true);
8519 _ui->actionDownload_graph->setEnabled(
true);
8520 _ui->actionTrigger_a_new_map->setEnabled(
true);
8521 _ui->actionLabel_current_location->setEnabled(
true);
8522 _ui->actionSend_goal->setEnabled(
true);
8523 _ui->actionCancel_goal->setEnabled(
true);
8524 _ui->statusbar->showMessage(tr(
"Monitoring..."));
8531 _ui->actionPause->setToolTip(tr(
"Continue"));
8532 _ui->actionPause->setChecked(
true);
8533 _ui->actionPause->setEnabled(
true);
8534 _ui->actionPause_on_match->setEnabled(
true);
8535 _ui->actionPause_on_local_loop_detection->setEnabled(
true);
8536 _ui->actionPause_when_a_loop_hypothesis_is_rejected->setEnabled(
true);
8537 _ui->actionReset_Odometry->setEnabled(
true);
8544 #ifdef RTABMAP_OCTOMAP 8547 _ui->actionExport_octomap->setEnabled(
false);
8551 _ui->actionDelete_memory->setEnabled(
true);
8552 _ui->actionDownload_all_clouds->setEnabled(
true);
8553 _ui->actionDownload_graph->setEnabled(
true);
8554 _ui->actionTrigger_a_new_map->setEnabled(
true);
8555 _ui->actionLabel_current_location->setEnabled(
true);
8556 _ui->actionSend_goal->setEnabled(
true);
8557 _ui->actionCancel_goal->setEnabled(
true);
8558 _ui->statusbar->showMessage(tr(
"Monitoring paused..."));
static void setPrintThreadId(bool printThreadId)
int UTILITE_EXP uStr2Int(const std::string &str)
bool isSavedMaximized() const
GLM_FUNC_DECL T roll(detail::tquat< T, P > const &x)
std::set< int > _cachedEmptyClouds
bool RTABMAP_EXP isFinite(const cv::Point3f &pt)
virtual void openPreferences()
static bool parse(const ParametersMap ¶meters, const std::string &key, bool &value)
bool notifyWhenNewGlobalPathIsReceived() const
bool update(const std::map< int, Transform > &poses)
void incrementStep(int steps=1)
pcl::PointCloud< pcl::PointXYZRGB >::Ptr RTABMAP_EXP subtractFiltering(const pcl::PointCloud< pcl::PointXYZRGB >::Ptr &cloud, const pcl::PointCloud< pcl::PointXYZRGB >::Ptr &substractCloud, float radiusSearch, int minNeighborsInRadius=1)
DepthCalibrationDialog * _depthCalibrationDialog
virtual void processStats(const rtabmap::Statistics &stat)
bool interSession() const
void setAspectRatio(int w, int h)
std::vector< cv::Point2f > refCorners
Camera * createCamera(bool useRawImages=false, bool useColor=true)
void changeImgRateSetting()
void saveMainWindowState(const QMainWindow *mainWindow)
const std::map< int, float > & posterior() const
double getLoopThr() const
bool imageRejectedShown() const
void updateParameters(const ParametersMap ¶meters, bool setOtherParametersToDefault=false)
void clearRawData(bool images=true, bool scan=true, bool userData=true)
QString getIMUPath() const
bool getGeneralLoggerPrintThreadId() const
void exportPosesRGBDSLAMID()
static void createPipe(const UEventsSender *sender, const UEventsHandler *receiver, const std::string &eventName)
bool isSubtractFiltering() const
double getBilateralSigmaR() const
void applyPrefSettings(PreferencesDialog::PANEL_FLAGS flags)
bool isCloudFiltering() const
double rotVariance(bool minimum=true) const
void setStereoExposureCompensation(bool enabled)
const std::string & getGoalLabel() const
pcl::PointCloud< pcl::PointXYZRGB >::Ptr createCloud(unsigned int treeDepth=0, std::vector< int > *obstacleIndices=0, std::vector< int > *emptyIndices=0, std::vector< int > *groundIndices=0, bool originalRefPoints=true, std::vector< int > *frontierIndices=0, std::vector< double > *cloudProb=0) const
const double & stamp() const
Transform transformGroundTruth
virtual ParametersMap getCustomParameters()
std::map< int, Transform > RTABMAP_EXP radiusPosesFiltering(const std::map< int, Transform > &poses, float radius, float angle, bool keepLatest=true)
std::multimap< int, Link >::iterator RTABMAP_EXP findLink(std::multimap< int, Link > &links, int from, int to, bool checkBothWays=true, Link::Type type=Link::kUndef)
void RTABMAP_EXP computeMaxGraphErrors(const std::map< int, Transform > &poses, const std::multimap< int, Link > &links, float &maxLinearErrorRatio, float &maxAngularErrorRatio, float &maxLinearError, float &maxAngularError, const Link **maxLinearErrorLink=0, const Link **maxAngularErrorLink=0, bool for3DoF=false)
virtual QString getTmpIniFilePath() const
float getCellSize() const
int getNormalKSearch() const
void setAutoClose(bool on, int delayedClosingTimeSec=-1)
void exportBundler(const std::map< int, Transform > &poses, const std::multimap< int, Link > &links, const QMap< int, Signature > &signatures, const ParametersMap ¶meters)
GLM_FUNC_DECL genType min(genType const &x, genType const &y)
cv::Point3f RTABMAP_EXP transformPoint(const cv::Point3f &pt, const Transform &transform)
int getGeneralLoggerEventLevel() const
const Transform & getGroundTruthPose() const
int currentGoalId() const
void setCancelButtonVisible(bool visible)
bool init(const std::string &path)
bool isRelocalizationColorOdomCacheGraphView() const
int getCloudColorScheme(int index) const
QString _newDatabasePathOutput
bool isDepthFilteringAvailable() const
double UTILITE_EXP uStr2Double(const std::string &str)
void updateCameraFrustum(const Transform &pose, const StereoCameraModel &model)
pcl::PointCloud< pcl::PointXYZ >::Ptr RTABMAP_EXP transformPointCloud(const pcl::PointCloud< pcl::PointXYZ >::Ptr &cloud, const Transform &transform)
rtabmap::ParametersMap getAllParameters() const
pcl::IndicesPtr RTABMAP_EXP passThrough(const pcl::PointCloud< pcl::PointXYZ >::Ptr &cloud, const pcl::IndicesPtr &indices, const std::string &axis, float min, float max, bool negative=false)
const std::string & label() const
bool isGroundTruthAligned() const
virtual void showEvent(QShowEvent *anEvent)
virtual Camera * createCamera(Camera **odomSensor, Transform &odomSensorExtrinsics, double &odomSensorTimeOffset, float &odomSensorScaleFactor)
void setCloudVisibility(const std::string &id, bool isVisible)
void setAspectRatio1080p()
bool uIsInBounds(const T &value, const T &low, const T &high)
const LaserScan & laserScanCompressed() const
void addOrUpdateCoordinate(const std::string &id, const Transform &transform, double scale, bool foreground=false)
void setMaxDepth(int maxDepth)
void addOrUpdateText(const std::string &id, const std::string &text, const Transform &position, double scale, const QColor &color, bool foreground=true)
bool getGeneralLoggerPrintTime() const
Transform transformFiltered
const QMap< std::string, Transform > & getAddedFrustums() const
int getOdomRegistrationApproach() const
std::map< int, float > _cachedLocalizationsCount
void setMonitoringState(bool monitoringState)
double getCloudOpacity(int index) const
bool isImagesKept() const
GLM_FUNC_DECL vecType< T, P > sqrt(vecType< T, P > const &x)
int getScanPointSize(int index) const
PreferencesDialog * _preferencesDialog
void updateMapCloud(const std::map< int, Transform > &poses, const std::multimap< int, Link > &constraints, const std::map< int, int > &mapIds, const std::map< int, std::string > &labels, const std::map< int, Transform > &groundTruths, const std::map< int, Transform > &odomCachePoses=std::map< int, Transform >(), const std::multimap< int, Link > &odomCacheConstraints=std::multimap< int, Link >(), bool verboseProgress=false, std::map< std::string, float > *stats=0)
std::map< int, cv::Point3f > localMap
int getSourceScanDownsampleStep() const
void removeFrustum(const std::string &id)
pcl::PointCloud< pcl::PointXYZRGBNormal >::Ptr RTABMAP_EXP laserScanToPointCloudRGBNormal(const LaserScan &laserScan, const Transform &transform=Transform(), unsigned char r=100, unsigned char g=100, unsigned char b=100)
void selectDepthAIOAKDLite()
std::pair< std::string, std::string > ParametersPair
bool UTILITE_EXP uStr2Bool(const char *str)
bool removeCloud(const std::string &id)
bool isOdomDisabled() const
void noMoreImagesReceived()
std::vector< int > RTABMAP_EXP filterNotUsedVerticesFromMesh(const pcl::PointCloud< pcl::PointXYZRGBNormal > &cloud, const std::vector< pcl::Vertices > &polygons, pcl::PointCloud< pcl::PointXYZRGBNormal > &outputCloud, std::vector< pcl::Vertices > &outputPolygons)
rtabmap::CameraThread * _camera
float inliersMeanDistance
const cv::Mat & depthOrRightRaw() const
bool isOdomSensorAsGt() const
double getGeneralInputRate() const
void enableBilateralFiltering(float sigmaS, float sigmaR)
std::map< int, std::vector< CameraModel > > localBundleModels
float getTimeLimit() const
double getFloorFilteringHeight() const
bool isSourceMirroring() const
QImage uCvMat2QImage(const cv::Mat &image, bool isBgr=true, uCvQtDepthColorMap colorMap=uCvQtDepthWhiteToBlack, float depthMin=0, float depthMax=0)
std::set< K > uKeysSet(const std::map< K, V > &m)
const std::set< std::string > & getAddedLines() const
bool _autoScreenCaptureOdomSync
bool isRefineLoopClosureLinks() const
void rtabmapLabelErrorReceived(int id, const QString &label)
Transform computeTransformation(const Signature &from, const Signature &to, Transform guess=Transform::getIdentity(), RegistrationInfo *info=0) const
virtual void stopDetection()
const std::multimap< int, Link > & getConstraints() const
double getCloudVoxelSizeScan(int index) const
void timeLimitChanged(float)
float UTILITE_EXP uStr2Float(const std::string &str)
bool addOccupancyGridMap(const cv::Mat &map8U, float resolution, float xMin, float yMin, float opacity)
void setRGBDImage(const cv::Mat &rgb, const cv::Mat &depth, const CameraModel &model, bool clearPreviousData=true)
const std::vector< StereoCameraModel > & stereoCameraModels() const
QString _openedDatabasePath
std::multimap< int, Link > _currentLinksMap
bool isCloudMeshingQuad() const
bool isScansShown(int index) const
void viewClouds(const std::map< int, Transform > &poses, const std::multimap< int, Link > &links, const std::map< int, int > &mapIds, const QMap< int, Signature > &cachedSignatures, const std::map< int, std::pair< pcl::PointCloud< pcl::PointXYZRGB >::Ptr, pcl::IndicesPtr > > &cachedClouds, const std::map< int, LaserScan > &cachedScans, const QString &workingDirectory, const ParametersMap ¶meters)
QString getWorkingDirectory() const
int getSubtractFilteringMinPts() const
virtual QString getIniFilePath() const
rtabmap::OdometryThread * _odomThread
std::map< std::string, std::string > ParametersMap
virtual void openDatabase()
bool getGridMapShown() const
void imgRateChanged(double)
virtual void changeState(MainWindow::State state)
const std::vector< cv::Point3f > & getWords3() const
void setData(const Signature &sA, const Signature &sB)
int getCloudMeshingTriangleSize()
void postProcessing(bool refineNeighborLinks, bool refineLoopClosureLinks, bool detectMoreLoopClosures, double clusterRadius, double clusterAngle, int iterations, bool interSession, bool intraSession, bool sba, int sbaIterations, double sbaVariance, Optimizer::Type sbaType, double sbaRematchFeatures, bool abortIfDataMissing=true)
double getCloudMaxDepth(int index) const
double getIMUGravityLength(int index) const
const cv::Vec4d & orientation() const
float timeParticleFiltering
void setData(const QMap< int, float > &dataMap, const QMap< int, int > &weightsMap)
GLM_FUNC_DECL T angle(detail::tquat< T, P > const &x)
void setWorkingDirectory(const QString &path)
std::vector< int > inliersIDs
PreferencesDialog::Src getOdomSourceDriver() const
void selectRealSense2Stereo()
void selectStereoFlyCapture2()
int getOdomQualityWarnThr() const
Some conversion functions.
virtual void openPreferencesSource()
int getOctomapRenderingType() const
const std::map< int, int > & weights() const
void setupMainLayout(bool vertical)
virtual void keyPressEvent(QKeyEvent *event)
void updateNodeVisibility(int, bool)
std::string getExtension()
void setImageRate(float imageRate)
static void setTreadIdFilter(const std::set< unsigned long > &ids)
GLM_FUNC_DECL T pitch(detail::tquat< T, P > const &x)
std::vector< CameraModel > _rectCameraModels
virtual std::map< int, Transform > optimizeBA(int rootId, const std::map< int, Transform > &poses, const std::multimap< int, Link > &links, const std::map< int, std::vector< CameraModel > > &models, std::map< int, cv::Point3f > &points3DMap, const std::map< int, std::map< int, FeatureBA > > &wordReferences, std::set< int > *outliers=0)
void post(UEvent *event, bool async=true) const
QMap< int, QString > _exportPosesFileName
void removeLine(const std::string &id)
int localBundleConstraints
static void setLevel(ULogger::Level level)
static Transform opticalRotation()
virtual void saveConfigGUI()
long _createdCloudsMemoryUsage
bool isCloudMeshing() const
int sbaIterations() const
void stateChanged(MainWindow::State)
int getGeneralLoggerType() const
const Transform & loopClosureTransform() const
double getCloudMeshingAngle() const
static bool isAvailable(Optimizer::Type type)
bool isRefineNeighborLinks() const
int getIMUFilteringStrategy() const
virtual void pauseDetection()
void drawLandmarks(cv::Mat &image, const Signature &signature)
pcl::PointCloud< pcl::Normal >::Ptr RTABMAP_EXP computeFastOrganizedNormals2D(const pcl::PointCloud< pcl::PointXYZ >::Ptr &cloud, int searchK=5, float searchRadius=0.0f, const Eigen::Vector3f &viewPoint=Eigen::Vector3f(0, 0, 0))
bool isLabelsShown() const
bool getIMUFilteringBaseFrameConversion() const
bool isOdomOnlyInliersShown() const
std::pair< pcl::PointCloud< pcl::PointXYZRGB >::Ptr, pcl::IndicesPtr > createAndAddCloudToMap(int nodeId, const Transform &pose, int mapId)
bool isCloudMeshingTexture() const
pcl::IndicesPtr RTABMAP_EXP extractIndices(const pcl::PointCloud< pcl::PointXYZ >::Ptr &cloud, const pcl::IndicesPtr &indices, bool negative)
pcl::PointCloud< pcl::PointXYZ >::Ptr RTABMAP_EXP laserScanToPointCloud(const LaserScan &laserScan, const Transform &transform=Transform())
double getScanNormalRadiusSearch() const
const std::map< int, Transform > & poses() const
virtual void resetOdometry()
void rtabmapGlobalPathEventReceived(const rtabmap::RtabmapGlobalPathEvent &event)
void updateView(const Transform &AtoB=Transform(), const ParametersMap ¶meters=ParametersMap())
const std::map< int, float > & likelihood() const
bool intraSession() const
bool isOctomap2dGrid() const
void loadMainWindowState(QMainWindow *mainWindow, bool &maximized, bool &statusBarShown)
bool addCloudTextureMesh(const std::string &id, const pcl::TextureMesh::Ptr &textureMesh, const cv::Mat &texture, const Transform &pose=Transform::getIdentity())
double getScanOpacity(int index) const
const std::map< std::string, float > & data() const
void setAspectRatio240p()
std::map< int, Transform > _currentPosesMap
const std::map< int, Link > & getLandmarks() const
int getFeaturesPointSize(int index) const
int loopClosureId() const
const std::string & getInfo() const
Transform _odometryCorrection
std::pair< int, std::pair< std::pair< pcl::PointCloud< pcl::PointXYZRGB >::Ptr, pcl::PointCloud< pcl::PointXYZRGBNormal >::Ptr >, pcl::IndicesPtr > > _previousCloud
bool isFeaturesShown(int index) const
void addOrUpdateLine(const std::string &id, const Transform &from, const Transform &to, const QColor &color, bool arrow=false, bool foreground=false)
void saveCustomConfig(const QString §ion, const QString &key, const QString &value)
bool openConnection(const std::string &url, bool overwritten=false)
const std::vector< cv::KeyPoint > & getWordsKpts() const
#define UASSERT(condition)
bool update(const std::map< int, Transform > &poses)
void setColorOnly(bool colorOnly)
void statsReceived(const rtabmap::Statistics &)
void clearOccupancyGridRaw()
std::map< int, LaserScan > _createdScans
void processCameraInfo(const rtabmap::CameraInfo &info)
void selectRealSense2L515()
Wrappers of STL for convenient functions.
bool isSourceDatabaseStampsUsed() const
const double & bearing() const
virtual void resizeEvent(QResizeEvent *anEvent)
void setLoopClosureViewer(rtabmap::LoopClosureViewer *loopClosureViewer)
void addToCache(int nodeId, const pcl::PointCloud< pcl::PointXYZRGB >::Ptr &ground, const pcl::PointCloud< pcl::PointXYZRGB >::Ptr &obstacles, const pcl::PointXYZ &viewPoint)
float timeStereoExposureCompensation
pcl::PointCloud< pcl::PointXYZRGB >::Ptr RTABMAP_EXP laserScanToPointCloudRGB(const LaserScan &laserScan, const Transform &transform=Transform(), unsigned char r=100, unsigned char g=100, unsigned char b=100)
virtual bool isCalibrated() const =0
virtual bool handleEvent(UEvent *anEvent)
rtabmap::LoopClosureViewer * loopClosureViewer() const
const std::map< int, Signature > & getSignatures() const
void notifyNoMoreImages()
void setAspectRatio16_9()
bool sbaRematchFeatures() const
const std::vector< CameraModel > & cameraModels() const
void mappingModeChanged(bool)
LaserScan RTABMAP_EXP commonFiltering(const LaserScan &scan, int downsamplingStep, float rangeMin=0.0f, float rangeMax=0.0f, float voxelSize=0.0f, int normalK=0, float normalRadius=0.0f, float groundNormalsUp=0.0f)
void changeDetectionRateSetting()
void calibrate(const std::map< int, Transform > &poses, const QMap< int, Signature > &cachedSignatures, const QString &workingDirectory, const ParametersMap ¶meters)
void rtabmapEventInitReceived(int status, const QString &info)
virtual size_t memoryUsage() const
double getCeilingFilteringHeight() const
QString getWorkingDirectory() const
static void setPrintTime(bool printTime)
bool isTimeUsedInFigures() const
const std::map< int, Transform > & addedNodes() const
#define ULOGGER_DEBUG(...)
void setDecimation(int decimation)
double getMarkerLength() const
int getScanColorScheme(int index) const
static Odometry * create(const ParametersMap ¶meters=ParametersMap())
std::vector< int > cornerInliers
bool contains(const M &m, const typename M::key_type &k)
const std::map< int, float > & rawLikelihood() const
void removeAllCoordinates(const std::string &prefix="")
const State & state() const
#define UASSERT_MSG(condition, msg_str)
CvImagePtr cvtColor(const CvImageConstPtr &source, const std::string &encoding)
Transform getIMULocalTransform() const
double getSourceScanVoxelSize() const
void closeConnection(bool save=true, const std::string &outputUrl="")
std::map< int, Transform > currentVisiblePosesMap() const
void addToCache(int nodeId, const cv::Mat &ground, const cv::Mat &obstacles, const cv::Mat &empty)
double getCloudMinDepth(int index) const
virtual std::string getClassName() const =0
pcl::PointCloud< pcl::PointXYZINormal >::Ptr RTABMAP_EXP laserScanToPointCloudINormal(const LaserScan &laserScan, const Transform &transform=Transform(), float intensity=0.0f)
void setScanParameters(bool fromDepth, int downsampleStep=1, float rangeMin=0.0f, float rangeMax=0.0f, float voxelSize=0.0f, int normalsK=0, int normalsRadius=0.0f, float groundNormalsUp=0.0f)
const cv::Mat & imageRaw() const
bool isPriorIgnored() const
void dataRecorderDestroyed()
bool isMarkerDetection() const
void cameraInfoReceived(const rtabmap::CameraInfo &)
rtabmap::OctoMap * _octomap
void enableIMUFiltering(int filteringStrategy=1, const ParametersMap ¶meters=ParametersMap(), bool baseFrameConversion=false)
void getAllNodeIds(std::set< int > &ids, bool ignoreChildren=false, bool ignoreBadSignatures=false, bool ignoreIntermediateNodes=false) const
std::map< int, Transform > optimize(int rootId, const std::map< int, Transform > &poses, const std::multimap< int, Link > &constraints, std::list< std::map< int, Transform > > *intermediateGraphes=0, double *finalError=0, int *iterationsDone=0)
void setAspectRatio480p()
PdfPlotCurve * _likelihoodCurve
Transform RTABMAP_EXP calcRMSE(const std::map< int, Transform > &groundTruth, const std::map< int, Transform > &poses, float &translational_rmse, float &translational_mean, float &translational_median, float &translational_std, float &translational_min, float &translational_max, float &rotational_rmse, float &rotational_mean, float &rotational_median, float &rotational_std, float &rotational_min, float &rotational_max)
const Transform & mapCorrection() const
rtabmap::IMUThread * _imuThread
double getCloudFilteringRadius() const
std::vector< double > RTABMAP_EXP getMaxOdomInf(const std::multimap< int, Link > &links)
static void registerCurrentThread(const std::string &name)
int getSourceImageDecimation() const
pcl::PointCloud< pcl::PointXYZRGB >::Ptr RTABMAP_EXP cloudRGBFromSensorData(const SensorData &sensorData, int decimation=1, float maxDepth=0.0f, float minDepth=0.0f, std::vector< int > *validIndices=0, const ParametersMap &stereoParameters=ParametersMap(), const std::vector< float > &roiRatios=std::vector< float >())
static void setType(Type type, const std::string &fileName=kDefaultLogFileName, bool append=true)
void removeText(const std::string &id)
void cameraInfoProcessed()
void loopClosureThrChanged(qreal)
void removeOccupancyGridMap()
std::map< int, Transform > localBundlePoses
std::map< int, std::pair< pcl::PointCloud< pcl::PointXYZRGB >::Ptr, pcl::IndicesPtr > > _cachedClouds
void setCloudPointSize(const std::string &id, int size)
static void setEventLevel(ULogger::Level eventSentLevel)
void openWorkingDirectory()
int getOdomBufferSize() const
std::vector< CameraModel > _rectCameraModelsOdom
void anchorCloudsToGroundTruth()
std::map< int, std::string > _currentLabels
void printLoopClosureIds()
virtual void closeEvent(QCloseEvent *event)
void changeTimeLimitSetting()
bool isFrustumsShown(int index) const
cv::Mat RTABMAP_EXP computeNormals(const cv::Mat &laserScan, int searchK, float searchRadius)
void setMaximumSteps(int steps)
const Transform & localTransform() const
rtabmap::ProgressDialog * progressDialog()
void exportPoses(int format)
void init(const QString &iniFilePath="")
void updateCameraTargetPosition(const Transform &pose)
cv::Mat getMap(float &xMin, float &yMin) const
void updateParameters(const rtabmap::ParametersMap ¶meters)
void saveWindowGeometry(const QWidget *window)
const std::multimap< int, Link > & odomCacheConstraints() const
const RtabmapColorOcTree * octree() const
void addOrUpdateFrustum(const std::string &id, const Transform &pose, const Transform &localTransform, double scale, const QColor &color=QColor(), float fovX=1.1, float fovY=0.85)
LaserScan laserScanFromPointCloud(const PointCloud2T &cloud, bool filterNaNs, bool is2D, const Transform &transform)
double getSubtractFilteringAngle() const
float icpStructuralDistribution
bool isIMUGravityShown(int index) const
bool isCloudsShown(int index) const
void setStereoImage(const cv::Mat &left, const cv::Mat &right, const StereoCameraModel &stereoCameraModel, bool clearPreviousData=true)
const std::map< int, Signature > & getSignaturesData() const
int getDownsamplingStepScan(int index) const
void processRtabmapLabelErrorEvent(int id, const QString &label)
float getDetectionRate() const
unsigned long getMemoryUsed() const
std::list< std::string > uSplitNumChar(const std::string &str)
int getGeneralLoggerPauseLevel() const
DiscreteDepthDistortionModel RTABMAP_EXP calibrate(const std::map< int, rtabmap::SensorData > &sequence, const std::map< int, rtabmap::Transform > &trajectory, const pcl::PointCloud< pcl::PointXYZ >::Ptr &map, double coneRadius=0.02, double coneStdevThresh=0.03)
bool isSourceRGBDColorOnly() const
void exportPosesRGBDSLAMMotionCapture()
void setDistortionModel(const std::string &path)
std::vector< pcl::Vertices > RTABMAP_EXP organizedFastMesh(const pcl::PointCloud< pcl::PointXYZ >::Ptr &cloud, double angleTolerance, bool quad, int trianglePixelSize, const Eigen::Vector3f &viewpoint=Eigen::Vector3f(0, 0, 0))
CloudViewer * _cloudViewer
double getSubtractFilteringRadius() const
OdometryInfo copyWithoutData() const
bool openDatabase(const QString &path)
virtual void deleteMemory()
PdfPlotCurve * _posteriorCurve
float inliersDistribution
void setMirroringEnabled(bool enabled)
bool _autoScreenCaptureRAM
void setBackgroundColor(const QColor &color)
void getConnectedGraph(int fromId, const std::map< int, Transform > &posesIn, const std::multimap< int, Link > &linksIn, std::map< int, Transform > &posesOut, std::multimap< int, Link > &linksOut, bool adjustPosesWithConstraints=true) const
bool uContains(const std::list< V > &list, const V &value)
bool updateFrustumPose(const std::string &id, const Transform &pose)
const cv::Mat & depthOrRightCompressed() const
void exportClouds(const std::map< int, Transform > &poses, const std::multimap< int, Link > &links, const std::map< int, int > &mapIds, const QMap< int, Signature > &cachedSignatures, const std::map< int, std::pair< pcl::PointCloud< pcl::PointXYZRGB >::Ptr, pcl::IndicesPtr > > &cachedClouds, const std::map< int, LaserScan > &cachedScans, const QString &workingDirectory, const ParametersMap ¶meters)
std::multimap< int, int > RTABMAP_EXP radiusPosesClustering(const std::map< int, Transform > &poses, float radius, float angle)
virtual void triggerNewMap()
bool RTABMAP_EXP exportPoses(const std::string &filePath, int format, const std::map< int, Transform > &poses, const std::multimap< int, Link > &constraints=std::multimap< int, Link >(), const std::map< int, double > &stamps=std::map< int, double >(), const ParametersMap ¶meters=ParametersMap())
MultiSessionLocWidget * _multiSessionLocWidget
void rtabmapEvent3DMapProcessed()
std::map< int, Transform > _currentGTPosesMap
void setMonitoringState(bool pauseChecked=false)
void setCameraLockZ(bool enabled=true)
void setPose(const Transform &pose)
static DBDriver * create(const ParametersMap ¶meters=ParametersMap())
GLM_FUNC_DECL detail::tquat< T, P > rotation(detail::tvec3< T, P > const &orig, detail::tvec3< T, P > const &dest)
const Transform & localTransform() const
void exportBundlerFormat()
std::map< int, pcl::PointCloud< pcl::PointXYZRGB >::Ptr > _createdFeatures
void setImageDecimation(int decimation)
QMap< int, Signature > _cachedSignatures
void selectStereoDC1394()
int getSourceScanNormalsK() const
void registerToEventsManager()
static void initGuiResource()
bool isSourceStereoDepthGenerated() const
bool addCloud(const std::string &id, const pcl::PCLPointCloud2Ptr &binaryCloud, const Transform &pose, bool rgb, bool hasNormals, bool hasIntensity, const QColor &color=QColor(), int viewport=1)
bool getCloudVisibility(const std::string &id)
static std::string getType(const std::string ¶mKey)
virtual void clearTheCache()
QMap< QString, QByteArray > _autoScreenCaptureCachedImages
const std::map< int, Transform > & addedNodes() const
MainWindow(PreferencesDialog *prefDialog=0, QWidget *parent=0, bool showSplashScreen=true)
double sbaVariance() const
void uSleep(unsigned int ms)
const std::multimap< int, Link > & constraints() const
int getKpMaxFeatures() const
QString getSourceDriverStr() const
void setCloudViewer(rtabmap::CloudViewer *cloudViewer)
pcl::IndicesPtr RTABMAP_EXP radiusFiltering(const pcl::PointCloud< pcl::PointXYZ >::Ptr &cloud, float radiusSearch, int minNeighborsInRadius)
const Transform & groundTruth() const
virtual void moveEvent(QMoveEvent *anEvent)
void showPostProcessingDialog()
void processRtabmapEvent3DMap(const rtabmap::RtabmapEvent3DMap &event)
cv::Mat RTABMAP_EXP convertMap2Image8U(const cv::Mat &map8S, bool pgmFormat=false)
PdfPlotCurve * _rawLikelihoodCurve
const std::vector< int > & localPath() const
static const ParametersMap & getDefaultParameters()
std::string getParameter(const std::string &key) const
double getScanFloorFilteringHeight() const
QString loadCustomConfig(const QString §ion, const QString &key)
void addOrUpdateGraph(const std::string &id, const pcl::PointCloud< pcl::PointXYZ >::Ptr &graph, const QColor &color=Qt::gray)
float getFrustumScale() const
std::vector< V > uValues(const std::multimap< K, V > &mm)
const QColor & getBackgroundColor() const
bool isGraphsShown() const
rtabmap::OccupancyGrid * _occupancyGrid
int getOctomapPointSize() const
virtual void setDefaultViews()
static Registration * create(const ParametersMap ¶meters)
void setStereoToDepth(bool enabled)
const LaserScan & laserScanRaw() const
virtual void startDetection()
std::map< int, float > _cachedWordsCount
bool isLocalizationsCountGraphView() const
virtual bool closeDatabase()
bool isStatisticsPublished() const
GLM_FUNC_DECL genType max(genType const &x, genType const &y)
std::multimap< int, cv::KeyPoint > words
SensorData & sensorData()
void saveWidgetState(const QWidget *widget)
QString captureScreen(bool cacheInRAM=false, bool png=true)
float icpStructuralComplexity
T uNormSquared(const std::vector< T > &v)
void detectionRateChanged(double)
void loadNodeData(Signature *signature, bool images=true, bool scan=true, bool userData=true, bool occupancyGrid=true) const
void updateCameraFrustums(const Transform &pose, const std::vector< CameraModel > &models)
rtabmap::CloudViewer * cloudViewer() const
std::map< int, int > _currentMapIds
std::list< K > uKeysList(const std::multimap< K, V > &mm)
double clusterRadius() const
const OdometryInfo & info() const
std::vector< std::string > getGeneralLoggerThreads() const
int getOctomapTreeDepth() const
void showCloseButton(bool visible=true)
bool isWordsCountGraphView() const
void processRtabmapEventInit(int status, const QString &info)
bool isOctomapShown() const
bool writeBinary(const std::string &path)
static void addHandler(UEventsHandler *handler)
double getNoiseRadius() const
void loadSignatures(const std::list< int > &ids, std::list< Signature *> &signatures, std::set< int > *loadedFromTrash=0)
QString _defaultOpenDatabasePath
QString getSourceDistortionModel() const
bool RTABMAP_EXP databaseRecovery(const std::string &corruptedDatabase, bool keepCorruptedDatabase=true, std::string *errorMsg=0, ProgressState *progressState=0)
bool isSourceScanFromDepth() const
pcl::PointCloud< pcl::PointNormal >::Ptr RTABMAP_EXP laserScanToPointCloudNormal(const LaserScan &laserScan, const Transform &transform=Transform())
PreferencesDialog::Src getSourceDriver() const
Optimizer::Type sbaType() const
static const std::map< std::string, float > & defaultData()
double getPlanningTime() const
const QColor & getDefaultBackgroundColor() const
int getScanNormalKSearch() const
double getSourceScanForceGroundNormalsUp() const
void selectSourceDriver(Src src, int variant=0)
void setCurrentPanelToSource()
virtual void downloadPoseGraph()
ULogger class and convenient macros.
const CameraInfo & info() const
void setAspectRatioCustom()
void loadWindowGeometry(QWidget *window)
double getSourceScanNormalsRadius() const
void setBackfaceCulling(bool enabled, bool frontfaceCulling)
const Signature & getLastSignatureData() const
void setAspectRatio360p()
ProgressDialog * _progressDialog
PostProcessingDialog * _postProcessingDialog
ParametersMap getLastParameters() const
double getScanCeilingFilteringHeight() const
float timeImageDecimation
bool isPosteriorGraphView() const
AboutDialog * _aboutDialog
virtual size_t size() const
void setCameraTargetFollow(bool enabled=true)
ExportBundlerDialog * _exportBundlerDialog
bool isCacheSavedInFigures() const
const Statistics & getStats() const
GLM_FUNC_DECL T yaw(detail::tquat< T, P > const &x)
void setAspectRatio16_10()
double getSourceScanRangeMin() const
std::vector< int > matchesIDs
std::vector< cv::Point2f > newCorners
void setCloudColorIndex(const std::string &id, int index)
double transVariance(bool minimum=true) const
void parseParameters(const ParametersMap ¶meters)
double getBilateralSigmaS() const
Transform alignPosesToGroundTruth(const std::map< int, Transform > &poses, const std::map< int, Transform > &groundTruth)
void removeCoordinate(const std::string &id)
bool hasIntensity() const
bool init(const QString &path, bool recordInRAM=true)
bool odomProvided() const
const cv::Vec3d linearAcceleration() const
cv::Mat RTABMAP_EXP cvtDepthFromFloat(const cv::Mat &depth32F)
bool _processingStatistics
int getOdomStrategy() const
double getOdomF2MGravitySigma() const
void exportPosesRGBDSLAM()
double getGridMapOpacity() const
const std::map< int, std::string > & labels() const
cv::Mat createProjectionMap(float &xMin, float &yMin, float &gridCellSize, float minGridSize=0.0f, unsigned int treeDepth=0)
bool addOctomap(const OctoMap *octomap, unsigned int treeDepth=0, bool volumeRepresentation=true)
float timeBilateralFiltering
bool addCloudMesh(const std::string &id, const pcl::PointCloud< pcl::PointXYZ >::Ptr &cloud, const std::vector< pcl::Vertices > &polygons, const Transform &pose=Transform::getIdentity())
bool isCloudsKept() const
double getScanMaxRange(int index) const
bool isOctomapUpdated() const
int proximityDetectionId() const
std::vector< float > getCloudRoiRatios(int index) const
pcl::PointCloud< pcl::PointXYZI >::Ptr RTABMAP_EXP laserScanToPointCloudI(const LaserScan &laserScan, const Transform &transform=Transform(), float intensity=0.0f)
QString _graphSavingFileName
void join(bool killFirst=false)
bool isMissingCacheRepublished() const
virtual bool eventFilter(QObject *obj, QEvent *event)
GLM_FUNC_DECL genType::value_type length(genType const &x)
void processOdometry(const rtabmap::OdometryEvent &odom, bool dataIgnored)
void rtabmapEvent3DMapReceived(const rtabmap::RtabmapEvent3DMap &event)
double getCloudFilteringAngle() const
void selectOpenniCvAsus()
void appendText(const QString &text, const QColor &color=Qt::black)
void setAspectRatio720p()
void createAndAddScanToMap(int nodeId, const Transform &pose, int mapId)
pcl::PointCloud< pcl::PointXYZ >::Ptr RTABMAP_EXP voxelize(const pcl::PointCloud< pcl::PointXYZ >::Ptr &cloud, const pcl::IndicesPtr &indices, float voxelSize)
void loadWidgetState(QWidget *widget)
void rtabmapGoalStatusEventReceived(int status)
bool isIMUAccShown() const
int getCloudDecimation(int index) const
void drawKeypoints(const std::multimap< int, cv::KeyPoint > &refWords, const std::multimap< int, cv::KeyPoint > &loopWords)
QVector< int > _loopClosureIds
const QMap< std::string, Transform > & getAddedClouds() const
const Transform & pose() const
double clusterAngle() const
float RTABMAP_EXP computePathLength(const std::vector< std::pair< int, Transform > > &path, unsigned int fromIndex=0, unsigned int toIndex=0)
int getNoiseMinNeighbors() const
std::string UTILITE_EXP uFormat(const char *fmt,...)
std::string UTILITE_EXP uNumber2Str(unsigned int number)
bool isVerticalLayoutUsed() const
ExportCloudsDialog * _exportCloudsDialog
double getNormalRadiusSearch() const
bool getPose(const std::string &id, Transform &pose)
int getGeneralLoggerLevel() const
void createAndAddFeaturesToMap(int nodeId, const Transform &pose, int mapId)
const std::map< int, Transform > & getPoses() const
double getScanMinRange(int index) const
bool isBilateralFiltering() const
bool isValidForProjection() const
const std::vector< std::pair< int, Transform > > & getPoses() const
std::map< int, float > RTABMAP_EXP findNearestNodes(int nodeId, const std::map< int, Transform > &poses, float radius, float angle=0.0f, int k=0)
bool _autoScreenCapturePNG
const cv::Mat & imageCompressed() const
Transform localTransform() const
DataRecorder * _dataRecorder
double getSourceScanRangeMax() const
static Optimizer * create(const ParametersMap ¶meters)
LaserScan RTABMAP_EXP laserScan2dFromPointCloud(const pcl::PointCloud< pcl::PointXYZ > &cloud, const Transform &transform=Transform(), bool filterNaNs=true)
LoopClosureViewer * _loopClosureViewer
V uValue(const std::map< K, V > &m, const K &key, const V &defaultValue=V())
virtual void newDatabase()
void updateSelectSourceMenu()
void processRtabmapGlobalPathEvent(const rtabmap::RtabmapGlobalPathEvent &event)
void updateCacheFromDatabase()
void setFeatures(const std::vector< cv::KeyPoint > &keypoints, const std::vector< cv::Point3f > &keypoints3D, const cv::Mat &descriptors)
const std::map< int, Transform > & odomCachePoses() const
int getCloudPointSize(int index) const
bool updateCloudPose(const std::string &id, const Transform &pose)
bool isSourceStereoExposureCompensation() const
bool isDetectMoreLoopClosures() const
void odometryReceived(const rtabmap::OdometryEvent &, bool)
double landmarkVisSize() const
virtual void downloadAllClouds()
void setCloudOpacity(const std::string &id, double opacity=1.0)
GLM_FUNC_DECL detail::tmat4x4< T, P > orientation(detail::tvec3< T, P > const &Normal, detail::tvec3< T, P > const &Up)
const SensorData & data() const
void uInsert(std::map< K, V > &map, const std::pair< K, V > &pair)
void selectScreenCaptureFormat(bool checked)
bool isFramesShown() const
Camera * createOdomSensor(Transform &extrinsics, double &timeOffset, float &scaleFactor)
const std::multimap< int, int > & getWords() const
void processRtabmapGoalStatusEvent(int status)
bool isLandmarksShown() const
bool _processingDownloadedMap
bool imageHighestHypShown() const