Pnp multicam refactoring (#902)

* gui: fixed wrongly showing landmark rejected when it was not (because a loop closure was rejected at the same time)

* Added Vis/PnPMaxVariance and RGBD/InvertedReg parameters. Implemented inlier distribution computation for multicam.

* On loc/small displacement: don't remove from odom cache if loop is rejected (maybe first loc)

* Loc: don't prune odom cache on small movement if delayed loc is enabled

* loc/small movement: cleanup bidirectional links

* Cov/PnP: fixed objPt transform to estimate depth

Co-authored-by: mathieu86 <mathieu@robust.ai>
This commit is contained in:
matlabbe
2022-09-24 12:29:42 -07:00
committed by GitHub
parent 95a76cb696
commit fa31affea0
14 changed files with 685 additions and 495 deletions

View File

@@ -63,6 +63,7 @@ public:
bool isLinesShown() const;
int getAlpha() const {return _alpha;}
int getFeaturesSize() const {return _featuresSize;}
int getLinesWidth() const {return _linesWidth;}
bool isGraphicsViewMode() const;
bool isGraphicsViewScaled() const;
bool isGraphicsViewScaledToHeight() const;
@@ -101,6 +102,7 @@ public:
void setFeaturesColor(QColor color);
void setAlpha(int alpha);
void setFeaturesSize(int size);
void setLinesWidth(int width);
void setSceneRect(const QRectF & rect);
const QMultiMap<int, rtabmap::KeypointItem *> & getFeatures() const {return _features;}
@@ -131,6 +133,7 @@ private:
QString _savedFileName;
int _alpha;
int _featuresSize;
int _linesWidth;
QColor _defaultBgColor;
QColor _defaultFeatureColor;
QColor _defaultMatchingFeatureColor;
@@ -148,6 +151,7 @@ private:
QAction * _saveImage;
QAction * _setAlpha;
QAction * _setFeaturesSize;
QAction * _setLinesWidth;
QAction * _graphicsViewMode;
QAction * _graphicsViewScaled;
QAction * _graphicsViewScaledToHeight;

View File

@@ -68,7 +68,11 @@ public:
delete _placeHolder;
}
void setColor(const QColor & color);
void setWidth(int width)
{
_width = width;
this->setPen(QPen(pen().color(), _width));
}
protected:
virtual void hoverEnterEvent ( QGraphicsSceneHoverEvent * event )
@@ -166,6 +170,7 @@ ImageView::ImageView(QWidget * parent) :
QWidget(parent),
_alpha(100),
_featuresSize(0.0f),
_linesWidth(0),
_defaultBgColor(Qt::black),
_defaultFeatureColor(Qt::yellow),
_defaultMatchingFeatureColor(Qt::magenta),
@@ -211,6 +216,7 @@ ImageView::ImageView(QWidget * parent) :
_showLines = _featureMenu->addAction(tr("Show lines"));
_showLines->setCheckable(true);
_showLines->setChecked(true);
_setLinesWidth = _featureMenu->addAction(tr("Set lines width..."));
_setFeatureColor = _featureMenu->addAction(tr("Set default feature color"));
_setFeatureColor->setIcon(createIcon(_defaultFeatureColor));
_setFeatureColor->setIconVisibleInMenu(true);
@@ -280,6 +286,7 @@ void ImageView::saveSettings(QSettings & settings, const QString & group) const
settings.setValue("features_shown", this->isFeaturesShown());
settings.setValue("features_size", this->getFeaturesSize());
settings.setValue("lines_shown", this->isLinesShown());
settings.setValue("lines_width", this->getLinesWidth());
settings.setValue("alpha", this->getAlpha());
settings.setValue("bg_color", this->getDefaultBackgroundColor());
settings.setValue("feature_color", this->getDefaultFeatureColor());
@@ -307,6 +314,7 @@ void ImageView::loadSettings(QSettings & settings, const QString & group)
this->setFeaturesShown(settings.value("features_shown", this->isFeaturesShown()).toBool());
this->setFeaturesSize(settings.value("features_size", this->getFeaturesSize()).toInt());
this->setLinesShown(settings.value("lines_shown", this->isLinesShown()).toBool());
this->setLinesWidth(settings.value("lines_width", this->getLinesWidth()).toInt());
this->setAlpha(settings.value("alpha", this->getAlpha()).toInt());
this->setDefaultBackgroundColor(settings.value("bg_color", this->getDefaultBackgroundColor()).value<QColor>());
this->setDefaultFeatureColor(settings.value("feature_color", this->getDefaultFeatureColor()).value<QColor>());
@@ -796,9 +804,8 @@ void ImageView::paintEvent(QPaintEvent *event)
{
for(QList<QGraphicsLineItem*>::iterator iter = _lines.begin(); iter != _lines.end(); ++iter)
{
QColor color = (*iter)->pen().color();
painter.save();
painter.setPen(color);
painter.setPen(QPen((*iter)->pen().color(), _linesWidth));
painter.drawLine((*iter)->line());
painter.restore();
}
@@ -996,6 +1003,16 @@ void ImageView::contextMenuEvent(QContextMenuEvent * e)
Q_EMIT configChanged();
}
}
else if(action == _setLinesWidth)
{
bool ok = false;
int value = QInputDialog::getInt(this, tr("Set lines width"), tr("Width"), _linesWidth, 0, 999, 1, &ok);
if(ok)
{
this->setLinesWidth(value);
Q_EMIT configChanged();
}
}
if(action == _showImage || action ==_showImageDepth)
{
@@ -1112,6 +1129,7 @@ void ImageView::addLine(float x1, float y1, float x2, float y2, QColor color, co
color.setAlpha(this->getAlpha());
LineItem * item = new LineItem(x1, y1, x2, y2, text);
item->setPen(QPen(color));
item->setWidth(_linesWidth);
_lines.push_back(item);
item->setVisible(isLinesShown());
item->setZValue(1);
@@ -1273,6 +1291,22 @@ void ImageView::setFeaturesSize(int size)
}
}
void ImageView::setLinesWidth(int width)
{
_linesWidth = width;
for(QList<QGraphicsLineItem*>::iterator iter=_lines.begin(); iter!=_lines.end(); ++iter)
{
if(dynamic_cast<LineItem*>(*iter))
{
((LineItem*)(*iter))->setWidth(_linesWidth);
}
}
if(!_graphicsView->isVisible())
{
this->update();
}
}
void ImageView::setSceneRect(const QRectF & rect)
{
_graphicsView->scene()->setSceneRect(rect);

View File

@@ -2186,12 +2186,30 @@ void MainWindow::processStats(const rtabmap::Statistics & stat)
//draw markers
if(!signature.getLandmarks().empty())
{
refImage = refImage.clone();
if(refImage.channels() == 1)
{
cv::Mat imgColor;
cvtColor(refImage, imgColor, cv::COLOR_GRAY2BGR);
refImage = imgColor;
}
else
{
refImage = refImage.clone();
}
drawLandmarks(refImage, signature);
}
if(!loopSignature.getLandmarks().empty())
{
loopImage = loopImage.clone();
if(loopImage.channels() == 1)
{
cv::Mat imgColor;
cv::cvtColor(loopImage, imgColor, cv::COLOR_GRAY2BGR);
loopImage = imgColor;
}
else
{
loopImage = loopImage.clone();
}
drawLandmarks(loopImage, loopSignature);
}
}
@@ -4910,44 +4928,72 @@ void MainWindow::drawLandmarks(cv::Mat & image, const Signature & signature)
{
for(std::map<int, Link>::const_iterator iter=signature.getLandmarks().begin(); iter!=signature.getLandmarks().end(); ++iter)
{
CameraModel model;
if(!signature.sensorData().cameraModels().empty() &&
signature.sensorData().cameraModels()[0].isValidForProjection())
// Project in all cameras in which the landmark is visible
for(size_t i=0; i<signature.sensorData().cameraModels().size() || i<signature.sensorData().stereoCameraModels().size(); ++i)
{
model = signature.sensorData().cameraModels()[0];
}
else if(!signature.sensorData().stereoCameraModels().empty() &&
signature.sensorData().stereoCameraModels()[0].isValidForProjection())
{
model = signature.sensorData().stereoCameraModels()[0].left();
}
if(model.isValidForProjection())
{
Transform t = model.localTransform().inverse() * iter->second.transform();
cv::Vec3d rvec, tvec;
tvec.val[0] = t.x();
tvec.val[1] = t.y();
tvec.val[2] = t.z();
cv::Mat R;
t.rotationMatrix().convertTo(R, CV_64F);
cv::Rodrigues(R, rvec);
CameraModel model;
if(i<signature.sensorData().cameraModels().size())
{
model = signature.sensorData().cameraModels()[i];
}
else if(i<signature.sensorData().stereoCameraModels().size())
{
model = signature.sensorData().stereoCameraModels()[i].left();
}
if(model.isValidForProjection())
{
Transform t = model.localTransform().inverse() * iter->second.transform();
cv::Vec3d rvec, tvec;
tvec.val[0] = t.x();
tvec.val[1] = t.y();
tvec.val[2] = t.z();
//cv::aruco::drawAxis(image, model.K(), model.D(), rvec, tvec, _preferencesDialog->getMarkerLength()<=0?0.1:_preferencesDialog->getMarkerLength() * 0.5f);
// In front of the camera?
if(t.z() > 0)
{
cv::Mat R;
t.rotationMatrix().convertTo(R, CV_64F);
cv::Rodrigues(R, rvec);
// project axis points
std::vector< cv::Point3f > axisPoints;
float length = _preferencesDialog->getMarkerLength()<=0?0.1:_preferencesDialog->getMarkerLength() * 0.5f;
axisPoints.push_back(cv::Point3f(0, 0, 0));
axisPoints.push_back(cv::Point3f(length, 0, 0));
axisPoints.push_back(cv::Point3f(0, length, 0));
axisPoints.push_back(cv::Point3f(0, 0, length));
std::vector< cv::Point2f > imagePoints;
projectPoints(axisPoints, rvec, tvec, model.K(), model.D(), imagePoints);
// draw axis lines
cv::line(image, imagePoints[0], imagePoints[1], cv::Scalar(0, 0, 255), 3);
cv::line(image, imagePoints[0], imagePoints[2], cv::Scalar(0, 255, 0), 3);
cv::line(image, imagePoints[0], imagePoints[3], cv::Scalar(255, 0, 0), 3);
cv::putText(image, uNumber2Str(-iter->first), imagePoints[0], cv::FONT_HERSHEY_SIMPLEX, 0.75, cv::Scalar(0, 255, 255), 2);
//cv::aruco::drawAxis(image, model.K(), model.D(), rvec, tvec, _preferencesDialog->getMarkerLength()<=0?0.1:_preferencesDialog->getMarkerLength() * 0.5f);
// project axis points
std::vector< cv::Point3f > axisPoints;
float length = _preferencesDialog->getMarkerLength()<=0?0.1:_preferencesDialog->getMarkerLength() * 0.5f;
axisPoints.push_back(cv::Point3f(0, 0, 0));
axisPoints.push_back(cv::Point3f(length, 0, 0));
axisPoints.push_back(cv::Point3f(0, length, 0));
axisPoints.push_back(cv::Point3f(0, 0, length));
std::vector< cv::Point2f > imagePoints;
projectPoints(axisPoints, rvec, tvec, model.K(), model.D(), imagePoints);
//offset x based on camera index
bool valid = true;
if(i!=0)
{
if(model.imageWidth() <= 0)
{
valid = false;
UWARN("Cannot draw correctly landmark %d with provided camera model %d (missing image width)", -iter->first, (int)i);
}
else
{
for(int j=0; j<4; ++j)
{
imagePoints[j].x += i*model.imageWidth();
}
}
}
if(valid)
{
// draw axis lines
cv::line(image, imagePoints[0], imagePoints[1], cv::Scalar(0, 0, 255), 3);
cv::line(image, imagePoints[0], imagePoints[2], cv::Scalar(0, 255, 0), 3);
cv::line(image, imagePoints[0], imagePoints[3], cv::Scalar(255, 0, 0), 3);
cv::putText(image, uNumber2Str(-iter->first), imagePoints[0], cv::FONT_HERSHEY_SIMPLEX, 0.75, cv::Scalar(0, 255, 255), 2);
}
}
}
}
}
}

