Adding doc and tests (#1492)

* added doc and tests for util2d.h

* updated cmake-ros ci

* Added util3d.h doc and tests

* util3d_transforms.h: Added doc and tests

* util3d_filtering.h: started doc and test

* util3d_filtering.h: more tests and doc

* Added more doc/tests

* finished util3d_filtering doc and tests

* added test for util2d::depthBleedingFiltering

* Added util3d_registration tests

* Added util3d_features.h doc/tests

* added doc/tests for util3d_correspondences.h

* added doc/gtest for util3d_mapping.h (missing hpp functions)

* finished testing util3d_mapping.hpp

* Added util3d_motion_estimation.h tests (2D->3D done)

* finished util3d_motion_estimation.h tests

* minimal util3d_surface.h

* Added Transform and VisualWord tests

* Added doc for CameraModel and StereoCameraModel

* Added more logs in ros ci

* Passing tests on fical

* improved all devcontainer

* added devcontainer kilted, fixed source setup.bash, removed ldconfig in ros-cmake workflow

* cleanup

* source ros

* Added utilite tests

* Added testing to appveyor, github actions cancellable on re-commit on same branch

* appveyor testing without all targets

* appveyor: specifying ALL_BUILD target

* Fixed Util2dTest.NMSImageBoundsRespected test

* Fixing PCL Indices error on old pcl

* Added VWDictionary tests and doc. Fixed LSH not working (fix from https://github.com/flann-lib/flann/pull/472

* fixing some appveyor CI errors, added test to check dictionary serialization against all type

* Added StereoDense, StereoBM and StereoSGBM doc and tests

* Added Stereo tests

* Added CameraModel and StereoCameraModel tests

* Added doc and test for Statistics

* Added doc/tests for Signature

* Added doc/test for SensorEvent, added doc for SensorCaptureInfo

* Added doc to SensorData

* Added SensorData tests

* Added SensorCapture and SensorCaptureThread doc and tests

* fixed sensordata test

* updated SSC test and doc

* Added doc and tests for BayesFilter class

* Enabled testing on mac, updated windows testing like on linux

* added test_link

* fixed unresolved on windows

* fixed ThreadHandle error on macos ci

* Added GPS and GeodeticCoords tests

* Added tests for compression

* Added Odometry tests (base class only)

* Added DBDriver tests

* Added coverage report

* uniformized test names

* fixing concurancy and coverage ci

* dont built tools, examples and app for coverage build

* fixed report tool rebuilt without qt compilation error

* updated coverage option

* updated coverage config

* added doc CI job

* fixing windows and mac ci errors

* Added DBDriverSqlite3 tests

* Added IMU tests

* Added Graph tests

* fixing flaky macos test

* Added IMUThread and IMUFilter tests

* Added Landmarks tests

* Added LASWriter tests

* fixing seed flaky test

* fixing flaky macos timing tests

* Added LocalGrid tests

* Added LocalGridMaker tests

* fixing ci errors

* Added GlobalMap tests

* Added doc for EnvSensor

* Added Features2D tests

* Added Registration tests

* Added RegistrationVis tests

* Added doc for Rtabmap and Memory classes

* Added Memory and Rtabmap tests

* making some tests less flaky

* lcov 1.14 support

* updated compatible tool arguments

* Added integration tests (RGB-D, Stereo, Lidar2d, Lidar3d)

* More octomap checks

* Refactored how/when python interpretor is created to simplify library usage

* Added python tests

* fixed some flaky tests

* suppressed some third party related warnings

* fixed ceres tests

* more flaky fixes

* Fixing tests without libpointmatcher

* Added RANSAC rejection filter to PCL ICP

* fixing multi platform flakiness

* Added test to detect regression

* Fixing windows pcl link error

* fixed some macos flakiness

* bigger 2D2D registration error on opencv 4.6.0

* flakiness

* fixing flaky tests on windows and mac

* flaky thread test on slow mac VM

* windows slow test

* fixing more ci erros

* fxing temp dir on windows

* Added Optimizer tests and discovered some bugs (fixed)

* fixing flaky tests in mac and windows

* Added Optimizer doc

* Added GTSAM BA, updated Ceres to use g2o ba parameters. Renamed g2o's ba related parameters to Optimizer group and used by both gtsam and ceres.

* fixing build without gtsam

* fixing home dir

* fixing python ci isssues

* Added multicam ba tests

* Added Ceres multicam BA support

* Aligned BundleAdjustment parameters with Optimizer/Strategy to avoid confusion in the code

* Added BA integration test

* Added robust graph optimization integration test

* Added loop3it test

* Added stereo20Hz test

* Added smartfactor gtsam

* Fixed bugged check and warn if python didn't return any descriptors

* Fixing gtsam version build issues

* fixing tilt on windows ci

* loosing ceres integration test for ci

* mac ci flakiness

* updating missing param in gui

* updating test bound for mac

* added appearance-based tests, set min gftt quality to quality level

* testing more stuff

* improving features2d tests

* ci flakiness

* fixing flaky ci

* ci fixes

* flaky fixes

* Added RegistrationIcp tests

* Added icp integration test with real-worl corridor like env

* intermediate nodes

* fixing enum

* Updated test to catch #1714

* Fixed 2d corridor failing on pcl

* flaky pnp test

* flaky brisk test

* Set rtabmap_integration test as long

* updating loop closure test

* flaky ci tests

* TEsting roundtrip g2o/toro save/load

* loosing test bound

* fixed cuda capable checks

* flaky tests

* Debugging test hanging

* more debugging stuff

* updating limit

* windows: disabled cuda on ci to avoid incompatible driver issue. Fixing a bad test mem allocation

* trying fixing cuda hanging issue

* fixing ci flakyness

* flaky tests

* Updated BOW flaky tests by checking min precision/recall instead of recall@100precision. Fixed signature test

* CameraModel::load() test initRectificationMap param

* test dbdriver load dictionary idsOnly

* Memory: test keepLinkedInDb param

* added dummyDictionary tests

* test intermediate nodes count

* Added MarkerDetector tests

* reverted breaking change of UMutex and USemaphore

* Features2d: fixed compiltion warnings with clang about override

* clang warnings

* fixing test build with pcl 1.8

* g2o and gtsam build errors on android

* opencv5 test fixes

* disabled testing for ios and android builds

* normalized endline characters for easier diff

* added LF CRLF rule

* bump 0.23.10. fixing doc version

* Publish rtabmap website doc from ci

* fixing MSCVC build error

* macos icp flaky test

* fixing ceres macos test bound

* ficing more flaky tests

* fixing opencv5 related test errors. Also fixed an actual bug in ENU_WGS84ToGeocentric_WGS84()

* added comment about mrpt change

* removed rosdoc2 (will add it for rtabmap_ros later)

* fixing website style

* updated download links

* locally deployable website with api

* sweep doxygen issues

* improved/revised doxygen main pages

* removed examples empty page

* Updated doxygen style

* more concise doxygen groups

* added api link on main readme

* fixing utilite test error

* fixing CommonFilteringGroundNormalsUp test

* updated precisionRecall test bounds for Freak and brief descriptors

* fixing scale check in ba tests

* disabled tests on windows cuda build (missing dlls amd runner cannot test cuda anyway)

* ceres: missing suitesparse dep in windows ci

* adjusting recall thr for fast/freak

* ficing more flaky tests

* fixing flaky tests

* disabled coverage in ros ci

* Enable integration tests for ros ci jobs

* loosing up some threshold for failing tests

* trigger cache

* fixing test data in ros ci. Updated flaky test for mac

* slaking some test limit

* Fixed rtabmap-detectMoreLoopClosures inverted output value

* loosing up sift recall on mac

* optimizer re-ordered distribution for reproducible results (mac g2o)

* macos dump test crash log

* combining all tests to save time on shared library reload. Also fixed Logs with missing arguments.

* Added ENABLE_FORMAT_ERRORS cmake option

* do test only one time

* fixed all format warnings

* format security android build errors

* less verbose tests

* updated ImuUThread test

* fixed a log

* Fixed libpointmatcher 2d normals eigen issue

* Fixing libpointmatcher conversion issues

* fixing libpointmatcher test on windows ci

* cleanup comments, relax some test thr

* disabled sequoia-intel ci build (too flaky, would need extensive testing directly on that machine)
This commit is contained in:
matlabbe
2026-08-06 13:32:20 -07:00
committed by GitHub
parent bcdb4b4546
commit ee49beaf4f
309 changed files with 67468 additions and 3069 deletions
+1 -1
View File
@@ -574,7 +574,7 @@ void CloudViewer::loadSettings(QSettings & settings, const QString & group)
void CloudViewer::refreshView()
{
#if VTK_MAJOR_VERSION > 8
this->renderWindow()->Render();
this->renderWindow()->GetInteractor()->Render();
#else
this->update();
#endif
+15 -15
View File
@@ -996,7 +996,7 @@ bool DatabaseViewer::openDatabase(const QString & path, const ParametersMap & ov
.arg(iter->first.c_str())
.arg(iter->second.c_str())
.arg(jter->second.c_str());
UWARN(msg.toStdString().c_str());
UWARN("%s", msg.toStdString().c_str());
}
}
}
@@ -1751,7 +1751,7 @@ void DatabaseViewer::extractImages()
UWARN("Failed saving \"%s\"", QString("%1/left/%2.%3").arg(path).arg(id).arg(ext).toStdString().c_str());
if(!cv::imwrite(QString("%1/right/%2.%3").arg(path).arg(id).arg(ext).toStdString(), data.rightRaw()))
UWARN("Failed saving \"%s\"", QString("%1/right/%2.%3").arg(path).arg(id).arg(ext).toStdString().c_str());
UINFO(QString("Saved left/%1.%2 and right/%1.%2").arg(id).arg(ext).toStdString().c_str());
UINFO("%s", QString("Saved left/%1.%2 and right/%1.%2").arg(id).arg(ext).toStdString().c_str());
if(databaseFileName_.empty())
{
@@ -1803,12 +1803,12 @@ void DatabaseViewer::extractImages()
if(!cv::imwrite(QString("%1/depth/%2.png").arg(path).arg(id).toStdString(), data.depthRaw().type()==CV_32FC1?util2d::cvtDepthFromFloat(data.depthRaw()):data.depthRaw()))
UWARN("Failed saving \"%s\"", QString("%1/depth/%2.png").arg(path).arg(id).toStdString().c_str());
if(data.depthConfidenceRaw().empty()) {
UINFO(QString("Saved rgb/%1.%2 and depth/%1.png").arg(id).arg(ext).toStdString().c_str());
UINFO("%s", QString("Saved rgb/%1.%2 and depth/%1.png").arg(id).arg(ext).toStdString().c_str());
}
else {
if(!cv::imwrite(QString("%1/confidence/%2.png").arg(path).arg(id).toStdString(), data.depthConfidenceRaw()))
UWARN("Failed saving \"%s\"", QString("%1/confidence/%2.png").arg(path).arg(id).toStdString().c_str());
UINFO(QString("Saved rgb/%1.%2, depth/%1.png and confidence/%1.png").arg(id).arg(ext).toStdString().c_str());
UINFO("%s", QString("Saved rgb/%1.%2, depth/%1.png and confidence/%1.png").arg(id).arg(ext).toStdString().c_str());
}
}
else
@@ -1816,7 +1816,7 @@ void DatabaseViewer::extractImages()
if(!cv::imwrite(QString("%1/%2.%3").arg(path).arg(id).arg(ext).toStdString(), data.imageRaw()))
UWARN("Failed saving \"%s\"", QString("%1/%2.%3").arg(path).arg(id).arg(ext).toStdString().c_str());
else
UINFO(QString("Saved %1.%2").arg(id).arg(ext).toStdString().c_str());
UINFO("%s", QString("Saved %1.%2").arg(id).arg(ext).toStdString().c_str());
}
if(databaseFileName_.empty())
@@ -3139,7 +3139,7 @@ void DatabaseViewer::editSaved2DMap()
progressDialog.setMinimumWidth(800);
QApplication::processEvents();
UINFO("Cropping empty space... poses=%d cropRadius=%d", poses.size(), cropRadius);
UINFO("Cropping empty space... poses=%d cropRadius=%d", (int)poses.size(), cropRadius);
UASSERT(cropRadius>=0);
for(std::map<int, Transform>::iterator iter=poses.begin(); iter!=poses.end() && !progressDialog.isCanceled(); ++iter)
{
@@ -3609,7 +3609,7 @@ void DatabaseViewer::exportOptimizedMesh()
path += ".obj";
}
QString baseName = QFileInfo(path).baseName();
UDEBUG("Materials: %d", mesh->tex_materials.size());
UDEBUG("Materials: %d", (int)mesh->tex_materials.size());
if(mesh->tex_materials.size() == 1)
{
mesh->tex_materials.at(0).tex_file = baseName.toStdString() + ".png";
@@ -3916,7 +3916,7 @@ void DatabaseViewer::generateLocalGraph()
idsSet.insert(idsSet.end(), iter->first);
UINFO("Node %d", iter->first);
}
UINFO("idsSet=%d", idsSet.size());
UINFO("idsSet=%d", (int)idsSet.size());
dbDriver_->generateGraph(path.toStdString(), idsSet);
}
else
@@ -5849,11 +5849,11 @@ void DatabaseViewer::update(int value,
polygons = filteredPolygons;
}
cloudViewer_->addCloudMesh(uFormat("mesh_%d", i), cloud, polygons, pose);
cloudViewer_->addCloudMesh(uFormat("mesh_%d", (int)i), cloud, polygons, pose);
}
if(ui_->checkBox_showCloud->isChecked())
{
std::string cloudName = uFormat("cloud_%d", i);
std::string cloudName = uFormat("cloud_%d", (int)i);
cloudViewer_->addCloud(cloudName, cloud, pose);
if(colorIndexAndPointSizeMap.find(cloudName) != colorIndexAndPointSizeMap.end()) {
cloudViewer_->setCloudColorIndex(cloudName, colorIndexAndPointSizeMap.at(cloudName).first);
@@ -5888,7 +5888,7 @@ void DatabaseViewer::update(int value,
cloud = util3d::voxelize(cloud, indices, ui_->doubleSpinBox_voxelSize->value());
}
std::string cloudName = uFormat("cloud_%d", i);
std::string cloudName = uFormat("cloud_%d", (int)i);
cloudViewer_->addCloud(cloudName, cloud, pose);
if(colorIndexAndPointSizeMap.find(cloudName) != colorIndexAndPointSizeMap.end()) {
cloudViewer_->setCloudColorIndex(cloudName, colorIndexAndPointSizeMap.at(cloudName).first);
@@ -8293,7 +8293,7 @@ void DatabaseViewer::updateGraphView()
}
else
{
UWARN("Empty WM poses!? Ignoring WM state... (root id=%d, wmState=%d)", fromId, wmState.size());
UWARN("Empty WM poses!? Ignoring WM state... (root id=%d, wmState=%d)", fromId, (int)wmState.size());
}
}
@@ -9396,7 +9396,7 @@ void DatabaseViewer::refineConstraint(int from, int to, Registration * reg, Regi
std::string msg = "Option to generate scan from depth is checked (GUI Parameters->Refine), but "
"resulting clouds from depth are empty. Transformation estimation will likely "
"fails. Uncheck the parameter to use laser scans.";
UWARN(msg.c_str());
UWARN("%s", msg.c_str());
if(!silent)
{
QMessageBox::warning(this,
@@ -9674,7 +9674,7 @@ bool DatabaseViewer::addConstraint(int from, int to, Registration * reg, bool si
std::string msg = "Option to generate scan from depth is checked (GUI Parameters->Refine), but "
"resulting clouds from depth are empty. Transformation estimation will likely "
"fails. Uncheck the parameter to use laser scans.";
UWARN(msg.c_str());
UWARN("%s", msg.c_str());
if(!silent)
{
QMessageBox::warning(this,
@@ -9701,7 +9701,7 @@ bool DatabaseViewer::addConstraint(int from, int to, Registration * reg, bool si
fromS->id(),
toS->id(),
Parameters::kRGBDLoopClosureReextractFeatures().c_str());
UWARN(msg.c_str());
UWARN("%s", msg.c_str());
if(!silent)
{
QMessageBox::warning(this,
+81 -21
View File
@@ -38,6 +38,28 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
namespace rtabmap {
namespace {
// Combo box order matches Optimizer::Type 1:1 (TORO=0, g2o=1, GTSAM=2,
// Ceres=3, CVSBA=4). TORO is shown but disabled because it's not BA-capable;
// keeping it in the dropdown lets the combo index equal the Optimizer::Type
// integer directly (no translation needed). We persist the Optimizer::Type
// integer in QSettings so future reordering of the .ui (should we want to
// drop TORO entirely) stays decoupled from saved preferences.
Optimizer::Type sbaIndexToType(int index)
{
return static_cast<Optimizer::Type>(index);
}
// PixelVariance is consumed by every BA backend except CVSBA (which feeds
// observations into cvsba's Sba::run() directly without an info-matrix knob).
bool sbaIndexUsesPixelVariance(int index)
{
return sbaIndexToType(index) != Optimizer::kTypeCVSBA;
}
} // namespace
ExportBundlerDialog::ExportBundlerDialog(QWidget * parent) :
QDialog(parent)
{
@@ -58,20 +80,31 @@ ExportBundlerDialog::ExportBundlerDialog(QWidget * parent) :
connect(_ui->comboBox_sbaType, SIGNAL(currentIndexChanged(int)), this, SLOT(updateVisibility()));
connect(_ui->sba_rematchFeatures, SIGNAL(stateChanged(int)), this, SIGNAL(configChanged()));
if(!Optimizer::isAvailable(Optimizer::kTypeCVSBA) && !Optimizer::isAvailable(Optimizer::kTypeG2O))
// Disable TORO (kept in the dropdown only so the combo index lines up
// 1:1 with Optimizer::Type) and any backend that wasn't compiled in.
// Remember the first available index so we can default to it.
int firstAvailable = -1;
for(int i = 0; i < _ui->comboBox_sbaType->count(); ++i)
{
const Optimizer::Type type = sbaIndexToType(i);
const bool usable = type != Optimizer::kTypeTORO && Optimizer::isAvailable(type);
if(usable)
{
if(firstAvailable < 0) firstAvailable = i;
}
else
{
_ui->comboBox_sbaType->setItemData(i, 0, Qt::UserRole - 1);
}
}
if(firstAvailable < 0)
{
_ui->groupBox_export_points->setEnabled(false);
_ui->groupBox_export_points->setChecked(false);
}
else if(!Optimizer::isAvailable(Optimizer::kTypeCVSBA))
else
{
_ui->comboBox_sbaType->setItemData(1, 0, Qt::UserRole - 1);
_ui->comboBox_sbaType->setCurrentIndex(0);
}
else if(!Optimizer::isAvailable(Optimizer::kTypeG2O))
{
_ui->comboBox_sbaType->setItemData(0, 0, Qt::UserRole - 1);
_ui->comboBox_sbaType->setCurrentIndex(1);
_ui->comboBox_sbaType->setCurrentIndex(firstAvailable);
}
_ui->lineEdit_path->setText(QDir::currentPath());
@@ -95,7 +128,9 @@ void ExportBundlerDialog::saveSettings(QSettings & settings, const QString & gro
settings.setValue("laplacianThr", _ui->doubleSpinBox_laplacianVariance->value());
settings.setValue("exportPoints", _ui->groupBox_export_points->isChecked());
settings.setValue("sba_iterations", _ui->sba_iterations->value());
settings.setValue("sba_type", _ui->comboBox_sbaType->currentIndex());
// Persist the Optimizer::Type rather than the combo index so reordering
// the dropdown in the future doesn't reshuffle saved preferences.
settings.setValue("sba_type", static_cast<int>(sbaIndexToType(_ui->comboBox_sbaType->currentIndex())));
settings.setValue("sba_variance", _ui->sba_variance->value());
settings.setValue("sba_rematch_features", _ui->sba_rematchFeatures->isChecked());
if(!group.isEmpty())
@@ -115,7 +150,25 @@ void ExportBundlerDialog::loadSettings(QSettings & settings, const QString & gro
_ui->doubleSpinBox_laplacianVariance->setValue(settings.value("laplacianThr", _ui->doubleSpinBox_laplacianVariance->value()).toDouble());
_ui->groupBox_export_points->setChecked(settings.value("exportPoints", _ui->groupBox_export_points->isChecked()).toBool());
_ui->sba_iterations->setValue(settings.value("sba_iterations", _ui->sba_iterations->value()).toInt());
_ui->comboBox_sbaType->setCurrentIndex((Optimizer::Type)settings.value("sba_type", _ui->comboBox_sbaType->currentIndex()).toInt());
{
// "sba_type" used to be the combo index (0=g2o, 1=cvsba) when only
// those two backends were exposed. The combo index now lines up 1:1
// with Optimizer::Type, so we read the saved value as a Type
// directly. Legacy 0 (= kTypeTORO in the new encoding, but TORO is
// disabled in the combo) is reinterpreted as the previous g2o
// selection; legacy 1 (= old cvsba index) collides with the new
// kTypeG2O encoding -- users who had cvsba selected will see g2o on
// first load and need to re-pick cvsba once.
int saved = settings.value("sba_type", static_cast<int>(Optimizer::kTypeG2O)).toInt();
if(saved == static_cast<int>(Optimizer::kTypeTORO))
{
saved = static_cast<int>(Optimizer::kTypeG2O);
}
if(saved >= 0 && saved < _ui->comboBox_sbaType->count())
{
_ui->comboBox_sbaType->setCurrentIndex(saved);
}
}
_ui->sba_variance->setValue(settings.value("sba_variance", _ui->sba_variance->value()).toDouble());
_ui->sba_rematchFeatures->setChecked(settings.value("sba_rematch_features", _ui->sba_rematchFeatures->isChecked()).toBool());
if(!group.isEmpty())
@@ -136,14 +189,20 @@ void ExportBundlerDialog::restoreDefaults()
_ui->doubleSpinBox_laplacianVariance->setValue(0);
_ui->groupBox_export_points->setChecked(false);
_ui->sba_iterations->setValue(20);
if(Optimizer::isAvailable(Optimizer::kTypeG2O) || !Optimizer::isAvailable(Optimizer::kTypeCVSBA))
// Default to the first compiled-in BA-capable backend (combo index
// matches Optimizer::Type, so we skip TORO at index 0). Falls back to
// index 1 (g2o) if nothing is available -- the group box is disabled in
// that case anyway.
int defaultIndex = static_cast<int>(Optimizer::kTypeG2O);
for(int i = 1; i < _ui->comboBox_sbaType->count(); ++i)
{
_ui->comboBox_sbaType->setCurrentIndex(0);
}
else
{
_ui->comboBox_sbaType->setCurrentIndex(1);
if(Optimizer::isAvailable(sbaIndexToType(i)))
{
defaultIndex = i;
break;
}
}
_ui->comboBox_sbaType->setCurrentIndex(defaultIndex);
_ui->sba_variance->setValue(1.0);
_ui->sba_rematchFeatures->setChecked(true);
@@ -151,8 +210,9 @@ void ExportBundlerDialog::restoreDefaults()
void ExportBundlerDialog::updateVisibility()
{
_ui->sba_variance->setVisible(_ui->comboBox_sbaType->currentIndex() == 0);
_ui->label_variance->setVisible(_ui->comboBox_sbaType->currentIndex() == 0);
const bool usesPixelVariance = sbaIndexUsesPixelVariance(_ui->comboBox_sbaType->currentIndex());
_ui->sba_variance->setVisible(usesPixelVariance);
_ui->label_variance->setVisible(usesPixelVariance);
}
void ExportBundlerDialog::getPath()
@@ -189,11 +249,11 @@ void ExportBundlerDialog::exportBundler(
{
std::map<int, Transform> posesOut;
std::multimap<int, Link> linksOut;
Optimizer::Type sbaType = _ui->comboBox_sbaType->currentIndex()==0?Optimizer::kTypeG2O:Optimizer::kTypeCVSBA;
Optimizer::Type sbaType = sbaIndexToType(_ui->comboBox_sbaType->currentIndex());
UASSERT(Optimizer::isAvailable(sbaType));
ParametersMap parametersSBA = parameters;
uInsert(parametersSBA, std::make_pair(Parameters::kOptimizerIterations(), uNumber2Str(_ui->sba_iterations->value())));
uInsert(parametersSBA, std::make_pair(Parameters::kg2oPixelVariance(), uNumber2Str(_ui->sba_variance->value())));
uInsert(parametersSBA, std::make_pair(Parameters::kOptimizerPixelVariance(), uNumber2Str(_ui->sba_variance->value())));
std::shared_ptr<Optimizer> sba(Optimizer::create(sbaType, parametersSBA));
sba->getConnectedGraph(poses.begin()->first, poses, links, posesOut, linksOut);
// set input poses as initial optimization guess
+8 -8
View File
@@ -2141,9 +2141,9 @@ bool ExportCloudsDialog::getExportedClouds(
_ui->spinBox_dilationSteps->value());
// make sure there are no nans
UDEBUG("NaNs filtering... size before = %d", cloudWithNormals->size());
UDEBUG("NaNs filtering... size before = %d", (int)cloudWithNormals->size());
cloudWithNormals = util3d::removeNaNNormalsFromPointCloud(cloudWithNormals);
UDEBUG("NaNs filtering... size after = %d", cloudWithNormals->size());
UDEBUG("NaNs filtering... size after = %d", (int)cloudWithNormals->size());
if(_ui->checkBox_assemble->isChecked())
{
@@ -2542,7 +2542,7 @@ bool ExportCloudsDialog::getExportedClouds(
{
std::string msg = uFormat("All %d polygons filtered after polygon cluster filtering. Cluster minimum size is %d.", before, _ui->spinBox_mesh_minClusterSize->value());
_progressDialog->appendText(msg.c_str(), Qt::darkYellow);
UWARN(msg.c_str());
UWARN("%s", msg.c_str());
}
_progressDialog->appendText(tr("Filtered %1 polygons.").arg(before-(int)polygons.size()));
@@ -2796,7 +2796,7 @@ bool ExportCloudsDialog::getExportedClouds(
{
std::string msg = uFormat("Some clouds are 2D laser scans. Meshing can be done only from RGB-D clouds or 3D laser scans.");
_progressDialog->appendText(msg.c_str(), Qt::darkYellow);
UWARN(msg.c_str());
UWARN("%s", msg.c_str());
}
else if(_ui->checkBox_cameraProjection->isEnabled() &&
_ui->checkBox_cameraProjection->isChecked() &&
@@ -2879,7 +2879,7 @@ bool ExportCloudsDialog::getExportedClouds(
"have 4 values [left right top bottom] between 0 and 1 "
"separated by space (%1), ignoring it for projecting cameras...")
.arg(_ui->lineEdit_camProjRoiRatios->text());
UWARN(msg.toStdString().c_str());
UWARN("%s", msg.toStdString().c_str());
_progressDialog->appendText(msg, Qt::darkYellow);
_progressDialog->setAutoClose(false);
}
@@ -3007,7 +3007,7 @@ bool ExportCloudsDialog::getExportedClouds(
}
}
QString msg = tr("Processed %1/%2 images").arg(imagesDone++).arg(cameraPoses.size());
UINFO(msg.toStdString().c_str());
UINFO("%s", msg.toStdString().c_str());
_progressDialog->appendText(msg);
QApplication::processEvents();
}
@@ -3448,7 +3448,7 @@ bool ExportCloudsDialog::getExportedClouds(
std::string msg = uFormat("More than 50%% of the cameras (%d/%d) have been filtered for "
"too fast motion and/or blur level. You may adjust the corresponding thresholds.",
ignoredCameras, (int)validCameras.size());
UWARN(msg.c_str());
UWARN("%s", msg.c_str());
_progressDialog->appendText(msg.c_str(), Qt::darkYellow);
_progressDialog->setAutoClose(false);
QApplication::processEvents();
@@ -3572,7 +3572,7 @@ bool ExportCloudsDialog::getExportedClouds(
"values [left right top bottom] between 0 and 1 "
"separated by space (%1), ignoring it for texturing...")
.arg(_ui->lineEdit_meshingTextureRoiRatios->text());
UWARN(msg.toStdString().c_str());
UWARN("%s", msg.toStdString().c_str());
_progressDialog->appendText(msg, Qt::darkYellow);
_progressDialog->setAutoClose(false);
}
+3 -2
View File
@@ -76,14 +76,15 @@ void LoopClosureViewer::updateView(const Transform & transform, const Parameters
float minDepth = 0;
if(!ui_->checkBox_rawCloud->isChecked())
{ decimation = decimation_;
{
decimation = decimation_;
maxDepth = maxDepth_;
minDepth = minDepth_;
}
UDEBUG("decimation = %d", decimation);
UDEBUG("maxDepth = %f", maxDepth);
UDEBUG("minDepth = %d", minDepth);
UDEBUG("minDepth = %d", (int)minDepth);
Transform t;
if(!transform.isNull())
+29 -28
View File
@@ -1507,7 +1507,7 @@ void MainWindow::processOdometry(const rtabmap::OdometryEvent & odom, bool dataI
{
for(size_t i=0; i<10; ++i)
{
std::string subFrustumId = uFormat("f_odom_%d", iter->first*10+i);
std::string subFrustumId = uFormat("f_odom_%d", (int)(iter->first*10+i));
_cloudViewer->updateFrustumPose(subFrustumId, _odometryCorrection*iter->second);
}
}
@@ -1520,7 +1520,7 @@ void MainWindow::processOdometry(const rtabmap::OdometryEvent & odom, bool dataI
if(!t.isNull())
{
QColor color = Qt::yellow;
std::string subFrustumId = uFormat("f_odom_%d", iter->first*10+i);
std::string subFrustumId = uFormat("f_odom_%d", (int)(iter->first*10+i));
_cloudViewer->addOrUpdateFrustum(subFrustumId, _odometryCorrection*iter->second, t, _cloudViewer->getFrustumScale(), color, models[i].fovX(), models[i].fovY());
}
}
@@ -2299,7 +2299,7 @@ void MainWindow::processStats(const rtabmap::Statistics & stat)
{
_cachedLocalizationsCount[matchId] += 1.0f;
}
UDEBUG("time= %d ms (update detection ui)", time.restart());
UDEBUG("time= %d ms (update detection ui)", (int)time.restart());
//update image views
if(!signature.sensorData().imageRaw().empty() ||
@@ -2351,7 +2351,7 @@ void MainWindow::processStats(const rtabmap::Statistics & stat)
qimageLoopThread.join();
QImage img = qimageThread.getQImage();
QImage lcImg = qimageLoopThread.getQImage();
UDEBUG("time= %d ms (convert image to qt)", time.restart());
UDEBUG("time= %d ms (convert image to qt)", (int)time.restart());
if(!img.isNull())
{
@@ -2399,7 +2399,7 @@ void MainWindow::processStats(const rtabmap::Statistics & stat)
_ui->imageView_loopClosure->setSceneRect(_ui->imageView_source->sceneRect());
}
UDEBUG("time= %d ms (update detection imageviews)", time.restart());
UDEBUG("time= %d ms (update detection imageviews)", (int)time.restart());
if(_ui->imageView_source->isFeaturesShown() || _ui->imageView_loopClosure->isFeaturesShown() ||
(_ui->imageView_source->isLinesShown() && _ui->imageView_loopClosure->isLinesShown()))
@@ -2433,7 +2433,7 @@ void MainWindow::processStats(const rtabmap::Statistics & stat)
_lastIds.clear();
}
UDEBUG("time= %d ms (draw keypoints)", time.restart());
UDEBUG("time= %d ms (draw keypoints)", (int)time.restart());
// loop closure view
if((stat.loopClosureId() > 0 || stat.proximityDetectionId() > 0) &&
@@ -2455,7 +2455,7 @@ void MainWindow::processStats(const rtabmap::Statistics & stat)
}
}
UDEBUG("time= %d ms (update loop closure viewer)", time.restart());
UDEBUG("time= %d ms (update loop closure viewer)", (int)time.restart());
}
}
else if(rehearsedSimilarity)
@@ -2489,7 +2489,7 @@ void MainWindow::processStats(const rtabmap::Statistics & stat)
{
_rawLikelihoodCurve->setData(QMap<int, float>(stat.rawLikelihood()), QMap<int, int>(stat.weights()));
}
UDEBUG("time= %d ms (update likelihood and posterior)", time.restart());
UDEBUG("time= %d ms (update likelihood and posterior)", (int)time.restart());
// Update statistics tool box
if(_preferencesDialog->isCacheSavedInFigures() || _ui->statsToolBox->isVisible())
@@ -2506,7 +2506,7 @@ void MainWindow::processStats(const rtabmap::Statistics & stat)
}
}
UDEBUG("time= %d ms (update stats toolbox)", time.restart());
UDEBUG("time= %d ms (update stats toolbox)", (int)time.restart());
//======================
// RGB-D Mapping stuff
@@ -2547,9 +2547,9 @@ void MainWindow::processStats(const rtabmap::Statistics & stat)
std::map<int, Transform> poses = stat.poses();
UDEBUG("time= %d ms (update gt-gps stuff)", time.restart());
UDEBUG("time= %d ms (update gt-gps stuff)", (int)time.restart());
UDEBUG("%d %d %d", poses.size(), poses.size()?poses.rbegin()->first:0, stat.refImageId());
UDEBUG("%d %d %d", (int)poses.size(), poses.size()?poses.rbegin()->first:0, stat.refImageId());
if(!_odometryReceived && poses.size() && poses.rbegin()->first == stat.refImageId())
{
if(_cloudViewer->isVisible())
@@ -2625,7 +2625,7 @@ void MainWindow::processStats(const rtabmap::Statistics & stat)
_odometryReceived = false;
UDEBUG("time= %d ms (update map cloud)", time.restart());
UDEBUG("time= %d ms (update map cloud)", (int)time.restart());
if(_preferencesDialog->isCacheSavedInFigures() || _ui->statsToolBox->isVisible())
{
@@ -2711,7 +2711,7 @@ void MainWindow::processStats(const rtabmap::Statistics & stat)
{
_ui->graphicsView_graphView->setCurrentGoalID(stat.currentGoalId(), uValue(stat.poses(), stat.currentGoalId(), Transform()));
}
UDEBUG("time= %d ms (update graph view)", time.restart());
UDEBUG("time= %d ms (update graph view)", (int)time.restart());
}
if(_multiSessionLocWidget->isVisible())
@@ -2767,7 +2767,7 @@ void MainWindow::processStats(const rtabmap::Statistics & stat)
}
}
UDEBUG("time= %d ms (update cache)", time.restart());
UDEBUG("time= %d ms (update cache)", (int)time.restart());
}
else if(!stat.extended() && stat.loopClosureId()>0)
{
@@ -2968,7 +2968,7 @@ void MainWindow::updateMapCloud(
}
// Map updated! regenerate the assembled cloud, last pose is the new one
UDEBUG("Update map with %d locations", poses.size());
UDEBUG("Update map with %d locations", (int)poses.size());
QMap<std::string, Transform> viewerClouds = _cloudViewer->getAddedClouds();
std::set<std::string> viewerLines = _cloudViewer->getAddedLines();
int i=1;
@@ -4394,7 +4394,7 @@ void MainWindow::createAndAddFeaturesToMap(int nodeId, const Transform & pose, i
if(_createdFeatures.find(nodeId) != _createdFeatures.end())
{
UDEBUG("Features cloud %d already created.");
UDEBUG("Features cloud %d already created.", nodeId);
return;
}
@@ -4419,7 +4419,7 @@ void MainWindow::createAndAddFeaturesToMap(int nodeId, const Transform & pose, i
int oi=0;
UASSERT(iter->getWords().size() == iter->getWords3().size());
float maxDepth = _preferencesDialog->getCloudMaxDepth(0);
UDEBUG("rgb.channels()=%d");
UDEBUG("rgb.channels()=%d", rgb.channels());
if(!iter->getWords3().empty() && iter->getWords3().size() == iter->getWordsKpts().size())
{
Transform invLocalTransform = Transform::getIdentity();
@@ -4668,14 +4668,14 @@ void MainWindow::processRtabmapEventInit(int status, const QString & info)
if(QFile::rename(_newDatabasePath, _newDatabasePathOutput))
{
std::string msg = uFormat("Database saved to \"%s\".", _newDatabasePathOutput.toStdString().c_str());
UINFO(msg.c_str());
UINFO("%s", msg.c_str());
QMessageBox::information(this, tr("Database saved!"), QString(msg.c_str()));
}
else
{
std::string msg = uFormat("Failed to rename temporary database from \"%s\" to \"%s\".",
_newDatabasePath.toStdString().c_str(), _newDatabasePathOutput.toStdString().c_str());
UERROR(msg.c_str());
UERROR("%s", msg.c_str());
QMessageBox::critical(this, tr("Closing failed!"), QString(msg.c_str()));
}
}
@@ -4683,7 +4683,7 @@ void MainWindow::processRtabmapEventInit(int status, const QString & info)
{
std::string msg = uFormat("Failed to overwrite the database \"%s\". The temporary database is still correctly saved at \"%s\".",
_newDatabasePathOutput.toStdString().c_str(), _newDatabasePath.toStdString().c_str());
UERROR(msg.c_str());
UERROR("%s", msg.c_str());
QMessageBox::critical(this, tr("Closing failed!"), QString(msg.c_str()));
}
}
@@ -4700,7 +4700,7 @@ void MainWindow::processRtabmapEventInit(int status, const QString & info)
else if(!_openedDatabasePath.isEmpty())
{
std::string msg = uFormat("Database \"%s\" updated.", _openedDatabasePath.toStdString().c_str());
UINFO(msg.c_str());
UINFO("%s", msg.c_str());
QMessageBox::information(this, tr("Database updated!"), QString(msg.c_str()));
}
}
@@ -5068,7 +5068,7 @@ void MainWindow::drawKeypoints(const std::multimap<int, cv::KeyPoint> & refWords
UTimer timer;
timer.start();
ULOGGER_DEBUG("refWords.size() = %d", refWords.size());
ULOGGER_DEBUG("refWords.size() = %d", (int)refWords.size());
_ui->imageView_source->clearFeatures();
if(_ui->imageView_source->isFeaturesShown())
{
@@ -5112,7 +5112,7 @@ void MainWindow::drawKeypoints(const std::multimap<int, cv::KeyPoint> & refWords
ULOGGER_DEBUG("source time (shown=%d) = %f s", _ui->imageView_source->isFeaturesShown()?1:0, timer.ticks());
timer.start();
ULOGGER_DEBUG("loopWords.size() = %d", loopWords.size());
ULOGGER_DEBUG("loopWords.size() = %d", (int)loopWords.size());
QList<QPair<cv::Point2f, cv::Point2f> > uniqueCorrespondences;
_ui->imageView_loopClosure->clearFeatures();
if(_ui->imageView_loopClosure->isFeaturesShown())
@@ -5499,7 +5499,7 @@ void MainWindow::updateParameters(const ParametersMap & parameters)
.arg(iter->first.c_str())
.arg(iter->second.c_str());
_ui->widget_console->appendMsg(msg);
UWARN(msg.toStdString().c_str());
UWARN("%s", msg.toStdString().c_str());
}
QMessageBox::StandardButton button = QMessageBox::question(this,
tr("Parameters"),
@@ -5709,7 +5709,7 @@ void MainWindow::openDatabase(const QString & path, const ParametersMap & overri
.arg(iter->second.c_str())
.arg(jter->second.c_str());
_ui->widget_console->appendMsg(msg);
UWARN(msg.toStdString().c_str());
UWARN("%s", msg.toStdString().c_str());
}
}
}
@@ -6696,7 +6696,7 @@ void MainWindow::postProcessing(
{
QString msg = tr("Some data missing in the cache to respect the constraints chosen. "
"Try \"Edit->Download all clouds\" to update the cache and try again.");
UWARN(msg.toStdString().c_str());
UWARN("%s", msg.toStdString().c_str());
if(abortIfDataMissing)
{
QMessageBox::warning(this, tr("Not all data available in the GUI..."), msg);
@@ -6875,7 +6875,8 @@ void MainWindow::postProcessing(
{
UWARN("\"%s\" is false and signatures (%d and %d) don't have raw "
"images. Update the cache.",
Parameters::kRGBDLoopClosureReextractFeatures().c_str());
Parameters::kRGBDLoopClosureReextractFeatures().c_str(),
signatureFrom.id(), signatureTo.id());
}
else
{
@@ -7168,7 +7169,7 @@ void MainWindow::postProcessing(
ParametersMap parametersSBA = _preferencesDialog->getAllParameters();
uInsert(parametersSBA, std::make_pair(Parameters::kOptimizerIterations(), uNumber2Str(sbaIterations)));
uInsert(parametersSBA, std::make_pair(Parameters::kg2oPixelVariance(), uNumber2Str(sbaVariance)));
uInsert(parametersSBA, std::make_pair(Parameters::kOptimizerPixelVariance(), uNumber2Str(sbaVariance)));
Optimizer * sbaOptimizer = Optimizer::create(sbaType, parametersSBA);
std::map<int, Transform> newPoses = sbaOptimizer->optimizeBA(
optimizedPoses.begin()->first,
+27 -31
View File
@@ -40,30 +40,28 @@ PostProcessingDialog::PostProcessingDialog(QWidget * parent) :
_ui = new Ui_PostProcessingDialog();
_ui->setupUi(this);
if(!Optimizer::isAvailable(Optimizer::kTypeCVSBA) &&
!Optimizer::isAvailable(Optimizer::kTypeG2O) &&
!Optimizer::isAvailable(Optimizer::kTypeCeres))
int firstAvailable = -1;
for(int i = 0; i < _ui->comboBox_sbaType->count(); ++i)
{
const Optimizer::Type type = static_cast<Optimizer::Type>(i);
const bool usable = type != Optimizer::kTypeTORO && Optimizer::isAvailable(type);
if(usable)
{
if(firstAvailable < 0) firstAvailable = i;
}
else
{
_ui->comboBox_sbaType->setItemData(i, 0, Qt::UserRole - 1);
}
}
if(firstAvailable < 0)
{
_ui->sba->setEnabled(false);
_ui->sba->setChecked(false);
}
else
{
if(!Optimizer::isAvailable(Optimizer::kTypeCVSBA))
{
_ui->comboBox_sbaType->setItemData(1, 0, Qt::UserRole - 1);
_ui->comboBox_sbaType->setCurrentIndex(0);
}
if(!Optimizer::isAvailable(Optimizer::kTypeG2O))
{
_ui->comboBox_sbaType->setItemData(0, 0, Qt::UserRole - 1);
_ui->comboBox_sbaType->setCurrentIndex(1);
}
if(!Optimizer::isAvailable(Optimizer::kTypeCeres))
{
_ui->comboBox_sbaType->setItemData(2, 0, Qt::UserRole - 1);
_ui->comboBox_sbaType->setCurrentIndex(1);
}
_ui->comboBox_sbaType->setCurrentIndex(firstAvailable);
}
restoreDefaults();
@@ -135,8 +133,13 @@ bool PostProcessingDialog::validateForm()
void PostProcessingDialog::updateVisibility()
{
_ui->sba_variance->setVisible(_ui->comboBox_sbaType->currentIndex() == 0);
_ui->label_variance->setVisible(_ui->comboBox_sbaType->currentIndex() == 0);
// Pixel variance applies to every BA backend except CVSBA (its
// underlying Sba::run() API takes 2D points only -- no info-matrix
// knob).
const Optimizer::Type type = static_cast<Optimizer::Type>(_ui->comboBox_sbaType->currentIndex());
const bool usesPixelVariance = type != Optimizer::kTypeCVSBA;
_ui->sba_variance->setVisible(usesPixelVariance);
_ui->label_variance->setVisible(usesPixelVariance);
}
void PostProcessingDialog::saveSettings(QSettings & settings, const QString & group) const
@@ -288,7 +291,7 @@ double PostProcessingDialog::sbaVariance() const
}
Optimizer::Type PostProcessingDialog::sbaType() const
{
return _ui->comboBox_sbaType->currentIndex()==2?Optimizer::kTypeCeres:_ui->comboBox_sbaType->currentIndex()==1?Optimizer::kTypeCVSBA:Optimizer::kTypeG2O;
return static_cast<Optimizer::Type>(_ui->comboBox_sbaType->currentIndex());
}
bool PostProcessingDialog::sbaRematchFeatures() const
{
@@ -349,18 +352,11 @@ void PostProcessingDialog::setSBAVariance(double variance)
}
void PostProcessingDialog::setSBAType(Optimizer::Type type)
{
if(type == Optimizer::kTypeCeres)
if(type < 0 || type >= _ui->comboBox_sbaType->count())
{
_ui->comboBox_sbaType->setCurrentIndex(2);
}
else if(type == Optimizer::kTypeCVSBA)
{
_ui->comboBox_sbaType->setCurrentIndex(1);
}
else
{
_ui->comboBox_sbaType->setCurrentIndex(0);
type = Optimizer::kTypeG2O;
}
_ui->comboBox_sbaType->setCurrentIndex(static_cast<int>(type));
}
void PostProcessingDialog::setSBARematchFeatures(bool value)
{
+7 -5
View File
@@ -152,11 +152,11 @@ PreferencesDialog::PreferencesDialog(QWidget * parent) :
bool haveCuda = false;
#if CV_MAJOR_VERSION < 3
#ifdef HAVE_OPENCV_GPU
haveCuda = cv::gpu::getCudaEnabledDeviceCount() != 0;
haveCuda = cv::gpu::getCudaEnabledDeviceCount() > 0;
#endif
#else
#ifdef HAVE_OPENCV_CUDAFEATURES2D
haveCuda = cv::cuda::getCudaEnabledDeviceCount() != 0;
haveCuda = cv::cuda::getCudaEnabledDeviceCount() > 0;
#endif
#endif
if(!haveCuda)
@@ -1317,9 +1317,10 @@ PreferencesDialog::PreferencesDialog(QWidget * parent) :
_ui->comboBox_g2o_solver->setObjectName(Parameters::kg2oSolver().c_str());
_ui->comboBox_g2o_optimizer->setObjectName(Parameters::kg2oOptimizer().c_str());
_ui->doubleSpinBox_g2o_pixelVariance->setObjectName(Parameters::kg2oPixelVariance().c_str());
_ui->doubleSpinBox_g2o_robustKernelDelta->setObjectName(Parameters::kg2oRobustKernelDelta().c_str());
_ui->doubleSpinBox_g2o_baseline->setObjectName(Parameters::kg2oBaseline().c_str());
_ui->doubleSpinBox_g2o_pixelVariance->setObjectName(Parameters::kOptimizerPixelVariance().c_str());
_ui->doubleSpinBox_optimizer_disparityVariance->setObjectName(Parameters::kOptimizerDisparityVariance().c_str());
_ui->doubleSpinBox_g2o_robustKernelDelta->setObjectName(Parameters::kOptimizerRobustKernelDelta().c_str());
_ui->doubleSpinBox_g2o_baseline->setObjectName(Parameters::kOptimizerBaseline().c_str());
_ui->comboBox_gtsam_optimizer->setObjectName(Parameters::kGTSAMOptimizer().c_str());
_ui->gtsam_incremental->setObjectName(Parameters::kGTSAMIncremental().c_str());
@@ -1429,6 +1430,7 @@ PreferencesDialog::PreferencesDialog(QWidget * parent) :
_ui->loopClosure_icpPointToPlaneNormalsRadius->setObjectName(Parameters::kIcpPointToPlaneRadius().c_str());
_ui->loopClosure_icpPointToPlaneGroundNormalsUp->setObjectName(Parameters::kIcpPointToPlaneGroundNormalsUp().c_str());
_ui->loopClosure_icpPointToPlaneNormalsMinComplexity->setObjectName(Parameters::kIcpPointToPlaneMinComplexity().c_str());
_ui->loopClosure_icpPointToPlaneComplexityCentered->setObjectName(Parameters::kIcpPointToPlaneComplexityCentered().c_str());
_ui->loopClosure_icpPointToPlaneLowComplexityStrategy->setObjectName(Parameters::kIcpPointToPlaneLowComplexityStrategy().c_str());
_ui->loopClosure_icpDebugExportFormat->setObjectName(Parameters::kIcpDebugExportFormat().c_str());
+15
View File
@@ -205,11 +205,26 @@
</item>
<item row="0" column="0">
<widget class="QComboBox" name="comboBox_sbaType">
<item>
<property name="text">
<string>TORO</string>
</property>
</item>
<item>
<property name="text">
<string>g2o</string>
</property>
</item>
<item>
<property name="text">
<string>GTSAM</string>
</property>
</item>
<item>
<property name="text">
<string>Ceres</string>
</property>
</item>
<item>
<property name="text">
<string>cvsba</string>
+12 -2
View File
@@ -267,7 +267,7 @@
<item row="2" column="1">
<widget class="QLabel" name="label_variance">
<property name="text">
<string>Pixel variance used by g2o.</string>
<string>Pixel variance used by g2o / GTSAM / Ceres BA.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
@@ -308,6 +308,11 @@
</item>
<item row="0" column="0">
<widget class="QComboBox" name="comboBox_sbaType">
<item>
<property name="text">
<string>TORO</string>
</property>
</item>
<item>
<property name="text">
<string>g2o</string>
@@ -315,7 +320,7 @@
</item>
<item>
<property name="text">
<string>cvsba</string>
<string>GTSAM</string>
</property>
</item>
<item>
@@ -323,6 +328,11 @@
<string>Ceres</string>
</property>
</item>
<item>
<property name="text">
<string>cvsba</string>
</property>
</item>
</widget>
</item>
<item row="3" column="1">
+156 -102
View File
@@ -24981,7 +24981,7 @@ Lower the ratio -&gt; higher the precision.</string>
</property>
</widget>
</item>
<item row="23" column="1">
<item row="24" column="1">
<widget class="QLabel" name="label_640">
<property name="text">
<string>Export scans used for ICP in the specified format (a warning on terminal will be shown with the file paths used). Supported formats are &quot;pcd&quot;, &quot;ply&quot; or &quot;vtk&quot;. If logger level is debug, from and to scans will stamped, so previous files won't be overwritten.</string>
@@ -25033,9 +25033,29 @@ Lower the ratio -&gt; higher the precision.</string>
</property>
</widget>
</item>
<item row="23" column="0">
<item row="24" column="0">
<widget class="QLineEdit" name="loopClosure_icpDebugExportFormat"/>
</item>
<item row="23" column="0">
<widget class="QCheckBox" name="loopClosure_icpPointToPlaneComplexityCentered">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="23" column="1">
<widget class="QLabel" name="label_icpPointToPlaneComplexityCentered">
<property name="text">
<string>Structural-complexity metric. If unchecked (default), use the uncentered second-moment matrix (1/N) * sum(n_i * n_i^T) — its smallest eigenvalue measures how well the surface normals span the ambient space, which correctly distinguishes perpendicular-surface scenes from corridors. If checked, use centered PCA (cv::PCA covariance) for backwards compatibility — but the centered metric is known to mis-classify perpendicular-surface scenes as degenerate when normals are consistently viewpoint-flipped.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item row="20" column="0">
<widget class="QDoubleSpinBox" name="loopClosure_icpPointToPlaneGroundNormalsUp">
<property name="decimals">
@@ -25259,7 +25279,7 @@ Lower the ratio -&gt; higher the precision.</string>
<item row="22" column="1">
<widget class="QLabel" name="label_6071">
<property name="text">
<string>Stuctural complexity strategy. If structural complexity is below the minimum complexity threshold: set to 0 to so that the transform is automatically rejected, set to 1 to limit ICP correction in axes with most constraints (e.g., for a corridor-like environment, the resulting transform will be limited in y and yaw, x will taken from the guess), set to 2 to accept &quot;as is&quot; the transform computed by PointToPoint.</string>
<string>Structural complexity strategy. If structural complexity is below the minimum complexity threshold: 0 = reject the transform; 1 (default) = recompute with PointToPoint and limit ICP correction along the unconstrained axes (e.g. in a corridor, x is taken from the guess while y/yaw are still solved for); 2 = recompute with PointToPoint and accept the result &quot;as is&quot;; 3 = keep the PointToPlane transform and apply the same axis-constrained projection as strategy 1.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
@@ -25286,6 +25306,11 @@ Lower the ratio -&gt; higher the precision.</string>
<string>PointToPoint</string>
</property>
</item>
<item>
<property name="text">
<string>Constrained PointToPlane</string>
</property>
</item>
</widget>
</item>
<item row="17" column="1">
@@ -25940,6 +25965,134 @@ Lower the ratio -&gt; higher the precision.</string>
</item>
</layout>
</item>
<item>
<widget class="QGroupBox" name="groupBox_20">
<property name="title">
<string>Bundle Adjustement</string>
</property>
<layout class="QGridLayout" name="gridLayout_84" columnstretch="0,1">
<item row="4" column="1">
<widget class="QLabel" name="label_disparityVariance">
<property name="text">
<string>Disparity variance. Set higher if the depth source is noisier than the feature precision (e.g. stereo block matching at long range); set lower if depth is more accurate than 2d pixel location of the features (e.g. ToF / LiDAR-fused depth).</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLabel" name="label_350">
<property name="text">
<string>Robust kernel delta used for bundle adjustment (0 means don't use robust kernel). Observations with chi2 over this threshold will be ignored in the second optimization pass.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLabel" name="label_352">
<property name="text">
<string>When doing bundle adjustment with RGB-D data, we can set a fake baseline to do stereo bundle adjustment (if 0, mono bundle adjustment is done). For stereo data, the baseline in the calibration is used directly.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QDoubleSpinBox" name="doubleSpinBox_g2o_robustKernelDelta">
<property name="decimals">
<number>3</number>
</property>
<property name="minimum">
<double>0.000000000000000</double>
</property>
<property name="maximum">
<double>999.000000000000000</double>
</property>
<property name="singleStep">
<double>1.000000000000000</double>
</property>
<property name="value">
<double>5.991000000000000</double>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QDoubleSpinBox" name="doubleSpinBox_g2o_baseline">
<property name="suffix">
<string> m</string>
</property>
<property name="decimals">
<number>4</number>
</property>
<property name="minimum">
<double>0.000000000000000</double>
</property>
<property name="maximum">
<double>9.000000000000000</double>
</property>
<property name="singleStep">
<double>0.010000000000000</double>
</property>
<property name="value">
<double>0.075000000000000</double>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QDoubleSpinBox" name="doubleSpinBox_optimizer_disparityVariance">
<property name="decimals">
<number>3</number>
</property>
<property name="minimum">
<double>0.001000000000000</double>
</property>
<property name="maximum">
<double>999.000000000000000</double>
</property>
<property name="singleStep">
<double>0.100000000000000</double>
</property>
<property name="value">
<double>1.000000000000000</double>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QDoubleSpinBox" name="doubleSpinBox_g2o_pixelVariance">
<property name="decimals">
<number>2</number>
</property>
<property name="minimum">
<double>0.010000000000000</double>
</property>
<property name="maximum">
<double>999.000000000000000</double>
</property>
<property name="singleStep">
<double>0.001000000000000</double>
</property>
<property name="value">
<double>0.010000000000000</double>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QLabel" name="label_148">
<property name="text">
<string>Pixel variance of the feature detection. Set higher if features are noisy (low texture, motion blur); set lower if features are sub-pixel.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBoxx_g2o">
<property name="title">
@@ -26008,105 +26161,6 @@ Lower the ratio -&gt; higher the precision.</string>
</item>
</layout>
</item>
<item>
<widget class="QGroupBox" name="groupBox_20">
<property name="title">
<string>Bundle Adjustement</string>
</property>
<layout class="QGridLayout" name="gridLayout_84" columnstretch="0,1">
<item row="0" column="0">
<widget class="QDoubleSpinBox" name="doubleSpinBox_g2o_pixelVariance">
<property name="decimals">
<number>2</number>
</property>
<property name="minimum">
<double>0.010000000000000</double>
</property>
<property name="maximum">
<double>999.000000000000000</double>
</property>
<property name="singleStep">
<double>0.001000000000000</double>
</property>
<property name="value">
<double>0.010000000000000</double>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLabel" name="label_148">
<property name="text">
<string>Pixel variance used for bundle adjustment.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QDoubleSpinBox" name="doubleSpinBox_g2o_robustKernelDelta">
<property name="decimals">
<number>3</number>
</property>
<property name="minimum">
<double>0.000000000000000</double>
</property>
<property name="maximum">
<double>999.000000000000000</double>
</property>
<property name="singleStep">
<double>1.000000000000000</double>
</property>
<property name="value">
<double>5.991000000000000</double>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLabel" name="label_350">
<property name="text">
<string>Robust kernel delta used for bundle adjustment (0 means don't use robust kernel). Observations with chi2 over this threshold will be ignored in the second optimization pass.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QDoubleSpinBox" name="doubleSpinBox_g2o_baseline">
<property name="suffix">
<string> m</string>
</property>
<property name="decimals">
<number>4</number>
</property>
<property name="minimum">
<double>0.000000000000000</double>
</property>
<property name="maximum">
<double>9.000000000000000</double>
</property>
<property name="singleStep">
<double>0.010000000000000</double>
</property>
<property name="value">
<double>0.075000000000000</double>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLabel" name="label_352">
<property name="text">
<string>When doing bundle adjustment with RGB-D data, we can set a fake baseline to do stereo bundle adjustment (if 0, mono bundle adjustment is done). For stereo data, the baseline in the calibration is used directly.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
</item>