Updated for issue #36: Moved "Export Poses..." to File menu, added "Export images..." action too, updated when some export actions are enabled or disabled

This commit is contained in:
matlabbe
2015-10-16 20:11:24 -04:00
parent eaff524e30
commit 1f33c39f3c
8 changed files with 421 additions and 160 deletions

View File

@@ -231,6 +231,13 @@ private:
float minInliers_; float minInliers_;
}; };
bool RTABMAP_EXP exportPoses(
const std::string & filePath,
int format, // 0=Raw (*.txt), 1=RGBD-SLAM (*.txt), 2=KITTI (*.txt), 3=TORO (*.graph), 4=g2o (*.g2o)
const std::map<int, Transform> & poses,
const std::multimap<int, Link> & constraints, // required for formats 3 and 4
const std::map<int, double> & stamps); // required for format 1
//////////////////////////////////////////// ////////////////////////////////////////////
// Graph utilities // Graph utilities
//////////////////////////////////////////// ////////////////////////////////////////////

View File

@@ -112,7 +112,7 @@ public:
const std::string & path, const std::string & path,
bool optimized, bool optimized,
bool global, bool global,
int type // 0=raw/KITTI format, 1=rgbd-slam format, 2=TORO int format // 0=raw, 1=rgbd-slam format, 2=KITTI format, 3=TORO, 4=g2o
); );
void resetMemory(); void resetMemory();
void dumpPrediction() const; void dumpPrediction() const;

View File

@@ -31,6 +31,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <rtabmap/utilite/UMath.h> #include <rtabmap/utilite/UMath.h>
#include <rtabmap/utilite/UConversion.h> #include <rtabmap/utilite/UConversion.h>
#include <rtabmap/utilite/UTimer.h> #include <rtabmap/utilite/UTimer.h>
#include <rtabmap/utilite/UFile.h>
#include <rtabmap/core/Memory.h> #include <rtabmap/core/Memory.h>
#include <pcl/search/kdtree.h> #include <pcl/search/kdtree.h>
#include <pcl/common/eigen.h> #include <pcl/common/eigen.h>
@@ -1573,6 +1574,109 @@ std::map<int, Transform> CVSBAOptimizer::optimizeBA(
#endif #endif
} }
bool exportPoses(
const std::string & filePath,
int format, // 0=Raw, 1=RGBD-SLAM, 2=KITTI, 3=TORO, 4=g2o
const std::map<int, Transform> & poses,
const std::multimap<int, Link> & constraints, // required for formats 3 and 4
const std::map<int, double> & stamps) // required for format 1
{
std::string tmpPath = filePath;
if(format==3) // TORO
{
if(UFile::getExtension(tmpPath).empty())
{
tmpPath+=".graph";
}
return graph::TOROOptimizer::saveGraph(tmpPath, poses, constraints);
}
else if(format == 4) // g2o
{
if(UFile::getExtension(tmpPath).empty())
{
tmpPath+=".g2o";
}
#ifdef WITH_G2O
return graph::G2OOptimizer::saveGraph(tmpPath, poses, constraints);
#else
UERROR("Cannot export in g2o format because RTAB-Map is not built with g2o support!");
return false;
#endif
}
else
{
if(UFile::getExtension(tmpPath).empty())
{
tmpPath+=".txt";
}
if(format == 1)
{
if(stamps.size() != poses.size())
{
UERROR("When exporting poses to format 1 (RGBD-SLAM), stamps and poses maps should have the same size!");
return false;
}
}
FILE* fout = 0;
#ifdef _MSC_VER
fopen_s(&fout, tmpPath.c_str(), "w");
#else
fout = fopen(tmpPath.c_str(), "w");
#endif
if(fout)
{
for(std::map<int, Transform>::const_iterator iter=poses.begin(); iter!=poses.end(); ++iter)
{
if(format == 1) // rgbd-slam format
{
// Format: stamp x y z qw qx qy qz
Eigen::Quaternionf q = (*iter).second.getQuaternionf();
UASSERT(uContains(stamps, iter->first));
fprintf(fout, "%f %f %f %f %f %f %f %f\n",
stamps.at(iter->first),
(*iter).second.x(),
(*iter).second.y(),
(*iter).second.z(),
q.w(),
q.x(),
q.y(),
q.z());
}
else // default / KITTI format
{
Transform pose = iter->second;
if(format == 2)
{
// for KITTI, we need to remove optical rotation
// z pointing front, x left, y down
Transform t( 0, 0, 1, 0,
-1, 0, 0, 0,
0,-1, 0, 0);
pose = t.inverse() * pose * t;
}
// Format: r11 r12 r13 tx r21 r22 r23 ty r31 r32 r33 tz
const float * p = (const float *)pose.data();
fprintf(fout, "%f", p[0]);
for(int i=1; i<pose.size(); i++)
{
fprintf(fout, " %f", p[i]);
}
fprintf(fout, "\n");
}
}
fclose(fout);
return true;
}
}
return false;
}
//////////////////////////////////////////// ////////////////////////////////////////////
// Graph utilities // Graph utilities
//////////////////////////////////////////// ////////////////////////////////////////////

View File

