Moved some util3d methods to Transform.h, Graph.h and Compression.h

Added computePath() method implementating A star on graph
GUI: SetWindowModified() and user should explicitly save the GUI config to keep them
Calibration: added mirror checkbox, added device id argument
This commit is contained in:
Mathieu Labbe
2015-01-23 11:17:42 -05:00
parent fdf7f69783
commit 7a6bf630ca
34 changed files with 1817 additions and 1282 deletions

View File

@@ -185,6 +185,9 @@ public slots:
void setCloudPointSize(const std::string & id, int size);
virtual void clear() {removeAllClouds(); clearTrajectory();}
signals:
void configChanged();
protected:
virtual void keyReleaseEvent(QKeyEvent * event);
virtual void keyPressEvent(QKeyEvent * event);

View File

@@ -75,6 +75,9 @@ public:
void clearLines();
void clear();
signals:
void configChanged();
protected:
virtual void contextMenuEvent(QContextMenuEvent * e);
virtual void wheelEvent(QWheelEvent * e);

View File

@@ -109,11 +109,15 @@ public slots:
protected:
virtual void closeEvent(QCloseEvent* event);
virtual void handleEvent(UEvent* anEvent);
virtual void showEvent(QShowEvent* anEvent);
virtual void moveEvent(QMoveEvent* anEvent);
virtual void resizeEvent(QResizeEvent* anEvent);
private slots:
void changeState(MainWindow::State state);
void beep();
void configGUIModified();
void saveConfigGUI();
void newDatabase();
void openDatabase();
void closeDatabase();

View File

@@ -97,12 +97,12 @@ public:
virtual QString getIniFilePath() const;
void init();
void saveWindowGeometry(const QString & windowName, const QWidget * window);
void loadWindowGeometry(const QString & windowName, QWidget * window);
void saveWindowGeometry(const QWidget * window);
void loadWindowGeometry(QWidget * window);
void saveMainWindowState(const QMainWindow * mainWindow);
void loadMainWindowState(QMainWindow * mainWindow);
void saveWidgetState(const QString & name, const QWidget * widget);
void loadWidgetState(const QString & name, QWidget * widget);
void saveWidgetState(const QWidget * widget);
void loadWidgetState(QWidget * widget);
void saveCustomConfig(const QString & section, const QString & key, const QString & value);
QString loadCustomConfig(const QString & section, const QString & key);

View File

@@ -245,7 +245,7 @@ void CalibrationDialog::processImage(const cv::Mat & image)
}
//show frame
ui_->image_view->setImage(uCvMat2QImage(image));
ui_->image_view->setImage(uCvMat2QImage(image).mirrored(ui_->checkBox_mirror->isChecked(), false));
}
void CalibrationDialog::restart()

View File

