From cb7c76889d711dc74f8f05bfd45607575e1ad454 Mon Sep 17 00:00:00 2001 From: matlabbe Date: Sun, 12 Jun 2016 13:51:49 -0400 Subject: [PATCH] API achange (0.11.8): computeNormals returns only pcl::Normal cloud, not pcl::PointNormal or pcl::PointXYZRGBNormal types. MainWindow: Normals are not kept in cache to save RAM. ProgressDialog: check if auto-close is still checked when close() slot is called. --- CMakeLists.txt | 2 +- corelib/include/rtabmap/core/util3d_surface.h | 15 +- corelib/src/CameraRGB.cpp | 6 +- corelib/src/CameraThread.cpp | 5 +- corelib/src/RegistrationIcp.cpp | 11 +- corelib/src/util3d.cpp | 4 +- corelib/src/util3d_surface.cpp | 70 ++++----- guilib/include/rtabmap/gui/MainWindow.h | 4 +- .../include/rtabmap/gui/PreferencesDialog.h | 1 + guilib/include/rtabmap/gui/ProgressDialog.h | 3 + guilib/src/DatabaseViewer.cpp | 11 +- guilib/src/ExportCloudsDialog.cpp | 148 ++++++++++-------- guilib/src/ExportCloudsDialog.h | 8 +- guilib/src/ExportScansDialog.cpp | 11 +- guilib/src/MainWindow.cpp | 127 +++++++++++---- guilib/src/PreferencesDialog.cpp | 10 +- guilib/src/ProgressDialog.cpp | 10 +- guilib/src/ui/DatabaseViewer.ui | 93 ++--------- guilib/src/ui/preferencesDialog.ui | 90 +++++++---- 19 files changed, 342 insertions(+), 287 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4d98b972..81e383bb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -20,7 +20,7 @@ SET(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake_modules") ####################### SET(RTABMAP_MAJOR_VERSION 0) SET(RTABMAP_MINOR_VERSION 11) -SET(RTABMAP_PATCH_VERSION 7) +SET(RTABMAP_PATCH_VERSION 8) SET(RTABMAP_VERSION ${RTABMAP_MAJOR_VERSION}.${RTABMAP_MINOR_VERSION}.${RTABMAP_PATCH_VERSION}) diff --git a/corelib/include/rtabmap/core/util3d_surface.h b/corelib/include/rtabmap/core/util3d_surface.h index 6a0f398d..f3e66bcb 100644 --- a/corelib/include/rtabmap/core/util3d_surface.h +++ b/corelib/include/rtabmap/core/util3d_surface.h @@ -121,28 +121,29 @@ pcl::TextureMesh::Ptr RTABMAP_EXP createTextureMesh( const std::map & poses, const std::map & cameraModels, const std::map & images, - const std::string & tmpDirectory = "."); + const std::string & tmpDirectory = ".", + int kNormalSearch = 20); // if mesh doesn't have normals, compute them with k neighbors -pcl::PointCloud::Ptr RTABMAP_EXP computeNormals( +pcl::PointCloud::Ptr RTABMAP_EXP computeNormals( const pcl::PointCloud::Ptr & cloud, int normalKSearch = 20); -pcl::PointCloud::Ptr RTABMAP_EXP computeNormals( +pcl::PointCloud::Ptr RTABMAP_EXP computeNormals( const pcl::PointCloud::Ptr & cloud, int normalKSearch = 20); -pcl::PointCloud::Ptr RTABMAP_EXP computeNormals( +pcl::PointCloud::Ptr RTABMAP_EXP computeNormals( const pcl::PointCloud::Ptr & cloud, const pcl::IndicesPtr & indices, int normalKSearch = 20); -pcl::PointCloud::Ptr RTABMAP_EXP computeNormals( +pcl::PointCloud::Ptr RTABMAP_EXP computeNormals( const pcl::PointCloud::Ptr & cloud, const pcl::IndicesPtr & indices, int normalKSearch = 20); -pcl::PointCloud::Ptr computeFastOrganizedNormals( +pcl::PointCloud::Ptr computeFastOrganizedNormals( const pcl::PointCloud::Ptr & cloud, float maxDepthChangeFactor = 0.02f, float normalSmoothingSize = 10.0f); -pcl::PointCloud::Ptr computeFastOrganizedNormals( +pcl::PointCloud::Ptr computeFastOrganizedNormals( const pcl::PointCloud::Ptr & cloud, const pcl::IndicesPtr & indices, float maxDepthChangeFactor = 0.02f, diff --git a/corelib/src/CameraRGB.cpp b/corelib/src/CameraRGB.cpp index 8c0a547a..547c89e0 100644 --- a/corelib/src/CameraRGB.cpp +++ b/corelib/src/CameraRGB.cpp @@ -42,6 +42,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include +#include + #include #include #include @@ -661,7 +663,9 @@ SensorData CameraImages::captureImage() } if(_scanNormalsK > 0 && cloud->size()) { - pcl::PointCloud::Ptr cloudNormals = util3d::computeNormals(cloud, _scanNormalsK); + pcl::PointCloud::Ptr normals = util3d::computeNormals(cloud, _scanNormalsK); + pcl::PointCloud::Ptr cloudNormals(new pcl::PointCloud); + pcl::concatenateFields(*cloud, *normals, *cloudNormals); scan = util3d::laserScanFromPointCloud(*cloudNormals); } else diff --git a/corelib/src/CameraThread.cpp b/corelib/src/CameraThread.cpp index 08f6db46..9c90cd5c 100644 --- a/corelib/src/CameraThread.cpp +++ b/corelib/src/CameraThread.cpp @@ -193,7 +193,10 @@ void CameraThread::mainLoop() cv::Mat scan; if(_scanNormalsK>0) { - scan = util3d::laserScanFromPointCloud(*util3d::computeNormals(cloud, _scanNormalsK)); + pcl::PointCloud::Ptr normals = util3d::computeNormals(cloud, _scanNormalsK); + pcl::PointCloud::Ptr cloudNormals(new pcl::PointCloud); + pcl::concatenateFields(*cloud, *normals, *cloudNormals); + scan = util3d::laserScanFromPointCloud(*cloudNormals); } else { diff --git a/corelib/src/RegistrationIcp.cpp b/corelib/src/RegistrationIcp.cpp index 04a94eb2..46d2bff7 100644 --- a/corelib/src/RegistrationIcp.cpp +++ b/corelib/src/RegistrationIcp.cpp @@ -200,8 +200,15 @@ Transform RegistrationIcp::computeTransformationImpl( pcl::PointCloud::Ptr fromCloudRegistered(new pcl::PointCloud()); if(_pointToPlane) // ICP Point To Plane, only in 3D { - pcl::PointCloud::Ptr fromCloudNormals = util3d::computeNormals(fromCloudFiltered, _pointToPlaneNormalNeighbors); - pcl::PointCloud::Ptr toCloudNormals = util3d::computeNormals(toCloudFiltered, _pointToPlaneNormalNeighbors); + pcl::PointCloud::Ptr normals; + + normals = util3d::computeNormals(fromCloudFiltered, _pointToPlaneNormalNeighbors); + pcl::PointCloud::Ptr fromCloudNormals(new pcl::PointCloud); + pcl::concatenateFields(*fromCloudFiltered, *normals, *fromCloudNormals); + + normals = util3d::computeNormals(toCloudFiltered, _pointToPlaneNormalNeighbors); + pcl::PointCloud::Ptr toCloudNormals(new pcl::PointCloud); + pcl::concatenateFields(*toCloudFiltered, *normals, *toCloudNormals); std::vector indices; toCloudNormals = util3d::removeNaNNormalsFromPointCloud(toCloudNormals); diff --git a/corelib/src/util3d.cpp b/corelib/src/util3d.cpp index e4755a65..dc360a3c 100644 --- a/corelib/src/util3d.cpp +++ b/corelib/src/util3d.cpp @@ -1441,7 +1441,9 @@ cv::Mat loadScan( pcl::PointCloud::Ptr cloud = loadCloud(path, Transform::getIdentity(), downsampleStep, voxelSize); if(normalsK > 0 && cloud->size()) { - pcl::PointCloud::Ptr cloudNormals = util3d::computeNormals(cloud, normalsK); + pcl::PointCloud::Ptr normals = util3d::computeNormals(cloud, normalsK); + pcl::PointCloud::Ptr cloudNormals(new pcl::PointCloud); + pcl::concatenateFields(*cloud, *normals, *cloudNormals); scan = util3d::laserScanFromPointCloud(*cloudNormals, transform); } else diff --git a/corelib/src/util3d_surface.cpp b/corelib/src/util3d_surface.cpp index 8bb82c3a..782b2625 100644 --- a/corelib/src/util3d_surface.cpp +++ b/corelib/src/util3d_surface.cpp @@ -500,7 +500,8 @@ pcl::TextureMesh::Ptr createTextureMesh( const std::map & poses, const std::map & cameraModels, const std::map & images, - const std::string & tmpDirectory) + const std::string & tmpDirectory, + int kNormalSearch) { pcl::TextureMesh::Ptr textureMesh(new pcl::TextureMesh); textureMesh->cloud = mesh->cloud; @@ -583,26 +584,28 @@ pcl::TextureMesh::Ptr createTextureMesh( { pcl::PointCloud::Ptr cloud (new pcl::PointCloud); pcl::fromPCLPointCloud2(textureMesh->cloud, *cloud); - pcl::PointCloud::Ptr cloudWithNormals = computeNormals(cloud, 20); + pcl::PointCloud::Ptr normals = computeNormals(cloud, kNormalSearch); + // Concatenate the XYZ and normal fields + pcl::PointCloud::Ptr cloudWithNormals; + pcl::concatenateFields (*cloud, *normals, *cloudWithNormals); pcl::toPCLPointCloud2 (*cloudWithNormals, textureMesh->cloud); } return textureMesh; } -pcl::PointCloud::Ptr computeNormals( +pcl::PointCloud::Ptr computeNormals( const pcl::PointCloud::Ptr & cloud, int normalKSearch) { pcl::IndicesPtr indices(new std::vector); return computeNormals(cloud, indices, normalKSearch); } -pcl::PointCloud::Ptr computeNormals( +pcl::PointCloud::Ptr computeNormals( const pcl::PointCloud::Ptr & cloud, const pcl::IndicesPtr & indices, int normalKSearch) { - pcl::PointCloud::Ptr cloud_with_normals(new pcl::PointCloud); pcl::search::KdTree::Ptr tree (new pcl::search::KdTree); if(indices->size()) { @@ -617,35 +620,30 @@ pcl::PointCloud::Ptr computeNormals( pcl::NormalEstimationOMP n; pcl::PointCloud::Ptr normals (new pcl::PointCloud); n.setInputCloud (cloud); - if(indices->size()) - { - n.setIndices(indices); - } + // Commented: Keep the output normals size the same as the input cloud + //if(indices->size()) + //{ + // n.setIndices(indices); + //} n.setSearchMethod (tree); n.setKSearch (normalKSearch); n.compute (*normals); - //* normals should not contain the point normals + surface curvatures - // Concatenate the XYZ and normal fields* - pcl::concatenateFields (*cloud, *normals, *cloud_with_normals); - //* cloud_with_normals = cloud + normals*/ - - return cloud_with_normals; + return normals; } -pcl::PointCloud::Ptr computeNormals( +pcl::PointCloud::Ptr computeNormals( const pcl::PointCloud::Ptr & cloud, int normalKSearch) { pcl::IndicesPtr indices(new std::vector); return computeNormals(cloud, indices, normalKSearch); } -pcl::PointCloud::Ptr computeNormals( +pcl::PointCloud::Ptr computeNormals( const pcl::PointCloud::Ptr & cloud, const pcl::IndicesPtr & indices, int normalKSearch) { - pcl::PointCloud::Ptr cloud_with_normals(new pcl::PointCloud); pcl::search::KdTree::Ptr tree (new pcl::search::KdTree); if(indices->size()) { @@ -660,23 +658,19 @@ pcl::PointCloud::Ptr computeNormals( pcl::NormalEstimationOMP n; pcl::PointCloud::Ptr normals (new pcl::PointCloud); n.setInputCloud (cloud); - if(indices->size()) - { - n.setIndices(indices); - } + // Commented: Keep the output normals size the same as the input cloud + //if(indices->size()) + //{ + // n.setIndices(indices); + //} n.setSearchMethod (tree); n.setKSearch (normalKSearch); n.compute (*normals); - //* normals should not contain the point normals + surface curvatures - // Concatenate the XYZ and normal fields* - pcl::concatenateFields (*cloud, *normals, *cloud_with_normals); - //* cloud_with_normals = cloud + normals*/ - - return cloud_with_normals; + return normals; } -pcl::PointCloud::Ptr computeFastOrganizedNormals( +pcl::PointCloud::Ptr computeFastOrganizedNormals( const pcl::PointCloud::Ptr & cloud, float maxDepthChangeFactor, float normalSmoothingSize) @@ -684,7 +678,7 @@ pcl::PointCloud::Ptr computeFastOrganizedNormals( pcl::IndicesPtr indices(new std::vector); return computeFastOrganizedNormals(cloud, indices, maxDepthChangeFactor, normalSmoothingSize); } -pcl::PointCloud::Ptr computeFastOrganizedNormals( +pcl::PointCloud::Ptr computeFastOrganizedNormals( const pcl::PointCloud::Ptr & cloud, const pcl::IndicesPtr & indices, float maxDepthChangeFactor, @@ -692,8 +686,6 @@ pcl::PointCloud::Ptr computeFastOrganizedNormals( { UASSERT(cloud->isOrganized()); - pcl::PointCloud::Ptr cloud_with_normals(new pcl::PointCloud); - // Normal estimation pcl::PointCloud::Ptr normals (new pcl::PointCloud); pcl::IntegralImageNormalEstimation ne; @@ -701,16 +693,14 @@ pcl::PointCloud::Ptr computeFastOrganizedNormals( ne.setMaxDepthChangeFactor(maxDepthChangeFactor); ne.setNormalSmoothingSize(normalSmoothingSize); ne.setInputCloud(cloud); - if(indices->size()) - { - ne.setIndices(indices); - } + // Commented: Keep the output normals size the same as the input cloud + //if(indices->size()) + //{ + // ne.setIndices(indices); + //} ne.compute(*normals); - // Concatenate the XYZ and normal fields - pcl::concatenateFields (*cloud, *normals, *cloud_with_normals); - - return cloud_with_normals; + return normals; } pcl::PointCloud::Ptr mls( diff --git a/guilib/include/rtabmap/gui/MainWindow.h b/guilib/include/rtabmap/gui/MainWindow.h index 3f512daa..136af153 100644 --- a/guilib/include/rtabmap/gui/MainWindow.h +++ b/guilib/include/rtabmap/gui/MainWindow.h @@ -286,8 +286,8 @@ private: std::multimap _currentLinksMap; // std::map _currentMapIds; // std::map _currentLabels; // - std::map::Ptr, pcl::IndicesPtr> > _createdClouds; - std::pair::Ptr, pcl::IndicesPtr> > _previousCloud; // used for subtraction + std::map::Ptr, pcl::IndicesPtr> > _createdClouds; + std::pair::Ptr, pcl::PointCloud::Ptr>, pcl::IndicesPtr> > _previousCloud; // used for subtraction std::map _createdScans; std::map > _projectionLocalMaps; // diff --git a/guilib/include/rtabmap/gui/PreferencesDialog.h b/guilib/include/rtabmap/gui/PreferencesDialog.h index 14a86f0b..d3730886 100644 --- a/guilib/include/rtabmap/gui/PreferencesDialog.h +++ b/guilib/include/rtabmap/gui/PreferencesDialog.h @@ -173,6 +173,7 @@ public: int getSubtractFilteringMinPts() const; double getSubtractFilteringRadius() const; double getSubtractFilteringAngle() const; + int getNormalKSearch() const; bool getGridMapShown() const; double getGridMapResolution() const;; diff --git a/guilib/include/rtabmap/gui/ProgressDialog.h b/guilib/include/rtabmap/gui/ProgressDialog.h index d2abf7bf..08af7945 100644 --- a/guilib/include/rtabmap/gui/ProgressDialog.h +++ b/guilib/include/rtabmap/gui/ProgressDialog.h @@ -63,6 +63,9 @@ public slots: void clear(); void resetProgress(); +private slots: + void closeDialog(); + private: QLabel * _text; QTextEdit * _detailedText; diff --git a/guilib/src/DatabaseViewer.cpp b/guilib/src/DatabaseViewer.cpp index 4859b635..e376e093 100644 --- a/guilib/src/DatabaseViewer.cpp +++ b/guilib/src/DatabaseViewer.cpp @@ -1629,7 +1629,9 @@ void DatabaseViewer::view3DLaserScans() } int normalK = uStr2Int(ui_->parameters_toolbox->getParameters().at(Parameters::kIcpPointToPlaneNormalNeighbors())); - pcl::PointCloud::Ptr cloudNormals = util3d::computeNormals(cloud, normalK); + pcl::PointCloud::Ptr normals = util3d::computeNormals(cloud, normalK); + pcl::PointCloud::Ptr cloudNormals(new pcl::PointCloud); + pcl::concatenateFields(*cloud, *normals, *cloudNormals); viewer->addCloud(uFormat("cloud%d", iter->first), cloudNormals, pose, color); @@ -3457,8 +3459,11 @@ void DatabaseViewer::sliderIterationsValueChanged(int value) iter->second.type() == rtabmap::Link::kNeighborMerged) { Eigen::Vector3f vA, vB; - poseA.getTranslation(vA[0], vA[1], vA[2]); - poseB.getTranslation(vB[0], vB[1], vB[2]); + float x,y,z; + poseA.getTranslation(x,y,z); + vA[0] = x; vA[1] = y; vA[2] = z; + poseB.getTranslation(x,y,z); + vB[0] = x; vB[1] = y; vB[2] = z; length += (vB - vA).norm(); } } diff --git a/guilib/src/ExportCloudsDialog.cpp b/guilib/src/ExportCloudsDialog.cpp index c87bff9d..ac14f994 100644 --- a/guilib/src/ExportCloudsDialog.cpp +++ b/guilib/src/ExportCloudsDialog.cpp @@ -243,7 +243,7 @@ void ExportCloudsDialog::loadSettings(QSettings & settings, const QString & grou void ExportCloudsDialog::restoreDefaults() { _ui->checkBox_binary->setChecked(true); - _ui->spinBox_normalKSearch->setValue(6); + _ui->spinBox_normalKSearch->setValue(10); _ui->groupBox_regenerate->setChecked(false); _ui->spinBox_decimation->setValue(1); @@ -259,7 +259,7 @@ void ExportCloudsDialog::restoreDefaults() _ui->groupBox_subtraction->setChecked(false); _ui->doubleSpinBox_subtractPointFilteringRadius->setValue(0.02); - _ui->doubleSpinBox_subtractPointFilteringAngle->setValue(45.0); + _ui->doubleSpinBox_subtractPointFilteringAngle->setValue(0); _ui->spinBox_subtractFilteringMinPts->setValue(5); _ui->groupBox_mls->setChecked(false); @@ -336,7 +336,7 @@ void ExportCloudsDialog::exportClouds( const std::map & poses, const std::map & mapIds, const QMap & cachedSignatures, - const std::map::Ptr, pcl::IndicesPtr> > & createdClouds, + const std::map::Ptr, pcl::IndicesPtr> > & createdClouds, const QString & workingDirectory, const ParametersMap & parameters) { @@ -388,7 +388,7 @@ void ExportCloudsDialog::viewClouds( const std::map & poses, const std::map & mapIds, const QMap & cachedSignatures, - const std::map::Ptr, pcl::IndicesPtr> > & createdClouds, + const std::map::Ptr, pcl::IndicesPtr> > & createdClouds, const QString & workingDirectory, const ParametersMap & parameters) { @@ -519,7 +519,7 @@ bool ExportCloudsDialog::getExportedClouds( const std::map & poses, const std::map & mapIds, const QMap & cachedSignatures, - const std::map::Ptr, pcl::IndicesPtr> > & createdClouds, + const std::map::Ptr, pcl::IndicesPtr> > & createdClouds, const QString & workingDirectory, const ParametersMap & parameters, std::map::Ptr> & cloudsWithNormals, @@ -701,81 +701,87 @@ bool ExportCloudsDialog::getExportedClouds( iter!= cloudsWithNormals.end(); ++iter) { - UASSERT(iter->second->isOrganized()); - if(iter->second->size()) + if(iter->second->isOrganized()) { - Eigen::Vector3f viewpoint(0.0f,0.0f,0.0f); - if(cachedSignatures.contains(iter->first)) + if(iter->second->size()) { - const SensorData & data = cachedSignatures.find(iter->first)->sensorData(); - if(data.cameraModels().size() && !data.cameraModels()[0].localTransform().isNull()) + Eigen::Vector3f viewpoint(0.0f,0.0f,0.0f); + if(cachedSignatures.contains(iter->first)) { - viewpoint[0] = data.cameraModels()[0].localTransform().x(); - viewpoint[1] = data.cameraModels()[0].localTransform().y(); - viewpoint[2] = data.cameraModels()[0].localTransform().z(); + const SensorData & data = cachedSignatures.find(iter->first)->sensorData(); + if(data.cameraModels().size() && !data.cameraModels()[0].localTransform().isNull()) + { + viewpoint[0] = data.cameraModels()[0].localTransform().x(); + viewpoint[1] = data.cameraModels()[0].localTransform().y(); + viewpoint[2] = data.cameraModels()[0].localTransform().z(); + } + else if(!data.stereoCameraModel().localTransform().isNull()) + { + viewpoint[0] = data.stereoCameraModel().localTransform().x(); + viewpoint[1] = data.stereoCameraModel().localTransform().y(); + viewpoint[2] = data.stereoCameraModel().localTransform().z(); + } } - else if(!data.stereoCameraModel().localTransform().isNull()) - { - viewpoint[0] = data.stereoCameraModel().localTransform().x(); - viewpoint[1] = data.stereoCameraModel().localTransform().y(); - viewpoint[2] = data.stereoCameraModel().localTransform().z(); - } - } - std::vector polygons = util3d::organizedFastMesh( - iter->second, - _ui->doubleSpinBox_mesh_angleTolerance->value()*M_PI/180.0, - _ui->checkBox_mesh_quad->isEnabled() && _ui->checkBox_mesh_quad->isChecked(), - _ui->spinBox_mesh_triangleSize->value(), - viewpoint); - _progressDialog->appendText(tr("Mesh %1 created with %2 polygons (%3/%4).").arg(iter->first).arg(polygons.size()).arg(++i).arg(clouds.size())); + std::vector polygons = util3d::organizedFastMesh( + iter->second, + _ui->doubleSpinBox_mesh_angleTolerance->value()*M_PI/180.0, + _ui->checkBox_mesh_quad->isEnabled() && _ui->checkBox_mesh_quad->isChecked(), + _ui->spinBox_mesh_triangleSize->value(), + viewpoint); + _progressDialog->appendText(tr("Mesh %1 created with %2 polygons (%3/%4).").arg(iter->first).arg(polygons.size()).arg(++i).arg(clouds.size())); - pcl::PointCloud::Ptr denseCloud(new pcl::PointCloud); - std::vector densePolygons; - std::map newToOldIndices = util3d::filterNotUsedVerticesFromMesh(*iter->second, polygons, *denseCloud, densePolygons); + pcl::PointCloud::Ptr denseCloud(new pcl::PointCloud); + std::vector densePolygons; + std::map newToOldIndices = util3d::filterNotUsedVerticesFromMesh(*iter->second, polygons, *denseCloud, densePolygons); - if(!_ui->checkBox_assemble->isChecked() || - (_ui->checkBox_textureMapping->isEnabled() && - _ui->checkBox_textureMapping->isChecked() && - _ui->doubleSpinBox_voxelSize_assembled->value() == 0.0)) // don't assemble now if we are texturing - { - if(_ui->checkBox_assemble->isChecked()) + if(!_ui->checkBox_assemble->isChecked() || + (_ui->checkBox_textureMapping->isEnabled() && + _ui->checkBox_textureMapping->isChecked() && + _ui->doubleSpinBox_voxelSize_assembled->value() == 0.0)) // don't assemble now if we are texturing { - denseCloud = util3d::transformPointCloud(denseCloud, poses.at(iter->first)); - } + if(_ui->checkBox_assemble->isChecked()) + { + denseCloud = util3d::transformPointCloud(denseCloud, poses.at(iter->first)); + } - pcl::PolygonMesh::Ptr mesh(new pcl::PolygonMesh); - pcl::toPCLPointCloud2(*denseCloud, mesh->cloud); - mesh->polygons = densePolygons; - if(_ui->doubleSpinBox_meshDecimationFactor->isEnabled() && - _ui->doubleSpinBox_meshDecimationFactor->value() > 0.0) - { - int count = mesh->polygons.size(); - mesh = util3d::meshDecimation(mesh, (float)_ui->doubleSpinBox_meshDecimationFactor->value()); - _progressDialog->appendText(tr("Mesh decimation (factor=%1) from %2 to %3 polygons").arg(_ui->doubleSpinBox_meshDecimationFactor->value()).arg(count).arg(mesh->polygons.size())); + pcl::PolygonMesh::Ptr mesh(new pcl::PolygonMesh); + pcl::toPCLPointCloud2(*denseCloud, mesh->cloud); + mesh->polygons = densePolygons; + if(_ui->doubleSpinBox_meshDecimationFactor->isEnabled() && + _ui->doubleSpinBox_meshDecimationFactor->value() > 0.0) + { + int count = mesh->polygons.size(); + mesh = util3d::meshDecimation(mesh, (float)_ui->doubleSpinBox_meshDecimationFactor->value()); + _progressDialog->appendText(tr("Mesh decimation (factor=%1) from %2 to %3 polygons").arg(_ui->doubleSpinBox_meshDecimationFactor->value()).arg(count).arg(mesh->polygons.size())); + } + else + { + organizedIndices.insert(std::make_pair(iter->first, std::make_pair(newToOldIndices, std::make_pair(iter->second->width, iter->second->height)))); + } + meshes.insert(std::make_pair(iter->first, mesh)); } else { - organizedIndices.insert(std::make_pair(iter->first, std::make_pair(newToOldIndices, std::make_pair(iter->second->width, iter->second->height)))); + denseCloud = util3d::transformPointCloud(denseCloud, poses.at(iter->first)); + if(mergedClouds->size() == 0) + { + *mergedClouds = *denseCloud; + mergedPolygons = densePolygons; + } + else + { + util3d::appendMesh(*mergedClouds, mergedPolygons, *denseCloud, densePolygons); + } } - meshes.insert(std::make_pair(iter->first, mesh)); } else { - denseCloud = util3d::transformPointCloud(denseCloud, poses.at(iter->first)); - if(mergedClouds->size() == 0) - { - *mergedClouds = *denseCloud; - mergedPolygons = densePolygons; - } - else - { - util3d::appendMesh(*mergedClouds, mergedPolygons, *denseCloud, densePolygons); - } + _progressDialog->appendText(tr("Mesh %1 not created (no valid points) (%2/%3).").arg(iter->first).arg(++i).arg(clouds.size())); } } else { - _progressDialog->appendText(tr("Mesh %1 not created (no valid points) (%2/%3).").arg(iter->first).arg(++i).arg(clouds.size())); + _progressDialog->appendText(tr("Mesh %1 not created (cloud is not organized). You may want to check cloud regeneration option (%2/%3).").arg(iter->first).arg(++i).arg(clouds.size())); } _progressDialog->incrementStep(); @@ -1012,7 +1018,7 @@ bool ExportCloudsDialog::getExportedClouds( std::map::Ptr, pcl::IndicesPtr> > ExportCloudsDialog::getClouds( const std::map & poses, const QMap & cachedSignatures, - const std::map::Ptr, pcl::IndicesPtr> > & createdClouds, + const std::map::Ptr, pcl::IndicesPtr> > & createdClouds, const ParametersMap & parameters) const { std::map::Ptr, pcl::IndicesPtr> > clouds; @@ -1059,9 +1065,8 @@ std::map::Ptr, pcl::Indic } } - cloud = util3d::computeNormals( - cloudWithoutNormals, - _ui->spinBox_normalKSearch->value()); + pcl::PointCloud::Ptr normals = util3d::computeNormals(cloudWithoutNormals, indices, _ui->spinBox_normalKSearch->value()); + pcl::concatenateFields(*cloudWithoutNormals, *normals, *cloud); if(_ui->groupBox_subtraction->isChecked() && _ui->doubleSpinBox_subtractPointFilteringRadius->value() > 0.0) @@ -1114,24 +1119,29 @@ std::map::Ptr, pcl::Indic } else if(uContains(createdClouds, iter->first)) { + pcl::PointCloud::Ptr cloudWithoutNormals; if(!_ui->groupBox_meshing->isChecked() && _ui->doubleSpinBox_voxelSize_assembled->value() > 0.0) { - cloud = util3d::voxelize( + cloudWithoutNormals = util3d::voxelize( createdClouds.at(iter->first).first, + createdClouds.at(iter->first).second, _ui->doubleSpinBox_voxelSize_assembled->value()); + //generate indices for all points (they are all valid) - indices->resize(cloud->size()); - for(unsigned int i=0; isize(); ++i) + indices->resize(cloudWithoutNormals->size()); + for(unsigned int i=0; isize(); ++i) { indices->at(i) = i; } } else { - cloud = createdClouds.at(iter->first).first; + cloudWithoutNormals = createdClouds.at(iter->first).first; indices = createdClouds.at(iter->first).second; } + pcl::PointCloud::Ptr normals = util3d::computeNormals(cloudWithoutNormals, indices, _ui->spinBox_normalKSearch->value()); + pcl::concatenateFields(*cloudWithoutNormals, *normals, *cloud); } if(indices->size()) diff --git a/guilib/src/ExportCloudsDialog.h b/guilib/src/ExportCloudsDialog.h index 2ee93248..6a4624e2 100644 --- a/guilib/src/ExportCloudsDialog.h +++ b/guilib/src/ExportCloudsDialog.h @@ -63,7 +63,7 @@ public: const std::map & poses, const std::map & mapIds, const QMap & cachedSignatures, - const std::map::Ptr, pcl::IndicesPtr> > & createdClouds, + const std::map::Ptr, pcl::IndicesPtr> > & createdClouds, const QString & workingDirectory, const ParametersMap & parameters); @@ -71,7 +71,7 @@ public: const std::map & poses, const std::map & mapIds, const QMap & cachedSignatures, - const std::map::Ptr, pcl::IndicesPtr> > & createdClouds, + const std::map::Ptr, pcl::IndicesPtr> > & createdClouds, const QString & workingDirectory, const ParametersMap & parameters); @@ -89,13 +89,13 @@ private: std::map::Ptr, pcl::IndicesPtr> > getClouds( const std::map & poses, const QMap & cachedSignatures, - const std::map::Ptr, pcl::IndicesPtr> > & createdClouds, + const std::map::Ptr, pcl::IndicesPtr> > & createdClouds, const ParametersMap & parameters) const; bool getExportedClouds( const std::map & poses, const std::map & mapIds, const QMap & cachedSignatures, - const std::map::Ptr, pcl::IndicesPtr> > & createdClouds, + const std::map::Ptr, pcl::IndicesPtr> > & createdClouds, const QString & workingDirectory, const ParametersMap & parameters, std::map::Ptr> & clouds, diff --git a/guilib/src/ExportScansDialog.cpp b/guilib/src/ExportScansDialog.cpp index 0f127bc2..74c02d26 100644 --- a/guilib/src/ExportScansDialog.cpp +++ b/guilib/src/ExportScansDialog.cpp @@ -336,9 +336,9 @@ bool ExportScansDialog::getExportedScans( pcl::PointCloud::Ptr cloudXYZ(new pcl::PointCloud); pcl::copyPointCloud(*assembledCloud, *cloudXYZ); - assembledCloud = util3d::computeNormals( - cloudXYZ, - _ui->spinBox_normalKSearch->value()); + + pcl::PointCloud::Ptr normals = util3d::computeNormals(cloudXYZ, _ui->spinBox_normalKSearch->value()); + pcl::concatenateFields(*cloudXYZ, *normals, *assembledCloud); _progressDialog->appendText(tr("Update %1 normals with %2 camera views...") .arg(assembledCloud->size()).arg(poses.size())); @@ -433,9 +433,8 @@ std::map::Ptr> ExportScansDialog::getScan if(!_ui->checkBox_assemble->isChecked() && _ui->spinBox_normalKSearch->value() > 0) { - cloud = util3d::computeNormals( - cloudXYZ, - _ui->spinBox_normalKSearch->value()); + pcl::PointCloud::Ptr normals = util3d::computeNormals(cloudXYZ, _ui->spinBox_normalKSearch->value()); + pcl::concatenateFields(*cloudXYZ, *normals, *cloud); } else { diff --git a/guilib/src/MainWindow.cpp b/guilib/src/MainWindow.cpp index 1ebd7563..db39bd00 100644 --- a/guilib/src/MainWindow.cpp +++ b/guilib/src/MainWindow.cpp @@ -2236,7 +2236,7 @@ void MainWindow::createAndAddCloudToMap(int nodeId, const Transform & pose, int SensorData data = iter->sensorData(); data.uncompressData(&image, &depth, 0); - pcl::PointCloud::Ptr cloudWithoutNormals; + pcl::PointCloud::Ptr cloud; pcl::IndicesPtr indices(new std::vector); UASSERT(nodeId == data.id()); @@ -2252,7 +2252,7 @@ void MainWindow::createAndAddCloudToMap(int nodeId, const Transform & pose, int } // Create organized cloud - cloudWithoutNormals = util3d::cloudRGBFromSensorData(data, + cloud = util3d::cloudRGBFromSensorData(data, _preferencesDialog->getCloudDecimation(0), _preferencesDialog->getCloudMaxDepth(0), _preferencesDialog->getCloudMinDepth(0), @@ -2262,10 +2262,10 @@ void MainWindow::createAndAddCloudToMap(int nodeId, const Transform & pose, int // filtering pipeline if(indices->size() && _preferencesDialog->getMapVoxel() > 0.0) { - cloudWithoutNormals = util3d::voxelize(cloudWithoutNormals, indices, _preferencesDialog->getMapVoxel()); + cloud = util3d::voxelize(cloud, indices, _preferencesDialog->getMapVoxel()); //generate indices for all points (they are all valid) - indices->resize(cloudWithoutNormals->size()); - for(unsigned int i=0; isize(); ++i) + indices->resize(cloud->size()); + for(unsigned int i=0; isize(); ++i) { indices->at(i) = i; } @@ -2277,22 +2277,19 @@ void MainWindow::createAndAddCloudToMap(int nodeId, const Transform & pose, int _preferencesDialog->getMapNoiseMinNeighbors() > 0) { indices = rtabmap::util3d::radiusFiltering( - cloudWithoutNormals, + cloud, indices, _preferencesDialog->getMapNoiseRadius(), _preferencesDialog->getMapNoiseMinNeighbors()); } - //compute normals - pcl::PointCloud::Ptr cloud = util3d::computeNormals(cloudWithoutNormals, 10); - if(indices->size() && _preferencesDialog->isGridMapFrom3DCloud() && _projectionLocalMaps.find(nodeId) == _projectionLocalMaps.end()) { UTimer timer; cv::Mat ground, obstacles; - pcl::PointCloud::Ptr voxelCloud = cloudWithoutNormals; + pcl::PointCloud::Ptr voxelCloud = cloud; // voxelize to grid cell size if(_preferencesDialog->getMapVoxel() < _preferencesDialog->getGridMapResolution()) @@ -2329,6 +2326,7 @@ void MainWindow::createAndAddCloudToMap(int nodeId, const Transform & pose, int UDEBUG("time gridMapFrom3DCloud = %f s", timer.ticks()); } + pcl::PointCloud::Ptr cloudWithNormals(new pcl::PointCloud); if(_cloudViewer->isVisible() && _preferencesDialog->isCloudsShown(0)) { if(_preferencesDialog->isSubtractFiltering() && @@ -2337,7 +2335,7 @@ void MainWindow::createAndAddCloudToMap(int nodeId, const Transform & pose, int pcl::IndicesPtr beforeFiltering = indices; if( cloud->size() && _previousCloud.first>0 && - _previousCloud.second.first.get() != 0 && + _previousCloud.second.first.first.get() != 0 && _previousCloud.second.second.get() != 0 && _previousCloud.second.second->size() && _currentPosesMap.find(_previousCloud.first) != _currentPosesMap.end()) @@ -2345,20 +2343,53 @@ void MainWindow::createAndAddCloudToMap(int nodeId, const Transform & pose, int UTimer time; rtabmap::Transform t = pose.inverse() * _currentPosesMap.at(_previousCloud.first); - pcl::PointCloud::Ptr previousCloud = rtabmap::util3d::transformPointCloud(_previousCloud.second.first, t); //UWARN("saved new.pcd and old.pcd"); //pcl::io::savePCDFile("new.pcd", *cloud, *indices); //pcl::io::savePCDFile("old.pcd", *previousCloud, *_previousCloud.second.second); - indices = rtabmap::util3d::subtractFiltering( - cloud, - indices, - previousCloud, - _previousCloud.second.second, - _preferencesDialog->getSubtractFilteringRadius(), - _preferencesDialog->getSubtractFilteringAngle(), - _preferencesDialog->getSubtractFilteringMinPts()); + if(_preferencesDialog->getSubtractFilteringAngle() > 0.0f) + { + //normals required + if(_preferencesDialog->getNormalKSearch() > 0) + { + pcl::PointCloud::Ptr normals = util3d::computeNormals(cloud, indices, _preferencesDialog->getNormalKSearch()); + pcl::concatenateFields(*cloud, *normals, *cloudWithNormals); + } + else + { + UWARN("Cloud subtraction with angle filtering is activated but " + "cloud normal K search is 0. Subtraction is done with angle."); + } + } + + if(cloudWithNormals->size() && + _previousCloud.second.first.second.get() && + _previousCloud.second.first.second->size()) + { + pcl::PointCloud::Ptr previousCloud = rtabmap::util3d::transformPointCloud(_previousCloud.second.first.second, t); + indices = rtabmap::util3d::subtractFiltering( + cloudWithNormals, + indices, + previousCloud, + _previousCloud.second.second, + _preferencesDialog->getSubtractFilteringRadius(), + _preferencesDialog->getSubtractFilteringAngle(), + _preferencesDialog->getSubtractFilteringMinPts()); + } + else + { + pcl::PointCloud::Ptr previousCloud = rtabmap::util3d::transformPointCloud(_previousCloud.second.first.first, t); + indices = rtabmap::util3d::subtractFiltering( + cloud, + indices, + previousCloud, + _previousCloud.second.second, + _preferencesDialog->getSubtractFilteringRadius(), + _preferencesDialog->getSubtractFilteringMinPts()); + } + + UWARN("Time subtract filtering %d from %d -> %d (%fs)", (int)_previousCloud.second.second->size(), (int)beforeFiltering->size(), @@ -2367,19 +2398,17 @@ void MainWindow::createAndAddCloudToMap(int nodeId, const Transform & pose, int } // keep all indices for next subtraction _previousCloud.first = nodeId; - _previousCloud.second.first = cloud; + _previousCloud.second.first.first = cloud; + _previousCloud.second.first.second = cloudWithNormals; _previousCloud.second.second = beforeFiltering; } - // keep substracted clouds - _createdClouds.insert(std::make_pair(nodeId, std::make_pair(cloud, indices))); - if(indices->size()) { if(_preferencesDialog->isCloudMeshing() && cloud->isOrganized()) { // Fast organized mesh - pcl::PointCloud::Ptr output; + pcl::PointCloud::Ptr output; // we need to extract indices as pcl::OrganizedFastMesh doesn't take indices output = util3d::extractIndices(cloud, indices, false, true); Eigen::Vector3f viewpoint(0.0f,0.0f,0.0f); @@ -2404,13 +2433,17 @@ void MainWindow::createAndAddCloudToMap(int nodeId, const Transform & pose, int if(polygons.size()) { // remove unused vertices to save memory - pcl::PointCloud::Ptr outputFiltered(new pcl::PointCloud); + pcl::PointCloud::Ptr outputFiltered(new pcl::PointCloud); std::vector outputPolygons; util3d::filterNotUsedVerticesFromMesh(*output, polygons, *outputFiltered, outputPolygons); if(!_cloudViewer->addCloudMesh(cloudName, outputFiltered, outputPolygons, pose)) { UERROR("Adding mesh cloud %d to viewer failed!", nodeId); } + else + { + _createdClouds.insert(std::make_pair(nodeId, std::make_pair(output, indices))); + } } } else @@ -2421,18 +2454,47 @@ void MainWindow::createAndAddCloudToMap(int nodeId, const Transform & pose, int "dense (voxel filtering is used or multiple cameras are used). Disable " "online meshing in Preferences->3D Rendering to hide this warning."); } - pcl::PointCloud::Ptr output; - // don't keep organized to save memory - output = util3d::extractIndices(cloud, indices, false, false); + + if(_preferencesDialog->getNormalKSearch() > 0 && cloudWithNormals->size() == 0) + { + pcl::PointCloud::Ptr normals = util3d::computeNormals(cloud, indices, _preferencesDialog->getNormalKSearch()); + pcl::concatenateFields(*cloud, *normals, *cloudWithNormals); + } + QColor color = Qt::gray; if(mapId >= 0) { color = (Qt::GlobalColor)(mapId+3 % 12 + 7 ); } - if(!_cloudViewer->addCloud(cloudName, output, pose, color)) + pcl::PointCloud::Ptr output; + output = util3d::extractIndices(cloud, indices, false, true); + + if(cloudWithNormals->size()) { - UERROR("Adding cloud %d to viewer failed!", nodeId); + pcl::PointCloud::Ptr outputWithNormals; + outputWithNormals = util3d::extractIndices(cloudWithNormals, indices, false, false); + + if(!_cloudViewer->addCloud(cloudName, outputWithNormals, pose, color)) + { + UERROR("Adding cloud %d to viewer failed!", nodeId); + } + else + { + _createdClouds.insert(std::make_pair(nodeId, std::make_pair(output, indices))); + } + } + else + { + + if(!_cloudViewer->addCloud(cloudName, output, pose, color)) + { + UERROR("Adding cloud %d to viewer failed!", nodeId); + } + else + { + _createdClouds.insert(std::make_pair(nodeId, std::make_pair(output, indices))); + } } } } @@ -4782,7 +4844,8 @@ void MainWindow::clearTheCache() _cachedSignatures.clear(); _createdClouds.clear(); _previousCloud.first = 0; - _previousCloud.second.first.reset(); + _previousCloud.second.first.first.reset(); + _previousCloud.second.first.second.reset(); _previousCloud.second.second.reset(); _createdScans.clear(); _gridLocalMaps.clear(); diff --git a/guilib/src/PreferencesDialog.cpp b/guilib/src/PreferencesDialog.cpp index 74872617..54da6439 100644 --- a/guilib/src/PreferencesDialog.cpp +++ b/guilib/src/PreferencesDialog.cpp @@ -363,6 +363,7 @@ PreferencesDialog::PreferencesDialog(QWidget * parent) : connect(_ui->spinBox_subtractFilteringMinPts, SIGNAL(valueChanged(int)), this, SLOT(makeObsoleteCloudRenderingPanel())); connect(_ui->doubleSpinBox_subtractFilteringRadius, SIGNAL(valueChanged(double)), this, SLOT(makeObsoleteCloudRenderingPanel())); connect(_ui->doubleSpinBox_subtractFilteringAngle, SIGNAL(valueChanged(double)), this, SLOT(makeObsoleteCloudRenderingPanel())); + connect(_ui->spinBox_normalKSearch, SIGNAL(valueChanged(int)), this, SLOT(makeObsoleteCloudRenderingPanel())); connect(_ui->checkBox_map_shown, SIGNAL(clicked(bool)), this, SLOT(makeObsoleteCloudRenderingPanel())); connect(_ui->doubleSpinBox_map_resolution, SIGNAL(valueChanged(double)), this, SLOT(makeObsoleteCloudRenderingPanel())); @@ -1190,7 +1191,8 @@ void PreferencesDialog::resetSettings(QGroupBox * groupBox) _ui->doubleSpinBox_cloudFilterAngle->setValue(30); _ui->spinBox_subtractFilteringMinPts->setValue(5); _ui->doubleSpinBox_subtractFilteringRadius->setValue(0.02); - _ui->doubleSpinBox_subtractFilteringAngle->setValue(45.0); + _ui->doubleSpinBox_subtractFilteringAngle->setValue(0); + _ui->spinBox_normalKSearch->setValue(10); _ui->checkBox_map_shown->setChecked(false); _ui->doubleSpinBox_map_resolution->setValue(0.05); @@ -1545,6 +1547,7 @@ void PreferencesDialog::readGuiSettings(const QString & filePath) _ui->spinBox_subtractFilteringMinPts->setValue(settings.value("subtractFilteringMinPts", _ui->spinBox_subtractFilteringMinPts->value()).toInt()); _ui->doubleSpinBox_subtractFilteringRadius->setValue(settings.value("subtractFilteringRadius", _ui->doubleSpinBox_subtractFilteringRadius->value()).toDouble()); _ui->doubleSpinBox_subtractFilteringAngle->setValue(settings.value("subtractFilteringAngle", _ui->doubleSpinBox_subtractFilteringAngle->value()).toDouble()); + _ui->spinBox_normalKSearch->setValue(settings.value("normalKSearch", _ui->spinBox_normalKSearch->value()).toInt()); _ui->checkBox_map_shown->setChecked(settings.value("gridMapShown", _ui->checkBox_map_shown->isChecked()).toBool()); _ui->doubleSpinBox_map_resolution->setValue(settings.value("gridMapResolution", _ui->doubleSpinBox_map_resolution->value()).toDouble()); @@ -1947,6 +1950,7 @@ void PreferencesDialog::writeGuiSettings(const QString & filePath) const settings.setValue("subtractFilteringMinPts", _ui->spinBox_subtractFilteringMinPts->value()); settings.setValue("subtractFilteringRadius", _ui->doubleSpinBox_subtractFilteringRadius->value()); settings.setValue("subtractFilteringAngle", _ui->doubleSpinBox_subtractFilteringAngle->value()); + settings.setValue("normalKSearch", _ui->spinBox_normalKSearch->value()); settings.setValue("gridMapShown", _ui->checkBox_map_shown->isChecked()); settings.setValue("gridMapResolution", _ui->doubleSpinBox_map_resolution->value()); @@ -3727,6 +3731,10 @@ double PreferencesDialog::getSubtractFilteringAngle() const { return _ui->doubleSpinBox_subtractFilteringAngle->value()*M_PI/180.0; } +int PreferencesDialog::getNormalKSearch() const +{ + return _ui->spinBox_normalKSearch->value(); +} bool PreferencesDialog::getGridMapShown() const { return _ui->checkBox_map_shown->isChecked(); diff --git a/guilib/src/ProgressDialog.cpp b/guilib/src/ProgressDialog.cpp index 8a21ce2d..7ef551f8 100644 --- a/guilib/src/ProgressDialog.cpp +++ b/guilib/src/ProgressDialog.cpp @@ -109,7 +109,7 @@ void ProgressDialog::setValue(int value) } else if(_closeWhenDoneCheckBox->isChecked()) { - QTimer::singleShot(_delayedClosingTime*1000, this, SLOT(close())); + QTimer::singleShot(_delayedClosingTime*1000, this, SLOT(closeDialog())); } } } @@ -146,6 +146,14 @@ void ProgressDialog::resetProgress() _closeButton->setEnabled(false); } +void ProgressDialog::closeDialog() +{ + if(_closeWhenDoneCheckBox->isChecked()) + { + close(); + } +} + void ProgressDialog::closeEvent(QCloseEvent *event) { if(_progressBar->value() == _progressBar->maximum()) diff --git a/guilib/src/ui/DatabaseViewer.ui b/guilib/src/ui/DatabaseViewer.ui index aab22087..bb6a6321 100644 --- a/guilib/src/ui/DatabaseViewer.ui +++ b/guilib/src/ui/DatabaseViewer.ui @@ -52,7 +52,7 @@ 0 0 - 201 + 198 196 @@ -210,7 +210,7 @@ 0 0 - 201 + 197 196 @@ -1122,9 +1122,9 @@ 0 - -236 - 297 - 704 + -245 + 284 + 611 @@ -1328,81 +1328,6 @@ - - - - Flat obstacles detected - - - - - - - m - - - 2 - - - 0.000000000000000 - - - 999.000000000000000 - - - 1.000000000000000 - - - 0.000000000000000 - - - - - - - Max ground height - - - - - - - Max obstacles height - - - - - - - m - - - 2 - - - 0.000000000000000 - - - 999.000000000000000 - - - 1.000000000000000 - - - 0.000000000000000 - - - - - - - - - - true - - - @@ -1609,8 +1534,8 @@ 0 0 - 290 - 182 + 201 + 117 @@ -1709,8 +1634,8 @@ 0 0 - 290 - 182 + 175 + 191 diff --git a/guilib/src/ui/preferencesDialog.ui b/guilib/src/ui/preferencesDialog.ui index 58c727b2..4667aced 100644 --- a/guilib/src/ui/preferencesDialog.ui +++ b/guilib/src/ui/preferencesDialog.ui @@ -63,7 +63,7 @@ 0 - -269 + -847 686 2023 @@ -935,7 +935,7 @@ Show a yellow background when the number of odometry inliers goes under this thr QFrame::Raised - + @@ -945,7 +945,7 @@ Show a yellow background when the number of odometry inliers goes under this thr - + Show scans. @@ -958,7 +958,7 @@ Show a yellow background when the number of odometry inliers goes under this thr - + @@ -990,7 +990,7 @@ Show a yellow background when the number of odometry inliers goes under this thr - + @@ -1000,7 +1000,7 @@ Show a yellow background when the number of odometry inliers goes under this thr - + @@ -1074,7 +1074,7 @@ Show a yellow background when the number of odometry inliers goes under this thr - + 1 @@ -1087,7 +1087,7 @@ Show a yellow background when the number of odometry inliers goes under this thr - + @@ -1132,7 +1132,7 @@ Show a yellow background when the number of odometry inliers goes under this thr - + 3D cloud opacity. @@ -1145,7 +1145,7 @@ Show a yellow background when the number of odometry inliers goes under this thr - + 1 @@ -1158,7 +1158,7 @@ Show a yellow background when the number of odometry inliers goes under this thr - + 1 @@ -1168,7 +1168,7 @@ Show a yellow background when the number of odometry inliers goes under this thr - + Scan point size (1..64). @@ -1181,7 +1181,7 @@ Show a yellow background when the number of odometry inliers goes under this thr - + m @@ -1200,7 +1200,7 @@ Show a yellow background when the number of odometry inliers goes under this thr - + Scan voxel size. @@ -1213,7 +1213,7 @@ Show a yellow background when the number of odometry inliers goes under this thr - + 1 @@ -1223,7 +1223,7 @@ Show a yellow background when the number of odometry inliers goes under this thr - + Scan opacity. @@ -1259,7 +1259,7 @@ Show a yellow background when the number of odometry inliers goes under this thr - + @@ -1278,7 +1278,7 @@ Show a yellow background when the number of odometry inliers goes under this thr - + @@ -1288,7 +1288,7 @@ Show a yellow background when the number of odometry inliers goes under this thr - + Show graphs. @@ -1301,7 +1301,7 @@ Show a yellow background when the number of odometry inliers goes under this thr - + @@ -1311,7 +1311,7 @@ Show a yellow background when the number of odometry inliers goes under this thr - + @@ -1330,7 +1330,7 @@ Show a yellow background when the number of odometry inliers goes under this thr - + 1 @@ -1350,7 +1350,7 @@ Show a yellow background when the number of odometry inliers goes under this thr - + Show labels. @@ -1363,7 +1363,7 @@ Show a yellow background when the number of odometry inliers goes under this thr - + @@ -1373,7 +1373,7 @@ Show a yellow background when the number of odometry inliers goes under this thr - + m @@ -1392,7 +1392,7 @@ Show a yellow background when the number of odometry inliers goes under this thr - + Scan downsampling step size. @@ -1405,7 +1405,7 @@ Show a yellow background when the number of odometry inliers goes under this thr - + 1 @@ -1415,7 +1415,7 @@ Show a yellow background when the number of odometry inliers goes under this thr - + 3D cloud point size (1..64). @@ -1441,7 +1441,7 @@ Show a yellow background when the number of odometry inliers goes under this thr - + Show 3D features. @@ -1454,7 +1454,7 @@ Show a yellow background when the number of odometry inliers goes under this thr - + Feature point size. @@ -1467,7 +1467,7 @@ Show a yellow background when the number of odometry inliers goes under this thr - + 1 @@ -1477,7 +1477,7 @@ Show a yellow background when the number of odometry inliers goes under this thr - + 1 @@ -1631,6 +1631,32 @@ Show a yellow background when the number of odometry inliers goes under this thr + + + + 3D cloud normal K search. If not 0, normals will be computed and added to created cloud for visualization (keys 7, 8 and 9). + + + true + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse + + + + + + + 0 + + + 1000 + + + 10 + + +