@@ -740,7 +740,7 @@ void Rtabmap::generateDOTGraph(const std::string & path, int id, int margin)
} }
} }
void Rtabmap::exportPoses(const std::string & path, bool optimized, bool global, int type) void Rtabmap::exportPoses(const std::string & path, bool optimized, bool global, int format)
{ {
if(_memory && _memory->getLastWorkingSignature()) if(_memory && _memory->getLastWorkingSignature())
{ {
@@ -757,89 +757,21 @@ void Rtabmap::exportPoses(const std::string & path, bool optimized, bool global,
_memory->getMetricConstraints(uKeysSet(ids), poses, constraints, global); _memory->getMetricConstraints(uKeysSet(ids), poses, constraints, global);
} }
if(type==3) // TORO std::map<int, double> stamps;
if(format == 1)
{ {
graph::TOROOptimizer::saveGraph(path, poses, constraints); for(std::map<int, Transform>::iterator iter=poses.begin(); iter!=poses.end(); ++iter)
}
else if(type == 4) // g2o
{
#ifdef WITH_G2O
graph::G2OOptimizer::saveGraph(path, poses, constraints);
#else
UERROR("Cannot export in g2o format because RTAB-Map is not built with g2o support!");
#endif
}
else
{
//get timestamps
std::map<int, double> stamps;
if(type == 1)
{ {
for(std::map<int, Transform>::iterator iter=poses.begin(); iter!=poses.end(); ++iter) Transform o;
{ int m, w;
Transform o; std::string l;
int m, w; double stamp = 0.0;
std::string l; _memory->getNodeInfo(iter->first, o, m, w, l, stamp, true);
double stamp = 0.0; stamps.insert(std::make_pair(iter->first, stamp));
_memory->getNodeInfo(iter->first, o, m, w, l, stamp, true);
stamps.insert(std::make_pair(iter->first, stamp));
}
UASSERT(stamps.size()== 0 || stamps.size() == poses.size());
}
FILE* fout = 0;
#ifdef _MSC_VER
fopen_s(&fout, path.c_str(), "w");
#else
fout = fopen(path.c_str(), "w");
#endif
if(fout)
{
for(std::map<int, Transform>::const_iterator iter=poses.begin(); iter!=poses.end(); ++iter)
{
if(type == 1) // rgbd-slam format
{
// Format: stamp x y z qw qx qy qz
Eigen::Quaternionf q = (*iter).second.getQuaternionf();
UASSERT(uContains(stamps, iter->first));
fprintf(fout, "%f %f %f %f %f %f %f %f\n",
stamps.at(iter->first),
(*iter).second.x(),
(*iter).second.y(),
(*iter).second.z(),
q.w(),
q.x(),
q.y(),
q.z());
}
else // default / KITTI format
{
Transform pose = iter->second;
if(type == 2)
{
// for KITTI, we need to remove optical rotation
// z pointing front, x left, y down
Transform t( 0, 0, 1, 0,
-1, 0, 0, 0,
0,-1, 0, 0);
pose = t.inverse() * pose * t;
}
// Format: r11 r12 r13 tx r21 r22 r23 ty r31 r32 r33 tz
const float * p = (const float *)pose.data();
fprintf(fout, "%f", p[0]);
for(int i=1; i<pose.size(); i++)
{
fprintf(fout, " %f", p[i]);
}
fprintf(fout, "\n");
}
}
fclose(fout);
} }
} }
graph::exportPoses(path, format, poses, constraints, stamps);
} }
} }

View File

@@ -134,6 +134,7 @@ private slots:
void exportPosesKITTI(); void exportPosesKITTI();
void exportPosesTORO(); void exportPosesTORO();
void exportPosesG2O(); void exportPosesG2O();
void exportImages();
void postProcessing(); void postProcessing();
void deleteMemory(); void deleteMemory();
void openWorkingDirectory(); void openWorkingDirectory();

View File

