30 #include "ui_mainWindow.h" 73 #include <QtGui/QCloseEvent> 74 #include <QtGui/QPixmap> 75 #include <QtCore/QDir> 76 #include <QtCore/QFile> 77 #include <QtCore/QTextStream> 78 #include <QtCore/QFileInfo> 79 #include <QMessageBox> 80 #include <QFileDialog> 81 #include <QGraphicsEllipseItem> 82 #include <QDockWidget> 83 #include <QtCore/QBuffer> 84 #include <QtCore/QTimer> 85 #include <QtCore/QTime> 86 #include <QActionGroup> 87 #include <QtCore/QThread> 88 #include <QtGui/QDesktopServices> 89 #include <QtCore/QStringList> 90 #include <QtCore/QProcess> 91 #include <QSplashScreen> 92 #include <QInputDialog> 93 #include <QToolButton> 110 #include <pcl/visualization/cloud_viewer.h> 111 #include <pcl/common/transforms.h> 112 #include <pcl/common/common.h> 113 #include <pcl/io/pcd_io.h> 114 #include <pcl/io/ply_io.h> 115 #include <pcl/filters/filter.h> 116 #include <pcl/search/kdtree.h> 118 #ifdef RTABMAP_OCTOMAP 122 #define LOG_FILE_NAME "LogRtabmap.txt" 123 #define SHARE_SHOW_LOG_FILE "share/rtabmap/showlogs.m" 124 #define SHARE_GET_PRECISION_RECALL_FILE "share/rtabmap/getPrecisionRecall.m" 125 #define SHARE_IMPORT_FILE "share/rtabmap/importfile.m" 141 _preferencesDialog(0),
143 _exportCloudsDialog(0),
144 _exportBundlerDialog(0),
148 _processingStatistics(
false),
149 _processingDownloadedMap(
false),
151 _odometryReceived(
false),
152 _newDatabasePath(
""),
153 _newDatabasePathOutput(
""),
154 _openedDatabasePath(
""),
155 _databaseUpdated(
false),
156 _odomImageShow(
true),
157 _odomImageDepthShow(
false),
158 _savedMaximized(
false),
160 _cachedMemoryUsage(0),
161 _createdCloudsMemoryUsage(0),
164 _odometryCorrection(
Transform::getIdentity()),
165 _processingOdometry(
false),
170 _rawLikelihoodCurve(0),
171 _exportPosesFrame(0),
172 _autoScreenCaptureOdomSync(
false),
173 _autoScreenCaptureRAM(
false),
174 _autoScreenCapturePNG(
false),
176 _progressCanceled(
false)
183 QSplashScreen * splash = 0;
184 if (showSplashScreen)
186 QPixmap pixmap(
":images/RTAB-Map.png");
187 splash =
new QSplashScreen(pixmap);
189 splash->showMessage(tr(
"Loading..."));
190 QApplication::processEvents();
205 _ui =
new Ui_mainWindow();
221 UDEBUG(
"Setup ui... end");
223 QString title(
"RTAB-Map[*]");
224 this->setWindowTitle(title);
225 this->setWindowIconText(tr(
"RTAB-Map"));
226 this->setObjectName(
"MainWindow");
231 _ui->widget_mainWindow->setVisible(
false);
247 bool statusBarShown =
false;
259 #ifdef RTABMAP_OCTOMAP 267 _ui->label_elapsedTime->setText(
"00:00:00");
273 _ui->imageView_source->setBackgroundColor(
_ui->imageView_source->getDefaultBackgroundColor());
274 _ui->imageView_loopClosure->setBackgroundColor(
_ui->imageView_loopClosure->getDefaultBackgroundColor());
275 _ui->imageView_odometry->setBackgroundColor(
_ui->imageView_odometry->getDefaultBackgroundColor());
276 _ui->imageView_odometry->setAlpha(200);
284 _ui->posteriorPlot->showLegend(
false);
285 _ui->posteriorPlot->setFixedYAxis(0,1);
292 _ui->likelihoodPlot->showLegend(
false);
296 _ui->rawLikelihoodPlot->showLegend(
false);
302 connect(
_ui->widget_mapVisibility, SIGNAL(visibilityChanged(
int,
bool)),
this, SLOT(
updateNodeVisibility(
int,
bool)));
305 connect(
_ui->actionExit, SIGNAL(triggered()),
this, SLOT(close()));
306 qRegisterMetaType<MainWindow::State>(
"MainWindow::State");
309 qRegisterMetaType<rtabmap::RtabmapEvent3DMap>(
"rtabmap::RtabmapEvent3DMap");
311 qRegisterMetaType<rtabmap::RtabmapGlobalPathEvent>(
"rtabmap::RtabmapGlobalPathEvent");
317 _ui->menuShow_view->addAction(
_ui->dockWidget_imageView->toggleViewAction());
318 _ui->menuShow_view->addAction(
_ui->dockWidget_posterior->toggleViewAction());
319 _ui->menuShow_view->addAction(
_ui->dockWidget_likelihood->toggleViewAction());
320 _ui->menuShow_view->addAction(
_ui->dockWidget_rawlikelihood->toggleViewAction());
321 _ui->menuShow_view->addAction(
_ui->dockWidget_statsV2->toggleViewAction());
322 _ui->menuShow_view->addAction(
_ui->dockWidget_console->toggleViewAction());
323 _ui->menuShow_view->addAction(
_ui->dockWidget_cloudViewer->toggleViewAction());
324 _ui->menuShow_view->addAction(
_ui->dockWidget_loopClosureViewer->toggleViewAction());
325 _ui->menuShow_view->addAction(
_ui->dockWidget_mapVisibility->toggleViewAction());
326 _ui->menuShow_view->addAction(
_ui->dockWidget_graphViewer->toggleViewAction());
327 _ui->menuShow_view->addAction(
_ui->dockWidget_odometry->toggleViewAction());
328 _ui->menuShow_view->addAction(
_ui->toolBar->toggleViewAction());
329 _ui->toolBar->setWindowTitle(tr(
"File toolbar"));
330 _ui->menuShow_view->addAction(
_ui->toolBar_2->toggleViewAction());
331 _ui->toolBar_2->setWindowTitle(tr(
"Control toolbar"));
332 QAction * a =
_ui->menuShow_view->addAction(
"Progress dialog");
333 a->setCheckable(
false);
335 QAction * statusBarAction =
_ui->menuShow_view->addAction(
"Status bar");
336 statusBarAction->setCheckable(
true);
337 statusBarAction->setChecked(statusBarShown);
338 connect(statusBarAction, SIGNAL(toggled(
bool)), this->statusBar(), SLOT(setVisible(
bool)));
341 connect(
_ui->actionSave_GUI_config, SIGNAL(triggered()),
this, SLOT(
saveConfigGUI()));
342 connect(
_ui->actionNew_database, SIGNAL(triggered()),
this, SLOT(
newDatabase()));
343 connect(
_ui->actionOpen_database, SIGNAL(triggered()),
this, SLOT(
openDatabase()));
344 connect(
_ui->actionClose_database, SIGNAL(triggered()),
this, SLOT(
closeDatabase()));
345 connect(
_ui->actionEdit_database, SIGNAL(triggered()),
this, SLOT(
editDatabase()));
349 connect(
_ui->actionDump_the_memory, SIGNAL(triggered()),
this, SLOT(
dumpTheMemory()));
350 connect(
_ui->actionDump_the_prediction_matrix, SIGNAL(triggered()),
this, SLOT(
dumpThePrediction()));
351 connect(
_ui->actionSend_goal, SIGNAL(triggered()),
this, SLOT(
sendGoal()));
352 connect(
_ui->actionSend_waypoints, SIGNAL(triggered()),
this, SLOT(
sendWaypoints()));
353 connect(
_ui->actionCancel_goal, SIGNAL(triggered()),
this, SLOT(
cancelGoal()));
354 connect(
_ui->actionLabel_current_location, SIGNAL(triggered()),
this, SLOT(
label()));
355 connect(
_ui->actionClear_cache, SIGNAL(triggered()),
this, SLOT(
clearTheCache()));
356 connect(
_ui->actionAbout, SIGNAL(triggered()),
_aboutDialog , SLOT(exec()));
357 connect(
_ui->actionHelp, SIGNAL(triggered()),
this , SLOT(
openHelp()));
358 connect(
_ui->actionPrint_loop_closure_IDs_to_console, SIGNAL(triggered()),
this, SLOT(
printLoopClosureIds()));
360 connect(
_ui->actionRaw_format_txt, SIGNAL(triggered()),
this , SLOT(
exportPosesRaw()));
362 connect(
_ui->actionKITTI_format_txt, SIGNAL(triggered()),
this , SLOT(
exportPosesKITTI()));
365 connect(
_ui->actionDelete_memory, SIGNAL(triggered()),
this , SLOT(
deleteMemory()));
371 connect(
_ui->actionDefault_views, SIGNAL(triggered(
bool)),
this, SLOT(
setDefaultViews()));
373 connect(
_ui->actionScreenshot, SIGNAL(triggered()),
this, SLOT(
takeScreenshot()));
383 connect(
_ui->actionSave_point_cloud, SIGNAL(triggered()),
this, SLOT(
exportClouds()));
384 connect(
_ui->actionExport_2D_Grid_map_bmp_png, SIGNAL(triggered()),
this, SLOT(
exportGridMap()));
385 connect(
_ui->actionExport_images_RGB_jpg_Depth_png, SIGNAL(triggered()),
this , SLOT(
exportImages()));
386 connect(
_ui->actionExport_cameras_in_Bundle_format_out, SIGNAL(triggered()), SLOT(
exportBundlerFormat()));
387 connect(
_ui->actionExport_octomap, SIGNAL(triggered()),
this, SLOT(
exportOctomap()));
388 connect(
_ui->actionView_high_res_point_cloud, SIGNAL(triggered()),
this, SLOT(
viewClouds()));
389 connect(
_ui->actionReset_Odometry, SIGNAL(triggered()),
this, SLOT(
resetOdometry()));
390 connect(
_ui->actionTrigger_a_new_map, SIGNAL(triggered()),
this, SLOT(
triggerNewMap()));
391 connect(
_ui->actionData_recorder, SIGNAL(triggered()),
this, SLOT(
dataRecorder()));
392 connect(
_ui->actionPost_processing, SIGNAL(triggered()),
this, SLOT(
postProcessing()));
393 connect(
_ui->actionDepth_Calibration, SIGNAL(triggered()),
this, SLOT(
depthCalibration()));
395 _ui->actionPause->setShortcut(Qt::Key_Space);
396 _ui->actionSave_GUI_config->setShortcut(QKeySequence::Save);
399 this->addAction(
_ui->actionSave_GUI_config);
400 _ui->actionReset_Odometry->setEnabled(
false);
401 _ui->actionPost_processing->setEnabled(
false);
402 _ui->actionAnchor_clouds_to_ground_truth->setEnabled(
false);
404 QToolButton* toolButton =
new QToolButton(
this);
405 toolButton->setMenu(
_ui->menuSelect_source);
406 toolButton->setPopupMode(QToolButton::InstantPopup);
407 toolButton->setIcon(QIcon(
":images/kinect_xbox_360.png"));
408 toolButton->setToolTip(
"Select sensor driver");
409 _ui->toolBar->addWidget(toolButton)->setObjectName(
"toolbar_source");
411 #if defined(Q_WS_MAC) || defined(Q_WS_WIN) 414 _ui->menuEdit->removeAction(
_ui->actionOpen_working_directory);
419 connect(
_ui->actionUsbCamera, SIGNAL(triggered()),
this, SLOT(
selectStream()));
420 connect(
_ui->actionOpenNI_PCL, SIGNAL(triggered()),
this, SLOT(
selectOpenni()));
421 connect(
_ui->actionOpenNI_PCL_ASUS, SIGNAL(triggered()),
this, SLOT(
selectOpenni()));
423 connect(
_ui->actionOpenNI_CV, SIGNAL(triggered()),
this, SLOT(
selectOpenniCv()));
425 connect(
_ui->actionOpenNI2, SIGNAL(triggered()),
this, SLOT(
selectOpenni2()));
426 connect(
_ui->actionOpenNI2_kinect, SIGNAL(triggered()),
this, SLOT(
selectOpenni2()));
427 connect(
_ui->actionOpenNI2_sense, SIGNAL(triggered()),
this, SLOT(
selectOpenni2()));
429 connect(
_ui->actionKinect_for_Windows_SDK_v2, SIGNAL(triggered()),
this, SLOT(
selectK4W2()));
430 connect(
_ui->actionRealSense_R200, SIGNAL(triggered()),
this, SLOT(
selectRealSense()));
431 connect(
_ui->actionRealSense_ZR300, SIGNAL(triggered()),
this, SLOT(
selectRealSense()));
457 QActionGroup * modeGrp =
new QActionGroup(
this);
458 modeGrp->addAction(
_ui->actionSLAM_mode);
459 modeGrp->addAction(
_ui->actionLocalization_mode);
467 qRegisterMetaType<PreferencesDialog::PANEL_FLAGS>(
"PreferencesDialog::PANEL_FLAGS");
469 qRegisterMetaType<rtabmap::ParametersMap>(
"rtabmap::ParametersMap");
486 connect(
_ui->toolBar->toggleViewAction(), SIGNAL(toggled(
bool)),
this, SLOT(
configGUIModified()));
487 connect(
_ui->toolBar, SIGNAL(orientationChanged(Qt::Orientation)),
this, SLOT(
configGUIModified()));
488 connect(statusBarAction, SIGNAL(toggled(
bool)),
this, SLOT(
configGUIModified()));
489 QList<QDockWidget*> dockWidgets = this->findChildren<QDockWidget*>();
490 for(
int i=0; i<dockWidgets.size(); ++i)
492 connect(dockWidgets[i], SIGNAL(dockLocationChanged(Qt::DockWidgetArea)),
this, SLOT(
configGUIModified()));
493 connect(dockWidgets[i]->toggleViewAction(), SIGNAL(toggled(
bool)),
this, SLOT(
configGUIModified()));
495 connect(
_ui->dockWidget_graphViewer->toggleViewAction(), SIGNAL(triggered()),
this, SLOT(
updateGraphView()));
497 _ui->dockWidget_posterior->installEventFilter(
this);
498 _ui->dockWidget_likelihood->installEventFilter(
this);
499 _ui->dockWidget_rawlikelihood->installEventFilter(
this);
500 _ui->dockWidget_statsV2->installEventFilter(
this);
501 _ui->dockWidget_console->installEventFilter(
this);
502 _ui->dockWidget_loopClosureViewer->installEventFilter(
this);
503 _ui->dockWidget_mapVisibility->installEventFilter(
this);
504 _ui->dockWidget_graphViewer->installEventFilter(
this);
505 _ui->dockWidget_odometry->installEventFilter(
this);
506 _ui->dockWidget_cloudViewer->installEventFilter(
this);
507 _ui->dockWidget_imageView->installEventFilter(
this);
521 qRegisterMetaType<rtabmap::Statistics>(
"rtabmap::Statistics");
524 qRegisterMetaType<rtabmap::CameraInfo>(
"rtabmap::CameraInfo");
527 qRegisterMetaType<rtabmap::OdometryEvent>(
"rtabmap::OdometryEvent");
536 _ui->statsToolBox->setNewFigureMaxItems(50);
549 if(
_ui->statsToolBox->findChildren<
StatItem*>().size() == 0)
552 for(std::map<std::string, float>::const_iterator iter = statistics.begin(); iter != statistics.end(); ++iter)
555 if(!QString((*iter).first.c_str()).contains(
"Gt/"))
557 _ui->statsToolBox->updateStat(QString((*iter).first.c_str()).replace(
'_',
' '),
false);
562 _ui->statsToolBox->updateStat(
"Planning/From/",
false);
563 _ui->statsToolBox->updateStat(
"Planning/Time/ms",
false);
564 _ui->statsToolBox->updateStat(
"Planning/Goal/",
false);
565 _ui->statsToolBox->updateStat(
"Planning/Poses/",
false);
566 _ui->statsToolBox->updateStat(
"Planning/Length/m",
false);
568 _ui->statsToolBox->updateStat(
"Camera/Time capturing/ms",
false);
569 _ui->statsToolBox->updateStat(
"Camera/Time decimation/ms",
false);
570 _ui->statsToolBox->updateStat(
"Camera/Time disparity/ms",
false);
571 _ui->statsToolBox->updateStat(
"Camera/Time mirroring/ms",
false);
572 _ui->statsToolBox->updateStat(
"Camera/Time scan from depth/ms",
false);
574 _ui->statsToolBox->updateStat(
"Odometry/ID/",
false);
575 _ui->statsToolBox->updateStat(
"Odometry/Features/",
false);
576 _ui->statsToolBox->updateStat(
"Odometry/Matches/",
false);
577 _ui->statsToolBox->updateStat(
"Odometry/MatchesRatio/",
false);
578 _ui->statsToolBox->updateStat(
"Odometry/Inliers/",
false);
579 _ui->statsToolBox->updateStat(
"Odometry/InliersRatio/",
false);
580 _ui->statsToolBox->updateStat(
"Odometry/ICPInliersRatio/",
false);
581 _ui->statsToolBox->updateStat(
"Odometry/ICPRotation/rad",
false);
582 _ui->statsToolBox->updateStat(
"Odometry/ICPTranslation/m",
false);
583 _ui->statsToolBox->updateStat(
"Odometry/ICPStructuralComplexity/",
false);
584 _ui->statsToolBox->updateStat(
"Odometry/StdDevLin/",
false);
585 _ui->statsToolBox->updateStat(
"Odometry/StdDevAng/",
false);
586 _ui->statsToolBox->updateStat(
"Odometry/VarianceLin/",
false);
587 _ui->statsToolBox->updateStat(
"Odometry/VarianceAng/",
false);
588 _ui->statsToolBox->updateStat(
"Odometry/TimeEstimation/ms",
false);
589 _ui->statsToolBox->updateStat(
"Odometry/TimeFiltering/ms",
false);
590 _ui->statsToolBox->updateStat(
"Odometry/LocalMapSize/",
false);
591 _ui->statsToolBox->updateStat(
"Odometry/LocalScanMapSize/",
false);
592 _ui->statsToolBox->updateStat(
"Odometry/LocalKeyFrames/",
false);
593 _ui->statsToolBox->updateStat(
"Odometry/localBundleOutliers/",
false);
594 _ui->statsToolBox->updateStat(
"Odometry/localBundleConstraints/",
false);
595 _ui->statsToolBox->updateStat(
"Odometry/localBundleTime/ms",
false);
596 _ui->statsToolBox->updateStat(
"Odometry/KeyFrameAdded/",
false);
597 _ui->statsToolBox->updateStat(
"Odometry/Interval/ms",
false);
598 _ui->statsToolBox->updateStat(
"Odometry/Speed/kph",
false);
599 _ui->statsToolBox->updateStat(
"Odometry/Distance/m",
false);
600 _ui->statsToolBox->updateStat(
"Odometry/Tx/m",
false);
601 _ui->statsToolBox->updateStat(
"Odometry/Ty/m",
false);
602 _ui->statsToolBox->updateStat(
"Odometry/Tz/m",
false);
603 _ui->statsToolBox->updateStat(
"Odometry/Troll/deg",
false);
604 _ui->statsToolBox->updateStat(
"Odometry/Tpitch/deg",
false);
605 _ui->statsToolBox->updateStat(
"Odometry/Tyaw/deg",
false);
606 _ui->statsToolBox->updateStat(
"Odometry/Px/m",
false);
607 _ui->statsToolBox->updateStat(
"Odometry/Py/m",
false);
608 _ui->statsToolBox->updateStat(
"Odometry/Pz/m",
false);
609 _ui->statsToolBox->updateStat(
"Odometry/Proll/deg",
false);
610 _ui->statsToolBox->updateStat(
"Odometry/Ppitch/deg",
false);
611 _ui->statsToolBox->updateStat(
"Odometry/Pyaw/deg",
false);
613 _ui->statsToolBox->updateStat(
"GUI/Refresh odom/ms",
false);
614 _ui->statsToolBox->updateStat(
"GUI/RGB-D cloud/ms",
false);
615 _ui->statsToolBox->updateStat(
"GUI/Graph Update/ms",
false);
616 #ifdef RTABMAP_OCTOMAP 617 _ui->statsToolBox->updateStat(
"GUI/Octomap Update/ms",
false);
618 _ui->statsToolBox->updateStat(
"GUI/Octomap Rendering/ms",
false);
620 _ui->statsToolBox->updateStat(
"GUI/Grid Update/ms",
false);
621 _ui->statsToolBox->updateStat(
"GUI/Grid Rendering/ms",
false);
622 _ui->statsToolBox->updateStat(
"GUI/Refresh stats/ms",
false);
623 _ui->statsToolBox->updateStat(
"GUI/Cache Data Size/MB",
false);
624 _ui->statsToolBox->updateStat(
"GUI/Cache Clouds Size/MB",
false);
625 #ifdef RTABMAP_OCTOMAP 626 _ui->statsToolBox->updateStat(
"GUI/Octomap Size/MB",
false);
653 #ifdef RTABMAP_OCTOMAP 664 qobject_cast<QHBoxLayout *>(
_ui->layout_imageview->layout())->setDirection(QBoxLayout::TopToBottom);
668 qobject_cast<QHBoxLayout *>(
_ui->layout_imageview->layout())->setDirection(QBoxLayout::LeftToRight);
707 bool processStopped =
true;
720 processStopped =
false;
728 if(this->isWindowModified())
730 QMessageBox::Button b=QMessageBox::question(
this,
732 tr(
"There are unsaved changed settings. Save them?"),
733 QMessageBox::Save | QMessageBox::Cancel | QMessageBox::Discard);
734 if(b == QMessageBox::Save)
738 else if(b != QMessageBox::Discard)
750 _ui->statsToolBox->closeFigures();
752 _ui->dockWidget_imageView->close();
753 _ui->dockWidget_likelihood->close();
754 _ui->dockWidget_rawlikelihood->close();
755 _ui->dockWidget_posterior->close();
756 _ui->dockWidget_statsV2->close();
757 _ui->dockWidget_console->close();
758 _ui->dockWidget_cloudViewer->close();
759 _ui->dockWidget_loopClosureViewer->close();
760 _ui->dockWidget_mapVisibility->close();
761 _ui->dockWidget_graphViewer->close();
762 _ui->dockWidget_odometry->close();
766 UERROR(
"Camera must be already deleted here!");
777 UERROR(
"OdomThread must be already deleted here!");
792 if(anEvent->
getClassName().compare(
"RtabmapEvent") == 0)
796 int highestHypothesisId = int(
uValue(stats.
data(), Statistics::kLoopHighest_hypothesis_id(), 0.0f));
797 int proximityClosureId = int(
uValue(stats.
data(), Statistics::kProximitySpace_last_detection_id(), 0.0f));
798 bool rejectedHyp = bool(
uValue(stats.
data(), Statistics::kLoopRejectedHypothesis(), 0.0f));
799 float highestHypothesisValue =
uValue(stats.
data(), Statistics::kLoopHighest_hypothesis_value(), 0.0f);
801 _ui->actionPause_on_match->isChecked())
804 highestHypothesisId > 0 &&
806 _ui->actionPause_when_a_loop_hypothesis_is_rejected->isChecked() &&
809 (proximityClosureId > 0 &&
810 _ui->actionPause_on_local_loop_detection->isChecked()))
816 QMetaObject::invokeMethod(
this,
"beep");
828 else if(anEvent->
getClassName().compare(
"RtabmapEventInit") == 0)
836 else if(anEvent->
getClassName().compare(
"RtabmapEvent3DMap") == 0)
841 else if(anEvent->
getClassName().compare(
"RtabmapGlobalPathEvent") == 0)
846 else if(anEvent->
getClassName().compare(
"RtabmapLabelErrorEvent") == 0)
851 else if(anEvent->
getClassName().compare(
"RtabmapGoalStatusEvent") == 0)
855 else if(anEvent->
getClassName().compare(
"CameraEvent") == 0)
862 QMetaObject::invokeMethod(
this,
"beep");
886 else if(anEvent->
getClassName().compare(
"OdometryEvent") == 0)
905 else if(anEvent->
getClassName().compare(
"ULogEvent") == 0)
910 QMetaObject::invokeMethod(
_ui->dockWidget_console,
"show");
917 QMetaObject::invokeMethod(
this,
"beep");
958 if(
_ui->imageView_odometry->toolTip().isEmpty())
960 _ui->imageView_odometry->setToolTip(
961 "Background Color Code:\n" 962 " Dark Red = Odometry Lost\n" 963 " Dark Yellow = Low Inliers\n" 964 "Feature Color code:\n" 966 " Yellow = Not matched features from previous frame(s)\n" 972 bool lostStateChanged =
false;
979 _ui->imageView_odometry->setBackgroundColor(Qt::darkRed);
991 _ui->imageView_odometry->setBackgroundColor(Qt::darkYellow);
998 _ui->imageView_odometry->setBackgroundColor(
_ui->imageView_odometry->getDefaultBackgroundColor());
1001 if(!pose.
isNull() && (
_ui->dockWidget_cloudViewer->isVisible() ||
_ui->graphicsView_graphView->isVisible()))
1006 if(
_ui->dockWidget_cloudViewer->isVisible())
1008 bool cloudUpdated =
false;
1009 bool scanUpdated =
false;
1010 bool featuresUpdated =
false;
1020 pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud;
1021 pcl::IndicesPtr indices(
new std::vector<int>);
1036 pcl::PointCloud<pcl::PointXYZRGB>::Ptr output(
new pcl::PointCloud<pcl::PointXYZRGB>);
1040 Eigen::Vector3f viewpoint(0.0
f,0.0
f,0.0
f);
1058 Eigen::Vector3f(pose.
x(), pose.
y(), pose.
z()) + viewpoint);
1063 pcl::TextureMesh::Ptr textureMesh(
new pcl::TextureMesh);
1064 pcl::toPCLPointCloud2(*cloud, textureMesh->cloud);
1065 textureMesh->tex_polygons.push_back(polygons);
1066 int w = cloud->width;
1067 int h = cloud->height;
1069 textureMesh->tex_coordinates.resize(1);
1070 int nPoints = (int)(textureMesh->cloud.data.size()/textureMesh->cloud.point_step);
1071 textureMesh->tex_coordinates[0].resize(nPoints);
1072 for(
int i=0; i<nPoints; ++i)
1075 textureMesh->tex_coordinates[0][i] = Eigen::Vector2f(
1076 float(i % w) /
float(w),
1077 float(h - i / w) /
float(h));
1080 pcl::TexMaterial mesh_material;
1081 mesh_material.tex_d = 1.0f;
1082 mesh_material.tex_Ns = 75.0f;
1083 mesh_material.tex_illum = 1;
1085 mesh_material.tex_name =
"material_odom";
1086 mesh_material.tex_file =
"";
1087 textureMesh->tex_materials.push_back(mesh_material);
1091 UERROR(
"Adding cloudOdom to viewer failed!");
1096 UERROR(
"Adding cloudOdom to viewer failed!");
1104 UERROR(
"Adding cloudOdom to viewer failed!");
1112 cloudUpdated =
true;
1123 pcl::PointCloud<pcl::PointNormal>::Ptr cloud;
1128 UERROR(
"Adding scanMapOdom to viewer failed!");
1155 pcl::PointCloud<pcl::PointNormal>::Ptr cloud;
1165 UERROR(
"Adding scanOdom to viewer failed!");
1183 pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud(
new pcl::PointCloud<pcl::PointXYZRGB>);
1186 for(std::map<int, cv::Point3f>::const_iterator iter=odom.
info().
localMap.begin(); iter!=odom.
info().
localMap.end(); ++iter)
1191 (*cloud)[i].x = iter->second.x;
1192 (*cloud)[i].y = iter->second.y;
1193 (*cloud)[i].z = iter->second.z;
1197 (*cloud)[i].r = inlier?0:255;
1198 (*cloud)[i].g = 255;
1212 featuresUpdated =
true;
1218 for(QMap<std::string, Transform>::iterator iter = addedFrustums.begin(); iter!=addedFrustums.end(); ++iter)
1220 std::list<std::string> splitted =
uSplitNumChar(iter.key());
1221 if(splitted.size() == 2)
1223 int id = std::atoi(splitted.back().c_str());
1224 if(splitted.front().compare(
"f_odom_") == 0 &&
1234 std::string frustumId =
uFormat(
"f_odom_%d", iter->first);
1245 QColor color = Qt::yellow;
1291 if(
_ui->graphicsView_graphView->isVisible())
1296 _ui->graphicsView_graphView->update();
1300 if(
_ui->dockWidget_odometry->isVisible() &&
1303 if(
_ui->imageView_odometry->isFeaturesShown())
1309 std::multimap<int, cv::KeyPoint> kpInliers;
1314 _ui->imageView_odometry->setFeatures(
1321 _ui->imageView_odometry->setFeatures(
1332 std::vector<cv::KeyPoint> kpts;
1334 _ui->imageView_odometry->setFeatures(
1342 bool monoInitialization =
false;
1345 monoInitialization =
true;
1348 _ui->imageView_odometry->clearLines();
1349 if(lost && !monoInitialization)
1351 if(lostStateChanged)
1358 _ui->imageView_odometry->setImageShown(
true);
1359 _ui->imageView_odometry->setImageDepthShown(
true);
1363 if(lostStateChanged)
1396 if(
_ui->imageView_odometry->isFeaturesShown() ||
_ui->imageView_odometry->isLinesShown())
1403 if(
_ui->imageView_odometry->isFeaturesShown() && inliers.find(i) != inliers.end())
1405 _ui->imageView_odometry->setFeatureColor(i, Qt::green);
1407 if(
_ui->imageView_odometry->isLinesShown())
1409 _ui->imageView_odometry->addLine(
1414 inliers.find(i) != inliers.end()?Qt::blue:Qt::yellow);
1425 _ui->imageView_odometry->update();
1538 QTime time, totalTime;
1548 int refMapId = -1, loopMapId = -1;
1553 int highestHypothesisId =
static_cast<float>(
uValue(stat.
data(), Statistics::kLoopHighest_hypothesis_id(), 0.0f));
1560 _ui->label_refId->setText(QString(
"New ID = %1 [%2]").arg(stat.
refImageId()).arg(refMapId));
1564 float totalTime =
static_cast<float>(
uValue(stat.
data(), Statistics::kTimingTotal(), 0.0f));
1571 bool highestHypothesisIsSaved = (bool)
uValue(stat.
data(), Statistics::kLoopHypothesis_reactivated(), 0.0f);
1573 bool smallMovement = (bool)
uValue(stat.
data(), Statistics::kMemorySmall_movement(), 0.0f);
1575 bool fastMovement = (bool)
uValue(stat.
data(), Statistics::kMemoryFast_movement(), 0.0f);
1587 if(smallMovement || fastMovement)
1595 unsigned int count = 0;
1596 for(std::multimap<int, cv::Point3f>::const_iterator jter=signature.
getWords3().upper_bound(-1); jter!=signature.
getWords3().end(); ++jter)
1612 _ui->imageView_source->clear();
1613 _ui->imageView_loopClosure->clear();
1615 _ui->imageView_source->setBackgroundColor(
_ui->imageView_source->getDefaultBackgroundColor());
1616 _ui->imageView_loopClosure->setBackgroundColor(
_ui->imageView_loopClosure->getDefaultBackgroundColor());
1618 _ui->label_matchId->clear();
1621 int rehearsalMerged = (int)
uValue(stat.
data(), Statistics::kMemoryRehearsal_merged(), 0.0f);
1622 bool rehearsedSimilarity = (float)
uValue(stat.
data(), Statistics::kMemoryRehearsal_id(), 0.0f) != 0.0
f;
1623 int proximityTimeDetections = (int)
uValue(stat.
data(), Statistics::kProximityTime_detections(), 0.0f);
1624 bool scanMatchingSuccess = (bool)
uValue(stat.
data(), Statistics::kNeighborLinkRefiningAccepted(), 0.0f);
1625 _ui->label_stats_imageNumber->setText(QString(
"%1 [%2]").arg(stat.
refImageId()).arg(refMapId));
1627 if(rehearsalMerged > 0)
1629 _ui->imageView_source->setBackgroundColor(Qt::blue);
1631 else if(proximityTimeDetections > 0)
1633 _ui->imageView_source->setBackgroundColor(Qt::darkYellow);
1635 else if(scanMatchingSuccess)
1637 _ui->imageView_source->setBackgroundColor(Qt::darkCyan);
1639 else if(rehearsedSimilarity)
1641 _ui->imageView_source->setBackgroundColor(Qt::darkBlue);
1643 else if(smallMovement)
1645 _ui->imageView_source->setBackgroundColor(Qt::gray);
1647 else if(fastMovement)
1649 _ui->imageView_source->setBackgroundColor(Qt::magenta);
1652 if(
_ui->label_refId->toolTip().isEmpty())
1654 _ui->label_refId->setToolTip(
1655 "Background Color Code:\n" 1656 " Blue = Weight Update Merged\n" 1657 " Dark Blue = Weight Update\n" 1658 " Dark Yellow = Proximity Detection in Time\n" 1659 " Dark Cyan = Neighbor Link Refined\n" 1660 " Gray = Small Movement\n" 1661 " Magenta = Fast Movement\n" 1662 "Feature Color code:\n" 1664 " Yellow = New but Not Unique\n" 1665 " Red = In Vocabulary\n" 1666 " Blue = In Vocabulary and in Previous Signature\n" 1667 " Pink = In Vocabulary and in Loop Closure Signature\n" 1668 " Gray = Not Quantized to Vocabulary");
1671 if(
_ui->label_matchId->toolTip().isEmpty())
1673 _ui->label_matchId->setToolTip(
1674 "Background Color Code:\n" 1675 " Green = Accepted Loop Closure Detection\n" 1676 " Red = Rejected Loop Closure Detection\n" 1677 " Yellow = Proximity Detection in Space\n" 1678 "Feature Color code:\n" 1679 " Red = In Vocabulary\n" 1680 " Pink = In Vocabulary and in Loop Closure Signature\n" 1681 " Gray = Not Quantized to Vocabulary");
1684 UDEBUG(
"time= %d ms", time.restart());
1686 int rejectedHyp = bool(
uValue(stat.
data(), Statistics::kLoopRejectedHypothesis(), 0.0f));
1687 float highestHypothesisValue =
uValue(stat.
data(), Statistics::kLoopHighest_hypothesis_value(), 0.0f);
1690 int shownLoopId = 0;
1696 _ui->imageView_loopClosure->setBackgroundColor(Qt::green);
1697 _ui->label_stats_loopClosuresDetected->setText(QString::number(
_ui->label_stats_loopClosuresDetected->text().toInt() + 1));
1698 if(highestHypothesisIsSaved)
1700 _ui->label_stats_loopClosuresReactivatedDetected->setText(QString::number(
_ui->label_stats_loopClosuresReactivatedDetected->text().toInt() + 1));
1702 _ui->label_matchId->setText(QString(
"Match ID = %1 [%2]").arg(stat.
loopClosureId()).arg(loopMapId));
1707 _ui->imageView_loopClosure->setBackgroundColor(Qt::yellow);
1708 _ui->label_matchId->setText(QString(
"Local match = %1 [%2]").arg(stat.
proximityDetectionId()).arg(loopMapId));
1716 _ui->imageView_loopClosure->setBackgroundColor(Qt::red);
1717 _ui->label_stats_loopClosuresRejected->setText(QString::number(
_ui->label_stats_loopClosuresRejected->text().toInt() + 1));
1718 _ui->label_matchId->setText(QString(
"Loop hypothesis %1 rejected!").arg(highestHypothesisId));
1726 _ui->label_matchId->setText(QString(
"Highest hypothesis (%1)").arg(highestHypothesisId));
1737 loopSignature = iter.value();
1753 qimageThread.
start();
1754 qimageLoopThread.start();
1755 qimageThread.join();
1756 qimageLoopThread.join();
1757 QImage img = qimageThread.getQImage();
1758 QImage lcImg = qimageLoopThread.getQImage();
1759 UDEBUG(
"time= %d ms", time.restart());
1763 _ui->imageView_source->setImage(img);
1784 if(sceneRect.isValid())
1786 _ui->imageView_source->setSceneRect(sceneRect);
1791 _ui->imageView_loopClosure->setImage(lcImg);
1797 if(
_ui->imageView_loopClosure->sceneRect().isNull())
1799 _ui->imageView_loopClosure->setSceneRect(
_ui->imageView_source->sceneRect());
1803 UDEBUG(
"time= %d ms", time.restart());
1808 UDEBUG(
"time= %d ms", time.restart());
1820 signature.
setPose(loopClosureTransform);
1822 if(
_ui->dockWidget_loopClosureViewer->isVisible())
1826 UINFO(
"Updating loop closure cloud view time=%fs", loopTimer.
elapsed());
1830 UDEBUG(
"time= %d ms", time.restart());
1835 if(!stat.
posterior().empty() &&
_ui->dockWidget_posterior->isVisible())
1846 if(!stat.
likelihood().empty() &&
_ui->dockWidget_likelihood->isVisible())
1850 if(!stat.
rawLikelihood().empty() &&
_ui->dockWidget_rawlikelihood->isVisible())
1856 const std::map<std::string, float> & statistics = stat.
data();
1857 for(std::map<std::string, float>::const_iterator iter = statistics.begin(); iter != statistics.end(); ++iter)
1863 UDEBUG(
"time= %d ms", time.restart());
1869 if(stat.
poses().size())
1872 std::map<int, int> mapIds;
1873 std::map<int, Transform> groundTruth;
1874 std::map<int, std::string> labels;
1877 mapIds.insert(std::make_pair(iter->first, iter->second.mapId()));
1878 if(!iter->second.getGroundTruthPose().isNull())
1880 groundTruth.insert(std::make_pair(iter->first, iter->second.getGroundTruthPose()));
1882 if(!iter->second.getLabel().empty())
1884 labels.insert(std::make_pair(iter->first, iter->second.getLabel()));
1888 std::map<int, Transform> poses = stat.
poses();
1889 UDEBUG(
"time= %d ms", time.restart());
1895 std::map<int, Signature>::const_iterator iter = stat.
getSignatures().find(poses.rbegin()->first);
1898 if(iter->second.sensorData().cameraModels().size() && !iter->second.sensorData().cameraModels()[0].localTransform().isNull())
1902 else if(!iter->second.sensorData().stereoCameraModel().localTransform().isNull())
1908 if(
_ui->graphicsView_graphView->isVisible())
1910 _ui->graphicsView_graphView->updateReferentialPosition(poses.rbegin()->second);
1916 if(poses.find(stat.
refImageId())!=poses.end())
1918 poses.insert(std::make_pair(-1, poses.at(stat.
refImageId())));
1921 if(groundTruth.find(stat.
refImageId())!=groundTruth.end())
1923 groundTruth.insert(std::make_pair(-1, groundTruth.at(stat.
refImageId())));
1928 std::map<std::string, float> updateCloudSats;
1940 UDEBUG(
"time= %d ms", time.restart());
1942 for(std::map<std::string, float>::iterator iter=updateCloudSats.begin(); iter!=updateCloudSats.end(); ++iter)
1949 if(
_ui->graphicsView_graphView->isVisible())
1955 _ui->graphicsView_graphView->updatePosterior(stat.
posterior());
1971 _ui->graphicsView_graphView->updateLocalPath(stat.
localPath());
1975 _ui->graphicsView_graphView->setGlobalPath(std::vector<std::pair<int, Transform> >());
2010 _ui->label_stats_loopClosuresDetected->setText(QString::number(
_ui->label_stats_loopClosuresDetected->text().toInt() + 1));
2011 _ui->label_matchId->setText(QString(
"Match ID = %1 [%2]").arg(stat.
loopClosureId()).arg(loopMapId));
2015 _ui->label_matchId->clear();
2017 float elapsedTime =
static_cast<float>(totalTime.elapsed());
2018 UINFO(
"Updating GUI time = %fs", elapsedTime/1000.0
f);
2033 #ifdef RTABMAP_OCTOMAP 2049 const std::map<int, Transform> & posesIn,
2050 const std::multimap<int, Link> & constraints,
2051 const std::map<int, int> & mapIdsIn,
2052 const std::map<int, std::string> & labels,
2053 const std::map<int, Transform> & groundTruths,
2054 bool verboseProgress,
2055 std::map<std::string, float> * stats)
2058 UDEBUG(
"posesIn=%d constraints=%d mapIdsIn=%d labelsIn=%d",
2059 (
int)posesIn.size(), (int)constraints.size(), (int)mapIdsIn.size(), (int)labels.size());
2078 std::map<int, Transform> poses;
2079 std::map<int, int> mapIds;
2084 bool hasNeg = posesIn.find(-1) != posesIn.end();
2087 std::map<int, Transform> posesInTmp = posesIn;
2088 posesInTmp.erase(-1);
2095 for(std::map<int, Transform>::iterator iter= poses.begin(); iter!=poses.end(); ++iter)
2097 std::map<int, int>::const_iterator jter = mapIdsIn.find(iter->first);
2098 if(jter!=mapIdsIn.end())
2100 mapIds.insert(*jter);
2104 UERROR(
"map id of node %d not found!", iter->first);
2110 poses.insert(*posesIn.find(-1));
2115 _progressDialog->
appendText(tr(
"Map update: %1 nodes shown of %2 (cloud filtering is on)").arg(poses.size()).arg(posesIn.size()));
2116 QApplication::processEvents();
2125 std::map<int, bool> posesMask;
2126 for(std::map<int, Transform>::const_iterator iter = posesIn.begin(); iter!=posesIn.end(); ++iter)
2128 posesMask.insert(posesMask.end(), std::make_pair(iter->first, poses.find(iter->first) != poses.end()));
2130 _ui->widget_mapVisibility->setMap(posesIn, posesMask);
2132 if(groundTruths.size() &&
_ui->actionAnchor_clouds_to_ground_truth->isChecked())
2134 for(std::map<int, Transform>::iterator iter = poses.begin(); iter!=poses.end(); ++iter)
2136 std::map<int, Transform>::const_iterator gtIter = groundTruths.find(iter->first);
2137 if(gtIter!=groundTruths.end())
2139 iter->second = gtIter->second;
2143 UWARN(
"Not found ground truth pose for node %d", iter->first);
2149 _ui->actionAnchor_clouds_to_ground_truth->setChecked(
false);
2153 if(maxNodes > 0 && poses.size()>1)
2156 std::map<int, Transform> nearestPoses;
2157 nearestPoses.insert(*poses.rbegin());
2158 for(std::vector<int>::iterator iter=nodes.begin(); iter!=nodes.end(); ++iter)
2160 std::map<int, Transform>::iterator pter = poses.find(*iter);
2161 if(pter != poses.end())
2163 nearestPoses.insert(*pter);
2167 for(std::map<int, Transform>::iterator iter=poses.begin(); iter!=poses.end(); ++iter)
2173 nearestPoses.insert(*iter);
2179 UDEBUG(
"Update map with %d locations", poses.size());
2182 for(std::map<int, Transform>::const_iterator iter = poses.begin(); iter!=poses.end(); ++iter)
2184 if(!iter->second.isNull())
2186 std::string cloudName =
uFormat(
"cloud%d", iter->first);
2190 viewerClouds.remove(cloudName);
2199 if(viewerClouds.contains(cloudName))
2204 if(tCloud.
isNull() || iter->second != tCloud)
2208 UERROR(
"Updating pose cloud %d failed!", iter->first);
2220 std::pair<pcl::PointCloud<pcl::PointXYZRGB>::Ptr, pcl::IndicesPtr> createdCloud = this->
createAndAddCloudToMap(iter->first, iter->second,
uValue(mapIds, iter->first, -1));
2227 else if(viewerClouds.contains(cloudName))
2233 std::string scanName =
uFormat(
"scan%d", iter->first);
2236 viewerClouds.remove(scanName);
2241 if(viewerClouds.contains(scanName))
2246 if(tScan.
isNull() || iter->second != tScan)
2250 UERROR(
"Updating pose scan %d failed!", iter->first);
2261 if(!jter->sensorData().laserScanCompressed().isEmpty() || !jter->sensorData().laserScanRaw().isEmpty())
2267 else if(viewerClouds.contains(scanName))
2273 bool updateGridMap =
2274 ((
_ui->graphicsView_graphView->isVisible() &&
_ui->graphicsView_graphView->isGridMapVisible()) ||
2277 bool updateOctomap =
false;
2278 #ifdef RTABMAP_OCTOMAP 2284 if(updateGridMap || updateOctomap)
2293 jter->sensorData().uncompressDataConst(0, 0, 0, 0, &ground, &obstacles, &empty);
2297 #ifdef RTABMAP_OCTOMAP 2300 if((ground.empty() || ground.channels() > 2) &&
2301 (obstacles.empty() || obstacles.channels() > 2))
2303 cv::Point3f viewpoint = jter->sensorData().gridViewPoint();
2306 else if(!ground.empty() || !obstacles.empty())
2308 UWARN(
"Node %d: Cannot update octomap with 2D occupancy grids.", iter->first);
2316 std::string featuresName =
uFormat(
"features%d", iter->first);
2319 viewerClouds.remove(featuresName);
2324 if(viewerClouds.contains(featuresName))
2329 if(tFeatures.
isNull() || iter->second != tFeatures)
2333 UERROR(
"Updating pose features %d failed!", iter->first);
2342 if(!jter->getWords3().empty())
2348 else if(viewerClouds.contains(featuresName))
2357 if(poses.size() < 200 || i % 100 == 0)
2359 QApplication::processEvents();
2372 for(QMap<std::string, Transform>::iterator iter = viewerClouds.begin(); iter!=viewerClouds.end(); ++iter)
2374 std::list<std::string> splitted =
uSplitNumChar(iter.key());
2376 if(splitted.size() == 2)
2378 id = std::atoi(splitted.back().c_str());
2379 if(splitted.front().at(splitted.front().size()-1) ==
'-')
2385 if(
id != 0 && poses.find(
id) == poses.end())
2389 UDEBUG(
"Hide %s", iter.key().c_str());
2398 stats->insert(std::make_pair(
"GUI/RGB-D cloud/ms", (
float)timer.
restart()*1000.0f));
2407 for(QMap<std::string, Transform>::iterator iter = addedFrustums.begin(); iter!=addedFrustums.end(); ++iter)
2409 std::list<std::string> splitted =
uSplitNumChar(iter.key());
2410 if(splitted.size() == 2)
2412 if((splitted.front().compare(
"f_") == 0 || splitted.front().compare(
"f_gt_") == 0))
2430 std::map<int, pcl::PointCloud<pcl::PointXYZ>::Ptr > graphs;
2438 std::map<int, pcl::PointCloud<pcl::PointXYZ>::Ptr >::iterator kter = graphs.find(mapId);
2439 if(kter == graphs.end())
2441 kter = graphs.insert(std::make_pair(mapId, pcl::PointCloud<pcl::PointXYZ>::Ptr(
new pcl::PointCloud<pcl::PointXYZ>))).first;
2443 pcl::PointXYZ pt(iter->second.x(), iter->second.y(), iter->second.z());
2444 kter->second->push_back(pt);
2450 std::string frustumId =
uFormat(
"f_%d", iter->first);
2464 QColor color = (Qt::GlobalColor)((mapId+3) % 12 + 7 );
2469 std::string gtFrustumId =
uFormat(
"f_gt_%d", iter->first);
2487 std::map<int, pcl::PointCloud<pcl::PointXYZ>::Ptr >::iterator kter = graphs.find(mapId);
2488 if(kter == graphs.end())
2490 kter = graphs.insert(std::make_pair(mapId, pcl::PointCloud<pcl::PointXYZ>::Ptr(
new pcl::PointCloud<pcl::PointXYZ>))).first;
2493 pcl::PointXYZ pt(t.
x(), t.
y(), t.
z());
2494 kter->second->push_back(pt);
2499 for(std::map<
int, pcl::PointCloud<pcl::PointXYZ>::Ptr >::iterator iter=graphs.begin(); iter!=graphs.end(); ++iter)
2501 QColor color = Qt::gray;
2502 if(iter->first >= 0)
2504 color = (Qt::GlobalColor)((iter->first+3) % 12 + 7 );
2512 UDEBUG(
"remove not used frustums");
2513 for(QMap<std::string, Transform>::iterator iter = addedFrustums.begin(); iter!=addedFrustums.end(); ++iter)
2515 std::list<std::string> splitted =
uSplitNumChar(iter.key());
2516 if(splitted.size() == 2)
2518 int id = std::atoi(splitted.back().c_str());
2519 if((splitted.front().compare(
"f_") == 0 || splitted.front().compare(
"f_gt_") == 0) &&
2531 UDEBUG(
"labels.size()=%d", (
int)labels.size());
2537 for(std::map<int, std::string>::const_iterator iter=labels.begin(); iter!=labels.end(); ++iter)
2539 if(posesIn.find(iter->first)!=posesIn.end())
2541 int mapId =
uValue(mapIdsIn, iter->first, -1);
2542 QColor color = Qt::gray;
2545 color = (Qt::GlobalColor)((mapId+3) % 12 + 7 );
2560 stats->insert(std::make_pair(
"GUI/Graph Update/ms", (
float)timer.
restart()*1000.0f));
2563 #ifdef RTABMAP_OCTOMAP 2571 UINFO(
"Octomap update time = %fs", time.
ticks());
2575 stats->insert(std::make_pair(
"GUI/Octomap Update/ms", (
float)timer.
restart()*1000.0f));
2587 pcl::IndicesPtr obstacles(
new std::vector<int>);
2589 if(obstacles->size())
2595 UINFO(
"Octomap show 3d map time = %fs", time.
ticks());
2600 stats->insert(std::make_pair(
"GUI/Octomap Rendering/ms", (
float)timer.
restart()*1000.0f));
2605 if(
_ui->graphicsView_graphView->isVisible())
2607 _ui->graphicsView_graphView->updateGraph(posesIn, constraints, mapIdsIn);
2611 for(std::map<int, Transform>::iterator iter=gtPoses.begin(); iter!=gtPoses.end(); ++iter)
2613 iter->second = mapToGt * iter->second;
2615 _ui->graphicsView_graphView->updateGTGraph(gtPoses);
2628 #ifdef RTABMAP_OCTOMAP 2643 stats->insert(std::make_pair(
"GUI/Grid Update/ms", (
float)timer.
restart()*1000.0f));
2657 if(
_ui->graphicsView_graphView->isVisible())
2659 _ui->graphicsView_graphView->updateMap(map8U, resolution, xMin, yMin);
2663 _ui->graphicsView_graphView->update();
2668 stats->insert(std::make_pair(
"GUI/Grid Rendering/ms", (
float)timer.
restart()*1000.0f));
2677 if(viewerClouds.contains(
"cloudOdom"))
2693 if(viewerClouds.contains(
"scanOdom"))
2709 if(viewerClouds.contains(
"scanMapOdom"))
2725 if(viewerClouds.contains(
"featuresOdom"))
2746 #ifdef RTABMAP_OCTOMAP 2749 _ui->actionExport_octomap->setEnabled(
false);
2761 std::string cloudName =
uFormat(
"cloud%d", nodeId);
2762 std::pair<pcl::PointCloud<pcl::PointXYZRGB>::Ptr, pcl::IndicesPtr> outputPair;
2765 UERROR(
"Cloud %d already added to map.", nodeId);
2772 UERROR(
"Node %d is not in the cache.", nodeId);
2778 if((!iter->sensorData().imageCompressed().empty() || !iter->sensorData().imageRaw().empty()) &&
2779 (!iter->sensorData().depthOrRightCompressed().empty() || !iter->sensorData().depthOrRightRaw().empty()))
2781 cv::Mat image, depth;
2785 bool rectifyOnlyFeatures = Parameters::defaultRtabmapRectifyOnlyFeatures();
2786 bool imagesAlreadyRectified = Parameters::defaultRtabmapImagesAlreadyRectified();
2787 Parameters::parse(allParameters, Parameters::kRtabmapRectifyOnlyFeatures(), rectifyOnlyFeatures);
2788 Parameters::parse(allParameters, Parameters::kRtabmapImagesAlreadyRectified(), imagesAlreadyRectified);
2789 if(rectifyOnlyFeatures && !imagesAlreadyRectified)
2797 cv::Mat rectifiedImages = data.
imageRaw().clone();
2803 for(
unsigned int i=0; i<data.
cameraModels().size(); ++i)
2812 UWARN(
"Initializing rectification maps for camera %d (only done for the first image received)...", i);
2814 UWARN(
"Initializing rectification maps for camera %d (only done for the first image received)... done!", i);
2820 rectifiedImage.copyTo(cv::Mat(rectifiedImages, cv::Rect(subImageWidth*i, 0, subImageWidth, data.
imageRaw().rows)));
2824 UWARN(
"Camera %d of data %d is not valid for rectification (%dx%d).",
2830 UINFO(
"Time rectification: %fs", time.
ticks());
2832 image = rectifiedImages;
2836 pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud;
2837 pcl::IndicesPtr indices(
new std::vector<int>);
2838 UASSERT_MSG(nodeId == -1 || nodeId == data.
id(),
uFormat(
"nodeId=%d data.id()=%d", nodeId, data.
id()).c_str());
2850 Eigen::Vector3f viewPoint(0.0
f,0.0
f,0.0
f);
2853 viewPoint[0] = data.
cameraModels()[0].localTransform().x();
2854 viewPoint[1] = data.
cameraModels()[0].localTransform().y();
2855 viewPoint[2] = data.
cameraModels()[0].localTransform().z();
2869 indices->resize(cloud->size());
2870 for(
unsigned int i=0; i<cloud->size(); ++i)
2877 if(indices->size() &&
2892 if(indices->size() &&
2903 pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr cloudWithNormals(
new pcl::PointCloud<pcl::PointXYZRGBNormal>);
2908 pcl::IndicesPtr beforeFiltering = indices;
2909 if( cloud->size() &&
2932 pcl::concatenateFields(*cloud, *normals, *cloudWithNormals);
2936 UWARN(
"Cloud subtraction with angle filtering is activated but " 2937 "cloud normal K search is 0. Subtraction is done with angle.");
2941 if(cloudWithNormals->size() &&
2968 UINFO(
"Time subtract filtering %d from %d -> %d (%fs)",
2970 (int)beforeFiltering->size(),
2971 (int)indices->size(),
2984 pcl::PointCloud<pcl::PointXYZRGB>::Ptr output;
3000 pcl::PointCloud<pcl::PointXYZRGB>::Ptr outputFiltered(
new pcl::PointCloud<pcl::PointXYZRGB>);
3001 std::vector<pcl::Vertices> outputPolygons;
3006 pcl::TextureMesh::Ptr textureMesh(
new pcl::TextureMesh);
3007 pcl::toPCLPointCloud2(*outputFiltered, textureMesh->cloud);
3008 textureMesh->tex_polygons.push_back(outputPolygons);
3009 int w = cloud->width;
3010 int h = cloud->height;
3012 textureMesh->tex_coordinates.resize(1);
3013 int nPoints = (int)outputFiltered->size();
3014 textureMesh->tex_coordinates[0].resize(nPoints);
3015 for(
int i=0; i<nPoints; ++i)
3018 UASSERT(i < (
int)denseToOrganizedIndices.size());
3019 int originalVertex = denseToOrganizedIndices[i];
3020 textureMesh->tex_coordinates[0][i] = Eigen::Vector2f(
3021 float(originalVertex % w) /
float(w),
3022 float(h - originalVertex / w) /
float(h));
3025 pcl::TexMaterial mesh_material;
3026 mesh_material.tex_d = 1.0f;
3027 mesh_material.tex_Ns = 75.0f;
3028 mesh_material.tex_illum = 1;
3030 std::stringstream tex_name;
3031 tex_name <<
"material_" << nodeId;
3032 tex_name >> mesh_material.tex_name;
3034 mesh_material.tex_file =
"";
3036 textureMesh->tex_materials.push_back(mesh_material);
3040 UERROR(
"Adding texture mesh %d to viewer failed!", nodeId);
3049 UERROR(
"Adding mesh cloud %d to viewer failed!", nodeId);
3061 UWARN(
"Online meshing is activated but the generated cloud is " 3062 "dense (voxel filtering is used or multiple cameras are used). Disable " 3063 "online meshing in Preferences->3D Rendering to hide this warning.");
3069 pcl::concatenateFields(*cloud, *normals, *cloudWithNormals);
3072 QColor color = Qt::gray;
3075 color = (Qt::GlobalColor)(mapId+3 % 12 + 7 );
3080 if(cloudWithNormals->size())
3082 pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr outputWithNormals;
3087 UERROR(
"Adding cloud %d to viewer failed!", nodeId);
3098 UERROR(
"Adding cloud %d to viewer failed!", nodeId);
3108 outputPair.first = output;
3109 outputPair.second = indices;
3135 std::string scanName =
uFormat(
"scan%d", nodeId);
3138 UERROR(
"Scan %d already added to map.", nodeId);
3145 UERROR(
"Node %d is not in the cache.", nodeId);
3149 if(!iter->sensorData().laserScanCompressed().isEmpty() || !iter->sensorData().laserScanRaw().isEmpty())
3152 iter->sensorData().uncompressData(0, 0, &scan);
3164 pcl::PointCloud<pcl::PointXYZ>::Ptr cloud;
3165 pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloudRGB;
3166 pcl::PointCloud<pcl::PointXYZI>::Ptr cloudI;
3167 pcl::PointCloud<pcl::PointNormal>::Ptr cloudWithNormals;
3168 pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr cloudRGBWithNormals;
3169 pcl::PointCloud<pcl::PointXYZINormal>::Ptr cloudIWithNormals;
3212 if((!scan.
is2d()) &&
3216 if(cloudRGBWithNormals.get())
3229 if(cloudIWithNormals.get())
3242 if(cloudWithNormals.get())
3296 if( (cloud.get() || cloudRGB.get() || cloudI.get()) &&
3299 Eigen::Vector3f scanViewpoint(
3304 pcl::PointCloud<pcl::Normal>::Ptr normals;
3305 if(cloud.get() && cloud->size())
3315 cloudWithNormals.reset(
new pcl::PointCloud<pcl::PointNormal>);
3316 pcl::concatenateFields(*cloud, *normals, *cloudWithNormals);
3319 else if(cloudRGB.get() && cloudRGB->size())
3323 cloudRGBWithNormals.reset(
new pcl::PointCloud<pcl::PointXYZRGBNormal>);
3324 pcl::concatenateFields(*cloudRGB, *normals, *cloudRGBWithNormals);
3327 else if(cloudI.get())
3337 cloudIWithNormals.reset(
new pcl::PointCloud<pcl::PointXYZINormal>);
3338 pcl::concatenateFields(*cloud, *normals, *cloudIWithNormals);
3343 QColor color = Qt::gray;
3346 color = (Qt::GlobalColor)(mapId+3 % 12 + 7 );
3349 if(cloudRGBWithNormals.get())
3352 if(added && nodeId > 0)
3357 else if(cloudIWithNormals.get())
3360 if(added && nodeId > 0)
3372 else if(cloudWithNormals.get())
3375 if(added && nodeId > 0)
3387 else if(cloudRGB.get())
3390 if(added && nodeId > 0)
3395 else if(cloudI.get())
3398 if(added && nodeId > 0)
3414 if(added && nodeId > 0)
3428 UERROR(
"Adding cloud %d to viewer failed!", nodeId);
3448 std::string cloudName =
uFormat(
"features%d", nodeId);
3451 UERROR(
"Features cloud %d already added to map.", nodeId);
3458 UERROR(
"Node %d is not in the cache.", nodeId);
3464 UDEBUG(
"Features cloud %d already created.");
3468 if(iter->getWords3().size())
3470 UINFO(
"Create cloud from 3D words");
3471 QColor color = Qt::gray;
3474 color = (Qt::GlobalColor)(mapId+3 % 12 + 7 );
3478 if(!iter->sensorData().imageCompressed().empty() || !iter->sensorData().imageRaw().empty())
3484 pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud(
new pcl::PointCloud<pcl::PointXYZRGB>);
3485 cloud->resize(iter->getWords3().size());
3487 UASSERT(iter->getWords().size() == iter->getWords3().size());
3488 std::multimap<int, cv::KeyPoint>::const_iterator kter=iter->getWords().begin();
3490 UDEBUG(
"rgb.channels()=%d");
3491 for(std::multimap<int, cv::Point3f>::const_iterator jter=iter->getWords3().begin();
3492 jter!=iter->getWords3().end(); ++jter, ++kter)
3494 if(
util3d::isFinite(jter->second) && (maxDepth == 0.0f || jter->second.z < maxDepth))
3496 (*cloud)[oi].x = jter->second.x;
3497 (*cloud)[oi].y = jter->second.y;
3498 (*cloud)[oi].z = jter->second.z;
3499 int u = kter->second.pt.x+0.5;
3500 int v = kter->second.pt.y+0.5;
3505 if(rgb.channels() == 1)
3507 (*cloud)[oi].r = (*cloud)[oi].g = (*cloud)[oi].b = rgb.at<
unsigned char>(v, u);
3511 cv::Vec3b bgr = rgb.at<cv::Vec3b>(v, u);
3512 (*cloud)[oi].b = bgr.val[0];
3513 (*cloud)[oi].g = bgr.val[1];
3514 (*cloud)[oi].r = bgr.val[2];
3519 (*cloud)[oi].r = (*cloud)[oi].g = (*cloud)[oi].b = 255;
3527 UERROR(
"Adding features cloud %d to viewer failed!", nodeId);
3544 const std::map<int, Transform> & poses,
3545 const std::map<int, Transform> & groundTruth)
3548 if(groundTruth.size() && poses.size())
3550 float translational_rmse = 0.0f;
3551 float translational_mean = 0.0f;
3552 float translational_median = 0.0f;
3553 float translational_std = 0.0f;
3554 float translational_min = 0.0f;
3555 float translational_max = 0.0f;
3556 float rotational_rmse = 0.0f;
3557 float rotational_mean = 0.0f;
3558 float rotational_median = 0.0f;
3559 float rotational_std = 0.0f;
3560 float rotational_min = 0.0f;
3561 float rotational_max = 0.0f;
3568 translational_median,
3580 UINFO(
"translational_rmse=%f", translational_rmse);
3581 UINFO(
"translational_mean=%f", translational_mean);
3582 UINFO(
"translational_median=%f", translational_median);
3583 UINFO(
"translational_std=%f", translational_std);
3584 UINFO(
"translational_min=%f", translational_min);
3585 UINFO(
"translational_max=%f", translational_max);
3587 UINFO(
"rotational_rmse=%f", rotational_rmse);
3588 UINFO(
"rotational_mean=%f", rotational_mean);
3589 UINFO(
"rotational_median=%f", rotational_median);
3590 UINFO(
"rotational_std=%f", rotational_std);
3591 UINFO(
"rotational_min=%f", rotational_min);
3592 UINFO(
"rotational_max=%f", rotational_max);
3599 UINFO(
"Update visibility %d", nodeId);
3603 _ui->actionAnchor_clouds_to_ground_truth->isChecked() &&
3613 if(!pose.
isNull() || !visible)
3617 std::string cloudName =
uFormat(
"cloud%d", nodeId);
3618 if(visible && !viewerClouds.contains(cloudName) &&
_cachedSignatures.contains(nodeId))
3622 else if(viewerClouds.contains(cloudName))
3635 std::string scanName =
uFormat(
"scan%d", nodeId);
3636 if(visible && !viewerClouds.contains(scanName) &&
_cachedSignatures.contains(nodeId))
3640 else if(viewerClouds.contains(scanName))
3657 if(
_ui->dockWidget_graphViewer->isVisible())
3659 UDEBUG(
"Graph visible!");
3709 bool removed =
true;
3720 QMessageBox::information(
this, tr(
"Database saved!"), QString(msg.c_str()));
3724 std::string msg =
uFormat(
"Failed to rename temporary database from \"%s\" to \"%s\".",
3727 QMessageBox::critical(
this, tr(
"Closing failed!"), QString(msg.c_str()));
3732 std::string msg =
uFormat(
"Failed to overwrite the database \"%s\". The temporary database is still correctly saved at \"%s\".",
3735 QMessageBox::critical(
this, tr(
"Closing failed!"), QString(msg.c_str()));
3752 QMessageBox::information(
this, tr(
"Database updated!"), QString(msg.c_str()));
3772 if(applicationClosing)
3787 msg.prepend(tr(
"[ERROR] "));
3805 UERROR(
"Map received with code error %d!", event.
getCode());
3813 UINFO(
"Received map!");
3819 QApplication::processEvents();
3821 int addedSignatures = 0;
3822 std::map<int, int> mapIds;
3823 std::map<int, Transform> groundTruth;
3824 std::map<int, std::string> labels;
3825 for(std::map<int, Signature>::const_iterator iter = event.
getSignatures().begin();
3826 iter!=
event.getSignatures().end();
3829 mapIds.insert(std::make_pair(iter->first, iter->second.mapId()));
3830 if(!iter->second.getGroundTruthPose().isNull())
3832 groundTruth.insert(std::make_pair(iter->first, iter->second.getGroundTruthPose()));
3834 if(!iter->second.getLabel().empty())
3836 labels.insert(std::make_pair(iter->first, iter->second.getLabel()));
3839 (
_cachedSignatures.value(iter->first).sensorData().imageCompressed().empty() && !iter->second.sensorData().imageCompressed().empty()))
3843 unsigned int count = 0;
3844 for(std::multimap<int, cv::Point3f>::const_iterator jter=iter->second.getWords3().upper_bound(-1); jter!=iter->second.getWords3().end(); ++jter)
3855 QApplication::processEvents();
3859 QApplication::processEvents();
3869 QApplication::processEvents();
3870 std::map<int, Transform> poses =
event.getPoses();
3873 if(
_ui->graphicsView_graphView->isVisible() &&
3886 UINFO(
"Map received is empty! Cannot update the map cloud...");
3916 _ui->graphicsView_graphView->setGlobalPath(event.
getPoses());
3930 QMessageBox * warn =
new QMessageBox(
3931 QMessageBox::Warning,
3932 tr(
"Setting goal failed!"),
3933 tr(
"Setting goal to location %1%2 failed. " 3935 "1) the robot is not yet localized in the map,\n" 3936 "2) the location doesn't exist in the map,\n" 3937 "3) the location is not linked to the global map or\n" 3938 "4) the location is too near of the current location (goal already reached).")
3943 warn->setAttribute(Qt::WA_DeleteOnClose,
true);
3948 QMessageBox * info =
new QMessageBox(
3949 QMessageBox::Information,
3950 tr(
"Goal detected!"),
3951 tr(
"Global path computed to %1%2 (%3 poses, %4 m).")
3958 info->setAttribute(Qt::WA_DeleteOnClose,
true);
3972 QMessageBox * warn =
new QMessageBox(
3973 QMessageBox::Warning,
3974 tr(
"Setting label failed!"),
3975 tr(
"Setting label %1 to location %2 failed. " 3977 "1) the location doesn't exist in the map,\n" 3978 "2) the location has already a label.").arg(label).arg(
id),
3981 warn->setAttribute(Qt::WA_DeleteOnClose,
true);
3987 _ui->widget_console->appendMsg(tr(
"Goal status received=%1").arg(status),
ULogger::kInfo);
4020 UDEBUG(
"General settings changed...");
4024 _ui->graphicsView_graphView->clearPosterior();
4030 UDEBUG(
"Cloud rendering settings changed...");
4044 UDEBUG(
"Logging settings changed...");
4064 if(parameters.size())
4066 for(rtabmap::ParametersMap::const_iterator iter = parameters.begin(); iter!=parameters.end(); ++iter)
4068 UDEBUG(
"Parameter changed: Key=%s Value=%s", iter->first.c_str(), iter->second.c_str());
4073 if(
uContains(parameters, Parameters::kRtabmapWorkingDirectory()))
4093 if(
uContains(parameters, Parameters::kRGBDLocalRadius()))
4095 _ui->graphicsView_graphView->setLocalRadius(
uStr2Float(parameters.at(Parameters::kRGBDLocalRadius())));
4117 _ui->imageView_source->clearFeatures();
4119 for(std::multimap<int, cv::KeyPoint>::const_iterator iter = refWords.begin(); iter != refWords.end(); ++iter )
4121 int id = iter->first;
4131 color = Qt::magenta;
4143 else if(refWords.count(
id) > 1)
4153 _ui->imageView_source->addFeature(iter->first, iter->second, 0, color);
4159 QList<QPair<cv::Point2f, cv::Point2f> > uniqueCorrespondences;
4160 if(loopWords.size())
4162 _ui->imageView_loopClosure->clearFeatures();
4164 for(std::multimap<int, cv::KeyPoint>::const_iterator iter = loopWords.begin(); iter != loopWords.end(); ++iter )
4166 int id = iter->first;
4176 color = Qt::magenta;
4178 if(
uValues(refWords,
id).size() == 1 &&
uValues(loopWords,
id).size() == 1)
4180 const cv::KeyPoint & a = refWords.find(
id)->second;
4181 const cv::KeyPoint & b = iter->second;
4182 uniqueCorrespondences.push_back(QPair<cv::Point2f, cv::Point2f>(a.pt, b.pt));
4190 else if(refWords.count(
id) > 1)
4200 _ui->imageView_loopClosure->addFeature(iter->first, iter->second, 0, color);
4205 if(refWords.size()>0)
4207 if((*refWords.rbegin()).first >
_lastId)
4209 _lastId = (*refWords.rbegin()).first;
4215 float scaleSource =
_ui->imageView_source->viewScale();
4216 float scaleLoop =
_ui->imageView_loopClosure->viewScale();
4217 UDEBUG(
"scale source=%f loop=%f", scaleSource, scaleLoop);
4219 float sourceMarginX = (
_ui->imageView_source->width() -
_ui->imageView_source->sceneRect().width()*scaleSource)/2.0
f;
4220 float sourceMarginY = (
_ui->imageView_source->height() -
_ui->imageView_source->sceneRect().height()*scaleSource)/2.0
f;
4221 float loopMarginX = (
_ui->imageView_loopClosure->width() -
_ui->imageView_loopClosure->sceneRect().width()*scaleLoop)/2.0
f;
4222 float loopMarginY = (
_ui->imageView_loopClosure->height() -
_ui->imageView_loopClosure->sceneRect().height()*scaleLoop)/2.0
f;
4229 deltaY =
_ui->label_matchId->height() +
_ui->imageView_source->height();
4233 deltaX =
_ui->imageView_source->width();
4236 if(refWords.size() && loopWords.size())
4238 _ui->imageView_source->clearLines();
4239 _ui->imageView_loopClosure->clearLines();
4242 for(QList<QPair<cv::Point2f, cv::Point2f> >::iterator iter = uniqueCorrespondences.begin();
4243 iter!=uniqueCorrespondences.end();
4247 _ui->imageView_source->addLine(
4250 (iter->second.x*scaleLoop+loopMarginX+deltaX-sourceMarginX)/scaleSource,
4251 (iter->second.y*scaleLoop+loopMarginY+deltaY-sourceMarginY)/scaleSource,
4254 _ui->imageView_loopClosure->addLine(
4255 (iter->first.x*scaleSource+sourceMarginX-deltaX-loopMarginX)/scaleLoop,
4256 (iter->first.y*scaleSource+sourceMarginY-deltaY-loopMarginY)/scaleLoop,
4261 _ui->imageView_source->update();
4262 _ui->imageView_loopClosure->update();
4273 if(this->isVisible())
4286 if(this->isVisible())
4295 if((event->modifiers() & Qt::ControlModifier) && event->key() == Qt::Key_S)
4303 if (event->type() == QEvent::Resize && qobject_cast<QDockWidget*>(obj))
4305 this->setWindowModified(
true);
4307 else if(event->type() == QEvent::FileOpen )
4311 return QWidget::eventFilter(obj, event);
4318 _ui->actionMore_options->setChecked(
4369 QString name = (QDateTime::currentDateTime().toString(
"yyMMddhhmmsszzz") + (png?
".png":
".jpg"));
4370 _ui->statusbar->clearMessage();
4371 QPixmap figure = QPixmap::grabWidget(
this);
4377 msg = tr(
"Screen captured \"%1\"").arg(name);
4379 QBuffer buffer(&bytes);
4380 buffer.open(QIODevice::WriteOnly);
4381 figure.save(&buffer, png?
"PNG":
"JPEG");
4387 if(!dir.exists(targetDir))
4389 dir.mkdir(targetDir);
4391 targetDir += QDir::separator();
4392 targetDir +=
"Main_window";
4393 if(!dir.exists(targetDir))
4395 dir.mkdir(targetDir);
4397 targetDir += QDir::separator();
4399 figure.save(targetDir + name);
4400 msg = tr(
"Screen captured \"%1\"").arg(targetDir + name);
4403 _ui->widget_console->appendMsg(msg);
4405 return targetDir + name;
4410 QApplication::beep();
4421 this->setWindowModified(
true);
4426 if(parameters.size())
4428 for(ParametersMap::const_iterator iter= parameters.begin(); iter!=parameters.end(); ++iter)
4430 QString msg = tr(
"Parameter update \"%1\"=\"%2\"")
4431 .arg(iter->first.c_str())
4432 .arg(iter->second.c_str());
4433 _ui->widget_console->appendMsg(msg);
4434 UWARN(msg.toStdString().c_str());
4436 QMessageBox::StandardButton button = QMessageBox::question(
this,
4438 tr(
"Some parameters have been set on command line, do you " 4439 "want to set all other RTAB-Map's parameters to default?"),
4440 QMessageBox::Yes | QMessageBox::No,
4464 this->setWindowModified(
false);
4471 UERROR(
"This method can be called only in IDLE state.");
4481 if(QFile::exists(databasePath.c_str()))
4483 int r = QMessageBox::question(
this,
4484 tr(
"Creating temporary database"),
4485 tr(
"Cannot create a new database because the temporary database \"%1\" already exists. " 4486 "There may be another instance of RTAB-Map running with the same Working Directory or " 4487 "the last time RTAB-Map was not closed correctly. " 4488 "Do you want to recover the database (click Ignore to delete it and create a new one)?").arg(databasePath.c_str()),
4489 QMessageBox::Yes | QMessageBox::No | QMessageBox::Ignore, QMessageBox::No);
4491 if(r == QMessageBox::Ignore)
4493 if(QFile::remove(databasePath.c_str()))
4495 UINFO(
"Deleted temporary database \"%s\".", databasePath.c_str());
4499 UERROR(
"Temporary database \"%s\" could not be deleted!", databasePath.c_str());
4503 else if(r == QMessageBox::Yes)
4505 std::string errorMsg;
4507 progressDialog->setAttribute(Qt::WA_DeleteOnClose);
4509 progressDialog->show();
4517 QString newPath = QFileDialog::getSaveFileName(
this, tr(
"Save recovered database"),
_preferencesDialog->
getWorkingDirectory()+QDir::separator()+QString(
"recovered.db"), tr(
"RTAB-Map database files (*.db)"));
4518 if(newPath.isEmpty())
4522 if(QFileInfo(newPath).suffix() ==
"")
4526 if(QFile::exists(newPath))
4528 QFile::remove(newPath);
4530 QFile::rename(databasePath.c_str(), newPath);
4537 QMessageBox::warning(
this,
"Database recovery", tr(
"Database recovery failed: \"%1\".").arg(errorMsg.c_str()));
4564 UERROR(
"Database can only be opened in IDLE state.");
4568 std::string value = path.toStdString();
4588 if(parameters.size())
4593 parameters.insert(*iter);
4596 uInsert(parameters, overridedParameters);
4600 for(ParametersMap::iterator iter=parameters.begin(); iter!=parameters.end(); ++iter)
4602 ParametersMap::iterator jter = currentParameters.find(iter->first);
4603 if(jter!=currentParameters.end() &&
4604 iter->second.compare(jter->second) != 0 &&
4605 iter->first.compare(Parameters::kRtabmapWorkingDirectory()) != 0)
4607 bool different =
true;
4618 differentParameters.insert(*iter);
4619 QString msg = tr(
"Parameter \"%1\": database=\"%2\" Preferences=\"%3\"")
4620 .arg(iter->first.c_str())
4621 .arg(iter->second.c_str())
4622 .arg(jter->second.c_str());
4623 _ui->widget_console->appendMsg(msg);
4624 UWARN(msg.toStdString().c_str());
4629 if(differentParameters.size())
4631 int r = QMessageBox::question(
this,
4632 tr(
"Update parameters..."),
4633 tr(
"The database is using %1 different parameter(s) than " 4634 "those currently set in Preferences. Do you want " 4635 "to use database's parameters?").arg(differentParameters.size()),
4636 QMessageBox::Yes | QMessageBox::No,
4638 if(r == QMessageBox::Yes)
4651 UERROR(
"File \"%s\" not valid.", value.c_str());
4659 UERROR(
"This method can be called only in INITIALIZED state.");
4666 QMessageBox::Button b = QMessageBox::question(
this,
4667 tr(
"Save database"),
4668 tr(
"Save the new database?"),
4669 QMessageBox::Save | QMessageBox::Cancel | QMessageBox::Discard,
4672 if(b == QMessageBox::Save)
4675 QString newName = QDateTime::currentDateTime().toString(
"yyMMdd-hhmmss");
4678 newPath = QFileDialog::getSaveFileName(
this, tr(
"Save database"), newPath, tr(
"RTAB-Map database files (*.db)"));
4679 if(newPath.isEmpty())
4684 if(QFileInfo(newPath).suffix() ==
"")
4691 else if(b != QMessageBox::Discard)
4705 UERROR(
"This method can be called only in IDLE state.");
4715 dbSettingsIn.beginGroup(
"DatabaseViewer");
4716 dbSettingsOut.beginGroup(
"DatabaseViewer");
4717 QStringList keys = dbSettingsIn.childKeys();
4718 for(QStringList::iterator iter = keys.begin(); iter!=keys.end(); ++iter)
4720 dbSettingsOut.setValue(*iter, dbSettingsIn.value(*iter));
4722 dbSettingsIn.endGroup();
4723 dbSettingsOut.endGroup();
4727 viewer->setWindowModality(Qt::WindowModal);
4728 viewer->setAttribute(Qt::WA_DeleteOnClose,
true);
4733 viewer->showMaximized();
4757 float detectionRate =
uStr2Float(parameters.at(Parameters::kRtabmapDetectionRate()));
4758 int bufferingSize =
uStr2Float(parameters.at(Parameters::kRtabmapImageBufferSize()));
4759 if(((detectionRate!=0.0
f && detectionRate <= inputRate) || (detectionRate > 0.0
f && inputRate == 0.0
f)) &&
4762 int button = QMessageBox::question(
this,
4763 tr(
"Incompatible frame rates!"),
4764 tr(
"\"Source/Input rate\" (%1 Hz) is equal to/higher than \"RTAB-Map/Detection rate\" (%2 Hz). As the " 4765 "source input is a directory of images/video/database, some images may be " 4766 "skipped by the detector. You may want to increase the \"RTAB-Map/Detection rate\" over " 4767 "the \"Source/Input rate\" to guaranty that all images are processed. Would you want to " 4768 "start the detection anyway?").arg(inputRate).arg(detectionRate),
4769 QMessageBox::Yes | QMessageBox::No);
4770 if(button == QMessageBox::No)
4777 if(bufferingSize != 0)
4779 int button = QMessageBox::question(
this,
4780 tr(
"Some images may be skipped!"),
4781 tr(
"\"RTAB-Map/Images buffer size\" is not infinite (size=%1). As the " 4782 "source input is a directory of images/video/database, some images may be " 4783 "skipped by the detector if the \"Source/Input rate\" (which is %2 Hz) is higher than the " 4784 "rate at which RTAB-Map can process the images. You may want to set the " 4785 "\"RTAB-Map/Images buffer size\" to 0 (infinite) to guaranty that all " 4786 "images are processed. Would you want to start the detection " 4787 "anyway?").arg(bufferingSize).arg(inputRate),
4788 QMessageBox::Yes | QMessageBox::No);
4789 if(button == QMessageBox::No)
4794 else if(inputRate == 0)
4796 int button = QMessageBox::question(
this,
4797 tr(
"Large number of images may be buffered!"),
4798 tr(
"\"RTAB-Map/Images buffer size\" is infinite. As the " 4799 "source input is a directory of images/video/database and " 4800 "that \"Source/Input rate\" is infinite too, a lot of images " 4801 "could be buffered at the same time (e.g., reading all images " 4802 "of a directory at once). This could make the GUI not responsive. " 4803 "You may want to set \"Source/Input rate\" at the rate at " 4804 "which the images have been recorded. " 4805 "Would you want to start the detection " 4806 "anyway?").arg(bufferingSize).arg(inputRate),
4807 QMessageBox::Yes | QMessageBox::No);
4808 if(button == QMessageBox::No)
4821 QMessageBox::warning(
this,
4823 tr(
"A camera is running, stop it first."));
4824 UWARN(
"_camera is not null... it must be stopped first");
4832 QMessageBox::warning(
this,
4834 tr(
"No sources are selected. See Preferences->Source panel."));
4835 UWARN(
"No sources are selected. See Preferences->Source panel.");
4873 if(
uStr2Bool(parameters.at(Parameters::kRGBDEnabled()).c_str()))
4878 UWARN(
"Camera is not calibrated!");
4883 int button = QMessageBox::question(
this,
4884 tr(
"Camera is not calibrated!"),
4885 tr(
"RTAB-Map in metric SLAM mode cannot run with an uncalibrated camera. Do you want to calibrate the camera now?"),
4886 QMessageBox::Yes | QMessageBox::No);
4887 if(button == QMessageBox::Yes)
4897 UERROR(
"OdomThread must be already deleted here?!");
4904 UERROR(
"ImuThread must be already deleted here?!");
4916 odomParameters.erase(Parameters::kRtabmapPublishRAMUsage());
4917 int odomStrategy = Parameters::defaultOdomStrategy();
4919 if(odomStrategy == 1)
4932 QMessageBox::warning(
this, tr(
"Source IMU Path"),
4933 tr(
"IMU path is set but odometry chosen doesn't support IMU, ignoring IMU..."), QMessageBox::Ok);
4940 QMessageBox::warning(
this, tr(
"Source IMU Path"),
4976 _ui->actionReset_Odometry->setEnabled(
true);
4981 QMessageBox::information(
this,
4983 tr(
"Note that publishing statistics is disabled, " 4984 "progress will not be shown in the GUI."));
4990 #ifdef RTABMAP_OCTOMAP 5011 if(
_state ==
kPaused && (QApplication::keyboardModifiers() & Qt::ShiftModifier))
5031 UINFO(
"Sending pause event!");
5036 UINFO(
"Sending unpause event!");
5051 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);
5053 if(button != QMessageBox::Yes)
5073 _ui->actionReset_Odometry->setEnabled(
false);
5105 QMessageBox::information(
this,
5106 tr(
"No more images..."),
5107 tr(
"The camera has reached the end of the stream."));
5112 _ui->dockWidget_console->show();
5115 for(
int i = 0; i<
_refIds.size(); ++i)
5117 msgRef.append(QString::number(
_refIds[i]));
5122 msgLoop.append(
" ");
5125 _ui->widget_console->appendMsg(QString(
"IDs = [%1];").arg(msgRef));
5126 _ui->widget_console->appendMsg(QString(
"LoopIDs = [%1];").arg(msgLoop));
5137 int id = QInputDialog::getInt(
this, tr(
"Around which location?"), tr(
"Location ID (0=full map)"), 0, 0, 999999, 0, &ok);
5143 margin = QInputDialog::getInt(
this, tr(
"Depth around the location?"), tr(
"Margin"), 4, 1, 100, 1, &ok);
5148 QString path = QFileDialog::getSaveFileName(
this, tr(
"Save File"),
_graphSavingFileName, tr(
"Graphiz file (*.dot)"));
5154 _ui->dockWidget_console->show();
5155 _ui->widget_console->appendMsg(QString(
"Graph saved... Tip:\nneato -Tpdf \"%1\" -o out.pdf").arg(
_graphSavingFileName));
5186 std::map<int, Transform> localTransforms;
5188 items.push_back(
"Robot");
5189 items.push_back(
"Camera");
5190 items.push_back(
"Scan");
5192 QString item = QInputDialog::getItem(
this, tr(
"Export Poses"), tr(
"Frame: "), items,
_exportPosesFrame,
false, &ok);
5193 if(!ok || item.isEmpty())
5197 if(item.compare(
"Robot") != 0)
5199 bool cameraFrame = item.compare(
"Camera") == 0;
5209 !
_cachedSignatures[iter->first].sensorData().cameraModels().at(0).localTransform().isNull()))
5211 localTransform =
_cachedSignatures[iter->first].sensorData().cameraModels().at(0).localTransform();
5213 else if(!
_cachedSignatures[iter->first].sensorData().stereoCameraModel().localTransform().isNull())
5215 localTransform =
_cachedSignatures[iter->first].sensorData().stereoCameraModel().localTransform();
5219 UWARN(
"Multi-camera is not supported (node %d)", iter->first);
5223 UWARN(
"Missing calibration for node %d", iter->first);
5228 if(!
_cachedSignatures[iter->first].sensorData().laserScanRaw().localTransform().isNull())
5230 localTransform =
_cachedSignatures[iter->first].sensorData().laserScanRaw().localTransform();
5232 else if(!
_cachedSignatures[iter->first].sensorData().laserScanCompressed().localTransform().isNull())
5234 localTransform =
_cachedSignatures[iter->first].sensorData().laserScanCompressed().localTransform();
5238 UWARN(
"Missing scan info for node %d", iter->first);
5241 if(!localTransform.
isNull())
5243 localTransforms.insert(std::make_pair(iter->first, localTransform));
5248 UWARN(
"Did not find node %d in cache", iter->first);
5251 if(localTransforms.empty())
5253 QMessageBox::warning(
this,
5255 tr(
"Could not find any \"%1\" frame, exporting in Robot frame instead.").arg(item));
5263 std::map<int, Transform> poses;
5264 std::multimap<int, Link> links;
5265 if(localTransforms.empty())
5273 for(std::map<int, Transform>::iterator iter=localTransforms.begin(); iter!=localTransforms.end(); ++iter)
5275 poses.insert(std::make_pair(iter->first,
_currentPosesMap.at(iter->first) * iter->second));
5281 std::multimap<int, Link>::iterator inserted = links.insert(*iter);
5282 int from = iter->second.from();
5283 int to = iter->second.to();
5284 inserted->second.setTransform(localTransforms.at(from).inverse()*iter->second.transform()*localTransforms.at(to));
5289 std::map<int, double> stamps;
5292 for(std::map<int, Transform>::iterator iter=poses.begin(); iter!=poses.end(); ++iter)
5296 stamps.insert(std::make_pair(iter->first,
_cachedSignatures.value(iter->first).getStamp()));
5299 if(stamps.size()!=poses.size())
5301 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.")
5302 .arg(poses.size()).arg(stamps.size()));
5312 QString path = QFileDialog::getSaveFileName(
5316 format == 3?tr(
"TORO file (*.graph)"):format==4?tr(
"g2o file (*.g2o)"):tr(
"Text file (*.txt)"));
5320 if(QFileInfo(path).suffix() ==
"")
5341 QMessageBox::information(
this,
5342 tr(
"Export poses..."),
5343 tr(
"%1 saved to \"%2\".")
5344 .arg(format == 3?
"TORO graph":format == 4?
"g2o graph":
"Poses")
5349 QMessageBox::information(
this,
5350 tr(
"Export poses..."),
5351 tr(
"Failed to save %1 to \"%2\"!")
5352 .arg(format == 3?
"TORO graph":format == 4?
"g2o graph":
"poses")
5363 QMessageBox::warning(
this,
5364 tr(
"Post-processing..."),
5365 tr(
"Signatures must be cached in the GUI for post-processing. " 5366 "Check the option in Preferences->General Settings (GUI), then " 5367 "refresh the cache."));
5386 if(!detectMoreLoopClosures && !refineNeighborLinks && !refineLoopClosureLinks && !sba)
5388 UWARN(
"No post-processing selection...");
5393 bool allDataAvailable =
true;
5394 std::map<int, Transform> odomPoses;
5402 if(jter->getPose().isNull())
5404 UWARN(
"Odometry pose of %d is null.", iter->first);
5405 allDataAvailable =
false;
5409 odomPoses.insert(*iter);
5414 UWARN(
"Node %d missing.", iter->first);
5415 allDataAvailable =
false;
5419 if(!allDataAvailable)
5421 QMessageBox::warning(
this, tr(
"Not all data available in the GUI..."),
5422 tr(
"Some data missing in the cache to respect the constraints chosen. " 5423 "Try \"Edit->Download all clouds\" to update the cache and try again."));
5435 if(refineNeighborLinks)
5437 totalSteps+=(int)odomPoses.size();
5439 if(refineLoopClosureLinks)
5452 bool optimizeFromGraphEnd = Parameters::defaultRGBDOptimizeFromGraphEnd();
5453 float optimizeMaxError = Parameters::defaultRGBDOptimizeMaxError();
5454 int optimizeIterations = Parameters::defaultOptimizerIterations();
5455 bool reextractFeatures = Parameters::defaultRGBDLoopClosureReextractFeatures();
5456 Parameters::parse(parameters, Parameters::kRGBDOptimizeFromGraphEnd(), optimizeFromGraphEnd);
5457 Parameters::parse(parameters, Parameters::kRGBDOptimizeMaxError(), optimizeMaxError);
5458 Parameters::parse(parameters, Parameters::kOptimizerIterations(), optimizeIterations);
5459 Parameters::parse(parameters, Parameters::kRGBDLoopClosureReextractFeatures(), reextractFeatures);
5462 int loopClosuresAdded = 0;
5463 std::multimap<int, int> checkedLoopClosures;
5464 if(detectMoreLoopClosures)
5468 UASSERT(detectLoopClosureIterations>0);
5471 _progressDialog->
appendText(tr(
"Looking for more loop closures, clustering poses... (iteration=%1/%2, radius=%3 m angle=%4 degrees)")
5472 .arg(n+1).arg(detectLoopClosureIterations).arg(clusterRadius).arg(clusterAngle));
5477 clusterAngle*CV_PI/180.0);
5480 _progressDialog->
appendText(tr(
"Looking for more loop closures, clustering poses... found %1 clusters.").arg(clusters.size()));
5481 QApplication::processEvents();
5484 std::set<int> addedLinks;
5485 for(std::multimap<int, int>::iterator iter=clusters.begin(); iter!= clusters.end() && !
_progressCanceled; ++iter, ++i)
5487 int from = iter->first;
5488 int to = iter->second;
5489 if(iter->first < iter->second)
5491 from = iter->second;
5495 bool alreadyChecked =
false;
5496 for(std::multimap<int, int>::iterator jter = checkedLoopClosures.lower_bound(from);
5497 !alreadyChecked && jter!=checkedLoopClosures.end() && jter->first == from;
5500 if(to == jter->second)
5502 alreadyChecked =
true;
5509 if(addedLinks.find(from) == addedLinks.end() &&
5512 checkedLoopClosures.insert(std::make_pair(from, to));
5516 UERROR(
"Didn't find signature %d", from);
5520 UERROR(
"Didn't find signature %d", to);
5532 if(parameters.find(Parameters::kRegStrategy()) != parameters.end() &&
5533 parameters.at(Parameters::kRegStrategy()).compare(
"1") == 0)
5539 if(reextractFeatures)
5547 UWARN(
"\"%s\" is false and signatures (%d and %d) don't have raw " 5548 "images. Update the cache.",
5549 Parameters::kRGBDLoopClosureReextractFeatures().c_str());
5553 signatureFrom.
setWords(std::multimap<int, cv::KeyPoint>());
5554 signatureFrom.
setWords3(std::multimap<int, cv::Point3f>());
5556 signatureFrom.
sensorData().
setFeatures(std::vector<cv::KeyPoint>(), std::vector<cv::Point3f>(), cv::Mat());
5557 signatureTo.
setWords(std::multimap<int, cv::KeyPoint>());
5558 signatureTo.
setWords3(std::multimap<int, cv::Point3f>());
5560 signatureTo.
sensorData().
setFeatures(std::vector<cv::KeyPoint>(), std::vector<cv::Point3f>(), cv::Mat());
5563 else if(!reextractFeatures && signatureFrom.
getWords().empty() && signatureTo.
getWords().empty())
5565 UWARN(
"\"%s\" is false and signatures (%d and %d) don't have words, " 5566 "registration will not be possible. Set \"%s\" to true.",
5567 Parameters::kRGBDLoopClosureReextractFeatures().c_str(),
5570 Parameters::kRGBDLoopClosureReextractFeatures().c_str());
5573 delete registration;
5574 if(!transform.isNull())
5576 if(!transform.isIdentity())
5582 info.
covariance = cv::Mat::eye(6,6,CV_64FC1)*0.0001;
5587 bool updateConstraint =
true;
5588 if(optimizeMaxError > 0.0
f && optimizeIterations > 0)
5595 if(iter->second == mapId && odomPoses.find(iter->first)!=odomPoses.end())
5597 fromId = iter->first;
5603 const Link * maxLinearLink = 0;
5604 const Link * maxAngularLink = 0;
5605 float maxLinearError = 0.0f;
5606 float maxAngularError = 0.0f;
5607 std::map<int, Transform> poses;
5608 std::multimap<int, Link> links;
5609 UASSERT(odomPoses.find(fromId) != odomPoses.end());
5610 UASSERT_MSG(odomPoses.find(from) != odomPoses.end(),
uFormat(
"id=%d poses=%d links=%d", from, (
int)poses.size(), (int)links.size()).c_str());
5611 UASSERT_MSG(odomPoses.find(to) != odomPoses.end(),
uFormat(
"id=%d poses=%d links=%d", to, (
int)poses.size(), (int)links.size()).c_str());
5613 UASSERT(poses.find(fromId) != poses.end());
5614 UASSERT_MSG(poses.find(from) != poses.end(),
uFormat(
"id=%d poses=%d links=%d", from, (
int)poses.size(), (int)links.size()).c_str());
5615 UASSERT_MSG(poses.find(to) != poses.end(),
uFormat(
"id=%d poses=%d links=%d", to, (
int)poses.size(), (int)links.size()).c_str());
5617 poses = optimizer->
optimize(fromId, poses, links);
5621 for(std::multimap<int, Link>::iterator iter=links.begin(); iter!=links.end(); ++iter)
5624 if(iter->second.transVariance() <= 1.0 && iter->second.from() != iter->second.to())
5626 UASSERT(poses.find(iter->second.from())!=poses.end());
5627 UASSERT(poses.find(iter->second.to())!=poses.end());
5628 Transform t1 = poses.at(iter->second.from());
5629 Transform t2 = poses.at(iter->second.to());
5632 float linearError =
uMax3(
5633 fabs(iter->second.transform().x() - t.x()),
5634 fabs(iter->second.transform().y() - t.y()),
5635 fabs(iter->second.transform().z() - t.z()));
5636 Eigen::Vector3f vA = t1.toEigen3f().linear()*Eigen::Vector3f(1,0,0);
5637 Eigen::Vector3f vB = t2.
toEigen3f().linear()*Eigen::Vector3f(1,0,0);
5638 float angularError = pcl::getAngle3D(Eigen::Vector4f(vA[0], vA[1], vA[2], 0), Eigen::Vector4f(vB[0], vB[1], vB[2], 0));
5639 if(linearError > maxLinearError)
5641 maxLinearError = linearError;
5642 maxLinearLink = &iter->second;
5644 if(angularError > maxAngularError)
5646 maxAngularError = angularError;
5647 maxAngularLink = &iter->second;
5653 UINFO(
"Max optimization linear error = %f m (link %d->%d)", maxLinearError, maxLinearLink->
from(), maxLinearLink->
to());
5657 UINFO(
"Max optimization angular error = %f deg (link %d->%d)", maxAngularError*180.0
f/
M_PI, maxAngularLink->
from(), maxAngularLink->
to());
5660 if(maxLinearError > optimizeMaxError)
5662 msg =
uFormat(
"Rejecting edge %d->%d because " 5663 "graph error is too large after optimization (%f m for edge %d->%d, %f deg for edge %d->%d). " 5668 maxLinearLink->
from(),
5669 maxLinearLink->
to(),
5670 maxAngularError*180.0f/
M_PI,
5671 maxAngularLink?maxAngularLink->
from():0,
5672 maxAngularLink?maxAngularLink->
to():0,
5673 Parameters::kRGBDOptimizeMaxError().c_str(),
5679 msg =
uFormat(
"Rejecting edge %d->%d because graph optimization has failed!",
5685 UWARN(
"%s", msg.c_str());
5687 QApplication::processEvents();
5688 updateConstraint =
false;
5692 if(updateConstraint)
5694 UINFO(
"Added new loop closure between %d and %d.", from, to);
5695 addedLinks.insert(from);
5696 addedLinks.insert(to);
5699 ++loopClosuresAdded;
5700 _progressDialog->
appendText(tr(
"Detected loop closure %1->%2! (%3/%4)").arg(from).arg(to).arg(i+1).arg(clusters.size()));
5707 QApplication::processEvents();
5710 _progressDialog->
appendText(tr(
"Iteration %1/%2: Detected %3 loop closures!").arg(n+1).arg(detectLoopClosureIterations).arg(addedLinks.size()/2));
5711 if(addedLinks.size() == 0)
5716 if(n+1 < detectLoopClosureIterations)
5720 QApplication::processEvents();
5722 int fromId = optimizeFromGraphEnd?odomPoses.rbegin()->first:odomPoses.begin()->first;
5723 std::map<int, rtabmap::Transform> posesOut;
5724 std::multimap<int, rtabmap::Link> linksOut;
5725 std::map<int, rtabmap::Transform> optimizedPoses;
5732 optimizedPoses = optimizer->
optimize(fromId, posesOut, linksOut);
5737 UINFO(
"Added %d loop closures.", loopClosuresAdded);
5744 if(refineLoopClosureLinks)
5750 QApplication::processEvents();
5757 int type = iter->second.type();
5762 int from = iter->second.from();
5763 int to = iter->second.to();
5767 QApplication::processEvents();
5771 UERROR(
"Didn't find signature %d",from);
5775 UERROR(
"Didn't find signature %d", to);
5794 Link newLink(from, to, iter->second.type(), transform, info.
covariance.inv());
5795 iter->second = newLink;
5799 QString str = tr(
"Cannot refine link %1->%2 (%3").arg(from).arg(to).arg(info.
rejectedMsg.c_str());
5801 UWARN(
"%s", str.toStdString().c_str());
5810 str = tr(
"Cannot refine link %1->%2 (Intermediate node detected!)").arg(from).arg(to);
5814 str = tr(
"Cannot refine link %1->%2 (scans empty!)").arg(from).arg(to);
5818 UWARN(
"%s", str.toStdString().c_str());
5830 int fromId = optimizeFromGraphEnd?odomPoses.rbegin()->first:odomPoses.begin()->first;
5831 std::map<int, rtabmap::Transform> posesOut;
5832 std::multimap<int, rtabmap::Link> linksOut;
5833 std::map<int, rtabmap::Transform> optimizedPoses;
5840 optimizedPoses = optimizer->
optimize(fromId, posesOut, linksOut);
5848 .arg(optimizedPoses.size()).arg(linksOut.size()).arg(sbaIterations));
5849 QApplication::processEvents();
5851 QApplication::processEvents();
5854 uInsert(parametersSBA, std::make_pair(Parameters::kOptimizerIterations(),
uNumber2Str(sbaIterations)));
5855 uInsert(parametersSBA, std::make_pair(Parameters::kg2oPixelVariance(),
uNumber2Str(sbaVariance)));
5857 std::map<int, Transform> newPoses = sba->
optimizeBA(optimizedPoses.begin()->first, optimizedPoses, linksOut,
_cachedSignatures.toStdMap());
5861 optimizedPoses = newPoses;
5907 QMessageBox::warning(
this, tr(
"Depth Calibration"), tr(
"No data in cache. Try to refresh the cache."));
5913 QMessageBox::StandardButton button;
5916 button = QMessageBox::question(
this,
5917 tr(
"Deleting memory..."),
5918 tr(
"The remote database and log files will be deleted. Are you sure you want to continue? (This cannot be reverted)"),
5919 QMessageBox::Yes|QMessageBox::No,
5924 button = QMessageBox::question(
this,
5925 tr(
"Deleting memory..."),
5926 tr(
"The current database and log files will be deleted. Are you sure you want to continue? (This cannot be reverted)"),
5927 QMessageBox::Yes|QMessageBox::No,
5931 if(button != QMessageBox::Yes)
5952 #if defined(Q_WS_MAC) 5955 args <<
"tell application \"Finder\"";
5959 args <<
"select POSIX file \""+filePath+
"\"";
5962 QProcess::startDetached(
"osascript", args);
5963 #elif defined(Q_WS_WIN) 5965 args <<
"/select," << QDir::toNativeSeparators(filePath);
5966 QProcess::startDetached(
"explorer", args);
5968 UERROR(
"Only works on Mac and Windows");
6069 UINFO(
"Sending a goal...");
6071 QString text = QInputDialog::getText(
this, tr(
"Send a goal"), tr(
"Goal location ID or label: "), QLineEdit::Normal,
"", &ok);
6072 if(ok && !text.isEmpty())
6083 UINFO(
"Sending waypoints...");
6085 QString text = QInputDialog::getText(
this, tr(
"Send waypoints"), tr(
"Waypoint IDs or labels (separated by spaces): "), QLineEdit::Normal,
"", &ok);
6086 if(ok && !text.isEmpty())
6088 QStringList wp = text.split(
' ');
6091 QMessageBox::warning(
this, tr(
"Send waypoints"), tr(
"At least two waypoints should be set. For only one goal, use send goal action."));
6107 int id = goal.toInt(&ok);
6108 _ui->graphicsView_graphView->setGlobalPath(std::vector<std::pair<int, Transform> >());
6109 UINFO(
"Posting event with goal %s", goal.toStdString().c_str());
6123 UINFO(
"Cancelling goal...");
6131 UINFO(
"Labelling current location...");
6133 QString
label = QInputDialog::getText(
this, tr(
"Label current location"), tr(
"Label: "), QLineEdit::Normal,
"", &ok);
6134 if(ok && !label.isEmpty())
6143 QString path = QFileDialog::getOpenFileName(
this, tr(
"Select file"), dir, tr(
"RTAB-Map database files (*.db)"));
6157 UINFO(
"Update cache...");
6165 std::list<Signature*> signaturesList;
6166 driver->
loadSignatures(std::list<int>(ids.begin(), ids.end()), signaturesList);
6167 std::map<int, Signature> signatures;
6169 for(std::list<Signature *>::iterator iter=signaturesList.begin(); iter!=signaturesList.end(); ++iter)
6171 signatures.insert(std::make_pair((*iter)->id(), *(*iter)));
6179 QMessageBox::warning(
this, tr(
"Update cache"), tr(
"Failed to open database \"%1\"").arg(path));
6188 items.append(
"Local map optimized");
6189 items.append(
"Local map not optimized");
6190 items.append(
"Global map optimized");
6191 items.append(
"Global map not optimized");
6194 QString item = QInputDialog::getItem(
this, tr(
"Download map"), tr(
"Options:"), items, 2,
false, &ok);
6197 bool optimized=
false, global=
false;
6198 if(item.compare(
"Local map optimized") == 0)
6202 else if(item.compare(
"Local map not optimized") == 0)
6206 else if(item.compare(
"Global map optimized") == 0)
6211 else if(item.compare(
"Global map not optimized") == 0)
6217 UFATAL(
"Item \"%s\" not found?!?", item.toStdString().c_str());
6220 UINFO(
"Download clouds...");
6224 .arg(global?
"true":
"false").arg(optimized?
"true":
"false"));
6232 items.append(
"Local map optimized");
6233 items.append(
"Local map not optimized");
6234 items.append(
"Global map optimized");
6235 items.append(
"Global map not optimized");
6238 QString item = QInputDialog::getItem(
this, tr(
"Download graph"), tr(
"Options:"), items, 2,
false, &ok);
6241 bool optimized=
false, global=
false;
6242 if(item.compare(
"Local map optimized") == 0)
6246 else if(item.compare(
"Local map not optimized") == 0)
6250 else if(item.compare(
"Global map optimized") == 0)
6255 else if(item.compare(
"Global map not optimized") == 0)
6261 UFATAL(
"Item \"%s\" not found?!?", item.toStdString().c_str());
6264 UINFO(
"Download the graph...");
6268 .arg(global?
"true":
"false").arg(optimized?
"true":
"false"));
6301 _ui->widget_mapVisibility->clear();
6309 _ui->statsToolBox->clear();
6311 _ui->actionExport_2D_Grid_map_bmp_png->setEnabled(
false);
6312 _ui->actionPost_processing->setEnabled(
false);
6313 _ui->actionSave_point_cloud->setEnabled(
false);
6314 _ui->actionExport_cameras_in_Bundle_format_out->setEnabled(
false);
6315 _ui->actionDepth_Calibration->setEnabled(
false);
6316 _ui->actionExport_images_RGB_jpg_Depth_png->setEnabled(
false);
6317 _ui->actionExport_octomap->setEnabled(
false);
6318 _ui->actionView_high_res_point_cloud->setEnabled(
false);
6325 _ui->label_stats_loopClosuresDetected->setText(
"0");
6326 _ui->label_stats_loopClosuresReactivatedDetected->setText(
"0");
6327 _ui->label_stats_loopClosuresRejected->setText(
"0");
6331 _ui->label_refId->clear();
6332 _ui->label_matchId->clear();
6333 _ui->graphicsView_graphView->clearAll();
6334 _ui->imageView_source->clear();
6335 _ui->imageView_loopClosure->clear();
6336 _ui->imageView_odometry->clear();
6337 _ui->imageView_source->setBackgroundColor(
_ui->imageView_source->getDefaultBackgroundColor());
6338 _ui->imageView_loopClosure->setBackgroundColor(
_ui->imageView_loopClosure->getDefaultBackgroundColor());
6339 _ui->imageView_odometry->setBackgroundColor(
_ui->imageView_odometry->getDefaultBackgroundColor());
6340 #ifdef RTABMAP_OCTOMAP 6354 QDesktopServices::openUrl(QUrl(
"http://wiki.ros.org/rtabmap_ros"));
6358 QDesktopServices::openUrl(QUrl(
"https://github.com/introlab/rtabmap/wiki"));
6366 QString format =
"hh:mm:ss";
6367 _ui->label_elapsedTime->setText((QTime().fromString(
_ui->label_elapsedTime->text(), format).addMSecs(
_elapsedTime->restart())).toString(format));
6373 QList<int> curvesPerFigure;
6374 QStringList curveNames;
6375 _ui->statsToolBox->getFiguresSetup(curvesPerFigure, curveNames);
6377 QStringList curvesPerFigureStr;
6378 for(
int i=0; i<curvesPerFigure.size(); ++i)
6380 curvesPerFigureStr.append(QString::number(curvesPerFigure[i]));
6382 for(
int i=0; i<curveNames.size(); ++i)
6384 curveNames[i].replace(
' ',
'_');
6395 if(!curvesPerFigure.isEmpty())
6397 QStringList curvesPerFigureList = curvesPerFigure.split(
" ");
6398 QStringList curvesNamesList = curveNames.split(
" ");
6401 for(
int i=0; i<curvesPerFigureList.size(); ++i)
6404 int count = curvesPerFigureList[i].toInt(&ok);
6407 QMessageBox::warning(
this,
"Loading failed",
"Corrupted figures setup...");
6412 _ui->statsToolBox->addCurve(curvesNamesList[j++].replace(
'_',
' '));
6413 for(
int k=1; k<count && j<curveNames.size(); ++k)
6415 _ui->statsToolBox->addCurve(curvesNamesList[j++].replace(
'_',
' '),
false);
6438 _ui->dockWidget_posterior->setVisible(
false);
6439 _ui->dockWidget_likelihood->setVisible(
false);
6440 _ui->dockWidget_rawlikelihood->setVisible(
false);
6441 _ui->dockWidget_statsV2->setVisible(
false);
6442 _ui->dockWidget_console->setVisible(
false);
6443 _ui->dockWidget_loopClosureViewer->setVisible(
false);
6444 _ui->dockWidget_mapVisibility->setVisible(
false);
6445 _ui->dockWidget_graphViewer->setVisible(
false);
6446 _ui->dockWidget_odometry->setVisible(
true);
6447 _ui->dockWidget_cloudViewer->setVisible(
true);
6448 _ui->dockWidget_imageView->setVisible(
true);
6450 _ui->toolBar_2->setVisible(
true);
6451 _ui->statusbar->setVisible(
false);
6463 items << QString(
"Synchronize with map update") << QString(
"Synchronize with odometry update");
6465 QString item = QInputDialog::getItem(
this, tr(
"Select synchronization behavior"), tr(
"Sync:"), items, 0,
false, &ok);
6466 if(ok && !item.isEmpty())
6468 if(item.compare(
"Synchronize with map update") == 0)
6479 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);
6480 if(r == QMessageBox::No || r == QMessageBox::Yes)
6486 _ui->actionAuto_screen_capture->setChecked(
false);
6489 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);
6490 if(r == QMessageBox::No || r == QMessageBox::Yes)
6496 _ui->actionAuto_screen_capture->setChecked(
false);
6502 _ui->actionAuto_screen_capture->setChecked(
false);
6509 if(!dir.exists(targetDir))
6511 dir.mkdir(targetDir);
6513 targetDir += QDir::separator();
6514 targetDir +=
"Main_window";
6515 if(!dir.exists(targetDir))
6517 dir.mkdir(targetDir);
6519 targetDir += QDir::separator();
6533 QApplication::processEvents();
6543 QDesktopServices::openUrl(QUrl::fromLocalFile(this->
captureScreen()));
6548 QRect rect = this->geometry();
6552 if(
float(rect.width())/
float(rect.height()) >
float(w)/float(h))
6554 rect.setWidth(w*(rect.height()/h));
6555 rect.setHeight((rect.height()/h)*h);
6559 rect.setHeight(h*(rect.width()/w));
6560 rect.setWidth((rect.width()/w)*w);
6569 this->setGeometry(rect);
6615 int width = QInputDialog::getInt(
this, tr(
"Aspect ratio"), tr(
"Width (pixels):"), this->geometry().width(), 100, 10000, 100, &ok);
6618 int height = QInputDialog::getInt(
this, tr(
"Aspect ratio"), tr(
"Height (pixels):"), this->geometry().height(), 100, 10000, 100, &ok);
6628 float gridCellSize = 0.05f;
6630 gridCellSize = (float)QInputDialog::getDouble(
this, tr(
"Grid cell size"), tr(
"Size (m):"), (double)gridCellSize, 0.01, 1, 2, &ok);
6637 float xMin=0.0f, yMin=0.0f;
6639 #ifdef RTABMAP_OCTOMAP 6653 cv::Mat map8U(pixels.rows, pixels.cols, CV_8U);
6655 for (
int i = 0; i < pixels.rows; ++i)
6657 for (
int j = 0; j < pixels.cols; ++j)
6659 char v = pixels.at<
char>(i, j);
6673 map8U.at<
unsigned char>(i, j) = gray;
6679 QString path = QFileDialog::getSaveFileName(
this, tr(
"Save to ..."),
"grid.png", tr(
"Image (*.png *.bmp)"));
6682 if(QFileInfo(path).suffix() !=
"png" && QFileInfo(path).suffix() !=
"bmp")
6688 QImage img = image.mirrored(
false,
true).transformed(QTransform().
rotate(-90));
6689 QPixmap::fromImage(img).save(path);
6691 QDesktopServices::openUrl(QUrl::fromLocalFile(path));
6703 std::map<int, Transform> poses =
_ui->widget_mapVisibility->getVisiblePoses();
6708 for(std::map<int, Transform>::iterator iter = poses.begin(); iter!=poses.end(); ++iter)
6713 iter->second = gtIter->second;
6717 UWARN(
"Not found ground truth pose for node %d", iter->first);
6740 std::map<int, Transform> poses =
_ui->widget_mapVisibility->getVisiblePoses();
6745 for(std::map<int, Transform>::iterator iter = poses.begin(); iter!=poses.end(); ++iter)
6750 iter->second = gtIter->second;
6754 UWARN(
"Not found ground truth pose for node %d", iter->first);
6773 #ifdef RTABMAP_OCTOMAP 6776 QString path = QFileDialog::getSaveFileName(
6780 tr(
"Octomap file (*.bt)"));
6786 QMessageBox::information(
this,
6787 tr(
"Export octomap..."),
6788 tr(
"Octomap successfully saved to \"%1\".")
6793 QMessageBox::information(
this,
6794 tr(
"Export octomap..."),
6795 tr(
"Failed to save octomap to \"%1\"!")
6802 UERROR(
"Empty octomap.");
6805 UERROR(
"Cannot export octomap, RTAB-Map is not built with it.");
6813 QMessageBox::warning(
this, tr(
"Export images..."), tr(
"Cannot export images, the cache is empty!"));
6816 std::map<int, Transform> poses =
_ui->widget_mapVisibility->getVisiblePoses();
6820 QMessageBox::warning(
this, tr(
"Export images..."), tr(
"There is no map!"));
6824 QStringList formats;
6825 formats.push_back(
"jpg");
6826 formats.push_back(
"png");
6828 QString ext = QInputDialog::getItem(
this, tr(
"Which RGB format?"), tr(
"Format:"), formats, 0,
false, &ok);
6834 QString path = QFileDialog::getExistingDirectory(
this, tr(
"Select directory where to save images..."), this->
getWorkingDirectory());
6846 dir.mkdir(QString(
"%1/left").arg(path));
6847 dir.mkdir(QString(
"%1/right").arg(path));
6850 std::string cameraName =
"calibration";
6868 if(model.save(path.toStdString()))
6870 UINFO(
"Saved stereo calibration \"%s\"", (path.toStdString()+
"/"+cameraName).c_str());
6874 UERROR(
"Failed saving calibration \"%s\"", (path.toStdString()+
"/"+cameraName).c_str());
6883 dir.mkdir(QString(
"%1/rgb").arg(path));
6884 dir.mkdir(QString(
"%1/depth").arg(path));
6889 UERROR(
"Only one camera calibration can be saved at this time (%d detected)", (
int)data.
cameraModels().size());
6893 std::string cameraName =
"calibration";
6901 if(model.save(path.toStdString()))
6903 UINFO(
"Saved calibration \"%s\"", (path.toStdString()+
"/"+cameraName).c_str());
6907 UERROR(
"Failed saving calibration \"%s\"", (path.toStdString()+
"/"+cameraName).c_str());
6913 QMessageBox::warning(
this,
6914 tr(
"Export images..."),
6915 tr(
"Data in the cache don't seem to have images (tested node %1). Calibration file will not be saved. Try refreshing the cache (with clouds).").arg(poses.rbegin()->first));
6922 unsigned int saved = 0;
6923 for(std::map<int, Transform>::iterator iter=poses.begin(); iter!=poses.end(); ++iter)
6925 int id = iter->first;
6936 cv::imwrite(QString(
"%1/left/%2.%3").arg(path).arg(
id).arg(ext).toStdString(), data.
imageRaw());
6937 cv::imwrite(QString(
"%1/right/%2.%3").arg(path).arg(
id).arg(ext).toStdString(), data.
rightRaw());
6938 info = tr(
"Saved left/%1.%2 and right/%1.%2.").arg(
id).arg(ext);
6942 cv::imwrite(QString(
"%1/rgb/%2.%3").arg(path).arg(
id).arg(ext).toStdString(), data.
imageRaw());
6944 info = tr(
"Saved rgb/%1.%2 and depth/%1.png.").arg(
id).arg(ext);
6948 cv::imwrite(QString(
"%1/%2.%3").arg(path).arg(
id).arg(ext).toStdString(), data.
imageRaw());
6949 info = tr(
"Saved %1.%2.").arg(
id).arg(ext);
6953 info = tr(
"No images saved for node %1!").arg(
id);
6959 QApplication::processEvents();
6962 if(saved!=poses.size())
6983 std::map<int, Transform> posesIn =
_ui->widget_mapVisibility->getVisiblePoses();
6988 for(std::map<int, Transform>::iterator iter = posesIn.begin(); iter!=posesIn.end(); ++iter)
6993 iter->second = gtIter->second;
6997 UWARN(
"Not found ground truth pose for node %d", iter->first);
7002 std::map<int, Transform> poses;
7003 for(std::map<int, Transform>::iterator iter=posesIn.begin(); iter!=posesIn.end(); ++iter)
7010 UWARN(
"Missing image in cache for node %d", iter->first);
7012 else if((
_cachedSignatures[iter->first].sensorData().cameraModels().size() == 1 &&
_cachedSignatures[iter->first].sensorData().cameraModels().at(0).isValidForProjection()) ||
7013 _cachedSignatures[iter->first].sensorData().stereoCameraModel().isValidForProjection())
7015 poses.insert(*iter);
7019 UWARN(
"Missing calibration for node %d", iter->first);
7024 UWARN(
"Did not find node %d in cache", iter->first);
7037 if(!QDir(path).mkpath(
"."))
7039 QMessageBox::warning(
this, tr(
"Exporting cameras..."), tr(
"Failed creating directory %1.").arg(path));
7043 QFile fileOut(path+QDir::separator()+
"cameras.out");
7044 QFile fileList(path+QDir::separator()+
"list.txt");
7045 QDir(path).mkdir(
"images");
7046 if(fileOut.open(QIODevice::WriteOnly | QIODevice::Text))
7048 if(fileList.open(QIODevice::WriteOnly | QIODevice::Text))
7050 std::set<int> ignoredCameras;
7051 for(std::map<int, Transform>::iterator iter=poses.begin(); iter!=poses.end(); ++iter)
7053 QString p = QString(
"images")+QDir::separator()+tr(
"%1.jpg").arg(iter->first);
7054 p = path+QDir::separator()+p;
7058 _cachedSignatures[iter->first].sensorData().uncompressDataConst(&image, 0, 0, 0);
7064 bool blurryImage =
false;
7065 const std::vector<float> & velocity =
_cachedSignatures[iter->first].getVelocity();
7066 if(maxLinearVel>0.0 || maxAngularVel>0.0)
7068 if(velocity.size() == 6)
7070 float transVel =
uMax3(fabs(velocity[0]), fabs(velocity[1]), fabs(velocity[2]));
7071 float rotVel =
uMax3(fabs(velocity[3]), fabs(velocity[4]), fabs(velocity[5]));
7072 if(maxLinearVel>0.0 && transVel > maxLinearVel)
7074 UWARN(
"Fast motion detected for camera %d (speed=%f m/s > thr=%f m/s), camera is ignored for texturing.", iter->first, transVel, maxLinearVel);
7077 else if(maxAngularVel>0.0 && rotVel > maxAngularVel)
7079 UWARN(
"Fast motion detected for camera %d (speed=%f rad/s > thr=%f rad/s), camera is ignored for texturing.", iter->first, rotVel, maxAngularVel);
7085 UWARN(
"Camera motion filtering is set, but velocity of camera %d is not available.", iter->first);
7089 if(!blurryImage && !image.empty() && laplacianThr>0.0)
7091 cv::Mat imgLaplacian;
7092 cv::Laplacian(image, imgLaplacian, CV_16S);
7094 cv::meanStdDev(imgLaplacian, m, s);
7095 double stddev_pxl = s.at<
double>(0);
7096 double var = stddev_pxl*stddev_pxl;
7097 if(var < laplacianThr)
7100 UWARN(
"Camera's image %d is detected as blurry (var=%f < thr=%f), camera is ignored for texturing.", iter->first, var, laplacianThr);
7105 ignoredCameras.insert(iter->first);
7109 if(cv::imwrite(p.toStdString(), image))
7111 UINFO(
"saved image %s", p.toStdString().c_str());
7115 UERROR(
"Failed to save image %s", p.toStdString().c_str());
7120 QTextStream out(&fileOut);
7121 QTextStream list(&fileList);
7122 out <<
"# Bundle file v0.3\n";
7123 out << poses.size()-ignoredCameras.size() <<
" 0\n";
7125 for(std::map<int, Transform>::iterator iter=poses.begin(); iter!=poses.end(); ++iter)
7127 if(ignoredCameras.find(iter->first) == ignoredCameras.end())
7129 QString p = QString(
"images")+QDir::separator()+tr(
"%1.jpg").arg(iter->first);
7135 out <<
_cachedSignatures[iter->first].sensorData().cameraModels().at(0).fx() <<
" 0 0\n";
7136 localTransform =
_cachedSignatures[iter->first].sensorData().cameraModels().at(0).localTransform();
7140 out <<
_cachedSignatures[iter->first].sensorData().stereoCameraModel().left().fx() <<
" 0 0\n";
7141 localTransform =
_cachedSignatures[iter->first].sensorData().stereoCameraModel().left().localTransform();
7145 0.0
f, -1.0
f, 0.0
f, 0.0
f,
7146 0.0
f, 0.0
f, 1.0
f, 0.0
f,
7147 -1.0
f, 0.0
f, 0.0
f, 0.0
f);
7149 static const Transform optical_rotation_inv(
7150 0.0
f, -1.0
f, 0.0
f, 0.0
f,
7151 0.0
f, 0.0
f, -1.0
f, 0.0
f,
7152 1.0
f, 0.0
f, 0.0
f, 0.0
f);
7155 if(!localTransform.
isNull())
7157 pose*=localTransform*optical_rotation_inv;
7161 out << poseGL.
r11() <<
" " << poseGL.
r12() <<
" " << poseGL.
r13() <<
"\n";
7162 out << poseGL.
r21() <<
" " << poseGL.
r22() <<
" " << poseGL.
r23() <<
"\n";
7163 out << poseGL.
r31() <<
" " << poseGL.
r32() <<
" " << poseGL.
r33() <<
"\n";
7164 out << poseGL.
x() <<
" " << poseGL.
y() <<
" " << poseGL.
z() <<
"\n";
7172 QMessageBox::information(
this,
7173 tr(
"Exporting cameras in Bundler format..."),
7174 tr(
"%1 cameras/images exported to directory \"%2\".%3")
7177 .arg(ignoredCameras.size()>0?tr(
" %1/%2 cameras ignored for too fast motion and/or blur level.").arg(ignoredCameras.size()).arg(poses.size()):
""));
7182 QMessageBox::warning(
this, tr(
"Exporting cameras..."), tr(
"Failed opening file %1 for writing.").arg(path+QDir::separator()+
"list.txt"));
7187 QMessageBox::warning(
this, tr(
"Exporting cameras..."), tr(
"Failed opening file %1 for writing.").arg(path+QDir::separator()+
"cameras.out"));
7193 QMessageBox::warning(
this, tr(
"Exporting cameras..."), tr(
"No poses exported because of missing images. Try refreshing the cache (with clouds)."));
7199 UINFO(
"reset odometry");
7205 UINFO(
"trigger a new map");
7216 int r = QMessageBox::question(
this, tr(
"Hard drive or RAM?"), tr(
"Save in RAM?"), QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
7218 if(r == QMessageBox::No || r == QMessageBox::Yes)
7220 bool recordInRAM = r == QMessageBox::Yes;
7225 _dataRecorder->setWindowTitle(tr(
"Data recorder (%1)").arg(path));
7236 _ui->actionData_recorder->setEnabled(
false);
7240 QMessageBox::warning(
this, tr(
""), tr(
"Cannot initialize the data recorder!"));
7241 UERROR(
"Cannot initialize the data recorder!");
7250 UERROR(
"Only one recorder at the same time.");
7256 _ui->actionData_recorder->setEnabled(
true);
7274 _ui->label_source->setVisible(!monitoring);
7275 _ui->label_stats_source->setVisible(!monitoring);
7276 _ui->actionNew_database->setVisible(!monitoring);
7277 _ui->actionOpen_database->setVisible(!monitoring);
7278 _ui->actionClose_database->setVisible(!monitoring);
7279 _ui->actionEdit_database->setVisible(!monitoring);
7280 _ui->actionStart->setVisible(!monitoring);
7281 _ui->actionStop->setVisible(!monitoring);
7282 _ui->actionDump_the_memory->setVisible(!monitoring);
7283 _ui->actionDump_the_prediction_matrix->setVisible(!monitoring);
7284 _ui->actionGenerate_map->setVisible(!monitoring);
7285 _ui->actionUpdate_cache_from_database->setVisible(monitoring);
7286 _ui->actionData_recorder->setVisible(!monitoring);
7287 _ui->menuSelect_source->menuAction()->setVisible(!monitoring);
7288 _ui->doubleSpinBox_stats_imgRate->setVisible(!monitoring);
7289 _ui->doubleSpinBox_stats_imgRate_label->setVisible(!monitoring);
7291 if(wasMonitoring != monitoring)
7293 _ui->toolBar->setVisible(!monitoring);
7294 _ui->toolBar->toggleViewAction()->setVisible(!monitoring);
7296 QList<QAction*> actions =
_ui->menuTools->actions();
7297 for(
int i=0; i<actions.size(); ++i)
7299 if(actions.at(i)->isSeparator())
7301 actions.at(i)->setVisible(!monitoring);
7304 actions =
_ui->menuFile->actions();
7305 if(actions.size()==16)
7307 if(actions.at(2)->isSeparator())
7309 actions.at(2)->setVisible(!monitoring);
7313 UWARN(
"Menu File separators have not the same order.");
7315 if(actions.at(12)->isSeparator())
7317 actions.at(12)->setVisible(!monitoring);
7321 UWARN(
"Menu File separators have not the same order.");
7326 UWARN(
"Menu File actions size has changed (%d)", actions.size());
7328 actions =
_ui->menuProcess->actions();
7329 if(actions.size()>=2)
7331 if(actions.at(1)->isSeparator())
7333 actions.at(1)->setVisible(!monitoring);
7337 UWARN(
"Menu File separators have not the same order.");
7342 UWARN(
"Menu File separators have not the same order.");
7350 _ui->actionNew_database->setEnabled(
true);
7351 _ui->actionOpen_database->setEnabled(
true);
7352 _ui->actionClose_database->setEnabled(
false);
7353 _ui->actionEdit_database->setEnabled(
true);
7354 _ui->actionStart->setEnabled(
false);
7355 _ui->actionPause->setEnabled(
false);
7356 _ui->actionPause->setChecked(
false);
7357 _ui->actionPause->setToolTip(tr(
"Pause"));
7358 _ui->actionStop->setEnabled(
false);
7359 _ui->actionPause_on_match->setEnabled(
true);
7360 _ui->actionPause_on_local_loop_detection->setEnabled(
true);
7361 _ui->actionPause_when_a_loop_hypothesis_is_rejected->setEnabled(
true);
7362 _ui->actionDump_the_memory->setEnabled(
false);
7363 _ui->actionDump_the_prediction_matrix->setEnabled(
false);
7364 _ui->actionDelete_memory->setEnabled(
false);
7367 _ui->actionGenerate_map->setEnabled(
false);
7372 #ifdef RTABMAP_OCTOMAP 7375 _ui->actionExport_octomap->setEnabled(
false);
7379 _ui->actionDownload_all_clouds->setEnabled(
false);
7380 _ui->actionDownload_graph->setEnabled(
false);
7381 _ui->menuSelect_source->setEnabled(
true);
7382 _ui->actionLabel_current_location->setEnabled(
false);
7383 _ui->actionSend_goal->setEnabled(
false);
7384 _ui->actionCancel_goal->setEnabled(
false);
7385 _ui->toolBar->findChild<QAction*>(
"toolbar_source")->setEnabled(
true);
7386 _ui->actionTrigger_a_new_map->setEnabled(
false);
7387 _ui->doubleSpinBox_stats_imgRate->setEnabled(
true);
7388 _ui->statusbar->clearMessage();
7395 _ui->actionStart->setEnabled(
false);
7396 _ui->actionPause->setEnabled(
false);
7397 _ui->actionStop->setEnabled(
false);
7402 _ui->actionNew_database->setEnabled(
false);
7403 _ui->actionOpen_database->setEnabled(
false);
7404 _ui->actionClose_database->setEnabled(
false);
7405 _ui->actionEdit_database->setEnabled(
false);
7410 _ui->actionNew_database->setEnabled(
false);
7411 _ui->actionOpen_database->setEnabled(
false);
7412 _ui->actionClose_database->setEnabled(
true);
7413 _ui->actionEdit_database->setEnabled(
false);
7414 _ui->actionStart->setEnabled(
true);
7415 _ui->actionPause->setEnabled(
false);
7416 _ui->actionPause->setChecked(
false);
7417 _ui->actionPause->setToolTip(tr(
"Pause"));
7418 _ui->actionStop->setEnabled(
false);
7419 _ui->actionPause_on_match->setEnabled(
true);
7420 _ui->actionPause_on_local_loop_detection->setEnabled(
true);
7421 _ui->actionPause_when_a_loop_hypothesis_is_rejected->setEnabled(
true);
7422 _ui->actionDump_the_memory->setEnabled(
true);
7423 _ui->actionDump_the_prediction_matrix->setEnabled(
true);
7427 _ui->actionGenerate_map->setEnabled(
true);
7432 #ifdef RTABMAP_OCTOMAP 7435 _ui->actionExport_octomap->setEnabled(
false);
7439 _ui->actionDownload_all_clouds->setEnabled(
true);
7440 _ui->actionDownload_graph->setEnabled(
true);
7441 _ui->menuSelect_source->setEnabled(
true);
7442 _ui->actionLabel_current_location->setEnabled(
true);
7443 _ui->actionSend_goal->setEnabled(
true);
7444 _ui->actionCancel_goal->setEnabled(
true);
7445 _ui->toolBar->findChild<QAction*>(
"toolbar_source")->setEnabled(
true);
7446 _ui->actionTrigger_a_new_map->setEnabled(
true);
7447 _ui->doubleSpinBox_stats_imgRate->setEnabled(
true);
7448 _ui->statusbar->clearMessage();
7454 _ui->actionStart->setEnabled(
false);
7459 _ui->actionNew_database->setEnabled(
false);
7460 _ui->actionOpen_database->setEnabled(
false);
7461 _ui->actionClose_database->setEnabled(
false);
7462 _ui->actionEdit_database->setEnabled(
false);
7463 _ui->actionStart->setEnabled(
false);
7464 _ui->actionPause->setEnabled(
true);
7465 _ui->actionPause->setChecked(
false);
7466 _ui->actionPause->setToolTip(tr(
"Pause"));
7467 _ui->actionStop->setEnabled(
true);
7468 _ui->actionPause_on_match->setEnabled(
true);
7469 _ui->actionPause_on_local_loop_detection->setEnabled(
true);
7470 _ui->actionPause_when_a_loop_hypothesis_is_rejected->setEnabled(
true);
7471 _ui->actionDump_the_memory->setEnabled(
false);
7472 _ui->actionDump_the_prediction_matrix->setEnabled(
false);
7473 _ui->actionDelete_memory->setEnabled(
false);
7474 _ui->actionPost_processing->setEnabled(
false);
7475 _ui->actionExport_images_RGB_jpg_Depth_png->setEnabled(
false);
7476 _ui->actionGenerate_map->setEnabled(
false);
7477 _ui->menuExport_poses->setEnabled(
false);
7478 _ui->actionSave_point_cloud->setEnabled(
false);
7479 _ui->actionView_high_res_point_cloud->setEnabled(
false);
7480 _ui->actionExport_2D_Grid_map_bmp_png->setEnabled(
false);
7481 _ui->actionExport_octomap->setEnabled(
false);
7482 _ui->actionExport_cameras_in_Bundle_format_out->setEnabled(
false);
7483 _ui->actionDepth_Calibration->setEnabled(
false);
7484 _ui->actionDownload_all_clouds->setEnabled(
false);
7485 _ui->actionDownload_graph->setEnabled(
false);
7486 _ui->menuSelect_source->setEnabled(
false);
7487 _ui->actionLabel_current_location->setEnabled(
true);
7488 _ui->actionSend_goal->setEnabled(
true);
7489 _ui->actionCancel_goal->setEnabled(
true);
7490 _ui->toolBar->findChild<QAction*>(
"toolbar_source")->setEnabled(
false);
7491 _ui->actionTrigger_a_new_map->setEnabled(
true);
7492 _ui->doubleSpinBox_stats_imgRate->setEnabled(
true);
7493 _ui->statusbar->showMessage(tr(
"Detecting..."));
7495 _ui->label_elapsedTime->setText(
"00:00:00");
7515 _ui->actionPause->setToolTip(tr(
"Pause"));
7516 _ui->actionPause->setChecked(
false);
7517 _ui->statusbar->showMessage(tr(
"Detecting..."));
7518 _ui->actionDump_the_memory->setEnabled(
false);
7519 _ui->actionDump_the_prediction_matrix->setEnabled(
false);
7520 _ui->actionDelete_memory->setEnabled(
false);
7521 _ui->actionPost_processing->setEnabled(
false);
7522 _ui->actionExport_images_RGB_jpg_Depth_png->setEnabled(
false);
7523 _ui->actionGenerate_map->setEnabled(
false);
7524 _ui->menuExport_poses->setEnabled(
false);
7525 _ui->actionSave_point_cloud->setEnabled(
false);
7526 _ui->actionView_high_res_point_cloud->setEnabled(
false);
7527 _ui->actionExport_2D_Grid_map_bmp_png->setEnabled(
false);
7528 _ui->actionExport_octomap->setEnabled(
false);
7529 _ui->actionExport_cameras_in_Bundle_format_out->setEnabled(
false);
7530 _ui->actionDepth_Calibration->setEnabled(
false);
7531 _ui->actionDownload_all_clouds->setEnabled(
false);
7532 _ui->actionDownload_graph->setEnabled(
false);
7549 _ui->actionPause->setToolTip(tr(
"Continue (shift-click for step-by-step)"));
7550 _ui->actionPause->setChecked(
true);
7551 _ui->statusbar->showMessage(tr(
"Paused..."));
7552 _ui->actionDump_the_memory->setEnabled(
true);
7553 _ui->actionDump_the_prediction_matrix->setEnabled(
true);
7554 _ui->actionDelete_memory->setEnabled(
false);
7557 _ui->actionGenerate_map->setEnabled(
true);
7562 #ifdef RTABMAP_OCTOMAP 7565 _ui->actionExport_octomap->setEnabled(
false);
7569 _ui->actionDownload_all_clouds->setEnabled(
true);
7570 _ui->actionDownload_graph->setEnabled(
true);
7586 _ui->actionPause->setEnabled(
true);
7587 _ui->actionPause->setChecked(
false);
7588 _ui->actionPause->setToolTip(tr(
"Pause"));
7589 _ui->actionPause_on_match->setEnabled(
true);
7590 _ui->actionPause_on_local_loop_detection->setEnabled(
true);
7591 _ui->actionPause_when_a_loop_hypothesis_is_rejected->setEnabled(
true);
7592 _ui->actionReset_Odometry->setEnabled(
true);
7593 _ui->actionPost_processing->setEnabled(
false);
7594 _ui->actionExport_images_RGB_jpg_Depth_png->setEnabled(
false);
7595 _ui->menuExport_poses->setEnabled(
false);
7596 _ui->actionSave_point_cloud->setEnabled(
false);
7597 _ui->actionView_high_res_point_cloud->setEnabled(
false);
7598 _ui->actionExport_2D_Grid_map_bmp_png->setEnabled(
false);
7599 _ui->actionExport_octomap->setEnabled(
false);
7600 _ui->actionExport_cameras_in_Bundle_format_out->setEnabled(
false);
7601 _ui->actionDepth_Calibration->setEnabled(
false);
7602 _ui->actionDelete_memory->setEnabled(
true);
7603 _ui->actionDownload_all_clouds->setEnabled(
true);
7604 _ui->actionDownload_graph->setEnabled(
true);
7605 _ui->actionTrigger_a_new_map->setEnabled(
true);
7606 _ui->actionLabel_current_location->setEnabled(
true);
7607 _ui->actionSend_goal->setEnabled(
true);
7608 _ui->actionCancel_goal->setEnabled(
true);
7609 _ui->statusbar->showMessage(tr(
"Monitoring..."));
7616 _ui->actionPause->setToolTip(tr(
"Continue"));
7617 _ui->actionPause->setChecked(
true);
7618 _ui->actionPause->setEnabled(
true);
7619 _ui->actionPause_on_match->setEnabled(
true);
7620 _ui->actionPause_on_local_loop_detection->setEnabled(
true);
7621 _ui->actionPause_when_a_loop_hypothesis_is_rejected->setEnabled(
true);
7622 _ui->actionReset_Odometry->setEnabled(
true);
7629 #ifdef RTABMAP_OCTOMAP 7632 _ui->actionExport_octomap->setEnabled(
false);
7636 _ui->actionDelete_memory->setEnabled(
true);
7637 _ui->actionDownload_all_clouds->setEnabled(
true);
7638 _ui->actionDownload_graph->setEnabled(
true);
7639 _ui->actionTrigger_a_new_map->setEnabled(
true);
7640 _ui->actionLabel_current_location->setEnabled(
true);
7641 _ui->actionSend_goal->setEnabled(
true);
7642 _ui->actionCancel_goal->setEnabled(
true);
7643 _ui->statusbar->showMessage(tr(
"Monitoring paused..."));
int getOctomapTreeDepth() const
const std::map< int, Transform > & getPoses() const
const std::multimap< int, cv::Point3f > & getWords3() const
static void setPrintThreadId(bool printThreadId)
int UTILITE_EXP uStr2Int(const std::string &str)
LaserScan RTABMAP_EXP laserScanFromPointCloud(const pcl::PCLPointCloud2 &cloud, bool filterNaNs=true)
const std::string & getInfo() const
GLM_FUNC_DECL T roll(detail::tquat< T, P > const &x)
double getCloudFilteringAngle() const
int getCloudColorScheme(int index) const
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 isSourceDatabaseStampsUsed() const
void setAutoClose(bool on, int delayedClosingTimeMsec=-1)
double sbaVariance() const
int getNoiseMinNeighbors() const
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)
void setAspectRatio(int w, int h)
std::vector< cv::Point2f > refCorners
Camera * createCamera(bool useRawImages=false, bool useColor=true)
void changeImgRateSetting()
double getScanMinRange(int index) const
void saveMainWindowState(const QMainWindow *mainWindow)
int getGeneralLoggerPauseLevel() const
void updateParameters(const ParametersMap ¶meters, bool setOtherParametersToDefault=false)
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 >(), bool g2oRobust=false)
QString getIMUPath() const
int getScanNormalKSearch() const
static void createPipe(const UEventsSender *sender, const UEventsHandler *receiver, const std::string &eventName)
bool isOdomOnlyInliersShown() const
bool getGridMapShown() const
void applyPrefSettings(PreferencesDialog::PANEL_FLAGS flags)
std::map< int, CameraModel > localBundleModels
void setStereoExposureCompensation(bool enabled)
Transform transformGroundTruth
float getCellSize() const
std::map< int, Transform > RTABMAP_EXP radiusPosesFiltering(const std::map< int, Transform > &poses, float radius, float angle, bool keepLatest=true)
GLM_FUNC_DECL genType min(genType const &x, genType const &y)
bool isCloudMeshingQuad() const
double getSubtractFilteringRadius() const
void setCancelButtonVisible(bool visible)
bool init(const std::string &path)
int getGeneralLoggerLevel() const
double getCeilingFilteringHeight() const
QString _newDatabasePathOutput
const cv::Mat & R() 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)
bool isRefineNeighborLinks() const
const std::multimap< int, cv::KeyPoint > & getWords() const
void setWords3(const std::multimap< int, cv::Point3f > &words3)
virtual size_t memoryUsage() const
virtual void showEvent(QShowEvent *anEvent)
void setCloudVisibility(const std::string &id, bool isVisible)
void setAspectRatio1080p()
bool uIsInBounds(const T &value, const T &low, const T &high)
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)
Transform transformFiltered
const std::map< int, Signature > & getSignatures() const
void update(const std::map< int, Transform > &poses)
std::map< int, float > _cachedLocalizationsCount
void setWords(const std::multimap< int, cv::KeyPoint > &words)
void setMonitoringState(bool monitoringState)
Transform computeTransformation(const Signature &from, const Signature &to, Transform guess=Transform::getIdentity(), RegistrationInfo *info=0) const
GLM_FUNC_DECL vecType< T, P > sqrt(vecType< T, P > const &x)
const Statistics & getStats() const
const std::map< int, float > & likelihood() const
void getAllNodeIds(std::set< int > &ids, bool ignoreChildren=false, bool ignoreBadSignatures=false) const
PreferencesDialog * _preferencesDialog
std::map< int, cv::Point3f > localMap
void removeFrustum(const std::string &id)
int proximityDetectionId() const
std::pair< std::string, std::string > ParametersPair
int getKpMaxFeatures() const
bool imageHighestHypShown() const
pcl::PointCloud< pcl::PointXYZRGBNormal >::Ptr RTABMAP_EXP laserScanToPointCloudRGBNormal(const LaserScan &laserScan, const Transform &transform=Transform(), unsigned char r=255, unsigned char g=255, unsigned char b=255)
bool UTILITE_EXP uStr2Bool(const char *str)
const std::map< int, float > & posterior() const
bool removeCloud(const std::string &id)
void noMoreImagesReceived()
bool isStatisticsPublished() const
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)
virtual QString getIniFilePath() const
rtabmap::CameraThread * _camera
void enableBilateralFiltering(float sigmaS, float sigmaR)
OdometryInfo copyWithoutData() const
bool _autoScreenCaptureOdomSync
void rtabmapLabelErrorReceived(int id, const QString &label)
virtual void stopDetection()
QString getWorkingDirectory() const
int getOctomapRenderingType() const
void timeLimitChanged(float)
bool isSourceRGBDColorOnly() const
const std::multimap< int, Link > & getConstraints() const
float UTILITE_EXP uStr2Float(const std::string &str)
std::vector< float > getCloudRoiRatios(int index) const
bool addOccupancyGridMap(const cv::Mat &map8U, float resolution, float xMin, float yMin, float opacity)
std::vector< int > RTABMAP_EXP findNearestNodes(const std::map< int, rtabmap::Transform > &nodes, const rtabmap::Transform &targetPose, int k)
QString _openedDatabasePath
std::multimap< int, Link > _currentLinksMap
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)
const cv::Mat & F() const
rtabmap::OdometryThread * _odomThread
std::map< std::string, std::string > ParametersMap
virtual void openDatabase()
void imgRateChanged(double)
virtual void changeState(MainWindow::State state)
double getGeneralInputRate() const
void setData(const Signature &sA, const Signature &sB)
int getCloudMeshingTriangleSize()
float timeParticleFiltering
void setCameraModels(const std::vector< CameraModel > &models)
const QColor & getDefaultBackgroundColor() const
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
rtabmap::LoopClosureViewer * loopClosureViewer() const
void selectStereoFlyCapture2()
void update(const std::map< int, Transform > &poses)
Some conversion functions.
bool isLocalizationsCountGraphView() const
virtual void openPreferencesSource()
void setupMainLayout(bool vertical)
virtual void keyPressEvent(QKeyEvent *event)
void updateNodeVisibility(int, bool)
double getScanMaxRange(int index) const
std::string getExtension()
void setImageRate(float imageRate)
static void setTreadIdFilter(const std::set< unsigned long > &ids)
const LaserScan & laserScanRaw() const
bool isGraphsShown() const
GLM_FUNC_DECL T pitch(detail::tquat< T, P > const &x)
std::vector< std::string > getGeneralLoggerThreads() const
std::vector< CameraModel > _rectCameraModels
const Transform & groundTruth() const
const cv::Mat & imageRaw() const
QMap< int, QString > _exportPosesFileName
int localBundleConstraints
static void setLevel(ULogger::Level level)
virtual void saveConfigGUI()
long _createdCloudsMemoryUsage
const std::string & getGoalLabel() const
void stateChanged(MainWindow::State)
double maxAngularSpeed() const
const std::map< int, int > & weights() const
static bool isAvailable(Optimizer::Type type)
virtual void pauseDetection()
int getSourceScanFromDepthDecimation() const
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 isGroundTruthAligned() const
std::pair< pcl::PointCloud< pcl::PointXYZRGB >::Ptr, pcl::IndicesPtr > createAndAddCloudToMap(int nodeId, const Transform &pose, int mapId)
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 getCloudVoxelSizeScan(int index) const
Transform getIMULocalTransform() const
void setUserDataRaw(const cv::Mat &userDataRaw)
void post(UEvent *event, bool async=true) const
bool isOdomDisabled() const
double getCloudOpacity(int index) const
virtual void resetOdometry()
const State & state() const
void rtabmapGlobalPathEventReceived(const rtabmap::RtabmapGlobalPathEvent &event)
void updateView(const Transform &AtoB=Transform(), const ParametersMap ¶meters=ParametersMap())
void setImageRaw(const cv::Mat &imageRaw)
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())
bool addCloud(const std::string &id, const pcl::PCLPointCloud2Ptr &binaryCloud, const Transform &pose, bool rgb, bool hasNormals, bool hasIntensity, const QColor &color=QColor())
int getGeneralLoggerEventLevel() const
bool isSubtractFiltering() const
void setAspectRatio240p()
std::map< int, Transform > _currentPosesMap
Transform _odometryCorrection
cv::Mat RTABMAP_EXP laserScan2dFromPointCloud(const pcl::PointCloud< pcl::PointXYZ > &cloud, const Transform &transform=Transform(), bool filterNaNs=true)
std::pair< int, std::pair< std::pair< pcl::PointCloud< pcl::PointXYZRGB >::Ptr, pcl::PointCloud< pcl::PointXYZRGBNormal >::Ptr >, pcl::IndicesPtr > > _previousCloud
QString outputPath() const
PreferencesDialog::Src getSourceDriver() const
void saveCustomConfig(const QString §ion, const QString &key, const QString &value)
bool openConnection(const std::string &url, bool overwritten=false)
#define UASSERT(condition)
QString getSourceDistortionModel() const
void setColorOnly(bool colorOnly)
void statsReceived(const rtabmap::Statistics &)
void clearOccupancyGridRaw()
std::map< int, LaserScan > _createdScans
double getPlanningTime() const
void processCameraInfo(const rtabmap::CameraInfo &info)
Wrappers of STL for convenient functions.
const std::map< std::string, float > & data() const
double getSourceScanNormalsRadius() const
bool isSourceMirroring() const
virtual void resizeEvent(QResizeEvent *anEvent)
void setLoopClosureViewer(rtabmap::LoopClosureViewer *loopClosureViewer)
Optimizer::Type sbaType() const
void addToCache(int nodeId, const pcl::PointCloud< pcl::PointXYZRGB >::Ptr &ground, const pcl::PointCloud< pcl::PointXYZRGB >::Ptr &obstacles, const pcl::PointXYZ &viewPoint)
float timeStereoExposureCompensation
const Transform & pose() const
const std::map< int, Transform > & addedNodes() const
bool isValidForProjection() const
virtual bool isCalibrated() const =0
virtual bool handleEvent(UEvent *anEvent)
const CameraModel & left() const
void notifyNoMoreImages()
void setAspectRatio16_9()
double getFloorFilteringHeight() const
float getDetectionRate() const
void mappingModeChanged(bool)
void selectSourceDriver(Src src)
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)
T uMax3(const T &a, const T &b, const T &c)
bool isBilateralFiltering() const
static void setPrintTime(bool printTime)
#define ULOGGER_DEBUG(...)
void setDecimation(int decimation)
std::vector< int > cornerInliers
bool isPosteriorGraphView() const
bool isSourceStereoDepthGenerated() const
QImage uCvMat2QImage(const cv::Mat &image, bool isBgr=true, uCvQtDepthColorMap colorMap=uCvQtDepthWhiteToBlack)
void addOrUpdateFrustum(const std::string &id, const Transform &transform, const Transform &localTransform, double scale, const QColor &color=QColor())
#define UASSERT_MSG(condition, msg_str)
double getScanNormalRadiusSearch() const
void closeConnection(bool save=true, const std::string &outputUrl="")
bool isTimeUsedInFigures() const
void addToCache(int nodeId, const cv::Mat &ground, const cv::Mat &obstacles, const cv::Mat &empty)
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)
double getCloudFilteringRadius() const
void loadSignatures(const std::list< int > &ids, std::list< Signature * > &signatures, std::set< int > *loadedFromTrash=0)
double laplacianThreshold() const
void dataRecorderDestroyed()
void cameraInfoReceived(const rtabmap::CameraInfo &)
bool isLabelsShown() const
rtabmap::OctoMap * _octomap
float getFrustumScale() const
double getNoiseRadius() const
int getDownsamplingStepScan(int index) const
bool isCloudMeshingTexture() const
double getSourceScanVoxelSize() const
const cv::Mat & T() 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()
const cv::Mat & E() const
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)
rtabmap::IMUThread * _imuThread
static void registerCurrentThread(const std::string &name)
int sbaIterations() const
double clusterAngle() 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)
int getCloudDecimation(int index) const
void cameraInfoProcessed()
void removeOccupancyGridMap()
std::map< int, Transform > localBundlePoses
std::map< int, std::pair< pcl::PointCloud< pcl::PointXYZRGB >::Ptr, pcl::IndicesPtr > > _cachedClouds
bool isWordsCountGraphView() const
void setCloudPointSize(const std::string &id, int size)
static void setEventLevel(ULogger::Level eventSentLevel)
int getScanPointSize(int index) const
void openWorkingDirectory()
static const rtabmap::Transform opengl_world_T_rtabmap_world(0.0f,-1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f,-1.0f, 0.0f, 0.0f, 0.0f)
int getOctomapPointSize() const
void setWordsDescriptors(const std::multimap< int, cv::Mat > &descriptors)
bool isSourceStereoExposureCompensation() 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) const
void anchorCloudsToGroundTruth()
std::map< int, std::string > _currentLabels
void printLoopClosureIds()
virtual void closeEvent(QCloseEvent *event)
int getSourceImageDecimation() const
const RtabmapColorOcTree * octree() const
void changeTimeLimitSetting()
cv::Mat RTABMAP_EXP computeNormals(const cv::Mat &laserScan, int searchK, float searchRadius)
void setMaximumSteps(int steps)
bool isCloudMeshing() const
static Odometry * create(const ParametersMap ¶meters)
rtabmap::ProgressDialog * progressDialog()
void exportPoses(int format)
void updateCameraTargetPosition(const Transform &pose)
void updateParameters(const rtabmap::ParametersMap ¶meters)
void saveWindowGeometry(const QWidget *window)
long getMemoryUsed() const
Transform localTransform() const
bool isCacheSavedInFigures() const
bool isFeaturesShown(int index) const
void loadNodeData(std::list< Signature * > &signatures, bool images=true, bool scan=true, bool userData=true, bool occupancyGrid=true) const
void processRtabmapLabelErrorEvent(int id, const QString &label)
std::list< std::string > uSplitNumChar(const std::string &str)
const cv::Mat & depthOrRightRaw() const
const OdometryInfo & info() 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)
const QColor & getBackgroundColor() const
int getCloudPointSize(int index) const
void setDistortionModel(const std::string &path)
int loopClosureId() const
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
bool openDatabase(const QString &path)
const QMap< std::string, Transform > & getAddedClouds() const
virtual void deleteMemory()
PdfPlotCurve * _posteriorCurve
int getSubtractFilteringMinPts() const
bool isScansShown(int index) const
void setMirroringEnabled(bool enabled)
bool _autoScreenCaptureRAM
void setBackgroundColor(const QColor &color)
bool uContains(const std::list< V > &list, const V &value)
double getCloudMeshingAngle() const
bool updateFrustumPose(const std::string &id, const Transform &pose)
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)
bool isFrustumsShown(int index) const
const Transform & loopClosureTransform() const
virtual void triggerNewMap()
double getScanCeilingFilteringHeight() const
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())
void exportBundlerFormat()
std::map< int, pcl::PointCloud< pcl::PointXYZRGB >::Ptr > _createdFeatures
void setImageDecimation(int decimation)
int getNormalKSearch() const
QMap< int, Signature > _cachedSignatures
void selectStereoDC1394()
bool isVerticalLayoutUsed() const
void registerToEventsManager()
static void initGuiResource()
bool getCloudVisibility(const std::string &id)
static std::string getType(const std::string ¶mKey)
virtual void clearTheCache()
QMap< QString, QByteArray > _autoScreenCaptureCachedImages
MainWindow(PreferencesDialog *prefDialog=0, QWidget *parent=0, bool showSplashScreen=true)
double maxLinearSpeed() const
void uSleep(unsigned int ms)
const std::map< int, Transform > & poses() const
double getScanOpacity(int index) const
void setCloudViewer(rtabmap::CloudViewer *cloudViewer)
pcl::IndicesPtr RTABMAP_EXP radiusFiltering(const pcl::PointCloud< pcl::PointXYZ >::Ptr &cloud, float radiusSearch, int minNeighborsInRadius)
virtual void moveEvent(QMoveEvent *anEvent)
void processRtabmapEvent3DMap(const rtabmap::RtabmapEvent3DMap &event)
cv::Mat RTABMAP_EXP convertMap2Image8U(const cv::Mat &map8S, bool pgmFormat=false)
PdfPlotCurve * _rawLikelihoodCurve
static const ParametersMap & getDefaultParameters()
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, bool verboseProgress=false, std::map< std::string, float > *stats=0)
const std::vector< std::pair< int, Transform > > & getPoses() const
QString loadCustomConfig(const QString §ion, const QString &key)
const std::vector< CameraModel > & cameraModels() const
std::string getParameter(const std::string &key) const
void addOrUpdateGraph(const std::string &id, const pcl::PointCloud< pcl::PointXYZ >::Ptr &graph, const QColor &color=Qt::gray)
virtual bool odomProvided() const
std::vector< V > uValues(const std::multimap< K, V > &mm)
rtabmap::OccupancyGrid * _occupancyGrid
virtual void setDefaultViews()
void setScanFromDepth(bool enabled, int decimation=4, float maxDepth=4.0f, float voxelSize=0.0f, int normalsK=0, int normalsRadius=0.0f)
static Registration * create(const ParametersMap ¶meters)
void setStereoToDepth(bool enabled)
QString getWorkingDirectory() const
virtual std::map< int, Transform > optimizeBA(int rootId, const std::map< int, Transform > &poses, const std::multimap< int, Link > &links, const std::map< int, CameraModel > &models, std::map< int, cv::Point3f > &points3DMap, const std::map< int, std::map< int, cv::Point3f > > &wordReferences, std::set< int > *outliers=0)
virtual void startDetection()
std::map< int, float > _cachedWordsCount
bool isSourceScanFromDepth() const
virtual bool closeDatabase()
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)
const CameraInfo & info() const
void updateCameraFrustums(const Transform &pose, const std::vector< CameraModel > &models)
const CameraModel & right() const
bool getGeneralLoggerPrintThreadId() const
std::map< int, int > _currentMapIds
std::list< K > uKeysList(const std::multimap< K, V > &mm)
std::multimap< int, Link >::iterator RTABMAP_EXP findLink(std::multimap< int, Link > &links, int from, int to, bool checkBothWays=true)
void postGoal(const QString &goal)
int getFeaturesPointSize(int index) const
void showCloseButton(bool visible=true)
void processRtabmapEventInit(int status, const QString &info)
bool writeBinary(const std::string &path)
static void addHandler(UEventsHandler *handler)
double getNormalRadiusSearch() const
void loopClosureThrChanged(float)
bool RTABMAP_EXP databaseRecovery(const std::string &corruptedDatabase, bool keepCorruptedDatabase=true, std::string *errorMsg=0, ProgressState *progressState=0)
const std::multimap< int, Link > & constraints() const
bool isCloudsKept() const
pcl::PointCloud< pcl::PointNormal >::Ptr RTABMAP_EXP laserScanToPointCloudNormal(const LaserScan &laserScan, const Transform &transform=Transform())
bool isSavedMaximized() const
const QMap< std::string, Transform > & getAddedFrustums() const
static const std::map< std::string, float > & defaultData()
QString getSourceDriverStr() const
double clusterRadius() const
bool isOctomapUpdated() const
ParametersMap getLastParameters() const
void setCurrentPanelToSource()
virtual void downloadPoseGraph()
ULogger class and convenient macros.
const StereoCameraModel & stereoCameraModel() const
void setAspectRatioCustom()
void loadWindowGeometry(QWidget *window)
void setBackfaceCulling(bool enabled, bool frontfaceCulling)
double getBilateralSigmaR() const
void setAspectRatio360p()
ProgressDialog * _progressDialog
PostProcessingDialog * _postProcessingDialog
int currentGoalId() const
float timeImageDecimation
AboutDialog * _aboutDialog
void setCameraTargetFollow(bool enabled=true)
ExportBundlerDialog * _exportBundlerDialog
bool getGeneralLoggerPrintTime() const
GLM_FUNC_DECL T yaw(detail::tquat< T, P > const &x)
void setAspectRatio16_10()
std::vector< int > matchesIDs
bool isCloudFiltering() const
std::vector< cv::Point2f > newCorners
bool isImagesKept() const
bool isOctomapShown() const
void setCloudColorIndex(const std::string &id, int index)
int getOdomStrategy() const
void parseParameters(const ParametersMap ¶meters)
Transform alignPosesToGroundTruth(const std::map< int, Transform > &poses, const std::map< int, Transform > &groundTruth)
double getSourceScanFromDepthMaxDepth() const
double getBilateralSigmaS() const
bool init(const QString &path, bool recordInRAM=true)
double getScanFloorFilteringHeight() const
cv::Mat RTABMAP_EXP cvtDepthFromFloat(const cv::Mat &depth32F)
bool isDepthFilteringAvailable() const
const SensorData & data() const
bool _processingStatistics
const std::string & label() const
void exportPosesRGBDSLAM()
double getLoopThr() const
bool isDetectMoreLoopClosures() const
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, bool forceGroundNormalsUp=false)
cv::Mat createProjectionMap(float &xMin, float &yMin, float &gridCellSize, float minGridSize=0.0f, unsigned int treeDepth=0)
static 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, int depth=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())
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)
virtual bool eventFilter(QObject *obj, QEvent *event)
double getSubtractFilteringAngle() const
void processOdometry(const rtabmap::OdometryEvent &odom, bool dataIgnored)
void rtabmapEvent3DMapReceived(const rtabmap::RtabmapEvent3DMap &event)
void selectOpenniCvAsus()
double getCloudMaxDepth(int index) const
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)
const Transform & mapCorrection() const
const std::vector< int > & localPath() const
int getGeneralLoggerType() const
int getSourceScanNormalsK() const
void drawKeypoints(const std::multimap< int, cv::KeyPoint > &refWords, const std::multimap< int, cv::KeyPoint > &loopWords)
QVector< int > _loopClosureIds
const Transform & localTransform() const
void setDepthOrRightRaw(const cv::Mat &depthOrImageRaw)
bool isCloudsShown(int index) const
float RTABMAP_EXP computePathLength(const std::vector< std::pair< int, Transform > > &path, unsigned int fromIndex=0, unsigned int toIndex=0)
bool notifyWhenNewGlobalPathIsReceived() const
std::string UTILITE_EXP uFormat(const char *fmt,...)
int getOdomRegistrationApproach() const
std::string UTILITE_EXP uNumber2Str(unsigned int number)
ExportCloudsDialog * _exportCloudsDialog
cv::Mat getMap(float &xMin, float &yMin) const
bool getPose(const std::string &id, Transform &pose)
void createAndAddFeaturesToMap(int nodeId, const Transform &pose, int mapId)
int getScanColorScheme(int index) const
bool isOctomap2dGrid() const
bool _autoScreenCapturePNG
virtual size_t size() const
int getOdomQualityWarnThr() const
virtual QString getTmpIniFilePath() const
DataRecorder * _dataRecorder
const std::map< int, Transform > & addedNodes() const
static Optimizer * create(const ParametersMap ¶meters)
pcl::PointCloud< pcl::PointXYZRGB >::Ptr RTABMAP_EXP laserScanToPointCloudRGB(const LaserScan &laserScan, const Transform &transform=Transform(), unsigned char r=255, unsigned char g=255, unsigned char b=255)
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()
rtabmap::CloudViewer * cloudViewer() const
bool isRefineLoopClosureLinks() const
void setFeatures(const std::vector< cv::KeyPoint > &keypoints, const std::vector< cv::Point3f > &keypoints3D, const cv::Mat &descriptors)
bool imageRejectedShown() const
bool updateCloudPose(const std::string &id, const Transform &pose)
int getOdomBufferSize() const
void odometryReceived(const rtabmap::OdometryEvent &, bool)
float getTimeLimit() const
virtual void downloadAllClouds()
void setCloudOpacity(const std::string &id, double opacity=1.0)
bool hasIntensity() const
double getGridMapOpacity() const
double getCloudMinDepth(int index) const
void uInsert(std::map< K, V > &map, const std::pair< K, V > &pair)
void selectScreenCaptureFormat(bool checked)
const Transform & localTransform() const
void setLaserScanRaw(const LaserScan &laserScanRaw)
const std::map< int, float > & rawLikelihood() const
void processRtabmapGoalStatusEvent(int status)
bool _processingDownloadedMap
const std::map< int, Signature > & getSignatures() const