View File

@@ -1130,6 +1130,7 @@ PreferencesDialog::PreferencesDialog(QWidget * parent) :
_ui->loopClosure_identityGuess->setObjectName(Parameters::kRGBDLoopClosureIdentityGuess().c_str());
_ui->loopClosure_reextract->setObjectName(Parameters::kRGBDLoopClosureReextractFeatures().c_str());
_ui->loopClosure_bunlde->setObjectName(Parameters::kRGBDLocalBundleOnLoopClosure().c_str());
_ui->loopClosure_invertedReg->setObjectName(Parameters::kRGBDInvertedReg().c_str());
_ui->checkbox_rgbd_createOccupancyGrid->setObjectName(Parameters::kRGBDCreateOccupancyGrid().c_str());
_ui->RGBDMarkerDetection->setObjectName(Parameters::kRGBDMarkerDetection().c_str());
_ui->spinBox_maxOdomCacheSize->setObjectName(Parameters::kRGBDMaxOdomCacheSize().c_str());
@@ -1154,6 +1155,7 @@ PreferencesDialog::PreferencesDialog(QWidget * parent) :
_ui->loopClosure_pnpReprojError->setObjectName(Parameters::kVisPnPReprojError().c_str());
_ui->loopClosure_pnpFlags->setObjectName(Parameters::kVisPnPFlags().c_str());
_ui->loopClosure_pnpRefineIterations->setObjectName(Parameters::kVisPnPRefineIterations().c_str());
_ui->loopClosure_pnpMaxVariance->setObjectName(Parameters::kVisPnPMaxVariance().c_str());
_ui->reextract_nn->setObjectName(Parameters::kVisCorNNType().c_str());
connect(_ui->reextract_nn, SIGNAL(currentIndexChanged(int)), this, SLOT(updateFeatureMatchingVisibility()));
_ui->reextract_nndrRatio->setObjectName(Parameters::kVisCorNNDR().c_str());

