Rtabmap::detectorMoreLoopClosures() added intraSession and interSession parameters

This commit is contained in:
matlabbe
2018-11-05 18:40:08 -05:00
parent 4f1deef971
commit 09a63bbc5b
9 changed files with 529 additions and 323 deletions

View File

@@ -57,6 +57,8 @@ public:
double clusterRadius() const;
double clusterAngle() const;
int iterations() const;
bool intraSession() const;
bool interSession() const;
bool isRefineNeighborLinks() const;
bool isRefineLoopClosureLinks() const;
bool isSBA() const;
@@ -70,6 +72,8 @@ public:
void setClusterRadius(double radius);
void setClusterAngle(double angle);
void setIterations(int iterations);
void setIntraSession(bool enabled);
void setInterSession(bool enabled);
void setRefineNeighborLinks(bool on);
void setRefineLoopClosureLinks(bool on);
void setSBA(bool on);
@@ -82,12 +86,15 @@ Q_SIGNALS:
void configChanged();
public Q_SLOTS:
void closeDialog ( QAbstractButton * button );
void restoreDefaults();
private Q_SLOTS:
void updateVisibility();
void updateButtonBox();
private:
bool validateForm();
private:
Ui_PostProcessingDialog * _ui;

View File

@@ -391,6 +391,8 @@ DatabaseViewer::DatabaseViewer(const QString & ini, QWidget * parent) :
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()));
connect(ui_->checkBox_detectMore_intraSession, SIGNAL(stateChanged(int)), this, SLOT(configModified()));
connect(ui_->checkBox_detectMore_interSession, SIGNAL(stateChanged(int)), this, SLOT(configModified()));
connect(ui_->lineEdit_obstacleColor, SIGNAL(textChanged(const QString &)), this, SLOT(configModified()));
connect(ui_->lineEdit_groundColor, SIGNAL(textChanged(const QString &)), this, SLOT(configModified()));
@@ -544,6 +546,8 @@ void DatabaseViewer::readSettings()
ui_->doubleSpinBox_detectMore_radius->setValue(settings.value("cluster_radius", ui_->doubleSpinBox_detectMore_radius->value()).toDouble());
ui_->doubleSpinBox_detectMore_angle->setValue(settings.value("cluster_angle", ui_->doubleSpinBox_detectMore_angle->value()).toDouble());
ui_->spinBox_detectMore_iterations->setValue(settings.value("iterations", ui_->spinBox_detectMore_iterations->value()).toInt());
ui_->checkBox_detectMore_intraSession->setChecked(settings.value("intra_session", ui_->checkBox_detectMore_intraSession->isChecked()).toBool());
ui_->checkBox_detectMore_interSession->setChecked(settings.value("inter_session", ui_->checkBox_detectMore_interSession->isChecked()).toBool());
settings.endGroup();
settings.endGroup();
@@ -626,6 +630,8 @@ void DatabaseViewer::writeSettings()
settings.setValue("cluster_radius", ui_->doubleSpinBox_detectMore_radius->value());
settings.setValue("cluster_angle", ui_->doubleSpinBox_detectMore_angle->value());
settings.setValue("iterations", ui_->spinBox_detectMore_iterations->value());
settings.setValue("intra_session", ui_->checkBox_detectMore_intraSession->isChecked());
settings.setValue("inter_session", ui_->checkBox_detectMore_interSession->isChecked());
settings.endGroup();
settings.endGroup();
@@ -693,6 +699,8 @@ void DatabaseViewer::restoreDefaultSettings()
ui_->doubleSpinBox_detectMore_radius->setValue(1.0);
ui_->doubleSpinBox_detectMore_angle->setValue(30.0);
ui_->spinBox_detectMore_iterations->setValue(5);
ui_->checkBox_detectMore_intraSession->setChecked(true);
ui_->checkBox_detectMore_interSession->setChecked(true);
}
void DatabaseViewer::openDatabase()
@@ -3234,6 +3242,13 @@ void DatabaseViewer::detectMoreLoopClosures()
int added = 0;
std::multimap<int, int> checkedLoopClosures;
std::pair<int, int> lastAdded(0,0);
bool intraSession = ui_->checkBox_detectMore_intraSession->isChecked();
bool interSession = ui_->checkBox_detectMore_interSession->isChecked();
if(!interSession && !intraSession)
{
QMessageBox::warning(this, tr("Cannot detect more loop closures"), tr("Intra and inter session parameters are disabled! Enable one or both."));
return;
}
for(int n=0; n<iterations; ++n)
{
UINFO("iteration %d/%d", n+1, iterations);
@@ -3262,24 +3277,32 @@ void DatabaseViewer::detectMoreLoopClosures()
to = iter->first;
}
// only add new links and one per cluster per iteration
if(rtabmap::graph::findLink(checkedLoopClosures, from, to) == checkedLoopClosures.end())
{
if(!findActiveLink(from, to).isValid() && !containsLink(linksRemoved_, from, to) &&
addedLinks.find(from) == addedLinks.end() && addedLinks.find(to) == addedLinks.end())
{
checkedLoopClosures.insert(std::make_pair(from, to));
if(addConstraint(from, to, true))
{
UINFO("Added new loop closure between %d and %d.", from, to);
++added;
addedLinks.insert(from);
addedLinks.insert(to);
lastAdded.first = from;
lastAdded.second = to;
int mapIdFrom = uValue(mapIds_, from, 0);
int mapIdTo = uValue(mapIds_, to, 0);
progressDialog->appendText(tr("Detected loop closure %1->%2! (%3/%4)").arg(from).arg(to).arg(i+1).arg(clusters.size()));
QApplication::processEvents();
if((interSession && mapIdFrom != mapIdTo) ||
(intraSession && mapIdFrom == mapIdTo))
{
// only add new links and one per cluster per iteration
if(rtabmap::graph::findLink(checkedLoopClosures, from, to) == checkedLoopClosures.end())
{
if(!findActiveLink(from, to).isValid() && !containsLink(linksRemoved_, from, to) &&
addedLinks.find(from) == addedLinks.end() &&
addedLinks.find(to) == addedLinks.end())
{
checkedLoopClosures.insert(std::make_pair(from, to));
if(addConstraint(from, to, true))
{
UINFO("Added new loop closure between %d and %d.", from, to);
++added;
addedLinks.insert(from);
addedLinks.insert(to);
lastAdded.first = from;
lastAdded.second = to;
progressDialog->appendText(tr("Detected loop closure %1->%2! (%3/%4)").arg(from).arg(to).arg(i+1).arg(clusters.size()));
QApplication::processEvents();
}
}
}
}

View File

@@ -5490,6 +5490,8 @@ void MainWindow::postProcessing()
}
UASSERT(detectLoopClosureIterations>0);
bool interSession = _postProcessingDialog->interSession();
bool intraSession = _postProcessingDialog->intraSession();
for(int n=0; n<detectLoopClosureIterations && !_progressCanceled; ++n)
{
_progressDialog->appendText(tr("Looking for more loop closures, clustering poses... (iteration=%1/%2, radius=%3 m angle=%4 degrees)")
@@ -5516,207 +5518,215 @@ void MainWindow::postProcessing()
to = iter->first;
}
bool alreadyChecked = false;
for(std::multimap<int, int>::iterator jter = checkedLoopClosures.lower_bound(from);
!alreadyChecked && jter!=checkedLoopClosures.end() && jter->first == from;
++jter)
int mapIdFrom = uValue(_currentMapIds, from, 0);
int mapIdTo = uValue(_currentMapIds, to, 0);
if((interSession && mapIdFrom != mapIdTo) ||
(intraSession && mapIdFrom == mapIdTo))
{
if(to == jter->second)
bool alreadyChecked = false;
for(std::multimap<int, int>::iterator jter = checkedLoopClosures.lower_bound(from);
!alreadyChecked && jter!=checkedLoopClosures.end() && jter->first == from;
++jter)
{
alreadyChecked = true;
if(to == jter->second)
{
alreadyChecked = true;
}
}
}
if(!alreadyChecked)
{
// only add new links and one per cluster per iteration
if(addedLinks.find(from) == addedLinks.end() &&
rtabmap::graph::findLink(_currentLinksMap, from, to) == _currentLinksMap.end())
if(!alreadyChecked)
{
checkedLoopClosures.insert(std::make_pair(from, to));
// only add new links and one per cluster per iteration
if(addedLinks.find(from) == addedLinks.end() &&
addedLinks.find(to) == addedLinks.end() &&
rtabmap::graph::findLink(_currentLinksMap, from, to) == _currentLinksMap.end())
{
checkedLoopClosures.insert(std::make_pair(from, to));
if(!_cachedSignatures.contains(from))
{
UERROR("Didn't find signature %d", from);
}
else if(!_cachedSignatures.contains(to))
{
UERROR("Didn't find signature %d", to);
}
else
{
Signature signatureFrom = _cachedSignatures[from];
Signature signatureTo = _cachedSignatures[to];
if(signatureFrom.getWeight() >= 0 &&
signatureTo.getWeight() >= 0) // ignore intermediate nodes
if(!_cachedSignatures.contains(from))
{
Transform transform;
RegistrationInfo info;
if(parameters.find(Parameters::kRegStrategy()) != parameters.end() &&
parameters.at(Parameters::kRegStrategy()).compare("1") == 0)
{
uInsert(parameters, ParametersPair(Parameters::kRegStrategy(), "2"));
}
Registration * registration = Registration::create(parameters);
UERROR("Didn't find signature %d", from);
}
else if(!_cachedSignatures.contains(to))
{
UERROR("Didn't find signature %d", to);
}
else
{
Signature signatureFrom = _cachedSignatures[from];
Signature signatureTo = _cachedSignatures[to];
if(reextractFeatures)
if(signatureFrom.getWeight() >= 0 &&
signatureTo.getWeight() >= 0) // ignore intermediate nodes
{
signatureFrom.sensorData().uncompressData();
signatureTo.sensorData().uncompressData();
Transform transform;
RegistrationInfo info;
if(parameters.find(Parameters::kRegStrategy()) != parameters.end() &&
parameters.at(Parameters::kRegStrategy()).compare("1") == 0)
{
uInsert(parameters, ParametersPair(Parameters::kRegStrategy(), "2"));
}
Registration * registration = Registration::create(parameters);
if(signatureFrom.sensorData().imageRaw().empty() &&
signatureTo.sensorData().imageRaw().empty())
if(reextractFeatures)
{
UWARN("\"%s\" is false and signatures (%d and %d) don't have raw "
"images. Update the cache.",
Parameters::kRGBDLoopClosureReextractFeatures().c_str());
}
else
{
signatureFrom.setWords(std::multimap<int, cv::KeyPoint>());
signatureFrom.setWords3(std::multimap<int, cv::Point3f>());
signatureFrom.setWordsDescriptors(std::multimap<int, cv::Mat>());
signatureFrom.sensorData().setFeatures(std::vector<cv::KeyPoint>(), std::vector<cv::Point3f>(), cv::Mat());
signatureTo.setWords(std::multimap<int, cv::KeyPoint>());
signatureTo.setWords3(std::multimap<int, cv::Point3f>());
signatureTo.setWordsDescriptors(std::multimap<int, cv::Mat>());
signatureTo.sensorData().setFeatures(std::vector<cv::KeyPoint>(), std::vector<cv::Point3f>(), cv::Mat());
}
}
else if(!reextractFeatures && signatureFrom.getWords().empty() && signatureTo.getWords().empty())
{
UWARN("\"%s\" is false and signatures (%d and %d) don't have words, "
"registration will not be possible. Set \"%s\" to true.",
Parameters::kRGBDLoopClosureReextractFeatures().c_str(),
signatureFrom.id(),
signatureTo.id(),
Parameters::kRGBDLoopClosureReextractFeatures().c_str());
}
transform = registration->computeTransformation(signatureFrom, signatureTo, Transform(), &info);
delete registration;
if(!transform.isNull())
{
//optimize the graph to see if the new constraint is globally valid
bool updateConstraint = true;
cv::Mat information = info.covariance.inv();
if(odomMaxInf.size() == 6 && information.cols==6 && information.rows==6)
{
for(int i=0; i<6; ++i)
signatureFrom.sensorData().uncompressData();
signatureTo.sensorData().uncompressData();
if(signatureFrom.sensorData().imageRaw().empty() &&
signatureTo.sensorData().imageRaw().empty())
{
if(information.at<double>(i,i) > odomMaxInf[i])
{
information.at<double>(i,i) = odomMaxInf[i];
}
}
}
if(optimizeMaxError > 0.0f && optimizeIterations > 0)
{
int fromId = from;
int mapId = _currentMapIds.at(from);
// use first node of the map containing from
for(std::map<int, int>::iterator iter=_currentMapIds.begin(); iter!=_currentMapIds.end(); ++iter)
{
if(iter->second == mapId && odomPoses.find(iter->first)!=odomPoses.end())
{
fromId = iter->first;
break;
}
}
std::multimap<int, Link> linksIn = _currentLinksMap;
linksIn.insert(std::make_pair(from, Link(from, to, Link::kUserClosure, transform, information)));
const Link * maxLinearLink = 0;
const Link * maxAngularLink = 0;
float maxLinearError = 0.0f;
float maxAngularError = 0.0f;
std::map<int, Transform> poses;
std::multimap<int, Link> links;
UASSERT(odomPoses.find(fromId) != odomPoses.end());
UASSERT_MSG(odomPoses.find(from) != odomPoses.end(), uFormat("id=%d poses=%d links=%d", from, (int)poses.size(), (int)links.size()).c_str());
UASSERT_MSG(odomPoses.find(to) != odomPoses.end(), uFormat("id=%d poses=%d links=%d", to, (int)poses.size(), (int)links.size()).c_str());
optimizer->getConnectedGraph(fromId, odomPoses, linksIn, poses, links);
UASSERT(poses.find(fromId) != poses.end());
UASSERT_MSG(poses.find(from) != poses.end(), uFormat("id=%d poses=%d links=%d", from, (int)poses.size(), (int)links.size()).c_str());
UASSERT_MSG(poses.find(to) != poses.end(), uFormat("id=%d poses=%d links=%d", to, (int)poses.size(), (int)links.size()).c_str());
UASSERT(graph::findLink(links, from, to) != links.end());
poses = optimizer->optimize(fromId, poses, links);
std::string msg;
if(poses.size())
{
float maxLinearErrorRatio = 0.0f;
float maxAngularErrorRatio = 0.0f;
graph::computeMaxGraphErrors(
poses,
links,
maxLinearErrorRatio,
maxAngularErrorRatio,
maxLinearError,
maxAngularError,
&maxLinearLink,
&maxAngularLink);
if(maxLinearLink)
{
UINFO("Max optimization linear error = %f m (link %d->%d)", maxLinearError, maxLinearLink->from(), maxLinearLink->to());
if(maxLinearErrorRatio > optimizeMaxError)
{
msg = uFormat("Rejecting edge %d->%d because "
"graph error is too large after optimization (%f m for edge %d->%d with ratio %f > std=%f m). "
"\"%s\" is %f.",
from,
to,
maxLinearError,
maxLinearLink->from(),
maxLinearLink->to(),
maxLinearErrorRatio,
sqrt(maxLinearLink->transVariance()),
Parameters::kRGBDOptimizeMaxError().c_str(),
optimizeMaxError);
}
}
else if(maxAngularLink)
{
UINFO("Max optimization angular error = %f deg (link %d->%d)", maxAngularError*180.0f/M_PI, maxAngularLink->from(), maxAngularLink->to());
if(maxAngularErrorRatio > optimizeMaxError)
{
msg = uFormat("Rejecting edge %d->%d because "
"graph error is too large after optimization (%f deg for edge %d->%d with ratio %f > std=%f deg). "
"\"%s\" is %f m.",
from,
to,
maxAngularError*180.0f/M_PI,
maxAngularLink->from(),
maxAngularLink->to(),
maxAngularErrorRatio,
sqrt(maxAngularLink->rotVariance()),
Parameters::kRGBDOptimizeMaxError().c_str(),
optimizeMaxError);
}
}
UWARN("\"%s\" is false and signatures (%d and %d) don't have raw "
"images. Update the cache.",
Parameters::kRGBDLoopClosureReextractFeatures().c_str());
}
else
{
msg = uFormat("Rejecting edge %d->%d because graph optimization has failed!",
from,
to);
}
if(!msg.empty())
{
UWARN("%s", msg.c_str());
_progressDialog->appendText(tr("%1").arg(msg.c_str()));
QApplication::processEvents();
updateConstraint = false;
signatureFrom.setWords(std::multimap<int, cv::KeyPoint>());
signatureFrom.setWords3(std::multimap<int, cv::Point3f>());
signatureFrom.setWordsDescriptors(std::multimap<int, cv::Mat>());
signatureFrom.sensorData().setFeatures(std::vector<cv::KeyPoint>(), std::vector<cv::Point3f>(), cv::Mat());
signatureTo.setWords(std::multimap<int, cv::KeyPoint>());
signatureTo.setWords3(std::multimap<int, cv::Point3f>());
signatureTo.setWordsDescriptors(std::multimap<int, cv::Mat>());
signatureTo.sensorData().setFeatures(std::vector<cv::KeyPoint>(), std::vector<cv::Point3f>(), cv::Mat());
}
}
if(updateConstraint)
else if(!reextractFeatures && signatureFrom.getWords().empty() && signatureTo.getWords().empty())
{
UINFO("Added new loop closure between %d and %d.", from, to);
addedLinks.insert(from);
addedLinks.insert(to);
UWARN("\"%s\" is false and signatures (%d and %d) don't have words, "
"registration will not be possible. Set \"%s\" to true.",
Parameters::kRGBDLoopClosureReextractFeatures().c_str(),
signatureFrom.id(),
signatureTo.id(),
Parameters::kRGBDLoopClosureReextractFeatures().c_str());
}
transform = registration->computeTransformation(signatureFrom, signatureTo, Transform(), &info);
delete registration;
if(!transform.isNull())
{
//optimize the graph to see if the new constraint is globally valid
bool updateConstraint = true;
cv::Mat information = info.covariance.inv();
if(odomMaxInf.size() == 6 && information.cols==6 && information.rows==6)
{
for(int i=0; i<6; ++i)
{
if(information.at<double>(i,i) > odomMaxInf[i])
{
information.at<double>(i,i) = odomMaxInf[i];
}
}
}
if(optimizeMaxError > 0.0f && optimizeIterations > 0)
{
int fromId = from;
int mapId = _currentMapIds.at(from);
// use first node of the map containing from
for(std::map<int, int>::iterator iter=_currentMapIds.begin(); iter!=_currentMapIds.end(); ++iter)
{
if(iter->second == mapId && odomPoses.find(iter->first)!=odomPoses.end())
{
fromId = iter->first;
break;
}
}
std::multimap<int, Link> linksIn = _currentLinksMap;
linksIn.insert(std::make_pair(from, Link(from, to, Link::kUserClosure, transform, information)));
const Link * maxLinearLink = 0;
const Link * maxAngularLink = 0;
float maxLinearError = 0.0f;
float maxAngularError = 0.0f;
std::map<int, Transform> poses;
std::multimap<int, Link> links;
UASSERT(odomPoses.find(fromId) != odomPoses.end());
UASSERT_MSG(odomPoses.find(from) != odomPoses.end(), uFormat("id=%d poses=%d links=%d", from, (int)poses.size(), (int)links.size()).c_str());
UASSERT_MSG(odomPoses.find(to) != odomPoses.end(), uFormat("id=%d poses=%d links=%d", to, (int)poses.size(), (int)links.size()).c_str());
optimizer->getConnectedGraph(fromId, odomPoses, linksIn, poses, links);
UASSERT(poses.find(fromId) != poses.end());
UASSERT_MSG(poses.find(from) != poses.end(), uFormat("id=%d poses=%d links=%d", from, (int)poses.size(), (int)links.size()).c_str());
UASSERT_MSG(poses.find(to) != poses.end(), uFormat("id=%d poses=%d links=%d", to, (int)poses.size(), (int)links.size()).c_str());
UASSERT(graph::findLink(links, from, to) != links.end());
poses = optimizer->optimize(fromId, poses, links);
std::string msg;
if(poses.size())
{
float maxLinearErrorRatio = 0.0f;
float maxAngularErrorRatio = 0.0f;
graph::computeMaxGraphErrors(
poses,
links,
maxLinearErrorRatio,
maxAngularErrorRatio,
maxLinearError,
maxAngularError,
&maxLinearLink,
&maxAngularLink);
if(maxLinearLink)
{
UINFO("Max optimization linear error = %f m (link %d->%d)", maxLinearError, maxLinearLink->from(), maxLinearLink->to());
if(maxLinearErrorRatio > optimizeMaxError)
{
msg = uFormat("Rejecting edge %d->%d because "
"graph error is too large after optimization (%f m for edge %d->%d with ratio %f > std=%f m). "
"\"%s\" is %f.",
from,
to,
maxLinearError,
maxLinearLink->from(),
maxLinearLink->to(),
maxLinearErrorRatio,
sqrt(maxLinearLink->transVariance()),
Parameters::kRGBDOptimizeMaxError().c_str(),
optimizeMaxError);
}
}
else if(maxAngularLink)
{
UINFO("Max optimization angular error = %f deg (link %d->%d)", maxAngularError*180.0f/M_PI, maxAngularLink->from(), maxAngularLink->to());
if(maxAngularErrorRatio > optimizeMaxError)
{
msg = uFormat("Rejecting edge %d->%d because "
"graph error is too large after optimization (%f deg for edge %d->%d with ratio %f > std=%f deg). "
"\"%s\" is %f m.",
from,
to,
maxAngularError*180.0f/M_PI,
maxAngularLink->from(),
maxAngularLink->to(),
maxAngularErrorRatio,
sqrt(maxAngularLink->rotVariance()),
Parameters::kRGBDOptimizeMaxError().c_str(),
optimizeMaxError);
}
}
}
else
{
msg = uFormat("Rejecting edge %d->%d because graph optimization has failed!",
from,
to);
}
if(!msg.empty())
{
UWARN("%s", msg.c_str());
_progressDialog->appendText(tr("%1").arg(msg.c_str()));
QApplication::processEvents();
updateConstraint = false;
}
}
_currentLinksMap.insert(std::make_pair(from, Link(from, to, Link::kUserClosure, transform, information)));
++loopClosuresAdded;
_progressDialog->appendText(tr("Detected loop closure %1->%2! (%3/%4)").arg(from).arg(to).arg(i+1).arg(clusters.size()));
if(updateConstraint)
{
UINFO("Added new loop closure between %d and %d.", from, to);
addedLinks.insert(from);
addedLinks.insert(to);
_currentLinksMap.insert(std::make_pair(from, Link(from, to, Link::kUserClosure, transform, information)));
++loopClosuresAdded;
_progressDialog->appendText(tr("Detected loop closure %1->%2! (%3/%4)").arg(from).arg(to).arg(i+1).arg(clusters.size()));
}
}
}
}

View File

@@ -29,6 +29,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "ui_postProcessingDialog.h"
#include <QPushButton>
#include <QMessageBox>
#include <rtabmap/core/Optimizer.h>
namespace rtabmap {
@@ -57,6 +58,8 @@ PostProcessingDialog::PostProcessingDialog(QWidget * parent) :
restoreDefaults();
connect(_ui->buttonBox, SIGNAL(clicked(QAbstractButton *)), this, SLOT(closeDialog(QAbstractButton *)));
connect(_ui->detectMoreLoopClosures, SIGNAL(clicked(bool)), this, SLOT(updateButtonBox()));
connect(_ui->refineNeighborLinks, SIGNAL(stateChanged(int)), this, SLOT(updateButtonBox()));
connect(_ui->refineLoopClosureLinks, SIGNAL(stateChanged(int)), this, SLOT(updateButtonBox()));
@@ -67,6 +70,8 @@ PostProcessingDialog::PostProcessingDialog(QWidget * parent) :
connect(_ui->clusterRadius, SIGNAL(valueChanged(double)), this, SIGNAL(configChanged()));
connect(_ui->clusterAngle, SIGNAL(valueChanged(double)), this, SIGNAL(configChanged()));
connect(_ui->iterations, SIGNAL(valueChanged(int)), this, SIGNAL(configChanged()));
connect(_ui->intraSession, SIGNAL(stateChanged(int)), this, SIGNAL(configChanged()));
connect(_ui->interSession, SIGNAL(stateChanged(int)), this, SIGNAL(configChanged()));
connect(_ui->refineNeighborLinks, SIGNAL(stateChanged(int)), this, SIGNAL(configChanged()));
connect(_ui->refineLoopClosureLinks, SIGNAL(stateChanged(int)), this, SIGNAL(configChanged()));
@@ -84,6 +89,43 @@ PostProcessingDialog::~PostProcessingDialog()
delete _ui;
}
void PostProcessingDialog::closeDialog ( QAbstractButton * button )
{
UDEBUG("");
QDialogButtonBox::ButtonRole role = _ui->buttonBox->buttonRole(button);
switch(role)
{
case QDialogButtonBox::RejectRole:
this->reject();
break;
case QDialogButtonBox::AcceptRole:
if(validateForm())
{
this->accept();
}
else
{
this->reject();
}
break;
default:
break;
}
}
bool PostProcessingDialog::validateForm()
{
if(!this->intraSession() && !this->interSession())
{
QMessageBox::warning(this, tr("Configuration error"), tr("Intra-session and inter-session parameters cannot be both disabled at the same time. Please select one (or both)."));
return false;
}
return true;
}
void PostProcessingDialog::updateVisibility()
{
_ui->sba_variance->setVisible(_ui->comboBox_sbaType->currentIndex() == 0);
@@ -100,6 +142,8 @@ void PostProcessingDialog::saveSettings(QSettings & settings, const QString & gr
settings.setValue("cluster_radius", this->clusterRadius());
settings.setValue("cluster_angle", this->clusterAngle());
settings.setValue("iterations", this->iterations());
settings.setValue("intra_session", this->intraSession());
settings.setValue("inter_session", this->interSession());
settings.setValue("refine_neigbors", this->isRefineNeighborLinks());
settings.setValue("refine_lc", this->isRefineLoopClosureLinks());
settings.setValue("sba", this->isSBA());
@@ -123,6 +167,8 @@ void PostProcessingDialog::loadSettings(QSettings & settings, const QString & gr
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->setIntraSession(settings.value("intra_session", this->intraSession()).toBool());
this->setInterSession(settings.value("inter_session", this->interSession()).toBool());
this->setRefineNeighborLinks(settings.value("refine_neigbors", this->isRefineNeighborLinks()).toBool());
this->setRefineLoopClosureLinks(settings.value("refine_lc", this->isRefineLoopClosureLinks()).toBool());
this->setSBA(settings.value("sba", this->isSBA()).toBool());
@@ -143,6 +189,8 @@ void PostProcessingDialog::restoreDefaults()
setClusterRadius(1);
setClusterAngle(30);
setIterations(5);
setIntraSession(true);
setInterSession(true);
setRefineNeighborLinks(false);
setRefineLoopClosureLinks(false);
setSBA(false);
@@ -178,6 +226,16 @@ int PostProcessingDialog::iterations() const
return _ui->iterations->value();
}
bool PostProcessingDialog::intraSession() const
{
return _ui->intraSession->isChecked();
}
bool PostProcessingDialog::interSession() const
{
return _ui->interSession->isChecked();
}
bool PostProcessingDialog::isRefineNeighborLinks() const
{
return _ui->refineNeighborLinks->isChecked();
@@ -227,6 +285,14 @@ void PostProcessingDialog::setIterations(int iterations)
{
_ui->iterations->setValue(iterations);
}
void PostProcessingDialog::setIntraSession(bool enabled)
{
_ui->intraSession->setChecked(enabled);
}
void PostProcessingDialog::setInterSession(bool enabled)
{
_ui->interSession->setChecked(enabled);
}
void PostProcessingDialog::setRefineNeighborLinks(bool on)
{
_ui->refineNeighborLinks->setChecked(on);

View File

@@ -61,7 +61,7 @@
<rect>
<x>0</x>
<y>0</y>
<width>287</width>
<width>413</width>
<height>288</height>
</rect>
</property>
@@ -287,7 +287,7 @@
<rect>
<x>0</x>
<y>0</y>
<width>287</width>
<width>412</width>
<height>288</height>
</rect>
</property>
@@ -1291,7 +1291,7 @@
<item>
<widget class="QToolBox" name="toolBox">
<property name="currentIndex">
<number>1</number>
<number>2</number>
</property>
<widget class="QWidget" name="page_3">
<property name="geometry">
@@ -1459,7 +1459,7 @@
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<y>-151</y>
<width>519</width>
<height>791</height>
</rect>
@@ -1994,14 +1994,21 @@
<rect>
<x>0</x>
<y>0</y>
<width>205</width>
<height>114</height>
<width>310</width>
<height>243</height>
</rect>
</property>
<attribute name="label">
<string>Detect more loop closures</string>
</attribute>
<layout class="QGridLayout" name="gridLayout_10" columnstretch="0,1">
<item row="3" column="1">
<widget class="QLabel" name="label_32">
<property name="text">
<string>Intra-session</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QDoubleSpinBox" name="doubleSpinBox_detectMore_radius">
<property name="suffix">
@@ -2074,7 +2081,7 @@
</property>
</widget>
</item>
<item row="3" column="0">
<item row="5" column="0">
<spacer name="verticalSpacer_5">
<property name="orientation">
<enum>Qt::Vertical</enum>
@@ -2087,6 +2094,27 @@
</property>
</spacer>
</item>
<item row="4" column="1">
<widget class="QLabel" name="label_34">
<property name="text">
<string>Inter-session</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QCheckBox" name="checkBox_detectMore_intraSession">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QCheckBox" name="checkBox_detectMore_interSession">
<property name="text">
<string/>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="page_2">

View File

@@ -7,7 +7,7 @@
<x>0</x>
<y>0</y>
<width>552</width>
<height>562</height>
<height>633</height>
</rect>
</property>
<property name="windowTitle">
@@ -110,6 +110,40 @@
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QLabel" name="label_7">
<property name="text">
<string>Intra-session</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QLabel" name="label_9">
<property name="text">
<string>Inter-session</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QCheckBox" name="intraSession">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QCheckBox" name="interSession">
<property name="text">
<string/>
</property>
</widget>
</item>
</layout>
</item>
<item>