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.

This commit is contained in:
matlabbe
2016-06-12 13:51:49 -04:00
parent 9f296c67b2
commit cb7c76889d
19 changed files with 342 additions and 287 deletions
+1 -1
View File
@@ -20,7 +20,7 @@ SET(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake_modules")
####################### #######################
SET(RTABMAP_MAJOR_VERSION 0) SET(RTABMAP_MAJOR_VERSION 0)
SET(RTABMAP_MINOR_VERSION 11) SET(RTABMAP_MINOR_VERSION 11)
SET(RTABMAP_PATCH_VERSION 7) SET(RTABMAP_PATCH_VERSION 8)
SET(RTABMAP_VERSION SET(RTABMAP_VERSION
${RTABMAP_MAJOR_VERSION}.${RTABMAP_MINOR_VERSION}.${RTABMAP_PATCH_VERSION}) ${RTABMAP_MAJOR_VERSION}.${RTABMAP_MINOR_VERSION}.${RTABMAP_PATCH_VERSION})
@@ -121,28 +121,29 @@ pcl::TextureMesh::Ptr RTABMAP_EXP createTextureMesh(
const std::map<int, Transform> & poses, const std::map<int, Transform> & poses,
const std::map<int, CameraModel> & cameraModels, const std::map<int, CameraModel> & cameraModels,
const std::map<int, cv::Mat> & images, const std::map<int, cv::Mat> & 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<pcl::PointNormal>::Ptr RTABMAP_EXP computeNormals( pcl::PointCloud<pcl::Normal>::Ptr RTABMAP_EXP computeNormals(
const pcl::PointCloud<pcl::PointXYZ>::Ptr & cloud, const pcl::PointCloud<pcl::PointXYZ>::Ptr & cloud,
int normalKSearch = 20); int normalKSearch = 20);
pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr RTABMAP_EXP computeNormals( pcl::PointCloud<pcl::Normal>::Ptr RTABMAP_EXP computeNormals(
const pcl::PointCloud<pcl::PointXYZRGB>::Ptr & cloud, const pcl::PointCloud<pcl::PointXYZRGB>::Ptr & cloud,
int normalKSearch = 20); int normalKSearch = 20);
pcl::PointCloud<pcl::PointNormal>::Ptr RTABMAP_EXP computeNormals( pcl::PointCloud<pcl::Normal>::Ptr RTABMAP_EXP computeNormals(
const pcl::PointCloud<pcl::PointXYZ>::Ptr & cloud, const pcl::PointCloud<pcl::PointXYZ>::Ptr & cloud,
const pcl::IndicesPtr & indices, const pcl::IndicesPtr & indices,
int normalKSearch = 20); int normalKSearch = 20);
pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr RTABMAP_EXP computeNormals( pcl::PointCloud<pcl::Normal>::Ptr RTABMAP_EXP computeNormals(
const pcl::PointCloud<pcl::PointXYZRGB>::Ptr & cloud, const pcl::PointCloud<pcl::PointXYZRGB>::Ptr & cloud,
const pcl::IndicesPtr & indices, const pcl::IndicesPtr & indices,
int normalKSearch = 20); int normalKSearch = 20);
pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr computeFastOrganizedNormals( pcl::PointCloud<pcl::Normal>::Ptr computeFastOrganizedNormals(
const pcl::PointCloud<pcl::PointXYZRGB>::Ptr & cloud, const pcl::PointCloud<pcl::PointXYZRGB>::Ptr & cloud,
float maxDepthChangeFactor = 0.02f, float maxDepthChangeFactor = 0.02f,
float normalSmoothingSize = 10.0f); float normalSmoothingSize = 10.0f);
pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr computeFastOrganizedNormals( pcl::PointCloud<pcl::Normal>::Ptr computeFastOrganizedNormals(
const pcl::PointCloud<pcl::PointXYZRGB>::Ptr & cloud, const pcl::PointCloud<pcl::PointXYZRGB>::Ptr & cloud,
const pcl::IndicesPtr & indices, const pcl::IndicesPtr & indices,
float maxDepthChangeFactor = 0.02f, float maxDepthChangeFactor = 0.02f,
+5 -1
View File
@@ -42,6 +42,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <rtabmap/core/util3d_filtering.h> #include <rtabmap/core/util3d_filtering.h>
#include <rtabmap/core/util3d_surface.h> #include <rtabmap/core/util3d_surface.h>
#include <pcl/common/io.h>
#include <iostream> #include <iostream>
#include <fstream> #include <fstream>
#include <cmath> #include <cmath>
@@ -661,7 +663,9 @@ SensorData CameraImages::captureImage()
} }
if(_scanNormalsK > 0 && cloud->size()) if(_scanNormalsK > 0 && cloud->size())
{ {
pcl::PointCloud<pcl::PointNormal>::Ptr cloudNormals = util3d::computeNormals(cloud, _scanNormalsK); pcl::PointCloud<pcl::Normal>::Ptr normals = util3d::computeNormals(cloud, _scanNormalsK);
pcl::PointCloud<pcl::PointNormal>::Ptr cloudNormals(new pcl::PointCloud<pcl::PointNormal>);
pcl::concatenateFields(*cloud, *normals, *cloudNormals);
scan = util3d::laserScanFromPointCloud(*cloudNormals); scan = util3d::laserScanFromPointCloud(*cloudNormals);
} }
else else
+4 -1
View File
@@ -193,7 +193,10 @@ void CameraThread::mainLoop()
cv::Mat scan; cv::Mat scan;
if(_scanNormalsK>0) if(_scanNormalsK>0)
{ {
scan = util3d::laserScanFromPointCloud(*util3d::computeNormals(cloud, _scanNormalsK)); pcl::PointCloud<pcl::Normal>::Ptr normals = util3d::computeNormals(cloud, _scanNormalsK);
pcl::PointCloud<pcl::PointNormal>::Ptr cloudNormals(new pcl::PointCloud<pcl::PointNormal>);
pcl::concatenateFields(*cloud, *normals, *cloudNormals);
scan = util3d::laserScanFromPointCloud(*cloudNormals);
} }
else else
{ {
+9 -2
View File
@@ -200,8 +200,15 @@ Transform RegistrationIcp::computeTransformationImpl(
pcl::PointCloud<pcl::PointXYZ>::Ptr fromCloudRegistered(new pcl::PointCloud<pcl::PointXYZ>()); pcl::PointCloud<pcl::PointXYZ>::Ptr fromCloudRegistered(new pcl::PointCloud<pcl::PointXYZ>());
if(_pointToPlane) // ICP Point To Plane, only in 3D if(_pointToPlane) // ICP Point To Plane, only in 3D
{ {
pcl::PointCloud<pcl::PointNormal>::Ptr fromCloudNormals = util3d::computeNormals(fromCloudFiltered, _pointToPlaneNormalNeighbors); pcl::PointCloud<pcl::Normal>::Ptr normals;
pcl::PointCloud<pcl::PointNormal>::Ptr toCloudNormals = util3d::computeNormals(toCloudFiltered, _pointToPlaneNormalNeighbors);
normals = util3d::computeNormals(fromCloudFiltered, _pointToPlaneNormalNeighbors);
pcl::PointCloud<pcl::PointNormal>::Ptr fromCloudNormals(new pcl::PointCloud<pcl::PointNormal>);
pcl::concatenateFields(*fromCloudFiltered, *normals, *fromCloudNormals);
normals = util3d::computeNormals(toCloudFiltered, _pointToPlaneNormalNeighbors);
pcl::PointCloud<pcl::PointNormal>::Ptr toCloudNormals(new pcl::PointCloud<pcl::PointNormal>);
pcl::concatenateFields(*toCloudFiltered, *normals, *toCloudNormals);
std::vector<int> indices; std::vector<int> indices;
toCloudNormals = util3d::removeNaNNormalsFromPointCloud(toCloudNormals); toCloudNormals = util3d::removeNaNNormalsFromPointCloud(toCloudNormals);
+3 -1
View File
@@ -1441,7 +1441,9 @@ cv::Mat loadScan(
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud = loadCloud(path, Transform::getIdentity(), downsampleStep, voxelSize); pcl::PointCloud<pcl::PointXYZ>::Ptr cloud = loadCloud(path, Transform::getIdentity(), downsampleStep, voxelSize);
if(normalsK > 0 && cloud->size()) if(normalsK > 0 && cloud->size())
{ {
pcl::PointCloud<pcl::PointNormal>::Ptr cloudNormals = util3d::computeNormals(cloud, normalsK); pcl::PointCloud<pcl::Normal>::Ptr normals = util3d::computeNormals(cloud, normalsK);
pcl::PointCloud<pcl::PointNormal>::Ptr cloudNormals(new pcl::PointCloud<pcl::PointNormal>);
pcl::concatenateFields(*cloud, *normals, *cloudNormals);
scan = util3d::laserScanFromPointCloud(*cloudNormals, transform); scan = util3d::laserScanFromPointCloud(*cloudNormals, transform);
} }
else else
+30 -40
View File
@@ -500,7 +500,8 @@ pcl::TextureMesh::Ptr createTextureMesh(
const std::map<int, Transform> & poses, const std::map<int, Transform> & poses,
const std::map<int, CameraModel> & cameraModels, const std::map<int, CameraModel> & cameraModels,
const std::map<int, cv::Mat> & images, const std::map<int, cv::Mat> & images,
const std::string & tmpDirectory) const std::string & tmpDirectory,
int kNormalSearch)
{ {
pcl::TextureMesh::Ptr textureMesh(new pcl::TextureMesh); pcl::TextureMesh::Ptr textureMesh(new pcl::TextureMesh);
textureMesh->cloud = mesh->cloud; textureMesh->cloud = mesh->cloud;
@@ -583,26 +584,28 @@ pcl::TextureMesh::Ptr createTextureMesh(
{ {
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZ>); pcl::PointCloud<pcl::PointXYZ>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZ>);
pcl::fromPCLPointCloud2(textureMesh->cloud, *cloud); pcl::fromPCLPointCloud2(textureMesh->cloud, *cloud);
pcl::PointCloud<pcl::PointNormal>::Ptr cloudWithNormals = computeNormals(cloud, 20); pcl::PointCloud<pcl::Normal>::Ptr normals = computeNormals(cloud, kNormalSearch);
// Concatenate the XYZ and normal fields
pcl::PointCloud<pcl::PointNormal>::Ptr cloudWithNormals;
pcl::concatenateFields (*cloud, *normals, *cloudWithNormals);
pcl::toPCLPointCloud2 (*cloudWithNormals, textureMesh->cloud); pcl::toPCLPointCloud2 (*cloudWithNormals, textureMesh->cloud);
} }
return textureMesh; return textureMesh;
} }
pcl::PointCloud<pcl::PointNormal>::Ptr computeNormals( pcl::PointCloud<pcl::Normal>::Ptr computeNormals(
const pcl::PointCloud<pcl::PointXYZ>::Ptr & cloud, const pcl::PointCloud<pcl::PointXYZ>::Ptr & cloud,
int normalKSearch) int normalKSearch)
{ {
pcl::IndicesPtr indices(new std::vector<int>); pcl::IndicesPtr indices(new std::vector<int>);
return computeNormals(cloud, indices, normalKSearch); return computeNormals(cloud, indices, normalKSearch);
} }
pcl::PointCloud<pcl::PointNormal>::Ptr computeNormals( pcl::PointCloud<pcl::Normal>::Ptr computeNormals(
const pcl::PointCloud<pcl::PointXYZ>::Ptr & cloud, const pcl::PointCloud<pcl::PointXYZ>::Ptr & cloud,
const pcl::IndicesPtr & indices, const pcl::IndicesPtr & indices,
int normalKSearch) int normalKSearch)
{ {
pcl::PointCloud<pcl::PointNormal>::Ptr cloud_with_normals(new pcl::PointCloud<pcl::PointNormal>);
pcl::search::KdTree<pcl::PointXYZ>::Ptr tree (new pcl::search::KdTree<pcl::PointXYZ>); pcl::search::KdTree<pcl::PointXYZ>::Ptr tree (new pcl::search::KdTree<pcl::PointXYZ>);
if(indices->size()) if(indices->size())
{ {
@@ -617,35 +620,30 @@ pcl::PointCloud<pcl::PointNormal>::Ptr computeNormals(
pcl::NormalEstimationOMP<pcl::PointXYZ, pcl::Normal> n; pcl::NormalEstimationOMP<pcl::PointXYZ, pcl::Normal> n;
pcl::PointCloud<pcl::Normal>::Ptr normals (new pcl::PointCloud<pcl::Normal>); pcl::PointCloud<pcl::Normal>::Ptr normals (new pcl::PointCloud<pcl::Normal>);
n.setInputCloud (cloud); n.setInputCloud (cloud);
if(indices->size()) // Commented: Keep the output normals size the same as the input cloud
{ //if(indices->size())
n.setIndices(indices); //{
} // n.setIndices(indices);
//}
n.setSearchMethod (tree); n.setSearchMethod (tree);
n.setKSearch (normalKSearch); n.setKSearch (normalKSearch);
n.compute (*normals); n.compute (*normals);
//* normals should not contain the point normals + surface curvatures
// Concatenate the XYZ and normal fields* return normals;
pcl::concatenateFields (*cloud, *normals, *cloud_with_normals);
//* cloud_with_normals = cloud + normals*/
return cloud_with_normals;
} }
pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr computeNormals( pcl::PointCloud<pcl::Normal>::Ptr computeNormals(
const pcl::PointCloud<pcl::PointXYZRGB>::Ptr & cloud, const pcl::PointCloud<pcl::PointXYZRGB>::Ptr & cloud,
int normalKSearch) int normalKSearch)
{ {
pcl::IndicesPtr indices(new std::vector<int>); pcl::IndicesPtr indices(new std::vector<int>);
return computeNormals(cloud, indices, normalKSearch); return computeNormals(cloud, indices, normalKSearch);
} }
pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr computeNormals( pcl::PointCloud<pcl::Normal>::Ptr computeNormals(
const pcl::PointCloud<pcl::PointXYZRGB>::Ptr & cloud, const pcl::PointCloud<pcl::PointXYZRGB>::Ptr & cloud,
const pcl::IndicesPtr & indices, const pcl::IndicesPtr & indices,
int normalKSearch) int normalKSearch)
{ {
pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr cloud_with_normals(new pcl::PointCloud<pcl::PointXYZRGBNormal>);
pcl::search::KdTree<pcl::PointXYZRGB>::Ptr tree (new pcl::search::KdTree<pcl::PointXYZRGB>); pcl::search::KdTree<pcl::PointXYZRGB>::Ptr tree (new pcl::search::KdTree<pcl::PointXYZRGB>);
if(indices->size()) if(indices->size())
{ {
@@ -660,23 +658,19 @@ pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr computeNormals(
pcl::NormalEstimationOMP<pcl::PointXYZRGB, pcl::Normal> n; pcl::NormalEstimationOMP<pcl::PointXYZRGB, pcl::Normal> n;
pcl::PointCloud<pcl::Normal>::Ptr normals (new pcl::PointCloud<pcl::Normal>); pcl::PointCloud<pcl::Normal>::Ptr normals (new pcl::PointCloud<pcl::Normal>);
n.setInputCloud (cloud); n.setInputCloud (cloud);
if(indices->size()) // Commented: Keep the output normals size the same as the input cloud
{ //if(indices->size())
n.setIndices(indices); //{
} // n.setIndices(indices);
//}
n.setSearchMethod (tree); n.setSearchMethod (tree);
n.setKSearch (normalKSearch); n.setKSearch (normalKSearch);
n.compute (*normals); n.compute (*normals);
//* normals should not contain the point normals + surface curvatures
// Concatenate the XYZ and normal fields* return normals;
pcl::concatenateFields (*cloud, *normals, *cloud_with_normals);
//* cloud_with_normals = cloud + normals*/
return cloud_with_normals;
} }
pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr computeFastOrganizedNormals( pcl::PointCloud<pcl::Normal>::Ptr computeFastOrganizedNormals(
const pcl::PointCloud<pcl::PointXYZRGB>::Ptr & cloud, const pcl::PointCloud<pcl::PointXYZRGB>::Ptr & cloud,
float maxDepthChangeFactor, float maxDepthChangeFactor,
float normalSmoothingSize) float normalSmoothingSize)
@@ -684,7 +678,7 @@ pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr computeFastOrganizedNormals(
pcl::IndicesPtr indices(new std::vector<int>); pcl::IndicesPtr indices(new std::vector<int>);
return computeFastOrganizedNormals(cloud, indices, maxDepthChangeFactor, normalSmoothingSize); return computeFastOrganizedNormals(cloud, indices, maxDepthChangeFactor, normalSmoothingSize);
} }
pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr computeFastOrganizedNormals( pcl::PointCloud<pcl::Normal>::Ptr computeFastOrganizedNormals(
const pcl::PointCloud<pcl::PointXYZRGB>::Ptr & cloud, const pcl::PointCloud<pcl::PointXYZRGB>::Ptr & cloud,
const pcl::IndicesPtr & indices, const pcl::IndicesPtr & indices,
float maxDepthChangeFactor, float maxDepthChangeFactor,
@@ -692,8 +686,6 @@ pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr computeFastOrganizedNormals(
{ {
UASSERT(cloud->isOrganized()); UASSERT(cloud->isOrganized());
pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr cloud_with_normals(new pcl::PointCloud<pcl::PointXYZRGBNormal>);
// Normal estimation // Normal estimation
pcl::PointCloud<pcl::Normal>::Ptr normals (new pcl::PointCloud<pcl::Normal>); pcl::PointCloud<pcl::Normal>::Ptr normals (new pcl::PointCloud<pcl::Normal>);
pcl::IntegralImageNormalEstimation<pcl::PointXYZRGB, pcl::Normal> ne; pcl::IntegralImageNormalEstimation<pcl::PointXYZRGB, pcl::Normal> ne;
@@ -701,16 +693,14 @@ pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr computeFastOrganizedNormals(
ne.setMaxDepthChangeFactor(maxDepthChangeFactor); ne.setMaxDepthChangeFactor(maxDepthChangeFactor);
ne.setNormalSmoothingSize(normalSmoothingSize); ne.setNormalSmoothingSize(normalSmoothingSize);
ne.setInputCloud(cloud); ne.setInputCloud(cloud);
if(indices->size()) // Commented: Keep the output normals size the same as the input cloud
{ //if(indices->size())
ne.setIndices(indices); //{
} // ne.setIndices(indices);
//}
ne.compute(*normals); ne.compute(*normals);
// Concatenate the XYZ and normal fields return normals;
pcl::concatenateFields (*cloud, *normals, *cloud_with_normals);
return cloud_with_normals;
} }
pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr mls( pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr mls(
+2 -2
View File
@@ -286,8 +286,8 @@ private:
std::multimap<int, Link> _currentLinksMap; // <nodeFromId, link> std::multimap<int, Link> _currentLinksMap; // <nodeFromId, link>
std::map<int, int> _currentMapIds; // <nodeId, mapId> std::map<int, int> _currentMapIds; // <nodeId, mapId>
std::map<int, std::string> _currentLabels; // <nodeId, label> std::map<int, std::string> _currentLabels; // <nodeId, label>
std::map<int, std::pair<pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr, pcl::IndicesPtr> > _createdClouds; std::map<int, std::pair<pcl::PointCloud<pcl::PointXYZRGB>::Ptr, pcl::IndicesPtr> > _createdClouds;
std::pair<int, std::pair<pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr, pcl::IndicesPtr> > _previousCloud; // used for subtraction std::pair<int, std::pair<std::pair<pcl::PointCloud<pcl::PointXYZRGB>::Ptr, pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr>, pcl::IndicesPtr> > _previousCloud; // used for subtraction
std::map<int, cv::Mat> _createdScans; std::map<int, cv::Mat> _createdScans;
std::map<int, std::pair<cv::Mat, cv::Mat> > _projectionLocalMaps; // <ground, obstacles> std::map<int, std::pair<cv::Mat, cv::Mat> > _projectionLocalMaps; // <ground, obstacles>
@@ -173,6 +173,7 @@ public:
int getSubtractFilteringMinPts() const; int getSubtractFilteringMinPts() const;
double getSubtractFilteringRadius() const; double getSubtractFilteringRadius() const;
double getSubtractFilteringAngle() const; double getSubtractFilteringAngle() const;
int getNormalKSearch() const;
bool getGridMapShown() const; bool getGridMapShown() const;
double getGridMapResolution() const;; double getGridMapResolution() const;;
@@ -63,6 +63,9 @@ public slots:
void clear(); void clear();
void resetProgress(); void resetProgress();
private slots:
void closeDialog();
private: private:
QLabel * _text; QLabel * _text;
QTextEdit * _detailedText; QTextEdit * _detailedText;
+8 -3
View File
@@ -1629,7 +1629,9 @@ void DatabaseViewer::view3DLaserScans()
} }
int normalK = uStr2Int(ui_->parameters_toolbox->getParameters().at(Parameters::kIcpPointToPlaneNormalNeighbors())); int normalK = uStr2Int(ui_->parameters_toolbox->getParameters().at(Parameters::kIcpPointToPlaneNormalNeighbors()));
pcl::PointCloud<pcl::PointNormal>::Ptr cloudNormals = util3d::computeNormals(cloud, normalK); pcl::PointCloud<pcl::Normal>::Ptr normals = util3d::computeNormals(cloud, normalK);
pcl::PointCloud<pcl::PointNormal>::Ptr cloudNormals(new pcl::PointCloud<pcl::PointNormal>);
pcl::concatenateFields(*cloud, *normals, *cloudNormals);
viewer->addCloud(uFormat("cloud%d", iter->first), cloudNormals, pose, color); 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) iter->second.type() == rtabmap::Link::kNeighborMerged)
{ {
Eigen::Vector3f vA, vB; Eigen::Vector3f vA, vB;
poseA.getTranslation(vA[0], vA[1], vA[2]); float x,y,z;
poseB.getTranslation(vB[0], vB[1], vB[2]); 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(); length += (vB - vA).norm();
} }
} }
+24 -14
View File
@@ -243,7 +243,7 @@ void ExportCloudsDialog::loadSettings(QSettings & settings, const QString & grou
void ExportCloudsDialog::restoreDefaults() void ExportCloudsDialog::restoreDefaults()
{ {
_ui->checkBox_binary->setChecked(true); _ui->checkBox_binary->setChecked(true);
_ui->spinBox_normalKSearch->setValue(6); _ui->spinBox_normalKSearch->setValue(10);
_ui->groupBox_regenerate->setChecked(false); _ui->groupBox_regenerate->setChecked(false);
_ui->spinBox_decimation->setValue(1); _ui->spinBox_decimation->setValue(1);
@@ -259,7 +259,7 @@ void ExportCloudsDialog::restoreDefaults()
_ui->groupBox_subtraction->setChecked(false); _ui->groupBox_subtraction->setChecked(false);
_ui->doubleSpinBox_subtractPointFilteringRadius->setValue(0.02); _ui->doubleSpinBox_subtractPointFilteringRadius->setValue(0.02);
_ui->doubleSpinBox_subtractPointFilteringAngle->setValue(45.0); _ui->doubleSpinBox_subtractPointFilteringAngle->setValue(0);
_ui->spinBox_subtractFilteringMinPts->setValue(5); _ui->spinBox_subtractFilteringMinPts->setValue(5);
_ui->groupBox_mls->setChecked(false); _ui->groupBox_mls->setChecked(false);
@@ -336,7 +336,7 @@ void ExportCloudsDialog::exportClouds(
const std::map<int, Transform> & poses, const std::map<int, Transform> & poses,
const std::map<int, int> & mapIds, const std::map<int, int> & mapIds,
const QMap<int, Signature> & cachedSignatures, const QMap<int, Signature> & cachedSignatures,
const std::map<int, std::pair<pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr, pcl::IndicesPtr> > & createdClouds, const std::map<int, std::pair<pcl::PointCloud<pcl::PointXYZRGB>::Ptr, pcl::IndicesPtr> > & createdClouds,
const QString & workingDirectory, const QString & workingDirectory,
const ParametersMap & parameters) const ParametersMap & parameters)
{ {
@@ -388,7 +388,7 @@ void ExportCloudsDialog::viewClouds(
const std::map<int, Transform> & poses, const std::map<int, Transform> & poses,
const std::map<int, int> & mapIds, const std::map<int, int> & mapIds,
const QMap<int, Signature> & cachedSignatures, const QMap<int, Signature> & cachedSignatures,
const std::map<int, std::pair<pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr, pcl::IndicesPtr> > & createdClouds, const std::map<int, std::pair<pcl::PointCloud<pcl::PointXYZRGB>::Ptr, pcl::IndicesPtr> > & createdClouds,
const QString & workingDirectory, const QString & workingDirectory,
const ParametersMap & parameters) const ParametersMap & parameters)
{ {
@@ -519,7 +519,7 @@ bool ExportCloudsDialog::getExportedClouds(
const std::map<int, Transform> & poses, const std::map<int, Transform> & poses,
const std::map<int, int> & mapIds, const std::map<int, int> & mapIds,
const QMap<int, Signature> & cachedSignatures, const QMap<int, Signature> & cachedSignatures,
const std::map<int, std::pair<pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr, pcl::IndicesPtr> > & createdClouds, const std::map<int, std::pair<pcl::PointCloud<pcl::PointXYZRGB>::Ptr, pcl::IndicesPtr> > & createdClouds,
const QString & workingDirectory, const QString & workingDirectory,
const ParametersMap & parameters, const ParametersMap & parameters,
std::map<int, pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr> & cloudsWithNormals, std::map<int, pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr> & cloudsWithNormals,
@@ -701,7 +701,8 @@ bool ExportCloudsDialog::getExportedClouds(
iter!= cloudsWithNormals.end(); iter!= cloudsWithNormals.end();
++iter) ++iter)
{ {
UASSERT(iter->second->isOrganized()); if(iter->second->isOrganized())
{
if(iter->second->size()) if(iter->second->size())
{ {
Eigen::Vector3f viewpoint(0.0f,0.0f,0.0f); Eigen::Vector3f viewpoint(0.0f,0.0f,0.0f);
@@ -777,6 +778,11 @@ bool ExportCloudsDialog::getExportedClouds(
{ {
_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 (no valid points) (%2/%3).").arg(iter->first).arg(++i).arg(clouds.size()));
} }
}
else
{
_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(); _progressDialog->incrementStep();
QApplication::processEvents(); QApplication::processEvents();
@@ -1012,7 +1018,7 @@ bool ExportCloudsDialog::getExportedClouds(
std::map<int, std::pair<pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr, pcl::IndicesPtr> > ExportCloudsDialog::getClouds( std::map<int, std::pair<pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr, pcl::IndicesPtr> > ExportCloudsDialog::getClouds(
const std::map<int, Transform> & poses, const std::map<int, Transform> & poses,
const QMap<int, Signature> & cachedSignatures, const QMap<int, Signature> & cachedSignatures,
const std::map<int, std::pair<pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr, pcl::IndicesPtr> > & createdClouds, const std::map<int, std::pair<pcl::PointCloud<pcl::PointXYZRGB>::Ptr, pcl::IndicesPtr> > & createdClouds,
const ParametersMap & parameters) const const ParametersMap & parameters) const
{ {
std::map<int, std::pair<pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr, pcl::IndicesPtr> > clouds; std::map<int, std::pair<pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr, pcl::IndicesPtr> > clouds;
@@ -1059,9 +1065,8 @@ std::map<int, std::pair<pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr, pcl::Indic
} }
} }
cloud = util3d::computeNormals( pcl::PointCloud<pcl::Normal>::Ptr normals = util3d::computeNormals(cloudWithoutNormals, indices, _ui->spinBox_normalKSearch->value());
cloudWithoutNormals, pcl::concatenateFields(*cloudWithoutNormals, *normals, *cloud);
_ui->spinBox_normalKSearch->value());
if(_ui->groupBox_subtraction->isChecked() && if(_ui->groupBox_subtraction->isChecked() &&
_ui->doubleSpinBox_subtractPointFilteringRadius->value() > 0.0) _ui->doubleSpinBox_subtractPointFilteringRadius->value() > 0.0)
@@ -1114,24 +1119,29 @@ std::map<int, std::pair<pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr, pcl::Indic
} }
else if(uContains(createdClouds, iter->first)) else if(uContains(createdClouds, iter->first))
{ {
pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloudWithoutNormals;
if(!_ui->groupBox_meshing->isChecked() && if(!_ui->groupBox_meshing->isChecked() &&
_ui->doubleSpinBox_voxelSize_assembled->value() > 0.0) _ui->doubleSpinBox_voxelSize_assembled->value() > 0.0)
{ {
cloud = util3d::voxelize( cloudWithoutNormals = util3d::voxelize(
createdClouds.at(iter->first).first, createdClouds.at(iter->first).first,
createdClouds.at(iter->first).second,
_ui->doubleSpinBox_voxelSize_assembled->value()); _ui->doubleSpinBox_voxelSize_assembled->value());
//generate indices for all points (they are all valid) //generate indices for all points (they are all valid)
indices->resize(cloud->size()); indices->resize(cloudWithoutNormals->size());
for(unsigned int i=0; i<cloud->size(); ++i) for(unsigned int i=0; i<cloudWithoutNormals->size(); ++i)
{ {
indices->at(i) = i; indices->at(i) = i;
} }
} }
else else
{ {
cloud = createdClouds.at(iter->first).first; cloudWithoutNormals = createdClouds.at(iter->first).first;
indices = createdClouds.at(iter->first).second; indices = createdClouds.at(iter->first).second;
} }
pcl::PointCloud<pcl::Normal>::Ptr normals = util3d::computeNormals(cloudWithoutNormals, indices, _ui->spinBox_normalKSearch->value());
pcl::concatenateFields(*cloudWithoutNormals, *normals, *cloud);
} }
if(indices->size()) if(indices->size())
+4 -4
View File
@@ -63,7 +63,7 @@ public:
const std::map<int, Transform> & poses, const std::map<int, Transform> & poses,
const std::map<int, int> & mapIds, const std::map<int, int> & mapIds,
const QMap<int, Signature> & cachedSignatures, const QMap<int, Signature> & cachedSignatures,
const std::map<int, std::pair<pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr, pcl::IndicesPtr> > & createdClouds, const std::map<int, std::pair<pcl::PointCloud<pcl::PointXYZRGB>::Ptr, pcl::IndicesPtr> > & createdClouds,
const QString & workingDirectory, const QString & workingDirectory,
const ParametersMap & parameters); const ParametersMap & parameters);
@@ -71,7 +71,7 @@ public:
const std::map<int, Transform> & poses, const std::map<int, Transform> & poses,
const std::map<int, int> & mapIds, const std::map<int, int> & mapIds,
const QMap<int, Signature> & cachedSignatures, const QMap<int, Signature> & cachedSignatures,
const std::map<int, std::pair<pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr, pcl::IndicesPtr> > & createdClouds, const std::map<int, std::pair<pcl::PointCloud<pcl::PointXYZRGB>::Ptr, pcl::IndicesPtr> > & createdClouds,
const QString & workingDirectory, const QString & workingDirectory,
const ParametersMap & parameters); const ParametersMap & parameters);
@@ -89,13 +89,13 @@ private:
std::map<int, std::pair<pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr, pcl::IndicesPtr> > getClouds( std::map<int, std::pair<pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr, pcl::IndicesPtr> > getClouds(
const std::map<int, Transform> & poses, const std::map<int, Transform> & poses,
const QMap<int, Signature> & cachedSignatures, const QMap<int, Signature> & cachedSignatures,
const std::map<int, std::pair<pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr, pcl::IndicesPtr> > & createdClouds, const std::map<int, std::pair<pcl::PointCloud<pcl::PointXYZRGB>::Ptr, pcl::IndicesPtr> > & createdClouds,
const ParametersMap & parameters) const; const ParametersMap & parameters) const;
bool getExportedClouds( bool getExportedClouds(
const std::map<int, Transform> & poses, const std::map<int, Transform> & poses,
const std::map<int, int> & mapIds, const std::map<int, int> & mapIds,
const QMap<int, Signature> & cachedSignatures, const QMap<int, Signature> & cachedSignatures,
const std::map<int, std::pair<pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr, pcl::IndicesPtr> > & createdClouds, const std::map<int, std::pair<pcl::PointCloud<pcl::PointXYZRGB>::Ptr, pcl::IndicesPtr> > & createdClouds,
const QString & workingDirectory, const QString & workingDirectory,
const ParametersMap & parameters, const ParametersMap & parameters,
std::map<int, pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr> & clouds, std::map<int, pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr> & clouds,
+5 -6
View File
@@ -336,9 +336,9 @@ bool ExportScansDialog::getExportedScans(
pcl::PointCloud<pcl::PointXYZ>::Ptr cloudXYZ(new pcl::PointCloud<pcl::PointXYZ>); pcl::PointCloud<pcl::PointXYZ>::Ptr cloudXYZ(new pcl::PointCloud<pcl::PointXYZ>);
pcl::copyPointCloud(*assembledCloud, *cloudXYZ); pcl::copyPointCloud(*assembledCloud, *cloudXYZ);
assembledCloud = util3d::computeNormals(
cloudXYZ, pcl::PointCloud<pcl::Normal>::Ptr normals = util3d::computeNormals(cloudXYZ, _ui->spinBox_normalKSearch->value());
_ui->spinBox_normalKSearch->value()); pcl::concatenateFields(*cloudXYZ, *normals, *assembledCloud);
_progressDialog->appendText(tr("Update %1 normals with %2 camera views...") _progressDialog->appendText(tr("Update %1 normals with %2 camera views...")
.arg(assembledCloud->size()).arg(poses.size())); .arg(assembledCloud->size()).arg(poses.size()));
@@ -433,9 +433,8 @@ std::map<int, pcl::PointCloud<pcl::PointNormal>::Ptr> ExportScansDialog::getScan
if(!_ui->checkBox_assemble->isChecked() && _ui->spinBox_normalKSearch->value() > 0) if(!_ui->checkBox_assemble->isChecked() && _ui->spinBox_normalKSearch->value() > 0)
{ {
cloud = util3d::computeNormals( pcl::PointCloud<pcl::Normal>::Ptr normals = util3d::computeNormals(cloudXYZ, _ui->spinBox_normalKSearch->value());
cloudXYZ, pcl::concatenateFields(*cloudXYZ, *normals, *cloud);
_ui->spinBox_normalKSearch->value());
} }
else else
{ {
+86 -23
View File
@@ -2236,7 +2236,7 @@ void MainWindow::createAndAddCloudToMap(int nodeId, const Transform & pose, int
SensorData data = iter->sensorData(); SensorData data = iter->sensorData();
data.uncompressData(&image, &depth, 0); data.uncompressData(&image, &depth, 0);
pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloudWithoutNormals; pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud;
pcl::IndicesPtr indices(new std::vector<int>); pcl::IndicesPtr indices(new std::vector<int>);
UASSERT(nodeId == data.id()); UASSERT(nodeId == data.id());
@@ -2252,7 +2252,7 @@ void MainWindow::createAndAddCloudToMap(int nodeId, const Transform & pose, int
} }
// Create organized cloud // Create organized cloud
cloudWithoutNormals = util3d::cloudRGBFromSensorData(data, cloud = util3d::cloudRGBFromSensorData(data,
_preferencesDialog->getCloudDecimation(0), _preferencesDialog->getCloudDecimation(0),
_preferencesDialog->getCloudMaxDepth(0), _preferencesDialog->getCloudMaxDepth(0),
_preferencesDialog->getCloudMinDepth(0), _preferencesDialog->getCloudMinDepth(0),
@@ -2262,10 +2262,10 @@ void MainWindow::createAndAddCloudToMap(int nodeId, const Transform & pose, int
// filtering pipeline // filtering pipeline
if(indices->size() && _preferencesDialog->getMapVoxel() > 0.0) 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) //generate indices for all points (they are all valid)
indices->resize(cloudWithoutNormals->size()); indices->resize(cloud->size());
for(unsigned int i=0; i<cloudWithoutNormals->size(); ++i) for(unsigned int i=0; i<cloud->size(); ++i)
{ {
indices->at(i) = i; indices->at(i) = i;
} }
@@ -2277,22 +2277,19 @@ void MainWindow::createAndAddCloudToMap(int nodeId, const Transform & pose, int
_preferencesDialog->getMapNoiseMinNeighbors() > 0) _preferencesDialog->getMapNoiseMinNeighbors() > 0)
{ {
indices = rtabmap::util3d::radiusFiltering( indices = rtabmap::util3d::radiusFiltering(
cloudWithoutNormals, cloud,
indices, indices,
_preferencesDialog->getMapNoiseRadius(), _preferencesDialog->getMapNoiseRadius(),
_preferencesDialog->getMapNoiseMinNeighbors()); _preferencesDialog->getMapNoiseMinNeighbors());
} }
//compute normals
pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr cloud = util3d::computeNormals(cloudWithoutNormals, 10);
if(indices->size() && if(indices->size() &&
_preferencesDialog->isGridMapFrom3DCloud() && _preferencesDialog->isGridMapFrom3DCloud() &&
_projectionLocalMaps.find(nodeId) == _projectionLocalMaps.end()) _projectionLocalMaps.find(nodeId) == _projectionLocalMaps.end())
{ {
UTimer timer; UTimer timer;
cv::Mat ground, obstacles; cv::Mat ground, obstacles;
pcl::PointCloud<pcl::PointXYZRGB>::Ptr voxelCloud = cloudWithoutNormals; pcl::PointCloud<pcl::PointXYZRGB>::Ptr voxelCloud = cloud;
// voxelize to grid cell size // voxelize to grid cell size
if(_preferencesDialog->getMapVoxel() < _preferencesDialog->getGridMapResolution()) 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()); UDEBUG("time gridMapFrom3DCloud = %f s", timer.ticks());
} }
pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr cloudWithNormals(new pcl::PointCloud<pcl::PointXYZRGBNormal>);
if(_cloudViewer->isVisible() && _preferencesDialog->isCloudsShown(0)) if(_cloudViewer->isVisible() && _preferencesDialog->isCloudsShown(0))
{ {
if(_preferencesDialog->isSubtractFiltering() && if(_preferencesDialog->isSubtractFiltering() &&
@@ -2337,7 +2335,7 @@ void MainWindow::createAndAddCloudToMap(int nodeId, const Transform & pose, int
pcl::IndicesPtr beforeFiltering = indices; pcl::IndicesPtr beforeFiltering = indices;
if( cloud->size() && if( cloud->size() &&
_previousCloud.first>0 && _previousCloud.first>0 &&
_previousCloud.second.first.get() != 0 && _previousCloud.second.first.first.get() != 0 &&
_previousCloud.second.second.get() != 0 && _previousCloud.second.second.get() != 0 &&
_previousCloud.second.second->size() && _previousCloud.second.second->size() &&
_currentPosesMap.find(_previousCloud.first) != _currentPosesMap.end()) _currentPosesMap.find(_previousCloud.first) != _currentPosesMap.end())
@@ -2345,20 +2343,53 @@ void MainWindow::createAndAddCloudToMap(int nodeId, const Transform & pose, int
UTimer time; UTimer time;
rtabmap::Transform t = pose.inverse() * _currentPosesMap.at(_previousCloud.first); rtabmap::Transform t = pose.inverse() * _currentPosesMap.at(_previousCloud.first);
pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr previousCloud = rtabmap::util3d::transformPointCloud(_previousCloud.second.first, t);
//UWARN("saved new.pcd and old.pcd"); //UWARN("saved new.pcd and old.pcd");
//pcl::io::savePCDFile("new.pcd", *cloud, *indices); //pcl::io::savePCDFile("new.pcd", *cloud, *indices);
//pcl::io::savePCDFile("old.pcd", *previousCloud, *_previousCloud.second.second); //pcl::io::savePCDFile("old.pcd", *previousCloud, *_previousCloud.second.second);
if(_preferencesDialog->getSubtractFilteringAngle() > 0.0f)
{
//normals required
if(_preferencesDialog->getNormalKSearch() > 0)
{
pcl::PointCloud<pcl::Normal>::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<pcl::PointXYZRGBNormal>::Ptr previousCloud = rtabmap::util3d::transformPointCloud(_previousCloud.second.first.second, t);
indices = rtabmap::util3d::subtractFiltering( indices = rtabmap::util3d::subtractFiltering(
cloud, cloudWithNormals,
indices, indices,
previousCloud, previousCloud,
_previousCloud.second.second, _previousCloud.second.second,
_preferencesDialog->getSubtractFilteringRadius(), _preferencesDialog->getSubtractFilteringRadius(),
_preferencesDialog->getSubtractFilteringAngle(), _preferencesDialog->getSubtractFilteringAngle(),
_preferencesDialog->getSubtractFilteringMinPts()); _preferencesDialog->getSubtractFilteringMinPts());
}
else
{
pcl::PointCloud<pcl::PointXYZRGB>::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)", UWARN("Time subtract filtering %d from %d -> %d (%fs)",
(int)_previousCloud.second.second->size(), (int)_previousCloud.second.second->size(),
(int)beforeFiltering->size(), (int)beforeFiltering->size(),
@@ -2367,19 +2398,17 @@ void MainWindow::createAndAddCloudToMap(int nodeId, const Transform & pose, int
} }
// keep all indices for next subtraction // keep all indices for next subtraction
_previousCloud.first = nodeId; _previousCloud.first = nodeId;
_previousCloud.second.first = cloud; _previousCloud.second.first.first = cloud;
_previousCloud.second.first.second = cloudWithNormals;
_previousCloud.second.second = beforeFiltering; _previousCloud.second.second = beforeFiltering;
} }
// keep substracted clouds
_createdClouds.insert(std::make_pair(nodeId, std::make_pair(cloud, indices)));
if(indices->size()) if(indices->size())
{ {
if(_preferencesDialog->isCloudMeshing() && cloud->isOrganized()) if(_preferencesDialog->isCloudMeshing() && cloud->isOrganized())
{ {
// Fast organized mesh // Fast organized mesh
pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr output; pcl::PointCloud<pcl::PointXYZRGB>::Ptr output;
// we need to extract indices as pcl::OrganizedFastMesh doesn't take indices // we need to extract indices as pcl::OrganizedFastMesh doesn't take indices
output = util3d::extractIndices(cloud, indices, false, true); output = util3d::extractIndices(cloud, indices, false, true);
Eigen::Vector3f viewpoint(0.0f,0.0f,0.0f); 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()) if(polygons.size())
{ {
// remove unused vertices to save memory // remove unused vertices to save memory
pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr outputFiltered(new pcl::PointCloud<pcl::PointXYZRGBNormal>); pcl::PointCloud<pcl::PointXYZRGB>::Ptr outputFiltered(new pcl::PointCloud<pcl::PointXYZRGB>);
std::vector<pcl::Vertices> outputPolygons; std::vector<pcl::Vertices> outputPolygons;
util3d::filterNotUsedVerticesFromMesh(*output, polygons, *outputFiltered, outputPolygons); util3d::filterNotUsedVerticesFromMesh(*output, polygons, *outputFiltered, outputPolygons);
if(!_cloudViewer->addCloudMesh(cloudName, outputFiltered, outputPolygons, pose)) if(!_cloudViewer->addCloudMesh(cloudName, outputFiltered, outputPolygons, pose))
{ {
UERROR("Adding mesh cloud %d to viewer failed!", nodeId); UERROR("Adding mesh cloud %d to viewer failed!", nodeId);
} }
else
{
_createdClouds.insert(std::make_pair(nodeId, std::make_pair(output, indices)));
}
} }
} }
else else
@@ -2421,19 +2454,48 @@ void MainWindow::createAndAddCloudToMap(int nodeId, const Transform & pose, int
"dense (voxel filtering is used or multiple cameras are used). Disable " "dense (voxel filtering is used or multiple cameras are used). Disable "
"online meshing in Preferences->3D Rendering to hide this warning."); "online meshing in Preferences->3D Rendering to hide this warning.");
} }
pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr output;
// don't keep organized to save memory if(_preferencesDialog->getNormalKSearch() > 0 && cloudWithNormals->size() == 0)
output = util3d::extractIndices(cloud, indices, false, false); {
pcl::PointCloud<pcl::Normal>::Ptr normals = util3d::computeNormals(cloud, indices, _preferencesDialog->getNormalKSearch());
pcl::concatenateFields(*cloud, *normals, *cloudWithNormals);
}
QColor color = Qt::gray; QColor color = Qt::gray;
if(mapId >= 0) if(mapId >= 0)
{ {
color = (Qt::GlobalColor)(mapId+3 % 12 + 7 ); color = (Qt::GlobalColor)(mapId+3 % 12 + 7 );
} }
pcl::PointCloud<pcl::PointXYZRGB>::Ptr output;
output = util3d::extractIndices(cloud, indices, false, true);
if(cloudWithNormals->size())
{
pcl::PointCloud<pcl::PointXYZRGBNormal>::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)) if(!_cloudViewer->addCloud(cloudName, output, pose, color))
{ {
UERROR("Adding cloud %d to viewer failed!", nodeId); UERROR("Adding cloud %d to viewer failed!", nodeId);
} }
else
{
_createdClouds.insert(std::make_pair(nodeId, std::make_pair(output, indices)));
}
}
} }
} }
_cloudViewer->setCloudOpacity(cloudName, _preferencesDialog->getCloudOpacity(0)); _cloudViewer->setCloudOpacity(cloudName, _preferencesDialog->getCloudOpacity(0));
@@ -4782,7 +4844,8 @@ void MainWindow::clearTheCache()
_cachedSignatures.clear(); _cachedSignatures.clear();
_createdClouds.clear(); _createdClouds.clear();
_previousCloud.first = 0; _previousCloud.first = 0;
_previousCloud.second.first.reset(); _previousCloud.second.first.first.reset();
_previousCloud.second.first.second.reset();
_previousCloud.second.second.reset(); _previousCloud.second.second.reset();
_createdScans.clear(); _createdScans.clear();
_gridLocalMaps.clear(); _gridLocalMaps.clear();
+9 -1
View File
@@ -363,6 +363,7 @@ PreferencesDialog::PreferencesDialog(QWidget * parent) :
connect(_ui->spinBox_subtractFilteringMinPts, SIGNAL(valueChanged(int)), this, SLOT(makeObsoleteCloudRenderingPanel())); connect(_ui->spinBox_subtractFilteringMinPts, SIGNAL(valueChanged(int)), this, SLOT(makeObsoleteCloudRenderingPanel()));
connect(_ui->doubleSpinBox_subtractFilteringRadius, SIGNAL(valueChanged(double)), 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->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->checkBox_map_shown, SIGNAL(clicked(bool)), this, SLOT(makeObsoleteCloudRenderingPanel()));
connect(_ui->doubleSpinBox_map_resolution, SIGNAL(valueChanged(double)), 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->doubleSpinBox_cloudFilterAngle->setValue(30);
_ui->spinBox_subtractFilteringMinPts->setValue(5); _ui->spinBox_subtractFilteringMinPts->setValue(5);
_ui->doubleSpinBox_subtractFilteringRadius->setValue(0.02); _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->checkBox_map_shown->setChecked(false);
_ui->doubleSpinBox_map_resolution->setValue(0.05); _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->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_subtractFilteringRadius->setValue(settings.value("subtractFilteringRadius", _ui->doubleSpinBox_subtractFilteringRadius->value()).toDouble());
_ui->doubleSpinBox_subtractFilteringAngle->setValue(settings.value("subtractFilteringAngle", _ui->doubleSpinBox_subtractFilteringAngle->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->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()); _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("subtractFilteringMinPts", _ui->spinBox_subtractFilteringMinPts->value());
settings.setValue("subtractFilteringRadius", _ui->doubleSpinBox_subtractFilteringRadius->value()); settings.setValue("subtractFilteringRadius", _ui->doubleSpinBox_subtractFilteringRadius->value());
settings.setValue("subtractFilteringAngle", _ui->doubleSpinBox_subtractFilteringAngle->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("gridMapShown", _ui->checkBox_map_shown->isChecked());
settings.setValue("gridMapResolution", _ui->doubleSpinBox_map_resolution->value()); 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; return _ui->doubleSpinBox_subtractFilteringAngle->value()*M_PI/180.0;
} }
int PreferencesDialog::getNormalKSearch() const
{
return _ui->spinBox_normalKSearch->value();
}
bool PreferencesDialog::getGridMapShown() const bool PreferencesDialog::getGridMapShown() const
{ {
return _ui->checkBox_map_shown->isChecked(); return _ui->checkBox_map_shown->isChecked();
+9 -1
View File
@@ -109,7 +109,7 @@ void ProgressDialog::setValue(int value)
} }
else if(_closeWhenDoneCheckBox->isChecked()) 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); _closeButton->setEnabled(false);
} }
void ProgressDialog::closeDialog()
{
if(_closeWhenDoneCheckBox->isChecked())
{
close();
}
}
void ProgressDialog::closeEvent(QCloseEvent *event) void ProgressDialog::closeEvent(QCloseEvent *event)
{ {
if(_progressBar->value() == _progressBar->maximum()) if(_progressBar->value() == _progressBar->maximum())
+9 -84
View File
@@ -52,7 +52,7 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>201</width> <width>198</width>
<height>196</height> <height>196</height>
</rect> </rect>
</property> </property>
@@ -210,7 +210,7 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>201</width> <width>197</width>
<height>196</height> <height>196</height>
</rect> </rect>
</property> </property>
@@ -1122,9 +1122,9 @@
<property name="geometry"> <property name="geometry">
<rect> <rect>
<x>0</x> <x>0</x>
<y>-236</y> <y>-245</y>
<width>297</width> <width>284</width>
<height>704</height> <height>611</height>
</rect> </rect>
</property> </property>
<attribute name="label"> <attribute name="label">
@@ -1328,81 +1328,6 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="8" column="1">
<widget class="QLabel" name="label_69">
<property name="text">
<string>Flat obstacles detected</string>
</property>
</widget>
</item>
<item row="6" column="0">
<widget class="QDoubleSpinBox" name="doubleSpinBox_projMaxGroundHeight">
<property name="suffix">
<string> m</string>
</property>
<property name="decimals">
<number>2</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>0.000000000000000</double>
</property>
</widget>
</item>
<item row="6" column="1">
<widget class="QLabel" name="label_68">
<property name="text">
<string>Max ground height</string>
</property>
</widget>
</item>
<item row="7" column="1">
<widget class="QLabel" name="label_70">
<property name="text">
<string>Max obstacles height</string>
</property>
</widget>
</item>
<item row="7" column="0">
<widget class="QDoubleSpinBox" name="doubleSpinBox_projMaxObstaclesHeight">
<property name="suffix">
<string> m</string>
</property>
<property name="decimals">
<number>2</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>0.000000000000000</double>
</property>
</widget>
</item>
<item row="8" column="0">
<widget class="QCheckBox" name="checkBox_projFlatObstaclesDetected">
<property name="text">
<string/>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
</layout> </layout>
</widget> </widget>
</item> </item>
@@ -1609,8 +1534,8 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>290</width> <width>201</width>
<height>182</height> <height>117</height>
</rect> </rect>
</property> </property>
<attribute name="label"> <attribute name="label">
@@ -1709,8 +1634,8 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>290</width> <width>175</width>
<height>182</height> <height>191</height>
</rect> </rect>
</property> </property>
<attribute name="label"> <attribute name="label">
+58 -32
View File
@@ -63,7 +63,7 @@
<property name="geometry"> <property name="geometry">
<rect> <rect>
<x>0</x> <x>0</x>
<y>-269</y> <y>-847</y>
<width>686</width> <width>686</width>
<height>2023</height> <height>2023</height>
</rect> </rect>
@@ -935,7 +935,7 @@ Show a yellow background when the number of odometry inliers goes under this thr
<enum>QFrame::Raised</enum> <enum>QFrame::Raised</enum>
</property> </property>
<layout class="QGridLayout" name="gridLayout_2" columnstretch="0,0,1"> <layout class="QGridLayout" name="gridLayout_2" columnstretch="0,0,1">
<item row="12" column="0"> <item row="13" column="0">
<widget class="QCheckBox" name="checkBox_showScans"> <widget class="QCheckBox" name="checkBox_showScans">
<property name="text"> <property name="text">
<string/> <string/>
@@ -945,7 +945,7 @@ Show a yellow background when the number of odometry inliers goes under this thr
</property> </property>
</widget> </widget>
</item> </item>
<item row="12" column="2"> <item row="13" column="2">
<widget class="QLabel" name="label_110"> <widget class="QLabel" name="label_110">
<property name="text"> <property name="text">
<string>Show scans.</string> <string>Show scans.</string>
@@ -958,7 +958,7 @@ Show a yellow background when the number of odometry inliers goes under this thr
</property> </property>
</widget> </widget>
</item> </item>
<item row="15" column="0"> <item row="16" column="0">
<widget class="QDoubleSpinBox" name="doubleSpinBox_opacity_scan"> <widget class="QDoubleSpinBox" name="doubleSpinBox_opacity_scan">
<property name="suffix"> <property name="suffix">
<string/> <string/>
@@ -990,7 +990,7 @@ Show a yellow background when the number of odometry inliers goes under this thr
</property> </property>
</widget> </widget>
</item> </item>
<item row="17" column="1"> <item row="18" column="1">
<widget class="QCheckBox" name="checkBox_showOdomFeatures"> <widget class="QCheckBox" name="checkBox_showOdomFeatures">
<property name="text"> <property name="text">
<string/> <string/>
@@ -1000,7 +1000,7 @@ Show a yellow background when the number of odometry inliers goes under this thr
</property> </property>
</widget> </widget>
</item> </item>
<item row="17" column="0"> <item row="18" column="0">
<widget class="QCheckBox" name="checkBox_showFeatures"> <widget class="QCheckBox" name="checkBox_showFeatures">
<property name="text"> <property name="text">
<string/> <string/>
@@ -1074,7 +1074,7 @@ Show a yellow background when the number of odometry inliers goes under this thr
</property> </property>
</widget> </widget>
</item> </item>
<item row="10" column="0"> <item row="11" column="0">
<widget class="QSpinBox" name="spinBox_ptsize"> <widget class="QSpinBox" name="spinBox_ptsize">
<property name="minimum"> <property name="minimum">
<number>1</number> <number>1</number>
@@ -1087,7 +1087,7 @@ Show a yellow background when the number of odometry inliers goes under this thr
</property> </property>
</widget> </widget>
</item> </item>
<item row="15" column="1"> <item row="16" column="1">
<widget class="QDoubleSpinBox" name="doubleSpinBox_opacity_odom_scan"> <widget class="QDoubleSpinBox" name="doubleSpinBox_opacity_odom_scan">
<property name="suffix"> <property name="suffix">
<string/> <string/>
@@ -1132,7 +1132,7 @@ Show a yellow background when the number of odometry inliers goes under this thr
</property> </property>
</widget> </widget>
</item> </item>
<item row="9" column="2"> <item row="10" column="2">
<widget class="QLabel" name="label_155"> <widget class="QLabel" name="label_155">
<property name="text"> <property name="text">
<string>3D cloud opacity.</string> <string>3D cloud opacity.</string>
@@ -1145,7 +1145,7 @@ Show a yellow background when the number of odometry inliers goes under this thr
</property> </property>
</widget> </widget>
</item> </item>
<item row="10" column="1"> <item row="11" column="1">
<widget class="QSpinBox" name="spinBox_ptsize_odom"> <widget class="QSpinBox" name="spinBox_ptsize_odom">
<property name="minimum"> <property name="minimum">
<number>1</number> <number>1</number>
@@ -1158,7 +1158,7 @@ Show a yellow background when the number of odometry inliers goes under this thr
</property> </property>
</widget> </widget>
</item> </item>
<item row="16" column="1"> <item row="17" column="1">
<widget class="QSpinBox" name="spinBox_ptsize_odom_scan"> <widget class="QSpinBox" name="spinBox_ptsize_odom_scan">
<property name="minimum"> <property name="minimum">
<number>1</number> <number>1</number>
@@ -1168,7 +1168,7 @@ Show a yellow background when the number of odometry inliers goes under this thr
</property> </property>
</widget> </widget>
</item> </item>
<item row="16" column="2"> <item row="17" column="2">
<widget class="QLabel" name="label_158"> <widget class="QLabel" name="label_158">
<property name="text"> <property name="text">
<string>Scan point size (1..64).</string> <string>Scan point size (1..64).</string>
@@ -1181,7 +1181,7 @@ Show a yellow background when the number of odometry inliers goes under this thr
</property> </property>
</widget> </widget>
</item> </item>
<item row="14" column="0"> <item row="15" column="0">
<widget class="QDoubleSpinBox" name="doubleSpinBox_voxelSizeScan"> <widget class="QDoubleSpinBox" name="doubleSpinBox_voxelSizeScan">
<property name="suffix"> <property name="suffix">
<string> m</string> <string> m</string>
@@ -1200,7 +1200,7 @@ Show a yellow background when the number of odometry inliers goes under this thr
</property> </property>
</widget> </widget>
</item> </item>
<item row="14" column="2"> <item row="15" column="2">
<widget class="QLabel" name="label_271"> <widget class="QLabel" name="label_271">
<property name="text"> <property name="text">
<string>Scan voxel size.</string> <string>Scan voxel size.</string>
@@ -1213,7 +1213,7 @@ Show a yellow background when the number of odometry inliers goes under this thr
</property> </property>
</widget> </widget>
</item> </item>
<item row="13" column="1"> <item row="14" column="1">
<widget class="QSpinBox" name="spinBox_downsamplingScan_odom"> <widget class="QSpinBox" name="spinBox_downsamplingScan_odom">
<property name="minimum"> <property name="minimum">
<number>1</number> <number>1</number>
@@ -1223,7 +1223,7 @@ Show a yellow background when the number of odometry inliers goes under this thr
</property> </property>
</widget> </widget>
</item> </item>
<item row="15" column="2"> <item row="16" column="2">
<widget class="QLabel" name="label_156"> <widget class="QLabel" name="label_156">
<property name="text"> <property name="text">
<string>Scan opacity.</string> <string>Scan opacity.</string>
@@ -1259,7 +1259,7 @@ Show a yellow background when the number of odometry inliers goes under this thr
</property> </property>
</widget> </widget>
</item> </item>
<item row="9" column="0"> <item row="10" column="0">
<widget class="QDoubleSpinBox" name="doubleSpinBox_opacity"> <widget class="QDoubleSpinBox" name="doubleSpinBox_opacity">
<property name="suffix"> <property name="suffix">
<string/> <string/>
@@ -1278,7 +1278,7 @@ Show a yellow background when the number of odometry inliers goes under this thr
</property> </property>
</widget> </widget>
</item> </item>
<item row="12" column="1"> <item row="13" column="1">
<widget class="QCheckBox" name="checkBox_showOdomScans"> <widget class="QCheckBox" name="checkBox_showOdomScans">
<property name="text"> <property name="text">
<string/> <string/>
@@ -1288,7 +1288,7 @@ Show a yellow background when the number of odometry inliers goes under this thr
</property> </property>
</widget> </widget>
</item> </item>
<item row="19" column="2"> <item row="20" column="2">
<widget class="QLabel" name="label_213"> <widget class="QLabel" name="label_213">
<property name="text"> <property name="text">
<string>Show graphs.</string> <string>Show graphs.</string>
@@ -1301,7 +1301,7 @@ Show a yellow background when the number of odometry inliers goes under this thr
</property> </property>
</widget> </widget>
</item> </item>
<item row="19" column="0"> <item row="20" column="0">
<widget class="QCheckBox" name="checkBox_showGraphs"> <widget class="QCheckBox" name="checkBox_showGraphs">
<property name="text"> <property name="text">
<string/> <string/>
@@ -1311,7 +1311,7 @@ Show a yellow background when the number of odometry inliers goes under this thr
</property> </property>
</widget> </widget>
</item> </item>
<item row="9" column="1"> <item row="10" column="1">
<widget class="QDoubleSpinBox" name="doubleSpinBox_opacity_odom"> <widget class="QDoubleSpinBox" name="doubleSpinBox_opacity_odom">
<property name="suffix"> <property name="suffix">
<string/> <string/>
@@ -1330,7 +1330,7 @@ Show a yellow background when the number of odometry inliers goes under this thr
</property> </property>
</widget> </widget>
</item> </item>
<item row="16" column="0"> <item row="17" column="0">
<widget class="QSpinBox" name="spinBox_ptsize_scan"> <widget class="QSpinBox" name="spinBox_ptsize_scan">
<property name="minimum"> <property name="minimum">
<number>1</number> <number>1</number>
@@ -1350,7 +1350,7 @@ Show a yellow background when the number of odometry inliers goes under this thr
</property> </property>
</widget> </widget>
</item> </item>
<item row="20" column="2"> <item row="21" column="2">
<widget class="QLabel" name="label_243"> <widget class="QLabel" name="label_243">
<property name="text"> <property name="text">
<string>Show labels.</string> <string>Show labels.</string>
@@ -1363,7 +1363,7 @@ Show a yellow background when the number of odometry inliers goes under this thr
</property> </property>
</widget> </widget>
</item> </item>
<item row="20" column="0"> <item row="21" column="0">
<widget class="QCheckBox" name="checkBox_showLabels"> <widget class="QCheckBox" name="checkBox_showLabels">
<property name="text"> <property name="text">
<string/> <string/>
@@ -1373,7 +1373,7 @@ Show a yellow background when the number of odometry inliers goes under this thr
</property> </property>
</widget> </widget>
</item> </item>
<item row="14" column="1"> <item row="15" column="1">
<widget class="QDoubleSpinBox" name="doubleSpinBox_voxelSizeScan_odom"> <widget class="QDoubleSpinBox" name="doubleSpinBox_voxelSizeScan_odom">
<property name="suffix"> <property name="suffix">
<string> m</string> <string> m</string>
@@ -1392,7 +1392,7 @@ Show a yellow background when the number of odometry inliers goes under this thr
</property> </property>
</widget> </widget>
</item> </item>
<item row="13" column="2"> <item row="14" column="2">
<widget class="QLabel" name="label_273"> <widget class="QLabel" name="label_273">
<property name="text"> <property name="text">
<string>Scan downsampling step size.</string> <string>Scan downsampling step size.</string>
@@ -1405,7 +1405,7 @@ Show a yellow background when the number of odometry inliers goes under this thr
</property> </property>
</widget> </widget>
</item> </item>
<item row="13" column="0"> <item row="14" column="0">
<widget class="QSpinBox" name="spinBox_downsamplingScan"> <widget class="QSpinBox" name="spinBox_downsamplingScan">
<property name="minimum"> <property name="minimum">
<number>1</number> <number>1</number>
@@ -1415,7 +1415,7 @@ Show a yellow background when the number of odometry inliers goes under this thr
</property> </property>
</widget> </widget>
</item> </item>
<item row="10" column="2"> <item row="11" column="2">
<widget class="QLabel" name="label_157"> <widget class="QLabel" name="label_157">
<property name="text"> <property name="text">
<string>3D cloud point size (1..64).</string> <string>3D cloud point size (1..64).</string>
@@ -1441,7 +1441,7 @@ Show a yellow background when the number of odometry inliers goes under this thr
</property> </property>
</widget> </widget>
</item> </item>
<item row="17" column="2"> <item row="18" column="2">
<widget class="QLabel" name="label_123"> <widget class="QLabel" name="label_123">
<property name="text"> <property name="text">
<string>Show 3D features.</string> <string>Show 3D features.</string>
@@ -1454,7 +1454,7 @@ Show a yellow background when the number of odometry inliers goes under this thr
</property> </property>
</widget> </widget>
</item> </item>
<item row="18" column="2"> <item row="19" column="2">
<widget class="QLabel" name="label_166"> <widget class="QLabel" name="label_166">
<property name="text"> <property name="text">
<string>Feature point size.</string> <string>Feature point size.</string>
@@ -1467,7 +1467,7 @@ Show a yellow background when the number of odometry inliers goes under this thr
</property> </property>
</widget> </widget>
</item> </item>
<item row="18" column="1"> <item row="19" column="1">
<widget class="QSpinBox" name="spinBox_ptsize_odom_features"> <widget class="QSpinBox" name="spinBox_ptsize_odom_features">
<property name="minimum"> <property name="minimum">
<number>1</number> <number>1</number>
@@ -1477,7 +1477,7 @@ Show a yellow background when the number of odometry inliers goes under this thr
</property> </property>
</widget> </widget>
</item> </item>
<item row="18" column="0"> <item row="19" column="0">
<widget class="QSpinBox" name="spinBox_ptsize_features"> <widget class="QSpinBox" name="spinBox_ptsize_features">
<property name="minimum"> <property name="minimum">
<number>1</number> <number>1</number>
@@ -1631,6 +1631,32 @@ Show a yellow background when the number of odometry inliers goes under this thr
</property> </property>
</widget> </widget>
</item> </item>
<item row="9" column="2">
<widget class="QLabel" name="label_210">
<property name="text">
<string>3D cloud normal K search. If not 0, normals will be computed and added to created cloud for visualization (keys 7, 8 and 9).</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item row="9" column="0">
<widget class="QSpinBox" name="spinBox_normalKSearch">
<property name="minimum">
<number>0</number>
</property>
<property name="maximum">
<number>1000</number>
</property>
<property name="value">
<number>10</number>
</property>
</widget>
</item>
</layout> </layout>
</widget> </widget>
</item> </item>