@@ -329,6 +329,7 @@ MainWindow::MainWindow(PreferencesDialog * prefDialog, QWidget * parent) :
connect(_ui->actionSave_point_cloud, SIGNAL(triggered()), this, SLOT(exportClouds())); 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_scans_ply_pcd, SIGNAL(triggered()), this, SLOT(exportScans()));
connect(_ui->actionExport_2D_Grid_map_bmp_png, SIGNAL(triggered()), this, SLOT(exportGridMap())); connect(_ui->actionExport_2D_Grid_map_bmp_png, SIGNAL(triggered()), this, SLOT(exportGridMap()));
connect(_ui->actionExport_images_RGB_jpg_Depth_png, SIGNAL(triggered()), this , SLOT(exportImages()));
connect(_ui->actionExport_cameras_in_Bundle_format_out, SIGNAL(triggered()), SLOT(exportBundlerFormat())); connect(_ui->actionExport_cameras_in_Bundle_format_out, SIGNAL(triggered()), SLOT(exportBundlerFormat()));
connect(_ui->actionView_scans, SIGNAL(triggered()), this, SLOT(viewScans())); connect(_ui->actionView_scans, SIGNAL(triggered()), this, SLOT(viewScans()));
connect(_ui->actionView_high_res_point_cloud, SIGNAL(triggered()), this, SLOT(viewClouds())); connect(_ui->actionView_high_res_point_cloud, SIGNAL(triggered()), this, SLOT(viewClouds()));
@@ -339,12 +340,6 @@ MainWindow::MainWindow(PreferencesDialog * prefDialog, QWidget * parent) :
_ui->actionPause->setShortcut(Qt::Key_Space); _ui->actionPause->setShortcut(Qt::Key_Space);
_ui->actionSave_GUI_config->setShortcut(QKeySequence::Save); _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);
_ui->actionExport_cameras_in_Bundle_format_out->setEnabled(false);
_ui->actionView_scans->setEnabled(false);
_ui->actionView_high_res_point_cloud->setEnabled(false);
_ui->actionReset_Odometry->setEnabled(false); _ui->actionReset_Odometry->setEnabled(false);
_ui->actionPost_processing->setEnabled(false); _ui->actionPost_processing->setEnabled(false);
@@ -1348,6 +1343,11 @@ void MainWindow::processStats(const rtabmap::Statistics & stat)
{ {
_cachedSignatures.clear(); _cachedSignatures.clear();
} }
if(_state != kMonitoring && _state != kDetecting)
{
_ui->actionExport_images_RGB_jpg_Depth_png->setEnabled(!_cachedSignatures.empty() && !_currentPosesMap.empty());
_ui->actionExport_cameras_in_Bundle_format_out->setEnabled(!_cachedSignatures.empty() && !_currentPosesMap.empty());
}
_processingStatistics = false; _processingStatistics = false;
} }
@@ -1371,6 +1371,7 @@ void MainWindow::updateMapCloud(
if(_state != kMonitoring && _state != kDetecting) if(_state != kMonitoring && _state != kDetecting)
{ {
_ui->actionPost_processing->setEnabled(_cachedSignatures.size() >= 2 && _currentPosesMap.size() >= 2 && _currentLinksMap.size() >= 1); _ui->actionPost_processing->setEnabled(_cachedSignatures.size() >= 2 && _currentPosesMap.size() >= 2 && _currentLinksMap.size() >= 1);
_ui->menuExport_poses->setEnabled(!_currentPosesMap.empty());
} }
} }
@@ -1517,12 +1518,14 @@ void MainWindow::updateMapCloud(
} }
// activate actions // activate actions
_ui->actionSave_point_cloud->setEnabled(!_createdClouds.empty()); if(_state != kMonitoring && _state != kDetecting)
_ui->actionView_high_res_point_cloud->setEnabled(!_createdClouds.empty()); {
_ui->actionExport_2D_scans_ply_pcd->setEnabled(!_createdScans.empty()); _ui->actionSave_point_cloud->setEnabled(!_createdClouds.empty());
_ui->actionExport_2D_Grid_map_bmp_png->setEnabled(!_gridLocalMaps.empty() || !_projectionLocalMaps.empty()); _ui->actionView_high_res_point_cloud->setEnabled(!_createdClouds.empty());
_ui->actionView_scans->setEnabled(!_createdScans.empty()); _ui->actionExport_2D_scans_ply_pcd->setEnabled(!_createdScans.empty());
_ui->actionExport_cameras_in_Bundle_format_out->setEnabled(!_createdClouds.empty()); _ui->actionExport_2D_Grid_map_bmp_png->setEnabled(!_gridLocalMaps.empty() || !_projectionLocalMaps.empty());
_ui->actionView_scans->setEnabled(!_createdScans.empty());
}
//remove not used clouds //remove not used clouds
for(QMap<std::string, Transform>::iterator iter = viewerClouds.begin(); iter!=viewerClouds.end(); ++iter) for(QMap<std::string, Transform>::iterator iter = viewerClouds.begin(); iter!=viewerClouds.end(); ++iter)
@@ -2173,6 +2176,11 @@ void MainWindow::processRtabmapEvent3DMap(const rtabmap::RtabmapEvent3DMap & eve
{ {
_cachedSignatures.clear(); _cachedSignatures.clear();
} }
if(_state != kMonitoring && _state != kDetecting)
{
_ui->actionExport_images_RGB_jpg_Depth_png->setEnabled(!_cachedSignatures.empty() && !_currentPosesMap.empty());
_ui->actionExport_cameras_in_Bundle_format_out->setEnabled(!_cachedSignatures.empty() && !_currentPosesMap.empty());
}
_processingDownloadedMap = false; _processingDownloadedMap = false;
} }
_initProgressDialog->setValue(_initProgressDialog->maximumSteps()); _initProgressDialog->setValue(_initProgressDialog->maximumSteps());
@@ -3229,36 +3237,24 @@ void MainWindow::exportPosesG2O()
void MainWindow::exportPoses(int format) void MainWindow::exportPoses(int format)
{ {
QStringList items; if(_currentPosesMap.size())
items.append("Local map optimized");
items.append("Local map not optimized");
items.append("Global map optimized");
items.append("Global map not optimized");
bool ok;
QString item = QInputDialog::getItem(this, tr("Parameters"), tr("Options:"), items, 2, false, &ok);
if(ok)
{ {
bool optimized=false, global=false; std::map<int, double> stamps;
if(item.compare("Local map optimized") == 0) if(format == 1)
{ {
optimized = true; for(std::map<int, Transform>::iterator iter=_currentPosesMap.begin(); iter!=_currentPosesMap.end(); ++iter)
} {
else if(item.compare("Local map not optimized") == 0) if(_cachedSignatures.contains(iter->first))
{ {
stamps.insert(std::make_pair(iter->first, _cachedSignatures.value(iter->first).getStamp()));
} }
else if(item.compare("Global map optimized") == 0) }
{ if(stamps.size()!=_currentPosesMap.size())
global=true; {
optimized=true; QMessageBox::warning(this, tr("Export poses..."), tr("RGB-D SLAM format: Poses (%1) and stamps (%2) have not the same size! Try again after updating the cache.")
} .arg(_currentPosesMap.size()).arg(stamps.size()));
else if(item.compare("Global map not optimized") == 0) return;
{ }
global=true;
}
else
{
UFATAL("Item \"%s\" not found?!?", item.toStdString().c_str());
} }
if(_exportPosesFileName[format].isEmpty()) if(_exportPosesFileName[format].isEmpty())
@@ -3276,17 +3272,25 @@ void MainWindow::exportPoses(int format)
{ {
_exportPosesFileName[format] = path; _exportPosesFileName[format] = path;
this->post(new RtabmapEventCmd(RtabmapEventCmd::kCmdExportPoses, global, optimized, path.toStdString(), format)); bool saved = graph::exportPoses(path.toStdString(), format, _currentPosesMap, _currentLinksMap, stamps);
_ui->dockWidget_console->show(); if(saved)
_ui->widget_console->appendMsg( {
QString("%1 saved (global=%2, optimized=%3)... %4") QMessageBox::information(this,
.arg(format == 3?"TORO graph":format == 4?"g2o graph":"Poses") tr("Export poses..."),
.arg(global?"true":"false") tr("%1 saved to \"%2\".")
.arg(optimized?"true":"false") .arg(format == 3?"TORO graph":format == 4?"g2o graph":"Poses")
.arg(_exportPosesFileName[format])); .arg(_exportPosesFileName[format]));
}
else
{
QMessageBox::information(this,
tr("Export poses..."),
tr("Failed to save %1 to \"%2\"!")
.arg(format == 3?"TORO graph":format == 4?"g2o graph":"poses")
.arg(_exportPosesFileName[format]));
}
} }
} }
} }
@@ -4149,6 +4153,7 @@ void MainWindow::clearTheCache()
_ui->actionPost_processing->setEnabled(false); _ui->actionPost_processing->setEnabled(false);
_ui->actionSave_point_cloud->setEnabled(false); _ui->actionSave_point_cloud->setEnabled(false);
_ui->actionExport_cameras_in_Bundle_format_out->setEnabled(false); _ui->actionExport_cameras_in_Bundle_format_out->setEnabled(false);
_ui->actionExport_images_RGB_jpg_Depth_png->setEnabled(false);
_ui->actionView_scans->setEnabled(false); _ui->actionView_scans->setEnabled(false);
_ui->actionView_high_res_point_cloud->setEnabled(false); _ui->actionView_high_res_point_cloud->setEnabled(false);
_likelihoodCurve->clear(); _likelihoodCurve->clear();
@@ -5040,6 +5045,163 @@ bool MainWindow::getExportedClouds(
return false; return false;
} }
void MainWindow::exportImages()
{
if(_cachedSignatures.empty())
{
QMessageBox::warning(this, tr("Export images..."), tr("Cannot export images, the cache is empty!"));
return;
}
std::map<int, Transform> poses = _ui->widget_mapVisibility->getVisiblePoses();
if(poses.empty())
{
QMessageBox::warning(this, tr("Export images..."), tr("There is no map!"));
return;
}
QString path = QFileDialog::getExistingDirectory(this, tr("Select directory where to save images..."), this->getWorkingDirectory());
if(!path.isNull())
{
SensorData data;
if(_cachedSignatures.contains(poses.rbegin()->first))
{
data = _cachedSignatures.value(poses.rbegin()->first).sensorData();
data.uncompressData();
}
if(!data.imageRaw().empty() && !data.rightRaw().empty())
{
QDir dir;
dir.mkdir(QString("%1/left").arg(path));
dir.mkdir(QString("%1/right").arg(path));
if(data.stereoCameraModel().isValid())
{
std::string cameraName = "calibration";
StereoCameraModel model(
cameraName,
data.imageRaw().size(),
data.stereoCameraModel().left().K(),
data.stereoCameraModel().left().D(),
data.stereoCameraModel().left().R(),
data.stereoCameraModel().left().P(),
data.rightRaw().size(),
data.stereoCameraModel().right().K(),
data.stereoCameraModel().right().D(),
data.stereoCameraModel().right().R(),
data.stereoCameraModel().right().P(),
data.stereoCameraModel().R(),
data.stereoCameraModel().T(),
data.stereoCameraModel().E(),
data.stereoCameraModel().F(),
data.stereoCameraModel().left().localTransform());
if(model.save(path.toStdString()))
{
UINFO("Saved stereo calibration \"%s\"", (path.toStdString()+"/"+cameraName).c_str());
}
else
{
UERROR("Failed saving calibration \"%s\"", (path.toStdString()+"/"+cameraName).c_str());
}
}
}
else if(!data.imageRaw().empty())
{
if(!data.depthRaw().empty())
{
QDir dir;
dir.mkdir(QString("%1/rgb").arg(path));
dir.mkdir(QString("%1/depth").arg(path));
}
if(data.cameraModels().size() > 1)
{
UERROR("Only one camera calibration can be saved at this time (%d detected)", (int)data.cameraModels().size());
}
else if(data.cameraModels().size() == 1 && data.cameraModels().front().isValid())
{
std::string cameraName = "calibration";
CameraModel model(cameraName,
data.imageRaw().size(),
data.cameraModels().front().K(),
data.cameraModels().front().D(),
data.cameraModels().front().R(),
data.cameraModels().front().P(),
data.cameraModels().front().localTransform());
if(model.save(path.toStdString()))
{
UINFO("Saved calibration \"%s\"", (path.toStdString()+"/"+cameraName).c_str());
}
else
{
UERROR("Failed saving calibration \"%s\"", (path.toStdString()+"/"+cameraName).c_str());
}
}
}
else
{
QMessageBox::warning(this,
tr("Export images..."),
tr("Data in the cache don't seem to have images (tested node %1). Calibration file will not be saved. Try refreshing the cache (with clouds).").arg(poses.rbegin()->first));
}
}
_initProgressDialog->resetProgress();
_initProgressDialog->show();
_initProgressDialog->setMaximumSteps(_cachedSignatures.size());
int saved = 0;
for(std::map<int, Transform>::iterator iter=poses.begin(); iter!=poses.end(); ++iter)
{
int id = iter->first;
SensorData data;
if(_cachedSignatures.contains(iter->first))
{
data = _cachedSignatures.value(iter->first).sensorData();
data.uncompressData();
}
QString info;
bool warn = false;
if(!data.imageRaw().empty() && !data.rightRaw().empty())
{
cv::imwrite(QString("%1/left/%2.jpg").arg(path).arg(id).toStdString(), data.imageRaw());
cv::imwrite(QString("%1/right/%2.jpg").arg(path).arg(id).toStdString(), data.rightRaw());
info = tr("Saved left/%1.jpg and right/%1.jpg.").arg(id);
}
else if(!data.imageRaw().empty() && !data.depthRaw().empty())
{
cv::imwrite(QString("%1/rgb/%2.jpg").arg(path).arg(id).toStdString(), data.imageRaw());
cv::imwrite(QString("%1/depth/%2.png").arg(path).arg(id).toStdString(), data.depthRaw());
info = tr("Saved rgb/%1.jpg and depth/%1.png.").arg(id);
}
else if(!data.imageRaw().empty())
{
cv::imwrite(QString("%1/%2.jpg").arg(path).arg(id).toStdString(), data.imageRaw());
info = tr("Saved %1.jpg.").arg(id);
}
else
{
info = tr("No images saved for node %1!").arg(id);
warn = true;
}
saved += warn?0:1;
_initProgressDialog->appendText(info, !warn?Qt::black:Qt::darkYellow);
_initProgressDialog->incrementStep();
QApplication::processEvents();
}
if(saved!=poses.size())
{
_initProgressDialog->setAutoClose(false);
_initProgressDialog->appendText(tr("%1 images of %2 saved to \"%3\".").arg(saved).arg(poses.size()).arg(path));
}
else
{
_initProgressDialog->appendText(tr("%1 images saved to \"%2\".").arg(saved).arg(path));
}
_initProgressDialog->setValue(_initProgressDialog->maximumSteps());
}
void MainWindow::exportBundlerFormat() void MainWindow::exportBundlerFormat()
{ {
std::map<int, Transform> posesIn = _ui->widget_mapVisibility->getVisiblePoses(); std::map<int, Transform> posesIn = _ui->widget_mapVisibility->getVisiblePoses();
@@ -5148,7 +5310,7 @@ void MainWindow::exportBundlerFormat()
} }
else else
{ {
QMessageBox::warning(this, tr("Exporting cameras..."), tr("No poses exported...")); QMessageBox::warning(this, tr("Exporting cameras..."), tr("No poses exported because of missing images. Try refreshing the cache (with clouds)."));
} }
} }
@@ -5823,7 +5985,6 @@ void MainWindow::changeState(MainWindow::State newState)
_ui->actionDump_the_prediction_matrix->setVisible(!monitoring); _ui->actionDump_the_prediction_matrix->setVisible(!monitoring);
_ui->actionGenerate_map->setVisible(!monitoring); _ui->actionGenerate_map->setVisible(!monitoring);
_ui->actionUpdate_cache_from_database->setVisible(monitoring); _ui->actionUpdate_cache_from_database->setVisible(monitoring);
_ui->menuExport_poses->menuAction()->setVisible(!monitoring);
_ui->actionOpen_working_directory->setVisible(!monitoring); _ui->actionOpen_working_directory->setVisible(!monitoring);
_ui->actionData_recorder->setVisible(!monitoring); _ui->actionData_recorder->setVisible(!monitoring);
_ui->menuSelect_source->menuAction()->setVisible(!monitoring); _ui->menuSelect_source->menuAction()->setVisible(!monitoring);
@@ -5844,7 +6005,7 @@ void MainWindow::changeState(MainWindow::State newState)
} }
} }
actions = _ui->menuFile->actions(); actions = _ui->menuFile->actions();
if(actions.size()>=10) if(actions.size()==15)
{ {
if(actions.at(2)->isSeparator()) if(actions.at(2)->isSeparator())
{ {
@@ -5854,9 +6015,9 @@ void MainWindow::changeState(MainWindow::State newState)
{ {
UWARN("Menu File separators have not the same order."); UWARN("Menu File separators have not the same order.");
} }
if(actions.at(9)->isSeparator()) if(actions.at(11)->isSeparator())
{ {
actions.at(9)->setVisible(!monitoring); actions.at(11)->setVisible(!monitoring);
} }
else else
{ {
@@ -5884,7 +6045,6 @@ void MainWindow::changeState(MainWindow::State newState)
UWARN("Menu File separators have not the same order."); UWARN("Menu File separators have not the same order.");
} }
switch (newState) switch (newState)
{ {
case kIdle: // RTAB-Map is not initialized yet case kIdle: // RTAB-Map is not initialized yet
@@ -5904,8 +6064,15 @@ void MainWindow::changeState(MainWindow::State newState)
_ui->actionDump_the_prediction_matrix->setEnabled(false); _ui->actionDump_the_prediction_matrix->setEnabled(false);
_ui->actionDelete_memory->setEnabled(false); _ui->actionDelete_memory->setEnabled(false);
_ui->actionPost_processing->setEnabled(_cachedSignatures.size() >= 2 && _currentPosesMap.size() >= 2 && _currentLinksMap.size() >= 1); _ui->actionPost_processing->setEnabled(_cachedSignatures.size() >= 2 && _currentPosesMap.size() >= 2 && _currentLinksMap.size() >= 1);
_ui->actionExport_images_RGB_jpg_Depth_png->setEnabled(!_cachedSignatures.empty() && !_currentPosesMap.empty());
_ui->actionGenerate_map->setEnabled(false); _ui->actionGenerate_map->setEnabled(false);
_ui->menuExport_poses->setEnabled(false); _ui->menuExport_poses->setEnabled(!_currentPosesMap.empty());
_ui->actionSave_point_cloud->setEnabled(!_createdClouds.empty());
_ui->actionView_high_res_point_cloud->setEnabled(!_createdClouds.empty());
_ui->actionExport_2D_scans_ply_pcd->setEnabled(!_createdScans.empty());
_ui->actionExport_2D_Grid_map_bmp_png->setEnabled(!_gridLocalMaps.empty() || !_projectionLocalMaps.empty());
_ui->actionView_scans->setEnabled(!_createdScans.empty());
_ui->actionExport_cameras_in_Bundle_format_out->setEnabled(!_cachedSignatures.empty() && !_currentPosesMap.empty());
_ui->actionDownload_all_clouds->setEnabled(false); _ui->actionDownload_all_clouds->setEnabled(false);
_ui->actionDownload_graph->setEnabled(false); _ui->actionDownload_graph->setEnabled(false);
_ui->menuSelect_source->setEnabled(false); _ui->menuSelect_source->setEnabled(false);
@@ -5953,8 +6120,15 @@ void MainWindow::changeState(MainWindow::State newState)
_ui->actionDump_the_prediction_matrix->setEnabled(true); _ui->actionDump_the_prediction_matrix->setEnabled(true);
_ui->actionDelete_memory->setEnabled(true); _ui->actionDelete_memory->setEnabled(true);
_ui->actionPost_processing->setEnabled(_cachedSignatures.size() >= 2 && _currentPosesMap.size() >= 2 && _currentLinksMap.size() >= 1); _ui->actionPost_processing->setEnabled(_cachedSignatures.size() >= 2 && _currentPosesMap.size() >= 2 && _currentLinksMap.size() >= 1);
_ui->actionExport_images_RGB_jpg_Depth_png->setEnabled(!_cachedSignatures.empty() && !_currentPosesMap.empty());
_ui->actionGenerate_map->setEnabled(true); _ui->actionGenerate_map->setEnabled(true);
_ui->menuExport_poses->setEnabled(true); _ui->menuExport_poses->setEnabled(!_currentPosesMap.empty());
_ui->actionSave_point_cloud->setEnabled(!_createdClouds.empty());
_ui->actionView_high_res_point_cloud->setEnabled(!_createdClouds.empty());
_ui->actionExport_2D_scans_ply_pcd->setEnabled(!_createdScans.empty());
_ui->actionExport_2D_Grid_map_bmp_png->setEnabled(!_gridLocalMaps.empty() || !_projectionLocalMaps.empty());
_ui->actionView_scans->setEnabled(!_createdScans.empty());
_ui->actionExport_cameras_in_Bundle_format_out->setEnabled(!_cachedSignatures.empty() && !_currentPosesMap.empty());
_ui->actionDownload_all_clouds->setEnabled(true); _ui->actionDownload_all_clouds->setEnabled(true);
_ui->actionDownload_graph->setEnabled(true); _ui->actionDownload_graph->setEnabled(true);
_ui->menuSelect_source->setEnabled(true); _ui->menuSelect_source->setEnabled(true);
@@ -5991,8 +6165,15 @@ void MainWindow::changeState(MainWindow::State newState)
_ui->actionDump_the_prediction_matrix->setEnabled(false); _ui->actionDump_the_prediction_matrix->setEnabled(false);
_ui->actionDelete_memory->setEnabled(false); _ui->actionDelete_memory->setEnabled(false);
_ui->actionPost_processing->setEnabled(false); _ui->actionPost_processing->setEnabled(false);
_ui->actionExport_images_RGB_jpg_Depth_png->setEnabled(false);
_ui->actionGenerate_map->setEnabled(false); _ui->actionGenerate_map->setEnabled(false);
_ui->menuExport_poses->setEnabled(false); _ui->menuExport_poses->setEnabled(false);
_ui->actionSave_point_cloud->setEnabled(false);
_ui->actionView_high_res_point_cloud->setEnabled(false);
_ui->actionExport_2D_scans_ply_pcd->setEnabled(false);
_ui->actionExport_2D_Grid_map_bmp_png->setEnabled(false);
_ui->actionView_scans->setEnabled(false);
_ui->actionExport_cameras_in_Bundle_format_out->setEnabled(false);
_ui->actionDownload_all_clouds->setEnabled(false); _ui->actionDownload_all_clouds->setEnabled(false);
_ui->actionDownload_graph->setEnabled(false); _ui->actionDownload_graph->setEnabled(false);
_ui->menuSelect_source->setEnabled(false); _ui->menuSelect_source->setEnabled(false);
@@ -6031,8 +6212,15 @@ void MainWindow::changeState(MainWindow::State newState)
_ui->actionDump_the_prediction_matrix->setEnabled(false); _ui->actionDump_the_prediction_matrix->setEnabled(false);
_ui->actionDelete_memory->setEnabled(false); _ui->actionDelete_memory->setEnabled(false);
_ui->actionPost_processing->setEnabled(false); _ui->actionPost_processing->setEnabled(false);
_ui->actionExport_images_RGB_jpg_Depth_png->setEnabled(false);
_ui->actionGenerate_map->setEnabled(false); _ui->actionGenerate_map->setEnabled(false);
_ui->menuExport_poses->setEnabled(false); _ui->menuExport_poses->setEnabled(false);
_ui->actionSave_point_cloud->setEnabled(false);
_ui->actionView_high_res_point_cloud->setEnabled(false);
_ui->actionExport_2D_scans_ply_pcd->setEnabled(false);
_ui->actionExport_2D_Grid_map_bmp_png->setEnabled(false);
_ui->actionView_scans->setEnabled(false);
_ui->actionExport_cameras_in_Bundle_format_out->setEnabled(false);
_ui->actionDownload_all_clouds->setEnabled(false); _ui->actionDownload_all_clouds->setEnabled(false);
_ui->actionDownload_graph->setEnabled(false); _ui->actionDownload_graph->setEnabled(false);
_state = kDetecting; _state = kDetecting;
@@ -6058,8 +6246,15 @@ void MainWindow::changeState(MainWindow::State newState)
_ui->actionDump_the_prediction_matrix->setEnabled(true); _ui->actionDump_the_prediction_matrix->setEnabled(true);
_ui->actionDelete_memory->setEnabled(false); _ui->actionDelete_memory->setEnabled(false);
_ui->actionPost_processing->setEnabled(_cachedSignatures.size() >= 2 && _currentPosesMap.size() >= 2 && _currentLinksMap.size() >= 1); _ui->actionPost_processing->setEnabled(_cachedSignatures.size() >= 2 && _currentPosesMap.size() >= 2 && _currentLinksMap.size() >= 1);
_ui->actionExport_images_RGB_jpg_Depth_png->setEnabled(!_cachedSignatures.empty() && !_currentPosesMap.empty());
_ui->actionGenerate_map->setEnabled(true); _ui->actionGenerate_map->setEnabled(true);
_ui->menuExport_poses->setEnabled(true); _ui->menuExport_poses->setEnabled(!_currentPosesMap.empty());
_ui->actionSave_point_cloud->setEnabled(!_createdClouds.empty());
_ui->actionView_high_res_point_cloud->setEnabled(!_createdClouds.empty());
_ui->actionExport_2D_scans_ply_pcd->setEnabled(!_createdScans.empty());
_ui->actionExport_2D_Grid_map_bmp_png->setEnabled(!_gridLocalMaps.empty() || !_projectionLocalMaps.empty());
_ui->actionView_scans->setEnabled(!_createdScans.empty());
_ui->actionExport_cameras_in_Bundle_format_out->setEnabled(!_cachedSignatures.empty() && !_currentPosesMap.empty());
_ui->actionDownload_all_clouds->setEnabled(true); _ui->actionDownload_all_clouds->setEnabled(true);
_ui->actionDownload_graph->setEnabled(true); _ui->actionDownload_graph->setEnabled(true);
_state = kPaused; _state = kPaused;
@@ -6086,6 +6281,14 @@ void MainWindow::changeState(MainWindow::State newState)
_ui->actionPause_when_a_loop_hypothesis_is_rejected->setEnabled(true); _ui->actionPause_when_a_loop_hypothesis_is_rejected->setEnabled(true);
_ui->actionReset_Odometry->setEnabled(true); _ui->actionReset_Odometry->setEnabled(true);
_ui->actionPost_processing->setEnabled(false); _ui->actionPost_processing->setEnabled(false);
_ui->actionExport_images_RGB_jpg_Depth_png->setEnabled(false);
_ui->menuExport_poses->setEnabled(false);
_ui->actionSave_point_cloud->setEnabled(false);
_ui->actionView_high_res_point_cloud->setEnabled(false);
_ui->actionExport_2D_scans_ply_pcd->setEnabled(false);
_ui->actionExport_2D_Grid_map_bmp_png->setEnabled(false);
_ui->actionView_scans->setEnabled(false);
_ui->actionExport_cameras_in_Bundle_format_out->setEnabled(false);
_ui->actionDelete_memory->setEnabled(true); _ui->actionDelete_memory->setEnabled(true);
_ui->actionDownload_all_clouds->setEnabled(true); _ui->actionDownload_all_clouds->setEnabled(true);
_ui->actionDownload_graph->setEnabled(true); _ui->actionDownload_graph->setEnabled(true);
@@ -6108,6 +6311,14 @@ void MainWindow::changeState(MainWindow::State newState)
_ui->actionPause_when_a_loop_hypothesis_is_rejected->setEnabled(true); _ui->actionPause_when_a_loop_hypothesis_is_rejected->setEnabled(true);
_ui->actionReset_Odometry->setEnabled(true); _ui->actionReset_Odometry->setEnabled(true);
_ui->actionPost_processing->setEnabled(_cachedSignatures.size() >= 2 && _currentPosesMap.size() >= 2 && _currentLinksMap.size() >= 1); _ui->actionPost_processing->setEnabled(_cachedSignatures.size() >= 2 && _currentPosesMap.size() >= 2 && _currentLinksMap.size() >= 1);
_ui->actionExport_images_RGB_jpg_Depth_png->setEnabled(!_cachedSignatures.empty() && !_currentPosesMap.empty());
_ui->menuExport_poses->setEnabled(!_currentPosesMap.empty());
_ui->actionSave_point_cloud->setEnabled(!_createdClouds.empty());
_ui->actionView_high_res_point_cloud->setEnabled(!_createdClouds.empty());
_ui->actionExport_2D_scans_ply_pcd->setEnabled(!_createdScans.empty());
_ui->actionExport_2D_Grid_map_bmp_png->setEnabled(!_gridLocalMaps.empty() || !_projectionLocalMaps.empty());
_ui->actionView_scans->setEnabled(!_createdScans.empty());
_ui->actionExport_cameras_in_Bundle_format_out->setEnabled(!_cachedSignatures.empty() && !_currentPosesMap.empty());
_ui->actionDelete_memory->setEnabled(true); _ui->actionDelete_memory->setEnabled(true);
_ui->actionDownload_all_clouds->setEnabled(true); _ui->actionDownload_all_clouds->setEnabled(true);
_ui->actionDownload_graph->setEnabled(true); _ui->actionDownload_graph->setEnabled(true);

View File

@@ -50,7 +50,7 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>166</width> <width>197</width>
<height>173</height> <height>173</height>
</rect> </rect>
</property> </property>
@@ -236,7 +236,7 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>165</width> <width>196</width>
<height>173</height> <height>173</height>
</rect> </rect>
</property> </property>
@@ -429,6 +429,7 @@
<addaction name="separator"/> <addaction name="separator"/>
<addaction name="actionSave_config"/> <addaction name="actionSave_config"/>
<addaction name="separator"/> <addaction name="separator"/>
<addaction name="actionGenerate_3D_map_pcd"/>
<addaction name="actionExport"/> <addaction name="actionExport"/>
<addaction name="actionExtract_images"/> <addaction name="actionExtract_images"/>
<addaction name="separator"/> <addaction name="separator"/>
@@ -452,7 +453,6 @@
<addaction name="actionReset_all_changes"/> <addaction name="actionReset_all_changes"/>
<addaction name="separator"/> <addaction name="separator"/>
<addaction name="actionView_3D_map"/> <addaction name="actionView_3D_map"/>
<addaction name="actionGenerate_3D_map_pcd"/>
</widget> </widget>
<widget class="QMenu" name="menuView"> <widget class="QMenu" name="menuView">
<property name="title"> <property name="title">
@@ -836,7 +836,7 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>338</width> <width>314</width>
<height>303</height> <height>303</height>
</rect> </rect>
</property> </property>
@@ -1375,7 +1375,7 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>338</width> <width>333</width>
<height>333</height> <height>333</height>
</rect> </rect>
</property> </property>
@@ -1613,8 +1613,8 @@
<property name="geometry"> <property name="geometry">
<rect> <rect>
<x>0</x> <x>0</x>
<y>-100</y> <y>0</y>
<width>338</width> <width>276</width>
<height>377</height> <height>377</height>
</rect> </rect>
</property> </property>
@@ -1871,7 +1871,7 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>351</width> <width>289</width>
<height>176</height> <height>176</height>
</rect> </rect>
</property> </property>
@@ -1971,7 +1971,7 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>338</width> <width>285</width>
<height>309</height> <height>309</height>
</rect> </rect>
</property> </property>
@@ -2363,7 +2363,7 @@
</action> </action>
<action name="actionExport"> <action name="actionExport">
<property name="text"> <property name="text">
<string>Export...</string> <string>Export database...</string>
</property> </property>
</action> </action>
<action name="actionExtract_images"> <action name="actionExtract_images">

View File

@@ -34,6 +34,16 @@
<property name="title"> <property name="title">
<string>File</string> <string>File</string>
</property> </property>
<widget class="QMenu" name="menuExport_poses">
<property name="title">
<string>Export poses...</string>
</property>
<addaction name="actionRaw_format_txt"/>
<addaction name="actionRGBD_SLAM_format_txt"/>
<addaction name="actionKITTI_format_txt"/>
<addaction name="actionTORO_graph"/>
<addaction name="actionG2o_g2o"/>
</widget>
<addaction name="actionNew_database"/> <addaction name="actionNew_database"/>
<addaction name="actionOpen_database"/> <addaction name="actionOpen_database"/>
<addaction name="separator"/> <addaction name="separator"/>
@@ -42,6 +52,8 @@
<addaction name="actionSave_point_cloud"/> <addaction name="actionSave_point_cloud"/>
<addaction name="actionExport_2D_scans_ply_pcd"/> <addaction name="actionExport_2D_scans_ply_pcd"/>
<addaction name="actionExport_2D_Grid_map_bmp_png"/> <addaction name="actionExport_2D_Grid_map_bmp_png"/>
<addaction name="menuExport_poses"/>
<addaction name="actionExport_images_RGB_jpg_Depth_png"/>
<addaction name="actionExport_cameras_in_Bundle_format_out"/> <addaction name="actionExport_cameras_in_Bundle_format_out"/>
<addaction name="separator"/> <addaction name="separator"/>
<addaction name="actionClose_database"/> <addaction name="actionClose_database"/>
@@ -56,21 +68,10 @@
<property name="title"> <property name="title">
<string>Advanced</string> <string>Advanced</string>
</property> </property>
<widget class="QMenu" name="menuExport_poses">
<property name="title">
<string>Export poses...</string>
</property>
<addaction name="actionRaw_format_txt"/>
<addaction name="actionRGBD_SLAM_format_txt"/>
<addaction name="actionKITTI_format_txt"/>
<addaction name="actionTORO_graph"/>
<addaction name="actionG2o_g2o"/>
</widget>
<addaction name="actionOpen_working_directory"/> <addaction name="actionOpen_working_directory"/>
<addaction name="actionDump_the_memory"/> <addaction name="actionDump_the_memory"/>
<addaction name="actionDump_the_prediction_matrix"/> <addaction name="actionDump_the_prediction_matrix"/>
<addaction name="actionGenerate_map"/> <addaction name="actionGenerate_map"/>
<addaction name="menuExport_poses"/>
<addaction name="actionPrint_loop_closure_IDs_to_console"/> <addaction name="actionPrint_loop_closure_IDs_to_console"/>
</widget> </widget>
<addaction name="actionDownload_all_clouds"/> <addaction name="actionDownload_all_clouds"/>
@@ -1283,6 +1284,11 @@
<string>Update cache from a local database copy...</string> <string>Update cache from a local database copy...</string>
</property> </property>
</action> </action>
<action name="actionExport_images_RGB_jpg_Depth_png">
<property name="text">
<string>Export images (RGB=*.jpg Depth=*.png)...</string>
</property>
</action>
</widget> </widget>
<customwidgets> <customwidgets>
<customwidget> <customwidget>