mirror of
https://github.com/introlab/rtabmap_ros.git
synced 2026-10-03 16:27:46 +08:00
GUI: custom aspect ratio, option to save auto screenshots in RAM, default views updated (reseting 3D map camera position and hiding the status bar)
This commit is contained in:
@@ -196,6 +196,7 @@ public:
|
||||
void setTrajectoryShown(bool shown);
|
||||
void setTrajectorySize(unsigned int value);
|
||||
void clearTrajectory();
|
||||
void resetCamera();
|
||||
|
||||
void removeAllClouds(); //including meshes
|
||||
bool removeCloud(const std::string & id); //including mesh
|
||||
|
||||
@@ -180,6 +180,7 @@ private slots:
|
||||
void setAspectRatio480p();
|
||||
void setAspectRatio720p();
|
||||
void setAspectRatio1080p();
|
||||
void setAspectRatioCustom();
|
||||
void exportGridMap();
|
||||
void exportScans();
|
||||
void exportClouds();
|
||||
@@ -227,7 +228,7 @@ private:
|
||||
void saveFigures();
|
||||
void loadFigures();
|
||||
void exportPoses(int format);
|
||||
QString captureScreen();
|
||||
QString captureScreen(bool cacheInRAM = false);
|
||||
|
||||
std::map<int, pcl::PointCloud<pcl::PointXYZRGB>::Ptr > getClouds(
|
||||
const std::map<int, Transform> & poses,
|
||||
@@ -304,6 +305,8 @@ private:
|
||||
QString _graphSavingFileName;
|
||||
QMap<int, QString> _exportPosesFileName;
|
||||
bool _autoScreenCaptureOdomSync;
|
||||
bool _autoScreenCaptureRAM;
|
||||
QMap<QString, QByteArray> _autoScreenCaptureCachedImages;
|
||||
|
||||
QVector<int> _refIds;
|
||||
QVector<int> _loopClosureIds;
|
||||
|
||||
@@ -117,7 +117,7 @@ public:
|
||||
void saveWindowGeometry(const QWidget * window);
|
||||
void loadWindowGeometry(QWidget * window);
|
||||
void saveMainWindowState(const QMainWindow * mainWindow);
|
||||
void loadMainWindowState(QMainWindow * mainWindow, bool & maximized);
|
||||
void loadMainWindowState(QMainWindow * mainWindow, bool & maximized, bool & statusBarShown);
|
||||
void saveWidgetState(const QWidget * widget);
|
||||
void loadWidgetState(QWidget * widget);
|
||||
|
||||
|
||||
+32
-27
@@ -889,6 +889,37 @@ void CloudViewer::clearTrajectory()
|
||||
this->update();
|
||||
}
|
||||
|
||||
void CloudViewer::resetCamera()
|
||||
{
|
||||
_lastCameraOrientation= _lastCameraPose = cv::Vec3f(0,0,0);
|
||||
if((_aFollowCamera->isChecked() || _aLockCamera->isChecked()) && !_lastPose.isNull())
|
||||
{
|
||||
// reset relative to last current pose
|
||||
if(_aLockViewZ->isChecked())
|
||||
{
|
||||
_visualizer->setCameraPosition(
|
||||
_lastPose.x()-1, _lastPose.y(), _lastPose.z(),
|
||||
_lastPose.x(), _lastPose.y(), _lastPose.z(),
|
||||
0, 0, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
_visualizer->setCameraPosition(
|
||||
_lastPose.x()-1, _lastPose.y(), _lastPose.z(),
|
||||
_lastPose.x(), _lastPose.y(), _lastPose.z(),
|
||||
_lastPose.r31(), _lastPose.r32(), _lastPose.r33());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_visualizer->setCameraPosition(
|
||||
-1, 0, 0,
|
||||
0, 0, 0,
|
||||
0, 0, 1);
|
||||
}
|
||||
this->update();
|
||||
}
|
||||
|
||||
void CloudViewer::removeAllClouds()
|
||||
{
|
||||
_addedClouds.clear();
|
||||
@@ -1506,33 +1537,7 @@ void CloudViewer::handleAction(QAction * a)
|
||||
}
|
||||
else if(a == _aResetCamera)
|
||||
{
|
||||
_lastCameraOrientation= _lastCameraPose = cv::Vec3f(0,0,0);
|
||||
if((_aFollowCamera->isChecked() || _aLockCamera->isChecked()) && !_lastPose.isNull())
|
||||
{
|
||||
// reset relative to last current pose
|
||||
if(_aLockViewZ->isChecked())
|
||||
{
|
||||
_visualizer->setCameraPosition(
|
||||
_lastPose.x()-1, _lastPose.y(), _lastPose.z(),
|
||||
_lastPose.x(), _lastPose.y(), _lastPose.z(),
|
||||
0, 0, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
_visualizer->setCameraPosition(
|
||||
_lastPose.x()-1, _lastPose.y(), _lastPose.z(),
|
||||
_lastPose.x(), _lastPose.y(), _lastPose.z(),
|
||||
_lastPose.r31(), _lastPose.r32(), _lastPose.r33());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_visualizer->setCameraPosition(
|
||||
-1, 0, 0,
|
||||
0, 0, 0,
|
||||
0, 0, 1);
|
||||
}
|
||||
this->update();
|
||||
this->resetCamera();
|
||||
}
|
||||
else if(a == _aShowGrid)
|
||||
{
|
||||
|
||||
+104
-33
@@ -145,6 +145,7 @@ MainWindow::MainWindow(PreferencesDialog * prefDialog, QWidget * parent) :
|
||||
_likelihoodCurve(0),
|
||||
_rawLikelihoodCurve(0),
|
||||
_autoScreenCaptureOdomSync(false),
|
||||
_autoScreenCaptureRAM(false),
|
||||
_firstCall(true)
|
||||
{
|
||||
UDEBUG("");
|
||||
@@ -174,20 +175,7 @@ MainWindow::MainWindow(PreferencesDialog * prefDialog, QWidget * parent) :
|
||||
this->setObjectName("MainWindow");
|
||||
|
||||
//Setup dock widgets position if it is the first time the application is started.
|
||||
//if(!QFile::exists(PreferencesDialog::getIniFilePath()))
|
||||
{
|
||||
_ui->dockWidget_posterior->setVisible(false);
|
||||
_ui->dockWidget_likelihood->setVisible(false);
|
||||
_ui->dockWidget_rawlikelihood->setVisible(false);
|
||||
_ui->dockWidget_statsV2->setVisible(false);
|
||||
_ui->dockWidget_console->setVisible(false);
|
||||
_ui->dockWidget_loopClosureViewer->setVisible(false);
|
||||
_ui->dockWidget_mapVisibility->setVisible(false);
|
||||
_ui->dockWidget_graphViewer->setVisible(false);
|
||||
//_ui->dockWidget_odometry->setVisible(false);
|
||||
//_ui->dockWidget_cloudViewer->setVisible(false);
|
||||
//_ui->dockWidget_imageView->setVisible(false);
|
||||
}
|
||||
setDefaultViews();
|
||||
|
||||
_ui->widget_mainWindow->setVisible(false);
|
||||
|
||||
@@ -204,7 +192,8 @@ MainWindow::MainWindow(PreferencesDialog * prefDialog, QWidget * parent) :
|
||||
_preferencesDialog->init();
|
||||
|
||||
// Restore window geometry
|
||||
_preferencesDialog->loadMainWindowState(this, _savedMaximized);
|
||||
bool statusBarShown = false;
|
||||
_preferencesDialog->loadMainWindowState(this, _savedMaximized, statusBarShown);
|
||||
_preferencesDialog->loadWindowGeometry(_preferencesDialog);
|
||||
_preferencesDialog->loadWindowGeometry(_exportDialog);
|
||||
_preferencesDialog->loadWindowGeometry(_postProcessingDialog);
|
||||
@@ -285,6 +274,10 @@ MainWindow::MainWindow(PreferencesDialog * prefDialog, QWidget * parent) :
|
||||
QAction * a = _ui->menuShow_view->addAction("Progress dialog");
|
||||
a->setCheckable(false);
|
||||
connect(a, SIGNAL(triggered(bool)), _initProgressDialog, SLOT(show()));
|
||||
QAction * statusBarAction = _ui->menuShow_view->addAction("Status bar");
|
||||
statusBarAction->setCheckable(true);
|
||||
statusBarAction->setChecked(statusBarShown);
|
||||
connect(statusBarAction, SIGNAL(toggled(bool)), this->statusBar(), SLOT(setVisible(bool)));
|
||||
|
||||
// connect actions with custom slots
|
||||
connect(_ui->actionSave_GUI_config, SIGNAL(triggered()), this, SLOT(saveConfigGUI()));
|
||||
@@ -325,6 +318,7 @@ MainWindow::MainWindow(PreferencesDialog * prefDialog, QWidget * parent) :
|
||||
connect(_ui->action480p, SIGNAL(triggered()), this, SLOT(setAspectRatio480p()));
|
||||
connect(_ui->action720p, SIGNAL(triggered()), this, SLOT(setAspectRatio720p()));
|
||||
connect(_ui->action1080p, SIGNAL(triggered()), this, SLOT(setAspectRatio1080p()));
|
||||
connect(_ui->actionCustom, SIGNAL(triggered()), this, SLOT(setAspectRatioCustom()));
|
||||
connect(_ui->actionSave_point_cloud, SIGNAL(triggered()), this, SLOT(exportClouds()));
|
||||
connect(_ui->actionExport_2D_scans_ply_pcd, SIGNAL(triggered()), this, SLOT(exportScans()));
|
||||
connect(_ui->actionExport_2D_Grid_map_bmp_png, SIGNAL(triggered()), this, SLOT(exportGridMap()));
|
||||
@@ -416,6 +410,7 @@ MainWindow::MainWindow(PreferencesDialog * prefDialog, QWidget * parent) :
|
||||
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()));
|
||||
connect(statusBarAction, SIGNAL(toggled(bool)), this, SLOT(configGUIModified()));
|
||||
QList<QDockWidget*> dockWidgets = this->findChildren<QDockWidget*>();
|
||||
for(int i=0; i<dockWidgets.size(); ++i)
|
||||
{
|
||||
@@ -946,7 +941,7 @@ void MainWindow::processOdometry(const rtabmap::OdometryEvent & odom)
|
||||
|
||||
if(_ui->actionAuto_screen_capture->isChecked() && _autoScreenCaptureOdomSync)
|
||||
{
|
||||
this->captureScreen();
|
||||
this->captureScreen(_autoScreenCaptureRAM);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1330,7 +1325,7 @@ void MainWindow::processStats(const rtabmap::Statistics & stat)
|
||||
_ui->statsToolBox->updateStat("/Gui refresh stats/ms", stat.refImageId(), elapsedTime);
|
||||
if(_ui->actionAuto_screen_capture->isChecked() && !_autoScreenCaptureOdomSync)
|
||||
{
|
||||
this->captureScreen();
|
||||
this->captureScreen(_autoScreenCaptureRAM);
|
||||
}
|
||||
|
||||
if(!_preferencesDialog->isImagesKept())
|
||||
@@ -2562,26 +2557,41 @@ void MainWindow::changeMappingMode()
|
||||
emit mappingModeChanged(_ui->actionSLAM_mode->isChecked());
|
||||
}
|
||||
|
||||
QString MainWindow::captureScreen()
|
||||
QString MainWindow::captureScreen(bool cacheInRAM)
|
||||
{
|
||||
QString targetDir = _preferencesDialog->getWorkingDirectory() + QDir::separator() + "ScreensCaptured";
|
||||
QDir dir;
|
||||
if(!dir.exists(targetDir))
|
||||
{
|
||||
dir.mkdir(targetDir);
|
||||
}
|
||||
targetDir += QDir::separator();
|
||||
targetDir += "Main_window";
|
||||
if(!dir.exists(targetDir))
|
||||
{
|
||||
dir.mkdir(targetDir);
|
||||
}
|
||||
targetDir += QDir::separator();
|
||||
QString name = (QDateTime::currentDateTime().toString("yyMMddhhmmsszzz") + ".png");
|
||||
_ui->statusbar->clearMessage();
|
||||
QPixmap figure = QPixmap::grabWidget(this);
|
||||
figure.save(targetDir + name);
|
||||
QString msg = tr("Screen captured \"%1\"").arg(targetDir + name);
|
||||
|
||||
QString targetDir = _preferencesDialog->getWorkingDirectory() + QDir::separator() + "ScreensCaptured";
|
||||
QString msg;
|
||||
if(cacheInRAM)
|
||||
{
|
||||
msg = tr("Screen captured \"%1\"").arg(name);
|
||||
QByteArray bytes;
|
||||
QBuffer buffer(&bytes);
|
||||
buffer.open(QIODevice::WriteOnly);
|
||||
figure.save(&buffer, "PNG");
|
||||
_autoScreenCaptureCachedImages.insert(name, bytes);
|
||||
}
|
||||
else
|
||||
{
|
||||
QDir dir;
|
||||
if(!dir.exists(targetDir))
|
||||
{
|
||||
dir.mkdir(targetDir);
|
||||
}
|
||||
targetDir += QDir::separator();
|
||||
targetDir += "Main_window";
|
||||
if(!dir.exists(targetDir))
|
||||
{
|
||||
dir.mkdir(targetDir);
|
||||
}
|
||||
targetDir += QDir::separator();
|
||||
|
||||
figure.save(targetDir + name);
|
||||
msg = tr("Screen captured \"%1\"").arg(targetDir + name);
|
||||
}
|
||||
_ui->statusbar->showMessage(msg, _preferencesDialog->getTimeLimit()*500);
|
||||
_ui->widget_console->appendMsg(msg);
|
||||
|
||||
@@ -4131,6 +4141,9 @@ void MainWindow::setDefaultViews()
|
||||
_ui->dockWidget_imageView->setVisible(true);
|
||||
_ui->toolBar->setVisible(_state != kMonitoring && _state != kMonitoringPaused);
|
||||
_ui->toolBar_2->setVisible(true);
|
||||
_ui->statusbar->setVisible(false);
|
||||
this->setAspectRatio720p();
|
||||
_ui->widget_cloudViewer->resetCamera();
|
||||
}
|
||||
|
||||
void MainWindow::selectScreenCaptureFormat(bool checked)
|
||||
@@ -4151,12 +4164,56 @@ void MainWindow::selectScreenCaptureFormat(bool checked)
|
||||
{
|
||||
_autoScreenCaptureOdomSync = true;
|
||||
}
|
||||
|
||||
if(_state != kMonitoring && _state != kMonitoringPaused)
|
||||
{
|
||||
int r = QMessageBox::question(this, tr("Hard drive or RAM?"), tr("Save in RAM? Images will be saved on disk when clicking auto screen capture again."), QMessageBox::Yes | QMessageBox::No, QMessageBox::No);
|
||||
if(r == QMessageBox::No || r == QMessageBox::Yes)
|
||||
{
|
||||
_autoScreenCaptureRAM = r == QMessageBox::Yes;
|
||||
}
|
||||
else
|
||||
{
|
||||
_ui->actionAuto_screen_capture->setChecked(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_ui->actionAuto_screen_capture->setChecked(false);
|
||||
}
|
||||
}
|
||||
else if(_autoScreenCaptureCachedImages.size())
|
||||
{
|
||||
QString targetDir = _preferencesDialog->getWorkingDirectory() + QDir::separator() + "ScreensCaptured";
|
||||
QDir dir;
|
||||
if(!dir.exists(targetDir))
|
||||
{
|
||||
dir.mkdir(targetDir);
|
||||
}
|
||||
targetDir += QDir::separator();
|
||||
targetDir += "Main_window";
|
||||
if(!dir.exists(targetDir))
|
||||
{
|
||||
dir.mkdir(targetDir);
|
||||
}
|
||||
targetDir += QDir::separator();
|
||||
|
||||
_initProgressDialog->resetProgress();
|
||||
_initProgressDialog->show();
|
||||
_initProgressDialog->setMaximumSteps(_autoScreenCaptureCachedImages.size());
|
||||
int i=0;
|
||||
for(QMap<QString, QByteArray>::iterator iter=_autoScreenCaptureCachedImages.begin(); iter!=_autoScreenCaptureCachedImages.end(); ++iter)
|
||||
{
|
||||
QPixmap figure;
|
||||
figure.loadFromData(iter.value(), "PNG");
|
||||
figure.save(targetDir + iter.key(), "PNG");
|
||||
_initProgressDialog->appendText(tr("Saved image \"%1\" (%2/%3).").arg(targetDir + iter.key()).arg(++i).arg(_autoScreenCaptureCachedImages.size()));
|
||||
_initProgressDialog->incrementStep();
|
||||
}
|
||||
_autoScreenCaptureCachedImages.clear();
|
||||
_initProgressDialog->setValue(_initProgressDialog->maximumSteps());
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::takeScreenshot()
|
||||
@@ -4230,6 +4287,20 @@ void MainWindow::setAspectRatio1080p()
|
||||
this->setAspectRatio((1080*16)/9, 1080);
|
||||
}
|
||||
|
||||
void MainWindow::setAspectRatioCustom()
|
||||
{
|
||||
bool ok;
|
||||
int width = QInputDialog::getInt(this, tr("Aspect ratio"), tr("Width (pixels):"), this->geometry().width(), 100, 10000, 100, &ok);
|
||||
if(ok)
|
||||
{
|
||||
int height = QInputDialog::getInt(this, tr("Aspect ratio"), tr("Height (pixels):"), this->geometry().height(), 100, 10000, 100, &ok);
|
||||
if(ok)
|
||||
{
|
||||
this->setAspectRatio(width, height);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::exportGridMap()
|
||||
{
|
||||
double gridCellSize = 0.05;
|
||||
|
||||
@@ -40,6 +40,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include <QMainWindow>
|
||||
#include <QProgressDialog>
|
||||
#include <QScrollBar>
|
||||
#include <QStatusBar>
|
||||
#include <QtGui/QCloseEvent>
|
||||
|
||||
#include "ui_preferencesDialog.h"
|
||||
@@ -2047,12 +2048,13 @@ void PreferencesDialog::saveMainWindowState(const QMainWindow * mainWindow)
|
||||
settings.beginGroup(mainWindow->objectName());
|
||||
settings.setValue("state", mainWindow->saveState());
|
||||
settings.setValue("maximized", mainWindow->isMaximized());
|
||||
settings.setValue("status_bar", mainWindow->statusBar()->isVisible());
|
||||
settings.endGroup(); // "MainWindow"
|
||||
settings.endGroup(); // rtabmap
|
||||
}
|
||||
}
|
||||
|
||||
void PreferencesDialog::loadMainWindowState(QMainWindow * mainWindow, bool & maximized)
|
||||
void PreferencesDialog::loadMainWindowState(QMainWindow * mainWindow, bool & maximized, bool & statusBarShown)
|
||||
{
|
||||
if(!mainWindow->objectName().isNull())
|
||||
{
|
||||
@@ -2068,6 +2070,8 @@ void PreferencesDialog::loadMainWindowState(QMainWindow * mainWindow, bool & ma
|
||||
mainWindow->restoreState(bytes);
|
||||
}
|
||||
maximized = settings.value("maximized", false).toBool();
|
||||
statusBarShown = settings.value("status_bar", false).toBool();
|
||||
mainWindow->statusBar()->setVisible(statusBarShown);
|
||||
settings.endGroup(); // "MainWindow"
|
||||
settings.endGroup(); // rtabmap
|
||||
}
|
||||
|
||||
@@ -238,6 +238,8 @@
|
||||
<addaction name="action480p"/>
|
||||
<addaction name="action360p"/>
|
||||
<addaction name="action240p"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionCustom"/>
|
||||
</widget>
|
||||
<addaction name="menuShow_view"/>
|
||||
<addaction name="actionDefault_views"/>
|
||||
@@ -1265,6 +1267,11 @@
|
||||
<string>g2o (*.g2o)</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionCustom">
|
||||
<property name="text">
|
||||
<string>Custom...</string>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
|
||||
Reference in New Issue
Block a user