Optimizer: fixed bad g2o optimizations on 2d slam when there are 3D landmarks (#384). DBViewer: landmarks can be now visualized.

This commit is contained in:
matlabbe
2019-04-26 14:03:25 -04:00
parent f9b7b54454
commit a5350c4891
11 changed files with 289 additions and 285 deletions

View File

@@ -370,7 +370,6 @@ DatabaseViewer::DatabaseViewer(const QString & ini, QWidget * parent) :
connect(ui_->checkBox_ignoreLocalLoopSpace, SIGNAL(stateChanged(int)), this, SLOT(updateGraphView()));
connect(ui_->checkBox_ignoreLocalLoopTime, SIGNAL(stateChanged(int)), this, SLOT(updateGraphView()));
connect(ui_->checkBox_ignoreUserLoop, SIGNAL(stateChanged(int)), this, SLOT(updateGraphView()));
connect(ui_->spinBox_optimizationDepth, SIGNAL(editingFinished()), this, SLOT(updateGraphView()));
connect(ui_->doubleSpinBox_optimizationScale, SIGNAL(editingFinished()), this, SLOT(updateGraphView()));
connect(ui_->checkBox_octomap, SIGNAL(stateChanged(int)), this, SLOT(updateGrid()));
connect(ui_->checkBox_grid_2d, SIGNAL(stateChanged(int)), this, SLOT(updateGrid()));
@@ -698,7 +697,6 @@ void DatabaseViewer::restoreDefaultSettings()
ui_->checkBox_ignoreLocalLoopSpace->setChecked(false);
ui_->checkBox_ignoreLocalLoopTime->setChecked(false);
ui_->checkBox_ignoreUserLoop->setChecked(false);
ui_->spinBox_optimizationDepth->setValue(0);
ui_->doubleSpinBox_optimizationScale->setValue(1.0);
ui_->doubleSpinBox_gainCompensationRadius->setValue(0.0);
ui_->doubleSpinBox_voxelSize->setValue(0.0);
@@ -1600,7 +1598,7 @@ void DatabaseViewer::updateIds()
QApplication::processEvents();
std::multimap<int, Link> unilinks;
dbDriver_->getAllLinks(unilinks, true);
dbDriver_->getAllLinks(unilinks, true, true);
UDEBUG("%d total links loaded", (int)unilinks.size());
// add both direction links
std::multimap<int, Link> links;
@@ -1694,7 +1692,7 @@ void DatabaseViewer::updateIds()
std::multimap<int, Link>::iterator invertedLinkIter = graph::findLink(links, jter->second.to(), jter->second.from(), false);
if( jter->second.isValid() && // null transform means a rehearsed location
ids.find(jter->second.from()) != ids.end() &&
ids.find(jter->second.to()) != ids.end() &&
(ids.find(jter->second.to()) != ids.end() || jter->second.to()<0) && // to add landmark links
graph::findLink(links_, jter->second.from(), jter->second.to()) == links_.end() &&
invertedLinkIter != links.end())
{
@@ -4995,14 +4993,15 @@ void DatabaseViewer::updateConstraintView(
ui_->checkBox_showOptimized->setEnabled(false);
UASSERT(!t.isNull() && dbDriver_);
ui_->label_type->setText(tr("%1 (%2)")
.arg(link.type())
ui_->label_type->setText(QString::number(link.type()));
ui_->label_type_name->setText(tr("(%1)")
.arg(link.type()==Link::kNeighbor?"Neighbor":
link.type()==Link::kNeighborMerged?"Merged neighbor":
link.type()==Link::kGlobalClosure?"Loop closure":
link.type()==Link::kLocalSpaceClosure?"Space proximity link":
link.type()==Link::kLocalTimeClosure?"Time proximity link":
link.type()==Link::kUserClosure?"User link":
link.type()==Link::kLandmark?"Landmark link":
link.type()==Link::kVirtualClosure?"Virtual link":"Undefined"));
ui_->label_variance->setText(QString("%1, %2")
.arg(sqrt(link.transVariance()))
@@ -5040,45 +5039,51 @@ void DatabaseViewer::updateConstraintView(
{
ui_->horizontalSlider_A->blockSignals(true);
ui_->horizontalSlider_B->blockSignals(true);
// set from on left and to on right {
ui_->horizontalSlider_A->setValue(idToIndex_.value(link.from()));
ui_->horizontalSlider_B->setValue(idToIndex_.value(link.to()));
// set from on left and to on right
if(link.from()>0)
ui_->horizontalSlider_A->setValue(idToIndex_.value(link.from()));
if(link.to() > 0)
ui_->horizontalSlider_B->setValue(idToIndex_.value(link.to()));
ui_->horizontalSlider_A->blockSignals(false);
ui_->horizontalSlider_B->blockSignals(false);
this->update(idToIndex_.value(link.from()),
ui_->label_indexA,
ui_->label_parentsA,
ui_->label_childrenA,
ui_->label_weightA,
ui_->label_labelA,
ui_->label_stampA,
ui_->graphicsView_A,
ui_->label_idA,
ui_->label_mapA,
ui_->label_poseA,
ui_->label_velA,
ui_->label_calibA,
ui_->label_scanA,
ui_->label_gpsA,
ui_->label_sensorsA,
false); // don't update constraints view!
this->update(idToIndex_.value(link.to()),
ui_->label_indexB,
ui_->label_parentsB,
ui_->label_childrenB,
ui_->label_weightB,
ui_->label_labelB,
ui_->label_stampB,
ui_->graphicsView_B,
ui_->label_idB,
ui_->label_mapB,
ui_->label_poseB,
ui_->label_velB,
ui_->label_calibB,
ui_->label_scanB,
ui_->label_gpsB,
ui_->label_sensorsB,
false); // don't update constraints view!
if(link.from()>0)
this->update(idToIndex_.value(link.from()),
ui_->label_indexA,
ui_->label_parentsA,
ui_->label_childrenA,
ui_->label_weightA,
ui_->label_labelA,
ui_->label_stampA,
ui_->graphicsView_A,
ui_->label_idA,
ui_->label_mapA,
ui_->label_poseA,
ui_->label_velA,
ui_->label_calibA,
ui_->label_scanA,
ui_->label_gpsA,
ui_->label_sensorsA,
false); // don't update constraints view!
if(link.to()>0)
{
this->update(idToIndex_.value(link.to()),
ui_->label_indexB,
ui_->label_parentsB,
ui_->label_childrenB,
ui_->label_weightB,
ui_->label_labelB,
ui_->label_stampB,
ui_->graphicsView_B,
ui_->label_idB,
ui_->label_mapB,
ui_->label_poseB,
ui_->label_velB,
ui_->label_calibB,
ui_->label_scanB,
ui_->label_gpsB,
ui_->label_sensorsB,
false); // don't update constraints view!
}
}
if(constraintsViewer_->isVisible())
@@ -5989,8 +5994,7 @@ void DatabaseViewer::updateGraphView()
int currentMapId = mapIds_.at(fromId);
for(std::map<int, rtabmap::Transform>::iterator iter=poses.begin(); iter!=poses.end();)
{
if(!uContains(mapIds_, iter->first) ||
mapIds_.at(iter->first) != currentMapId)
if(iter->first>0 && (!uContains(mapIds_, iter->first) || mapIds_.at(iter->first) != currentMapId))
{
poses.erase(iter++);
}
@@ -6011,10 +6015,8 @@ void DatabaseViewer::updateGraphView()
int currentMapId = mapIds_.at(fromId);
for(std::multimap<int, rtabmap::Link>::iterator iter=links.begin(); iter!=links.end();)
{
if(!uContains(mapIds_, iter->second.from()) ||
!uContains(mapIds_, iter->second.to()) ||
mapIds_.at(iter->second.from()) != currentMapId ||
mapIds_.at(iter->second.to()) != currentMapId)
if((iter->second.from()>0 && (!uContains(mapIds_, iter->second.from()) || mapIds_.at(iter->second.from()) != currentMapId)) ||
(iter->second.to()>0 && (!uContains(mapIds_, iter->second.to()) || mapIds_.at(iter->second.to()) != currentMapId)))
{
links.erase(iter++);
}
@@ -6056,6 +6058,7 @@ void DatabaseViewer::updateGraphView()
int totalLocalSpace = 0;
int totalUser = 0;
int totalPriors = 0;
int totalLandmarks = 0;
for(std::multimap<int, rtabmap::Link>::iterator iter=links.begin(); iter!=links.end();)
{
if(iter->second.type() == Link::kNeighbor)
@@ -6106,6 +6109,16 @@ void DatabaseViewer::updateGraphView()
loopLinks_.push_back(iter->second);
++totalUser;
}
else if(iter->second.type() == Link::kLandmark)
{
UASSERT(iter->second.from() > 0 && iter->second.to() < 0);
if(poses.find(iter->second.from()) != poses.end() && poses.find(iter->second.to()) == poses.end())
{
poses.insert(std::make_pair(iter->second.to(), poses.at(iter->second.from())*iter->second.transform()));
}
loopLinks_.push_back(iter->second);
++totalLandmarks;
}
else if(iter->second.type() == Link::kPosePrior)
{
++totalPriors;
@@ -6118,14 +6131,15 @@ void DatabaseViewer::updateGraphView()
}
updateLoopClosuresSlider();
ui_->label_loopClosures->setText(tr("(%1, %2, %3, %4, %5, %6, %7)")
ui_->label_loopClosures->setText(tr("(%1, %2, %3, %4, %5, %6, %7, %8)")
.arg(totalNeighbor)
.arg(totalNeighborMerged)
.arg(totalGlobal)
.arg(totalLocalSpace)
.arg(totalLocalTime)
.arg(totalUser)
.arg(totalPriors));
.arg(totalPriors)
.arg(totalLandmarks));
// remove intermediate nodes?
if(ui_->checkBox_ignoreIntermediateNodes->isVisible() &&
@@ -6170,8 +6184,7 @@ void DatabaseViewer::updateGraphView()
poses,
links,
posesOut,
linksOut,
ui_->spinBox_optimizationDepth->value());
linksOut);
if(optimizedGraphGuess.size() == posesOut.size())
{
bool identical=true;

View File

@@ -2646,7 +2646,7 @@ void MainWindow::updateMapCloud(
for(std::map<int, Transform>::const_iterator iter=posesIn.begin(); iter!=posesIn.end() && iter->first<0; ++iter)
{
#if PCL_VERSION_COMPARE(>=, 1, 7, 2)
_cloudViewer->addOrUpdateCoordinate(uFormat("landmark_%d", -iter->first), iter->second, _preferencesDialog->getMarkerLength()<=0?0.1:_preferencesDialog->getMarkerLength()/2.0, false);
_cloudViewer->addOrUpdateCoordinate(uFormat("landmark_%d", -iter->first), iter->second, _preferencesDialog->landmarkVisSize()>0.0?_preferencesDialog->landmarkVisSize():_preferencesDialog->getMarkerLength()<=0?0.1:_preferencesDialog->getMarkerLength()/2.0, false);
#endif
if(_preferencesDialog->isLabelsShown())
{

View File

@@ -502,6 +502,7 @@ PreferencesDialog::PreferencesDialog(QWidget * parent) :
connect(_ui->checkBox_showGraphs, SIGNAL(stateChanged(int)), this, SLOT(makeObsoleteCloudRenderingPanel()));
connect(_ui->checkBox_showLabels, SIGNAL(stateChanged(int)), this, SLOT(makeObsoleteCloudRenderingPanel()));
connect(_ui->checkBox_showLandmarks, SIGNAL(stateChanged(int)), this, SLOT(makeObsoleteCloudRenderingPanel()));
connect(_ui->doubleSpinBox_landmarkSize, SIGNAL(valueChanged(double)), this, SLOT(makeObsoleteCloudRenderingPanel()));
connect(_ui->radioButton_noFiltering, SIGNAL(toggled(bool)), this, SLOT(makeObsoleteCloudRenderingPanel()));
connect(_ui->radioButton_nodeFiltering, SIGNAL(toggled(bool)), this, SLOT(makeObsoleteCloudRenderingPanel()));
@@ -1611,6 +1612,7 @@ void PreferencesDialog::resetSettings(QGroupBox * groupBox)
_ui->checkBox_showGraphs->setChecked(true);
_ui->checkBox_showLabels->setChecked(false);
_ui->checkBox_showLandmarks->setChecked(true);
_ui->doubleSpinBox_landmarkSize->setValue(0);
_ui->doubleSpinBox_mesh_angleTolerance->setValue(15.0);
_ui->groupBox_organized->setChecked(false);
@@ -2028,6 +2030,7 @@ void PreferencesDialog::readGuiSettings(const QString & filePath)
_ui->checkBox_showGraphs->setChecked(settings.value("showGraphs", _ui->checkBox_showGraphs->isChecked()).toBool());
_ui->checkBox_showLabels->setChecked(settings.value("showLabels", _ui->checkBox_showLabels->isChecked()).toBool());
_ui->checkBox_showLandmarks->setChecked(settings.value("showLandmarks", _ui->checkBox_showLandmarks->isChecked()).toBool());
_ui->doubleSpinBox_landmarkSize->setValue(settings.value("landmarkSize", _ui->doubleSpinBox_landmarkSize->value()).toDouble());
_ui->radioButton_noFiltering->setChecked(settings.value("noFiltering", _ui->radioButton_noFiltering->isChecked()).toBool());
_ui->radioButton_nodeFiltering->setChecked(settings.value("cloudFiltering", _ui->radioButton_nodeFiltering->isChecked()).toBool());
@@ -2449,6 +2452,7 @@ void PreferencesDialog::writeGuiSettings(const QString & filePath) const
settings.setValue("showGraphs", _ui->checkBox_showGraphs->isChecked());
settings.setValue("showLabels", _ui->checkBox_showLabels->isChecked());
settings.setValue("showLandmarks", _ui->checkBox_showLandmarks->isChecked());
settings.setValue("landmarkSize", _ui->doubleSpinBox_landmarkSize->value());
settings.setValue("noFiltering", _ui->radioButton_noFiltering->isChecked());
@@ -4687,6 +4691,10 @@ bool PreferencesDialog::isLandmarksShown() const
{
return _ui->checkBox_showLandmarks->isChecked();
}
double PreferencesDialog::landmarkVisSize() const
{
return _ui->doubleSpinBox_landmarkSize->value();
}
bool PreferencesDialog::isMarkerDetection() const
{
return _ui->RGBDMarkerDetection->isChecked();

View File

@@ -61,7 +61,7 @@
<rect>
<x>0</x>
<y>0</y>
<width>413</width>
<width>409</width>
<height>288</height>
</rect>
</property>
@@ -287,7 +287,7 @@
<rect>
<x>0</x>
<y>0</y>
<width>412</width>
<width>408</width>
<height>288</height>
</rect>
</property>
@@ -870,16 +870,6 @@
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLabel" name="label_type">
<property name="text">
<string/>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_16">
<property name="text">
@@ -921,6 +911,30 @@
</property>
</widget>
</item>
<item row="2" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_14" stretch="0,1">
<item>
<widget class="QLabel" name="label_type">
<property name="text">
<string/>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_type_name">
<property name="text">
<string/>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</item>
<item>
@@ -1075,7 +1089,7 @@
<item row="9" column="1">
<widget class="QLabel" name="label_41">
<property name="text">
<string>Links (N, NM, G, LS, LT, U, P)</string>
<string>Links (N, NM, G, LS, LT, U, P, LM)</string>
</property>
</widget>
</item>
@@ -1294,7 +1308,7 @@
<item>
<widget class="QToolBox" name="toolBox">
<property name="currentIndex">
<number>2</number>
<number>0</number>
</property>
<widget class="QWidget" name="page_3">
<property name="geometry">
@@ -1302,28 +1316,31 @@
<x>0</x>
<y>0</y>
<width>318</width>
<height>197</height>
<height>165</height>
</rect>
</property>
<attribute name="label">
<string>Graph optimization</string>
</attribute>
<layout class="QGridLayout" name="gridLayout_7" columnstretch="0,0,1">
<item row="0" column="2">
<widget class="QLabel" name="label_8">
<layout class="QGridLayout" name="gridLayout_7" columnstretch="0,0,0">
<item row="2" column="0">
<widget class="QCheckBox" name="checkBox_ignoreGlobalLoop">
<property name="text">
<string>Depth (0=inf)</string>
<string/>
</property>
<property name="checked">
<bool>false</bool>
</property>
</widget>
</item>
<item row="5" column="2">
<item row="4" column="2">
<widget class="QLabel" name="label_49">
<property name="text">
<string>Ignore local loop closures (time)</string>
</property>
</widget>
</item>
<item row="4" column="0">
<item row="3" column="0">
<widget class="QCheckBox" name="checkBox_ignoreLocalLoopSpace">
<property name="text">
<string/>
@@ -1333,21 +1350,21 @@
</property>
</widget>
</item>
<item row="3" column="2">
<item row="2" column="2">
<widget class="QLabel" name="label_48">
<property name="text">
<string>Ignore global loop closures</string>
</property>
</widget>
</item>
<item row="2" column="2">
<item row="1" column="2">
<widget class="QLabel" name="label_35">
<property name="text">
<string>Ignore pose correction</string>
</property>
</widget>
</item>
<item row="2" column="0">
<item row="1" column="0">
<widget class="QCheckBox" name="checkBox_ignorePoseCorrection">
<property name="text">
<string/>
@@ -1357,7 +1374,7 @@
</property>
</widget>
</item>
<item row="5" column="0">
<item row="4" column="0">
<widget class="QCheckBox" name="checkBox_ignoreLocalLoopTime">
<property name="text">
<string/>
@@ -1367,7 +1384,7 @@
</property>
</widget>
</item>
<item row="7" column="0">
<item row="6" column="0">
<spacer name="verticalSpacer_3">
<property name="orientation">
<enum>Qt::Vertical</enum>
@@ -1380,7 +1397,7 @@
</property>
</spacer>
</item>
<item row="6" column="0">
<item row="5" column="0">
<widget class="QCheckBox" name="checkBox_ignoreUserLoop">
<property name="text">
<string/>
@@ -1390,38 +1407,28 @@
</property>
</widget>
</item>
<item row="6" column="2">
<item row="5" column="2">
<widget class="QLabel" name="label_50">
<property name="text">
<string>Ignore user loop closures</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QCheckBox" name="checkBox_ignoreGlobalLoop">
<property name="text">
<string/>
</property>
<property name="checked">
<bool>false</bool>
</property>
</widget>
</item>
<item row="4" column="2">
<item row="3" column="2">
<widget class="QLabel" name="label_47">
<property name="text">
<string>Ignore local loop closures (space)</string>
</property>
</widget>
</item>
<item row="1" column="2">
<item row="0" column="2">
<widget class="QLabel" name="label_scale_title">
<property name="text">
<string>Scale</string>
</property>
</widget>
</item>
<item row="1" column="0">
<item row="0" column="0">
<widget class="QDoubleSpinBox" name="doubleSpinBox_optimizationScale">
<property name="decimals">
<number>3</number>
@@ -1440,22 +1447,6 @@
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QSpinBox" name="spinBox_optimizationDepth">
<property name="suffix">
<string/>
</property>
<property name="minimum">
<number>0</number>
</property>
<property name="maximum">
<number>1000</number>
</property>
<property name="value">
<number>0</number>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="page_4">
@@ -1463,8 +1454,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>280</width>
<height>875</height>
<width>519</width>
<height>791</height>
</rect>
</property>
<attribute name="label">

View File

@@ -94,7 +94,7 @@
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<y>-1219</y>
<width>680</width>
<height>3082</height>
</rect>
@@ -126,7 +126,7 @@
<enum>QFrame::Raised</enum>
</property>
<property name="currentIndex">
<number>21</number>
<number>1</number>
</property>
<widget class="QWidget" name="page_22">
<layout class="QVBoxLayout" name="verticalLayout_29" stretch="0,1">
@@ -1901,6 +1901,35 @@ Show a yellow background when the number of odometry inliers goes under this thr
</property>
</widget>
</item>
<item row="7" column="2">
<widget class="QLabel" name="label_528">
<property name="text">
<string>Landmark size. If zero, marker's length parameter is used.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item row="7" column="0">
<widget class="QDoubleSpinBox" name="doubleSpinBox_landmarkSize">
<property name="suffix">
<string> m</string>
</property>
<property name="minimum">
<double>0.000000000000000</double>
</property>
<property name="singleStep">
<double>0.100000000000000</double>
</property>
<property name="value">
<double>0.100000000000000</double>
</property>
</widget>
</item>
</layout>
</widget>
</item>