View File

@@ -63,7 +63,7 @@
<property name="geometry">
<rect>
<x>0</x>
<y>-454</y>
<y>-853</y>
<width>756</width>
<height>3657</height>
</rect>
@@ -95,7 +95,7 @@
<enum>QFrame::Raised</enum>
</property>
<property name="currentIndex">
<number>5</number>
<number>21</number>
</property>
<widget class="QWidget" name="page_22">
<layout class="QVBoxLayout" name="verticalLayout_29" stretch="0,0">
@@ -10929,10 +10929,10 @@ If set to false, classic RTAB-Map loop closure detection is done using only imag
<string>Map Update</string>
</property>
<layout class="QGridLayout" name="gridLayout_47" columnstretch="0,1">
<item row="2" column="1">
<widget class="QLabel" name="label_432">
<item row="8" column="1">
<widget class="QLabel" name="label_scanMatching_14">
<property name="text">
<string>Maximum linear speed to update the map (0 means not limit).</string>
<string>Use Identity matrix as guess when computing loop closure transform, otherwise no guess is used (assuming that registration strategy can deal with transformation estimation without guess).</string>
</property>
<property name="wordWrap">
<bool>true</bool>
@@ -10942,16 +10942,13 @@ If set to false, classic RTAB-Map loop closure detection is done using only imag
</property>
</widget>
</item>
<item row="6" column="1">
<widget class="QLabel" name="label_scanMatching">
<property name="text">
<string>Neighbor link refining. When a new node is added to the graph, the transformation of its neighbor link (odometry) with the previous node is refined using ICP registration approach (laser scans required).</string>
<item row="17" column="0">
<widget class="QDoubleSpinBox" name="maxLocalizationDistance">
<property name="suffix">
<string> m</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
<property name="value">
<double>1.000000000000000</double>
</property>
</widget>
</item>
@@ -10968,16 +10965,61 @@ If set to false, classic RTAB-Map loop closure detection is done using only imag
</property>
</widget>
</item>
<item row="13" column="0">
<widget class="QSpinBox" name="spinBox_maxLocalLocationsRetrieved"/>
<item row="1" column="0">
<widget class="QDoubleSpinBox" name="rgdb_angularUpdate">
<property name="suffix">
<string> rad</string>
</property>
<property name="decimals">
<number>2</number>
</property>
<property name="maximum">
<double>3.140000000000000</double>
</property>
<property name="singleStep">
<double>0.100000000000000</double>
</property>
</widget>
</item>
<item row="9" column="0">
<widget class="QCheckBox" name="loopClosure_reextract">
<item row="12" column="0">
<widget class="QCheckBox" name="memCovOffDiagIgnored">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="16" column="1">
<widget class="QLabel" name="label_space2">
<property name="text">
<string>Local radius for nodes selection in the local map. This parameter is used in some approaches of the sub-panels.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item row="15" column="0">
<widget class="QDoubleSpinBox" name="rgdb_localImmunizationRatio">
<property name="suffix">
<string/>
</property>
<property name="decimals">
<number>2</number>
</property>
<property name="maximum">
<double>1.000000000000000</double>
</property>
<property name="singleStep">
<double>0.100000000000000</double>
</property>
<property name="value">
<double>0.100000000000000</double>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QDoubleSpinBox" name="rgdb_newMapOdomChange">
<property name="suffix">
@@ -10997,121 +11039,6 @@ If set to false, classic RTAB-Map loop closure detection is done using only imag
</property>
</widget>
</item>
<item row="14" column="1">
<widget class="QLabel" name="label_scanMatching_5">
<property name="text">
<string>Ratio of working memory for which local nodes are immunized from transfer.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QCheckBox" name="rgbd_savedLocalizationIgnored">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="9" column="1">
<widget class="QLabel" name="label_scanMatching_9">
<property name="text">
<string>Re-extract visual features when computing loop closure transformations. Raw features are not saved in database.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QDoubleSpinBox" name="rgdb_linearSpeedUpdate">
<property name="suffix">
<string> m/s</string>
</property>
<property name="decimals">
<number>3</number>
</property>
<property name="singleStep">
<double>0.100000000000000</double>
</property>
</widget>
</item>
<item row="6" column="0">
<widget class="QCheckBox" name="odomScanHistory">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="15" column="0">
<widget class="QDoubleSpinBox" name="localDetection_radius">
<property name="suffix">
<string> m</string>
</property>
<property name="value">
<double>1.000000000000000</double>
</property>
</widget>
</item>
<item row="14" column="0">
<widget class="QDoubleSpinBox" name="rgdb_localImmunizationRatio">
<property name="suffix">
<string/>
</property>
<property name="decimals">
<number>2</number>
</property>
<property name="maximum">
<double>1.000000000000000</double>
</property>
<property name="singleStep">
<double>0.100000000000000</double>
</property>
<property name="value">
<double>0.100000000000000</double>
</property>
</widget>
</item>
<item row="11" column="0">
<widget class="QCheckBox" name="memCovOffDiagIgnored">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="QLabel" name="label_163">
<property name="text">
<string>Odometry change detected that triggers a new map (0 means whatever the odometry change, the detector will still link the new pose in the current map). Also by default, when an odometry with Identity transformation is detected, a new map is automatically created. </string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QLabel" name="label_433">
<property name="text">
<string>Maximum angular speed to update the map (0 means not limit).</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item row="10" column="0">
<widget class="QCheckBox" name="loopClosure_bunlde">
<property name="text">
@@ -11119,45 +11046,6 @@ If set to false, classic RTAB-Map loop closure detection is done using only imag
</property>
</widget>
</item>
<item row="10" column="1">
<widget class="QLabel" name="label_scanMatching_10">
<property name="text">
<string>Do local bundle adjustment with neighborhood of the loop closure.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item row="11" column="1">
<widget class="QLabel" name="label_scanMatching_11">
<property name="text">
<string>Ignore off diagonal values of the odometry covariance matrix.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QDoubleSpinBox" name="rgdb_linearUpdate">
<property name="suffix">
<string> m</string>
</property>
<property name="decimals">
<number>3</number>
</property>
<property name="singleStep">
<double>0.100000000000000</double>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLabel" name="label_153">
<property name="text">
@@ -11171,33 +11059,10 @@ If set to false, classic RTAB-Map loop closure detection is done using only imag
</property>
</widget>
</item>
<item row="12" column="0">
<widget class="QCheckBox" name="rgbd_loopCovLimited">
<item row="2" column="1">
<widget class="QLabel" name="label_432">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QDoubleSpinBox" name="rgdb_angularUpdate">
<property name="suffix">
<string> rad</string>
</property>
<property name="decimals">
<number>2</number>
</property>
<property name="maximum">
<double>3.140000000000000</double>
</property>
<property name="singleStep">
<double>0.100000000000000</double>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QLabel" name="label_scanMatching_2">
<property name="text">
<string>If true, rtabmap will assume the robot is restarting from origin of the map. If false, rtabmap will assume the robot is restarting from the last saved localization pose from previous session (the place where it shut down previously). Used only in localization mode.</string>
<string>Maximum linear speed to update the map (0 means not limit).</string>
</property>
<property name="wordWrap">
<bool>true</bool>
@@ -11207,10 +11072,73 @@ If set to false, classic RTAB-Map loop closure detection is done using only imag
</property>
</widget>
</item>
<item row="15" column="1">
<widget class="QLabel" name="label_space2">
<item row="4" column="0">
<widget class="QCheckBox" name="rgbd_savedLocalizationIgnored">
<property name="text">
<string>Local radius for nodes selection in the local map. This parameter is used in some approaches of the sub-panels.</string>
<string/>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QDoubleSpinBox" name="rgdb_linearSpeedUpdate">
<property name="suffix">
<string> m/s</string>
</property>
<property name="decimals">
<number>3</number>
</property>
<property name="singleStep">
<double>0.100000000000000</double>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QDoubleSpinBox" name="rgdb_linearUpdate">
<property name="suffix">
<string> m</string>
</property>
<property name="decimals">
<number>3</number>
</property>
<property name="singleStep">
<double>0.100000000000000</double>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="QLabel" name="label_163">
<property name="text">
<string>Odometry change detected that triggers a new map (0 means whatever the odometry change, the detector will still link the new pose in the current map). Also by default, when an odometry with Identity transformation is detected, a new map is automatically created. </string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item row="18" column="0">
<widget class="QSpinBox" name="spinBox_maxOdomCacheSize">
<property name="maximum">
<number>9999</number>
</property>
</widget>
</item>
<item row="16" column="0">
<widget class="QDoubleSpinBox" name="localDetection_radius">
<property name="suffix">
<string> m</string>
</property>
<property name="value">
<double>1.000000000000000</double>
</property>
</widget>
</item>
<item row="12" column="1">
<widget class="QLabel" name="label_scanMatching_11">
<property name="text">
<string>Ignore off diagonal values of the odometry covariance matrix.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
@@ -11221,42 +11149,6 @@ If set to false, classic RTAB-Map loop closure detection is done using only imag
</widget>
</item>
<item row="13" column="1">
<widget class="QLabel" name="label_scanMatching_3">
<property name="text">
<string>Maximum local locations retrieved (0=disabled) near the current pose in the local map or on the current planned path (those on the planned path have priority).</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item row="17" column="0">
<widget class="QSpinBox" name="spinBox_maxOdomCacheSize">
<property name="maximum">
<number>9999</number>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QDoubleSpinBox" name="rgdb_angularSpeedUpdate">
<property name="suffix">
<string> rad/s</string>
</property>
<property name="decimals">
<number>2</number>
</property>
<property name="maximum">
<double>3.140000000000000</double>
</property>
<property name="singleStep">
<double>0.100000000000000</double>
</property>
</widget>
</item>
<item row="12" column="1">
<widget class="QLabel" name="label_scanMatching_12">
<property name="text">
<string>Limit covariance of non-neighbor links to minimum covariance of neighbor links. In other words, if covariance of a loop closure link is smaller than the minimum covariance of odometry links, its covariance is set to minimum covariance of odometry links.</string>
@@ -11269,26 +11161,6 @@ If set to false, classic RTAB-Map loop closure detection is done using only imag
</property>
</widget>
</item>
<item row="7" column="0">
<widget class="QCheckBox" name="odomGravity">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="17" column="1">
<widget class="QLabel" name="label_space2_5">
<property name="text">
<string>Maximum odometry cache size. Used only in localization mode. This is used to get smoother localizations and to verify localization transforms (when maximum graph error is not null) to make sure we don't teleport to a location very similar to one we previously localized on. Set 0 to disable caching.</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="1">
<widget class="QLabel" name="label_scanMatching_7">
<property name="text">
@@ -11302,7 +11174,99 @@ If set to false, classic RTAB-Map loop closure detection is done using only imag
</property>
</widget>
</item>
<item row="16" column="1">
<item row="9" column="1">
<widget class="QLabel" name="label_scanMatching_9">
<property name="text">
<string>Re-extract visual features when computing loop closure transformations. Raw features are not saved in database.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QDoubleSpinBox" name="rgdb_angularSpeedUpdate">
<property name="suffix">
<string> rad/s</string>
</property>
<property name="decimals">
<number>2</number>
</property>
<property name="maximum">
<double>3.140000000000000</double>
</property>
<property name="singleStep">
<double>0.100000000000000</double>
</property>
</widget>
</item>
<item row="13" column="0">
<widget class="QCheckBox" name="rgbd_loopCovLimited">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QLabel" name="label_433">
<property name="text">
<string>Maximum angular speed to update the map (0 means not limit).</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item row="14" column="0">
<widget class="QSpinBox" name="spinBox_maxLocalLocationsRetrieved"/>
</item>
<item row="10" column="1">
<widget class="QLabel" name="label_scanMatching_10">
<property name="text">
<string>Do local bundle adjustment with neighborhood of the loop closure.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QLabel" name="label_scanMatching_2">
<property name="text">
<string>If true, rtabmap will assume the robot is restarting from origin of the map. If false, rtabmap will assume the robot is restarting from the last saved localization pose from previous session (the place where it shut down previously). Used only in localization mode.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item row="6" column="0">
<widget class="QCheckBox" name="odomScanHistory">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="7" column="0">
<widget class="QCheckBox" name="odomGravity">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="17" column="1">
<widget class="QLabel" name="label_space2_12">
<property name="text">
<string>Reject loop closures/localizations if the distance from the map is over this distance (0=disabled).</string>
@@ -11315,20 +11279,43 @@ If set to false, classic RTAB-Map loop closure detection is done using only imag
</property>
</widget>
</item>
<item row="16" column="0">
<widget class="QDoubleSpinBox" name="maxLocalizationDistance">
<property name="suffix">
<string> m</string>
<item row="14" column="1">
<widget class="QLabel" name="label_scanMatching_3">
<property name="text">
<string>Maximum local locations retrieved (0=disabled) near the current pose in the local map or on the current planned path (those on the planned path have priority).</string>
</property>
<property name="value">
<double>1.000000000000000</double>
<property name="wordWrap">
<bool>true</bool>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item row="8" column="1">
<widget class="QLabel" name="label_scanMatching_14">
<item row="9" column="0">
<widget class="QCheckBox" name="loopClosure_reextract">
<property name="text">
<string>Use Identity matrix as guess when computing loop closure transform, otherwise no guess is used (assuming that registration strategy can deal with transformation estimation without guess).</string>
<string/>
</property>
</widget>
</item>
<item row="18" column="1">
<widget class="QLabel" name="label_space2_5">
<property name="text">
<string>Maximum odometry cache size. Used only in localization mode. This is used to get smoother localizations and to verify localization transforms (when maximum graph error is not null) to make sure we don't teleport to a location very similar to one we previously localized on. Set 0 to disable caching.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item row="15" column="1">
<widget class="QLabel" name="label_scanMatching_5">
<property name="text">
<string>Ratio of working memory for which local nodes are immunized from transfer.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
@@ -11345,6 +11332,39 @@ If set to false, classic RTAB-Map loop closure detection is done using only imag
</property>
</widget>
</item>
<item row="6" column="1">
<widget class="QLabel" name="label_scanMatching">
<property name="text">
<string>Neighbor link refining. When a new node is added to the graph, the transformation of its neighbor link (odometry) with the previous node is refined using ICP registration approach (laser scans required).</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item row="11" column="1">
<widget class="QLabel" name="label_scanMatching_16">
<property name="text">
<string>Inverted registration. On loop closure, do registration from the target to reference instead of reference to target.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item row="11" column="0">
<widget class="QCheckBox" name="loopClosure_invertedReg">
<property name="text">
<string/>
</property>
</widget>
</item>
</layout>
</widget>
</item>
@@ -18973,7 +18993,7 @@ Lower the ratio -&gt; higher the precision.</string>
<item>
<widget class="QStackedWidget" name="stackedWidget_loopClosureEstimation">
<property name="currentIndex">
<number>2</number>
<number>1</number>
</property>
<widget class="QWidget" name="page_38">
<layout class="QVBoxLayout" name="verticalLayout_68">
@@ -19087,29 +19107,10 @@ Lower the ratio -&gt; higher the precision.</string>
<string>Motion Estimation: 3D to 2D (PnP)</string>
</property>
<layout class="QGridLayout" name="gridLayout_59" columnstretch="0,1">
<item row="0" column="0">
<widget class="QDoubleSpinBox" name="loopClosure_pnpReprojError">
<property name="suffix">
<string> pix</string>
</property>
<property name="decimals">
<number>1</number>
</property>
<property name="minimum">
<double>0.100000000000000</double>
</property>
<property name="singleStep">
<double>1.000000000000000</double>
</property>
<property name="value">
<double>8.000000000000000</double>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLabel" name="label_236">
<item row="2" column="1">
<widget class="QLabel" name="label_loopClosure_pnpOpenCV2">
<property name="text">
<string>Reprojection error.</string>
<string>Refine iterations.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
@@ -19138,10 +19139,10 @@ Lower the ratio -&gt; higher the precision.</string>
</item>
</widget>
</item>
<item row="1" column="1">
<widget class="QLabel" name="label_235">
<item row="0" column="1">
<widget class="QLabel" name="label_236">
<property name="text">
<string>Flags.</string>
<string>Reprojection error.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
@@ -19151,16 +19152,22 @@ Lower the ratio -&gt; higher the precision.</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLabel" name="label_loopClosure_pnpOpenCV2">
<property name="text">
<string>Refine iterations.</string>
<item row="0" column="0">
<widget class="QDoubleSpinBox" name="loopClosure_pnpReprojError">
<property name="suffix">
<string> pix</string>
</property>
<property name="wordWrap">
<bool>true</bool>
<property name="decimals">
<number>1</number>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
<property name="minimum">
<double>0.100000000000000</double>
</property>
<property name="singleStep">
<double>1.000000000000000</double>
</property>
<property name="value">
<double>8.000000000000000</double>
</property>
</widget>
</item>
@@ -19180,6 +19187,54 @@ Lower the ratio -&gt; higher the precision.</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLabel" name="label_235">
<property name="text">
<string>Flags.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QLabel" name="label_loopClosure_pnpOpenCV2_2">
<property name="text">
<string>Max linear variance between 3D point correspondences after PnP. 0 means disabled.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QDoubleSpinBox" name="loopClosure_pnpMaxVariance">
<property name="suffix">
<string/>
</property>
<property name="decimals">
<number>4</number>
</property>
<property name="minimum">
<double>0.000000000000000</double>
</property>
<property name="maximum">
<double>99.000000000000000</double>
</property>
<property name="singleStep">
<double>0.100000000000000</double>
</property>
<property name="value">
<double>0.000000000000000</double>
</property>
</widget>
</item>
</layout>
</widget>
</item>