0.13.3: scan2d with normals support/registration

This commit is contained in:
matlabbe
2017-08-25 18:02:40 -04:00
parent 964a052be1
commit 52a4e8964f
28 changed files with 1029 additions and 337 deletions

View File

@@ -28,6 +28,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "rtabmap/gui/CloudViewer.h"
#include <rtabmap/core/Version.h>
#include <rtabmap/core/util3d_transforms.h>
#include <rtabmap/utilite/ULogger.h>
#include <rtabmap/utilite/UTimer.h>
#include <rtabmap/utilite/UMath.h>
@@ -190,6 +191,9 @@ CloudViewer::CloudViewer(QWidget *parent) :
_aShowGrid(0),
_aSetGridCellCount(0),
_aSetGridCellSize(0),
_aShowNormals(0),
_aSetNormalsStep(0),
_aSetNormalsScale(0),
_aSetBackgroundColor(0),
_aSetRenderingRate(0),
_aSetLighting(0),
@@ -203,6 +207,8 @@ CloudViewer::CloudViewer(QWidget *parent) :
_frustumColor(Qt::gray),
_gridCellCount(50),
_gridCellSize(1),
_normalsStep(1),
_normalsScale(0.2),
_lastCameraOrientation(0,0,0),
_lastCameraPose(0,0,0),
_defaultBgColor(Qt::black),
@@ -310,6 +316,10 @@ void CloudViewer::createMenu()
_aShowGrid->setCheckable(true);
_aSetGridCellCount = new QAction("Set cell count...", this);
_aSetGridCellSize = new QAction("Set cell size...", this);
_aShowNormals = new QAction("Show normals", this);
_aShowNormals->setCheckable(true);
_aSetNormalsStep = new QAction("Set normals step...", this);
_aSetNormalsScale = new QAction("Set normals scale...", this);
_aSetBackgroundColor = new QAction("Set background color...", this);
_aSetRenderingRate = new QAction("Set rendering rate...", this);
_aSetLighting = new QAction("Lighting", this);
@@ -352,12 +362,18 @@ void CloudViewer::createMenu()
gridMenu->addAction(_aSetGridCellCount);
gridMenu->addAction(_aSetGridCellSize);
QMenu * normalsMenu = new QMenu("Normals", this);
normalsMenu->addAction(_aShowNormals);
normalsMenu->addAction(_aSetNormalsStep);
normalsMenu->addAction(_aSetNormalsScale);
//menus
_menu = new QMenu(this);
_menu->addMenu(cameraMenu);
_menu->addMenu(trajectoryMenu);
_menu->addMenu(frustumMenu);
_menu->addMenu(gridMenu);
_menu->addMenu(normalsMenu);
_menu->addAction(_aSetBackgroundColor);
_menu->addAction(_aSetRenderingRate);
_menu->addAction(_aSetLighting);
@@ -400,6 +416,10 @@ void CloudViewer::saveSettings(QSettings & settings, const QString & group) cons
settings.setValue("grid_cell_count", this->getGridCellCount());
settings.setValue("grid_cell_size", (double)this->getGridCellSize());
settings.setValue("normals", this->isNormalsShown());
settings.setValue("normals_step", this->getNormalsStep());
settings.setValue("normals_scale", (double)this->getNormalsScale());
settings.setValue("trajectory_shown", this->isTrajectoryShown());
settings.setValue("trajectory_size", this->getTrajectorySize());
@@ -439,6 +459,10 @@ void CloudViewer::loadSettings(QSettings & settings, const QString & group)
this->setGridCellCount(settings.value("grid_cell_count", this->getGridCellCount()).toUInt());
this->setGridCellSize(settings.value("grid_cell_size", this->getGridCellSize()).toFloat());
this->setNormalsShown(settings.value("normals", this->isNormalsShown()).toBool());
this->setNormalsStep(settings.value("normals_step", this->getNormalsStep()).toInt());
this->setNormalsScale(settings.value("normals_scale", this->getNormalsScale()).toFloat());
this->setTrajectoryShown(settings.value("trajectory_shown", this->isTrajectoryShown()).toBool());
this->setTrajectorySize(settings.value("trajectory_size", this->getTrajectorySize()).toUInt());
@@ -473,10 +497,21 @@ bool CloudViewer::updateCloudPose(
if(_addedClouds.contains(id))
{
UDEBUG("Updating pose %s to %s", id.c_str(), pose.prettyPrint().c_str());
if(_addedClouds.find(id).value() == pose ||
_visualizer->updatePointCloudPose(id, pose.toEigen3f()))
bool samePose = _addedClouds.find(id).value() == pose;
Eigen::Affine3f posef = pose.toEigen3f();
if(samePose ||
_visualizer->updatePointCloudPose(id, posef))
{
_addedClouds.find(id).value() = pose;
if(!samePose)
{
std::string idNormals = id+"-normals";
if(_addedClouds.find(idNormals)!=_addedClouds.end())
{
_visualizer->updatePointCloudPose(idNormals, posef);
_addedClouds.find(idNormals).value() = pose;
}
}
return true;
}
}
@@ -501,6 +536,18 @@ bool CloudViewer::addCloud(
Eigen::Vector4f origin(pose.x(), pose.y(), pose.z(), 0.0f);
Eigen::Quaternionf orientation = Eigen::Quaternionf(pose.toEigen3f().rotation());
if(haveNormals && _aShowNormals->isChecked())
{
pcl::PointCloud<pcl::PointNormal>::Ptr cloud_xyz (new pcl::PointCloud<pcl::PointNormal>);
pcl::fromPCLPointCloud2 (*binaryCloud, *cloud_xyz);
std::string idNormals = id + "-normals";
if(_visualizer->addPointCloudNormals<pcl::PointNormal>(cloud_xyz, _normalsStep, _normalsScale, idNormals, 0))
{
_visualizer->updatePointCloudPose(idNormals, pose.toEigen3f());
_addedClouds.insert(idNormals, pose);
}
}
// add random color channel
pcl::visualization::PointCloudColorHandler<pcl::PCLPointCloud2>::Ptr colorHandler;
colorHandler.reset (new pcl::visualization::PointCloudColorHandlerRandom<pcl::PCLPointCloud2> (binaryCloud));
@@ -1626,7 +1673,9 @@ void CloudViewer::removeAllClouds()
bool CloudViewer::removeCloud(const std::string & id)
{
bool success = _visualizer->removePointCloud(id);
_visualizer->removePointCloud(id+"-normals");
_addedClouds.remove(id); // remove after visualizer
_addedClouds.remove(id+"-normals");
return success;
}
@@ -1929,6 +1978,12 @@ void CloudViewer::setCloudVisibility(const std::string & id, bool isVisible)
if(iter != cloudActorMap->end())
{
iter->second.actor->SetVisibility(isVisible?1:0);
iter = cloudActorMap->find(id+"-normals");
if(iter != cloudActorMap->end())
{
iter->second.actor->SetVisibility(isVisible&&_aShowNormals->isChecked()?1:0);
}
}
else
{
@@ -1992,20 +2047,6 @@ void CloudViewer::setCameraLockZ(bool enabled)
_lastCameraOrientation= _lastCameraPose = cv::Vec3f(0,0,0);
_aLockViewZ->setChecked(enabled);
}
void CloudViewer::setGridShown(bool shown)
{
_aShowGrid->setChecked(shown);
if(shown)
{
this->addGrid();
}
else
{
this->removeGrid();
}
}
bool CloudViewer::isCameraTargetLocked() const
{
return _aLockCamera->isChecked();
@@ -2022,6 +2063,23 @@ bool CloudViewer::isCameraLockZ() const
{
return _aLockViewZ->isChecked();
}
double CloudViewer::getRenderingRate() const
{
return _renderingRate;
}
void CloudViewer::setGridShown(bool shown)
{
_aShowGrid->setChecked(shown);
if(shown)
{
this->addGrid();
}
else
{
this->removeGrid();
}
}
bool CloudViewer::isGridShown() const
{
return _aShowGrid->isChecked();
@@ -2034,11 +2092,6 @@ float CloudViewer::getGridCellSize() const
{
return _gridCellSize;
}
double CloudViewer::getRenderingRate() const
{
return _renderingRate;
}
void CloudViewer::setGridCellCount(unsigned int count)
{
if(count > 0)
@@ -2110,6 +2163,54 @@ void CloudViewer::removeGrid()
_gridLines.clear();
}
void CloudViewer::setNormalsShown(bool shown)
{
_aShowNormals->setChecked(shown);
QList<std::string> ids = _addedClouds.keys();
for(QList<std::string>::iterator iter = ids.begin(); iter!=ids.end(); ++iter)
{
std::string idNormals = *iter + "-normals";
if(_addedClouds.find(idNormals) != _addedClouds.end())
{
this->setCloudVisibility(idNormals, this->getCloudVisibility(*iter) && shown);
}
}
}
bool CloudViewer::isNormalsShown() const
{
return _aShowNormals->isChecked();
}
int CloudViewer::getNormalsStep() const
{
return _normalsStep;
}
float CloudViewer::getNormalsScale() const
{
return _normalsScale;
}
void CloudViewer::setNormalsStep(int step)
{
if(step > 0)
{
_normalsStep = step;
}
else
{
UERROR("Cannot set normals step <= 0, step=%d", step);
}
}
void CloudViewer::setNormalsScale(float scale)
{
if(scale > 0)
{
_normalsScale= scale;
}
else
{
UERROR("Cannot set normals scale <= 0, value=%f", scale);
}
}
Eigen::Vector3f rotatePointAroundAxe(
const Eigen::Vector3f & point,
const Eigen::Vector3f & axis,
@@ -2405,6 +2506,29 @@ void CloudViewer::handleAction(QAction * a)
this->setGridCellSize(value);
}
}
else if(a == _aShowNormals)
{
this->setNormalsShown(_aShowNormals->isChecked());
this->update();
}
else if(a == _aSetNormalsStep)
{
bool ok;
int value = QInputDialog::getInt(this, tr("Set normals step"), tr("Step"), _normalsStep, 1, 10000, 1, &ok);
if(ok)
{
this->setNormalsStep(value);
}
}
else if(a == _aSetNormalsScale)
{
bool ok;
double value = QInputDialog::getDouble(this, tr("Set normals scale"), tr("Scale (m)"), _normalsScale, 0.01, 10, 2, &ok);
if(ok)
{
this->setNormalsScale(value);
}
}
else if(a == _aSetBackgroundColor)
{
QColor color = this->getDefaultBackgroundColor();

View File

@@ -88,6 +88,7 @@ ExportCloudsDialog::ExportCloudsDialog(QWidget *parent) :
connect(_ui->checkBox_fromDepth, SIGNAL(stateChanged(int)), this, SLOT(updateReconstructionFlavor()));
connect(_ui->checkBox_binary, SIGNAL(stateChanged(int)), this, SIGNAL(configChanged()));
connect(_ui->spinBox_normalKSearch, SIGNAL(valueChanged(int)), this, SIGNAL(configChanged()));
connect(_ui->doubleSpinBox_normalRadiusSearch, SIGNAL(valueChanged(double)), this, SIGNAL(configChanged()));
connect(_ui->comboBox_pipeline, SIGNAL(currentIndexChanged(int)), this, SIGNAL(configChanged()));
connect(_ui->comboBox_pipeline, SIGNAL(currentIndexChanged(int)), this, SLOT(updateReconstructionFlavor()));
connect(_ui->comboBox_meshingApproach, SIGNAL(currentIndexChanged(int)), this, SIGNAL(configChanged()));
@@ -255,6 +256,7 @@ void ExportCloudsDialog::saveSettings(QSettings & settings, const QString & grou
settings.setValue("from_depth", _ui->checkBox_fromDepth->isChecked());
settings.setValue("binary", _ui->checkBox_binary->isChecked());
settings.setValue("normals_k", _ui->spinBox_normalKSearch->value());
settings.setValue("normals_radius", _ui->doubleSpinBox_normalRadiusSearch->value());
settings.setValue("regenerate", _ui->checkBox_regenerate->isChecked());
settings.setValue("regenerate_decimation", _ui->spinBox_decimation->value());
@@ -371,6 +373,7 @@ void ExportCloudsDialog::loadSettings(QSettings & settings, const QString & grou
_ui->checkBox_fromDepth->setChecked(settings.value("from_depth", _ui->checkBox_fromDepth->isChecked()).toBool());
_ui->checkBox_binary->setChecked(settings.value("binary", _ui->checkBox_binary->isChecked()).toBool());
_ui->spinBox_normalKSearch->setValue(settings.value("normals_k", _ui->spinBox_normalKSearch->value()).toInt());
_ui->doubleSpinBox_normalRadiusSearch->setValue(settings.value("normals_radius", _ui->doubleSpinBox_normalRadiusSearch->value()).toDouble());
_ui->checkBox_regenerate->setChecked(settings.value("regenerate", _ui->checkBox_regenerate->isChecked()).toBool());
_ui->spinBox_decimation->setValue(settings.value("regenerate_decimation", _ui->spinBox_decimation->value()).toInt());
@@ -487,6 +490,7 @@ void ExportCloudsDialog::restoreDefaults()
_ui->checkBox_fromDepth->setChecked(true);
_ui->checkBox_binary->setChecked(true);
_ui->spinBox_normalKSearch->setValue(20);
_ui->doubleSpinBox_normalRadiusSearch->setValue(0.0);
_ui->checkBox_regenerate->setChecked(_dbDriver!=0?true:false);
_ui->spinBox_decimation->setValue(1);
@@ -1384,7 +1388,7 @@ bool ExportCloudsDialog::getExportedClouds(
// recompute normals
pcl::PointCloud<pcl::PointXYZ>::Ptr cloudWithoutNormals(new pcl::PointCloud<pcl::PointXYZ>);
pcl::copyPointCloud(*assembledCloud, *cloudWithoutNormals);
pcl::PointCloud<pcl::Normal>::Ptr normals = util3d::computeNormals(cloudWithoutNormals, indices, _ui->spinBox_normalKSearch->value());
pcl::PointCloud<pcl::Normal>::Ptr normals = util3d::computeNormals(cloudWithoutNormals, indices, _ui->spinBox_normalKSearch->value(), _ui->doubleSpinBox_normalRadiusSearch->value());
UASSERT(assembledCloud->size() == normals->size());
for(unsigned int i=0; i<normals->size(); ++i)
@@ -2521,7 +2525,7 @@ std::map<int, std::pair<pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr, pcl::Indic
viewPoint[2] = data.stereoCameraModel().localTransform().z();
}
pcl::PointCloud<pcl::Normal>::Ptr normals = util3d::computeNormals(cloudWithoutNormals, indices, _ui->spinBox_normalKSearch->value(), viewPoint);
pcl::PointCloud<pcl::Normal>::Ptr normals = util3d::computeNormals(cloudWithoutNormals, indices, _ui->spinBox_normalKSearch->value(), _ui->doubleSpinBox_normalRadiusSearch->value(), viewPoint);
pcl::concatenateFields(*cloudWithoutNormals, *normals, *cloud);
if(_ui->checkBox_subtraction->isChecked() &&
@@ -2592,7 +2596,7 @@ std::map<int, std::pair<pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr, pcl::Indic
}
else
{
normals = util3d::computeNormals(cloudWithoutNormals, indices, _ui->spinBox_normalKSearch->value(), viewPoint);
normals = util3d::computeNormals(cloudWithoutNormals, indices, _ui->spinBox_normalKSearch->value(), _ui->doubleSpinBox_normalRadiusSearch->value(), viewPoint);
}
pcl::concatenateFields(*cloudWithoutNormals, *normals, *cloud);
}
@@ -2673,7 +2677,7 @@ std::map<int, std::pair<pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr, pcl::Indic
_progressDialog->appendText(tr("Cached cloud %1 is not found in cached data, the view point for normal computation will not be set (%2/%3).").arg(iter->first).arg(index).arg(poses.size()), Qt::darkYellow);
}
pcl::PointCloud<pcl::Normal>::Ptr normals = util3d::computeNormals(cloudWithoutNormals, indices, _ui->spinBox_normalKSearch->value(), viewPoint);
pcl::PointCloud<pcl::Normal>::Ptr normals = util3d::computeNormals(cloudWithoutNormals, indices, _ui->spinBox_normalKSearch->value(), _ui->doubleSpinBox_normalRadiusSearch->value(), viewPoint);
pcl::concatenateFields(*cloudWithoutNormals, *normals, *cloud);
}
else if(!_ui->checkBox_fromDepth->isChecked() && uContains(cachedScans, iter->first))
@@ -2731,7 +2735,7 @@ std::map<int, std::pair<pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr, pcl::Indic
}
else
{
normals = util3d::computeNormals(cloudWithoutNormals, indices, _ui->spinBox_normalKSearch->value(), viewPoint);
normals = util3d::computeNormals(cloudWithoutNormals, indices, _ui->spinBox_normalKSearch->value(), _ui->doubleSpinBox_normalRadiusSearch->value(), viewPoint);
}
pcl::concatenateFields(*cloudWithoutNormals, *normals, *cloud);
}

View File

@@ -2651,9 +2651,9 @@ std::pair<pcl::PointCloud<pcl::PointXYZRGB>::Ptr, pcl::IndicesPtr> MainWindow::c
if(_preferencesDialog->getSubtractFilteringAngle() > 0.0f)
{
//normals required
if(_preferencesDialog->getNormalKSearch() > 0)
if(_preferencesDialog->getNormalKSearch() > 0 || _preferencesDialog->getNormalRadiusSearch() > 0)
{
pcl::PointCloud<pcl::Normal>::Ptr normals = util3d::computeNormals(cloud, indices, _preferencesDialog->getNormalKSearch(), viewPoint);
pcl::PointCloud<pcl::Normal>::Ptr normals = util3d::computeNormals(cloud, indices, _preferencesDialog->getNormalKSearch(), _preferencesDialog->getNormalRadiusSearch(), viewPoint);
pcl::concatenateFields(*cloud, *normals, *cloudWithNormals);
}
else
@@ -2790,7 +2790,7 @@ std::pair<pcl::PointCloud<pcl::PointXYZRGB>::Ptr, pcl::IndicesPtr> MainWindow::c
if(_preferencesDialog->getNormalKSearch() > 0 && cloudWithNormals->size() == 0)
{
pcl::PointCloud<pcl::Normal>::Ptr normals = util3d::computeNormals(cloud, indices, _preferencesDialog->getNormalKSearch(), viewPoint);
pcl::PointCloud<pcl::Normal>::Ptr normals = util3d::computeNormals(cloud, indices, _preferencesDialog->getNormalKSearch(), _preferencesDialog->getNormalRadiusSearch(), viewPoint);
pcl::concatenateFields(*cloud, *normals, *cloudWithNormals);
}
@@ -2880,22 +2880,48 @@ void MainWindow::createAndAddScanToMap(int nodeId, const Transform & pose, int m
scan = util3d::downsample(scan, _preferencesDialog->getDownsamplingStepScan(0));
}
if(scan.channels() == 6)
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud;
pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloudRGB;
pcl::PointCloud<pcl::PointNormal>::Ptr cloudWithNormals;
pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr cloudRGBWithNormals;
if(scan.channels() == 7 && _preferencesDialog->getCloudVoxelSizeScan(0) <= 0.0)
{
pcl::PointCloud<pcl::PointNormal>::Ptr cloud;
cloud = util3d::laserScanToPointCloudNormal(scan, iter->sensorData().laserScanInfo().localTransform());
if(_preferencesDialog->getCloudVoxelSizeScan(0) > 0.0)
cloudRGBWithNormals = util3d::laserScanToPointCloudRGBNormal(scan, iter->sensorData().laserScanInfo().localTransform());
}
else if(scan.channels() == 6 && _preferencesDialog->getCloudVoxelSizeScan(0) <= 0.0)
{
cloudWithNormals = util3d::laserScanToPointCloudNormal(scan, iter->sensorData().laserScanInfo().localTransform());
}
else if(scan.channels() == 4)
{
cloudRGB = util3d::laserScanToPointCloudRGB(scan, iter->sensorData().laserScanInfo().localTransform());
}
else
{
cloud = util3d::laserScanToPointCloud(scan, iter->sensorData().laserScanInfo().localTransform());
}
if(_preferencesDialog->getCloudVoxelSizeScan(0) > 0.0)
{
if(cloud.get())
{
cloud = util3d::voxelize(cloud, _preferencesDialog->getCloudVoxelSizeScan(0));
}
if(cloudRGB.get())
{
cloudRGB = util3d::voxelize(cloudRGB, _preferencesDialog->getCloudVoxelSizeScan(0));
}
}
// Do ceiling/floor filtering
if(cloud->size() &&
(_preferencesDialog->getScanFloorFilteringHeight() != 0.0 ||
_preferencesDialog->getScanCeilingFilteringHeight() != 0.0))
// Do ceiling/floor filtering
if(scan.channels() > 2 && // don't filter 2D scans
(_preferencesDialog->getScanFloorFilteringHeight() != 0.0 ||
_preferencesDialog->getScanCeilingFilteringHeight() != 0.0))
{
if(cloudRGBWithNormals.get())
{
// perform in /map frame
pcl::PointCloud<pcl::PointNormal>::Ptr cloudTransformed = util3d::transformPointCloud(cloud, pose);
pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr cloudTransformed = util3d::transformPointCloud(cloudRGBWithNormals, pose);
cloudTransformed = rtabmap::util3d::passThrough(
cloudTransformed,
"z",
@@ -2903,53 +2929,35 @@ void MainWindow::createAndAddScanToMap(int nodeId, const Transform & pose, int m
_preferencesDialog->getScanCeilingFilteringHeight()==0.0?(float)std::numeric_limits<int>::max():_preferencesDialog->getScanCeilingFilteringHeight());
//transform back in sensor frame
cloud = util3d::transformPointCloud(cloudTransformed, pose.inverse());
cloudRGBWithNormals = util3d::transformPointCloud(cloudTransformed, pose.inverse());
}
if(cloudWithNormals.get())
{
// perform in /map frame
pcl::PointCloud<pcl::PointNormal>::Ptr cloudTransformed = util3d::transformPointCloud(cloudWithNormals, pose);
cloudTransformed = rtabmap::util3d::passThrough(
cloudTransformed,
"z",
_preferencesDialog->getScanFloorFilteringHeight()==0.0?(float)std::numeric_limits<int>::min():_preferencesDialog->getScanFloorFilteringHeight(),
_preferencesDialog->getScanCeilingFilteringHeight()==0.0?(float)std::numeric_limits<int>::max():_preferencesDialog->getScanCeilingFilteringHeight());
QColor color = Qt::gray;
if(mapId >= 0)
{
color = (Qt::GlobalColor)(mapId+3 % 12 + 7 );
//transform back in sensor frame
cloudWithNormals = util3d::transformPointCloud(cloudTransformed, pose.inverse());
}
if(!_cloudViewer->addCloud(scanName, cloud, pose, color))
if(cloudRGB.get())
{
UERROR("Adding cloud %d to viewer failed!", nodeId);
}
else
{
if(nodeId > 0)
{
if(_preferencesDialog->getCloudVoxelSizeScan(0) > 0.0)
{
//reconvert the voxelized cloud
scan = util3d::laserScanFromPointCloud(*cloud);
}
else
{
scan = util3d::transformLaserScan(scan, iter->sensorData().laserScanInfo().localTransform());
}
_createdScans.insert(std::make_pair(nodeId, scan)); // keep scan in base_link frame
}
_cloudViewer->setCloudOpacity(scanName, _preferencesDialog->getScanOpacity(0));
_cloudViewer->setCloudPointSize(scanName, _preferencesDialog->getScanPointSize(0));
}
}
else
{
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud;
cloud = util3d::laserScanToPointCloud(scan, iter->sensorData().laserScanInfo().localTransform());
bool filtered = false;
if(_preferencesDialog->getCloudVoxelSizeScan(0) > 0.0)
{
cloud = util3d::voxelize(cloud, _preferencesDialog->getCloudVoxelSizeScan(0));
filtered = true;
}
// perform in /map frame
pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloudTransformed = util3d::transformPointCloud(cloudRGB, pose);
cloudTransformed = rtabmap::util3d::passThrough(
cloudTransformed,
"z",
_preferencesDialog->getScanFloorFilteringHeight()==0.0?(float)std::numeric_limits<int>::min():_preferencesDialog->getScanFloorFilteringHeight(),
_preferencesDialog->getScanCeilingFilteringHeight()==0.0?(float)std::numeric_limits<int>::max():_preferencesDialog->getScanCeilingFilteringHeight());
// Do ceiling/floor filtering
if(scan.channels() > 2 && // don't filter 2D scans
cloud->size() &&
(_preferencesDialog->getScanFloorFilteringHeight() != 0.0 ||
_preferencesDialog->getScanCeilingFilteringHeight() != 0.0))
//transform back in sensor frame
cloudRGB = util3d::transformPointCloud(cloudTransformed, pose.inverse());
}
if(cloud.get())
{
// perform in /map frame
pcl::PointCloud<pcl::PointXYZ>::Ptr cloudTransformed = util3d::transformPointCloud(cloud, pose);
@@ -2961,78 +2969,103 @@ void MainWindow::createAndAddScanToMap(int nodeId, const Transform & pose, int m
//transform back in sensor frame
cloud = util3d::transformPointCloud(cloudTransformed, pose.inverse());
filtered = true;
}
}
pcl::PointCloud<pcl::PointNormal>::Ptr cloudWithNormals;
if(scan.channels() > 2 && // don't compute normals for 2D scans
cloud->size() &&
_preferencesDialog->getScanNormalKSearch() > 0)
{
pcl::PointCloud<pcl::Normal>::Ptr normals = util3d::computeNormals(cloud, _preferencesDialog->getScanNormalKSearch());
cloudWithNormals.reset(new pcl::PointCloud<pcl::PointNormal>);
pcl::concatenateFields(*cloud, *normals, *cloudWithNormals);
filtered = true;
}
if( (cloud.get() || cloudRGB.get()) &&
(_preferencesDialog->getScanNormalKSearch() > 0 || _preferencesDialog->getScanNormalRadiusSearch() > 0.0))
{
Eigen::Vector3f scanViewpoint(
iter->sensorData().laserScanInfo().localTransform().x(),
iter->sensorData().laserScanInfo().localTransform().y(),
iter->sensorData().laserScanInfo().localTransform().z());
QColor color = Qt::gray;
if(mapId >= 0)
pcl::PointCloud<pcl::Normal>::Ptr normals;
if(cloud->size())
{
color = (Qt::GlobalColor)(mapId+3 % 12 + 7 );
}
if(cloudWithNormals.get())
{
if(!_cloudViewer->addCloud(scanName, cloudWithNormals, pose, color))
if(scan.channels() == 2)
{
UERROR("Adding cloud %d to viewer failed!", nodeId);
normals = util3d::computeFastOrganizedNormals2D(cloud, _preferencesDialog->getScanNormalKSearch(), _preferencesDialog->getScanNormalRadiusSearch(), scanViewpoint);
}
else
{
if(nodeId > 0)
{
//reconvert the voxelized cloud
scan = util3d::laserScanFromPointCloud(*cloudWithNormals);
_createdScans.insert(std::make_pair(nodeId, scan)); // keep scan in base_link frame
}
_cloudViewer->setCloudOpacity(scanName, _preferencesDialog->getScanOpacity(0));
_cloudViewer->setCloudPointSize(scanName, _preferencesDialog->getScanPointSize(0));
normals = util3d::computeNormals(cloud, _preferencesDialog->getScanNormalKSearch(), _preferencesDialog->getScanNormalRadiusSearch(), scanViewpoint);
}
cloudWithNormals.reset(new pcl::PointCloud<pcl::PointNormal>);
pcl::concatenateFields(*cloud, *normals, *cloudWithNormals);
cloud.reset();
}
else
{
if(!_cloudViewer->addCloud(scanName, cloud, pose, color))
UASSERT(cloudRGB->size()); // Assuming 4 channels cannot be 2D
normals = util3d::computeNormals(cloudRGB, _preferencesDialog->getScanNormalKSearch(), _preferencesDialog->getScanNormalRadiusSearch(), scanViewpoint);
cloudRGBWithNormals.reset(new pcl::PointCloud<pcl::PointXYZRGBNormal>);
pcl::concatenateFields(*cloudRGB, *normals, *cloudRGBWithNormals);
cloudRGB.reset();
}
}
QColor color = Qt::gray;
if(mapId >= 0)
{
color = (Qt::GlobalColor)(mapId+3 % 12 + 7 );
}
bool added = false;
if(cloudRGBWithNormals.get())
{
added = _cloudViewer->addCloud(scanName, cloudRGBWithNormals, pose, color);
if(added && nodeId > 0)
{
scan = util3d::laserScanFromPointCloud(*cloudRGBWithNormals);
}
}
else if(cloudWithNormals.get())
{
added = _cloudViewer->addCloud(scanName, cloudWithNormals, pose, color);
if(added && nodeId > 0)
{
scan = util3d::laserScanFromPointCloud(*cloudWithNormals);
}
}
else if(cloudRGB.get())
{
added = _cloudViewer->addCloud(scanName, cloudWithNormals, pose, color);
if(added && nodeId > 0)
{
scan = util3d::laserScanFromPointCloud(*cloudWithNormals);
}
}
else
{
UASSERT(cloud.get());
added = _cloudViewer->addCloud(scanName, cloud, pose, color);
if(added && nodeId > 0)
{
if(scan.channels() == 2)
{
UERROR("Adding cloud %d to viewer failed!", nodeId);
scan = util3d::laserScan2dFromPointCloud(*cloud);
}
else
{
if(nodeId > 0)
{
if(filtered)
{
//reconvert the voxelized cloud
if(scan.channels() == 2)
{
scan = util3d::laserScan2dFromPointCloud(*cloud);
}
else
{
scan = util3d::laserScanFromPointCloud(*cloud);
}
}
else
{
scan = util3d::transformLaserScan(scan, iter->sensorData().laserScanInfo().localTransform());
}
_createdScans.insert(std::make_pair(nodeId, scan)); // keep scan in base_link frame
}
_cloudViewer->setCloudOpacity(scanName, _preferencesDialog->getScanOpacity(0));
_cloudViewer->setCloudPointSize(scanName, _preferencesDialog->getScanPointSize(0));
scan = util3d::laserScanFromPointCloud(*cloud);
}
}
}
if(!added)
{
UERROR("Adding cloud %d to viewer failed!", nodeId);
}
else
{
if(nodeId > 0)
{
_createdScans.insert(std::make_pair(nodeId, scan)); // keep scan in base_link frame
}
_cloudViewer->setCloudOpacity(scanName, _preferencesDialog->getScanOpacity(0));
_cloudViewer->setCloudPointSize(scanName, _preferencesDialog->getScanPointSize(0));
}
}
}
@@ -4496,7 +4529,8 @@ void MainWindow::startDetection()
_preferencesDialog->getSourceScanFromDepthDecimation(),
_preferencesDialog->getSourceScanFromDepthMaxDepth(),
_preferencesDialog->getSourceScanVoxelSize(),
_preferencesDialog->getSourceScanNormalsK());
_preferencesDialog->getSourceScanNormalsK(),
_preferencesDialog->getSourceScanNormalsRadius());
if(_preferencesDialog->isDepthFilteringAvailable())
{
if(_preferencesDialog->isBilateralFiltering())

View File

@@ -410,9 +410,11 @@ PreferencesDialog::PreferencesDialog(QWidget * parent) :
connect(_ui->doubleSpinBox_ceilingFilterHeight, SIGNAL(valueChanged(double)), this, SLOT(makeObsoleteCloudRenderingPanel()));
connect(_ui->doubleSpinBox_floorFilterHeight, SIGNAL(valueChanged(double)), this, SLOT(makeObsoleteCloudRenderingPanel()));
connect(_ui->spinBox_normalKSearch, SIGNAL(valueChanged(int)), this, SLOT(makeObsoleteCloudRenderingPanel()));
connect(_ui->doubleSpinBox_normalRadiusSearch, SIGNAL(valueChanged(double)), this, SLOT(makeObsoleteCloudRenderingPanel()));
connect(_ui->doubleSpinBox_ceilingFilterHeight_scan, SIGNAL(valueChanged(double)), this, SLOT(makeObsoleteCloudRenderingPanel()));
connect(_ui->doubleSpinBox_floorFilterHeight_scan, SIGNAL(valueChanged(double)), this, SLOT(makeObsoleteCloudRenderingPanel()));
connect(_ui->spinBox_normalKSearch_scan, SIGNAL(valueChanged(int)), this, SLOT(makeObsoleteCloudRenderingPanel()));
connect(_ui->doubleSpinBox_normalRadiusSearch_scan, SIGNAL(valueChanged(double)), this, SLOT(makeObsoleteCloudRenderingPanel()));
connect(_ui->checkBox_showGraphs, SIGNAL(stateChanged(int)), this, SLOT(makeObsoleteCloudRenderingPanel()));
connect(_ui->checkBox_showFrustums, SIGNAL(stateChanged(int)), this, SLOT(makeObsoleteCloudRenderingPanel()));
@@ -585,6 +587,7 @@ PreferencesDialog::PreferencesDialog(QWidget * parent) :
connect(_ui->doubleSpinBox_cameraSCanFromDepth_maxDepth, SIGNAL(valueChanged(double)), this, SLOT(makeObsoleteSourcePanel()));
connect(_ui->doubleSpinBox_cameraImages_scanVoxelSize, SIGNAL(valueChanged(double)), this, SLOT(makeObsoleteSourcePanel()));
connect(_ui->spinBox_cameraImages_scanNormalsK, SIGNAL(valueChanged(int)), this, SLOT(makeObsoleteSourcePanel()));
connect(_ui->doubleSpinBox_cameraImages_scanNormalsRadius, SIGNAL(valueChanged(double)), this, SLOT(makeObsoleteSourcePanel()));
//Rtabmap basic
connect(_ui->general_doubleSpinBox_timeThr, SIGNAL(valueChanged(double)), _ui->general_doubleSpinBox_timeThr_2, SLOT(setValue(double)));
@@ -650,6 +653,7 @@ PreferencesDialog::PreferencesDialog(QWidget * parent) :
_ui->spinBox_imagePostDecimation->setObjectName(Parameters::kMemImagePostDecimation().c_str());
_ui->general_spinBox_laserScanDownsample->setObjectName(Parameters::kMemLaserScanDownsampleStepSize().c_str());
_ui->general_spinBox_laserScanNormalK->setObjectName(Parameters::kMemLaserScanNormalK().c_str());
_ui->general_doubleSpinBox_laserScanNormalRadius->setObjectName(Parameters::kMemLaserScanNormalRadius().c_str());
_ui->checkBox_useOdomFeatures->setObjectName(Parameters::kMemUseOdomFeatures().c_str());
// Database
@@ -857,7 +861,8 @@ PreferencesDialog::PreferencesDialog(QWidget * parent) :
_ui->loopClosure_icpEpsilon->setObjectName(Parameters::kIcpEpsilon().c_str());
_ui->loopClosure_icpRatio->setObjectName(Parameters::kIcpCorrespondenceRatio().c_str());
_ui->loopClosure_icpPointToPlane->setObjectName(Parameters::kIcpPointToPlane().c_str());
_ui->loopClosure_icpPointToPlaneNormals->setObjectName(Parameters::kIcpPointToPlaneNormalNeighbors().c_str());
_ui->loopClosure_icpPointToPlaneNormals->setObjectName(Parameters::kIcpPointToPlaneK().c_str());
_ui->loopClosure_icpPointToPlaneNormalsRadius->setObjectName(Parameters::kIcpPointToPlaneRadius().c_str());
_ui->groupBox_libpointmatcher->setObjectName(Parameters::kIcpPM().c_str());
_ui->lineEdit_IcpPMConfigPath->setObjectName(Parameters::kIcpPMConfig().c_str());
@@ -1374,10 +1379,12 @@ void PreferencesDialog::resetSettings(QGroupBox * groupBox)
_ui->doubleSpinBox_ceilingFilterHeight->setValue(0);
_ui->doubleSpinBox_floorFilterHeight->setValue(0);
_ui->spinBox_normalKSearch->setValue(10);
_ui->doubleSpinBox_normalRadiusSearch->setValue(0.0);
_ui->doubleSpinBox_ceilingFilterHeight_scan->setValue(0);
_ui->doubleSpinBox_floorFilterHeight_scan->setValue(0);
_ui->spinBox_normalKSearch_scan->setValue(0);
_ui->doubleSpinBox_normalRadiusSearch_scan->setValue(0.0);
_ui->checkBox_showGraphs->setChecked(true);
_ui->checkBox_showFrustums->setChecked(false);
@@ -1542,6 +1549,7 @@ void PreferencesDialog::resetSettings(QGroupBox * groupBox)
_ui->doubleSpinBox_cameraSCanFromDepth_maxDepth->setValue(4.0);
_ui->doubleSpinBox_cameraImages_scanVoxelSize->setValue(0.025f);
_ui->spinBox_cameraImages_scanNormalsK->setValue(20);
_ui->doubleSpinBox_cameraImages_scanNormalsRadius->setValue(0.0);
_ui->groupBox_depthFromScan->setChecked(false);
_ui->groupBox_depthFromScan_fillHoles->setChecked(true);
@@ -1769,9 +1777,11 @@ void PreferencesDialog::readGuiSettings(const QString & filePath)
_ui->doubleSpinBox_ceilingFilterHeight->setValue(settings.value("cloudCeilingHeight", _ui->doubleSpinBox_ceilingFilterHeight->value()).toDouble());
_ui->doubleSpinBox_floorFilterHeight->setValue(settings.value("cloudFloorHeight", _ui->doubleSpinBox_floorFilterHeight->value()).toDouble());
_ui->spinBox_normalKSearch->setValue(settings.value("normalKSearch", _ui->spinBox_normalKSearch->value()).toInt());
_ui->doubleSpinBox_normalRadiusSearch->setValue(settings.value("normalRadiusSearch", _ui->doubleSpinBox_normalRadiusSearch->value()).toDouble());
_ui->doubleSpinBox_ceilingFilterHeight_scan->setValue(settings.value("scanCeilingHeight", _ui->doubleSpinBox_ceilingFilterHeight_scan->value()).toDouble());
_ui->doubleSpinBox_floorFilterHeight_scan->setValue(settings.value("scanFloorHeight", _ui->doubleSpinBox_floorFilterHeight_scan->value()).toDouble());
_ui->spinBox_normalKSearch_scan->setValue(settings.value("scanNormalKSearch", _ui->spinBox_normalKSearch_scan->value()).toInt());
_ui->doubleSpinBox_normalRadiusSearch_scan->setValue(settings.value("scanNormalRadiusSearch", _ui->doubleSpinBox_normalRadiusSearch_scan->value()).toDouble());
_ui->checkBox_showGraphs->setChecked(settings.value("showGraphs", _ui->checkBox_showGraphs->isChecked()).toBool());
_ui->checkBox_showFrustums->setChecked(settings.value("showFrustums", _ui->checkBox_showFrustums->isChecked()).toBool());
@@ -1933,6 +1943,7 @@ void PreferencesDialog::readCameraSettings(const QString & filePath)
_ui->doubleSpinBox_cameraSCanFromDepth_maxDepth->setValue(settings.value("maxDepth", _ui->doubleSpinBox_cameraSCanFromDepth_maxDepth->value()).toDouble());
_ui->doubleSpinBox_cameraImages_scanVoxelSize->setValue(settings.value("voxelSize", _ui->doubleSpinBox_cameraImages_scanVoxelSize->value()).toDouble());
_ui->spinBox_cameraImages_scanNormalsK->setValue(settings.value("normalsK", _ui->spinBox_cameraImages_scanNormalsK->value()).toInt());
_ui->doubleSpinBox_cameraImages_scanNormalsRadius->setValue(settings.value("normalsRadius", _ui->doubleSpinBox_cameraImages_scanNormalsRadius->value()).toDouble());
settings.endGroup();//ScanFromDepth
settings.beginGroup("DepthFromScan");
@@ -2155,9 +2166,11 @@ void PreferencesDialog::writeGuiSettings(const QString & filePath) const
settings.setValue("cloudCeilingHeight", _ui->doubleSpinBox_ceilingFilterHeight->value());
settings.setValue("cloudFloorHeight", _ui->doubleSpinBox_floorFilterHeight->value());
settings.setValue("normalKSearch", _ui->spinBox_normalKSearch->value());
settings.setValue("normalRadiusSearch", _ui->doubleSpinBox_normalRadiusSearch->value());
settings.setValue("scanCeilingHeight", _ui->doubleSpinBox_ceilingFilterHeight_scan->value());
settings.setValue("scanFloorHeight", _ui->doubleSpinBox_floorFilterHeight_scan->value());
settings.setValue("scanNormalKSearch", _ui->spinBox_normalKSearch_scan->value());
settings.setValue("scanNormalRadiusSearch", _ui->doubleSpinBox_normalRadiusSearch_scan->value());
settings.setValue("showGraphs", _ui->checkBox_showGraphs->isChecked());
settings.setValue("showFrustums", _ui->checkBox_showFrustums->isChecked());
@@ -2321,6 +2334,7 @@ void PreferencesDialog::writeCameraSettings(const QString & filePath) const
settings.setValue("maxDepth", _ui->doubleSpinBox_cameraSCanFromDepth_maxDepth->value());
settings.setValue("voxelSize", _ui->doubleSpinBox_cameraImages_scanVoxelSize->value());
settings.setValue("normalsK", _ui->spinBox_cameraImages_scanNormalsK->value());
settings.setValue("normalsRadius", _ui->doubleSpinBox_cameraImages_scanNormalsRadius->value());
settings.endGroup();
settings.beginGroup("DepthFromScan");
@@ -4286,6 +4300,10 @@ int PreferencesDialog::getNormalKSearch() const
{
return _ui->spinBox_normalKSearch->value();
}
double PreferencesDialog::getNormalRadiusSearch() const
{
return _ui->doubleSpinBox_normalRadiusSearch->value();
}
double PreferencesDialog::getScanCeilingFilteringHeight() const
{
return _ui->doubleSpinBox_ceilingFilterHeight_scan->value();
@@ -4298,6 +4316,10 @@ int PreferencesDialog::getScanNormalKSearch() const
{
return _ui->spinBox_normalKSearch_scan->value();
}
double PreferencesDialog::getScanNormalRadiusSearch() const
{
return _ui->doubleSpinBox_normalRadiusSearch_scan->value();
}
bool PreferencesDialog::isGraphsShown() const
{
@@ -4636,6 +4658,10 @@ int PreferencesDialog::getSourceScanNormalsK() const
{
return _ui->spinBox_cameraImages_scanNormalsK->value();
}
double PreferencesDialog::getSourceScanNormalsRadius() const
{
return _ui->doubleSpinBox_cameraImages_scanNormalsRadius->value();
}
Camera * PreferencesDialog::createCamera(bool useRawImages, bool useColor)
{
@@ -4743,6 +4769,7 @@ Camera * PreferencesDialog::createCamera(bool useRawImages, bool useColor)
_ui->spinBox_cameraImages_scanDownsampleStep->value(),
_ui->doubleSpinBox_cameraImages_scanVoxelSize->value(),
_ui->spinBox_cameraImages_scanNormalsK->value(),
_ui->doubleSpinBox_cameraImages_scanNormalsRadius->value(),
this->getLaserLocalTransform());
((CameraRGBDImages*)camera)->setTimestamps(
_ui->checkBox_cameraImages_timestamps->isChecked(),
@@ -4788,6 +4815,7 @@ Camera * PreferencesDialog::createCamera(bool useRawImages, bool useColor)
_ui->spinBox_cameraImages_scanDownsampleStep->value(),
_ui->doubleSpinBox_cameraImages_scanVoxelSize->value(),
_ui->spinBox_cameraImages_scanNormalsK->value(),
_ui->doubleSpinBox_cameraImages_scanNormalsRadius->value(),
this->getLaserLocalTransform());
((CameraStereoImages*)camera)->setTimestamps(
_ui->checkBox_cameraImages_timestamps->isChecked(),
@@ -4893,6 +4921,7 @@ Camera * PreferencesDialog::createCamera(bool useRawImages, bool useColor)
_ui->spinBox_cameraImages_scanDownsampleStep->value(),
_ui->doubleSpinBox_cameraImages_scanVoxelSize->value(),
_ui->spinBox_cameraImages_scanNormalsK->value(),
_ui->doubleSpinBox_cameraImages_scanNormalsRadius->value(),
this->getLaserLocalTransform());
((CameraImages*)camera)->setDepthFromScan(
_ui->groupBox_depthFromScan->isChecked(),
@@ -5138,7 +5167,8 @@ void PreferencesDialog::testOdometry()
_ui->spinBox_cameraScanFromDepth_decimation->value(),
_ui->doubleSpinBox_cameraSCanFromDepth_maxDepth->value(),
_ui->doubleSpinBox_cameraImages_scanVoxelSize->value(),
_ui->spinBox_cameraImages_scanNormalsK->value());
_ui->spinBox_cameraImages_scanNormalsK->value(),
_ui->doubleSpinBox_cameraImages_scanNormalsRadius->value());
if(isDepthFilteringAvailable())
{
if(_ui->groupBox_bilateral->isChecked())
@@ -5186,7 +5216,8 @@ void PreferencesDialog::testCamera()
_ui->spinBox_cameraScanFromDepth_decimation->value(),
_ui->doubleSpinBox_cameraSCanFromDepth_maxDepth->value(),
_ui->doubleSpinBox_cameraImages_scanVoxelSize->value(),
_ui->spinBox_cameraImages_scanNormalsK->value());
_ui->spinBox_cameraImages_scanNormalsK->value(),
_ui->doubleSpinBox_cameraImages_scanNormalsRadius->value());
if(isDepthFilteringAvailable())
{
if(_ui->groupBox_bilateral->isChecked())

View File

@@ -23,9 +23,9 @@
<property name="geometry">
<rect>
<x>0</x>
<y>-2684</y>
<width>773</width>
<height>4103</height>
<y>0</y>
<width>778</width>
<height>4058</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_13">
@@ -52,21 +52,21 @@
</property>
</widget>
</item>
<item row="8" column="0">
<item row="9" column="0">
<widget class="QCheckBox" name="checkBox_regenerate">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="9" column="0">
<item row="10" column="0">
<widget class="QCheckBox" name="checkBox_filtering">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="8" column="1">
<item row="9" column="1">
<widget class="QLabel" name="label_regenerate">
<property name="text">
<string>Regenerate clouds. This can be used to regenerate the point clouds at higher density than those used for online visualization.</string>
@@ -76,7 +76,14 @@
</property>
</widget>
</item>
<item row="7" column="1">
<item row="12" column="0">
<widget class="QCheckBox" name="checkBox_gainCompensation">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="8" column="1">
<widget class="QLabel" name="label_voxel">
<property name="text">
<string>Voxel size. Set 0 to disable. When organized meshes are assembled, this is the radius in which the vertices of the polygons are merged.</string>
@@ -86,13 +93,6 @@
</property>
</widget>
</item>
<item row="11" column="0">
<widget class="QCheckBox" name="checkBox_gainCompensation">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QLabel" name="label_binaryFile_2">
<property name="text">
@@ -103,7 +103,7 @@
</property>
</widget>
</item>
<item row="11" column="1">
<item row="12" column="1">
<widget class="QLabel" name="label_gainCompensation">
<property name="text">
<string>Gain compensation. Normalize brightness of images.</string>
@@ -133,7 +133,7 @@
</property>
</widget>
</item>
<item row="12" column="1">
<item row="13" column="1">
<widget class="QLabel" name="label_binaryFile_12">
<property name="text">
<string>Meshing.</string>
@@ -143,7 +143,14 @@
</property>
</widget>
</item>
<item row="9" column="1">
<item row="11" column="0">
<widget class="QCheckBox" name="checkBox_smoothing">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="10" column="1">
<widget class="QLabel" name="label_binaryFile_9">
<property name="text">
<string>Cloud filtering. Remove sparse points that are far from surfaces.</string>
@@ -153,8 +160,8 @@
</property>
</widget>
</item>
<item row="10" column="0">
<widget class="QCheckBox" name="checkBox_smoothing">
<item row="13" column="0">
<widget class="QCheckBox" name="checkBox_meshing">
<property name="text">
<string/>
</property>
@@ -170,14 +177,7 @@
</property>
</widget>
</item>
<item row="12" column="0">
<widget class="QCheckBox" name="checkBox_meshing">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="10" column="1">
<item row="11" column="1">
<widget class="QLabel" name="label_binaryFile_10">
<property name="text">
<string>Cloud smoothing using Moving Least Squares algorithm (MLS).</string>
@@ -187,7 +187,7 @@
</property>
</widget>
</item>
<item row="7" column="0">
<item row="8" column="0">
<widget class="QDoubleSpinBox" name="doubleSpinBox_voxelSize_assembled">
<property name="suffix">
<string> m</string>
@@ -206,6 +206,13 @@
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QCheckBox" name="checkBox_assemble">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="6" column="1">
<widget class="QLabel" name="label_normal">
<property name="text">
@@ -216,23 +223,6 @@
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QCheckBox" name="checkBox_binary">
<property name="text">
<string/>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QCheckBox" name="checkBox_assemble">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QComboBox" name="comboBox_frame">
<item>
@@ -257,6 +247,16 @@
</item>
</widget>
</item>
<item row="3" column="0">
<widget class="QCheckBox" name="checkBox_binary">
<property name="text">
<string/>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLabel" name="label_binaryFile_11">
<property name="text">
@@ -277,6 +277,23 @@
</property>
</widget>
</item>
<item row="7" column="1">
<widget class="QLabel" name="label_normal_2">
<property name="text">
<string>Set the search radius for the normal estimation.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item row="7" column="0">
<widget class="QDoubleSpinBox" name="doubleSpinBox_normalRadiusSearch">
<property name="singleStep">
<double>0.010000000000000</double>
</property>
</widget>
</item>
</layout>
</item>
<item>

View File

@@ -63,7 +63,7 @@
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<y>-831</y>
<width>678</width>
<height>2739</height>
</rect>
@@ -95,7 +95,7 @@
<enum>QFrame::Raised</enum>
</property>
<property name="currentIndex">
<number>21</number>
<number>1</number>
</property>
<widget class="QWidget" name="page_22">
<layout class="QVBoxLayout" name="verticalLayout_29" stretch="0,1">
@@ -512,6 +512,31 @@ Show a yellow background when the number of odometry inliers goes under this thr
<layout class="QVBoxLayout" name="verticalLayout_112">
<item>
<layout class="QGridLayout" name="gridLayout_2" columnstretch="0,0,1">
<item row="3" column="1">
<widget class="QDoubleSpinBox" name="doubleSpinBox_maxDepth_odom">
<property name="suffix">
<string> m</string>
</property>
<property name="decimals">
<number>1</number>
</property>
<property name="maximum">
<double>100.000000000000000</double>
</property>
<property name="singleStep">
<double>0.100000000000000</double>
</property>
<property name="value">
<double>0.000000000000000</double>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="QLineEdit" name="lineEdit_roiRatios_odom"/>
</item>
<item row="5" column="0">
<widget class="QLineEdit" name="lineEdit_roiRatios"/>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label_154">
<property name="text">
@@ -597,7 +622,7 @@ Show a yellow background when the number of odometry inliers goes under this thr
</property>
</widget>
</item>
<item row="12" column="0">
<item row="13" column="0">
<widget class="QDoubleSpinBox" name="doubleSpinBox_opacity">
<property name="suffix">
<string/>
@@ -616,7 +641,7 @@ Show a yellow background when the number of odometry inliers goes under this thr
</property>
</widget>
</item>
<item row="12" column="1">
<item row="13" column="1">
<widget class="QDoubleSpinBox" name="doubleSpinBox_opacity_odom">
<property name="suffix">
<string/>
@@ -635,7 +660,7 @@ Show a yellow background when the number of odometry inliers goes under this thr
</property>
</widget>
</item>
<item row="12" column="2">
<item row="13" column="2">
<widget class="QLabel" name="label_155">
<property name="text">
<string>Opacity.</string>
@@ -648,7 +673,7 @@ Show a yellow background when the number of odometry inliers goes under this thr
</property>
</widget>
</item>
<item row="13" column="2">
<item row="14" column="2">
<widget class="QLabel" name="label_157">
<property name="text">
<string>Point size (1..64).</string>
@@ -712,25 +737,6 @@ Show a yellow background when the number of odometry inliers goes under this thr
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QDoubleSpinBox" name="doubleSpinBox_maxDepth_odom">
<property name="suffix">
<string> m</string>
</property>
<property name="decimals">
<number>1</number>
</property>
<property name="maximum">
<double>100.000000000000000</double>
</property>
<property name="singleStep">
<double>0.100000000000000</double>
</property>
<property name="value">
<double>0.000000000000000</double>
</property>
</widget>
</item>
<item row="3" column="2">
<widget class="QLabel" name="label_132">
<property name="text">
@@ -798,12 +804,6 @@ Show a yellow background when the number of odometry inliers goes under this thr
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QLineEdit" name="lineEdit_roiRatios"/>
</item>
<item row="5" column="1">
<widget class="QLineEdit" name="lineEdit_roiRatios_odom"/>
</item>
<item row="5" column="2">
<widget class="QLabel" name="label_353">
<property name="text">
@@ -858,7 +858,7 @@ Show a yellow background when the number of odometry inliers goes under this thr
</property>
</widget>
</item>
<item row="13" column="0">
<item row="14" column="0">
<widget class="QSpinBox" name="spinBox_ptsize">
<property name="minimum">
<number>1</number>
@@ -871,7 +871,7 @@ Show a yellow background when the number of odometry inliers goes under this thr
</property>
</widget>
</item>
<item row="13" column="1">
<item row="14" column="1">
<widget class="QSpinBox" name="spinBox_ptsize_odom">
<property name="minimum">
<number>1</number>
@@ -1010,6 +1010,26 @@ Show a yellow background when the number of odometry inliers goes under this thr
</property>
</widget>
</item>
<item row="12" column="2">
<widget class="QLabel" name="label_427">
<property name="text">
<string>Normal radius 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="12" column="0">
<widget class="QDoubleSpinBox" name="doubleSpinBox_normalRadiusSearch">
<property name="singleStep">
<double>0.010000000000000</double>
</property>
</widget>
</item>
</layout>
</item>
<item>
@@ -1117,7 +1137,7 @@ Show a yellow background when the number of odometry inliers goes under this thr
<string>Laser Scan</string>
</property>
<layout class="QGridLayout" name="gridLayout_79" columnstretch="0,0,1">
<item row="8" column="1">
<item row="9" column="1">
<widget class="QSpinBox" name="spinBox_ptsize_odom_scan">
<property name="minimum">
<number>1</number>
@@ -1127,7 +1147,7 @@ Show a yellow background when the number of odometry inliers goes under this thr
</property>
</widget>
</item>
<item row="8" column="2">
<item row="9" column="2">
<widget class="QLabel" name="label_158">
<property name="text">
<string>Scan point size (1..64).</string>
@@ -1169,7 +1189,7 @@ Show a yellow background when the number of odometry inliers goes under this thr
</property>
</widget>
</item>
<item row="7" column="2">
<item row="8" column="2">
<widget class="QLabel" name="label_156">
<property name="text">
<string>Scan opacity.</string>
@@ -1195,7 +1215,7 @@ Show a yellow background when the number of odometry inliers goes under this thr
</property>
</widget>
</item>
<item row="8" column="0">
<item row="9" column="0">
<widget class="QSpinBox" name="spinBox_ptsize_scan">
<property name="minimum">
<number>1</number>
@@ -1235,7 +1255,7 @@ Show a yellow background when the number of odometry inliers goes under this thr
</property>
</widget>
</item>
<item row="7" column="0">
<item row="8" column="0">
<widget class="QDoubleSpinBox" name="doubleSpinBox_opacity_scan">
<property name="suffix">
<string/>
@@ -1267,7 +1287,7 @@ Show a yellow background when the number of odometry inliers goes under this thr
</property>
</widget>
</item>
<item row="7" column="1">
<item row="8" column="1">
<widget class="QDoubleSpinBox" name="doubleSpinBox_opacity_odom_scan">
<property name="suffix">
<string/>
@@ -1440,6 +1460,26 @@ Show a yellow background when the number of odometry inliers goes under this thr
</property>
</widget>
</item>
<item row="7" column="2">
<widget class="QLabel" name="label_428">
<property name="text">
<string>Normal radius 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="7" column="0">
<widget class="QDoubleSpinBox" name="doubleSpinBox_normalRadiusSearch_scan">
<property name="singleStep">
<double>0.010000000000000</double>
</property>
</widget>
</item>
</layout>
</widget>
</item>
@@ -5283,6 +5323,29 @@ when using the file type, logs are saved in LogRtabmap.txt (located in the worki
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QLabel" name="label_425">
<property name="text">
<string>Search radius for normals computation (0=disabled). Useful if the ICP registration approach is point to plane.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QDoubleSpinBox" name="doubleSpinBox_cameraImages_scanNormalsRadius">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;KITTI: 130 000 points&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="singleStep">
<double>0.010000000000000</double>
</property>
</widget>
</item>
</layout>
</item>
</layout>
@@ -5995,6 +6058,16 @@ If set to false, classic RTAB-Map loop closure detection is done using only imag
<layout class="QVBoxLayout" name="verticalLayout_10">
<item>
<layout class="QGridLayout" name="gridLayout_42" columnstretch="0,1">
<item row="15" column="0">
<widget class="QSpinBox" name="spinBox_imagePostDecimation">
<property name="minimum">
<number>-16</number>
</property>
<property name="maximum">
<number>16</number>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QSpinBox" name="general_spinBox_maxStMemSize">
<property name="minimum">
@@ -6066,19 +6139,6 @@ If set to false, classic RTAB-Map loop closure detection is done using only imag
</property>
</widget>
</item>
<item row="6" column="1">
<widget class="QLabel" name="label_retrieved_3">
<property name="text">
<string>Bad signatures are ignored.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item row="8" column="0">
<widget class="QCheckBox" name="general_checkBox_initWMWithAllNodes">
<property name="text">
@@ -6089,10 +6149,10 @@ If set to false, classic RTAB-Map loop closure detection is done using only imag
</property>
</widget>
</item>
<item row="9" column="1">
<widget class="QLabel" name="label_retrieved_5">
<item row="6" column="1">
<widget class="QLabel" name="label_retrieved_3">
<property name="text">
<string>Keep raw sensor data. Only useful to save loop closure computation time when features re-extraction is enabled. Disable to save RAM memory.</string>
<string>Bad signatures are ignored.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
@@ -6122,10 +6182,10 @@ If set to false, classic RTAB-Map loop closure detection is done using only imag
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="QLabel" name="label_retrieved_11">
<item row="9" column="1">
<widget class="QLabel" name="label_retrieved_5">
<property name="text">
<string>Create map labels. The first node of a map will be labelled as &quot;map#&quot; where # is the map ID.</string>
<string>Keep raw sensor data. Only useful to save loop closure computation time when features re-extraction is enabled. Disable to save RAM memory.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
@@ -6145,6 +6205,19 @@ If set to false, classic RTAB-Map loop closure detection is done using only imag
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="QLabel" name="label_retrieved_11">
<property name="text">
<string>Create map labels. The first node of a map will be labelled as &quot;map#&quot; where # is the map ID.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item row="16" column="0">
<widget class="QSpinBox" name="general_spinBox_laserScanDownsample">
<property name="minimumSize">
@@ -6161,6 +6234,16 @@ If set to false, classic RTAB-Map loop closure detection is done using only imag
</property>
</widget>
</item>
<item row="11" column="0">
<widget class="QCheckBox" name="general_checkBox_keepDescriptors">
<property name="text">
<string/>
</property>
<property name="checked">
<bool>false</bool>
</property>
</widget>
</item>
<item row="11" column="1">
<widget class="QLabel" name="label_retrieved_12">
<property name="text">
@@ -6174,16 +6257,6 @@ If set to false, classic RTAB-Map loop closure detection is done using only imag
</property>
</widget>
</item>
<item row="11" column="0">
<widget class="QCheckBox" name="general_checkBox_keepDescriptors">
<property name="text">
<string/>
</property>
<property name="checked">
<bool>false</bool>
</property>
</widget>
</item>
<item row="14" column="1">
<widget class="QLabel" name="label_retrieved_13">
<property name="text">
@@ -6256,13 +6329,13 @@ If set to false, classic RTAB-Map loop closure detection is done using only imag
</property>
</widget>
</item>
<item row="15" column="0">
<widget class="QSpinBox" name="spinBox_imagePostDecimation">
<property name="minimum">
<number>-16</number>
<item row="6" column="0">
<widget class="QCheckBox" name="general_checkBox_badSignaturesIgnored">
<property name="text">
<string/>
</property>
<property name="maximum">
<number>16</number>
<property name="checked">
<bool>false</bool>
</property>
</widget>
</item>
@@ -6292,16 +6365,6 @@ If set to false, classic RTAB-Map loop closure detection is done using only imag
</property>
</widget>
</item>
<item row="6" column="0">
<widget class="QCheckBox" name="general_checkBox_badSignaturesIgnored">
<property name="text">
<string/>
</property>
<property name="checked">
<bool>false</bool>
</property>
</widget>
</item>
<item row="15" column="1">
<widget class="QLabel" name="label_retrieved_6">
<property name="text">
@@ -6315,6 +6378,16 @@ If set to false, classic RTAB-Map loop closure detection is done using only imag
</property>
</widget>
</item>
<item row="12" column="0">
<widget class="QCheckBox" name="general_checkBox_saveDepth16bits">
<property name="text">
<string/>
</property>
<property name="checked">
<bool>false</bool>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QLabel" name="label_retrieved_7">
<property name="text">
@@ -6341,16 +6414,6 @@ If set to false, classic RTAB-Map loop closure detection is done using only imag
</property>
</widget>
</item>
<item row="12" column="0">
<widget class="QCheckBox" name="general_checkBox_saveDepth16bits">
<property name="text">
<string/>
</property>
<property name="checked">
<bool>false</bool>
</property>
</widget>
</item>
<item row="14" column="0">
<widget class="QSpinBox" name="spinBox_imagePreDecimation">
<property name="minimum">
@@ -6380,10 +6443,20 @@ If set to false, classic RTAB-Map loop closure detection is done using only imag
</property>
</widget>
</item>
<item row="13" column="0">
<widget class="QCheckBox" name="general_checkBox_compressionParallelized">
<property name="text">
<string/>
</property>
<property name="checked">
<bool>false</bool>
</property>
</widget>
</item>
<item row="17" column="1">
<widget class="QLabel" name="label_retrieved_14">
<property name="text">
<string>If &gt; 0 and laser scans are 3D without normals, normals will be computed with K search neighbors when creating a signature.</string>
<string>If &gt; 0 and laser scans don't have normals, normals will be computed with K search neighbors when creating a signature.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
@@ -6406,8 +6479,8 @@ If set to false, classic RTAB-Map loop closure detection is done using only imag
</property>
</widget>
</item>
<item row="13" column="0">
<widget class="QCheckBox" name="general_checkBox_compressionParallelized">
<item row="10" column="0">
<widget class="QCheckBox" name="general_checkBox_saveIntermediateNodeData">
<property name="text">
<string/>
</property>
@@ -6429,13 +6502,29 @@ If set to false, classic RTAB-Map loop closure detection is done using only imag
</property>
</widget>
</item>
<item row="10" column="0">
<widget class="QCheckBox" name="general_checkBox_saveIntermediateNodeData">
<item row="18" column="1">
<widget class="QLabel" name="label_retrieved_17">
<property name="text">
<string/>
<string>If &gt; 0 and laser scans don't have normals, normals will be computed with radius search when creating a signature.</string>
</property>
<property name="checked">
<bool>false</bool>
<property name="wordWrap">
<bool>true</bool>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item row="18" column="0">
<widget class="QDoubleSpinBox" name="general_doubleSpinBox_laserScanNormalRadius">
<property name="minimumSize">
<size>
<width>50</width>
<height>0</height>
</size>
</property>
<property name="singleStep">
<double>0.010000000000000</double>
</property>
</widget>
</item>
@@ -13764,6 +13853,26 @@ Lower the ratio -&gt; higher the precision. 0 means disabled, matching the neare
</property>
</widget>
</item>
<item row="10" column="1">
<widget class="QLabel" name="label_426">
<property name="text">
<string>Search radius to compute normals for point to plane. Normals won't be recomputed if uniform sampling is disabled and that there are already normals in the laser scans.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item row="10" column="0">
<widget class="QDoubleSpinBox" name="loopClosure_icpPointToPlaneNormalsRadius">
<property name="singleStep">
<double>0.010000000000000</double>
</property>
</widget>
</item>
</layout>
</item>
<item>