mirror of
https://github.com/introlab/rtabmap.git
synced 2026-09-01 17:10:26 +08:00
Increased version to 0.6.2
Memory management tested on RGBD SLAM Fixed some crashes New parameter RGBD/LocalLoopDetectionMaxDiffID New parameter LccIcp2/VoxelSize Updated parameter LccIcp/Type (added "No ICP" type) Updated parameter kLccBowMinInliers (inliers minimum reduced to 1) TORO optimization: The graph root is explicitly defined as the last node added (fixed a TORO crash when a root could not be found) TORO optimization: only one constraint between neighbors and loop closures TORO optimization: added initial tree guess Map correction/Map transform: now only used in localization mode (map correction is always identity on mapping mode) New statistics: local loop space diff, last loop closure parent and child ids Database: Fixed empty signatures with no poses loaded ICP: fixed transform multiplication order Dump memory: added 3D words DatabaseViewer: added Export option (added ExportDialog object) DataRecorder: Option recording in RAM or Hard drive GUI: added a dock widget (MapVisibilityWidget) to change visibility of nodes in the 3D map GUI: fixed progress bar step count when generating the map Menu option: generate TORO graph (full/current map, optimized/not optimized) Menu option: download map (full/current map, optimized/not optimized) Preferences: added Reset all settings button Preferences: A QGroupBox can be a boolean parameter git-svn-id: http://rtabmap.googlecode.com/svn/trunk/rtabmap@1066 f169173b-cf89-36c8-b27e-44dbe73f0c83
This commit is contained in:
@@ -98,6 +98,7 @@ public:
|
||||
bool removeCloud(const std::string & id); //including mesh
|
||||
|
||||
bool getPose(const std::string & id, Transform & pose); //including meshes
|
||||
bool getCloudVisibility(const std::string & id);
|
||||
|
||||
const QMap<std::string, Transform> & getAddedClouds() {return _addedClouds;} //including meshes
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ class RTABMAPGUI_EXP DataRecorder : public QWidget, public UEventsHandler
|
||||
Q_OBJECT
|
||||
public:
|
||||
DataRecorder(QWidget * parent = 0);
|
||||
bool init(const QString & path);
|
||||
bool init(const QString & path, bool recordInRAM = true);
|
||||
|
||||
void close();
|
||||
|
||||
|
||||
@@ -54,6 +54,7 @@ public:
|
||||
private slots:
|
||||
void openDatabase();
|
||||
void generateGraph();
|
||||
void exportDatabase();
|
||||
void generateLocalGraph();
|
||||
void generate3DMap();
|
||||
void sliderAValueChanged(int);
|
||||
|
||||
@@ -104,6 +104,7 @@ private slots:
|
||||
void printLoopClosureIds();
|
||||
void generateMap();
|
||||
void generateLocalMap();
|
||||
void generateTOROMap();
|
||||
void deleteMemory();
|
||||
void openWorkingDirectory();
|
||||
void updateEditMenu();
|
||||
@@ -147,6 +148,7 @@ private slots:
|
||||
void viewMeshes();
|
||||
void resetOdometry();
|
||||
void triggerNewMap();
|
||||
void updateNodeVisibility(int, bool);
|
||||
|
||||
signals:
|
||||
void statsReceived(const rtabmap::Statistics &);
|
||||
@@ -231,6 +233,7 @@ private:
|
||||
DetailedProgressDialog * _initProgressDialog;
|
||||
|
||||
QString _graphSavingFileName;
|
||||
QString _toroSavingFileName;
|
||||
QString _autoScreenCaptureFormat;
|
||||
|
||||
QVector<int> _refIds;
|
||||
|
||||
@@ -192,7 +192,8 @@ private slots:
|
||||
void resetApply ( QAbstractButton * button );
|
||||
void resetSettings(int panelNumber);
|
||||
void loadConfigFrom();
|
||||
void saveConfigTo();
|
||||
bool saveConfigTo();
|
||||
void resetConfig();
|
||||
void makeObsoleteGeneralPanel();
|
||||
void makeObsoleteCloudRenderingPanel();
|
||||
void makeObsoleteLoggingPanel();
|
||||
|
||||
@@ -16,6 +16,8 @@ SET(headers_ui
|
||||
../include/${PROJECT_PREFIX}/gui/OdometryViewer.h
|
||||
../include/${PROJECT_PREFIX}/gui/LoopClosureViewer.h
|
||||
../include/${PROJECT_PREFIX}/gui/DataRecorder.h
|
||||
./ExportDialog.h
|
||||
./MapVisibilityWidget.h
|
||||
)
|
||||
|
||||
SET(uis
|
||||
@@ -25,6 +27,7 @@ SET(uis
|
||||
./ui/consoleWidget.ui
|
||||
./ui/DatabaseViewer.ui
|
||||
./ui/loopClosureViewer.ui
|
||||
./ui/exportDialog.ui
|
||||
)
|
||||
|
||||
SET(qrc
|
||||
@@ -60,6 +63,8 @@ SET(SRC_FILES
|
||||
./OdometryViewer.cpp
|
||||
./LoopClosureViewer.cpp
|
||||
./DataRecorder.cpp
|
||||
./ExportDialog.cpp
|
||||
./MapVisibilityWidget.cpp
|
||||
${moc_srcs}
|
||||
${moc_uis}
|
||||
${srcs_qrc}
|
||||
|
||||
@@ -473,6 +473,21 @@ void CloudViewer::setCloudVisibility(const std::string & id, bool isVisible)
|
||||
}
|
||||
}
|
||||
|
||||
bool CloudViewer::getCloudVisibility(const std::string & id)
|
||||
{
|
||||
pcl::visualization::CloudActorMapPtr cloudActorMap = _visualizer->getCloudActorMap();
|
||||
pcl::visualization::CloudActorMap::iterator iter = cloudActorMap->find(id);
|
||||
if(iter != cloudActorMap->end())
|
||||
{
|
||||
return iter->second.actor->GetVisibility() != 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
UERROR("Cannot find actor named \"%s\".", id.c_str());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void CloudViewer::setCloudOpacity(const std::string & id, double opacity)
|
||||
{
|
||||
_visualizer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_OPACITY, opacity, id);
|
||||
|
||||
@@ -32,7 +32,7 @@ DataRecorder::DataRecorder(QWidget * parent) :
|
||||
layout->addWidget(imageView_);
|
||||
this->setLayout(layout);
|
||||
}
|
||||
bool DataRecorder::init(const QString & path)
|
||||
bool DataRecorder::init(const QString & path, bool recordInRAM)
|
||||
{
|
||||
if(!memory_)
|
||||
{
|
||||
@@ -40,6 +40,10 @@ bool DataRecorder::init(const QString & path)
|
||||
customParameters.insert(ParametersPair(Parameters::kMemRehearsalSimilarity(), "1.0")); // desactivate rehearsal
|
||||
customParameters.insert(ParametersPair(Parameters::kKpWordsPerImage(), "-1")); // desactivate keypoints extraction
|
||||
customParameters.insert(ParametersPair(Parameters::kMemImageKept(), "true")); // to keep images
|
||||
if(!recordInRAM)
|
||||
{
|
||||
customParameters.insert(ParametersPair(Parameters::kDbSqlite3InMemory(), "false")); // to keep images
|
||||
}
|
||||
memory_ = new Memory();
|
||||
if(!memory_->init(path.toStdString(), true, customParameters, false))
|
||||
{
|
||||
|
||||
@@ -35,6 +35,10 @@
|
||||
#include "rtabmap/gui/UCv2Qt.h"
|
||||
#include "rtabmap/core/util3d.h"
|
||||
#include "rtabmap/core/Signature.h"
|
||||
#include "rtabmap/gui/DataRecorder.h"
|
||||
#include "rtabmap/core/Image.h"
|
||||
#include "ExportDialog.h"
|
||||
#include "DetailedProgressDialog.h"
|
||||
|
||||
#include <pcl/io/pcd_io.h>
|
||||
#include <pcl/filters/voxel_grid.h>
|
||||
@@ -59,6 +63,7 @@ DatabaseViewer::DatabaseViewer(QWidget * parent) :
|
||||
|
||||
// connect actions with custom slots
|
||||
connect(ui_->actionOpen_database, SIGNAL(triggered()), this, SLOT(openDatabase()));
|
||||
connect(ui_->actionExport, SIGNAL(triggered()), this, SLOT(exportDatabase()));
|
||||
connect(ui_->actionGenerate_graph_dot, SIGNAL(triggered()), this, SLOT(generateGraph()));
|
||||
connect(ui_->actionGenerate_local_graph_dot, SIGNAL(triggered()), this, SLOT(generateLocalGraph()));
|
||||
connect(ui_->actionGenerate_3D_map_pcd, SIGNAL(triggered()), this, SLOT(generate3DMap()));
|
||||
@@ -130,6 +135,82 @@ bool DatabaseViewer::openDatabase(const QString & path)
|
||||
return false;
|
||||
}
|
||||
|
||||
void DatabaseViewer::exportDatabase()
|
||||
{
|
||||
if(!memory_ || ids_.size() == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
rtabmap::ExportDialog dialog;
|
||||
|
||||
if(dialog.exec())
|
||||
{
|
||||
if(!dialog.outputPath().isEmpty())
|
||||
{
|
||||
int framesIgnored = dialog.framesIgnored();
|
||||
QString path = dialog.outputPath();
|
||||
rtabmap::DataRecorder recorder;
|
||||
if(recorder.init(path, false))
|
||||
{
|
||||
rtabmap::DetailedProgressDialog progressDialog(this);
|
||||
progressDialog.setMaximumSteps(ids_.size() / (1+framesIgnored) + 1);
|
||||
progressDialog.show();
|
||||
|
||||
for(int i=0; i<ids_.size(); i+=1+framesIgnored)
|
||||
{
|
||||
int id = ids_.at(i);
|
||||
std::vector<unsigned char> compressedRgb, compressedDepth, compressedDepth2d;
|
||||
float tmpDepthConstant;
|
||||
rtabmap::Transform tmpLocalTransform, pose;
|
||||
|
||||
memory_->getImageDepth(id, compressedRgb, compressedDepth, compressedDepth2d, tmpDepthConstant, tmpLocalTransform);
|
||||
if(dialog.isOdomExported())
|
||||
{
|
||||
memory_->getPose(id, pose, true);
|
||||
}
|
||||
|
||||
cv::Mat rgb, depth, depth2d;
|
||||
float depthConstant = 0;
|
||||
rtabmap::Transform localTransform;
|
||||
|
||||
if(dialog.isRgbExported())
|
||||
{
|
||||
rgb = rtabmap::util3d::uncompressImage(compressedRgb);
|
||||
}
|
||||
if(dialog.isDepthExported())
|
||||
{
|
||||
depth = rtabmap::util3d::uncompressImage(compressedDepth);
|
||||
depthConstant = tmpDepthConstant;
|
||||
localTransform = tmpLocalTransform;
|
||||
}
|
||||
if(dialog.isDepth2dExported())
|
||||
{
|
||||
depth2d = rtabmap::util3d::uncompressData(compressedDepth2d);
|
||||
}
|
||||
|
||||
rtabmap::Image data(rgb, depth, depth2d, depthConstant, pose, localTransform, id);
|
||||
recorder.addData(data);
|
||||
|
||||
progressDialog.appendText(tr("Exported node %1").arg(id));
|
||||
progressDialog.incrementStep();
|
||||
QApplication::processEvents();
|
||||
}
|
||||
progressDialog.setValue(progressDialog.maximumSteps());
|
||||
progressDialog.appendText("Export finished!");
|
||||
}
|
||||
else
|
||||
{
|
||||
UERROR("DataRecorder init failed?!");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
QMessageBox::warning(this, tr("Cannot export database"), tr("An output path must be set!"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DatabaseViewer::updateIds()
|
||||
{
|
||||
if(!memory_)
|
||||
@@ -246,7 +327,7 @@ void DatabaseViewer::generate3DMap()
|
||||
{
|
||||
std::map<int, rtabmap::Transform> poses, optimizedPoses;
|
||||
std::multimap<int, std::pair<int, rtabmap::Transform> > edgeConstraints;
|
||||
memory_->getMetricConstraints(uKeys(ids), memory_->getSignature(id)->mapId(), poses, edgeConstraints, true);
|
||||
memory_->getMetricConstraints(uKeys(ids), poses, edgeConstraints, true);
|
||||
|
||||
UINFO("Poses=%d, constraints=%d", poses.size(), edgeConstraints.size());
|
||||
|
||||
|
||||
82
guilib/src/ExportDialog.cpp
Normal file
82
guilib/src/ExportDialog.cpp
Normal file
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Copyright (C) 2010-2011, Mathieu Labbe and IntRoLab - Universite de Sherbrooke
|
||||
*
|
||||
* This file is part of RTAB-Map.
|
||||
*
|
||||
* RTAB-Map is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* RTAB-Map is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with RTAB-Map. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "ExportDialog.h"
|
||||
#include "ui_exportDialog.h"
|
||||
|
||||
#include <QtGui/QFileDialog>
|
||||
|
||||
namespace rtabmap {
|
||||
|
||||
ExportDialog::ExportDialog(QWidget * parent) :
|
||||
QDialog(parent)
|
||||
{
|
||||
_ui = new Ui_ExportDialog();
|
||||
_ui->setupUi(this);
|
||||
|
||||
connect(_ui->toolButton_path, SIGNAL(clicked()), this, SLOT(getPath()));
|
||||
|
||||
_ui->lineEdit_path->setText(QDir::homePath()+QDir::separator()+"output.db");
|
||||
}
|
||||
|
||||
ExportDialog::~ExportDialog()
|
||||
{
|
||||
delete _ui;
|
||||
}
|
||||
|
||||
void ExportDialog::getPath()
|
||||
{
|
||||
QString path = QFileDialog::getSaveFileName(this, tr("Output database path..."), _ui->lineEdit_path->text(), tr("RTAB-Map database (*.db)"));
|
||||
if(!path.isEmpty())
|
||||
{
|
||||
_ui->lineEdit_path->setText(path);
|
||||
}
|
||||
}
|
||||
|
||||
QString ExportDialog::outputPath() const
|
||||
{
|
||||
return _ui->lineEdit_path->text();
|
||||
}
|
||||
|
||||
int ExportDialog::framesIgnored() const
|
||||
{
|
||||
return _ui->spinBox_ignored->value();
|
||||
}
|
||||
|
||||
bool ExportDialog::isRgbExported() const
|
||||
{
|
||||
return _ui->checkBox_rgb->isChecked();
|
||||
}
|
||||
|
||||
bool ExportDialog::isDepthExported() const
|
||||
{
|
||||
return _ui->checkBox_depth->isChecked();
|
||||
}
|
||||
|
||||
bool ExportDialog::isDepth2dExported() const
|
||||
{
|
||||
return _ui->checkBox_depth2d->isChecked();
|
||||
}
|
||||
|
||||
bool ExportDialog::isOdomExported() const
|
||||
{
|
||||
return _ui->checkBox_odom->isChecked();
|
||||
}
|
||||
|
||||
}
|
||||
54
guilib/src/ExportDialog.h
Normal file
54
guilib/src/ExportDialog.h
Normal file
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright (C) 2010-2011, Mathieu Labbe and IntRoLab - Universite de Sherbrooke
|
||||
*
|
||||
* This file is part of RTAB-Map.
|
||||
*
|
||||
* RTAB-Map is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* RTAB-Map is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with RTAB-Map. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef EXPORTDIALOG_H_
|
||||
#define EXPORTDIALOG_H_
|
||||
|
||||
#include <QtGui/QDialog>
|
||||
|
||||
class Ui_ExportDialog;
|
||||
|
||||
namespace rtabmap {
|
||||
|
||||
class ExportDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
ExportDialog(QWidget * parent = 0);
|
||||
|
||||
virtual ~ExportDialog();
|
||||
|
||||
QString outputPath() const;
|
||||
int framesIgnored() const;
|
||||
bool isRgbExported() const;
|
||||
bool isDepthExported() const;
|
||||
bool isDepth2dExported() const;
|
||||
bool isOdomExported() const;
|
||||
|
||||
private slots:
|
||||
void getPath();
|
||||
|
||||
private:
|
||||
Ui_ExportDialog * _ui;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif /* ABOUTDIALOG_H_ */
|
||||
@@ -151,6 +151,7 @@ MainWindow::MainWindow(PreferencesDialog * prefDialog, QWidget * parent) :
|
||||
_ui->dockWidget_statsV2->setVisible(false);
|
||||
_ui->dockWidget_console->setVisible(false);
|
||||
_ui->dockWidget_loopClosureViewer->setVisible(false);
|
||||
_ui->dockWidget_mapVisibility->setVisible(false);
|
||||
//_ui->dockWidget_cloudViewer->setVisible(false);
|
||||
}
|
||||
|
||||
@@ -206,6 +207,8 @@ MainWindow::MainWindow(PreferencesDialog * prefDialog, QWidget * parent) :
|
||||
_initProgressDialog->setWindowTitle(tr("Progress dialog"));
|
||||
_initProgressDialog->setMinimumWidth(800);
|
||||
|
||||
connect(_ui->widget_mapVisibility, SIGNAL(visibilityChanged(int, bool)), this, SLOT(updateNodeVisibility(int, bool)));
|
||||
|
||||
//connect stuff
|
||||
connect(_ui->actionExit, SIGNAL(triggered()), this, SLOT(close()));
|
||||
qRegisterMetaType<MainWindow::State>("MainWindow::State");
|
||||
@@ -222,6 +225,7 @@ MainWindow::MainWindow(PreferencesDialog * prefDialog, QWidget * parent) :
|
||||
_ui->menuShow_view->addAction(_ui->dockWidget_console->toggleViewAction());
|
||||
_ui->menuShow_view->addAction(_ui->dockWidget_cloudViewer->toggleViewAction());
|
||||
_ui->menuShow_view->addAction(_ui->dockWidget_loopClosureViewer->toggleViewAction());
|
||||
_ui->menuShow_view->addAction(_ui->dockWidget_mapVisibility->toggleViewAction());
|
||||
_ui->menuShow_view->addAction(_ui->toolBar->toggleViewAction());
|
||||
_ui->toolBar->setWindowTitle(tr("Control toolbar"));
|
||||
QAction * a = _ui->menuShow_view->addAction("Progress dialog");
|
||||
@@ -239,6 +243,7 @@ MainWindow::MainWindow(PreferencesDialog * prefDialog, QWidget * parent) :
|
||||
connect(_ui->actionPrint_loop_closure_IDs_to_console, SIGNAL(triggered()), this, SLOT(printLoopClosureIds()));
|
||||
connect(_ui->actionGenerate_map, SIGNAL(triggered()), this , SLOT(generateMap()));
|
||||
connect(_ui->actionGenerate_local_map, SIGNAL(triggered()), this, SLOT(generateLocalMap()));
|
||||
connect(_ui->actionGenerate_TORO_graph_graph, SIGNAL(triggered()), this , SLOT(generateTOROMap()));
|
||||
connect(_ui->actionDelete_memory, SIGNAL(triggered()), this , SLOT(deleteMemory()));
|
||||
connect(_ui->actionDownload_all_clouds, SIGNAL(triggered()), this , SLOT(downloadAllClouds()));
|
||||
connect(_ui->menuEdit, SIGNAL(aboutToShow()), this, SLOT(updateEditMenu()));
|
||||
@@ -391,6 +396,7 @@ void MainWindow::closeEvent(QCloseEvent* event)
|
||||
_ui->dockWidget_console->close();
|
||||
_ui->dockWidget_cloudViewer->close();
|
||||
_ui->dockWidget_loopClosureViewer->close();
|
||||
_ui->dockWidget_mapVisibility->close();
|
||||
|
||||
if(_camera)
|
||||
{
|
||||
@@ -616,7 +622,8 @@ void MainWindow::processStats(const rtabmap::Statistics & stat)
|
||||
//Affichage des stats et images
|
||||
|
||||
int refMapId = uValue(stat.getMapIds(), stat.refImageId(), -1);
|
||||
int loopMapId = uValue(stat.getMapIds(), stat.loopClosureId(), -1);
|
||||
int loopMapId = uValue(stat.getMapIds(), stat.loopClosureId(), uValue(stat.getMapIds(), stat.localLoopClosureId(), -1));
|
||||
|
||||
_ui->label_refId->setText(QString("New ID = %1 [%2]").arg(stat.refImageId()).arg(refMapId));
|
||||
_ui->label_matchId->clear();
|
||||
|
||||
@@ -688,7 +695,7 @@ void MainWindow::processStats(const rtabmap::Statistics & stat)
|
||||
|
||||
int rehearsed = (int)uValue(stat.data(), Statistics::kMemoryRehearsal_merged(), 0.0f);
|
||||
int localTimeClosures = (int)uValue(stat.data(), Statistics::kLocalLoopTime_closures(), 0.0f);
|
||||
bool scanMatchingSuccess = (bool)uValue(stat.data(), Statistics::kLocalLoopScan_matching_success(), 0.0f);
|
||||
bool scanMatchingSuccess = (bool)uValue(stat.data(), Statistics::kLocalLoopOdom_corrected(), 0.0f);
|
||||
_ui->label_matchId->clear();
|
||||
_ui->label_stats_imageNumber->setText(QString("%1 [%2]").arg(stat.refImageId()).arg(refMapId));
|
||||
|
||||
@@ -916,6 +923,7 @@ void MainWindow::processStats(const rtabmap::Statistics & stat)
|
||||
{
|
||||
// update pose only if a odometry is not received
|
||||
updateMapCloud(stat.poses(), _odometryReceived?Transform():stat.currentPose());
|
||||
_ui->widget_mapVisibility->setMap(stat.poses());
|
||||
_odometryReceived = false;
|
||||
|
||||
_odometryCorrection = stat.mapCorrection();
|
||||
@@ -1130,7 +1138,11 @@ void MainWindow::updateMapCloud(const std::map<int, Transform> & poses, const Tr
|
||||
int id = std::atoi(splitted.back().c_str());
|
||||
if(poses.find(id) == poses.end())
|
||||
{
|
||||
_ui->widget_cloudViewer->setCloudVisibility(iter.key(), false);
|
||||
if(_ui->widget_cloudViewer->getCloudVisibility(iter.key()))
|
||||
{
|
||||
UDEBUG("Hide %s", iter.key().c_str());
|
||||
_ui->widget_cloudViewer->setCloudVisibility(iter.key(), false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1170,6 +1182,25 @@ void MainWindow::updateMapCloud(const std::map<int, Transform> & poses, const Tr
|
||||
_ui->widget_cloudViewer->render();
|
||||
}
|
||||
|
||||
void MainWindow::updateNodeVisibility(int nodeId, bool visible)
|
||||
{
|
||||
if(_currentPosesMap.find(nodeId) != _currentPosesMap.end())
|
||||
{
|
||||
if(_preferencesDialog->isCloudsShown(0))
|
||||
{
|
||||
std::string cloudName = uFormat("cloud%d", nodeId);
|
||||
_ui->widget_cloudViewer->setCloudVisibility(cloudName, visible);
|
||||
}
|
||||
|
||||
if(_preferencesDialog->isScansShown(0))
|
||||
{
|
||||
std::string scanName = uFormat("scan%d", nodeId);
|
||||
_ui->widget_cloudViewer->setCloudVisibility(scanName, visible);
|
||||
}
|
||||
}
|
||||
_ui->widget_cloudViewer->render();
|
||||
}
|
||||
|
||||
void MainWindow::processRtabmapEventInit(int status, const QString & info)
|
||||
{
|
||||
if((RtabmapEventInit::Status)status == RtabmapEventInit::kInitializing)
|
||||
@@ -1220,7 +1251,6 @@ void MainWindow::processRtabmapEvent3DMap(const rtabmap::RtabmapEvent3DMap & eve
|
||||
UINFO(" depthConstants = %d", event.getDepthConstants().size());
|
||||
UINFO(" localTransforms = %d", event.getLocalTransforms().size());
|
||||
UINFO(" poses = %d", event.getPoses().size());
|
||||
UINFO(" mapCorrection = %s", event.getMapCorrection().prettyPrint().c_str());
|
||||
|
||||
_initProgressDialog->appendText("Inserting data in the cache...");
|
||||
|
||||
@@ -1269,7 +1299,7 @@ void MainWindow::processRtabmapEvent3DMap(const rtabmap::RtabmapEvent3DMap & eve
|
||||
_initProgressDialog->appendText(tr("Inserted %1 local transforms.").arg(_localTransformsMap.size()));
|
||||
_initProgressDialog->incrementStep();
|
||||
|
||||
_odometryCorrection = event.getMapCorrection();
|
||||
_odometryCorrection.setIdentity();
|
||||
|
||||
_initProgressDialog->appendText("Inserting data in the cache... done.");
|
||||
|
||||
@@ -2155,6 +2185,66 @@ void MainWindow::generateLocalMap()
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::generateTOROMap()
|
||||
{
|
||||
if(_toroSavingFileName.isEmpty())
|
||||
{
|
||||
_toroSavingFileName = _preferencesDialog->getWorkingDirectory() + "/toro.graph";
|
||||
}
|
||||
|
||||
QStringList items;
|
||||
items.append("Current map optimized");
|
||||
items.append("Current map not optimized");
|
||||
items.append("Full map optimized");
|
||||
items.append("Full map not optimized");
|
||||
bool ok;
|
||||
QString item = QInputDialog::getItem(this, tr("Parameters"), tr("Options:"), items, 0, false, &ok);
|
||||
if(ok)
|
||||
{
|
||||
bool optimized=false, full=false;
|
||||
if(item.compare("Current map optimized") == 0)
|
||||
{
|
||||
optimized = true;
|
||||
}
|
||||
else if(item.compare("Current map not optimized") == 0)
|
||||
{
|
||||
|
||||
}
|
||||
else if(item.compare("Full map optimized") == 0)
|
||||
{
|
||||
full=true;
|
||||
optimized=true;
|
||||
}
|
||||
else if(item.compare("Full map not optimized") == 0)
|
||||
{
|
||||
full=true;
|
||||
}
|
||||
else
|
||||
{
|
||||
UFATAL("Item \"%s\" not found?!?", item.toStdString().c_str());
|
||||
}
|
||||
|
||||
QString path = QFileDialog::getSaveFileName(this, tr("Save File"), _toroSavingFileName, tr("TORO file (*.graph)"));
|
||||
if(!path.isEmpty())
|
||||
{
|
||||
_toroSavingFileName = path;
|
||||
if(full)
|
||||
{
|
||||
this->post(new RtabmapEventCmd(RtabmapEventCmd::kCmdGenerateTOROGraphFull, path.toStdString(), optimized?1:0));
|
||||
}
|
||||
else
|
||||
{
|
||||
this->post(new RtabmapEventCmd(RtabmapEventCmd::kCmdGenerateTOROGraph, path.toStdString(), optimized?1:0));
|
||||
}
|
||||
|
||||
_ui->dockWidget_console->show();
|
||||
_ui->widget_console->appendMsg(QString("TORO Graph saved (full=%1, optimized=%2)... %3")
|
||||
.arg(full?"true":"false").arg(optimized?"true":"false").arg(_toroSavingFileName));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::deleteMemory()
|
||||
{
|
||||
QMessageBox::StandardButton button;
|
||||
@@ -2261,12 +2351,61 @@ void MainWindow::dumpThePrediction()
|
||||
|
||||
void MainWindow::downloadAllClouds()
|
||||
{
|
||||
UINFO("Download clouds...");
|
||||
_initProgressDialog->setAutoClose(true, 1);
|
||||
_initProgressDialog->resetProgress();
|
||||
_initProgressDialog->show();
|
||||
_initProgressDialog->appendText("Downloading the map...");
|
||||
this->post(new RtabmapEventCmd(RtabmapEventCmd::kCmdPublish3DMap));
|
||||
bool showAll = _state != kMonitoringPaused && _state != kMonitoring;
|
||||
|
||||
QStringList items;
|
||||
items.append("Current map optimized");
|
||||
if(showAll)
|
||||
{
|
||||
items.append("Current map not optimized");
|
||||
}
|
||||
items.append("Full map optimized");
|
||||
if(showAll)
|
||||
{
|
||||
items.append("Full map not optimized");
|
||||
}
|
||||
bool ok;
|
||||
QString item = QInputDialog::getItem(this, tr("Parameters"), tr("Options:"), items, showAll?2:1, false, &ok);
|
||||
if(ok)
|
||||
{
|
||||
bool optimized=false, full=false;
|
||||
if(item.compare("Current map optimized") == 0)
|
||||
{
|
||||
optimized = true;
|
||||
}
|
||||
else if(item.compare("Current map not optimized") == 0)
|
||||
{
|
||||
|
||||
}
|
||||
else if(item.compare("Full map optimized") == 0)
|
||||
{
|
||||
full=true;
|
||||
optimized=true;
|
||||
}
|
||||
else if(item.compare("Full map not optimized") == 0)
|
||||
{
|
||||
full=true;
|
||||
}
|
||||
else
|
||||
{
|
||||
UFATAL("Item \"%s\" not found?!?", item.toStdString().c_str());
|
||||
}
|
||||
|
||||
UINFO("Download clouds...");
|
||||
_initProgressDialog->setAutoClose(true, 1);
|
||||
_initProgressDialog->resetProgress();
|
||||
_initProgressDialog->show();
|
||||
_initProgressDialog->appendText(tr("Downloading the map (full=%1 ,optimized=%2)...")
|
||||
.arg(full?"true":"false").arg(optimized?"true":"false"));
|
||||
if(full)
|
||||
{
|
||||
this->post(new RtabmapEventCmd(RtabmapEventCmd::kCmdPublish3DMapFull, optimized?1:0));
|
||||
}
|
||||
else
|
||||
{
|
||||
this->post(new RtabmapEventCmd(RtabmapEventCmd::kCmdPublish3DMap, optimized?1:0));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::clearTheCache()
|
||||
@@ -2470,6 +2609,7 @@ void MainWindow::savePointClouds()
|
||||
_initProgressDialog->setAutoClose(true, 1);
|
||||
_initProgressDialog->resetProgress();
|
||||
_initProgressDialog->show();
|
||||
_initProgressDialog->setMaximumSteps(_currentPosesMap.size()+1);
|
||||
|
||||
std::map<int, pcl::PointCloud<pcl::PointXYZRGB>::Ptr> clouds;
|
||||
if(button == QMessageBox::No)
|
||||
@@ -2497,6 +2637,7 @@ void MainWindow::saveMeshes()
|
||||
_initProgressDialog->setAutoClose(true, 1);
|
||||
_initProgressDialog->resetProgress();
|
||||
_initProgressDialog->show();
|
||||
_initProgressDialog->setMaximumSteps(_currentPosesMap.size()+1);
|
||||
|
||||
std::map<int, pcl::PolygonMesh::Ptr> meshes;
|
||||
if(button == QMessageBox::No)
|
||||
@@ -2527,6 +2668,7 @@ void MainWindow::viewPointClouds()
|
||||
_initProgressDialog->setAutoClose(true, 1);
|
||||
_initProgressDialog->resetProgress();
|
||||
_initProgressDialog->show();
|
||||
_initProgressDialog->setMaximumSteps(_currentPosesMap.size()+1);
|
||||
|
||||
std::map<int, pcl::PointCloud<pcl::PointXYZRGB>::Ptr> clouds;
|
||||
if(button == QMessageBox::No)
|
||||
@@ -2586,6 +2728,7 @@ void MainWindow::viewMeshes()
|
||||
_initProgressDialog->setAutoClose(true, 1);
|
||||
_initProgressDialog->resetProgress();
|
||||
_initProgressDialog->show();
|
||||
_initProgressDialog->setMaximumSteps(_currentPosesMap.size()+1);
|
||||
|
||||
std::map<int, pcl::PolygonMesh::Ptr> meshes;
|
||||
if(button == QMessageBox::No)
|
||||
@@ -3135,6 +3278,7 @@ void MainWindow::changeState(MainWindow::State newState)
|
||||
_ui->actionDelete_memory->setEnabled(true);
|
||||
_ui->actionGenerate_map->setEnabled(true);
|
||||
_ui->actionGenerate_local_map->setEnabled(true);
|
||||
_ui->actionGenerate_TORO_graph_graph->setEnabled(true);
|
||||
_ui->actionOpen_working_directory->setEnabled(true);
|
||||
_ui->actionApply_settings_to_the_detector->setEnabled(true);
|
||||
_ui->actionDownload_all_clouds->setEnabled(true);
|
||||
@@ -3163,6 +3307,7 @@ void MainWindow::changeState(MainWindow::State newState)
|
||||
_ui->actionDelete_memory->setEnabled(false);
|
||||
_ui->actionGenerate_map->setEnabled(false);
|
||||
_ui->actionGenerate_local_map->setEnabled(false);
|
||||
_ui->actionGenerate_TORO_graph_graph->setEnabled(false);
|
||||
_ui->actionOpen_working_directory->setEnabled(true);
|
||||
_ui->actionApply_settings_to_the_detector->setEnabled(false);
|
||||
_ui->actionDownload_all_clouds->setEnabled(false);
|
||||
@@ -3201,6 +3346,7 @@ void MainWindow::changeState(MainWindow::State newState)
|
||||
_ui->actionDelete_memory->setEnabled(false);
|
||||
_ui->actionGenerate_map->setEnabled(false);
|
||||
_ui->actionGenerate_local_map->setEnabled(false);
|
||||
_ui->actionGenerate_TORO_graph_graph->setEnabled(false);
|
||||
_ui->actionDownload_all_clouds->setEnabled(false);
|
||||
_state = kDetecting;
|
||||
_elapsedTime->start();
|
||||
@@ -3231,6 +3377,7 @@ void MainWindow::changeState(MainWindow::State newState)
|
||||
_ui->actionDelete_memory->setEnabled(true);
|
||||
_ui->actionGenerate_map->setEnabled(true);
|
||||
_ui->actionGenerate_local_map->setEnabled(true);
|
||||
_ui->actionGenerate_TORO_graph_graph->setEnabled(true);
|
||||
_ui->actionDownload_all_clouds->setEnabled(true);
|
||||
_state = kPaused;
|
||||
_oneSecondTimer->stop();
|
||||
@@ -3267,6 +3414,7 @@ void MainWindow::changeState(MainWindow::State newState)
|
||||
_ui->actionDelete_memory->setEnabled(true);
|
||||
_ui->actionGenerate_map->setVisible(false);
|
||||
_ui->actionGenerate_local_map->setVisible(false);
|
||||
_ui->actionGenerate_TORO_graph_graph->setVisible(false);
|
||||
_ui->actionOpen_working_directory->setEnabled(false);
|
||||
_ui->actionApply_settings_to_the_detector->setVisible(false);
|
||||
_ui->actionDownload_all_clouds->setEnabled(true);
|
||||
@@ -3294,6 +3442,7 @@ void MainWindow::changeState(MainWindow::State newState)
|
||||
_ui->actionDelete_memory->setEnabled(true);
|
||||
_ui->actionGenerate_map->setVisible(false);
|
||||
_ui->actionGenerate_local_map->setVisible(false);
|
||||
_ui->actionGenerate_TORO_graph_graph->setVisible(false);
|
||||
_ui->actionOpen_working_directory->setEnabled(false);
|
||||
_ui->actionApply_settings_to_the_detector->setVisible(false);
|
||||
_ui->actionDownload_all_clouds->setEnabled(true);
|
||||
|
||||
86
guilib/src/MapVisibilityWidget.cpp
Normal file
86
guilib/src/MapVisibilityWidget.cpp
Normal file
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* MapVisibilityWidget.cpp
|
||||
*
|
||||
* Created on: 2014-01-20
|
||||
* Author: mathieu
|
||||
*/
|
||||
|
||||
#include "MapVisibilityWidget.h"
|
||||
|
||||
#include <QtGui/QCheckBox>
|
||||
#include <QtGui/QVBoxLayout>
|
||||
#include <QtGui/QScrollArea>
|
||||
|
||||
#include <rtabmap/utilite/ULogger.h>
|
||||
|
||||
namespace rtabmap {
|
||||
|
||||
MapVisibilityWidget::MapVisibilityWidget(QWidget * parent) : QWidget(parent) {
|
||||
|
||||
QVBoxLayout * verticalLayout1 = new QVBoxLayout(this);
|
||||
QScrollArea * scrollArea = new QScrollArea(this);
|
||||
scrollArea->setWidgetResizable(true);
|
||||
QWidget * scrollAreaWidgetContent = new QWidget();
|
||||
scrollAreaWidgetContent->setObjectName("area");
|
||||
QVBoxLayout * layout2 = new QVBoxLayout(scrollAreaWidgetContent);
|
||||
scrollAreaWidgetContent->setLayout(layout2);
|
||||
scrollArea->setWidget(scrollAreaWidgetContent);
|
||||
verticalLayout1->addWidget(scrollArea);
|
||||
}
|
||||
|
||||
MapVisibilityWidget::~MapVisibilityWidget() {
|
||||
|
||||
}
|
||||
|
||||
void MapVisibilityWidget::showEvent(QShowEvent * event)
|
||||
{
|
||||
updateCheckBoxes();
|
||||
}
|
||||
|
||||
void MapVisibilityWidget::updateCheckBoxes()
|
||||
{
|
||||
QWidget * area = this->findChild<QWidget*>("area");
|
||||
QVBoxLayout * layout = (QVBoxLayout *)area->layout();
|
||||
QList<QCheckBox*> checkboxes = area->findChildren<QCheckBox*>();
|
||||
while(checkboxes.size() && checkboxes.size() > _poses.size())
|
||||
{
|
||||
delete *checkboxes.begin();
|
||||
checkboxes.erase(checkboxes.begin());
|
||||
}
|
||||
int i=0;
|
||||
for(std::map<int, Transform>::iterator iter=_poses.begin(); iter!=_poses.end(); ++iter)
|
||||
{
|
||||
bool added = false;
|
||||
if(i >= checkboxes.size())
|
||||
{
|
||||
checkboxes.push_back(new QCheckBox(area));
|
||||
added = true;
|
||||
}
|
||||
checkboxes[i]->setText(QString("%1 (%2)").arg(iter->first).arg(iter->second.prettyPrint().c_str()));
|
||||
checkboxes[i]->setChecked(true);
|
||||
if(added)
|
||||
{
|
||||
connect(checkboxes[i], SIGNAL(stateChanged(int)), this, SLOT(signalVisibility()));
|
||||
layout->addWidget(checkboxes[i]);
|
||||
}
|
||||
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
void MapVisibilityWidget::setMap(const std::map<int, Transform> & poses)
|
||||
{
|
||||
_poses = poses;
|
||||
if(this->isVisible())
|
||||
{
|
||||
updateCheckBoxes();
|
||||
}
|
||||
}
|
||||
|
||||
void MapVisibilityWidget::signalVisibility()
|
||||
{
|
||||
QCheckBox * check = qobject_cast<QCheckBox*>(sender());
|
||||
emit visibilityChanged(check->text().split('(').first().toInt(), check->isChecked());
|
||||
}
|
||||
|
||||
} /* namespace rtabmap */
|
||||
42
guilib/src/MapVisibilityWidget.h
Normal file
42
guilib/src/MapVisibilityWidget.h
Normal file
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* MapVisibilityWidget.h
|
||||
*
|
||||
* Created on: 2014-01-20
|
||||
* Author: mathieu
|
||||
*/
|
||||
|
||||
#ifndef MAPVISIBILITYWIDGET_H_
|
||||
#define MAPVISIBILITYWIDGET_H_
|
||||
|
||||
#include <QtGui/QWidget>
|
||||
#include <rtabmap/core/Transform.h>
|
||||
#include <map>
|
||||
|
||||
namespace rtabmap {
|
||||
|
||||
class MapVisibilityWidget : public QWidget {
|
||||
Q_OBJECT;
|
||||
public:
|
||||
MapVisibilityWidget(QWidget * parent = 0);
|
||||
virtual ~MapVisibilityWidget();
|
||||
|
||||
void setMap(const std::map<int, Transform> & poses);
|
||||
|
||||
protected:
|
||||
virtual void showEvent(QShowEvent * event);
|
||||
|
||||
private slots:
|
||||
void signalVisibility();
|
||||
|
||||
private:
|
||||
void updateCheckBoxes();
|
||||
|
||||
signals:
|
||||
void visibilityChanged(int id, bool visible);
|
||||
|
||||
private:
|
||||
std::map<int, Transform> _poses;
|
||||
};
|
||||
|
||||
} /* namespace rtabmap */
|
||||
#endif /* MAPVISIBILITYWIDGET_H_ */
|
||||
@@ -137,6 +137,7 @@ PreferencesDialog::PreferencesDialog(QWidget * parent) :
|
||||
connect(_ui->buttonBox_local, SIGNAL(clicked(QAbstractButton *)), this, SLOT(resetApply(QAbstractButton *)));
|
||||
connect(_ui->pushButton_loadConfig, SIGNAL(clicked()), this, SLOT(loadConfigFrom()));
|
||||
connect(_ui->pushButton_saveConfig, SIGNAL(clicked()), this, SLOT(saveConfigTo()));
|
||||
connect(_ui->pushButton_resetConfig, SIGNAL(clicked()), this, SLOT(resetConfig()));
|
||||
connect(_ui->radioButton_basic, SIGNAL(toggled(bool)), this, SLOT(setupTreeView()));
|
||||
connect(_ui->pushButton_testSourceOdometry, SIGNAL(clicked()), this, SLOT(testSourceOdometry()));
|
||||
|
||||
@@ -374,19 +375,19 @@ PreferencesDialog::PreferencesDialog(QWidget * parent) :
|
||||
_ui->rgdb_angularUpdate->setObjectName(Parameters::kRGBDAngularUpdate().c_str());
|
||||
_ui->odomScanHistory->setObjectName(Parameters::kRGBDScanMatchingSize().c_str());
|
||||
|
||||
_ui->localDetection_time->setObjectName(Parameters::kRGBDLocalLoopDetectionTime().c_str());
|
||||
_ui->localDetection_space->setObjectName(Parameters::kRGBDLocalLoopDetectionSpace().c_str());
|
||||
_ui->groupBox_localDetection_time->setObjectName(Parameters::kRGBDLocalLoopDetectionTime().c_str());
|
||||
_ui->groupBox_localDetection_space->setObjectName(Parameters::kRGBDLocalLoopDetectionSpace().c_str());
|
||||
_ui->localDetection_radius->setObjectName(Parameters::kRGBDLocalLoopDetectionRadius().c_str());
|
||||
_ui->localDetection_maxNeighbors->setObjectName(Parameters::kRGBDLocalLoopDetectionNeighbors().c_str());
|
||||
|
||||
_ui->loopClosure_icpEnabled->setObjectName(Parameters::kLccIcpEnabled().c_str());
|
||||
_ui->loopClosure_icpType->setObjectName(Parameters::kLccIcpType().c_str());
|
||||
_ui->localDetection_maxDiffID->setObjectName(Parameters::kRGBDLocalLoopDetectionMaxDiffID().c_str());
|
||||
|
||||
_ui->loopClosure_bowMinInliers->setObjectName(Parameters::kLccBowMinInliers().c_str());
|
||||
_ui->loopClosure_bowInlierDistance->setObjectName(Parameters::kLccBowInlierDistance().c_str());
|
||||
_ui->loopClosure_bowIterations->setObjectName(Parameters::kLccBowIterations().c_str());
|
||||
_ui->loopClosure_bowMaxDepth->setObjectName(Parameters::kLccBowMaxDepth().c_str());
|
||||
|
||||
_ui->globalDetection_icpType->setObjectName(Parameters::kLccIcpType().c_str());
|
||||
|
||||
_ui->loopClosure_icpDecimation->setObjectName(Parameters::kLccIcp3Decimation().c_str());
|
||||
_ui->loopClosure_icpMaxDepth->setObjectName(Parameters::kLccIcp3MaxDepth().c_str());
|
||||
_ui->loopClosure_icpVoxelSize->setObjectName(Parameters::kLccIcp3VoxelSize().c_str());
|
||||
@@ -399,6 +400,7 @@ PreferencesDialog::PreferencesDialog(QWidget * parent) :
|
||||
_ui->loopClosure_icp2Iterations->setObjectName(Parameters::kLccIcp2Iterations().c_str());
|
||||
_ui->loopClosure_icp2MaxFitness->setObjectName(Parameters::kLccIcp2MaxFitness().c_str());
|
||||
_ui->loopClosure_icp2Ratio->setObjectName(Parameters::kLccIcp2CorrespondenceRatio().c_str());
|
||||
_ui->loopClosure_icp2Voxel->setObjectName(Parameters::kLccIcp2VoxelSize().c_str());
|
||||
|
||||
//Odometry
|
||||
_ui->odom_type->setObjectName(Parameters::kOdomType().c_str());
|
||||
@@ -589,6 +591,7 @@ void PreferencesDialog::setupSignals()
|
||||
QCheckBox * check = qobject_cast<QCheckBox *>(obj);
|
||||
QRadioButton * radio = qobject_cast<QRadioButton *>(obj);
|
||||
QLineEdit * lineEdit = qobject_cast<QLineEdit *>(obj);
|
||||
QGroupBox * groupBox = qobject_cast<QGroupBox *>(obj);
|
||||
if(spin)
|
||||
{
|
||||
connect(spin, SIGNAL(valueChanged(int)), this, SLOT(addParameter(int)));
|
||||
@@ -613,6 +616,10 @@ void PreferencesDialog::setupSignals()
|
||||
{
|
||||
connect(lineEdit, SIGNAL(textChanged(const QString &)), this, SLOT(addParameter(const QString &)));
|
||||
}
|
||||
else if(groupBox)
|
||||
{
|
||||
connect(groupBox, SIGNAL(clicked(bool)), this, SLOT(addParameter(bool)));
|
||||
}
|
||||
else
|
||||
{
|
||||
ULOGGER_WARN("QObject called %s can't be cast to a supported widget", (*iter).first.c_str());
|
||||
@@ -823,6 +830,13 @@ void PreferencesDialog::resetSettings(int panelNumber)
|
||||
{
|
||||
this->resetSettings(boxes.at(panelNumber));
|
||||
}
|
||||
else if(panelNumber == -1)
|
||||
{
|
||||
for(QList<QGroupBox*>::iterator iter = boxes.begin(); iter!=boxes.end(); ++iter)
|
||||
{
|
||||
this->resetSettings(*iter);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ULOGGER_WARN("panel number and the number of stacked widget doesn't match");
|
||||
@@ -856,7 +870,7 @@ QString PreferencesDialog::getIniFilePath() const
|
||||
|
||||
void PreferencesDialog::loadConfigFrom()
|
||||
{
|
||||
QString path = QFileDialog::getOpenFileName(this, tr("Load configurations..."), this->getWorkingDirectory(), "*.ini");
|
||||
QString path = QFileDialog::getOpenFileName(this, tr("Load settings..."), this->getWorkingDirectory(), "*.ini");
|
||||
if(!path.isEmpty())
|
||||
{
|
||||
this->readSettings(path);
|
||||
@@ -1054,12 +1068,28 @@ bool PreferencesDialog::readCoreSettings(const QString & filePath)
|
||||
return true;
|
||||
}
|
||||
|
||||
void PreferencesDialog::saveConfigTo()
|
||||
bool PreferencesDialog::saveConfigTo()
|
||||
{
|
||||
QString path = QFileDialog::getSaveFileName(this, tr("Save configurations..."), this->getWorkingDirectory()+"/config.ini", "*.ini");
|
||||
QString path = QFileDialog::getSaveFileName(this, tr("Save settings..."), this->getWorkingDirectory()+"/config.ini", "*.ini");
|
||||
if(!path.isEmpty())
|
||||
{
|
||||
this->writeSettings(path);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void PreferencesDialog::resetConfig()
|
||||
{
|
||||
int button = QMessageBox::warning(this,
|
||||
tr("Reset settings..."),
|
||||
tr("This will reset all settings. Restore all settings to default without saving them first?"),
|
||||
QMessageBox::Cancel | QMessageBox::Yes | QMessageBox::Save,
|
||||
QMessageBox::Cancel);
|
||||
if(button == QMessageBox::Yes ||
|
||||
(button == QMessageBox::Save && saveConfigTo()))
|
||||
{
|
||||
this->resetSettings(-1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1204,6 +1234,7 @@ void PreferencesDialog::writeCoreSettings(const QString & filePath)
|
||||
QCheckBox * check = qobject_cast<QCheckBox *>(obj);
|
||||
QRadioButton * radio = qobject_cast<QRadioButton *>(obj);
|
||||
QLineEdit * lineEdit = qobject_cast<QLineEdit *>(obj);
|
||||
QGroupBox * groupBox = qobject_cast<QGroupBox *>(obj);
|
||||
if(spin)
|
||||
{
|
||||
settings.setValue(obj->objectName(), spin->value());
|
||||
@@ -1228,6 +1259,10 @@ void PreferencesDialog::writeCoreSettings(const QString & filePath)
|
||||
{
|
||||
settings.setValue(obj->objectName(), lineEdit->text());
|
||||
}
|
||||
else if(groupBox)
|
||||
{
|
||||
settings.setValue(obj->objectName(), uBool2Str(groupBox->isChecked()).c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
ULOGGER_WARN("QObject called %s can't be cast to a supported widget", (*iter).first.c_str());
|
||||
@@ -1599,6 +1634,7 @@ void PreferencesDialog::setParameter(const std::string & key, const std::string
|
||||
QCheckBox * check = qobject_cast<QCheckBox *>(obj);
|
||||
QRadioButton * radio = qobject_cast<QRadioButton *>(obj);
|
||||
QLineEdit * lineEdit = qobject_cast<QLineEdit *>(obj);
|
||||
QGroupBox * groupBox = qobject_cast<QGroupBox *>(obj);
|
||||
bool ok;
|
||||
if(spin)
|
||||
{
|
||||
@@ -1636,6 +1672,10 @@ void PreferencesDialog::setParameter(const std::string & key, const std::string
|
||||
{
|
||||
lineEdit->setText(value.c_str());
|
||||
}
|
||||
else if(groupBox)
|
||||
{
|
||||
groupBox->setChecked(uStr2Bool(value.c_str()));
|
||||
}
|
||||
else
|
||||
{
|
||||
ULOGGER_WARN("QObject called %s can't be cast to a supported widget", key.c_str());
|
||||
@@ -1755,17 +1795,15 @@ void PreferencesDialog::addParameter(const QObject * object, int value)
|
||||
_ui->stackedWidget_odom->setCurrentIndex(2);
|
||||
}
|
||||
}
|
||||
else if(comboBox == _ui->loopClosure_icpType)
|
||||
else if(comboBox == _ui->globalDetection_icpType)
|
||||
{
|
||||
if(value == 0) // 0 icp3
|
||||
if(value == 1) // 1 icp3
|
||||
{
|
||||
this->addParameters(_ui->groupBox_loopClosure_icp3);
|
||||
_ui->stackedWidget_loopClosureICP->setCurrentIndex(0);
|
||||
}
|
||||
else if(value == 1) // 1 icp2
|
||||
else if(value == 2) // 2 icp2
|
||||
{
|
||||
this->addParameters(_ui->groupBox_loopClosure_icp2);
|
||||
_ui->stackedWidget_loopClosureICP->setCurrentIndex(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1797,28 +1835,38 @@ void PreferencesDialog::addParameter(const QObject * object, bool value)
|
||||
|
||||
const QCheckBox * checkbox = qobject_cast<const QCheckBox*>(object);
|
||||
const QRadioButton * radio = qobject_cast<const QRadioButton*>(object);
|
||||
if(checkbox || radio)
|
||||
const QGroupBox * groupBox = qobject_cast<const QGroupBox*>(object);
|
||||
if(checkbox || radio || groupBox)
|
||||
{
|
||||
// Add parameter
|
||||
_parameters.insert(rtabmap::ParametersPair(object->objectName().toStdString(), uBool2Str(value)));
|
||||
|
||||
// RGBD panel
|
||||
if(value && checkbox == _ui->general_checkBox_activateRGBD)
|
||||
{
|
||||
// add all RGBD parameters!
|
||||
this->addParameter(_ui->rgdb_linearUpdate, _ui->rgdb_linearUpdate->value());
|
||||
this->addParameter(_ui->rgdb_angularUpdate, _ui->rgdb_linearUpdate->value());
|
||||
this->addParameter(_ui->odomScanHistory, _ui->odomScanHistory->value());
|
||||
this->addParameters(_ui->groupBox_local_loop_closure);
|
||||
|
||||
this->addParameters(_ui->groupBox_lcc_bow);
|
||||
if(_ui->loopClosure_icpEnabled->isChecked())
|
||||
{
|
||||
this->addParameter(_ui->loopClosure_icpType, _ui->loopClosure_icpType->currentIndex());
|
||||
}
|
||||
this->addParameters(_ui->groupBox_slam_update);
|
||||
this->addParameters(_ui->groupBox_odom_correction);
|
||||
this->addParameters(_ui->groupBox_localDetection_time);
|
||||
this->addParameters(_ui->groupBox_localDetection_space);
|
||||
this->addParameters(_ui->groupBox_globalConstraints);
|
||||
this->addParameters(_ui->groupBox_visualTransform2);
|
||||
}
|
||||
if(value && checkbox == _ui->loopClosure_icpEnabled)
|
||||
|
||||
if(groupBox)
|
||||
{
|
||||
this->addParameter(_ui->loopClosure_icpType, _ui->loopClosure_icpType->currentIndex());
|
||||
// RGBD panel
|
||||
if(value && groupBox == _ui->groupBox_localDetection_time)
|
||||
{
|
||||
this->addParameters(_ui->groupBox_globalConstraints);
|
||||
this->addParameters(_ui->groupBox_visualTransform2);
|
||||
}
|
||||
if(value && groupBox == _ui->groupBox_localDetection_space)
|
||||
{
|
||||
this->addParameters(_ui->groupBox_loopClosure_icp2);
|
||||
}
|
||||
|
||||
this->addParameters(groupBox);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -1910,7 +1958,14 @@ void PreferencesDialog::addParameters(const QObjectList & children)
|
||||
}
|
||||
else if(groupBox)
|
||||
{
|
||||
this->addParameters(groupBox);
|
||||
if(groupBox->isCheckable())
|
||||
{
|
||||
this->addParameter(groupBox, groupBox->isChecked());
|
||||
}
|
||||
else
|
||||
{
|
||||
this->addParameters(groupBox);
|
||||
}
|
||||
}
|
||||
else if(stackedWidget)
|
||||
{
|
||||
|
||||
@@ -288,7 +288,7 @@
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>736</width>
|
||||
<height>21</height>
|
||||
<height>25</height>
|
||||
</rect>
|
||||
</property>
|
||||
<widget class="QMenu" name="menuFile">
|
||||
@@ -297,6 +297,8 @@
|
||||
</property>
|
||||
<addaction name="actionOpen_database"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionExport"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionQuit"/>
|
||||
</widget>
|
||||
<widget class="QMenu" name="menuEdit">
|
||||
@@ -359,6 +361,11 @@
|
||||
<string>Generate 3D map (.pcd) ...</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionExport">
|
||||
<property name="text">
|
||||
<string>Export...</string>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
|
||||
166
guilib/src/ui/exportDialog.ui
Normal file
166
guilib/src/ui/exportDialog.ui
Normal file
@@ -0,0 +1,166 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>ExportDialog</class>
|
||||
<widget class="QDialog" name="ExportDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>371</width>
|
||||
<height>236</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Export...</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<widget class="QSpinBox" name="spinBox_ignored">
|
||||
<property name="suffix">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Frames ignored</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="checkBox_rgb">
|
||||
<property name="text">
|
||||
<string>RGB images</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="checkBox_depth">
|
||||
<property name="text">
|
||||
<string>Depth images</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="checkBox_depth2d">
|
||||
<property name="text">
|
||||
<string>Depth 2D (laser scans)</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="checkBox_odom">
|
||||
<property name="text">
|
||||
<string>Odometry</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QLineEdit" name="lineEdit_path">
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="toolButton_path">
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>ExportDialog</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>248</x>
|
||||
<y>254</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>157</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>ExportDialog</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>316</x>
|
||||
<y>260</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>286</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
||||
@@ -102,7 +102,7 @@
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>809</width>
|
||||
<height>21</height>
|
||||
<height>25</height>
|
||||
</rect>
|
||||
</property>
|
||||
<widget class="QMenu" name="menuFile">
|
||||
@@ -128,6 +128,7 @@
|
||||
<addaction name="actionDump_the_prediction_matrix"/>
|
||||
<addaction name="actionGenerate_map"/>
|
||||
<addaction name="actionGenerate_local_map"/>
|
||||
<addaction name="actionGenerate_TORO_graph_graph"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionView_high_res_point_cloud"/>
|
||||
<addaction name="actionSave_point_cloud"/>
|
||||
@@ -620,6 +621,27 @@
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
<widget class="QDockWidget" name="dockWidget_mapVisibility">
|
||||
<property name="windowTitle">
|
||||
<string>Map visibility</string>
|
||||
</property>
|
||||
<attribute name="dockWidgetArea">
|
||||
<number>8</number>
|
||||
</attribute>
|
||||
<widget class="QWidget" name="dockWidgetContents_8">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_9">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="margin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="rtabmap::MapVisibilityWidget" name="widget_mapVisibility" native="true"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
<action name="actionExit">
|
||||
<property name="text">
|
||||
<string>Exit</string>
|
||||
@@ -909,6 +931,11 @@
|
||||
<string>Trigger a new map</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionGenerate_TORO_graph_graph">
|
||||
<property name="text">
|
||||
<string>Generate TORO graph (*.graph)...</string>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
@@ -946,6 +973,12 @@
|
||||
<header>../include/rtabmap/gui/LoopClosureViewer.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>rtabmap::MapVisibilityWidget</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>MapVisibilityWidget.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources>
|
||||
<include location="../GuiLib.qrc"/>
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user