diff --git a/corelib/include/rtabmap/core/OdometryInfo.h b/corelib/include/rtabmap/core/OdometryInfo.h index 615f2e12..4d8be307 100644 --- a/corelib/include/rtabmap/core/OdometryInfo.h +++ b/corelib/include/rtabmap/core/OdometryInfo.h @@ -52,6 +52,27 @@ public: distanceTravelled(0.0f), type(0) {} + + OdometryInfo copyWithoutData() const + { + OdometryInfo output; + output.lost = lost; + output.matches = matches; + output.inliers = inliers; + output.icpInliersRatio = icpInliersRatio; + output.variance = variance; + output.features = features; + output.localMapSize = localMapSize; + output.timeEstimation = timeEstimation; + output.timeParticleFiltering = timeParticleFiltering; + output.stamp = stamp; + output.transform = transform; + output.transformFiltered = transformFiltered; + output.transformGroundTruth = transformGroundTruth; + output.distanceTravelled = distanceTravelled; + return output; + } + bool lost; int matches; int inliers; diff --git a/corelib/include/rtabmap/core/Parameters.h b/corelib/include/rtabmap/core/Parameters.h index 160e21ff..75ec8a1f 100644 --- a/corelib/include/rtabmap/core/Parameters.h +++ b/corelib/include/rtabmap/core/Parameters.h @@ -382,7 +382,7 @@ class RTABMAP_EXP Parameters RTABMAP_PARAM(Vis, EstimationType, int, 0, "Motion estimation approach: 0:3D->3D, 1:3D->2D (PnP), 2:2D->2D (Epipolar Geometry)"); RTABMAP_PARAM(Vis, ForwardEstOnly, bool, true, "Forward estimation only (A->B). If false, a transformation is also computed in backward direction (B->A), then the two resulting transforms are merged (middle interpolation between the transforms)."); RTABMAP_PARAM(Vis, InlierDistance, float, 0.1, "[Vis/EstimationType = 0] Maximum distance for feature correspondences. Used by 3D->3D estimation approach."); - RTABMAP_PARAM(Vis, RefineIterations, int, 10, "[Vis/EstimationType = 0] Number of iterations used to refine the transformation found by RANSAC. 0 means that the transformation is not refined."); + RTABMAP_PARAM(Vis, RefineIterations, int, 5, "[Vis/EstimationType = 0] Number of iterations used to refine the transformation found by RANSAC. 0 means that the transformation is not refined."); RTABMAP_PARAM(Vis, PnPReprojError, float, 2.0, "[Vis/EstimationType = 1] PnP reprojection error."); RTABMAP_PARAM(Vis, PnPFlags, int, 1, "[Vis/EstimationType = 1] PnP flags: 0=Iterative, 1=EPNP, 2=P3P"); #ifdef RTABMAP_OPENCV3 diff --git a/corelib/src/DBDriverSqlite3.cpp b/corelib/src/DBDriverSqlite3.cpp index 9ffa5cdc..3e986f70 100644 --- a/corelib/src/DBDriverSqlite3.cpp +++ b/corelib/src/DBDriverSqlite3.cpp @@ -1777,7 +1777,6 @@ void DBDriverSqlite3::loadSignaturesQuery(const std::list & ids, std::list< UFATAL("Wrong format of the Data.calibration field (size=%d bytes)", dataSize); } - UWARN("Set %d models to %d", models.size(), (*iter)->id()); (*iter)->sensorData().setCameraModels(models); (*iter)->sensorData().setStereoCameraModel(stereoModel); } diff --git a/corelib/src/OdometryF2M.cpp b/corelib/src/OdometryF2M.cpp index 0c406c74..cbc27efa 100644 --- a/corelib/src/OdometryF2M.cpp +++ b/corelib/src/OdometryF2M.cpp @@ -335,6 +335,7 @@ Transform OdometryF2M::computeTransform( { info->wordMatches = regInfo.matchesIDs; info->wordInliers = regInfo.inliersIDs; + info->localMap = uMultimapToMap(map_->getWords3()); } } diff --git a/corelib/src/RegistrationVis.cpp b/corelib/src/RegistrationVis.cpp index 1f37da16..55cc38e2 100644 --- a/corelib/src/RegistrationVis.cpp +++ b/corelib/src/RegistrationVis.cpp @@ -793,11 +793,14 @@ Transform RegistrationVis::computeTransformationImpl( else if(descriptorsFrom.rows) { //just create fake words - UASSERT(int(kptsFrom.size()) == descriptorsFrom.rows); - UASSERT(words3From.empty() || kptsFrom.size() == words3From.size()); - for(unsigned int i=0; i0) { - double inlier_distance_threshold_sqr = inlierThreshold * inlierThreshold; double error_threshold = inlierThreshold; - double sigma_sqr = refineSigma * refineSigma; int refine_iterations = 0; bool inlier_changed = false, oscillating = false; std::vector new_inliers, prev_inliers = inliers; @@ -143,7 +141,7 @@ Transform transformFromXYZCorrespondences( // Estimate the variance and the new threshold double variance = model->computeVariance (); - error_threshold = sqrt (std::min (inlier_distance_threshold_sqr, sigma_sqr * variance)); + error_threshold = std::min (inlierThreshold, refineSigma * sqrt(variance)); UDEBUG ("RANSAC refineModel: New estimated error threshold: %f (variance=%f) on iteration %d out of %d.", error_threshold, variance, refine_iterations, refineIterations); diff --git a/guilib/include/rtabmap/gui/MainWindow.h b/guilib/include/rtabmap/gui/MainWindow.h index 6cc3f1de..83875f21 100644 --- a/guilib/include/rtabmap/gui/MainWindow.h +++ b/guilib/include/rtabmap/gui/MainWindow.h @@ -234,6 +234,7 @@ private: bool verboseProgress = false); void createAndAddCloudToMap(int nodeId, const Transform & pose, int mapId); void createAndAddScanToMap(int nodeId, const Transform & pose, int mapId); + void createAndAddFeaturesToMap(int nodeId, const Transform & pose, int mapId); Transform alignPosesToGroundTruth(std::map & poses, const std::map & groundTruth); void drawKeypoints(const std::multimap & refWords, const std::multimap & loopWords); void setupMainLayout(bool vertical); @@ -289,6 +290,9 @@ private: std::map::Ptr > _createdScans; std::map > _projectionLocalMaps; // std::map > _gridLocalMaps; // + + std::map::Ptr> _createdFeatures; + Transform _odometryCorrection; Transform _lastOdomPose; bool _processingOdometry; diff --git a/guilib/include/rtabmap/gui/PreferencesDialog.h b/guilib/include/rtabmap/gui/PreferencesDialog.h index 8b5b2e06..c9c9d82c 100644 --- a/guilib/include/rtabmap/gui/PreferencesDialog.h +++ b/guilib/include/rtabmap/gui/PreferencesDialog.h @@ -157,6 +157,9 @@ public: double getScanOpacity(int index) const; // 0=map, 1=odom int getScanPointSize(int index) const; // 0=map, 1=odom + bool isFeaturesShown(int index) const; // 0=map, 1=odom + int getFeaturesPointSize(int index) const; // 0=map, 1=odom + bool isCloudFiltering() const; bool isSubtractFiltering() const; double getCloudFilteringRadius() const; @@ -344,6 +347,8 @@ private: QVector _3dRenderingVoxelSizeScan; QVector _3dRenderingOpacityScan; QVector _3dRenderingPtSizeScan; + QVector _3dRenderingShowFeatures; + QVector _3dRenderingPtSizeFeatures; }; Q_DECLARE_OPERATORS_FOR_FLAGS(PreferencesDialog::PANEL_FLAGS) diff --git a/guilib/src/CloudViewer.cpp b/guilib/src/CloudViewer.cpp index e4d5af28..78df637e 100644 --- a/guilib/src/CloudViewer.cpp +++ b/guilib/src/CloudViewer.cpp @@ -1072,10 +1072,12 @@ void CloudViewer::updateCameraTargetPosition(const Transform & pose) this->addOrUpdateCoordinate("reference", pose, 0.2); - _visualizer->setCameraPosition( - cameras.front().pos[0], cameras.front().pos[1], cameras.front().pos[2], - cameras.front().focal[0], cameras.front().focal[1], cameras.front().focal[2], - cameras.front().view[0], cameras.front().view[1], cameras.front().view[2]); + vtkRenderer* renderer = _visualizer->getRendererCollection()->GetFirstRenderer(); + vtkSmartPointer cam = renderer->GetActiveCamera (); + cam->SetPosition (cameras.front().pos[0], cameras.front().pos[1], cameras.front().pos[2]); + cam->SetFocalPoint (cameras.front().focal[0], cameras.front().focal[1], cameras.front().focal[2]); + cam->SetViewUp (cameras.front().view[0], cameras.front().view[1], cameras.front().view[2]); + renderer->ResetCameraClippingRange(); } } diff --git a/guilib/src/MainWindow.cpp b/guilib/src/MainWindow.cpp index ddb7cc54..a2a475f6 100644 --- a/guilib/src/MainWindow.cpp +++ b/guilib/src/MainWindow.cpp @@ -709,7 +709,7 @@ void MainWindow::handleEvent(UEvent* anEvent) // we receive too many odometry events! just send without data SensorData data(cv::Mat(), odomEvent->data().id(), odomEvent->data().stamp()); data.setGroundTruth(odomEvent->data().groundTruth()); - OdometryEvent tmp(data, odomEvent->pose(), odomEvent->covariance(), odomEvent->info()); + OdometryEvent tmp(data, odomEvent->pose(), odomEvent->covariance(), odomEvent->info().copyWithoutData()); emit odometryReceived(tmp); } } @@ -799,6 +799,7 @@ void MainWindow::processOdometry(const rtabmap::OdometryEvent & odom) { bool cloudUpdated = false; bool scanUpdated = false; + bool featuresUpdated = false; if(!pose.isNull()) { // 3d cloud @@ -880,6 +881,35 @@ void MainWindow::processOdometry(const rtabmap::OdometryEvent & odom) scanUpdated = true; } + + // 3d features + if(_preferencesDialog->isFeaturesShown(1)) + { + if(!odom.info().localMap.empty()) + { + pcl::PointCloud::Ptr cloud(new pcl::PointCloud); + cloud->resize(odom.info().localMap.size()); + int i=0; + for(std::map::const_iterator iter=odom.info().localMap.begin(); iter!=odom.info().localMap.end(); ++iter) + { + (*cloud)[i].x = iter->second.x; + (*cloud)[i].y = iter->second.y; + (*cloud)[i].z = iter->second.z; + + // green = inlier, yellow = outliers + bool inlier = odom.info().words.find(iter->first) != odom.info().words.end(); + (*cloud)[i].r = inlier?0:255; + (*cloud)[i].g = 255; + (*cloud)[i++].b = 0; + } + + _ui->widget_cloudViewer->addCloud("featuresOdom", cloud, _odometryCorrection); + _ui->widget_cloudViewer->setCloudVisibility("featuresOdom", true); + _ui->widget_cloudViewer->setCloudPointSize("featuresOdom", _preferencesDialog->getFeaturesPointSize(1)); + + featuresUpdated = true; + } + } } if(!cloudUpdated && _ui->widget_cloudViewer->getAddedClouds().contains("cloudOdom")) { @@ -889,6 +919,10 @@ void MainWindow::processOdometry(const rtabmap::OdometryEvent & odom) { _ui->widget_cloudViewer->setCloudVisibility("scanOdom", false); } + if(!featuresUpdated && _ui->widget_cloudViewer->getAddedClouds().contains("featuresOdom")) + { + _ui->widget_cloudViewer->setCloudVisibility("featuresOdom", false); + } } if(!odom.pose().isNull()) @@ -1658,6 +1692,44 @@ void MainWindow::updateMapCloud( _ui->widget_cloudViewer->setCloudVisibility(scanName.c_str(), false); } + // 3d features + std::string featuresName = uFormat("features%d", iter->first); + if(_ui->widget_cloudViewer->isVisible() && _preferencesDialog->isFeaturesShown(0)) + { + if(viewerClouds.contains(featuresName)) + { + // Update only if the pose has changed + Transform tFeatures; + _ui->widget_cloudViewer->getPose(featuresName, tFeatures); + if(tFeatures.isNull() || iter->second != tFeatures) + { + if(!_ui->widget_cloudViewer->updateCloudPose(featuresName, iter->second)) + { + UERROR("Updating pose features %d failed!", iter->first); + } + } + _ui->widget_cloudViewer->setCloudVisibility(featuresName, true); + _ui->widget_cloudViewer->setCloudPointSize(featuresName, _preferencesDialog->getFeaturesPointSize(0)); + } + else if(_cachedSignatures.contains(iter->first)) + { + QMap::iterator jter = _cachedSignatures.find(iter->first); + if(!jter->getWords3().empty()) + { + this->createAndAddFeaturesToMap(iter->first, iter->second, uValue(mapIds, iter->first, -1)); + } + } + if(!_preferencesDialog->isFeaturesShown(0)) + { + UDEBUG("Hide features %s", featuresName.c_str()); + _ui->widget_cloudViewer->setCloudVisibility(featuresName.c_str(), false); + } + } + else if(viewerClouds.contains(featuresName)) + { + _ui->widget_cloudViewer->setCloudVisibility(featuresName.c_str(), false); + } + if(verboseProgress) { _initProgressDialog->appendText(tr("Updated cloud %1 (%2/%3)").arg(iter->first).arg(i).arg(poses.size())); @@ -1858,6 +1930,20 @@ void MainWindow::updateMapCloud( _ui->widget_cloudViewer->setCloudPointSize("scanOdom", _preferencesDialog->getScanPointSize(1)); } } + if(viewerClouds.contains("featuresOdom")) + { + if(!_preferencesDialog->isFeaturesShown(1)) + { + UDEBUG(""); + _ui->widget_cloudViewer->setCloudVisibility("featuresOdom", false); + } + else + { + UDEBUG(""); + _ui->widget_cloudViewer->updateCloudPose("featuresOdom", _odometryCorrection); + _ui->widget_cloudViewer->setCloudPointSize("featuresOdom", _preferencesDialog->getFeaturesPointSize(1)); + } + } if(!currentPose.isNull()) { @@ -2023,60 +2109,6 @@ void MainWindow::createAndAddCloudToMap(int nodeId, const Transform & pose, int } } } - else if(iter->getWords3().size()) - { - UINFO("Create cloud from 3D words"); - QColor color = Qt::gray; - if(mapId >= 0) - { - color = (Qt::GlobalColor)(mapId+3 % 12 + 7 ); - } - pcl::PointCloud::Ptr cloud(new pcl::PointCloud); - pcl::IndicesPtr indices(new std::vector); - cloud->resize(iter->getWords3().size()); - indices->resize(cloud->size()); - int oi=0; - UASSERT(iter->getWords().size() == iter->getWords3().size()); - std::multimap::const_iterator kter=iter->getWords().begin(); - for(std::multimap::const_iterator jter=iter->getWords3().begin(); - jter!=iter->getWords3().end(); ++jter, ++kter, ++oi) - { - indices->at(oi) = oi; - (*cloud)[oi].x = jter->second.x; - (*cloud)[oi].y = jter->second.y; - (*cloud)[oi].z = jter->second.z; - int u = kter->second.pt.x+0.5; - int v = kter->second.pt.x+0.5; - if(!iter->sensorData().imageRaw().empty() && - uIsInBounds(u, 0, iter->sensorData().imageRaw().cols-1) && - uIsInBounds(v, 0, iter->sensorData().imageRaw().rows-1)) - { - if(iter->sensorData().imageRaw().channels() == 1) - { - (*cloud)[oi].r = (*cloud)[oi].g = (*cloud)[oi].b = iter->sensorData().imageRaw().at(u, v); - } - else - { - cv::Vec3b bgr = iter->sensorData().imageRaw().at(u, v); - (*cloud)[oi].r = bgr.val[0]; - (*cloud)[oi].g = bgr.val[1]; - (*cloud)[oi].b = bgr.val[2]; - } - } - else - { - (*cloud)[oi].r = (*cloud)[oi].g = (*cloud)[oi].b = 255; - } - } - if(!_ui->widget_cloudViewer->addCloud(cloudName, cloud, pose, color)) - { - UERROR("Adding cloud %d to viewer failed!", nodeId); - } - else - { - _createdClouds.insert(std::make_pair(nodeId, std::make_pair(cloud, indices))); - } - } else { return; @@ -2171,6 +2203,98 @@ void MainWindow::createAndAddScanToMap(int nodeId, const Transform & pose, int m } } +void MainWindow::createAndAddFeaturesToMap(int nodeId, const Transform & pose, int mapId) +{ + UDEBUG(""); + UASSERT(!pose.isNull()); + std::string cloudName = uFormat("features%d", nodeId); + if(_ui->widget_cloudViewer->getAddedClouds().contains(cloudName)) + { + UERROR("Features cloud %d already added to map.", nodeId); + return; + } + + QMap::iterator iter = _cachedSignatures.find(nodeId); + if(iter == _cachedSignatures.end()) + { + UERROR("Node %d is not in the cache.", nodeId); + return; + } + + if(_createdFeatures.find(nodeId) != _createdFeatures.end()) + { + UDEBUG("Features cloud %d already created."); + return; + } + + if(iter->getWords3().size()) + { + UINFO("Create cloud from 3D words"); + QColor color = Qt::gray; + if(mapId >= 0) + { + color = (Qt::GlobalColor)(mapId+3 % 12 + 7 ); + } + + cv::Mat rgb; + if(!iter->sensorData().imageCompressed().empty() || !iter->sensorData().imageRaw().empty()) + { + SensorData data = iter->sensorData(); + data.uncompressData(&rgb, 0, 0); + } + + pcl::PointCloud::Ptr cloud(new pcl::PointCloud); + cloud->resize(iter->getWords3().size()); + int oi=0; + UASSERT(iter->getWords().size() == iter->getWords3().size()); + std::multimap::const_iterator kter=iter->getWords().begin(); + for(std::multimap::const_iterator jter=iter->getWords3().begin(); + jter!=iter->getWords3().end(); ++jter, ++kter, ++oi) + { + (*cloud)[oi].x = jter->second.x; + (*cloud)[oi].y = jter->second.y; + (*cloud)[oi].z = jter->second.z; + int u = kter->second.pt.x+0.5; + int v = kter->second.pt.y+0.5; + if(!rgb.empty() && + uIsInBounds(u, 0, rgb.cols-1) && + uIsInBounds(v, 0, rgb.rows-1)) + { + if(rgb.channels() == 1) + { + (*cloud)[oi].r = (*cloud)[oi].g = (*cloud)[oi].b = rgb.at(v, u); + } + else + { + cv::Vec3b bgr = rgb.at(v, u); + (*cloud)[oi].b = bgr.val[0]; + (*cloud)[oi].g = bgr.val[1]; + (*cloud)[oi].r = bgr.val[2]; + } + } + else + { + (*cloud)[oi].r = (*cloud)[oi].g = (*cloud)[oi].b = 255; + } + } + if(!_ui->widget_cloudViewer->addCloud(cloudName, cloud, pose, color)) + { + UERROR("Adding features cloud %d to viewer failed!", nodeId); + } + else + { + _createdFeatures.insert(std::make_pair(nodeId, cloud)); + } + } + else + { + return; + } + + _ui->widget_cloudViewer->setCloudPointSize(cloudName, _preferencesDialog->getFeaturesPointSize(0)); + UDEBUG(""); +} + Transform MainWindow::alignPosesToGroundTruth( std::map & poses, const std::map & groundTruth) @@ -4301,6 +4425,7 @@ void MainWindow::clearTheCache() _createdScans.clear(); _gridLocalMaps.clear(); _projectionLocalMaps.clear(); + _createdFeatures.clear(); _ui->widget_cloudViewer->clear(); _ui->widget_cloudViewer->setBackgroundColor(_ui->widget_cloudViewer->getDefaultBackgroundColor()); _ui->widget_cloudViewer->clearTrajectory(); diff --git a/guilib/src/PreferencesDialog.cpp b/guilib/src/PreferencesDialog.cpp index 661ad53b..4f5e43f9 100644 --- a/guilib/src/PreferencesDialog.cpp +++ b/guilib/src/PreferencesDialog.cpp @@ -308,12 +308,21 @@ PreferencesDialog::PreferencesDialog(QWidget * parent) : _3dRenderingPtSizeScan[0] = _ui->spinBox_ptsize_scan; _3dRenderingPtSizeScan[1] = _ui->spinBox_ptsize_odom_scan; + _3dRenderingShowFeatures.resize(2); + _3dRenderingShowFeatures[0] = _ui->checkBox_showFeatures; + _3dRenderingShowFeatures[1] = _ui->checkBox_showOdomFeatures; + + _3dRenderingPtSizeFeatures.resize(2); + _3dRenderingPtSizeFeatures[0] = _ui->spinBox_ptsize_features; + _3dRenderingPtSizeFeatures[1] = _ui->spinBox_ptsize_odom_features; + for(int i=0; i<2; ++i) { connect(_3dRenderingShowClouds[i], SIGNAL(stateChanged(int)), this, SLOT(makeObsoleteCloudRenderingPanel())); connect(_3dRenderingDecimation[i], SIGNAL(valueChanged(int)), this, SLOT(makeObsoleteCloudRenderingPanel())); connect(_3dRenderingMaxDepth[i], SIGNAL(valueChanged(double)), this, SLOT(makeObsoleteCloudRenderingPanel())); connect(_3dRenderingShowScans[i], SIGNAL(stateChanged(int)), this, SLOT(makeObsoleteCloudRenderingPanel())); + connect(_3dRenderingShowFeatures[i], SIGNAL(stateChanged(int)), this, SLOT(makeObsoleteCloudRenderingPanel())); connect(_3dRenderingDownsamplingScan[i], SIGNAL(valueChanged(int)), this, SLOT(makeObsoleteCloudRenderingPanel())); connect(_3dRenderingVoxelSizeScan[i], SIGNAL(valueChanged(double)), this, SLOT(makeObsoleteCloudRenderingPanel())); @@ -321,6 +330,7 @@ PreferencesDialog::PreferencesDialog(QWidget * parent) : connect(_3dRenderingPtSize[i], SIGNAL(valueChanged(int)), this, SLOT(makeObsoleteCloudRenderingPanel())); connect(_3dRenderingOpacityScan[i], SIGNAL(valueChanged(double)), this, SLOT(makeObsoleteCloudRenderingPanel())); connect(_3dRenderingPtSizeScan[i], SIGNAL(valueChanged(int)), this, SLOT(makeObsoleteCloudRenderingPanel())); + connect(_3dRenderingPtSizeFeatures[i], SIGNAL(valueChanged(int)), this, SLOT(makeObsoleteCloudRenderingPanel())); } connect(_ui->checkBox_showGraphs, SIGNAL(stateChanged(int)), this, SLOT(makeObsoleteCloudRenderingPanel())); @@ -1119,6 +1129,7 @@ void PreferencesDialog::resetSettings(QGroupBox * groupBox) _3dRenderingDecimation[i]->setValue(8); _3dRenderingMaxDepth[i]->setValue(0.0); _3dRenderingShowScans[i]->setChecked(true); + _3dRenderingShowFeatures[i]->setChecked(false); _3dRenderingDownsamplingScan[i]->setValue(1); _3dRenderingVoxelSizeScan[i]->setValue(0.0); @@ -1126,6 +1137,7 @@ void PreferencesDialog::resetSettings(QGroupBox * groupBox) _3dRenderingPtSize[i]->setValue(2); _3dRenderingOpacityScan[i]->setValue(i==0?1.0:0.5); _3dRenderingPtSizeScan[i]->setValue(2); + _3dRenderingPtSizeFeatures[i]->setValue(3); } _ui->checkBox_showGraphs->setChecked(true); @@ -1454,6 +1466,7 @@ void PreferencesDialog::readGuiSettings(const QString & filePath) _3dRenderingDecimation[i]->setValue(settings.value(QString("decimation%1").arg(i), _3dRenderingDecimation[i]->value()).toInt()); _3dRenderingMaxDepth[i]->setValue(settings.value(QString("maxDepth%1").arg(i), _3dRenderingMaxDepth[i]->value()).toDouble()); _3dRenderingShowScans[i]->setChecked(settings.value(QString("showScans%1").arg(i), _3dRenderingShowScans[i]->isChecked()).toBool()); + _3dRenderingShowFeatures[i]->setChecked(settings.value(QString("showFeatures%1").arg(i), _3dRenderingShowFeatures[i]->isChecked()).toBool()); _3dRenderingDownsamplingScan[i]->setValue(settings.value(QString("downsamplingScan%1").arg(i), _3dRenderingDownsamplingScan[i]->value()).toInt()); _3dRenderingVoxelSizeScan[i]->setValue(settings.value(QString("voxelSizeScan%1").arg(i), _3dRenderingVoxelSizeScan[i]->value()).toDouble()); @@ -1461,6 +1474,7 @@ void PreferencesDialog::readGuiSettings(const QString & filePath) _3dRenderingPtSize[i]->setValue(settings.value(QString("ptSize%1").arg(i), _3dRenderingPtSize[i]->value()).toInt()); _3dRenderingOpacityScan[i]->setValue(settings.value(QString("opacityScan%1").arg(i), _3dRenderingOpacityScan[i]->value()).toDouble()); _3dRenderingPtSizeScan[i]->setValue(settings.value(QString("ptSizeScan%1").arg(i), _3dRenderingPtSizeScan[i]->value()).toInt()); + _3dRenderingPtSizeFeatures[i]->setValue(settings.value(QString("ptSizeFeatures%1").arg(i), _3dRenderingPtSizeFeatures[i]->value()).toInt()); } _ui->checkBox_showGraphs->setChecked(settings.value("showGraphs", _ui->checkBox_showGraphs->isChecked()).toBool()); _ui->checkBox_showLabels->setChecked(settings.value("showLabels", _ui->checkBox_showLabels->isChecked()).toBool()); @@ -1832,6 +1846,7 @@ void PreferencesDialog::writeGuiSettings(const QString & filePath) const settings.setValue(QString("decimation%1").arg(i), _3dRenderingDecimation[i]->value()); settings.setValue(QString("maxDepth%1").arg(i), _3dRenderingMaxDepth[i]->value()); settings.setValue(QString("showScans%1").arg(i), _3dRenderingShowScans[i]->isChecked()); + settings.setValue(QString("showFeatures%1").arg(i), _3dRenderingShowFeatures[i]->isChecked()); settings.setValue(QString("downsamplingScan%1").arg(i), _3dRenderingDownsamplingScan[i]->value()); settings.setValue(QString("voxelSizeScan%1").arg(i), _3dRenderingVoxelSizeScan[i]->value()); @@ -1839,6 +1854,7 @@ void PreferencesDialog::writeGuiSettings(const QString & filePath) const settings.setValue(QString("ptSize%1").arg(i), _3dRenderingPtSize[i]->value()); settings.setValue(QString("opacityScan%1").arg(i), _3dRenderingOpacityScan[i]->value()); settings.setValue(QString("ptSizeScan%1").arg(i), _3dRenderingPtSizeScan[i]->value()); + settings.setValue(QString("ptSizeFeatures%1").arg(i), _3dRenderingPtSizeFeatures[i]->value()); } settings.setValue("showGraphs", _ui->checkBox_showGraphs->isChecked()); settings.setValue("showLabels", _ui->checkBox_showLabels->isChecked()); @@ -2137,7 +2153,7 @@ bool PreferencesDialog::validateForm() } // verify that Robust and Reject threshold are not set at the same time - if(_ui->graphOptimization_robust->isEnabled() && _ui->graphOptimization_maxError->value()>0.0) + if(_ui->graphOptimization_robust->isChecked() && _ui->graphOptimization_maxError->value()>0.0) { QMessageBox::warning(this, tr("Parameter warning"), tr("Robust graph optimization and maximum optimization error threshold cannot be " @@ -3544,6 +3560,18 @@ int PreferencesDialog::getScanPointSize(int index) const UASSERT(index >= 0 && index <= 1); return _3dRenderingPtSizeScan[index]->value(); } + +bool PreferencesDialog::isFeaturesShown(int index) const +{ + UASSERT(index >= 0 && index <= 1); + return _3dRenderingShowFeatures[index]->isChecked(); +} +int PreferencesDialog::getFeaturesPointSize(int index) const +{ + UASSERT(index >= 0 && index <= 1); + return _3dRenderingPtSizeFeatures[index]->value(); +} + bool PreferencesDialog::isCloudFiltering() const { return _ui->radioButton_nodeFiltering->isChecked(); diff --git a/guilib/src/ui/preferencesDialog.ui b/guilib/src/ui/preferencesDialog.ui index dcd20294..e568010e 100644 --- a/guilib/src/ui/preferencesDialog.ui +++ b/guilib/src/ui/preferencesDialog.ui @@ -63,7 +63,7 @@ 0 - 0 + -629 681 2010 @@ -86,7 +86,7 @@ QFrame::Raised - 7 + 1 @@ -773,16 +773,22 @@ Show a yellow background when the number of odometry inliers goes under this thr QFrame::Raised - - - - Show 3D clouds. + + + + - - true + + 2 - - Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse + + 1.000000000000000 + + + 0.100000000000000 + + + 1.000000000000000 @@ -799,6 +805,39 @@ Show a yellow background when the number of odometry inliers goes under this thr + + + + Show 3D clouds. + + + true + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse + + + + + + + + + + true + + + + + + + + + + true + + + @@ -876,25 +915,6 @@ Show a yellow background when the number of odometry inliers goes under this thr - - - - - - - 2 - - - 1.000000000000000 - - - 0.100000000000000 - - - 1.000000000000000 - - - @@ -1106,7 +1126,7 @@ Show a yellow background when the number of odometry inliers goes under this thr - + Show graphs. @@ -1119,7 +1139,7 @@ Show a yellow background when the number of odometry inliers goes under this thr - + @@ -1168,7 +1188,7 @@ Show a yellow background when the number of odometry inliers goes under this thr - + Show labels. @@ -1181,7 +1201,7 @@ Show a yellow background when the number of odometry inliers goes under this thr - + @@ -1259,6 +1279,52 @@ Show a yellow background when the number of odometry inliers goes under this thr + + + + Show 3D features. + + + true + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse + + + + + + + Feature point size. + + + true + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse + + + + + + + 1 + + + 64 + + + + + + + 1 + + + 64 + + +