@@ -97,6 +97,8 @@ CloudViewer::CloudViewer(QWidget *parent) :
//setup menu/actions
createMenu();
setMouseTracking(false);
}
CloudViewer::~CloudViewer()
@@ -171,7 +173,7 @@ bool CloudViewer::updateCloudPose(
{
UDEBUG("Updating pose %s to %s", id.c_str(), pose.prettyPrint().c_str());
if(_addedClouds.find(id).value() == pose ||
_visualizer->updatePointCloudPose(id, util3d::transformToEigen3f(pose)))
_visualizer->updatePointCloudPose(id, pose.toEigen3f()))
{
_addedClouds.find(id).value() = pose;
return true;
@@ -254,7 +256,7 @@ bool CloudViewer::addCloud(
if(!_addedClouds.contains(id))
{
Eigen::Vector4f origin(pose.x(), pose.y(), pose.z(), 0.0f);
Eigen::Quaternionf orientation = Eigen::Quaternionf(util3d::transformToEigen3f(pose).rotation());
Eigen::Quaternionf orientation = Eigen::Quaternionf(pose.toEigen3f().rotation());
// add random color channel
pcl::visualization::PointCloudColorHandler<pcl::PCLPointCloud2>::Ptr colorHandler;
@@ -334,7 +336,7 @@ bool CloudViewer::addCloudMesh(
UDEBUG("Adding %s with %d points and %d polygons", id.c_str(), (int)cloud->size(), (int)polygons.size());
if(_visualizer->addPolygonMesh<pcl::PointXYZRGB>(cloud, polygons, id))
{
_visualizer->updatePointCloudPose(id, util3d::transformToEigen3f(pose));
_visualizer->updatePointCloudPose(id, pose.toEigen3f());
_addedClouds.insert(id, pose);
return true;
}
@@ -352,7 +354,7 @@ bool CloudViewer::addCloudMesh(
UDEBUG("Adding %s with %d polygons", id.c_str(), (int)mesh->polygons.size());
if(_visualizer->addPolygonMesh(*mesh, id))
{
_visualizer->updatePointCloudPose(id, util3d::transformToEigen3f(pose));
_visualizer->updatePointCloudPose(id, pose.toEigen3f());
_addedClouds.insert(id, pose);
return true;
}
@@ -580,7 +582,7 @@ void CloudViewer::updateCameraTargetPosition(const Transform & pose)
{
if(!pose.isNull())
{
Eigen::Affine3f m = util3d::transformToEigen3f(pose);
Eigen::Affine3f m = pose.toEigen3f();
Eigen::Vector3f pos = m.translation();
Eigen::Vector3f lastPos(0,0,0);
@@ -1044,6 +1046,8 @@ void CloudViewer::keyPressEvent(QKeyEvent * event)
cameras.front().view[0], cameras.front().view[1], cameras.front().view[2]);
render();
emit configChanged();
}
else
{
@@ -1082,6 +1086,7 @@ void CloudViewer::mouseMoveEvent(QMouseEvent * event)
cameras.front().view[0], cameras.front().view[1], cameras.front().view[2]);
}
emit configChanged();
}
void CloudViewer::contextMenuEvent(QContextMenuEvent * event)
@@ -1090,6 +1095,7 @@ void CloudViewer::contextMenuEvent(QContextMenuEvent * event)
if(a)
{
handleAction(a);
emit configChanged();
}
}

View File

@@ -49,6 +49,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "rtabmap/core/util3d.h"
#include "rtabmap/core/Signature.h"
#include "rtabmap/core/Features2d.h"
#include "rtabmap/core/Compression.h"
#include "rtabmap/core/Graph.h"
#include "rtabmap/gui/DataRecorder.h"
#include "rtabmap/core/SensorData.h"
#include "ExportDialog.h"
@@ -239,7 +241,7 @@ void DatabaseViewer::closeEvent(QCloseEvent* event)
// Added links
for(std::multimap<int, rtabmap::Link>::iterator iter=linksAdded_.begin(); iter!=linksAdded_.end(); ++iter)
{
std::multimap<int, rtabmap::Link>::iterator refinedIter = util3d::findLink(linksRefined_, iter->second.from(), iter->second.to());
std::multimap<int, rtabmap::Link>::iterator refinedIter = rtabmap::findLink(linksRefined_, iter->second.from(), iter->second.to());
if(refinedIter != linksRefined_.end())
{
memory_->addLoopClosureLink(refinedIter->second.to(), refinedIter->second.from(), refinedIter->second.transform(), refinedIter->second.type(), refinedIter->second.variance());
@@ -373,7 +375,7 @@ void DatabaseViewer::extractImages()
cv::Mat compressedRgb = memory_->getImageCompressed(id);
if(!compressedRgb.empty())
{
cv::Mat imageMat = rtabmap::util3d::uncompressImage(compressedRgb);
cv::Mat imageMat = rtabmap::uncompressImage(compressedRgb);
cv::imwrite(QString("%1/%2.png").arg(path).arg(id).toStdString(), imageMat);
UINFO(QString("Saved %1/%2.png").arg(path).arg(id).toStdString().c_str());
}
@@ -569,7 +571,7 @@ void DatabaseViewer::generateTOROGraph()
QString path = QFileDialog::getSaveFileName(this, tr("Save File"), pathDatabase_+"/constraints" + QString::number(id) + ".graph", tr("TORO file (*.graph)"));
if(!path.isEmpty())
{
rtabmap::util3d::saveTOROGraph(path.toStdString(), uValueAt(graphes_, id), links);
rtabmap::saveTOROGraph(path.toStdString(), uValueAt(graphes_, id), links);
}
}
}
@@ -801,7 +803,7 @@ void DatabaseViewer::detectMoreLoopClosures()
for(int n=0; n<iterations; ++n)
{
UINFO("iteration %d/%d", n+1, iterations);
std::multimap<int, int> clusters = util3d::radiusPosesClustering(
std::multimap<int, int> clusters = rtabmap::radiusPosesClustering(
optimizedPoses,
ui_->doubleSpinBox_detectMore_radius->value(),
ui_->doubleSpinBox_detectMore_angle->value()*CV_PI/180.0);
@@ -1216,7 +1218,7 @@ void DatabaseViewer::updateStereo(const Signature * data)
if(pcl::isFinite(tmpPt))
{
pt = pcl::transformPoint(tmpPt, util3d::transformToEigen3f(data->getLocalTransform()));
pt = pcl::transformPoint(tmpPt, data->getLocalTransform().toEigen3f());
if(fabs(pt.x) > 2 || fabs(pt.y) > 2 || fabs(pt.z) > 2)
{
status[i] = 100; //blue
@@ -1413,7 +1415,7 @@ void DatabaseViewer::updateConstraintView(const rtabmap::Link & linkIn,
const pcl::PointCloud<pcl::PointXYZ>::Ptr & cloudTo,
bool updateImageSliders)
{
std::multimap<int, Link>::iterator iter = util3d::findLink(linksRefined_, linkIn.from(), linkIn.to());
std::multimap<int, Link>::iterator iter = rtabmap::findLink(linksRefined_, linkIn.from(), linkIn.to());
rtabmap::Link link = linkIn;
if(iter != linksRefined_.end())
{
@@ -1696,7 +1698,7 @@ void DatabaseViewer::updateConstraintButtons()
//check for modified link
bool modified = false;
std::multimap<int, Link>::iterator iter = util3d::findLink(linksRefined_, currentLink.from(), currentLink.to());
std::multimap<int, Link>::iterator iter = rtabmap::findLink(linksRefined_, currentLink.from(), currentLink.to());
if(iter != linksRefined_.end())
{
currentLink = iter->second;
@@ -1726,7 +1728,7 @@ void DatabaseViewer::sliderIterationsValueChanged(int value)
if(!data.getLaserScanCompressed().empty())
{
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud;
cv::Mat laserScan = rtabmap::util3d::uncompressData(data.getLaserScanCompressed());
cv::Mat laserScan = rtabmap::uncompressData(data.getLaserScanCompressed());
cloud = rtabmap::util3d::laserScanToPointCloud(laserScan);
scans_.insert(std::make_pair(ids_.at(i), cloud));
}
@@ -1786,8 +1788,8 @@ void DatabaseViewer::updateGraphView()
graphes_.push_back(poses_);
ui_->actionGenerate_TORO_graph_graph->setEnabled(true);
std::multimap<int, rtabmap::Link> links = updateLinksWithModifications(links_);
std::map<int, int> depthGraph = util3d::generateDepthGraph(links, ui_->spinBox_optimizationsFrom->value(), 0);
util3d::optimizeTOROGraph(
std::map<int, int> depthGraph = rtabmap::generateDepthGraph(links, ui_->spinBox_optimizationsFrom->value(), 0);
rtabmap::optimizeTOROGraph(
depthGraph,
poses_,
links, finalPoses,
@@ -1813,21 +1815,21 @@ void DatabaseViewer::updateGraphView()
Link DatabaseViewer::findActiveLink(int from, int to)
{
Link link;
std::multimap<int, Link>::iterator findIter = util3d::findLink(linksRefined_, from ,to);
std::multimap<int, Link>::iterator findIter = rtabmap::findLink(linksRefined_, from ,to);
if(findIter != linksRefined_.end())
{
link = findIter->second;
}
else
{
findIter = util3d::findLink(linksAdded_, from ,to);
findIter = rtabmap::findLink(linksAdded_, from ,to);
if(findIter != linksAdded_.end())
{
link = findIter->second;
}
else if(!containsLink(linksRemoved_, from ,to))
{
findIter = util3d::findLink(links_, from ,to);
findIter = rtabmap::findLink(links_, from ,to);
if(findIter != links_.end())
{
link = findIter->second;
@@ -1839,7 +1841,7 @@ Link DatabaseViewer::findActiveLink(int from, int to)
bool DatabaseViewer::containsLink(std::multimap<int, Link> & links, int from, int to)
{
return util3d::findLink(links, from, to) != links.end();
return rtabmap::findLink(links, from, to) != links.end();
}
void DatabaseViewer::refineConstraint()
@@ -1897,8 +1899,8 @@ void DatabaseViewer::refineConstraint(int from, int to, bool updateGraph)
if(ui_->checkBox_icp_2d->isChecked())
{
//2D
cv::Mat oldLaserScan = util3d::uncompressData(dataFrom.getLaserScanCompressed());
cv::Mat newLaserScan = util3d::uncompressData(dataTo.getLaserScanCompressed());
cv::Mat oldLaserScan = rtabmap::uncompressData(dataFrom.getLaserScanCompressed());
cv::Mat newLaserScan = rtabmap::uncompressData(dataTo.getLaserScanCompressed());
if(!oldLaserScan.empty() && !newLaserScan.empty())
{
@@ -1928,13 +1930,13 @@ void DatabaseViewer::refineConstraint(int from, int to, bool updateGraph)
else
{
//3D
cv::Mat depthA = rtabmap::util3d::uncompressImage(dataFrom.getDepthCompressed());
cv::Mat depthB = rtabmap::util3d::uncompressImage(dataTo.getDepthCompressed());
cv::Mat depthA = rtabmap::uncompressImage(dataFrom.getDepthCompressed());
cv::Mat depthB = rtabmap::uncompressImage(dataTo.getDepthCompressed());
if(depthA.type() == CV_8UC1)
{
cv::Mat leftMono;
cv::Mat left = rtabmap::util3d::uncompressImage(dataFrom.getImageCompressed());
cv::Mat left = rtabmap::uncompressImage(dataFrom.getImageCompressed());
if(left.channels() > 1)
{
cv::cvtColor(left, leftMono, CV_BGR2GRAY);
@@ -1967,7 +1969,7 @@ void DatabaseViewer::refineConstraint(int from, int to, bool updateGraph)
if(depthB.type() == CV_8UC1)
{
cv::Mat leftMono;
cv::Mat left = rtabmap::util3d::uncompressImage(dataTo.getImageCompressed());
cv::Mat left = rtabmap::uncompressImage(dataTo.getImageCompressed());
if(left.channels() > 1)
{
cv::cvtColor(left, leftMono, CV_BGR2GRAY);
@@ -2266,7 +2268,7 @@ bool DatabaseViewer::addConstraint(int from, int to, bool silent, bool updateGra
// We are 2D here, make sure the guess has only YAW rotation
float x,y,z,r,p,yaw;
t.getTranslationAndEulerAngles(x,y,z, r,p,yaw);
t = util3d::transformFromEigen3f(pcl::getTransformation(x,y,0, 0, 0, yaw));
t = Transform::fromEigen3f(pcl::getTransformation(x,y,0, 0, 0, yaw));
}
// transform is valid, make a link
@@ -2277,7 +2279,7 @@ bool DatabaseViewer::addConstraint(int from, int to, bool silent, bool updateGra
else if(containsLink(linksRemoved_, from, to))
{
//simply remove from linksRemoved
linksRemoved_.erase(util3d::findLink(linksRemoved_, from, to));
linksRemoved_.erase(rtabmap::findLink(linksRemoved_, from, to));
updateSlider = true;
}
@@ -2310,19 +2312,19 @@ void DatabaseViewer::resetConstraint()
}
std::multimap<int, Link>::iterator iter = util3d::findLink(linksRefined_, from, to);
std::multimap<int, Link>::iterator iter = rtabmap::findLink(linksRefined_, from, to);
if(iter != linksRefined_.end())
{
linksRefined_.erase(iter);
this->updateGraphView();
}
iter = util3d::findLink(links_, from, to);
iter = rtabmap::findLink(links_, from, to);
if(iter != links_.end())
{
this->updateConstraintView(iter->second);
}
iter = util3d::findLink(linksAdded_, from, to);
iter = rtabmap::findLink(linksAdded_, from, to);
if(iter != linksAdded_.end())
{
this->updateConstraintView(iter->second);
@@ -2350,7 +2352,7 @@ void DatabaseViewer::rejectConstraint()
// find the original one
std::multimap<int, Link>::iterator iter;
iter = util3d::findLink(links_, from, to);
iter = rtabmap::findLink(links_, from, to);
if(iter != links_.end())
{
if(iter->second.type() == Link::kNeighbor)
@@ -2363,13 +2365,13 @@ void DatabaseViewer::rejectConstraint()
}
// remove from refined and added
iter = util3d::findLink(linksRefined_, from, to);
iter = rtabmap::findLink(linksRefined_, from, to);
if(iter != linksRefined_.end())
{
linksRefined_.erase(iter);
removed = true;
}
iter = util3d::findLink(linksAdded_, from, to);
iter = rtabmap::findLink(linksAdded_, from, to);
if(iter != linksAdded_.end())
{
linksAdded_.erase(iter);
@@ -2392,7 +2394,7 @@ std::multimap<int, rtabmap::Link> DatabaseViewer::updateLinksWithModifications(
{
std::multimap<int, rtabmap::Link>::iterator findIter;
findIter = util3d::findLink(linksRemoved_, iter->second.from(), iter->second.to());
findIter = rtabmap::findLink(linksRemoved_, iter->second.from(), iter->second.to());
if(findIter != linksRemoved_.end())
{
if(!(iter->second.from() == findIter->second.from() &&
@@ -2410,7 +2412,7 @@ std::multimap<int, rtabmap::Link> DatabaseViewer::updateLinksWithModifications(
}
}
findIter = util3d::findLink(linksRefined_, iter->second.from(), iter->second.to());
findIter = rtabmap::findLink(linksRefined_, iter->second.from(), iter->second.to());
if(findIter!=linksRefined_.end())
{
if(iter->second.from() == findIter->second.from() &&

View File

@@ -39,6 +39,19 @@ ExportCloudsDialog::ExportCloudsDialog(QWidget *parent) :
_ui->setupUi(this);
connect(_ui->buttonBox->button(QDialogButtonBox::RestoreDefaults), SIGNAL(clicked()), this, SLOT(restoreDefaults()));
connect(_ui->groupBox_assemble, SIGNAL(clicked(bool)), this, SIGNAL(configChanged()));
connect(_ui->doubleSpinBox_voxelSize_assembled, SIGNAL(valueChanged(double)), this, SIGNAL(configChanged()));
connect(_ui->groupBox_regenerate, SIGNAL(clicked(bool)), this, SIGNAL(configChanged()));
connect(_ui->spinBox_decimation, SIGNAL(valueChanged(int)), this, SIGNAL(configChanged()));
connect(_ui->doubleSpinBox_voxelSize, SIGNAL(valueChanged(double)), this, SIGNAL(configChanged()));
connect(_ui->doubleSpinBox_maxDepth, SIGNAL(valueChanged(double)), this, SIGNAL(configChanged()));
connect(_ui->checkBox_binary, SIGNAL(stateChanged(int)), this, SIGNAL(configChanged()));
connect(_ui->groupBox_mls, SIGNAL(clicked(bool)), this, SIGNAL(configChanged()));
connect(_ui->doubleSpinBox_mlsRadius, SIGNAL(valueChanged(double)), this, SIGNAL(configChanged()));
connect(_ui->groupBox_gp3, SIGNAL(clicked(bool)), this, SIGNAL(configChanged()));
connect(_ui->spinBox_normalKSearch, SIGNAL(valueChanged(int)), this, SIGNAL(configChanged()));
connect(_ui->doubleSpinBox_gp3Radius, SIGNAL(valueChanged(double)), this, SIGNAL(configChanged()));
}
ExportCloudsDialog::~ExportCloudsDialog()

View File

@@ -76,6 +76,9 @@ public:
void setMeshNormalKSearch(int k);
void setMeshGp3Radius(double radius);
signals:
void configChanged();
public slots:
void restoreDefaults();

View File

@@ -40,6 +40,12 @@ ExportDialog::ExportDialog(QWidget * parent) :
connect(_ui->toolButton_path, SIGNAL(clicked()), this, SLOT(getPath()));
connect(_ui->spinBox_ignored, SIGNAL(valueChanged(int)), this, SIGNAL(configChanged()));
connect(_ui->checkBox_rgb, SIGNAL(stateChanged(int)), this, SIGNAL(configChanged()));
connect(_ui->checkBox_depth, SIGNAL(stateChanged(int)), this, SIGNAL(configChanged()));
connect(_ui->checkBox_depth2d, SIGNAL(stateChanged(int)), this, SIGNAL(configChanged()));
connect(_ui->checkBox_odom, SIGNAL(stateChanged(int)), this, SIGNAL(configChanged()));
_ui->lineEdit_path->setText(QDir::homePath()+QDir::separator()+"output.db");
}

View File

@@ -50,6 +50,9 @@ public:
bool isDepth2dExported() const;
bool isOdomExported() const;
signals:
void configChanged();
private slots:
void getPath();

View File

@@ -162,23 +162,28 @@ void ImageView::contextMenuEvent(QContextMenuEvent * e)
else if(action == _showFeatures)
{
this->setFeaturesShown(_showFeatures->isChecked());
emit configChanged();
}
else if(action == _showImage)
{
this->setImageShown(_showImage->isChecked());
emit configChanged();
}
else if(action == _showImageDepth)
{
this->setImageDepthShown(_showImageDepth->isChecked());
emit configChanged();
}
else if(action == _showLines)
{
this->setLinesShown(_showLines->isChecked());
emit configChanged();
}
if(action == _showImage || action ==_showImageDepth)
{
this->updateOpacity();
emit configChanged();
}
}

View File

@@ -82,6 +82,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "rtabmap/core/Odometry.h"
#include "rtabmap/core/OdometryEvent.h"
#include "rtabmap/core/util3d.h"
#include "rtabmap/core/Graph.h"
#include <pcl/visualization/cloud_viewer.h>
#include <pcl/common/transforms.h>
#include <pcl/common/common.h>
@@ -128,7 +129,7 @@ MainWindow::MainWindow(PreferencesDialog * prefDialog, QWidget * parent) :
_rawLikelihoodCurve(0),
_autoScreenCaptureOdomSync(false)
{
ULOGGER_DEBUG("");
UDEBUG("");
initGuiResource();
@@ -140,6 +141,7 @@ MainWindow::MainWindow(PreferencesDialog * prefDialog, QWidget * parent) :
// Create dialogs
_aboutDialog = new AboutDialog(this);
_aboutDialog->setObjectName("AboutDialog");
_exportDialog = new ExportCloudsDialog(this);
_exportDialog->setObjectName("ExportCloudsDialog");
_postProcessingDialog = new PostProcessingDialog(this);
@@ -148,9 +150,10 @@ MainWindow::MainWindow(PreferencesDialog * prefDialog, QWidget * parent) :
_ui = new Ui_mainWindow();
_ui->setupUi(this);
QString title("RTAB-Map: Real-Time Appearance-Based Mapping");
QString title("RTAB-Map[*]");
this->setWindowTitle(title);
this->setWindowIconText(tr("RTAB-Map"));
this->setObjectName("MainWindow");
//Setup dock widgets position if it is the first time the application is started.
//if(!QFile::exists(PreferencesDialog::getIniFilePath()))
@@ -179,10 +182,15 @@ MainWindow::MainWindow(PreferencesDialog * prefDialog, QWidget * parent) :
{
_preferencesDialog = new PreferencesDialog(this);
}
_preferencesDialog->setObjectName("PreferencesDialog");
_preferencesDialog->init();
// Restore window geometry
_preferencesDialog->loadMainWindowState(this);
_preferencesDialog->loadWindowGeometry(_preferencesDialog);
_preferencesDialog->loadWindowGeometry(_exportDialog);
_preferencesDialog->loadWindowGeometry(_postProcessingDialog);
_preferencesDialog->loadWindowGeometry(_aboutDialog);
setupMainLayout(_preferencesDialog->isVerticalLayoutUsed());
// Timer
@@ -198,9 +206,9 @@ MainWindow::MainWindow(PreferencesDialog * prefDialog, QWidget * parent) :
_ui->imageView_source->setBackgroundBrush(QBrush(Qt::black));
_ui->imageView_loopClosure->setBackgroundBrush(QBrush(Qt::black));
_ui->imageView_odometry->setBackgroundBrush(QBrush(Qt::black));
_preferencesDialog->loadWidgetState(_ui->imageView_source->objectName(), _ui->imageView_source);
_preferencesDialog->loadWidgetState(_ui->imageView_loopClosure->objectName(), _ui->imageView_loopClosure);
_preferencesDialog->loadWidgetState(_ui->imageView_odometry->objectName(), _ui->imageView_odometry);
_preferencesDialog->loadWidgetState(_ui->imageView_source);
_preferencesDialog->loadWidgetState(_ui->imageView_loopClosure);
_preferencesDialog->loadWidgetState(_ui->imageView_odometry);
_posteriorCurve = new PdfPlotCurve("Posterior", &_cachedSignatures, this);
_ui->posteriorPlot->addCurve(_posteriorCurve, false);
@@ -255,6 +263,7 @@ MainWindow::MainWindow(PreferencesDialog * prefDialog, QWidget * parent) :
connect(a, SIGNAL(triggered(bool)), _initProgressDialog, SLOT(show()));
// connect actions with custom slots
connect(_ui->actionSave_GUI_config, SIGNAL(triggered()), this, SLOT(saveConfigGUI()));
connect(_ui->actionNew_database, SIGNAL(triggered()), this, SLOT(newDatabase()));
connect(_ui->actionOpen_database, SIGNAL(triggered()), this, SLOT(openDatabase()));
connect(_ui->actionClose_database, SIGNAL(triggered()), this, SLOT(closeDatabase()));
@@ -295,6 +304,7 @@ MainWindow::MainWindow(PreferencesDialog * prefDialog, QWidget * parent) :
connect(_ui->actionPost_processing, SIGNAL(triggered()), this, SLOT(postProcessing()));
_ui->actionPause->setShortcut(Qt::Key_Space);
_ui->actionSave_GUI_config->setShortcut(QKeySequence::Save);
_ui->actionSave_point_cloud->setEnabled(false);
_ui->actionExport_2D_scans_ply_pcd->setEnabled(false);
_ui->actionExport_2D_Grid_map_bmp_png->setEnabled(false);
@@ -349,6 +359,21 @@ MainWindow::MainWindow(PreferencesDialog * prefDialog, QWidget * parent) :
connect(_preferencesDialog, SIGNAL(settingsChanged(PreferencesDialog::PANEL_FLAGS)), this, SLOT(applyPrefSettings(PreferencesDialog::PANEL_FLAGS)));
qRegisterMetaType<rtabmap::ParametersMap>("rtabmap::ParametersMap");
connect(_preferencesDialog, SIGNAL(settingsChanged(rtabmap::ParametersMap)), this, SLOT(applyPrefSettings(rtabmap::ParametersMap)));
// config GUI modified
connect(_ui->imageView_source, SIGNAL(configChanged()), this, SLOT(configGUIModified()));
connect(_ui->imageView_loopClosure, SIGNAL(configChanged()), this, SLOT(configGUIModified()));
connect(_ui->imageView_odometry, SIGNAL(configChanged()), this, SLOT(configGUIModified()));
connect(_ui->widget_cloudViewer, SIGNAL(configChanged()), this, SLOT(configGUIModified()));
connect(_exportDialog, SIGNAL(configChanged()), this, SLOT(configGUIModified()));
connect(_postProcessingDialog, SIGNAL(configChanged()), this, SLOT(configGUIModified()));
connect(_ui->toolBar->toggleViewAction(), SIGNAL(toggled(bool)), this, SLOT(configGUIModified()));
connect(_ui->toolBar, SIGNAL(orientationChanged(Qt::Orientation)), this, SLOT(configGUIModified()));
QList<QDockWidget*> dockWidgets = this->findChildren<QDockWidget*>();
for(int i=0; i<dockWidgets.size(); ++i)
{
connect(dockWidgets[i], SIGNAL(dockLocationChanged(Qt::DockWidgetArea)), this, SLOT(configGUIModified()));
connect(dockWidgets[i]->toggleViewAction(), SIGNAL(toggled(bool)), this, SLOT(configGUIModified()));
}
// more connects...
connect(_ui->doubleSpinBox_stats_imgRate, SIGNAL(editingFinished()), this, SLOT(changeImgRateSetting()));
@@ -375,11 +400,11 @@ MainWindow::MainWindow(PreferencesDialog * prefDialog, QWidget * parent) :
_ui->statsToolBox->setWorkingDirectory(_preferencesDialog->getWorkingDirectory());
_ui->graphicsView_graphView->setWorkingDirectory(_preferencesDialog->getWorkingDirectory());
_ui->widget_cloudViewer->setWorkingDirectory(_preferencesDialog->getWorkingDirectory());
_preferencesDialog->loadWidgetState(_ui->widget_cloudViewer->objectName(), _ui->widget_cloudViewer);
_preferencesDialog->loadWidgetState(_ui->widget_cloudViewer);
//dialog states
_preferencesDialog->loadWidgetState(_exportDialog->objectName(), _exportDialog);
_preferencesDialog->loadWidgetState(_postProcessingDialog->objectName(), _postProcessingDialog);
_preferencesDialog->loadWidgetState(_exportDialog);
_preferencesDialog->loadWidgetState(_postProcessingDialog);
if(_ui->statsToolBox->findChildren<StatItem*>().size() == 0)
{
@@ -404,6 +429,8 @@ MainWindow::MainWindow(PreferencesDialog * prefDialog, QWidget * parent) :
splash.close();
this->setFocus();
UDEBUG("");
}
MainWindow::~MainWindow()
@@ -454,16 +481,32 @@ void MainWindow::closeEvent(QCloseEvent* event)
if(processStopped)
{
//write settings before quit?
bool save = false;
if(this->isWindowModified())
{
QMessageBox::Button b=QMessageBox::question(this,
tr("RTAB-Map"),
tr("There are unsaved GUI changes. Save them?"),
QMessageBox::Save | QMessageBox::Cancel | QMessageBox::Discard);
if(b == QMessageBox::Save)
{
save = true;
}
else if(b != QMessageBox::Discard)
{
event->ignore();
return;
}
}
if(save)
{
saveConfigGUI();
}
_ui->statsToolBox->closeFigures();
//write settings before quit?
_preferencesDialog->saveMainWindowState(this);
_preferencesDialog->saveWidgetState(_ui->widget_cloudViewer->objectName(), _ui->widget_cloudViewer);
_preferencesDialog->saveWidgetState(_ui->imageView_source->objectName(), _ui->imageView_source);
_preferencesDialog->saveWidgetState(_ui->imageView_loopClosure->objectName(), _ui->imageView_loopClosure);
_preferencesDialog->saveWidgetState(_ui->imageView_odometry->objectName(), _ui->imageView_odometry);
_preferencesDialog->saveWidgetState(_exportDialog->objectName(), _exportDialog);
_preferencesDialog->saveWidgetState(_postProcessingDialog->objectName(), _postProcessingDialog);
_ui->dockWidget_imageView->close();
_ui->dockWidget_likelihood->close();
_ui->dockWidget_rawlikelihood->close();
@@ -1131,7 +1174,7 @@ void MainWindow::updateMapCloud(
{
float radius = _preferencesDialog->getCloudFilteringRadius();
float angle = _preferencesDialog->getCloudFilteringAngle()*CV_PI/180.0; // convert to rad
poses = util3d::radiusPosesFiltering(posesIn, radius, angle);
poses = rtabmap::radiusPosesFiltering(posesIn, radius, angle);
// make sure the last is here
poses.insert(*posesIn.rbegin());
for(std::map<int, Transform>::iterator iter= poses.begin(); iter!=poses.end(); ++iter)
@@ -2027,6 +2070,25 @@ void MainWindow::drawKeypoints(const std::multimap<int, cv::KeyPoint> & refWords
}
}
void MainWindow::showEvent(QShowEvent* anEvent)
{
this->setWindowModified(false);
}
void MainWindow::moveEvent(QMoveEvent* anEvent)
{
if(this->isVisible())
{
// HACK, there is a move event when the window is shown the first time.
static bool firstCall = true;
if(!firstCall)
{
this->configGUIModified();
}
firstCall = false;
}
}
void MainWindow::resizeEvent(QResizeEvent* anEvent)
{
_ui->imageView_source->fitInView(_ui->imageView_source->sceneRect(), Qt::KeepAspectRatio);
@@ -2035,6 +2097,10 @@ void MainWindow::resizeEvent(QResizeEvent* anEvent)
_ui->imageView_source->resetZoom();
_ui->imageView_loopClosure->resetZoom();
_ui->imageView_odometry->resetZoom();
if(this->isVisible())
{
this->configGUIModified();
}
}
void MainWindow::updateSelectSourceImageMenu(bool used, PreferencesDialog::Src src)
@@ -2108,7 +2174,26 @@ void MainWindow::beep()
QApplication::beep();
}
void MainWindow::configGUIModified()
{
this->setWindowModified(true);
}
//ACTIONS
void MainWindow::saveConfigGUI()
{
_preferencesDialog->saveMainWindowState(this);
_preferencesDialog->saveWindowGeometry(_preferencesDialog);
_preferencesDialog->saveWindowGeometry(_aboutDialog);
_preferencesDialog->saveWidgetState(_ui->widget_cloudViewer);
_preferencesDialog->saveWidgetState(_ui->imageView_source);
_preferencesDialog->saveWidgetState(_ui->imageView_loopClosure);
_preferencesDialog->saveWidgetState(_ui->imageView_odometry);
_preferencesDialog->saveWidgetState(_exportDialog);
_preferencesDialog->saveWidgetState(_postProcessingDialog);
this->setWindowModified(false);
}
void MainWindow::newDatabase()
{
if(_state != MainWindow::kIdle)
@@ -2871,7 +2956,7 @@ void MainWindow::postProcessing()
_initProgressDialog->appendText(tr("Looking for more loop closures, clustering poses... (iteration=%1/%2, radius=%3 m angle=%4 degrees)")
.arg(n+1).arg(detectLoopClosureIterations).arg(clusterRadius).arg(clusterAngle));
std::multimap<int, int> clusters = util3d::radiusPosesClustering(
std::multimap<int, int> clusters = rtabmap::radiusPosesClustering(
_currentPosesMap,
clusterRadius,
clusterAngle*CV_PI/180.0);
@@ -2893,7 +2978,7 @@ void MainWindow::postProcessing()
// only add new links and one per cluster per iteration
if(addedLinks.find(from) == addedLinks.end() && addedLinks.find(to) == addedLinks.end() &&
util3d::findLink(_currentLinksMap, from, to) == _currentLinksMap.end())
rtabmap::findLink(_currentLinksMap, from, to) == _currentLinksMap.end())
{
if(!_cachedSignatures.contains(from))
{
@@ -2976,8 +3061,8 @@ void MainWindow::postProcessing()
_initProgressDialog->appendText(tr("Optimizing graph with new links (%1 nodes, %2 constraints)...")
.arg(odomPoses.size()).arg(_currentLinksMap.size()));
std::map<int, rtabmap::Transform> optimizedPoses;
std::map<int, int> depthGraph = util3d::generateDepthGraph(_currentLinksMap, toroOptimizeFromGraphEnd?odomPoses.rbegin()->first:odomPoses.begin()->first);
util3d::optimizeTOROGraph(depthGraph, odomPoses, _currentLinksMap, optimizedPoses, toroIterations, true, ignoreVariance);
std::map<int, int> depthGraph = rtabmap::generateDepthGraph(_currentLinksMap, toroOptimizeFromGraphEnd?odomPoses.rbegin()->first:odomPoses.begin()->first);
rtabmap::optimizeTOROGraph(depthGraph, odomPoses, _currentLinksMap, optimizedPoses, toroIterations, true, ignoreVariance);
_currentPosesMap = optimizedPoses;
_initProgressDialog->appendText(tr("Optimizing graph with new links... done!"));
}
@@ -3131,8 +3216,8 @@ void MainWindow::postProcessing()
_initProgressDialog->appendText(tr("Optimizing graph with updated links (%1 nodes, %2 constraints)...")
.arg(odomPoses.size()).arg(_currentLinksMap.size()));
std::map<int, rtabmap::Transform> optimizedPoses;
std::map<int, int> depthGraph = util3d::generateDepthGraph(_currentLinksMap, toroOptimizeFromGraphEnd?odomPoses.rbegin()->first:odomPoses.begin()->first);
util3d::optimizeTOROGraph(depthGraph, odomPoses, _currentLinksMap, optimizedPoses, toroIterations, true, ignoreVariance);
std::map<int, int> depthGraph = rtabmap::generateDepthGraph(_currentLinksMap, toroOptimizeFromGraphEnd?odomPoses.rbegin()->first:odomPoses.begin()->first);
rtabmap::optimizeTOROGraph(depthGraph, odomPoses, _currentLinksMap, optimizedPoses, toroIterations, true, ignoreVariance);
_initProgressDialog->appendText(tr("Optimizing graph with updated links... done!"));
_initProgressDialog->incrementStep();

View File

@@ -42,6 +42,14 @@ PostProcessingDialog::PostProcessingDialog(QWidget * parent) :
connect(_ui->refineNeighborLinks, SIGNAL(stateChanged(int)), this, SLOT(updateButtonBox()));
connect(_ui->refineLoopClosureLinks, SIGNAL(stateChanged(int)), this, SLOT(updateButtonBox()));
connect(_ui->buttonBox->button(QDialogButtonBox::RestoreDefaults), SIGNAL(clicked()), this, SLOT(restoreDefaults()));
connect(_ui->detectMoreLoopClosures, SIGNAL(clicked(bool)), this, SIGNAL(configChanged()));
connect(_ui->clusterRadius, SIGNAL(valueChanged(double)), this, SIGNAL(configChanged()));
connect(_ui->clusterAngle, SIGNAL(valueChanged(double)), this, SIGNAL(configChanged()));
connect(_ui->iterations, SIGNAL(valueChanged(int)), this, SIGNAL(configChanged()));
connect(_ui->reextractFeatures, SIGNAL(stateChanged(int)), this, SIGNAL(configChanged()));
connect(_ui->refineNeighborLinks, SIGNAL(stateChanged(int)), this, SIGNAL(configChanged()));
connect(_ui->refineLoopClosureLinks, SIGNAL(stateChanged(int)), this, SIGNAL(configChanged()));
}
PostProcessingDialog::~PostProcessingDialog()

View File

@@ -62,6 +62,9 @@ public:
void setRefineNeighborLinks(bool on);
void setRefineLoopClosureLinks(bool on);
signals:
void configChanged();
public slots:
void restoreDefaults();

View File

@@ -543,7 +543,6 @@ PreferencesDialog::PreferencesDialog(QWidget * parent) :
}
PreferencesDialog::~PreferencesDialog() {
this->saveWindowGeometry("PreferencesDialog", this);
delete _ui;
}
@@ -559,8 +558,6 @@ void PreferencesDialog::init()
this->readSettings();
this->writeSettings();// This will create the ini file if not exist
this->loadWindowGeometry("PreferencesDialog", this);
_initialized = true;
}
@@ -1638,229 +1635,250 @@ void PreferencesDialog::readSettingsEnd()
_progressDialog->setValue(2); // this will make closing...
}
void PreferencesDialog::saveWindowGeometry(const QString & windowName, const QWidget * window)
void PreferencesDialog::saveWindowGeometry(const QWidget * window)
{
QSettings settings(getIniFilePath(), QSettings::IniFormat);
settings.beginGroup("Gui");
settings.beginGroup(windowName);
settings.setValue("geometry", window->saveGeometry());
settings.endGroup(); // "windowName"
settings.endGroup(); // rtabmap
if(!window->objectName().isNull())
{
if(!window->isMaximized())
{
QSettings settings(getIniFilePath(), QSettings::IniFormat);
settings.beginGroup("Gui");
settings.beginGroup(window->objectName());
settings.setValue("geometry", window->saveGeometry());
settings.endGroup(); // "windowName"
settings.endGroup(); // rtabmap
}
}
}
void PreferencesDialog::loadWindowGeometry(const QString & windowName, QWidget * window)
void PreferencesDialog::loadWindowGeometry(QWidget * window)
{
QByteArray bytes;
QSettings settings(getIniFilePath(), QSettings::IniFormat);
settings.beginGroup("Gui");
settings.beginGroup(windowName);
bytes = settings.value("geometry", QByteArray()).toByteArray();
if(!bytes.isEmpty())
if(!window->objectName().isNull())
{
window->restoreGeometry(bytes);
QByteArray bytes;
QSettings settings(getIniFilePath(), QSettings::IniFormat);
settings.beginGroup("Gui");
settings.beginGroup(window->objectName());
bytes = settings.value("geometry", QByteArray()).toByteArray();
if(!bytes.isEmpty())
{
window->restoreGeometry(bytes);
}
settings.endGroup(); // "windowName"
settings.endGroup(); // rtabmap
}
settings.endGroup(); // "windowName"
settings.endGroup(); // rtabmap
}
void PreferencesDialog::saveMainWindowState(const QMainWindow * mainWindow)
{
QSettings settings(getIniFilePath(), QSettings::IniFormat);
settings.beginGroup("Gui");
settings.beginGroup("MainWindow");
settings.setValue("state", mainWindow->saveState());
settings.endGroup(); // "MainWindow"
settings.endGroup(); // rtabmap
if(!mainWindow->objectName().isNull())
{
saveWindowGeometry(mainWindow);
saveWindowGeometry("MainWindow", mainWindow);
QSettings settings(getIniFilePath(), QSettings::IniFormat);
settings.beginGroup("Gui");
settings.beginGroup(mainWindow->objectName());
settings.setValue("state", mainWindow->saveState());
settings.endGroup(); // "MainWindow"
settings.endGroup(); // rtabmap
}
}
void PreferencesDialog::loadMainWindowState(QMainWindow * mainWindow)
{
QByteArray bytes;
QSettings settings(getIniFilePath(), QSettings::IniFormat);
settings.beginGroup("Gui");
settings.beginGroup("MainWindow");
bytes = settings.value("state", QByteArray()).toByteArray();
if(!bytes.isEmpty())
if(!mainWindow->objectName().isNull())
{
mainWindow->restoreState(bytes);
}
settings.endGroup(); // "MainWindow"
settings.endGroup(); // rtabmap
loadWindowGeometry(mainWindow);
loadWindowGeometry("MainWindow", mainWindow);
QByteArray bytes;
QSettings settings(getIniFilePath(), QSettings::IniFormat);
settings.beginGroup("Gui");
settings.beginGroup(mainWindow->objectName());
bytes = settings.value("state", QByteArray()).toByteArray();
if(!bytes.isEmpty())
{
mainWindow->restoreState(bytes);
}
settings.endGroup(); // "MainWindow"
settings.endGroup(); // rtabmap
}
}
void PreferencesDialog::saveWidgetState(const QString & name, const QWidget * widget)
void PreferencesDialog::saveWidgetState(const QWidget * widget)
{
QSettings settings(getIniFilePath(), QSettings::IniFormat);
settings.beginGroup("Gui");
settings.beginGroup(name);
const CloudViewer * cloudViewer = qobject_cast<const CloudViewer*>(widget);
const ImageView * imageView = qobject_cast<const ImageView*>(widget);
const ExportCloudsDialog * exportCloudsDialog = qobject_cast<const ExportCloudsDialog*>(widget);
const PostProcessingDialog * postProcessingDialog = qobject_cast<const PostProcessingDialog *>(widget);
if(cloudViewer)
if(!widget->objectName().isNull())
{
float poseX, poseY, poseZ, focalX, focalY, focalZ, upX, upY, upZ;
cloudViewer->getCameraPosition(poseX, poseY, poseZ, focalX, focalY, focalZ, upX, upY, upZ);
QVector3D pose(poseX, poseY, poseZ);
QVector3D focal(focalX, focalY, focalZ);
if(!cloudViewer->isCameraFree())
QSettings settings(getIniFilePath(), QSettings::IniFormat);
settings.beginGroup("Gui");
settings.beginGroup(widget->objectName());
const CloudViewer * cloudViewer = qobject_cast<const CloudViewer*>(widget);
const ImageView * imageView = qobject_cast<const ImageView*>(widget);
const ExportCloudsDialog * exportCloudsDialog = qobject_cast<const ExportCloudsDialog*>(widget);
const PostProcessingDialog * postProcessingDialog = qobject_cast<const PostProcessingDialog *>(widget);
if(cloudViewer)
{
// make camera position relative to target
Transform T = cloudViewer->getTargetPose();
if(cloudViewer->isCameraTargetLocked())
float poseX, poseY, poseZ, focalX, focalY, focalZ, upX, upY, upZ;
cloudViewer->getCameraPosition(poseX, poseY, poseZ, focalX, focalY, focalZ, upX, upY, upZ);
QVector3D pose(poseX, poseY, poseZ);
QVector3D focal(focalX, focalY, focalZ);
if(!cloudViewer->isCameraFree())
{
T = Transform(T.x(), T.y(), T.z(), 0,0,0);
// make camera position relative to target
Transform T = cloudViewer->getTargetPose();
if(cloudViewer->isCameraTargetLocked())
{
T = Transform(T.x(), T.y(), T.z(), 0,0,0);
}
Transform F(focalX, focalY, focalZ, 0,0,0);
Transform P(poseX, poseY, poseZ, 0,0,0);
Transform newFocal = T.inverse() * F;
Transform newPose = newFocal * F.inverse() * P;
pose = QVector3D(newPose.x(), newPose.y(), newPose.z());
focal = QVector3D(newFocal.x(), newFocal.y(), newFocal.z());
}
Transform F(focalX, focalY, focalZ, 0,0,0);
Transform P(poseX, poseY, poseZ, 0,0,0);
Transform newFocal = T.inverse() * F;
Transform newPose = newFocal * F.inverse() * P;
pose = QVector3D(newPose.x(), newPose.y(), newPose.z());
focal = QVector3D(newFocal.x(), newFocal.y(), newFocal.z());
settings.setValue("camera_pose", pose);
settings.setValue("camera_focal", focal);
settings.setValue("camera_up", QVector3D(upX, upY, upZ));
settings.setValue("grid", cloudViewer->isGridShown());
settings.setValue("grid_cell_count", cloudViewer->getGridCellCount());
settings.setValue("grid_cell_size", cloudViewer->getGridCellSize());
settings.setValue("trajectory_shown", cloudViewer->isTrajectoryShown());
settings.setValue("trajectory_size", cloudViewer->getTrajectorySize());
settings.setValue("camera_target_locked", cloudViewer->isCameraTargetLocked());
settings.setValue("camera_target_follow", cloudViewer->isCameraTargetFollow());
settings.setValue("camera_free", cloudViewer->isCameraFree());
settings.setValue("camera_lockZ", cloudViewer->isCameraLockZ());
settings.setValue("bg_color", cloudViewer->getBackgroundColor());
}
else if(imageView)
{
settings.setValue("image_shown", imageView->isImageShown());
settings.setValue("depth_shown", imageView->isImageDepthShown());
settings.setValue("features_shown", imageView->isFeaturesShown());
settings.setValue("lines_shown", imageView->isLinesShown());
}
else if(exportCloudsDialog)
{
settings.setValue("assemble", exportCloudsDialog->getAssemble());
settings.setValue("assemble_voxel", exportCloudsDialog->getAssembleVoxel());
settings.setValue("regenerate", exportCloudsDialog->getGenerate());
settings.setValue("regenerate_decimation", exportCloudsDialog->getGenerateDecimation());
settings.setValue("regenerate_voxel", exportCloudsDialog->getGenerateVoxel());
settings.setValue("regenerate_max_depth", exportCloudsDialog->getGenerateMaxDepth());
settings.setValue("binary", exportCloudsDialog->getBinaryFile());
settings.setValue("mls", exportCloudsDialog->getMLS());
settings.setValue("mls_radius", exportCloudsDialog->getMLSRadius());
settings.setValue("mesh", exportCloudsDialog->getMesh());
settings.setValue("mesh_k", exportCloudsDialog->getMeshNormalKSearch());
settings.setValue("mesh_radius", exportCloudsDialog->getMeshGp3Radius());
}
else if(postProcessingDialog)
{
settings.setValue("detect_more_lc", postProcessingDialog->isDetectMoreLoopClosures());
settings.setValue("cluster_radius", postProcessingDialog->clusterRadius());
settings.setValue("cluster_angle", postProcessingDialog->clusterAngle());
settings.setValue("iterations", postProcessingDialog->iterations());
settings.setValue("reextract_features", postProcessingDialog->isReextractFeatures());
settings.setValue("refine_neigbors", postProcessingDialog->isRefineNeighborLinks());
settings.setValue("refine_lc", postProcessingDialog->isRefineLoopClosureLinks());
}
else
{
UERROR("Widget \"%s\" cannot be exported in config file.", widget->objectName().toStdString().c_str());
}
settings.setValue("camera_pose", pose);
settings.setValue("camera_focal", focal);
settings.setValue("camera_up", QVector3D(upX, upY, upZ));
settings.setValue("grid", cloudViewer->isGridShown());
settings.setValue("grid_cell_count", cloudViewer->getGridCellCount());
settings.setValue("grid_cell_size", cloudViewer->getGridCellSize());
settings.setValue("trajectory_shown", cloudViewer->isTrajectoryShown());
settings.setValue("trajectory_size", cloudViewer->getTrajectorySize());
settings.setValue("camera_target_locked", cloudViewer->isCameraTargetLocked());
settings.setValue("camera_target_follow", cloudViewer->isCameraTargetFollow());
settings.setValue("camera_free", cloudViewer->isCameraFree());
settings.setValue("camera_lockZ", cloudViewer->isCameraLockZ());
settings.setValue("bg_color", cloudViewer->getBackgroundColor());
settings.endGroup(); // "name"
settings.endGroup(); // Gui
}
else if(imageView)
{
settings.setValue("image_shown", imageView->isImageShown());
settings.setValue("depth_shown", imageView->isImageDepthShown());
settings.setValue("features_shown", imageView->isFeaturesShown());
settings.setValue("lines_shown", imageView->isLinesShown());
}
else if(exportCloudsDialog)
{
settings.setValue("assemble", exportCloudsDialog->getAssemble());
settings.setValue("assemble_voxel", exportCloudsDialog->getAssembleVoxel());
settings.setValue("regenerate", exportCloudsDialog->getGenerate());
settings.setValue("regenerate_decimation", exportCloudsDialog->getGenerateDecimation());
settings.setValue("regenerate_voxel", exportCloudsDialog->getGenerateVoxel());
settings.setValue("regenerate_max_depth", exportCloudsDialog->getGenerateMaxDepth());
settings.setValue("binary", exportCloudsDialog->getBinaryFile());
settings.setValue("mls", exportCloudsDialog->getMLS());
settings.setValue("mls_radius", exportCloudsDialog->getMLSRadius());
settings.setValue("mesh", exportCloudsDialog->getMesh());
settings.setValue("mesh_k", exportCloudsDialog->getMeshNormalKSearch());
settings.setValue("mesh_radius", exportCloudsDialog->getMeshGp3Radius());
}
else if(postProcessingDialog)
{
settings.setValue("detect_more_lc", postProcessingDialog->isDetectMoreLoopClosures());
settings.setValue("cluster_radius", postProcessingDialog->clusterRadius());
settings.setValue("cluster_angle", postProcessingDialog->clusterAngle());
settings.setValue("iterations", postProcessingDialog->iterations());
settings.setValue("reextract_features", postProcessingDialog->isReextractFeatures());
settings.setValue("refine_neigbors", postProcessingDialog->isRefineNeighborLinks());
settings.setValue("refine_lc", postProcessingDialog->isRefineLoopClosureLinks());
}
else
{
UERROR("Widget \"%s\" cannot be exported in config file.", widget->objectName().toStdString().c_str());
}
settings.endGroup(); // "name"
settings.endGroup(); // Gui
}
void PreferencesDialog::loadWidgetState(const QString & name, QWidget * widget)
void PreferencesDialog::loadWidgetState(QWidget * widget)
{
QByteArray bytes;
QSettings settings(getIniFilePath(), QSettings::IniFormat);
settings.beginGroup("Gui");
settings.beginGroup(name);
CloudViewer * cloudViewer = qobject_cast<CloudViewer*>(widget);
ImageView * imageView = qobject_cast<ImageView*>(widget);
ExportCloudsDialog * exportCloudsDialog = qobject_cast<ExportCloudsDialog*>(widget);
PostProcessingDialog * postProcessingDialog = qobject_cast<PostProcessingDialog *>(widget);
if(cloudViewer)
if(!widget->objectName().isNull())
{
float poseX, poseY, poseZ, focalX, focalY, focalZ, upX, upY, upZ;
cloudViewer->getCameraPosition(poseX, poseY, poseZ, focalX, focalY, focalZ, upX, upY, upZ);
QVector3D pose(poseX, poseY, poseZ), focal(focalX, focalY, focalZ), up(upX, upY, upZ);
pose = settings.value("camera_pose", pose).value<QVector3D>();
focal = settings.value("camera_focal", focal).value<QVector3D>();
up = settings.value("camera_up", up).value<QVector3D>();
cloudViewer->setCameraPosition(pose.x(),pose.y(),pose.z(), focal.x(),focal.y(),focal.z(), up.x(),up.y(),up.z());
QByteArray bytes;
QSettings settings(getIniFilePath(), QSettings::IniFormat);
settings.beginGroup("Gui");
settings.beginGroup(widget->objectName());
cloudViewer->setGridShown(settings.value("grid", cloudViewer->isGridShown()).toBool());
cloudViewer->setGridCellCount(settings.value("grid_cell_count", cloudViewer->getGridCellCount()).toUInt());
cloudViewer->setGridCellSize(settings.value("grid_cell_size", cloudViewer->getGridCellSize()).toFloat());
CloudViewer * cloudViewer = qobject_cast<CloudViewer*>(widget);
ImageView * imageView = qobject_cast<ImageView*>(widget);
ExportCloudsDialog * exportCloudsDialog = qobject_cast<ExportCloudsDialog*>(widget);
PostProcessingDialog * postProcessingDialog = qobject_cast<PostProcessingDialog *>(widget);
cloudViewer->setTrajectoryShown(settings.value("trajectory_shown", cloudViewer->isTrajectoryShown()).toBool());
cloudViewer->setTrajectorySize(settings.value("trajectory_size", cloudViewer->getTrajectorySize()).toUInt());
cloudViewer->setCameraTargetLocked(settings.value("camera_target_locked", cloudViewer->isCameraTargetLocked()).toBool());
cloudViewer->setCameraTargetFollow(settings.value("camera_target_follow", cloudViewer->isCameraTargetFollow()).toBool());
if(settings.value("camera_free", cloudViewer->isCameraFree()).toBool())
if(cloudViewer)
{
cloudViewer->setCameraFree();
float poseX, poseY, poseZ, focalX, focalY, focalZ, upX, upY, upZ;
cloudViewer->getCameraPosition(poseX, poseY, poseZ, focalX, focalY, focalZ, upX, upY, upZ);
QVector3D pose(poseX, poseY, poseZ), focal(focalX, focalY, focalZ), up(upX, upY, upZ);
pose = settings.value("camera_pose", pose).value<QVector3D>();
focal = settings.value("camera_focal", focal).value<QVector3D>();
up = settings.value("camera_up", up).value<QVector3D>();
cloudViewer->setCameraPosition(pose.x(),pose.y(),pose.z(), focal.x(),focal.y(),focal.z(), up.x(),up.y(),up.z());
cloudViewer->setGridShown(settings.value("grid", cloudViewer->isGridShown()).toBool());
cloudViewer->setGridCellCount(settings.value("grid_cell_count", cloudViewer->getGridCellCount()).toUInt());
cloudViewer->setGridCellSize(settings.value("grid_cell_size", cloudViewer->getGridCellSize()).toFloat());
cloudViewer->setTrajectoryShown(settings.value("trajectory_shown", cloudViewer->isTrajectoryShown()).toBool());
cloudViewer->setTrajectorySize(settings.value("trajectory_size", cloudViewer->getTrajectorySize()).toUInt());
cloudViewer->setCameraTargetLocked(settings.value("camera_target_locked", cloudViewer->isCameraTargetLocked()).toBool());
cloudViewer->setCameraTargetFollow(settings.value("camera_target_follow", cloudViewer->isCameraTargetFollow()).toBool());
if(settings.value("camera_free", cloudViewer->isCameraFree()).toBool())
{
cloudViewer->setCameraFree();
}
cloudViewer->setCameraLockZ(settings.value("camera_lockZ", cloudViewer->isCameraLockZ()).toBool());
cloudViewer->setBackgroundColor(settings.value("bg_color", cloudViewer->getBackgroundColor()).value<QColor>());
}
else if(imageView)
{
imageView->setImageShown(settings.value("image_shown", imageView->isImageShown()).toBool());
imageView->setImageDepthShown(settings.value("depth_shown", imageView->isImageDepthShown()).toBool());
imageView->setFeaturesShown(settings.value("features_shown", imageView->isFeaturesShown()).toBool());
imageView->setLinesShown(settings.value("lines_shown", imageView->isLinesShown()).toBool());
}
else if(exportCloudsDialog)
{
exportCloudsDialog->setAssemble(settings.value("assemble", exportCloudsDialog->getAssemble()).toBool());
exportCloudsDialog->setAssembleVoxel(settings.value("assemble_voxel", exportCloudsDialog->getAssembleVoxel()).toDouble());
exportCloudsDialog->setGenerate(settings.value("regenerate", exportCloudsDialog->getGenerate()).toBool());
exportCloudsDialog->setGenerateDecimation(settings.value("regenerate_decimation", exportCloudsDialog->getGenerateDecimation()).toInt());
exportCloudsDialog->setGenerateVoxel(settings.value("regenerate_voxel", exportCloudsDialog->getGenerateVoxel()).toDouble());
exportCloudsDialog->setGenerateMaxDepth(settings.value("regenerate_max_depth", exportCloudsDialog->getGenerateMaxDepth()).toDouble());
exportCloudsDialog->setBinaryFile(settings.value("binary", exportCloudsDialog->getBinaryFile()).toBool());
exportCloudsDialog->setMLS(settings.value("mls", exportCloudsDialog->getMLS()).toBool());
exportCloudsDialog->setMLSRadius(settings.value("mls_radius", exportCloudsDialog->getMLSRadius()).toDouble());
exportCloudsDialog->setMesh(settings.value("mesh", exportCloudsDialog->getMesh()).toBool());
exportCloudsDialog->setMeshNormalKSearch(settings.value("mesh_k", exportCloudsDialog->getMeshNormalKSearch()).toInt());
exportCloudsDialog->setMeshGp3Radius(settings.value("mesh_radius", exportCloudsDialog->getMeshGp3Radius()).toDouble());
}
else if(postProcessingDialog)
{
postProcessingDialog->setDetectMoreLoopClosures(settings.value("detect_more_lc", postProcessingDialog->isDetectMoreLoopClosures()).toBool());
postProcessingDialog->setClusterRadius(settings.value("cluster_radius", postProcessingDialog->clusterRadius()).toDouble());
postProcessingDialog->setClusterAngle(settings.value("cluster_angle", postProcessingDialog->clusterAngle()).toDouble());
postProcessingDialog->setIterations(settings.value("iterations", postProcessingDialog->iterations()).toInt());
postProcessingDialog->setReextractFeatures(settings.value("reextract_features", postProcessingDialog->isReextractFeatures()).toBool());
postProcessingDialog->setRefineNeighborLinks(settings.value("refine_neigbors", postProcessingDialog->isRefineNeighborLinks()).toBool());
postProcessingDialog->setRefineLoopClosureLinks(settings.value("refine_lc", postProcessingDialog->isRefineLoopClosureLinks()).toBool());
}
else
{
UERROR("Widget \"%s\" cannot be loaded from config file.", widget->objectName().toStdString().c_str());
}
cloudViewer->setCameraLockZ(settings.value("camera_lockZ", cloudViewer->isCameraLockZ()).toBool());
cloudViewer->setBackgroundColor(settings.value("bg_color", cloudViewer->getBackgroundColor()).value<QColor>());
settings.endGroup(); //"name"
settings.endGroup(); // Gui
}
else if(imageView)
{
imageView->setImageShown(settings.value("image_shown", imageView->isImageShown()).toBool());
imageView->setImageDepthShown(settings.value("depth_shown", imageView->isImageDepthShown()).toBool());
imageView->setFeaturesShown(settings.value("features_shown", imageView->isFeaturesShown()).toBool());
imageView->setLinesShown(settings.value("lines_shown", imageView->isLinesShown()).toBool());
}
else if(exportCloudsDialog)
{
exportCloudsDialog->setAssemble(settings.value("assemble", exportCloudsDialog->getAssemble()).toBool());
exportCloudsDialog->setAssembleVoxel(settings.value("assemble_voxel", exportCloudsDialog->getAssembleVoxel()).toDouble());
exportCloudsDialog->setGenerate(settings.value("regenerate", exportCloudsDialog->getGenerate()).toBool());
exportCloudsDialog->setGenerateDecimation(settings.value("regenerate_decimation", exportCloudsDialog->getGenerateDecimation()).toInt());
exportCloudsDialog->setGenerateVoxel(settings.value("regenerate_voxel", exportCloudsDialog->getGenerateVoxel()).toDouble());
exportCloudsDialog->setGenerateMaxDepth(settings.value("regenerate_max_depth", exportCloudsDialog->getGenerateMaxDepth()).toDouble());
exportCloudsDialog->setBinaryFile(settings.value("binary", exportCloudsDialog->getBinaryFile()).toBool());
exportCloudsDialog->setMLS(settings.value("mls", exportCloudsDialog->getMLS()).toBool());
exportCloudsDialog->setMLSRadius(settings.value("mls_radius", exportCloudsDialog->getMLSRadius()).toDouble());
exportCloudsDialog->setMesh(settings.value("mesh", exportCloudsDialog->getMesh()).toBool());
exportCloudsDialog->setMeshNormalKSearch(settings.value("mesh_k", exportCloudsDialog->getMeshNormalKSearch()).toInt());
exportCloudsDialog->setMeshGp3Radius(settings.value("mesh_radius", exportCloudsDialog->getMeshGp3Radius()).toDouble());
}
else if(postProcessingDialog)
{
postProcessingDialog->setDetectMoreLoopClosures(settings.value("detect_more_lc", postProcessingDialog->isDetectMoreLoopClosures()).toBool());
postProcessingDialog->setClusterRadius(settings.value("cluster_radius", postProcessingDialog->clusterRadius()).toDouble());
postProcessingDialog->setClusterAngle(settings.value("cluster_angle", postProcessingDialog->clusterAngle()).toDouble());
postProcessingDialog->setIterations(settings.value("iterations", postProcessingDialog->iterations()).toInt());
postProcessingDialog->setReextractFeatures(settings.value("reextract_features", postProcessingDialog->isReextractFeatures()).toBool());
postProcessingDialog->setRefineNeighborLinks(settings.value("refine_neigbors", postProcessingDialog->isRefineNeighborLinks()).toBool());
postProcessingDialog->setRefineLoopClosureLinks(settings.value("refine_lc", postProcessingDialog->isRefineLoopClosureLinks()).toBool());
}
else
{
UERROR("Widget \"%s\" cannot be loaded from config file.", widget->objectName().toStdString().c_str());
}
settings.endGroup(); //"name"
settings.endGroup(); // Gui
}

View File

@@ -15,18 +15,42 @@
</property>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2" stretch="1,0">
<layout class="QHBoxLayout" name="horizontalLayout_3" stretch="1,0">
<item>
<layout class="QVBoxLayout" name="verticalLayout_2" stretch="1,0">
<item>
<widget class="UImageView" name="image_view" native="true"/>
</item>
<item>
<widget class="QCheckBox" name="checkBox_rectified">
<property name="text">
<string>Show rectified</string>
</property>
</widget>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QCheckBox" name="checkBox_rectified">
<property name="text">
<string>Show rectified</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkBox_mirror">
<property name="text">
<string>Mirror</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>
</layout>
</item>
@@ -88,7 +112,7 @@
<item row="2" column="1">
<widget class="QDoubleSpinBox" name="doubleSpinBox_squareSize">
<property name="decimals">
<number>3</number>
<number>4</number>
</property>
<property name="maximum">
<double>1.000000000000000</double>

View File

@@ -178,6 +178,7 @@
<addaction name="action360p"/>
<addaction name="action240p"/>
</widget>
<addaction name="actionSave_GUI_config"/>
<addaction name="menuShow_view"/>
<addaction name="menuFigures"/>
<addaction name="actionScreenshot"/>
@@ -1116,6 +1117,11 @@
<string>Post-processing...</string>
</property>
</action>
<action name="actionSave_GUI_config">
<property name="text">
<string>Save GUI config</string>
</property>
</action>
</widget>
<customwidgets>
<customwidget>