mirror of
https://github.com/introlab/rtabmap.git
synced 2026-09-02 09:30:25 +08:00
DatabaseViewer: Saving/loading settings, added 3D view, added Grid from 3d projection parameter
This commit is contained in:
@@ -128,21 +128,21 @@ pcl::PointCloud<pcl::PointXYZ>::Ptr RTABMAP_EXP cloudFromDisparity(
|
|||||||
const cv::Mat & imageDisparity,
|
const cv::Mat & imageDisparity,
|
||||||
float cx, float cy,
|
float cx, float cy,
|
||||||
float fx, float baseline,
|
float fx, float baseline,
|
||||||
int decimation);
|
int decimation = 1);
|
||||||
|
|
||||||
pcl::PointCloud<pcl::PointXYZRGB>::Ptr RTABMAP_EXP cloudFromDisparityRGB(
|
pcl::PointCloud<pcl::PointXYZRGB>::Ptr RTABMAP_EXP cloudFromDisparityRGB(
|
||||||
const cv::Mat & imageRgb,
|
const cv::Mat & imageRgb,
|
||||||
const cv::Mat & imageDisparity,
|
const cv::Mat & imageDisparity,
|
||||||
float cx, float cy,
|
float cx, float cy,
|
||||||
float fx, float baseline,
|
float fx, float baseline,
|
||||||
int decimation);
|
int decimation = 1);
|
||||||
|
|
||||||
pcl::PointCloud<pcl::PointXYZRGB>::Ptr RTABMAP_EXP cloudFromStereoImages(
|
pcl::PointCloud<pcl::PointXYZRGB>::Ptr RTABMAP_EXP cloudFromStereoImages(
|
||||||
const cv::Mat & imageLeft,
|
const cv::Mat & imageLeft,
|
||||||
const cv::Mat & imageRight,
|
const cv::Mat & imageRight,
|
||||||
float cx, float cy,
|
float cx, float cy,
|
||||||
float fx, float baseline,
|
float fx, float baseline,
|
||||||
int decimation);
|
int decimation = 1);
|
||||||
|
|
||||||
cv::Mat RTABMAP_EXP disparityFromStereoImages(
|
cv::Mat RTABMAP_EXP disparityFromStereoImages(
|
||||||
const cv::Mat & leftImage,
|
const cv::Mat & leftImage,
|
||||||
|
|||||||
@@ -139,7 +139,7 @@ void optimizeTOROGraph(
|
|||||||
std::list<std::map<int, Transform> > * intermediateGraphes)
|
std::list<std::map<int, Transform> > * intermediateGraphes)
|
||||||
{
|
{
|
||||||
optimizedPoses.clear();
|
optimizedPoses.clear();
|
||||||
if(depthGraph.size() && poses.size()>=2 && links.size()>=1)
|
if(depthGraph.size() >= 2 && poses.size()>=2 && links.size()>=1)
|
||||||
{
|
{
|
||||||
// Modify IDs using the margin from the current signature (TORO root will be the last signature)
|
// Modify IDs using the margin from the current signature (TORO root will be the last signature)
|
||||||
int m = 0;
|
int m = 0;
|
||||||
@@ -184,7 +184,7 @@ void optimizeTOROGraph(
|
|||||||
if(uContains(depthGraph, iter->second.from()) && uContains(depthGraph, iter->second.to()))
|
if(uContains(depthGraph, iter->second.from()) && uContains(depthGraph, iter->second.to()))
|
||||||
{
|
{
|
||||||
UASSERT(uContains(rtabmapToToro, iter->first) && uContains(rtabmapToToro, iter->second.to()));
|
UASSERT(uContains(rtabmapToToro, iter->first) && uContains(rtabmapToToro, iter->second.to()));
|
||||||
UASSERT(!iter->second.transform().isNull());
|
UASSERT_MSG(!iter->second.transform().isNull(), uFormat("Link from=%d to=%d", iter->first, iter->second.to()).c_str());
|
||||||
edgeConstraintsToro.insert(std::make_pair(rtabmapToToro.at(iter->first), Link(rtabmapToToro.at(iter->first), rtabmapToToro.at(iter->second.to()), iter->second.type(), iter->second.transform(), iter->second.rotVariance(), iter->second.transVariance())));
|
edgeConstraintsToro.insert(std::make_pair(rtabmapToToro.at(iter->first), Link(rtabmapToToro.at(iter->first), rtabmapToToro.at(iter->second.to()), iter->second.type(), iter->second.transform(), iter->second.rotVariance(), iter->second.transVariance())));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -225,12 +225,30 @@ void optimizeTOROGraph(
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
UERROR("No TORO poses and constraints!?");
|
if(edgeConstraintsToro.size() == 0)
|
||||||
|
{
|
||||||
|
UERROR("No TORO constraints!? (input poses=%d, links=%d, depthGraph=%d)",
|
||||||
|
(int)poses.size(), (int)links.size(), (int)depthGraph.size());
|
||||||
|
}
|
||||||
|
if(posesToro.size() == 0)
|
||||||
|
{
|
||||||
|
UERROR("No TORO poses!? (input poses=%d, links=%d, depthGraph=%d)",
|
||||||
|
(int)poses.size(), (int)links.size(), (int)depthGraph.size());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(links.size() == 0 && poses.size() == 1)
|
else if(depthGraph.size() == 1)
|
||||||
{
|
{
|
||||||
optimizedPoses = poses;
|
std::map<int, Transform>::const_iterator iter = poses.find(depthGraph.begin()->first);
|
||||||
|
if(iter != poses.end())
|
||||||
|
{
|
||||||
|
UASSERT_MSG(!iter->second.isNull(), uFormat("Poses should not be null! Id=%d", iter->first).c_str());
|
||||||
|
optimizedPoses.insert(*iter);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
UERROR("Pose %d from depthGraph not found in the poses map!", depthGraph.begin()->first);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -2614,7 +2614,8 @@ bool Memory::rehearsalMerge(int oldId, int newId)
|
|||||||
UERROR("Didn't find neighbor %d of %d in RAM...", link.to(), oldS->id());
|
UERROR("Didn't find neighbor %d of %d in RAM...", link.to(), oldS->id());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
newS->setLabel(oldS->getLabel());
|
||||||
|
oldS->setLabel("");
|
||||||
oldS->removeLinks(); // remove all links
|
oldS->removeLinks(); // remove all links
|
||||||
oldS->addLink(Link(oldS->id(), newS->id(), Link::kGlobalClosure, Transform(), 1.0f, 1.0f)); // to keep track of the merged location
|
oldS->addLink(Link(oldS->id(), newS->id(), Link::kGlobalClosure, Transform(), 1.0f, 1.0f)); // to keep track of the merged location
|
||||||
|
|
||||||
@@ -3840,7 +3841,10 @@ void Memory::getMetricConstraints(
|
|||||||
{
|
{
|
||||||
Transform pose;
|
Transform pose;
|
||||||
this->getPose(ids[i], pose, lookInDatabase);
|
this->getPose(ids[i], pose, lookInDatabase);
|
||||||
poses.insert(std::make_pair(ids[i], pose));
|
if(!pose.isNull())
|
||||||
|
{
|
||||||
|
poses.insert(std::make_pair(ids[i], pose));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for(unsigned int i=0; i<ids.size(); ++i)
|
for(unsigned int i=0; i<ids.size(); ++i)
|
||||||
@@ -3850,7 +3854,7 @@ void Memory::getMetricConstraints(
|
|||||||
std::map<int, Link> neighbors = this->getNeighborLinks(ids[i], lookInDatabase); // only direct neighbors
|
std::map<int, Link> neighbors = this->getNeighborLinks(ids[i], lookInDatabase); // only direct neighbors
|
||||||
for(std::map<int, Link>::iterator jter=neighbors.begin(); jter!=neighbors.end(); ++jter)
|
for(std::map<int, Link>::iterator jter=neighbors.begin(); jter!=neighbors.end(); ++jter)
|
||||||
{
|
{
|
||||||
if(uContains(poses, jter->first))
|
if(uContains(poses, jter->first) && jter->second.isValid())
|
||||||
{
|
{
|
||||||
bool edgeAlreadyAdded = false;
|
bool edgeAlreadyAdded = false;
|
||||||
for(std::multimap<int, Link>::iterator iter = links.lower_bound(jter->first);
|
for(std::multimap<int, Link>::iterator iter = links.lower_bound(jter->first);
|
||||||
@@ -3873,7 +3877,8 @@ void Memory::getMetricConstraints(
|
|||||||
for(std::map<int, Link>::iterator jter=loops.begin(); jter!=loops.end(); ++jter)
|
for(std::map<int, Link>::iterator jter=loops.begin(); jter!=loops.end(); ++jter)
|
||||||
{
|
{
|
||||||
if(jter->first < ids[i] &&
|
if(jter->first < ids[i] &&
|
||||||
uContains(poses, jter->first))
|
uContains(poses, jter->first) &&
|
||||||
|
jter->second.isValid()) // null transform means a child (rehearsed location)
|
||||||
{
|
{
|
||||||
links.insert(std::make_pair(ids[i],jter->second));
|
links.insert(std::make_pair(ids[i],jter->second));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -835,12 +835,23 @@ cv::Mat disparityFromStereoImages(
|
|||||||
const cv::Mat & rightImage)
|
const cv::Mat & rightImage)
|
||||||
{
|
{
|
||||||
UASSERT(!leftImage.empty() && !rightImage.empty() &&
|
UASSERT(!leftImage.empty() && !rightImage.empty() &&
|
||||||
leftImage.type() == CV_8UC1 && rightImage.type() == CV_8UC1 &&
|
(leftImage.type() == CV_8UC1 || leftImage.type() == CV_8UC3) && rightImage.type() == CV_8UC1 &&
|
||||||
leftImage.cols == rightImage.cols &&
|
leftImage.cols == rightImage.cols &&
|
||||||
leftImage.rows == rightImage.rows);
|
leftImage.rows == rightImage.rows);
|
||||||
|
|
||||||
|
cv::Mat leftMono;
|
||||||
|
if(leftImage.channels() == 3)
|
||||||
|
{
|
||||||
|
cv::cvtColor(leftImage, leftMono, CV_BGR2GRAY);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
leftMono = leftImage;
|
||||||
|
}
|
||||||
|
|
||||||
cv::StereoBM stereo(cv::StereoBM::BASIC_PRESET, 0, 15);
|
cv::StereoBM stereo(cv::StereoBM::BASIC_PRESET, 0, 15);
|
||||||
cv::Mat disparity;
|
cv::Mat disparity;
|
||||||
stereo(leftImage, rightImage, disparity, CV_16SC1);
|
stereo(leftMono, rightImage, disparity, CV_16SC1);
|
||||||
cv::filterSpeckles(disparity, 0, 1000, 16);
|
cv::filterSpeckles(disparity, 0, 1000, 16);
|
||||||
return disparity;
|
return disparity;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#include <QtCore/QMap>
|
#include <QtCore/QMap>
|
||||||
#include <QtCore/QSet>
|
#include <QtCore/QSet>
|
||||||
#include <QtCore/qnamespace.h>
|
#include <QtCore/qnamespace.h>
|
||||||
|
#include <QtCore/QSettings>
|
||||||
|
|
||||||
#include <opencv2/opencv.hpp>
|
#include <opencv2/opencv.hpp>
|
||||||
|
|
||||||
@@ -63,6 +64,9 @@ public:
|
|||||||
CloudViewer(QWidget * parent = 0);
|
CloudViewer(QWidget * parent = 0);
|
||||||
virtual ~CloudViewer();
|
virtual ~CloudViewer();
|
||||||
|
|
||||||
|
void saveSettings(QSettings & settings, const QString & group = "") const;
|
||||||
|
void loadSettings(QSettings & settings, const QString & group = "");
|
||||||
|
|
||||||
bool updateCloudPose(
|
bool updateCloudPose(
|
||||||
const std::string & id,
|
const std::string & id,
|
||||||
const Transform & pose); //including mesh
|
const Transform & pose); //including mesh
|
||||||
|
|||||||
@@ -53,6 +53,7 @@ namespace rtabmap
|
|||||||
class Memory;
|
class Memory;
|
||||||
class ImageView;
|
class ImageView;
|
||||||
class Signature;
|
class Signature;
|
||||||
|
class CloudViewer;
|
||||||
|
|
||||||
class RTABMAPGUI_EXP DatabaseViewer : public QMainWindow
|
class RTABMAPGUI_EXP DatabaseViewer : public QMainWindow
|
||||||
{
|
{
|
||||||
@@ -62,13 +63,18 @@ public:
|
|||||||
DatabaseViewer(QWidget * parent = 0);
|
DatabaseViewer(QWidget * parent = 0);
|
||||||
virtual ~DatabaseViewer();
|
virtual ~DatabaseViewer();
|
||||||
bool openDatabase(const QString & path);
|
bool openDatabase(const QString & path);
|
||||||
|
bool isSavedMaximized() const {return savedMaximized_;}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void showEvent(QShowEvent* anEvent);
|
virtual void showEvent(QShowEvent* anEvent);
|
||||||
|
virtual void moveEvent(QMoveEvent* anEvent);
|
||||||
virtual void resizeEvent(QResizeEvent* anEvent);
|
virtual void resizeEvent(QResizeEvent* anEvent);
|
||||||
virtual void closeEvent(QCloseEvent* event);
|
virtual void closeEvent(QCloseEvent* event);
|
||||||
|
virtual bool eventFilter(QObject *obj, QEvent *event);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
|
void writeSettings();
|
||||||
|
void configModified();
|
||||||
void openDatabase();
|
void openDatabase();
|
||||||
void generateGraph();
|
void generateGraph();
|
||||||
void exportDatabase();
|
void exportDatabase();
|
||||||
@@ -89,6 +95,7 @@ private slots:
|
|||||||
void sliderNeighborValueChanged(int);
|
void sliderNeighborValueChanged(int);
|
||||||
void sliderLoopValueChanged(int);
|
void sliderLoopValueChanged(int);
|
||||||
void sliderIterationsValueChanged(int);
|
void sliderIterationsValueChanged(int);
|
||||||
|
void updateGrid();
|
||||||
void updateGraphView();
|
void updateGraphView();
|
||||||
void refineConstraint();
|
void refineConstraint();
|
||||||
void refineConstraintVisually();
|
void refineConstraintVisually();
|
||||||
@@ -98,6 +105,9 @@ private slots:
|
|||||||
void updateConstraintView();
|
void updateConstraintView();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
QString getIniFilePath() const;
|
||||||
|
void readSettings();
|
||||||
|
|
||||||
void updateIds();
|
void updateIds();
|
||||||
void update(int value,
|
void update(int value,
|
||||||
QLabel * labelIndex,
|
QLabel * labelIndex,
|
||||||
@@ -107,6 +117,7 @@ private:
|
|||||||
QLabel * label,
|
QLabel * label,
|
||||||
QLabel * stamp,
|
QLabel * stamp,
|
||||||
rtabmap::ImageView * view,
|
rtabmap::ImageView * view,
|
||||||
|
rtabmap::CloudViewer * view3D,
|
||||||
QLabel * labelId,
|
QLabel * labelId,
|
||||||
bool updateConstraintView = true);
|
bool updateConstraintView = true);
|
||||||
void updateStereo(const Signature * data);
|
void updateStereo(const Signature * data);
|
||||||
@@ -145,7 +156,10 @@ private:
|
|||||||
std::multimap<int, rtabmap::Link> linksRefined_;
|
std::multimap<int, rtabmap::Link> linksRefined_;
|
||||||
std::multimap<int, rtabmap::Link> linksAdded_;
|
std::multimap<int, rtabmap::Link> linksAdded_;
|
||||||
std::multimap<int, rtabmap::Link> linksRemoved_;
|
std::multimap<int, rtabmap::Link> linksRemoved_;
|
||||||
std::map<int, pcl::PointCloud<pcl::PointXYZ>::Ptr > scans_;
|
std::map<int, std::pair<cv::Mat, cv::Mat> > localMaps_; // <ground, obstacles>
|
||||||
|
|
||||||
|
bool savedMaximized_;
|
||||||
|
bool firstCall_;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#include <QtGui/QGraphicsView>
|
#include <QtGui/QGraphicsView>
|
||||||
#include <QtCore/QRectF>
|
#include <QtCore/QRectF>
|
||||||
#include <QtCore/QMultiMap>
|
#include <QtCore/QMultiMap>
|
||||||
|
#include <QtCore/QSettings>
|
||||||
#include <opencv2/features2d/features2d.hpp>
|
#include <opencv2/features2d/features2d.hpp>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
@@ -51,6 +52,9 @@ public:
|
|||||||
ImageView(QWidget * parent = 0);
|
ImageView(QWidget * parent = 0);
|
||||||
virtual ~ImageView();
|
virtual ~ImageView();
|
||||||
|
|
||||||
|
void saveSettings(QSettings & settings, const QString & group = "") const;
|
||||||
|
void loadSettings(QSettings & settings, const QString & group = "");
|
||||||
|
|
||||||
void resetZoom();
|
void resetZoom();
|
||||||
|
|
||||||
bool isImageShown() const;
|
bool isImageShown() const;
|
||||||
|
|||||||
@@ -298,6 +298,8 @@ private:
|
|||||||
|
|
||||||
QVector<int> _refIds;
|
QVector<int> _refIds;
|
||||||
QVector<int> _loopClosureIds;
|
QVector<int> _loopClosureIds;
|
||||||
|
|
||||||
|
bool _firstCall;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#include <QtGui/QWheelEvent>
|
#include <QtGui/QWheelEvent>
|
||||||
#include <QtGui/QKeyEvent>
|
#include <QtGui/QKeyEvent>
|
||||||
#include <QtGui/QColorDialog>
|
#include <QtGui/QColorDialog>
|
||||||
|
#include <QtGui/QVector3D>
|
||||||
#include <set>
|
#include <set>
|
||||||
|
|
||||||
#include <vtkRenderWindow.h>
|
#include <vtkRenderWindow.h>
|
||||||
@@ -159,6 +160,92 @@ void CloudViewer::createMenu()
|
|||||||
_menu->addAction(_aSetBackgroundColor);
|
_menu->addAction(_aSetBackgroundColor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CloudViewer::saveSettings(QSettings & settings, const QString & group) const
|
||||||
|
{
|
||||||
|
if(!group.isEmpty())
|
||||||
|
{
|
||||||
|
settings.beginGroup(group);
|
||||||
|
}
|
||||||
|
|
||||||
|
float poseX, poseY, poseZ, focalX, focalY, focalZ, upX, upY, upZ;
|
||||||
|
this->getCameraPosition(poseX, poseY, poseZ, focalX, focalY, focalZ, upX, upY, upZ);
|
||||||
|
QVector3D pose(poseX, poseY, poseZ);
|
||||||
|
QVector3D focal(focalX, focalY, focalZ);
|
||||||
|
if(!this->isCameraFree())
|
||||||
|
{
|
||||||
|
// make camera position relative to target
|
||||||
|
Transform T = this->getTargetPose();
|
||||||
|
if(this->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());
|
||||||
|
}
|
||||||
|
settings.setValue("camera_pose", pose);
|
||||||
|
settings.setValue("camera_focal", focal);
|
||||||
|
settings.setValue("camera_up", QVector3D(upX, upY, upZ));
|
||||||
|
|
||||||
|
settings.setValue("grid", this->isGridShown());
|
||||||
|
settings.setValue("grid_cell_count", this->getGridCellCount());
|
||||||
|
settings.setValue("grid_cell_size", this->getGridCellSize());
|
||||||
|
|
||||||
|
settings.setValue("trajectory_shown", this->isTrajectoryShown());
|
||||||
|
settings.setValue("trajectory_size", this->getTrajectorySize());
|
||||||
|
|
||||||
|
settings.setValue("camera_target_locked", this->isCameraTargetLocked());
|
||||||
|
settings.setValue("camera_target_follow", this->isCameraTargetFollow());
|
||||||
|
settings.setValue("camera_free", this->isCameraFree());
|
||||||
|
settings.setValue("camera_lockZ", this->isCameraLockZ());
|
||||||
|
|
||||||
|
settings.setValue("bg_color", this->getBackgroundColor());
|
||||||
|
if(!group.isEmpty())
|
||||||
|
{
|
||||||
|
settings.endGroup();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CloudViewer::loadSettings(QSettings & settings, const QString & group)
|
||||||
|
{
|
||||||
|
if(!group.isEmpty())
|
||||||
|
{
|
||||||
|
settings.beginGroup(group);
|
||||||
|
}
|
||||||
|
|
||||||
|
float poseX, poseY, poseZ, focalX, focalY, focalZ, upX, upY, upZ;
|
||||||
|
this->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>();
|
||||||
|
this->setCameraPosition(pose.x(),pose.y(),pose.z(), focal.x(),focal.y(),focal.z(), up.x(),up.y(),up.z());
|
||||||
|
|
||||||
|
this->setGridShown(settings.value("grid", this->isGridShown()).toBool());
|
||||||
|
this->setGridCellCount(settings.value("grid_cell_count", this->getGridCellCount()).toUInt());
|
||||||
|
this->setGridCellSize(settings.value("grid_cell_size", this->getGridCellSize()).toFloat());
|
||||||
|
|
||||||
|
this->setTrajectoryShown(settings.value("trajectory_shown", this->isTrajectoryShown()).toBool());
|
||||||
|
this->setTrajectorySize(settings.value("trajectory_size", this->getTrajectorySize()).toUInt());
|
||||||
|
|
||||||
|
this->setCameraTargetLocked(settings.value("camera_target_locked", this->isCameraTargetLocked()).toBool());
|
||||||
|
this->setCameraTargetFollow(settings.value("camera_target_follow", this->isCameraTargetFollow()).toBool());
|
||||||
|
if(settings.value("camera_free", this->isCameraFree()).toBool())
|
||||||
|
{
|
||||||
|
this->setCameraFree();
|
||||||
|
}
|
||||||
|
this->setCameraLockZ(settings.value("camera_lockZ", this->isCameraLockZ()).toBool());
|
||||||
|
|
||||||
|
this->setBackgroundColor(settings.value("bg_color", this->getBackgroundColor()).value<QColor>());
|
||||||
|
if(!group.isEmpty())
|
||||||
|
{
|
||||||
|
settings.endGroup();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool CloudViewer::updateCloudPose(
|
bool CloudViewer::updateCloudPose(
|
||||||
const std::string & id,
|
const std::string & id,
|
||||||
const Transform & pose)
|
const Transform & pose)
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#include <QtCore/QBuffer>
|
#include <QtCore/QBuffer>
|
||||||
#include <QtCore/QTextStream>
|
#include <QtCore/QTextStream>
|
||||||
#include <QtCore/QDateTime>
|
#include <QtCore/QDateTime>
|
||||||
|
#include <QtCore/QSettings>
|
||||||
#include <rtabmap/utilite/ULogger.h>
|
#include <rtabmap/utilite/ULogger.h>
|
||||||
#include <rtabmap/utilite/UDirectory.h>
|
#include <rtabmap/utilite/UDirectory.h>
|
||||||
#include <rtabmap/utilite/UConversion.h>
|
#include <rtabmap/utilite/UConversion.h>
|
||||||
@@ -65,7 +66,9 @@ namespace rtabmap {
|
|||||||
|
|
||||||
DatabaseViewer::DatabaseViewer(QWidget * parent) :
|
DatabaseViewer::DatabaseViewer(QWidget * parent) :
|
||||||
QMainWindow(parent),
|
QMainWindow(parent),
|
||||||
memory_(0)
|
memory_(0),
|
||||||
|
savedMaximized_(false),
|
||||||
|
firstCall_(true)
|
||||||
{
|
{
|
||||||
pathDatabase_ = QDir::homePath()+"/Documents/RTAB-Map"; //use home directory by default
|
pathDatabase_ = QDir::homePath()+"/Documents/RTAB-Map"; //use home directory by default
|
||||||
|
|
||||||
@@ -77,24 +80,34 @@ DatabaseViewer::DatabaseViewer(QWidget * parent) :
|
|||||||
ui_ = new Ui_DatabaseViewer();
|
ui_ = new Ui_DatabaseViewer();
|
||||||
ui_->setupUi(this);
|
ui_->setupUi(this);
|
||||||
|
|
||||||
|
QString title("RTAB-Map Database Viewer[*]");
|
||||||
|
this->setWindowTitle(title);
|
||||||
|
|
||||||
ui_->dockWidget_constraints->setVisible(false);
|
ui_->dockWidget_constraints->setVisible(false);
|
||||||
ui_->dockWidget_graphView->setVisible(false);
|
ui_->dockWidget_graphView->setVisible(false);
|
||||||
ui_->dockWidget_icp->setVisible(false);
|
ui_->dockWidget_icp->setVisible(false);
|
||||||
ui_->dockWidget_visual->setVisible(false);
|
ui_->dockWidget_visual->setVisible(false);
|
||||||
ui_->dockWidget_stereoView->setVisible(false);
|
ui_->dockWidget_stereoView->setVisible(false);
|
||||||
ui_->dockWidget_icp->setFloating(true);
|
ui_->dockWidget_view3d->setVisible(false);
|
||||||
ui_->dockWidget_visual->setFloating(true);
|
|
||||||
|
ui_->constraintsViewer->setCameraLockZ(false);
|
||||||
|
ui_->constraintsViewer->setCameraFree();
|
||||||
|
|
||||||
|
this->readSettings();
|
||||||
|
|
||||||
ui_->menuView->addAction(ui_->dockWidget_constraints->toggleViewAction());
|
ui_->menuView->addAction(ui_->dockWidget_constraints->toggleViewAction());
|
||||||
ui_->menuView->addAction(ui_->dockWidget_graphView->toggleViewAction());
|
ui_->menuView->addAction(ui_->dockWidget_graphView->toggleViewAction());
|
||||||
ui_->menuView->addAction(ui_->dockWidget_icp->toggleViewAction());
|
ui_->menuView->addAction(ui_->dockWidget_icp->toggleViewAction());
|
||||||
ui_->menuView->addAction(ui_->dockWidget_visual->toggleViewAction());
|
ui_->menuView->addAction(ui_->dockWidget_visual->toggleViewAction());
|
||||||
ui_->menuView->addAction(ui_->dockWidget_stereoView->toggleViewAction());
|
ui_->menuView->addAction(ui_->dockWidget_stereoView->toggleViewAction());
|
||||||
|
ui_->menuView->addAction(ui_->dockWidget_view3d->toggleViewAction());
|
||||||
connect(ui_->dockWidget_graphView->toggleViewAction(), SIGNAL(triggered()), this, SLOT(updateGraphView()));
|
connect(ui_->dockWidget_graphView->toggleViewAction(), SIGNAL(triggered()), this, SLOT(updateGraphView()));
|
||||||
|
|
||||||
connect(ui_->actionQuit, SIGNAL(triggered()), this, SLOT(close()));
|
connect(ui_->actionQuit, SIGNAL(triggered()), this, SLOT(close()));
|
||||||
connect(ui_->buttonBox, SIGNAL(rejected()), this, SLOT(close()));
|
|
||||||
|
|
||||||
// connect actions with custom slots
|
// connect actions with custom slots
|
||||||
|
ui_->actionSave_config->setShortcut(QKeySequence::Save);
|
||||||
|
connect(ui_->actionSave_config, SIGNAL(triggered()), this, SLOT(writeSettings()));
|
||||||
connect(ui_->actionOpen_database, SIGNAL(triggered()), this, SLOT(openDatabase()));
|
connect(ui_->actionOpen_database, SIGNAL(triggered()), this, SLOT(openDatabase()));
|
||||||
connect(ui_->actionExport, SIGNAL(triggered()), this, SLOT(exportDatabase()));
|
connect(ui_->actionExport, SIGNAL(triggered()), this, SLOT(exportDatabase()));
|
||||||
connect(ui_->actionExtract_images, SIGNAL(triggered()), this, SLOT(extractImages()));
|
connect(ui_->actionExtract_images, SIGNAL(triggered()), this, SLOT(extractImages()));
|
||||||
@@ -144,16 +157,65 @@ DatabaseViewer::DatabaseViewer(QWidget * parent) :
|
|||||||
ui_->checkBox_showOptimized->setEnabled(false);
|
ui_->checkBox_showOptimized->setEnabled(false);
|
||||||
|
|
||||||
ui_->horizontalSlider_iterations->setTracking(false);
|
ui_->horizontalSlider_iterations->setTracking(false);
|
||||||
ui_->dockWidget_graphView->setEnabled(false);
|
ui_->horizontalSlider_iterations->setEnabled(false);
|
||||||
|
ui_->spinBox_optimizationsFrom->setEnabled(false);
|
||||||
connect(ui_->horizontalSlider_iterations, SIGNAL(valueChanged(int)), this, SLOT(sliderIterationsValueChanged(int)));
|
connect(ui_->horizontalSlider_iterations, SIGNAL(valueChanged(int)), this, SLOT(sliderIterationsValueChanged(int)));
|
||||||
connect(ui_->horizontalSlider_iterations, SIGNAL(sliderMoved(int)), this, SLOT(sliderIterationsValueChanged(int)));
|
connect(ui_->horizontalSlider_iterations, SIGNAL(sliderMoved(int)), this, SLOT(sliderIterationsValueChanged(int)));
|
||||||
connect(ui_->spinBox_iterations, SIGNAL(editingFinished()), this, SLOT(updateGraphView()));
|
connect(ui_->spinBox_iterations, SIGNAL(editingFinished()), this, SLOT(updateGraphView()));
|
||||||
connect(ui_->spinBox_optimizationsFrom, SIGNAL(valueChanged(int)), this, SLOT(updateGraphView()));
|
connect(ui_->spinBox_optimizationsFrom, SIGNAL(valueChanged(int)), this, SLOT(updateGraphView()));
|
||||||
connect(ui_->checkBox_initGuess, SIGNAL(stateChanged(int)), this, SLOT(updateGraphView()));
|
connect(ui_->checkBox_initGuess, SIGNAL(stateChanged(int)), this, SLOT(updateGraphView()));
|
||||||
connect(ui_->checkBox_ignoreCovariance, SIGNAL(stateChanged(int)), this, SLOT(updateGraphView()));
|
connect(ui_->checkBox_ignoreCovariance, SIGNAL(stateChanged(int)), this, SLOT(updateGraphView()));
|
||||||
|
connect(ui_->checkBox_gridFromProjection, SIGNAL(stateChanged(int)), this, SLOT(updateGrid()));
|
||||||
|
connect(ui_->doubleSpinBox_gridCellSize, SIGNAL(editingFinished()), this, SLOT(updateGrid()));
|
||||||
|
connect(ui_->spinBox_projDecimation, SIGNAL(editingFinished()), this, SLOT(updateGrid()));
|
||||||
|
connect(ui_->doubleSpinBox_projMaxDepth, SIGNAL(editingFinished()), this, SLOT(updateGrid()));
|
||||||
|
|
||||||
ui_->constraintsViewer->setCameraLockZ(false);
|
// connect configuration changed
|
||||||
ui_->constraintsViewer->setCameraFree();
|
connect(ui_->graphViewer, SIGNAL(configChanged()), this, SLOT(configModified()));
|
||||||
|
//connect(ui_->graphicsView_A, SIGNAL(configChanged()), this, SLOT(configModified()));
|
||||||
|
//connect(ui_->graphicsView_B, SIGNAL(configChanged()), this, SLOT(configModified()));
|
||||||
|
// Graph view
|
||||||
|
connect(ui_->spinBox_iterations, SIGNAL(valueChanged(int)), this, SLOT(configModified()));
|
||||||
|
connect(ui_->checkBox_initGuess, SIGNAL(stateChanged(int)), this, SLOT(configModified()));
|
||||||
|
connect(ui_->checkBox_ignoreCovariance, SIGNAL(stateChanged(int)), this, SLOT(configModified()));
|
||||||
|
connect(ui_->checkBox_gridFromProjection, SIGNAL(stateChanged(int)), this, SLOT(configModified()));
|
||||||
|
connect(ui_->doubleSpinBox_gridCellSize, SIGNAL(valueChanged(double)), this, SLOT(configModified()));
|
||||||
|
connect(ui_->spinBox_projDecimation, SIGNAL(valueChanged(int)), this, SLOT(configModified()));
|
||||||
|
connect(ui_->doubleSpinBox_projMaxDepth, SIGNAL(valueChanged(double)), this, SLOT(configModified()));
|
||||||
|
// ICP parameters
|
||||||
|
connect(ui_->spinBox_icp_decimation, SIGNAL(valueChanged(int)), this, SLOT(configModified()));
|
||||||
|
connect(ui_->doubleSpinBox_icp_maxDepth, SIGNAL(valueChanged(double)), this, SLOT(configModified()));
|
||||||
|
connect(ui_->doubleSpinBox_icp_voxel, SIGNAL(valueChanged(double)), this, SLOT(configModified()));
|
||||||
|
connect(ui_->doubleSpinBox_icp_maxCorrespDistance, SIGNAL(valueChanged(double)), this, SLOT(configModified()));
|
||||||
|
connect(ui_->spinBox_icp_iteration, SIGNAL(valueChanged(int)), this, SLOT(configModified()));
|
||||||
|
connect(ui_->checkBox_icp_p2plane, SIGNAL(stateChanged(int)), this, SLOT(configModified()));
|
||||||
|
connect(ui_->spinBox_icp_normalKSearch, SIGNAL(valueChanged(int)), this, SLOT(configModified()));
|
||||||
|
connect(ui_->checkBox_icp_2d, SIGNAL(stateChanged(int)), this, SLOT(configModified()));
|
||||||
|
// Visual parameters
|
||||||
|
connect(ui_->checkBox_visual_recomputeFeatures, SIGNAL(stateChanged(int)), this, SLOT(configModified()));
|
||||||
|
connect(ui_->checkBox_visual_2d, SIGNAL(stateChanged(int)), this, SLOT(configModified()));
|
||||||
|
connect(ui_->doubleSpinBox_visual_hessian, SIGNAL(valueChanged(double)), this, SLOT(configModified()));
|
||||||
|
connect(ui_->doubleSpinBox_visual_nndr, SIGNAL(valueChanged(double)), this, SLOT(configModified()));
|
||||||
|
connect(ui_->spinBox_visual_minCorrespondences, SIGNAL(valueChanged(int)), this, SLOT(configModified()));
|
||||||
|
connect(ui_->doubleSpinBox_visual_maxCorrespDistance, SIGNAL(valueChanged(double)), this, SLOT(configModified()));
|
||||||
|
connect(ui_->spinBox_visual_iteration, SIGNAL(valueChanged(int)), this, SLOT(configModified()));
|
||||||
|
connect(ui_->doubleSpinBox_visual_maxDepth, SIGNAL(valueChanged(double)), this, SLOT(configModified()));
|
||||||
|
connect(ui_->doubleSpinBox_detectMore_radius, SIGNAL(valueChanged(double)), this, SLOT(configModified()));
|
||||||
|
connect(ui_->doubleSpinBox_detectMore_angle, SIGNAL(valueChanged(double)), this, SLOT(configModified()));
|
||||||
|
connect(ui_->spinBox_detectMore_iterations, SIGNAL(valueChanged(int)), this, SLOT(configModified()));
|
||||||
|
// dockwidget
|
||||||
|
QList<QDockWidget*> dockWidgets = this->findChildren<QDockWidget*>();
|
||||||
|
for(int i=0; i<dockWidgets.size(); ++i)
|
||||||
|
{
|
||||||
|
connect(dockWidgets[i], SIGNAL(dockLocationChanged(Qt::DockWidgetArea)), this, SLOT(configModified()));
|
||||||
|
connect(dockWidgets[i]->toggleViewAction(), SIGNAL(toggled(bool)), this, SLOT(configModified()));
|
||||||
|
}
|
||||||
|
ui_->dockWidget_constraints->installEventFilter(this);
|
||||||
|
ui_->dockWidget_graphView->installEventFilter(this);
|
||||||
|
ui_->dockWidget_icp->installEventFilter(this);
|
||||||
|
ui_->dockWidget_stereoView->installEventFilter(this);
|
||||||
|
ui_->dockWidget_visual->installEventFilter(this);
|
||||||
|
ui_->dockWidget_view3d->installEventFilter(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
DatabaseViewer::~DatabaseViewer()
|
DatabaseViewer::~DatabaseViewer()
|
||||||
@@ -165,6 +227,150 @@ DatabaseViewer::~DatabaseViewer()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DatabaseViewer::configModified()
|
||||||
|
{
|
||||||
|
this->setWindowModified(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString DatabaseViewer::getIniFilePath() const
|
||||||
|
{
|
||||||
|
QString privatePath = QDir::homePath() + "/.rtabmap";
|
||||||
|
if(!QDir(privatePath).exists())
|
||||||
|
{
|
||||||
|
QDir::home().mkdir(".rtabmap");
|
||||||
|
}
|
||||||
|
return privatePath + "/dbviewer.ini";
|
||||||
|
}
|
||||||
|
|
||||||
|
void DatabaseViewer::readSettings()
|
||||||
|
{
|
||||||
|
QString path = getIniFilePath();
|
||||||
|
QSettings settings(path, QSettings::IniFormat);
|
||||||
|
settings.beginGroup("DatabaseViewer");
|
||||||
|
|
||||||
|
//load window state / geometry
|
||||||
|
QByteArray bytes;
|
||||||
|
bytes = settings.value("geometry", QByteArray()).toByteArray();
|
||||||
|
if(!bytes.isEmpty())
|
||||||
|
{
|
||||||
|
this->restoreGeometry(bytes);
|
||||||
|
}
|
||||||
|
bytes = settings.value("state", QByteArray()).toByteArray();
|
||||||
|
if(!bytes.isEmpty())
|
||||||
|
{
|
||||||
|
this->restoreState(bytes);
|
||||||
|
}
|
||||||
|
savedMaximized_ = settings.value("maximized", false).toBool();
|
||||||
|
|
||||||
|
// GraphViewer settings
|
||||||
|
settings.beginGroup("GraphView");
|
||||||
|
ui_->graphViewer->loadSettings(settings);
|
||||||
|
ui_->spinBox_iterations->setValue(settings.value("iterations", ui_->spinBox_iterations->value()).toInt());
|
||||||
|
ui_->checkBox_initGuess->setChecked(settings.value("initGuess", ui_->checkBox_initGuess->isChecked()).toBool());
|
||||||
|
ui_->checkBox_ignoreCovariance->setChecked(settings.value("ignoreCovariance", ui_->checkBox_ignoreCovariance->isChecked()).toBool());
|
||||||
|
ui_->checkBox_gridFromProjection->setChecked(settings.value("gridFromProj", ui_->checkBox_gridFromProjection->isChecked()).toBool());
|
||||||
|
ui_->doubleSpinBox_gridCellSize->setValue(settings.value("gridCellSize", ui_->doubleSpinBox_gridCellSize->value()).toDouble());
|
||||||
|
ui_->spinBox_projDecimation->setValue(settings.value("projDecimation", ui_->spinBox_projDecimation->value()).toInt());
|
||||||
|
ui_->doubleSpinBox_projMaxDepth->setValue(settings.value("projMaxDepth", ui_->doubleSpinBox_projMaxDepth->value()).toDouble());
|
||||||
|
settings.endGroup();
|
||||||
|
|
||||||
|
// ImageViews
|
||||||
|
//ui_->graphicsView_A->loadSettings(settings, "ImageViewA");
|
||||||
|
//ui_->graphicsView_B->loadSettings(settings, "ImageViewB");
|
||||||
|
|
||||||
|
// ICP parameters
|
||||||
|
settings.beginGroup("icp");
|
||||||
|
ui_->spinBox_icp_decimation->setValue(settings.value("decimation", ui_->spinBox_icp_decimation->value()).toInt());
|
||||||
|
ui_->doubleSpinBox_icp_maxDepth->setValue(settings.value("maxDepth", ui_->doubleSpinBox_icp_maxDepth->value()).toDouble());
|
||||||
|
ui_->doubleSpinBox_icp_voxel->setValue(settings.value("voxel", ui_->doubleSpinBox_icp_voxel->value()).toDouble());
|
||||||
|
ui_->doubleSpinBox_icp_maxCorrespDistance->setValue(settings.value("maxCorrDist", ui_->doubleSpinBox_icp_maxCorrespDistance->value()).toDouble());
|
||||||
|
ui_->spinBox_icp_iteration->setValue(settings.value("iterations", ui_->spinBox_icp_iteration->value()).toInt());
|
||||||
|
ui_->checkBox_icp_p2plane->setChecked(settings.value("point2place", ui_->checkBox_icp_p2plane->isChecked()).toBool());
|
||||||
|
ui_->spinBox_icp_normalKSearch->setValue(settings.value("normalKSearch", ui_->spinBox_icp_normalKSearch->value()).toInt());
|
||||||
|
ui_->checkBox_icp_2d->setChecked(settings.value("icp2d", ui_->checkBox_icp_2d->isChecked()).toBool());
|
||||||
|
settings.endGroup();
|
||||||
|
|
||||||
|
// Visual parameters
|
||||||
|
settings.beginGroup("visual");
|
||||||
|
ui_->checkBox_visual_recomputeFeatures->setChecked(settings.value("reextract", ui_->checkBox_visual_recomputeFeatures->isChecked()).toBool());
|
||||||
|
ui_->checkBox_visual_2d->setChecked(settings.value("force2d", ui_->checkBox_visual_2d->isChecked()).toBool());
|
||||||
|
ui_->doubleSpinBox_visual_hessian->setValue(settings.value("hessian", ui_->doubleSpinBox_visual_hessian->value()).toDouble());
|
||||||
|
ui_->doubleSpinBox_visual_nndr->setValue(settings.value("nndr", ui_->doubleSpinBox_visual_nndr->value()).toDouble());
|
||||||
|
ui_->spinBox_visual_minCorrespondences->setValue(settings.value("minCorr", ui_->spinBox_visual_minCorrespondences->value()).toInt());
|
||||||
|
ui_->doubleSpinBox_visual_maxCorrespDistance->setValue(settings.value("maxCorrDist", ui_->doubleSpinBox_visual_maxCorrespDistance->value()).toDouble());
|
||||||
|
ui_->spinBox_visual_iteration->setValue(settings.value("iterations", ui_->spinBox_visual_iteration->value()).toDouble());
|
||||||
|
ui_->doubleSpinBox_visual_maxDepth->setValue(settings.value("maxDepth", ui_->doubleSpinBox_visual_maxDepth->value()).toDouble());
|
||||||
|
ui_->doubleSpinBox_detectMore_radius->setValue(settings.value("detectMoreRadius", ui_->doubleSpinBox_detectMore_radius->value()).toDouble());
|
||||||
|
ui_->doubleSpinBox_detectMore_angle->setValue(settings.value("detectMoreAngle", ui_->doubleSpinBox_detectMore_angle->value()).toDouble());
|
||||||
|
ui_->spinBox_detectMore_iterations->setValue(settings.value("detectMoreIterations", ui_->spinBox_detectMore_iterations->value()).toInt());
|
||||||
|
settings.endGroup();
|
||||||
|
|
||||||
|
settings.endGroup(); // DatabaseViewer
|
||||||
|
}
|
||||||
|
|
||||||
|
void DatabaseViewer::writeSettings()
|
||||||
|
{
|
||||||
|
QString path = getIniFilePath();
|
||||||
|
QSettings settings(path, QSettings::IniFormat);
|
||||||
|
settings.beginGroup("DatabaseViewer");
|
||||||
|
|
||||||
|
//save window state / geometry
|
||||||
|
if(!this->isMaximized())
|
||||||
|
{
|
||||||
|
settings.setValue("geometry", this->saveGeometry());
|
||||||
|
}
|
||||||
|
settings.setValue("state", this->saveState());
|
||||||
|
settings.setValue("maximized", this->isMaximized());
|
||||||
|
savedMaximized_ = this->isMaximized();
|
||||||
|
|
||||||
|
// save GraphViewer settings
|
||||||
|
settings.beginGroup("GraphView");
|
||||||
|
ui_->graphViewer->saveSettings(settings);
|
||||||
|
settings.setValue("iterations", ui_->spinBox_iterations->value());
|
||||||
|
settings.setValue("initGuess", ui_->checkBox_initGuess->isChecked());
|
||||||
|
settings.setValue("ignoreCovariance", ui_->checkBox_ignoreCovariance->isChecked());
|
||||||
|
settings.setValue("gridFromProj", ui_->checkBox_gridFromProjection->isChecked());
|
||||||
|
settings.setValue("gridCellSize", ui_->doubleSpinBox_gridCellSize->value());
|
||||||
|
settings.setValue("projDecimation", ui_->spinBox_projDecimation->value());
|
||||||
|
settings.setValue("projMaxDepth", ui_->doubleSpinBox_projMaxDepth->value());
|
||||||
|
settings.endGroup();
|
||||||
|
|
||||||
|
// ImageViews
|
||||||
|
//ui_->graphicsView_A->saveSettings(settings, "ImageViewA");
|
||||||
|
//ui_->graphicsView_B->saveSettings(settings, "ImageViewB");
|
||||||
|
|
||||||
|
// save ICP parameters
|
||||||
|
settings.beginGroup("icp");
|
||||||
|
settings.setValue("decimation", ui_->spinBox_icp_decimation->value());
|
||||||
|
settings.setValue("maxDepth", ui_->doubleSpinBox_icp_maxDepth->value());
|
||||||
|
settings.setValue("voxel", ui_->doubleSpinBox_icp_voxel->value());
|
||||||
|
settings.setValue("maxCorrDist", ui_->doubleSpinBox_icp_maxCorrespDistance->value());
|
||||||
|
settings.setValue("iterations", ui_->spinBox_icp_iteration->value());
|
||||||
|
settings.setValue("point2place", ui_->checkBox_icp_p2plane->isChecked());
|
||||||
|
settings.setValue("normalKSearch", ui_->spinBox_icp_normalKSearch->value());
|
||||||
|
settings.setValue("icp2d", ui_->checkBox_icp_2d->isChecked());
|
||||||
|
settings.endGroup();
|
||||||
|
|
||||||
|
// save Visual parameters
|
||||||
|
settings.beginGroup("visual");
|
||||||
|
settings.setValue("reextract", ui_->checkBox_visual_recomputeFeatures->isChecked());
|
||||||
|
settings.setValue("force2d", ui_->checkBox_visual_2d->isChecked());
|
||||||
|
settings.setValue("hessian", ui_->doubleSpinBox_visual_hessian->value());
|
||||||
|
settings.setValue("nndr", ui_->doubleSpinBox_visual_nndr->value());
|
||||||
|
settings.setValue("minCorr", ui_->spinBox_visual_minCorrespondences->value());
|
||||||
|
settings.setValue("maxCorrDist", ui_->doubleSpinBox_visual_maxCorrespDistance->value());
|
||||||
|
settings.setValue("iterations", ui_->spinBox_visual_iteration->value());
|
||||||
|
settings.setValue("maxDepth", ui_->doubleSpinBox_visual_maxDepth->value());
|
||||||
|
settings.setValue("detectMoreRadius", ui_->doubleSpinBox_detectMore_radius->value());
|
||||||
|
settings.setValue("detectMoreAngle", ui_->doubleSpinBox_detectMore_angle->value());
|
||||||
|
settings.setValue("detectMoreIterations", ui_->spinBox_detectMore_iterations->value());
|
||||||
|
settings.endGroup();
|
||||||
|
|
||||||
|
settings.endGroup(); // DatabaseViewer
|
||||||
|
|
||||||
|
this->setWindowModified(false);
|
||||||
|
}
|
||||||
|
|
||||||
void DatabaseViewer::openDatabase()
|
void DatabaseViewer::openDatabase()
|
||||||
{
|
{
|
||||||
QString path = QFileDialog::getOpenFileName(this, tr("Select file"), pathDatabase_, tr("Databases (*.db)"));
|
QString path = QFileDialog::getOpenFileName(this, tr("Select file"), pathDatabase_, tr("Databases (*.db)"));
|
||||||
@@ -193,7 +399,7 @@ bool DatabaseViewer::openDatabase(const QString & path)
|
|||||||
linksAdded_.clear();
|
linksAdded_.clear();
|
||||||
linksRefined_.clear();
|
linksRefined_.clear();
|
||||||
linksRemoved_.clear();
|
linksRemoved_.clear();
|
||||||
scans_.clear();
|
localMaps_.clear();
|
||||||
ui_->actionGenerate_TORO_graph_graph->setEnabled(false);
|
ui_->actionGenerate_TORO_graph_graph->setEnabled(false);
|
||||||
ui_->checkBox_showOptimized->setEnabled(false);
|
ui_->checkBox_showOptimized->setEnabled(false);
|
||||||
}
|
}
|
||||||
@@ -228,6 +434,30 @@ bool DatabaseViewer::openDatabase(const QString & path)
|
|||||||
|
|
||||||
void DatabaseViewer::closeEvent(QCloseEvent* event)
|
void DatabaseViewer::closeEvent(QCloseEvent* event)
|
||||||
{
|
{
|
||||||
|
//write settings before quit?
|
||||||
|
bool save = false;
|
||||||
|
if(this->isWindowModified())
|
||||||
|
{
|
||||||
|
QMessageBox::Button b=QMessageBox::question(this,
|
||||||
|
tr("Database Viewer"),
|
||||||
|
tr("There are unsaved changed settings. Save them?"),
|
||||||
|
QMessageBox::Save | QMessageBox::Cancel | QMessageBox::Discard);
|
||||||
|
if(b == QMessageBox::Save)
|
||||||
|
{
|
||||||
|
save = true;
|
||||||
|
}
|
||||||
|
else if(b != QMessageBox::Discard)
|
||||||
|
{
|
||||||
|
event->ignore();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(save)
|
||||||
|
{
|
||||||
|
writeSettings();
|
||||||
|
}
|
||||||
|
|
||||||
if(linksAdded_.size() || linksRefined_.size() || linksRemoved_.size())
|
if(linksAdded_.size() || linksRefined_.size() || linksRemoved_.size())
|
||||||
{
|
{
|
||||||
QMessageBox::StandardButton button = QMessageBox::question(this,
|
QMessageBox::StandardButton button = QMessageBox::question(this,
|
||||||
@@ -316,6 +546,21 @@ void DatabaseViewer::showEvent(QShowEvent* anEvent)
|
|||||||
ui_->graphicsView_B->fitInView(ui_->graphicsView_B->sceneRect(), Qt::KeepAspectRatio);
|
ui_->graphicsView_B->fitInView(ui_->graphicsView_B->sceneRect(), Qt::KeepAspectRatio);
|
||||||
ui_->graphicsView_A->resetZoom();
|
ui_->graphicsView_A->resetZoom();
|
||||||
ui_->graphicsView_B->resetZoom();
|
ui_->graphicsView_B->resetZoom();
|
||||||
|
|
||||||
|
this->setWindowModified(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DatabaseViewer::moveEvent(QMoveEvent* anEvent)
|
||||||
|
{
|
||||||
|
if(this->isVisible())
|
||||||
|
{
|
||||||
|
// HACK, there is a move event when the window is shown the first time.
|
||||||
|
if(!firstCall_)
|
||||||
|
{
|
||||||
|
this->configModified();
|
||||||
|
}
|
||||||
|
firstCall_ = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DatabaseViewer::resizeEvent(QResizeEvent* anEvent)
|
void DatabaseViewer::resizeEvent(QResizeEvent* anEvent)
|
||||||
@@ -324,6 +569,19 @@ void DatabaseViewer::resizeEvent(QResizeEvent* anEvent)
|
|||||||
ui_->graphicsView_B->fitInView(ui_->graphicsView_B->sceneRect(), Qt::KeepAspectRatio);
|
ui_->graphicsView_B->fitInView(ui_->graphicsView_B->sceneRect(), Qt::KeepAspectRatio);
|
||||||
ui_->graphicsView_A->resetZoom();
|
ui_->graphicsView_A->resetZoom();
|
||||||
ui_->graphicsView_B->resetZoom();
|
ui_->graphicsView_B->resetZoom();
|
||||||
|
if(this->isVisible())
|
||||||
|
{
|
||||||
|
this->configModified();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DatabaseViewer::eventFilter(QObject *obj, QEvent *event)
|
||||||
|
{
|
||||||
|
if (event->type() == QEvent::Resize && qobject_cast<QDockWidget*>(obj))
|
||||||
|
{
|
||||||
|
this->setWindowModified(true);
|
||||||
|
}
|
||||||
|
return QWidget::eventFilter(obj, event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -422,6 +680,8 @@ void DatabaseViewer::updateIds()
|
|||||||
linksRemoved_.clear();
|
linksRemoved_.clear();
|
||||||
if(memory_->getLastWorkingSignature())
|
if(memory_->getLastWorkingSignature())
|
||||||
{
|
{
|
||||||
|
//get constraints only for parent links
|
||||||
|
|
||||||
memory_->getMetricConstraints(std::vector<int>(ids.begin(), ids.end()), poses_, links_, true);
|
memory_->getMetricConstraints(std::vector<int>(ids.begin(), ids.end()), poses_, links_, true);
|
||||||
|
|
||||||
if(poses_.size())
|
if(poses_.size())
|
||||||
@@ -818,7 +1078,7 @@ void DatabaseViewer::detectMoreLoopClosures()
|
|||||||
{
|
{
|
||||||
const std::map<int, Transform> & optimizedPoses = graphes_.back();
|
const std::map<int, Transform> & optimizedPoses = graphes_.back();
|
||||||
|
|
||||||
int iterations = ui_->doubleSpinBox_detectMore_iterations->value();
|
int iterations = ui_->spinBox_detectMore_iterations->value();
|
||||||
UASSERT(iterations > 0);
|
UASSERT(iterations > 0);
|
||||||
int added = 0;
|
int added = 0;
|
||||||
for(int n=0; n<iterations; ++n)
|
for(int n=0; n<iterations; ++n)
|
||||||
@@ -973,6 +1233,7 @@ void DatabaseViewer::sliderAValueChanged(int value)
|
|||||||
ui_->label_labelA,
|
ui_->label_labelA,
|
||||||
ui_->label_stampA,
|
ui_->label_stampA,
|
||||||
ui_->graphicsView_A,
|
ui_->graphicsView_A,
|
||||||
|
ui_->widget_cloudA,
|
||||||
ui_->label_idA);
|
ui_->label_idA);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -986,6 +1247,7 @@ void DatabaseViewer::sliderBValueChanged(int value)
|
|||||||
ui_->label_labelB,
|
ui_->label_labelB,
|
||||||
ui_->label_stampB,
|
ui_->label_stampB,
|
||||||
ui_->graphicsView_B,
|
ui_->graphicsView_B,
|
||||||
|
ui_->widget_cloudB,
|
||||||
ui_->label_idB);
|
ui_->label_idB);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -997,6 +1259,7 @@ void DatabaseViewer::update(int value,
|
|||||||
QLabel * label,
|
QLabel * label,
|
||||||
QLabel * stamp,
|
QLabel * stamp,
|
||||||
rtabmap::ImageView * view,
|
rtabmap::ImageView * view,
|
||||||
|
rtabmap::CloudViewer * view3D,
|
||||||
QLabel * labelId,
|
QLabel * labelId,
|
||||||
bool updateConstraintView)
|
bool updateConstraintView)
|
||||||
{
|
{
|
||||||
@@ -1051,6 +1314,32 @@ void DatabaseViewer::update(int value,
|
|||||||
{
|
{
|
||||||
this->updateStereo(&data);
|
this->updateStereo(&data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 3d view
|
||||||
|
if(view3D->isVisible() && !data.getDepthRaw().empty())
|
||||||
|
{
|
||||||
|
pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud;
|
||||||
|
if(data.getDepthRaw().type() == CV_8UC1)
|
||||||
|
{
|
||||||
|
cloud = util3d::cloudFromStereoImages(
|
||||||
|
data.getImageRaw(),
|
||||||
|
data.getDepthRaw(),
|
||||||
|
data.getDepthCx(), data.getDepthCy(),
|
||||||
|
data.getDepthFx(), data.getDepthFy(),
|
||||||
|
1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cloud = util3d::cloudFromDepthRGB(
|
||||||
|
data.getImageRaw(),
|
||||||
|
data.getDepthRaw(),
|
||||||
|
data.getDepthCx(), data.getDepthCy(),
|
||||||
|
data.getDepthFx(), data.getDepthFy(),
|
||||||
|
1);
|
||||||
|
}
|
||||||
|
view3D->addOrUpdateCloud("0", cloud, data.getLocalTransform());
|
||||||
|
view3D->update();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!imgDepth.isNull())
|
if(!imgDepth.isNull())
|
||||||
@@ -1522,6 +1811,7 @@ void DatabaseViewer::updateConstraintView(
|
|||||||
ui_->label_labelA,
|
ui_->label_labelA,
|
||||||
ui_->label_stampA,
|
ui_->label_stampA,
|
||||||
ui_->graphicsView_A,
|
ui_->graphicsView_A,
|
||||||
|
ui_->widget_cloudA,
|
||||||
ui_->label_idA,
|
ui_->label_idA,
|
||||||
false); // don't update constraints view!
|
false); // don't update constraints view!
|
||||||
}
|
}
|
||||||
@@ -1535,6 +1825,7 @@ void DatabaseViewer::updateConstraintView(
|
|||||||
ui_->label_labelB,
|
ui_->label_labelB,
|
||||||
ui_->label_stampB,
|
ui_->label_stampB,
|
||||||
ui_->graphicsView_B,
|
ui_->graphicsView_B,
|
||||||
|
ui_->widget_cloudB,
|
||||||
ui_->label_idB,
|
ui_->label_idB,
|
||||||
false); // don't update constraints view!
|
false); // don't update constraints view!
|
||||||
}
|
}
|
||||||
@@ -1773,31 +2064,99 @@ void DatabaseViewer::sliderIterationsValueChanged(int value)
|
|||||||
{
|
{
|
||||||
if(memory_ && value >=0 && value < (int)graphes_.size())
|
if(memory_ && value >=0 && value < (int)graphes_.size())
|
||||||
{
|
{
|
||||||
if(ui_->dockWidget_graphView->isVisible() && scans_.size() == 0)
|
if(ui_->dockWidget_graphView->isVisible() && localMaps_.size() == 0)
|
||||||
{
|
{
|
||||||
//update scans
|
//update scans
|
||||||
UINFO("Update scans list...");
|
UINFO("Update local maps list...");
|
||||||
|
|
||||||
for(int i=0; i<ids_.size(); ++i)
|
for(int i=0; i<ids_.size(); ++i)
|
||||||
{
|
{
|
||||||
Signature data = memory_->getSignatureData(ids_.at(i), false);
|
UTimer time;
|
||||||
if(!data.getLaserScanCompressed().empty())
|
bool added = false;
|
||||||
|
if(ui_->checkBox_gridFromProjection->isChecked())
|
||||||
{
|
{
|
||||||
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud;
|
Signature data = memory_->getSignatureData(ids_.at(i), true);
|
||||||
cv::Mat laserScan = rtabmap::uncompressData(data.getLaserScanCompressed());
|
if(!data.getDepthRaw().empty())
|
||||||
cloud = rtabmap::util3d::laserScanToPointCloud(laserScan);
|
{
|
||||||
scans_.insert(std::make_pair(ids_.at(i), cloud));
|
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud;
|
||||||
|
if(data.getDepthRaw().type() == CV_8UC1)
|
||||||
|
{
|
||||||
|
cloud = rtabmap::util3d::cloudFromDisparity(
|
||||||
|
util3d::disparityFromStereoImages(data.getImageRaw(), data.getDepthRaw()),
|
||||||
|
data.getDepthCx(),
|
||||||
|
data.getDepthCy(),
|
||||||
|
data.getDepthFx(),
|
||||||
|
data.getDepthFy(),
|
||||||
|
ui_->spinBox_projDecimation->value());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cloud = util3d::cloudFromDepth(
|
||||||
|
data.getDepthRaw(),
|
||||||
|
data.getDepthCx(),
|
||||||
|
data.getDepthCy(),
|
||||||
|
data.getDepthFx(),
|
||||||
|
data.getDepthFy(),
|
||||||
|
ui_->spinBox_projDecimation->value());
|
||||||
|
}
|
||||||
|
if(cloud->size())
|
||||||
|
{
|
||||||
|
cloud = util3d::passThrough<pcl::PointXYZ>(cloud, "z", 0, ui_->doubleSpinBox_projMaxDepth->value());
|
||||||
|
}
|
||||||
|
|
||||||
|
if(cloud->size())
|
||||||
|
{
|
||||||
|
cloud = util3d::voxelize<pcl::PointXYZ>(cloud, ui_->doubleSpinBox_gridCellSize->value());
|
||||||
|
cloud = util3d::transformPointCloud<pcl::PointXYZ>(cloud, data.getLocalTransform());
|
||||||
|
|
||||||
|
UTimer timer;
|
||||||
|
float cellSize = ui_->doubleSpinBox_gridCellSize->value();
|
||||||
|
float groundNormalMaxAngle = M_PI_4;
|
||||||
|
int minClusterSize = 20;
|
||||||
|
cv::Mat ground, obstacles;
|
||||||
|
util3d::occupancy2DFromCloud3D<pcl::PointXYZ>(
|
||||||
|
cloud,
|
||||||
|
ground, obstacles,
|
||||||
|
cellSize,
|
||||||
|
groundNormalMaxAngle,
|
||||||
|
minClusterSize);
|
||||||
|
if(!ground.empty() || !obstacles.empty())
|
||||||
|
{
|
||||||
|
localMaps_.insert(std::make_pair(ids_.at(i), std::make_pair(ground, obstacles)));
|
||||||
|
added = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Signature data = memory_->getSignatureData(ids_.at(i), false);
|
||||||
|
if(!data.getLaserScanCompressed().empty())
|
||||||
|
{
|
||||||
|
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud;
|
||||||
|
cv::Mat laserScan;
|
||||||
|
data.uncompressDataConst(0, 0, &laserScan);
|
||||||
|
cv::Mat ground, obstacles;
|
||||||
|
util3d::occupancy2DFromLaserScan(laserScan, ground, obstacles, ui_->doubleSpinBox_gridCellSize->value());
|
||||||
|
localMaps_.insert(std::make_pair(ids_.at(i), std::make_pair(ground, obstacles)));
|
||||||
|
added = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(added)
|
||||||
|
{
|
||||||
|
UINFO("Processed grid map %d/%d (%fs)", i+1, (int)ids_.size(), time.ticks());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
UINFO("Update scans list... done");
|
UINFO("Update local maps list... done");
|
||||||
}
|
}
|
||||||
std::map<int, rtabmap::Transform> & graph = uValueAt(graphes_, value);
|
std::map<int, rtabmap::Transform> & graph = uValueAt(graphes_, value);
|
||||||
std::multimap<int, Link> links = updateLinksWithModifications(links_);
|
std::multimap<int, Link> links = updateLinksWithModifications(links_);
|
||||||
ui_->graphViewer->updateGraph(graph, links);
|
ui_->graphViewer->updateGraph(graph, links);
|
||||||
if(graph.size() && scans_.size())
|
if(graph.size() && localMaps_.size())
|
||||||
{
|
{
|
||||||
float xMin, yMin;
|
float xMin, yMin;
|
||||||
float cell = 0.05;
|
float cell = ui_->doubleSpinBox_gridCellSize->value();
|
||||||
cv::Mat map = rtabmap::util3d::convertMap2Image8U(rtabmap::util3d::create2DMap(graph, scans_, cell, true, xMin, yMin));
|
cv::Mat map = rtabmap::util3d::convertMap2Image8U(rtabmap::util3d::create2DMapFromOccupancyLocalMaps(graph, localMaps_, cell, xMin, yMin));
|
||||||
ui_->graphViewer->updateMap(map, cell, xMin, yMin);
|
ui_->graphViewer->updateMap(map, cell, xMin, yMin);
|
||||||
}
|
}
|
||||||
ui_->label_iterations->setNum(value);
|
ui_->label_iterations->setNum(value);
|
||||||
@@ -1858,12 +2217,25 @@ void DatabaseViewer::updateGraphView()
|
|||||||
{
|
{
|
||||||
ui_->horizontalSlider_iterations->setMaximum(graphes_.size()-1);
|
ui_->horizontalSlider_iterations->setMaximum(graphes_.size()-1);
|
||||||
ui_->horizontalSlider_iterations->setValue(graphes_.size()-1);
|
ui_->horizontalSlider_iterations->setValue(graphes_.size()-1);
|
||||||
ui_->dockWidget_graphView->setEnabled(true);
|
ui_->horizontalSlider_iterations->setEnabled(true);
|
||||||
|
ui_->spinBox_optimizationsFrom->setEnabled(true);
|
||||||
sliderIterationsValueChanged(graphes_.size()-1);
|
sliderIterationsValueChanged(graphes_.size()-1);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ui_->dockWidget_graphView->setEnabled(false);
|
ui_->horizontalSlider_iterations->setEnabled(false);
|
||||||
|
ui_->spinBox_optimizationsFrom->setEnabled(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DatabaseViewer::updateGrid()
|
||||||
|
{
|
||||||
|
if((sender() != ui_->spinBox_projDecimation && sender() != ui_->doubleSpinBox_projMaxDepth) ||
|
||||||
|
(sender() == ui_->spinBox_projDecimation && ui_->checkBox_gridFromProjection->isChecked()) ||
|
||||||
|
(sender() == ui_->doubleSpinBox_projMaxDepth && ui_->checkBox_gridFromProjection->isChecked()))
|
||||||
|
{
|
||||||
|
localMaps_.clear();
|
||||||
|
updateGraphView();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -59,6 +59,54 @@ ExportCloudsDialog::~ExportCloudsDialog()
|
|||||||
delete _ui;
|
delete _ui;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ExportCloudsDialog::saveSettings(QSettings & settings, const QString & group) const
|
||||||
|
{
|
||||||
|
if(!group.isEmpty())
|
||||||
|
{
|
||||||
|
settings.beginGroup(group);
|
||||||
|
}
|
||||||
|
settings.setValue("assemble", this->getAssemble());
|
||||||
|
settings.setValue("assemble_voxel", this->getAssembleVoxel());
|
||||||
|
settings.setValue("regenerate", this->getGenerate());
|
||||||
|
settings.setValue("regenerate_decimation", this->getGenerateDecimation());
|
||||||
|
settings.setValue("regenerate_voxel", this->getGenerateVoxel());
|
||||||
|
settings.setValue("regenerate_max_depth", this->getGenerateMaxDepth());
|
||||||
|
settings.setValue("binary", this->getBinaryFile());
|
||||||
|
settings.setValue("mls", this->getMLS());
|
||||||
|
settings.setValue("mls_radius", this->getMLSRadius());
|
||||||
|
settings.setValue("mesh", this->getMesh());
|
||||||
|
settings.setValue("mesh_k", this->getMeshNormalKSearch());
|
||||||
|
settings.setValue("mesh_radius", this->getMeshGp3Radius());
|
||||||
|
if(!group.isEmpty())
|
||||||
|
{
|
||||||
|
settings.endGroup();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ExportCloudsDialog::loadSettings(QSettings & settings, const QString & group)
|
||||||
|
{
|
||||||
|
if(!group.isEmpty())
|
||||||
|
{
|
||||||
|
settings.beginGroup(group);
|
||||||
|
}
|
||||||
|
this->setAssemble(settings.value("assemble", this->getAssemble()).toBool());
|
||||||
|
this->setAssembleVoxel(settings.value("assemble_voxel", this->getAssembleVoxel()).toDouble());
|
||||||
|
this->setGenerate(settings.value("regenerate", this->getGenerate()).toBool());
|
||||||
|
this->setGenerateDecimation(settings.value("regenerate_decimation", this->getGenerateDecimation()).toInt());
|
||||||
|
this->setGenerateVoxel(settings.value("regenerate_voxel", this->getGenerateVoxel()).toDouble());
|
||||||
|
this->setGenerateMaxDepth(settings.value("regenerate_max_depth", this->getGenerateMaxDepth()).toDouble());
|
||||||
|
this->setBinaryFile(settings.value("binary", this->getBinaryFile()).toBool());
|
||||||
|
this->setMLS(settings.value("mls", this->getMLS()).toBool());
|
||||||
|
this->setMLSRadius(settings.value("mls_radius", this->getMLSRadius()).toDouble());
|
||||||
|
this->setMesh(settings.value("mesh", this->getMesh()).toBool());
|
||||||
|
this->setMeshNormalKSearch(settings.value("mesh_k", this->getMeshNormalKSearch()).toInt());
|
||||||
|
this->setMeshGp3Radius(settings.value("mesh_radius", this->getMeshGp3Radius()).toDouble());
|
||||||
|
if(!group.isEmpty())
|
||||||
|
{
|
||||||
|
settings.endGroup();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void ExportCloudsDialog::restoreDefaults()
|
void ExportCloudsDialog::restoreDefaults()
|
||||||
{
|
{
|
||||||
setAssemble(true);
|
setAssemble(true);
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#define EXPORTCLOUDSDIALOG_H_
|
#define EXPORTCLOUDSDIALOG_H_
|
||||||
|
|
||||||
#include <QtGui/QDialog>
|
#include <QtGui/QDialog>
|
||||||
|
#include <QtCore/QSettings>
|
||||||
|
|
||||||
class Ui_ExportCloudsDialog;
|
class Ui_ExportCloudsDialog;
|
||||||
class QAbstractButton;
|
class QAbstractButton;
|
||||||
@@ -44,6 +45,9 @@ public:
|
|||||||
|
|
||||||
virtual ~ExportCloudsDialog();
|
virtual ~ExportCloudsDialog();
|
||||||
|
|
||||||
|
void saveSettings(QSettings & settings, const QString & group = "") const;
|
||||||
|
void loadSettings(QSettings & settings, const QString & group = "");
|
||||||
|
|
||||||
void setSaveButton();
|
void setSaveButton();
|
||||||
void setOkButton();
|
void setOkButton();
|
||||||
void enableRegeneration(bool enabled);
|
void enableRegeneration(bool enabled);
|
||||||
|
|||||||
@@ -486,6 +486,54 @@ void GraphViewer::clearAll()
|
|||||||
clearGraph();
|
clearGraph();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GraphViewer::saveSettings(QSettings & settings, const QString & group) const
|
||||||
|
{
|
||||||
|
if(!group.isEmpty())
|
||||||
|
{
|
||||||
|
settings.beginGroup(group);
|
||||||
|
}
|
||||||
|
settings.setValue("node_radius", this->getNodeRadius());
|
||||||
|
settings.setValue("link_width", this->getLinkWidth());
|
||||||
|
settings.setValue("node_color", this->getNodeColor());
|
||||||
|
settings.setValue("neighbor_color", this->getNeighborColor());
|
||||||
|
settings.setValue("global_color", this->getGlobalLoopClosureColor());
|
||||||
|
settings.setValue("local_color", this->getLocalLoopClosureColor());
|
||||||
|
settings.setValue("user_color", this->getUserLoopClosureColor());
|
||||||
|
settings.setValue("virtual_color", this->getVirtualLoopClosureColor());
|
||||||
|
settings.setValue("local_path_color", this->getLocalPathColor());
|
||||||
|
settings.setValue("grid_visible", this->isGridMapVisible());
|
||||||
|
settings.setValue("origin_visible", this->isOriginVisible());
|
||||||
|
settings.setValue("referential_visible", this->isReferentialVisible());
|
||||||
|
if(!group.isEmpty())
|
||||||
|
{
|
||||||
|
settings.endGroup();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GraphViewer::loadSettings(QSettings & settings, const QString & group)
|
||||||
|
{
|
||||||
|
if(!group.isEmpty())
|
||||||
|
{
|
||||||
|
settings.beginGroup(group);
|
||||||
|
}
|
||||||
|
this->setNodeRadius(settings.value("node_radius", this->getNodeRadius()).toDouble());
|
||||||
|
this->setLinkWidth(settings.value("link_width", this->getLinkWidth()).toDouble());
|
||||||
|
this->setNodeColor(settings.value("node_color", this->getNodeColor()).value<QColor>());
|
||||||
|
this->setNeighborColor(settings.value("neighbor_color", this->getNeighborColor()).value<QColor>());
|
||||||
|
this->setGlobalLoopClosureColor(settings.value("global_color", this->getGlobalLoopClosureColor()).value<QColor>());
|
||||||
|
this->setLocalLoopClosureColor(settings.value("local_color", this->getLocalLoopClosureColor()).value<QColor>());
|
||||||
|
this->setUserLoopClosureColor(settings.value("user_color", this->getUserLoopClosureColor()).value<QColor>());
|
||||||
|
this->setVirtualLoopClosureColor(settings.value("virtual_color", this->getVirtualLoopClosureColor()).value<QColor>());
|
||||||
|
this->setLocalPathColor(settings.value("local_path_color", this->getLocalPathColor()).value<QColor>());
|
||||||
|
this->setGridMapVisible(settings.value("grid_visible", this->isGridMapVisible()).toBool());
|
||||||
|
this->setOriginVisible(settings.value("origin_visible", this->isOriginVisible()).toBool());
|
||||||
|
this->setReferentialVisible(settings.value("referential_visible", this->isReferentialVisible()).toBool());
|
||||||
|
if(!group.isEmpty())
|
||||||
|
{
|
||||||
|
settings.endGroup();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool GraphViewer::isGridMapVisible() const
|
bool GraphViewer::isGridMapVisible() const
|
||||||
{
|
{
|
||||||
return _gridMap->isVisible();
|
return _gridMap->isVisible();
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
#include <QtGui/QGraphicsView>
|
#include <QtGui/QGraphicsView>
|
||||||
#include <QtCore/QMap>
|
#include <QtCore/QMap>
|
||||||
|
#include <QtCore/QSettings>
|
||||||
#include <rtabmap/core/Link.h>
|
#include <rtabmap/core/Link.h>
|
||||||
#include <opencv2/opencv.hpp>
|
#include <opencv2/opencv.hpp>
|
||||||
#include <map>
|
#include <map>
|
||||||
@@ -62,6 +63,9 @@ public:
|
|||||||
void clearPosterior();
|
void clearPosterior();
|
||||||
void clearAll();
|
void clearAll();
|
||||||
|
|
||||||
|
void saveSettings(QSettings & settings, const QString & group = "") const;
|
||||||
|
void loadSettings(QSettings & settings, const QString & group = "");
|
||||||
|
|
||||||
//getters
|
//getters
|
||||||
const QString & getWorkingDirectory() const {return _workingDirectory;}
|
const QString & getWorkingDirectory() const {return _workingDirectory;}
|
||||||
float getNodeRadius() const {return _nodeRadius;}
|
float getNodeRadius() const {return _nodeRadius;}
|
||||||
|
|||||||
@@ -74,6 +74,40 @@ ImageView::~ImageView() {
|
|||||||
clear();
|
clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ImageView::saveSettings(QSettings & settings, const QString & group) const
|
||||||
|
{
|
||||||
|
if(!group.isEmpty())
|
||||||
|
{
|
||||||
|
settings.beginGroup(group);
|
||||||
|
}
|
||||||
|
settings.setValue("image_shown", this->isImageShown());
|
||||||
|
settings.setValue("depth_shown", this->isImageDepthShown());
|
||||||
|
settings.setValue("features_shown", this->isFeaturesShown());
|
||||||
|
settings.setValue("lines_shown", this->isLinesShown());
|
||||||
|
settings.setValue("alpha", this->getAlpha());
|
||||||
|
if(!group.isEmpty())
|
||||||
|
{
|
||||||
|
settings.endGroup();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImageView::loadSettings(QSettings & settings, const QString & group)
|
||||||
|
{
|
||||||
|
if(!group.isEmpty())
|
||||||
|
{
|
||||||
|
settings.beginGroup(group);
|
||||||
|
}
|
||||||
|
this->setImageShown(settings.value("image_shown", this->isImageShown()).toBool());
|
||||||
|
this->setImageDepthShown(settings.value("depth_shown", this->isImageDepthShown()).toBool());
|
||||||
|
this->setFeaturesShown(settings.value("features_shown", this->isFeaturesShown()).toBool());
|
||||||
|
this->setLinesShown(settings.value("lines_shown", this->isLinesShown()).toBool());
|
||||||
|
this->setAlpha(settings.value("alpha", this->getAlpha()).toInt());
|
||||||
|
if(!group.isEmpty())
|
||||||
|
{
|
||||||
|
settings.endGroup();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void ImageView::resetZoom()
|
void ImageView::resetZoom()
|
||||||
{
|
{
|
||||||
_zoom = _minZoom;
|
_zoom = _minZoom;
|
||||||
|
|||||||
@@ -131,7 +131,8 @@ MainWindow::MainWindow(PreferencesDialog * prefDialog, QWidget * parent) :
|
|||||||
_posteriorCurve(0),
|
_posteriorCurve(0),
|
||||||
_likelihoodCurve(0),
|
_likelihoodCurve(0),
|
||||||
_rawLikelihoodCurve(0),
|
_rawLikelihoodCurve(0),
|
||||||
_autoScreenCaptureOdomSync(false)
|
_autoScreenCaptureOdomSync(false),
|
||||||
|
_firstCall(true)
|
||||||
{
|
{
|
||||||
UDEBUG("");
|
UDEBUG("");
|
||||||
|
|
||||||
@@ -173,19 +174,6 @@ MainWindow::MainWindow(PreferencesDialog * prefDialog, QWidget * parent) :
|
|||||||
//_ui->dockWidget_odometry->setVisible(false);
|
//_ui->dockWidget_odometry->setVisible(false);
|
||||||
//_ui->dockWidget_cloudViewer->setVisible(false);
|
//_ui->dockWidget_cloudViewer->setVisible(false);
|
||||||
//_ui->dockWidget_imageView->setVisible(false);
|
//_ui->dockWidget_imageView->setVisible(false);
|
||||||
|
|
||||||
// catch resize events
|
|
||||||
_ui->dockWidget_posterior->installEventFilter(this);
|
|
||||||
_ui->dockWidget_likelihood->installEventFilter(this);
|
|
||||||
_ui->dockWidget_rawlikelihood->installEventFilter(this);
|
|
||||||
_ui->dockWidget_statsV2->installEventFilter(this);
|
|
||||||
_ui->dockWidget_console->installEventFilter(this);
|
|
||||||
_ui->dockWidget_loopClosureViewer->installEventFilter(this);
|
|
||||||
_ui->dockWidget_mapVisibility->installEventFilter(this);
|
|
||||||
_ui->dockWidget_graphViewer->installEventFilter(this);
|
|
||||||
_ui->dockWidget_odometry->installEventFilter(this);
|
|
||||||
_ui->dockWidget_cloudViewer->installEventFilter(this);
|
|
||||||
_ui->dockWidget_imageView->installEventFilter(this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_ui->widget_mainWindow->setVisible(false);
|
_ui->widget_mainWindow->setVisible(false);
|
||||||
@@ -399,6 +387,18 @@ MainWindow::MainWindow(PreferencesDialog * prefDialog, QWidget * parent) :
|
|||||||
connect(dockWidgets[i], SIGNAL(dockLocationChanged(Qt::DockWidgetArea)), this, SLOT(configGUIModified()));
|
connect(dockWidgets[i], SIGNAL(dockLocationChanged(Qt::DockWidgetArea)), this, SLOT(configGUIModified()));
|
||||||
connect(dockWidgets[i]->toggleViewAction(), SIGNAL(toggled(bool)), this, SLOT(configGUIModified()));
|
connect(dockWidgets[i]->toggleViewAction(), SIGNAL(toggled(bool)), this, SLOT(configGUIModified()));
|
||||||
}
|
}
|
||||||
|
// catch resize events
|
||||||
|
_ui->dockWidget_posterior->installEventFilter(this);
|
||||||
|
_ui->dockWidget_likelihood->installEventFilter(this);
|
||||||
|
_ui->dockWidget_rawlikelihood->installEventFilter(this);
|
||||||
|
_ui->dockWidget_statsV2->installEventFilter(this);
|
||||||
|
_ui->dockWidget_console->installEventFilter(this);
|
||||||
|
_ui->dockWidget_loopClosureViewer->installEventFilter(this);
|
||||||
|
_ui->dockWidget_mapVisibility->installEventFilter(this);
|
||||||
|
_ui->dockWidget_graphViewer->installEventFilter(this);
|
||||||
|
_ui->dockWidget_odometry->installEventFilter(this);
|
||||||
|
_ui->dockWidget_cloudViewer->installEventFilter(this);
|
||||||
|
_ui->dockWidget_imageView->installEventFilter(this);
|
||||||
|
|
||||||
// more connects...
|
// more connects...
|
||||||
connect(_ui->doubleSpinBox_stats_imgRate, SIGNAL(editingFinished()), this, SLOT(changeImgRateSetting()));
|
connect(_ui->doubleSpinBox_stats_imgRate, SIGNAL(editingFinished()), this, SLOT(changeImgRateSetting()));
|
||||||
@@ -2193,12 +2193,11 @@ void MainWindow::moveEvent(QMoveEvent* anEvent)
|
|||||||
if(this->isVisible())
|
if(this->isVisible())
|
||||||
{
|
{
|
||||||
// HACK, there is a move event when the window is shown the first time.
|
// HACK, there is a move event when the window is shown the first time.
|
||||||
static bool firstCall = true;
|
if(!_firstCall)
|
||||||
if(!firstCall)
|
|
||||||
{
|
{
|
||||||
this->configGUIModified();
|
this->configGUIModified();
|
||||||
}
|
}
|
||||||
firstCall = false;
|
_firstCall = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2471,7 +2470,14 @@ void MainWindow::editDatabase()
|
|||||||
viewer->setWindowModality(Qt::WindowModal);
|
viewer->setWindowModality(Qt::WindowModal);
|
||||||
if(viewer->openDatabase(path))
|
if(viewer->openDatabase(path))
|
||||||
{
|
{
|
||||||
viewer->show();
|
if(viewer->isSavedMaximized())
|
||||||
|
{
|
||||||
|
viewer->showMaximized();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
viewer->show();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -57,6 +57,44 @@ PostProcessingDialog::~PostProcessingDialog()
|
|||||||
delete _ui;
|
delete _ui;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PostProcessingDialog::saveSettings(QSettings & settings, const QString & group) const
|
||||||
|
{
|
||||||
|
if(!group.isEmpty())
|
||||||
|
{
|
||||||
|
settings.beginGroup(group);
|
||||||
|
}
|
||||||
|
settings.setValue("detect_more_lc", this->isDetectMoreLoopClosures());
|
||||||
|
settings.setValue("cluster_radius", this->clusterRadius());
|
||||||
|
settings.setValue("cluster_angle", this->clusterAngle());
|
||||||
|
settings.setValue("iterations", this->iterations());
|
||||||
|
settings.setValue("reextract_features", this->isReextractFeatures());
|
||||||
|
settings.setValue("refine_neigbors", this->isRefineNeighborLinks());
|
||||||
|
settings.setValue("refine_lc", this->isRefineLoopClosureLinks());
|
||||||
|
if(!group.isEmpty())
|
||||||
|
{
|
||||||
|
settings.endGroup();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PostProcessingDialog::loadSettings(QSettings & settings, const QString & group)
|
||||||
|
{
|
||||||
|
if(!group.isEmpty())
|
||||||
|
{
|
||||||
|
settings.beginGroup(group);
|
||||||
|
}
|
||||||
|
this->setDetectMoreLoopClosures(settings.value("detect_more_lc", this->isDetectMoreLoopClosures()).toBool());
|
||||||
|
this->setClusterRadius(settings.value("cluster_radius", this->clusterRadius()).toDouble());
|
||||||
|
this->setClusterAngle(settings.value("cluster_angle", this->clusterAngle()).toDouble());
|
||||||
|
this->setIterations(settings.value("iterations", this->iterations()).toInt());
|
||||||
|
this->setReextractFeatures(settings.value("reextract_features", this->isReextractFeatures()).toBool());
|
||||||
|
this->setRefineNeighborLinks(settings.value("refine_neigbors", this->isRefineNeighborLinks()).toBool());
|
||||||
|
this->setRefineLoopClosureLinks(settings.value("refine_lc", this->isRefineLoopClosureLinks()).toBool());
|
||||||
|
if(!group.isEmpty())
|
||||||
|
{
|
||||||
|
settings.endGroup();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void PostProcessingDialog::restoreDefaults()
|
void PostProcessingDialog::restoreDefaults()
|
||||||
{
|
{
|
||||||
setDetectMoreLoopClosures(true);
|
setDetectMoreLoopClosures(true);
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#define POSTPROCESSINGDIALOG_H_
|
#define POSTPROCESSINGDIALOG_H_
|
||||||
|
|
||||||
#include <QtGui/QDialog>
|
#include <QtGui/QDialog>
|
||||||
|
#include <QtCore/QSettings>
|
||||||
|
|
||||||
class Ui_PostProcessingDialog;
|
class Ui_PostProcessingDialog;
|
||||||
class QAbstractButton;
|
class QAbstractButton;
|
||||||
@@ -44,6 +45,9 @@ public:
|
|||||||
|
|
||||||
virtual ~PostProcessingDialog();
|
virtual ~PostProcessingDialog();
|
||||||
|
|
||||||
|
void saveSettings(QSettings & settings, const QString & group = "") const;
|
||||||
|
void loadSettings(QSettings & settings, const QString & group = "");
|
||||||
|
|
||||||
//getters
|
//getters
|
||||||
bool isDetectMoreLoopClosures() const;
|
bool isDetectMoreLoopClosures() const;
|
||||||
double clusterRadius() const;
|
double clusterRadius() const;
|
||||||
|
|||||||
@@ -34,7 +34,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#include <QtCore/QDir>
|
#include <QtCore/QDir>
|
||||||
#include <QtCore/QTimer>
|
#include <QtCore/QTimer>
|
||||||
|
|
||||||
#include <QtGui/QVector3D>
|
|
||||||
#include <QtGui/QFileDialog>
|
#include <QtGui/QFileDialog>
|
||||||
#include <QtGui/QMessageBox>
|
#include <QtGui/QMessageBox>
|
||||||
#include <QtGui/QStandardItemModel>
|
#include <QtGui/QStandardItemModel>
|
||||||
@@ -1750,90 +1749,23 @@ void PreferencesDialog::saveWidgetState(const QWidget * widget)
|
|||||||
|
|
||||||
if(cloudViewer)
|
if(cloudViewer)
|
||||||
{
|
{
|
||||||
float poseX, poseY, poseZ, focalX, focalY, focalZ, upX, upY, upZ;
|
cloudViewer->saveSettings(settings);
|
||||||
cloudViewer->getCameraPosition(poseX, poseY, poseZ, focalX, focalY, focalZ, upX, upY, upZ);
|
|
||||||
QVector3D pose(poseX, poseY, poseZ);
|
|
||||||
QVector3D focal(focalX, focalY, focalZ);
|
|
||||||
if(!cloudViewer->isCameraFree())
|
|
||||||
{
|
|
||||||
// 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());
|
|
||||||
}
|
|
||||||
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)
|
else if(imageView)
|
||||||
{
|
{
|
||||||
settings.setValue("image_shown", imageView->isImageShown());
|
imageView->saveSettings(settings);
|
||||||
settings.setValue("depth_shown", imageView->isImageDepthShown());
|
|
||||||
settings.setValue("features_shown", imageView->isFeaturesShown());
|
|
||||||
settings.setValue("lines_shown", imageView->isLinesShown());
|
|
||||||
settings.setValue("alpha", imageView->getAlpha());
|
|
||||||
}
|
}
|
||||||
else if(exportCloudsDialog)
|
else if(exportCloudsDialog)
|
||||||
{
|
{
|
||||||
settings.setValue("assemble", exportCloudsDialog->getAssemble());
|
exportCloudsDialog->saveSettings(settings);
|
||||||
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)
|
else if(postProcessingDialog)
|
||||||
{
|
{
|
||||||
settings.setValue("detect_more_lc", postProcessingDialog->isDetectMoreLoopClosures());
|
postProcessingDialog->saveSettings(settings);
|
||||||
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 if(graphViewer)
|
else if(graphViewer)
|
||||||
{
|
{
|
||||||
settings.setValue("node_radius", graphViewer->getNodeRadius());
|
graphViewer->saveSettings(settings);
|
||||||
settings.setValue("link_width", graphViewer->getLinkWidth());
|
|
||||||
settings.setValue("node_color", graphViewer->getNodeColor());
|
|
||||||
settings.setValue("neighbor_color", graphViewer->getNeighborColor());
|
|
||||||
settings.setValue("global_color", graphViewer->getGlobalLoopClosureColor());
|
|
||||||
settings.setValue("local_color", graphViewer->getLocalLoopClosureColor());
|
|
||||||
settings.setValue("user_color", graphViewer->getUserLoopClosureColor());
|
|
||||||
settings.setValue("virtual_color", graphViewer->getVirtualLoopClosureColor());
|
|
||||||
settings.setValue("local_path_color", graphViewer->getLocalPathColor());
|
|
||||||
settings.setValue("grid_visible", graphViewer->isGridMapVisible());
|
|
||||||
settings.setValue("origin_visible", graphViewer->isOriginVisible());
|
|
||||||
settings.setValue("referential_visible", graphViewer->isReferentialVisible());
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -1862,78 +1794,23 @@ void PreferencesDialog::loadWidgetState(QWidget * widget)
|
|||||||
|
|
||||||
if(cloudViewer)
|
if(cloudViewer)
|
||||||
{
|
{
|
||||||
float poseX, poseY, poseZ, focalX, focalY, focalZ, upX, upY, upZ;
|
cloudViewer->loadSettings(settings);
|
||||||
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)
|
else if(imageView)
|
||||||
{
|
{
|
||||||
imageView->setImageShown(settings.value("image_shown", imageView->isImageShown()).toBool());
|
imageView->loadSettings(settings);
|
||||||
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());
|
|
||||||
imageView->setAlpha(settings.value("alpha", imageView->getAlpha()).toInt());
|
|
||||||
}
|
}
|
||||||
else if(exportCloudsDialog)
|
else if(exportCloudsDialog)
|
||||||
{
|
{
|
||||||
exportCloudsDialog->setAssemble(settings.value("assemble", exportCloudsDialog->getAssemble()).toBool());
|
exportCloudsDialog->loadSettings(settings);
|
||||||
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)
|
else if(postProcessingDialog)
|
||||||
{
|
{
|
||||||
postProcessingDialog->setDetectMoreLoopClosures(settings.value("detect_more_lc", postProcessingDialog->isDetectMoreLoopClosures()).toBool());
|
postProcessingDialog->loadSettings(settings);
|
||||||
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 if(graphViewer)
|
else if(graphViewer)
|
||||||
{
|
{
|
||||||
graphViewer->setNodeRadius(settings.value("node_radius", graphViewer->getNodeRadius()).toDouble());
|
graphViewer->loadSettings(settings);
|
||||||
graphViewer->setLinkWidth(settings.value("link_width", graphViewer->getLinkWidth()).toDouble());
|
|
||||||
graphViewer->setNodeColor(settings.value("node_color", graphViewer->getNodeColor()).value<QColor>());
|
|
||||||
graphViewer->setNeighborColor(settings.value("neighbor_color", graphViewer->getNeighborColor()).value<QColor>());
|
|
||||||
graphViewer->setGlobalLoopClosureColor(settings.value("global_color", graphViewer->getGlobalLoopClosureColor()).value<QColor>());
|
|
||||||
graphViewer->setLocalLoopClosureColor(settings.value("local_color", graphViewer->getLocalLoopClosureColor()).value<QColor>());
|
|
||||||
graphViewer->setUserLoopClosureColor(settings.value("user_color", graphViewer->getUserLoopClosureColor()).value<QColor>());
|
|
||||||
graphViewer->setVirtualLoopClosureColor(settings.value("virtual_color", graphViewer->getVirtualLoopClosureColor()).value<QColor>());
|
|
||||||
graphViewer->setLocalPathColor(settings.value("local_path_color", graphViewer->getLocalPathColor()).value<QColor>());
|
|
||||||
graphViewer->setGridMapVisible(settings.value("grid_visible", graphViewer->isGridMapVisible()).toBool());
|
|
||||||
graphViewer->setOriginVisible(settings.value("origin_visible", graphViewer->isOriginVisible()).toBool());
|
|
||||||
graphViewer->setReferentialVisible(settings.value("referential_visible", graphViewer->isReferentialVisible()).toBool());
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -7,17 +7,14 @@
|
|||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>1187</width>
|
<width>1187</width>
|
||||||
<height>862</height>
|
<height>1018</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="windowTitle">
|
<property name="windowTitle">
|
||||||
<string>Database viewer</string>
|
<string>Database viewer</string>
|
||||||
</property>
|
</property>
|
||||||
<widget class="QWidget" name="centralwidget">
|
<widget class="QWidget" name="centralwidget">
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_7">
|
<layout class="QVBoxLayout" name="verticalLayout_7" stretch="2">
|
||||||
<property name="spacing">
|
|
||||||
<number>0</number>
|
|
||||||
</property>
|
|
||||||
<item>
|
<item>
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||||
<property name="rightMargin">
|
<property name="rightMargin">
|
||||||
@@ -335,13 +332,6 @@
|
|||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
|
||||||
<widget class="QDialogButtonBox" name="buttonBox">
|
|
||||||
<property name="standardButtons">
|
|
||||||
<set>QDialogButtonBox::Close</set>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="QMenuBar" name="menubar">
|
<widget class="QMenuBar" name="menubar">
|
||||||
@@ -359,6 +349,8 @@
|
|||||||
</property>
|
</property>
|
||||||
<addaction name="actionOpen_database"/>
|
<addaction name="actionOpen_database"/>
|
||||||
<addaction name="separator"/>
|
<addaction name="separator"/>
|
||||||
|
<addaction name="actionSave_config"/>
|
||||||
|
<addaction name="separator"/>
|
||||||
<addaction name="actionExport"/>
|
<addaction name="actionExport"/>
|
||||||
<addaction name="actionExtract_images"/>
|
<addaction name="actionExtract_images"/>
|
||||||
<addaction name="separator"/>
|
<addaction name="separator"/>
|
||||||
@@ -403,10 +395,7 @@
|
|||||||
<widget class="rtabmap::CloudViewer" name="constraintsViewer" native="true"/>
|
<widget class="rtabmap::CloudViewer" name="constraintsViewer" native="true"/>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<layout class="QFormLayout" name="formLayout">
|
<layout class="QGridLayout" name="gridLayout_6" columnstretch="0,1">
|
||||||
<property name="fieldGrowthPolicy">
|
|
||||||
<enum>QFormLayout::ExpandingFieldsGrow</enum>
|
|
||||||
</property>
|
|
||||||
<item row="0" column="0">
|
<item row="0" column="0">
|
||||||
<widget class="QLabel" name="label">
|
<widget class="QLabel" name="label">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
@@ -441,6 +430,20 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item row="2" column="0">
|
||||||
|
<widget class="QLabel" name="label_33">
|
||||||
|
<property name="text">
|
||||||
|
<string>Type</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="1">
|
||||||
|
<widget class="QLabel" name="label_type">
|
||||||
|
<property name="text">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
<item row="3" column="0">
|
<item row="3" column="0">
|
||||||
<widget class="QLabel" name="label_16">
|
<widget class="QLabel" name="label_16">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
@@ -455,6 +458,20 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item row="4" column="0">
|
||||||
|
<widget class="QLabel" name="label_18">
|
||||||
|
<property name="text">
|
||||||
|
<string>σ (rot, trans)</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="4" column="1">
|
||||||
|
<widget class="QLabel" name="label_variance">
|
||||||
|
<property name="text">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
<item row="5" column="0">
|
<item row="5" column="0">
|
||||||
<widget class="QCheckBox" name="checkBox_showOptimized">
|
<widget class="QCheckBox" name="checkBox_showOptimized">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
@@ -483,34 +500,6 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="4" column="0">
|
|
||||||
<widget class="QLabel" name="label_18">
|
|
||||||
<property name="text">
|
|
||||||
<string>σ (rot, trans)</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="4" column="1">
|
|
||||||
<widget class="QLabel" name="label_variance">
|
|
||||||
<property name="text">
|
|
||||||
<string/>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="2" column="0">
|
|
||||||
<widget class="QLabel" name="label_33">
|
|
||||||
<property name="text">
|
|
||||||
<string>Type</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="2" column="1">
|
|
||||||
<widget class="QLabel" name="label_type">
|
|
||||||
<property name="text">
|
|
||||||
<string/>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
@@ -602,15 +591,79 @@
|
|||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<layout class="QFormLayout" name="formLayout_2">
|
<layout class="QGridLayout" name="gridLayout_5" columnstretch="0,1">
|
||||||
<item row="0" column="0">
|
<item row="1" column="1">
|
||||||
<widget class="QLabel" name="label_7">
|
<widget class="QLabel" name="label_7">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>TORO iterations:</string>
|
<string>TORO iterations</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="0" column="1">
|
<item row="6" column="1">
|
||||||
|
<widget class="QLabel" name="label_36">
|
||||||
|
<property name="text">
|
||||||
|
<string>Grid cell size</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="5" column="1">
|
||||||
|
<widget class="QLabel" name="label_35">
|
||||||
|
<property name="text">
|
||||||
|
<string>Grid from 3D projection</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="1">
|
||||||
|
<widget class="QLabel" name="label_9">
|
||||||
|
<property name="text">
|
||||||
|
<string>Initial tree guess</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="4" column="1">
|
||||||
|
<widget class="QLabel" name="label_34">
|
||||||
|
<property name="text">
|
||||||
|
<string>Ignore covariance</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="6" column="0">
|
||||||
|
<widget class="QDoubleSpinBox" name="doubleSpinBox_gridCellSize">
|
||||||
|
<property name="suffix">
|
||||||
|
<string> m</string>
|
||||||
|
</property>
|
||||||
|
<property name="minimum">
|
||||||
|
<double>0.010000000000000</double>
|
||||||
|
</property>
|
||||||
|
<property name="maximum">
|
||||||
|
<double>5.000000000000000</double>
|
||||||
|
</property>
|
||||||
|
<property name="singleStep">
|
||||||
|
<double>0.010000000000000</double>
|
||||||
|
</property>
|
||||||
|
<property name="value">
|
||||||
|
<double>0.050000000000000</double>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="9" column="1">
|
||||||
|
<widget class="QLabel" name="label_10">
|
||||||
|
<property name="text">
|
||||||
|
<string>Total path length (m)</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="0">
|
||||||
|
<widget class="QCheckBox" name="checkBox_initGuess">
|
||||||
|
<property name="text">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
<property name="checked">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="0">
|
||||||
<widget class="QSpinBox" name="spinBox_iterations">
|
<widget class="QSpinBox" name="spinBox_iterations">
|
||||||
<property name="suffix">
|
<property name="suffix">
|
||||||
<string/>
|
<string/>
|
||||||
@@ -626,55 +679,17 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="3" column="0">
|
<item row="5" column="0">
|
||||||
<widget class="QLabel" name="label_8">
|
<widget class="QCheckBox" name="checkBox_gridFromProjection">
|
||||||
<property name="text">
|
|
||||||
<string>Optimize from:</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="3" column="1">
|
|
||||||
<widget class="QSpinBox" name="spinBox_optimizationsFrom"/>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="1">
|
|
||||||
<widget class="QCheckBox" name="checkBox_initGuess">
|
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string/>
|
<string/>
|
||||||
</property>
|
</property>
|
||||||
<property name="checked">
|
<property name="checked">
|
||||||
<bool>true</bool>
|
<bool>false</bool>
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="0">
|
|
||||||
<widget class="QLabel" name="label_9">
|
|
||||||
<property name="text">
|
|
||||||
<string>Initial tree guess:</string>
|
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="4" column="0">
|
<item row="4" column="0">
|
||||||
<widget class="QLabel" name="label_10">
|
|
||||||
<property name="text">
|
|
||||||
<string>Total path length (m):</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="4" column="1">
|
|
||||||
<widget class="QLabel" name="label_pathLength">
|
|
||||||
<property name="text">
|
|
||||||
<string/>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="2" column="0">
|
|
||||||
<widget class="QLabel" name="label_34">
|
|
||||||
<property name="text">
|
|
||||||
<string>Ignore covariance:</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="2" column="1">
|
|
||||||
<widget class="QCheckBox" name="checkBox_ignoreCovariance">
|
<widget class="QCheckBox" name="checkBox_ignoreCovariance">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string/>
|
<string/>
|
||||||
@@ -684,12 +699,81 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="QSpinBox" name="spinBox_optimizationsFrom"/>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="1">
|
||||||
|
<widget class="QLabel" name="label_8">
|
||||||
|
<property name="text">
|
||||||
|
<string>Optimize from</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="7" column="0">
|
||||||
|
<widget class="QSpinBox" name="spinBox_projDecimation">
|
||||||
|
<property name="minimum">
|
||||||
|
<number>1</number>
|
||||||
|
</property>
|
||||||
|
<property name="maximum">
|
||||||
|
<number>8</number>
|
||||||
|
</property>
|
||||||
|
<property name="value">
|
||||||
|
<number>4</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="7" column="1">
|
||||||
|
<widget class="QLabel" name="label_37">
|
||||||
|
<property name="text">
|
||||||
|
<string>Cloud decimation (3D projection)</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="8" column="1">
|
||||||
|
<widget class="QLabel" name="label_38">
|
||||||
|
<property name="text">
|
||||||
|
<string>Cloud max depth (3D projection)</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="8" column="0">
|
||||||
|
<widget class="QDoubleSpinBox" name="doubleSpinBox_projMaxDepth">
|
||||||
|
<property name="suffix">
|
||||||
|
<string> m</string>
|
||||||
|
</property>
|
||||||
|
<property name="decimals">
|
||||||
|
<number>1</number>
|
||||||
|
</property>
|
||||||
|
<property name="minimum">
|
||||||
|
<double>0.400000000000000</double>
|
||||||
|
</property>
|
||||||
|
<property name="maximum">
|
||||||
|
<double>15.000000000000000</double>
|
||||||
|
</property>
|
||||||
|
<property name="singleStep">
|
||||||
|
<double>1.000000000000000</double>
|
||||||
|
</property>
|
||||||
|
<property name="value">
|
||||||
|
<double>4.000000000000000</double>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="9" column="0">
|
||||||
|
<widget class="QLabel" name="label_pathLength">
|
||||||
|
<property name="text">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="QDockWidget" name="dockWidget_icp">
|
<widget class="QDockWidget" name="dockWidget_icp">
|
||||||
|
<property name="floating">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
<property name="windowTitle">
|
<property name="windowTitle">
|
||||||
<string>ICP parameters</string>
|
<string>ICP parameters</string>
|
||||||
</property>
|
</property>
|
||||||
@@ -699,22 +783,64 @@
|
|||||||
<widget class="QWidget" name="dockWidgetContents_3">
|
<widget class="QWidget" name="dockWidgetContents_3">
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_11">
|
<layout class="QVBoxLayout" name="verticalLayout_11">
|
||||||
<item>
|
<item>
|
||||||
<layout class="QGridLayout" name="gridLayout_4" columnminimumwidth="1,0">
|
<layout class="QGridLayout" name="gridLayout_4" columnstretch="0,1">
|
||||||
<item row="4" column="0">
|
<item row="4" column="1">
|
||||||
<widget class="QLabel" name="label_15">
|
<widget class="QLabel" name="label_15">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Iteration</string>
|
<string>Iteration</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="0" column="0">
|
<item row="0" column="1">
|
||||||
<widget class="QLabel" name="label_14">
|
<widget class="QLabel" name="label_14">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Decimation</string>
|
<string>Decimation</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="0" column="1">
|
<item row="1" column="1">
|
||||||
|
<widget class="QLabel" name="label_17">
|
||||||
|
<property name="text">
|
||||||
|
<string>Max depth</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="1">
|
||||||
|
<widget class="QLabel" name="label_13">
|
||||||
|
<property name="text">
|
||||||
|
<string>Voxel</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="1">
|
||||||
|
<widget class="QLabel" name="label_12">
|
||||||
|
<property name="text">
|
||||||
|
<string>Max correspondence distance</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="5" column="1">
|
||||||
|
<widget class="QLabel" name="label_11">
|
||||||
|
<property name="text">
|
||||||
|
<string>Point to plane</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="6" column="1">
|
||||||
|
<widget class="QLabel" name="label_20">
|
||||||
|
<property name="text">
|
||||||
|
<string>Normal K neighbors</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="7" column="1">
|
||||||
|
<widget class="QLabel" name="label_27">
|
||||||
|
<property name="text">
|
||||||
|
<string>2D icp</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="0">
|
||||||
<widget class="QSpinBox" name="spinBox_icp_decimation">
|
<widget class="QSpinBox" name="spinBox_icp_decimation">
|
||||||
<property name="minimum">
|
<property name="minimum">
|
||||||
<number>1</number>
|
<number>1</number>
|
||||||
@@ -728,13 +854,6 @@
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="1" column="0">
|
<item row="1" column="0">
|
||||||
<widget class="QLabel" name="label_17">
|
|
||||||
<property name="text">
|
|
||||||
<string>Max depth</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="1">
|
|
||||||
<widget class="QDoubleSpinBox" name="doubleSpinBox_icp_maxDepth">
|
<widget class="QDoubleSpinBox" name="doubleSpinBox_icp_maxDepth">
|
||||||
<property name="suffix">
|
<property name="suffix">
|
||||||
<string> m</string>
|
<string> m</string>
|
||||||
@@ -751,13 +870,6 @@
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="2" column="0">
|
<item row="2" column="0">
|
||||||
<widget class="QLabel" name="label_13">
|
|
||||||
<property name="text">
|
|
||||||
<string>Voxel</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="2" column="1">
|
|
||||||
<widget class="QDoubleSpinBox" name="doubleSpinBox_icp_voxel">
|
<widget class="QDoubleSpinBox" name="doubleSpinBox_icp_voxel">
|
||||||
<property name="suffix">
|
<property name="suffix">
|
||||||
<string> m</string>
|
<string> m</string>
|
||||||
@@ -774,13 +886,6 @@
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="3" column="0">
|
<item row="3" column="0">
|
||||||
<widget class="QLabel" name="label_12">
|
|
||||||
<property name="text">
|
|
||||||
<string>Max correspondence distance</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="3" column="1">
|
|
||||||
<widget class="QDoubleSpinBox" name="doubleSpinBox_icp_maxCorrespDistance">
|
<widget class="QDoubleSpinBox" name="doubleSpinBox_icp_maxCorrespDistance">
|
||||||
<property name="suffix">
|
<property name="suffix">
|
||||||
<string> m</string>
|
<string> m</string>
|
||||||
@@ -799,7 +904,7 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="4" column="1">
|
<item row="4" column="0">
|
||||||
<widget class="QSpinBox" name="spinBox_icp_iteration">
|
<widget class="QSpinBox" name="spinBox_icp_iteration">
|
||||||
<property name="minimum">
|
<property name="minimum">
|
||||||
<number>1</number>
|
<number>1</number>
|
||||||
@@ -812,31 +917,7 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="5" column="0">
|
|
||||||
<widget class="QLabel" name="label_11">
|
|
||||||
<property name="text">
|
|
||||||
<string>Point to plane</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="5" column="1">
|
|
||||||
<widget class="QCheckBox" name="checkBox_icp_p2plane">
|
|
||||||
<property name="text">
|
|
||||||
<string/>
|
|
||||||
</property>
|
|
||||||
<property name="checked">
|
|
||||||
<bool>false</bool>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="6" column="0">
|
<item row="6" column="0">
|
||||||
<widget class="QLabel" name="label_20">
|
|
||||||
<property name="text">
|
|
||||||
<string>Normal K neighbors</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="6" column="1">
|
|
||||||
<widget class="QSpinBox" name="spinBox_icp_normalKSearch">
|
<widget class="QSpinBox" name="spinBox_icp_normalKSearch">
|
||||||
<property name="minimum">
|
<property name="minimum">
|
||||||
<number>1</number>
|
<number>1</number>
|
||||||
@@ -849,14 +930,17 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="7" column="0">
|
<item row="5" column="0">
|
||||||
<widget class="QLabel" name="label_27">
|
<widget class="QCheckBox" name="checkBox_icp_p2plane">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>2D icp</string>
|
<string/>
|
||||||
|
</property>
|
||||||
|
<property name="checked">
|
||||||
|
<bool>false</bool>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="7" column="1">
|
<item row="7" column="0">
|
||||||
<widget class="QCheckBox" name="checkBox_icp_2d">
|
<widget class="QCheckBox" name="checkBox_icp_2d">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string/>
|
<string/>
|
||||||
@@ -885,6 +969,9 @@
|
|||||||
</widget>
|
</widget>
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="QDockWidget" name="dockWidget_visual">
|
<widget class="QDockWidget" name="dockWidget_visual">
|
||||||
|
<property name="floating">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
<property name="windowTitle">
|
<property name="windowTitle">
|
||||||
<string>Visual parameters</string>
|
<string>Visual parameters</string>
|
||||||
</property>
|
</property>
|
||||||
@@ -894,15 +981,85 @@
|
|||||||
<widget class="QWidget" name="dockWidgetContents_4">
|
<widget class="QWidget" name="dockWidgetContents_4">
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_10">
|
<layout class="QVBoxLayout" name="verticalLayout_10">
|
||||||
<item>
|
<item>
|
||||||
<layout class="QGridLayout" name="gridLayout_3" columnminimumwidth="1,0">
|
<layout class="QGridLayout" name="gridLayout_3" columnstretch="0,1">
|
||||||
<item row="0" column="0">
|
<item row="0" column="1">
|
||||||
<widget class="QLabel" name="label_24">
|
<widget class="QLabel" name="label_24">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Recompute features (SURF)</string>
|
<string>Recompute features (SURF)</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="0" column="1">
|
<item row="2" column="1">
|
||||||
|
<widget class="QLabel" name="label_25">
|
||||||
|
<property name="text">
|
||||||
|
<string>SURF hessian threshold</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="1">
|
||||||
|
<widget class="QLabel" name="label_26">
|
||||||
|
<property name="text">
|
||||||
|
<string>NNDR</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="4" column="1">
|
||||||
|
<widget class="QLabel" name="label_21">
|
||||||
|
<property name="text">
|
||||||
|
<string>Min correspondences</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="5" column="1">
|
||||||
|
<widget class="QLabel" name="label_22">
|
||||||
|
<property name="text">
|
||||||
|
<string>Max correspondence distance</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="6" column="1">
|
||||||
|
<widget class="QLabel" name="label_23">
|
||||||
|
<property name="text">
|
||||||
|
<string>Iteration</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="7" column="1">
|
||||||
|
<widget class="QLabel" name="label_19">
|
||||||
|
<property name="text">
|
||||||
|
<string>Max feature depth</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="1">
|
||||||
|
<widget class="QLabel" name="label_28">
|
||||||
|
<property name="text">
|
||||||
|
<string>2D transform (x,y,yaw)</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="8" column="1">
|
||||||
|
<widget class="QLabel" name="label_29">
|
||||||
|
<property name="text">
|
||||||
|
<string>Detect more LCs: radius</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="9" column="1">
|
||||||
|
<widget class="QLabel" name="label_30">
|
||||||
|
<property name="text">
|
||||||
|
<string>Detect more LCs: angle</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="10" column="1">
|
||||||
|
<widget class="QLabel" name="label_31">
|
||||||
|
<property name="text">
|
||||||
|
<string>Detect more LCs: iterations</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="0">
|
||||||
<widget class="QCheckBox" name="checkBox_visual_recomputeFeatures">
|
<widget class="QCheckBox" name="checkBox_visual_recomputeFeatures">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string/>
|
<string/>
|
||||||
@@ -912,14 +1069,14 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="2" column="0">
|
<item row="1" column="0">
|
||||||
<widget class="QLabel" name="label_25">
|
<widget class="QCheckBox" name="checkBox_visual_2d">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>SURF hessian threshold</string>
|
<string/>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="2" column="1">
|
<item row="2" column="0">
|
||||||
<widget class="QDoubleSpinBox" name="doubleSpinBox_visual_hessian">
|
<widget class="QDoubleSpinBox" name="doubleSpinBox_visual_hessian">
|
||||||
<property name="suffix">
|
<property name="suffix">
|
||||||
<string/>
|
<string/>
|
||||||
@@ -939,13 +1096,6 @@
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="3" column="0">
|
<item row="3" column="0">
|
||||||
<widget class="QLabel" name="label_26">
|
|
||||||
<property name="text">
|
|
||||||
<string>NNDR</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="3" column="1">
|
|
||||||
<widget class="QDoubleSpinBox" name="doubleSpinBox_visual_nndr">
|
<widget class="QDoubleSpinBox" name="doubleSpinBox_visual_nndr">
|
||||||
<property name="suffix">
|
<property name="suffix">
|
||||||
<string> m</string>
|
<string> m</string>
|
||||||
@@ -968,13 +1118,6 @@
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="4" column="0">
|
<item row="4" column="0">
|
||||||
<widget class="QLabel" name="label_21">
|
|
||||||
<property name="text">
|
|
||||||
<string>Min correspondences</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="4" column="1">
|
|
||||||
<widget class="QSpinBox" name="spinBox_visual_minCorrespondences">
|
<widget class="QSpinBox" name="spinBox_visual_minCorrespondences">
|
||||||
<property name="minimum">
|
<property name="minimum">
|
||||||
<number>3</number>
|
<number>3</number>
|
||||||
@@ -988,13 +1131,6 @@
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="5" column="0">
|
<item row="5" column="0">
|
||||||
<widget class="QLabel" name="label_22">
|
|
||||||
<property name="text">
|
|
||||||
<string>Max correspondence distance</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="5" column="1">
|
|
||||||
<widget class="QDoubleSpinBox" name="doubleSpinBox_visual_maxCorrespDistance">
|
<widget class="QDoubleSpinBox" name="doubleSpinBox_visual_maxCorrespDistance">
|
||||||
<property name="suffix">
|
<property name="suffix">
|
||||||
<string> m</string>
|
<string> m</string>
|
||||||
@@ -1014,13 +1150,6 @@
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="6" column="0">
|
<item row="6" column="0">
|
||||||
<widget class="QLabel" name="label_23">
|
|
||||||
<property name="text">
|
|
||||||
<string>Iteration</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="6" column="1">
|
|
||||||
<widget class="QSpinBox" name="spinBox_visual_iteration">
|
<widget class="QSpinBox" name="spinBox_visual_iteration">
|
||||||
<property name="minimum">
|
<property name="minimum">
|
||||||
<number>1</number>
|
<number>1</number>
|
||||||
@@ -1034,13 +1163,6 @@
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="7" column="0">
|
<item row="7" column="0">
|
||||||
<widget class="QLabel" name="label_19">
|
|
||||||
<property name="text">
|
|
||||||
<string>Max feature depth</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="7" column="1">
|
|
||||||
<widget class="QDoubleSpinBox" name="doubleSpinBox_visual_maxDepth">
|
<widget class="QDoubleSpinBox" name="doubleSpinBox_visual_maxDepth">
|
||||||
<property name="suffix">
|
<property name="suffix">
|
||||||
<string> m</string>
|
<string> m</string>
|
||||||
@@ -1056,35 +1178,7 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="1" column="0">
|
|
||||||
<widget class="QLabel" name="label_28">
|
|
||||||
<property name="text">
|
|
||||||
<string>2D transform (x,y,yaw)</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="1">
|
|
||||||
<widget class="QCheckBox" name="checkBox_visual_2d">
|
|
||||||
<property name="text">
|
|
||||||
<string/>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="8" column="0">
|
<item row="8" column="0">
|
||||||
<widget class="QLabel" name="label_29">
|
|
||||||
<property name="text">
|
|
||||||
<string>Detect more LCs: radius</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="9" column="0">
|
|
||||||
<widget class="QLabel" name="label_30">
|
|
||||||
<property name="text">
|
|
||||||
<string>Detect more LCs: angle</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="8" column="1">
|
|
||||||
<widget class="QDoubleSpinBox" name="doubleSpinBox_detectMore_radius">
|
<widget class="QDoubleSpinBox" name="doubleSpinBox_detectMore_radius">
|
||||||
<property name="suffix">
|
<property name="suffix">
|
||||||
<string> m</string>
|
<string> m</string>
|
||||||
@@ -1103,7 +1197,7 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="9" column="1">
|
<item row="9" column="0">
|
||||||
<widget class="QDoubleSpinBox" name="doubleSpinBox_detectMore_angle">
|
<widget class="QDoubleSpinBox" name="doubleSpinBox_detectMore_angle">
|
||||||
<property name="suffix">
|
<property name="suffix">
|
||||||
<string> degrees</string>
|
<string> degrees</string>
|
||||||
@@ -1123,14 +1217,7 @@
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="10" column="0">
|
<item row="10" column="0">
|
||||||
<widget class="QLabel" name="label_31">
|
<widget class="QSpinBox" name="spinBox_detectMore_iterations">
|
||||||
<property name="text">
|
|
||||||
<string>Detect more LCs: iterations</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="10" column="1">
|
|
||||||
<widget class="QSpinBox" name="doubleSpinBox_detectMore_iterations">
|
|
||||||
<property name="minimum">
|
<property name="minimum">
|
||||||
<number>1</number>
|
<number>1</number>
|
||||||
</property>
|
</property>
|
||||||
@@ -1178,6 +1265,24 @@
|
|||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</widget>
|
</widget>
|
||||||
|
<widget class="QDockWidget" name="dockWidget_view3d">
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>3D view</string>
|
||||||
|
</property>
|
||||||
|
<attribute name="dockWidgetArea">
|
||||||
|
<number>4</number>
|
||||||
|
</attribute>
|
||||||
|
<widget class="QWidget" name="dockWidgetContents_6">
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_8">
|
||||||
|
<item>
|
||||||
|
<widget class="rtabmap::CloudViewer" name="widget_cloudA" native="true"/>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="rtabmap::CloudViewer" name="widget_cloudB" native="true"/>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</widget>
|
||||||
<action name="actionOpen_database">
|
<action name="actionOpen_database">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Open database</string>
|
<string>Open database</string>
|
||||||
@@ -1268,6 +1373,11 @@
|
|||||||
<string>Visual: Refine all loop closure links...</string>
|
<string>Visual: Refine all loop closure links...</string>
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
|
<action name="actionSave_config">
|
||||||
|
<property name="text">
|
||||||
|
<string>Save config</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
</widget>
|
</widget>
|
||||||
<customwidgets>
|
<customwidgets>
|
||||||
<customwidget>
|
<customwidget>
|
||||||
|
|||||||
Reference in New Issue
Block a user