0.11.2: First Google Tango release

This commit is contained in:
matlabbe
2016-02-15 19:35:24 -05:00
parent 8dc01c491b
commit c6a46a7238
415 changed files with 73300 additions and 3193 deletions

View File

@@ -146,12 +146,12 @@ void CameraViewer::showImage(const rtabmap::SensorData & data)
if(!data.imageRaw().empty() && !data.depthOrRightRaw().empty())
{
showCloudCheckbox_->setEnabled(true);
cloudView_->addOrUpdateCloud("cloud", util3d::cloudRGBFromSensorData(data, validDecimationValue_));
cloudView_->addCloud("cloud", util3d::cloudRGBFromSensorData(data, validDecimationValue_));
}
else if(!data.depthOrRightRaw().empty())
{
showCloudCheckbox_->setEnabled(true);
cloudView_->addOrUpdateCloud("cloud", util3d::cloudFromSensorData(data, validDecimationValue_));
cloudView_->addCloud("cloud", util3d::cloudFromSensorData(data, validDecimationValue_));
}
}
}
@@ -161,7 +161,7 @@ void CameraViewer::showImage(const rtabmap::SensorData & data)
showScanCheckbox_->setEnabled(true);
if(showScanCheckbox_->isChecked())
{
cloudView_->addOrUpdateCloud("scan", util3d::downsample(util3d::laserScanToPointCloud(data.laserScanRaw()), validDecimationValue_), Transform::getIdentity(), Qt::yellow);
cloudView_->addCloud("scan", util3d::downsample(util3d::laserScanToPointCloud(data.laserScanRaw()), validDecimationValue_), Transform::getIdentity(), Qt::yellow);
}
}

View File

@@ -113,7 +113,9 @@ CloudViewer::CloudViewer(QWidget *parent) :
_lastCameraPose(0,0,0),
_workingDirectory("."),
_defaultBgColor(Qt::black),
_currentBgColor(Qt::black)
_currentBgColor(Qt::black),
_backfaceCulling(false),
_frontfaceCulling(false)
{
this->setMinimumSize(200, 200);
@@ -317,138 +319,6 @@ bool CloudViewer::updateCloudPose(
return false;
}
bool CloudViewer::updateCloud(
const std::string & id,
const pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr & cloud,
const Transform & pose,
const QColor & color)
{
if(_addedClouds.contains(id))
{
UDEBUG("Updating %s with %d points", id.c_str(), (int)cloud->size());
int index = _visualizer->getColorHandlerIndex(id);
this->removeCloud(id);
if(this->addCloud(id, cloud, pose, color))
{
_visualizer->updateColorHandlerIndex(id, index);
return true;
}
}
return false;
}
bool CloudViewer::updateCloud(
const std::string & id,
const pcl::PointCloud<pcl::PointXYZRGB>::Ptr & cloud,
const Transform & pose,
const QColor & color)
{
if(_addedClouds.contains(id))
{
UDEBUG("Updating %s with %d points", id.c_str(), (int)cloud->size());
int index = _visualizer->getColorHandlerIndex(id);
this->removeCloud(id);
if(this->addCloud(id, cloud, pose, color))
{
_visualizer->updateColorHandlerIndex(id, index);
return true;
}
}
return false;
}
bool CloudViewer::updateCloud(
const std::string & id,
const pcl::PointCloud<pcl::PointNormal>::Ptr & cloud,
const Transform & pose,
const QColor & color)
{
if(_addedClouds.contains(id))
{
UDEBUG("Updating %s with %d points", id.c_str(), (int)cloud->size());
int index = _visualizer->getColorHandlerIndex(id);
this->removeCloud(id);
if(this->addCloud(id, cloud, pose, color))
{
_visualizer->updateColorHandlerIndex(id, index);
return true;
}
}
return false;
}
bool CloudViewer::updateCloud(
const std::string & id,
const pcl::PointCloud<pcl::PointXYZ>::Ptr & cloud,
const Transform & pose,
const QColor & color)
{
if(_addedClouds.contains(id))
{
UDEBUG("Updating %s with %d points", id.c_str(), (int)cloud->size());
int index = _visualizer->getColorHandlerIndex(id);
this->removeCloud(id);
if(this->addCloud(id, cloud, pose, color))
{
_visualizer->updateColorHandlerIndex(id, index);
return true;
}
}
return false;
}
bool CloudViewer::addOrUpdateCloud(
const std::string & id,
const pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr & cloud,
const Transform & pose,
const QColor & color)
{
if(!updateCloud(id, cloud, pose, color))
{
return addCloud(id, cloud, pose, color);
}
return true;
}
bool CloudViewer::addOrUpdateCloud(
const std::string & id,
const pcl::PointCloud<pcl::PointXYZRGB>::Ptr & cloud,
const Transform & pose,
const QColor & color)
{
if(!updateCloud(id, cloud, pose, color))
{
return addCloud(id, cloud, pose, color);
}
return true;
}
bool CloudViewer::addOrUpdateCloud(
const std::string & id,
const pcl::PointCloud<pcl::PointNormal>::Ptr & cloud,
const Transform & pose,
const QColor & color)
{
if(!updateCloud(id, cloud, pose, color))
{
return addCloud(id, cloud, pose, color);
}
return true;
}
bool CloudViewer::addOrUpdateCloud(
const std::string & id,
const pcl::PointCloud<pcl::PointXYZ>::Ptr & cloud,
const Transform & pose,
const QColor & color)
{
if(!updateCloud(id, cloud, pose, color))
{
return addCloud(id, cloud, pose, color);
}
return true;
}
bool CloudViewer::addCloud(
const std::string & id,
const pcl::PCLPointCloud2Ptr & binaryCloud,
@@ -457,62 +327,78 @@ bool CloudViewer::addCloud(
bool haveNormals,
const QColor & color)
{
if(!_addedClouds.contains(id))
int previousColorIndex = -1;
if(_addedClouds.contains(id))
{
Eigen::Vector4f origin(pose.x(), pose.y(), pose.z(), 0.0f);
Eigen::Quaternionf orientation = Eigen::Quaternionf(pose.toEigen3f().rotation());
previousColorIndex = _visualizer->getColorHandlerIndex(id);
this->removeCloud(id);
}
// add random color channel
pcl::visualization::PointCloudColorHandler<pcl::PCLPointCloud2>::Ptr colorHandler;
colorHandler.reset (new pcl::visualization::PointCloudColorHandlerRandom<pcl::PCLPointCloud2> (binaryCloud));
if(_visualizer->addPointCloud (binaryCloud, colorHandler, origin, orientation, id))
Eigen::Vector4f origin(pose.x(), pose.y(), pose.z(), 0.0f);
Eigen::Quaternionf orientation = Eigen::Quaternionf(pose.toEigen3f().rotation());
// add random color channel
pcl::visualization::PointCloudColorHandler<pcl::PCLPointCloud2>::Ptr colorHandler;
colorHandler.reset (new pcl::visualization::PointCloudColorHandlerRandom<pcl::PCLPointCloud2> (binaryCloud));
if(_visualizer->addPointCloud (binaryCloud, colorHandler, origin, orientation, id))
{
QColor c = Qt::gray;
if(color.isValid())
{
QColor c = Qt::gray;
if(color.isValid())
{
c = color;
}
colorHandler.reset (new pcl::visualization::PointCloudColorHandlerCustom<pcl::PCLPointCloud2> (binaryCloud, c.red(), c.green(), c.blue()));
_visualizer->addPointCloud (binaryCloud, colorHandler, origin, orientation, id);
// x,y,z
colorHandler.reset (new pcl::visualization::PointCloudColorHandlerGenericField<pcl::PCLPointCloud2> (binaryCloud, "x"));
_visualizer->addPointCloud (binaryCloud, colorHandler, origin, orientation, id);
colorHandler.reset (new pcl::visualization::PointCloudColorHandlerGenericField<pcl::PCLPointCloud2> (binaryCloud, "y"));
_visualizer->addPointCloud (binaryCloud, colorHandler, origin, orientation, id);
colorHandler.reset (new pcl::visualization::PointCloudColorHandlerGenericField<pcl::PCLPointCloud2> (binaryCloud, "z"));
_visualizer->addPointCloud (binaryCloud, colorHandler, origin, orientation, id);
if(rgb)
{
//rgb
colorHandler.reset(new pcl::visualization::PointCloudColorHandlerRGBField<pcl::PCLPointCloud2>(binaryCloud));
_visualizer->addPointCloud (binaryCloud, colorHandler, origin, orientation, id);
}
if(haveNormals)
{
//normals
colorHandler.reset (new pcl::visualization::PointCloudColorHandlerGenericField<pcl::PCLPointCloud2> (binaryCloud, "normal_x"));
_visualizer->addPointCloud (binaryCloud, colorHandler, origin, orientation, id);
colorHandler.reset (new pcl::visualization::PointCloudColorHandlerGenericField<pcl::PCLPointCloud2> (binaryCloud, "normal_y"));
_visualizer->addPointCloud (binaryCloud, colorHandler, origin, orientation, id);
colorHandler.reset (new pcl::visualization::PointCloudColorHandlerGenericField<pcl::PCLPointCloud2> (binaryCloud, "normal_z"));
_visualizer->addPointCloud (binaryCloud, colorHandler, origin, orientation, id);
}
if(rgb)
{
_visualizer->updateColorHandlerIndex(id, 5);
}
else if(color.isValid())
{
_visualizer->updateColorHandlerIndex(id, 1);
}
_addedClouds.insert(id, pose);
return true;
c = color;
}
colorHandler.reset (new pcl::visualization::PointCloudColorHandlerCustom<pcl::PCLPointCloud2> (binaryCloud, c.red(), c.green(), c.blue()));
_visualizer->addPointCloud (binaryCloud, colorHandler, origin, orientation, id);
// x,y,z
colorHandler.reset (new pcl::visualization::PointCloudColorHandlerGenericField<pcl::PCLPointCloud2> (binaryCloud, "x"));
_visualizer->addPointCloud (binaryCloud, colorHandler, origin, orientation, id);
colorHandler.reset (new pcl::visualization::PointCloudColorHandlerGenericField<pcl::PCLPointCloud2> (binaryCloud, "y"));
_visualizer->addPointCloud (binaryCloud, colorHandler, origin, orientation, id);
colorHandler.reset (new pcl::visualization::PointCloudColorHandlerGenericField<pcl::PCLPointCloud2> (binaryCloud, "z"));
_visualizer->addPointCloud (binaryCloud, colorHandler, origin, orientation, id);
if(rgb)
{
//rgb
colorHandler.reset(new pcl::visualization::PointCloudColorHandlerRGBField<pcl::PCLPointCloud2>(binaryCloud));
_visualizer->addPointCloud (binaryCloud, colorHandler, origin, orientation, id);
}
else if(previousColorIndex == 5)
{
previousColorIndex = -1;
}
if(haveNormals)
{
//normals
colorHandler.reset (new pcl::visualization::PointCloudColorHandlerGenericField<pcl::PCLPointCloud2> (binaryCloud, "normal_x"));
_visualizer->addPointCloud (binaryCloud, colorHandler, origin, orientation, id);
colorHandler.reset (new pcl::visualization::PointCloudColorHandlerGenericField<pcl::PCLPointCloud2> (binaryCloud, "normal_y"));
_visualizer->addPointCloud (binaryCloud, colorHandler, origin, orientation, id);
colorHandler.reset (new pcl::visualization::PointCloudColorHandlerGenericField<pcl::PCLPointCloud2> (binaryCloud, "normal_z"));
_visualizer->addPointCloud (binaryCloud, colorHandler, origin, orientation, id);
}
else if(previousColorIndex > 5)
{
previousColorIndex = -1;
}
if(previousColorIndex>=0)
{
_visualizer->updateColorHandlerIndex(id, previousColorIndex);
}
else if(rgb)
{
_visualizer->updateColorHandlerIndex(id, 5);
}
else if(color.isValid())
{
_visualizer->updateColorHandlerIndex(id, 1);
}
_addedClouds.insert(id, pose);
return true;
}
return false;
}
@@ -523,15 +409,9 @@ bool CloudViewer::addCloud(
const Transform & pose,
const QColor & color)
{
if(!_addedClouds.contains(id))
{
UDEBUG("Adding %s with %d points", id.c_str(), (int)cloud->size());
pcl::PCLPointCloud2Ptr binaryCloud(new pcl::PCLPointCloud2);
pcl::toPCLPointCloud2(*cloud, *binaryCloud);
return addCloud(id, binaryCloud, pose, true, true, color);
}
return false;
pcl::PCLPointCloud2Ptr binaryCloud(new pcl::PCLPointCloud2);
pcl::toPCLPointCloud2(*cloud, *binaryCloud);
return addCloud(id, binaryCloud, pose, true, true, color);
}
bool CloudViewer::addCloud(
@@ -540,15 +420,9 @@ bool CloudViewer::addCloud(
const Transform & pose,
const QColor & color)
{
if(!_addedClouds.contains(id))
{
UDEBUG("Adding %s with %d points", id.c_str(), (int)cloud->size());
pcl::PCLPointCloud2Ptr binaryCloud(new pcl::PCLPointCloud2);
pcl::toPCLPointCloud2(*cloud, *binaryCloud);
return addCloud(id, binaryCloud, pose, true, false, color);
}
return false;
pcl::PCLPointCloud2Ptr binaryCloud(new pcl::PCLPointCloud2);
pcl::toPCLPointCloud2(*cloud, *binaryCloud);
return addCloud(id, binaryCloud, pose, true, false, color);
}
bool CloudViewer::addCloud(
@@ -557,15 +431,9 @@ bool CloudViewer::addCloud(
const Transform & pose,
const QColor & color)
{
if(!_addedClouds.contains(id))
{
UDEBUG("Adding %s with %d points", id.c_str(), (int)cloud->size());
pcl::PCLPointCloud2Ptr binaryCloud(new pcl::PCLPointCloud2);
pcl::toPCLPointCloud2(*cloud, *binaryCloud);
return addCloud(id, binaryCloud, pose, false, true, color);
}
return false;
pcl::PCLPointCloud2Ptr binaryCloud(new pcl::PCLPointCloud2);
pcl::toPCLPointCloud2(*cloud, *binaryCloud);
return addCloud(id, binaryCloud, pose, false, true, color);
}
bool CloudViewer::addCloud(
@@ -574,15 +442,9 @@ bool CloudViewer::addCloud(
const Transform & pose,
const QColor & color)
{
if(!_addedClouds.contains(id))
{
UDEBUG("Adding %s with %d points", id.c_str(), (int)cloud->size());
pcl::PCLPointCloud2Ptr binaryCloud(new pcl::PCLPointCloud2);
pcl::toPCLPointCloud2(*cloud, *binaryCloud);
return addCloud(id, binaryCloud, pose, false, false, color);
}
return false;
pcl::PCLPointCloud2Ptr binaryCloud(new pcl::PCLPointCloud2);
pcl::toPCLPointCloud2(*cloud, *binaryCloud);
return addCloud(id, binaryCloud, pose, false, false, color);
}
bool CloudViewer::addCloudMesh(
@@ -591,15 +453,26 @@ bool CloudViewer::addCloudMesh(
const std::vector<pcl::Vertices> & polygons,
const Transform & pose)
{
if(!_addedClouds.contains(id))
if(_addedClouds.contains(id))
{
UDEBUG("Adding %s with %d points and %d polygons", id.c_str(), (int)cloud->size(), (int)polygons.size());
if(_visualizer->addPolygonMesh<pcl::PointXYZ>(cloud, polygons, id))
this->removeCloud(id);
}
UDEBUG("Adding %s with %d points and %d polygons", id.c_str(), (int)cloud->size(), (int)polygons.size());
if(_visualizer->addPolygonMesh<pcl::PointXYZ>(cloud, polygons, id))
{
_visualizer->getCloudActorMap()->find(id)->second.actor->GetProperty()->LightingOff();
if(_backfaceCulling)
{
_visualizer->updatePointCloudPose(id, pose.toEigen3f());
_addedClouds.insert(id, pose);
return true;
_visualizer->getCloudActorMap()->find(id)->second.actor->GetProperty()->BackfaceCullingOn();
}
if(_frontfaceCulling)
{
_visualizer->getCloudActorMap()->find(id)->second.actor->GetProperty()->FrontfaceCullingOn();
}
_visualizer->updatePointCloudPose(id, pose.toEigen3f());
_addedClouds.insert(id, pose);
return true;
}
return false;
}
@@ -610,15 +483,56 @@ bool CloudViewer::addCloudMesh(
const std::vector<pcl::Vertices> & polygons,
const Transform & pose)
{
if(!_addedClouds.contains(id))
if(_addedClouds.contains(id))
{
UDEBUG("Adding %s with %d points and %d polygons", id.c_str(), (int)cloud->size(), (int)polygons.size());
if(_visualizer->addPolygonMesh<pcl::PointXYZRGB>(cloud, polygons, id))
this->removeCloud(id);
}
UDEBUG("Adding %s with %d points and %d polygons", id.c_str(), (int)cloud->size(), (int)polygons.size());
if(_visualizer->addPolygonMesh<pcl::PointXYZRGB>(cloud, polygons, id))
{
_visualizer->getCloudActorMap()->find(id)->second.actor->GetProperty()->LightingOff();
if(_backfaceCulling)
{
_visualizer->updatePointCloudPose(id, pose.toEigen3f());
_addedClouds.insert(id, pose);
return true;
_visualizer->getCloudActorMap()->find(id)->second.actor->GetProperty()->BackfaceCullingOn();
}
if(_frontfaceCulling)
{
_visualizer->getCloudActorMap()->find(id)->second.actor->GetProperty()->FrontfaceCullingOn();
}
_visualizer->updatePointCloudPose(id, pose.toEigen3f());
_addedClouds.insert(id, pose);
return true;
}
return false;
}
bool CloudViewer::addCloudMesh(
const std::string & id,
const pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr & cloud,
const std::vector<pcl::Vertices> & polygons,
const Transform & pose)
{
if(_addedClouds.contains(id))
{
this->removeCloud(id);
}
UDEBUG("Adding %s with %d points and %d polygons", id.c_str(), (int)cloud->size(), (int)polygons.size());
if(_visualizer->addPolygonMesh<pcl::PointXYZRGBNormal>(cloud, polygons, id))
{
_visualizer->getCloudActorMap()->find(id)->second.actor->GetProperty()->LightingOff();
if(_backfaceCulling)
{
_visualizer->getCloudActorMap()->find(id)->second.actor->GetProperty()->BackfaceCullingOn();
}
if(_frontfaceCulling)
{
_visualizer->getCloudActorMap()->find(id)->second.actor->GetProperty()->FrontfaceCullingOn();
}
_visualizer->updatePointCloudPose(id, pose.toEigen3f());
_addedClouds.insert(id, pose);
return true;
}
return false;
}
@@ -628,16 +542,28 @@ bool CloudViewer::addCloudMesh(
const pcl::PolygonMesh::Ptr & mesh,
const Transform & pose)
{
if(!_addedClouds.contains(id))
if(_addedClouds.contains(id))
{
UDEBUG("Adding %s with %d polygons", id.c_str(), (int)mesh->polygons.size());
if(_visualizer->addPolygonMesh(*mesh, id))
{
_visualizer->updatePointCloudPose(id, pose.toEigen3f());
_addedClouds.insert(id, pose);
return true;
}
this->removeCloud(id);
}
UDEBUG("Adding %s with %d polygons", id.c_str(), (int)mesh->polygons.size());
if(_visualizer->addPolygonMesh(*mesh, id))
{
_visualizer->getCloudActorMap()->find(id)->second.actor->GetProperty()->LightingOff();
if(_backfaceCulling)
{
_visualizer->getCloudActorMap()->find(id)->second.actor->GetProperty()->BackfaceCullingOn();
}
if(_frontfaceCulling)
{
_visualizer->getCloudActorMap()->find(id)->second.actor->GetProperty()->FrontfaceCullingOn();
}
_visualizer->updatePointCloudPose(id, pose.toEigen3f());
_addedClouds.insert(id, pose);
return true;
}
return false;
}
@@ -647,16 +573,19 @@ bool CloudViewer::addCloudTextureMesh(
const Transform & pose)
{
#if PCL_VERSION_COMPARE(>=, 1, 7, 2)
if(!_addedClouds.contains(id))
if(_addedClouds.contains(id))
{
UDEBUG("Adding %s", id.c_str());
if(_visualizer->addTextureMesh(*textureMesh, id))
{
_visualizer->updatePointCloudPose(id, pose.toEigen3f());
_addedClouds.insert(id, pose);
return true;
}
this->removeCloud(id);
}
UDEBUG("Adding %s", id.c_str());
if(_visualizer->addTextureMesh(*textureMesh, id))
{
_visualizer->updatePointCloudPose(id, pose.toEigen3f());
_addedClouds.insert(id, pose);
return true;
}
#endif
// not implemented on lower version of PCL
return false;
@@ -826,7 +755,7 @@ void CloudViewer::addOrUpdateGraph(
_visualizer->addPolylineFromPolygonMesh(mesh, id);
_visualizer->setShapeRenderingProperties(pcl::visualization::PCL_VISUALIZER_COLOR, color.redF(), color.greenF(), color.blueF(), id);
this->addOrUpdateCloud(id+"_nodes", graph, Transform::getIdentity(), color);
this->addCloud(id+"_nodes", graph, Transform::getIdentity(), color);
this->setCloudPointSize(id+"_nodes", 5);
}
}
@@ -1002,6 +931,12 @@ Transform CloudViewer::getTargetPose() const
return _lastPose;
}
void CloudViewer::setBackfaceCulling(bool enabled, bool frontfaceCulling)
{
_backfaceCulling = enabled;
_frontfaceCulling = frontfaceCulling;
}
void CloudViewer::getCameraPosition(
float & x, float & y, float & z,
float & focalX, float & focalY, float & focalZ,
@@ -1023,13 +958,7 @@ void CloudViewer::getCameraPosition(
}
else
{
_visualizer->setCameraPosition(
-1, 0, 0,
0, 0, 0,
0, 0, 1);
x=-1.0f;
y=z=focalX=focalY=focalZ=upX=upY=0;
upZ=1.0f;
UERROR("No camera set!?");
}
}
@@ -1341,9 +1270,12 @@ void CloudViewer::addGrid()
name = uFormat("line%d", ++id);
_visualizer->addLine(pcl::PointXYZ(i, min, 0.0f), pcl::PointXYZ(i, max, 0.0f), r, g, b, name);
_gridLines.push_back(name);
//over y
//over y or z
name = uFormat("line%d", ++id);
_visualizer->addLine(pcl::PointXYZ(min, i, 0.0f), pcl::PointXYZ(max, i, 0.0f), r, g, b, name);
_visualizer->addLine(
pcl::PointXYZ(min, i, 0),
pcl::PointXYZ(max, i, 0),
r, g, b, name);
_gridLines.push_back(name);
}
}

View File

@@ -194,6 +194,13 @@ DatabaseViewer::DatabaseViewer(const QString & ini, QWidget * parent) :
connect(ui_->horizontalSlider_A, SIGNAL(sliderMoved(int)), this, SLOT(sliderAMoved(int)));
connect(ui_->horizontalSlider_B, SIGNAL(sliderMoved(int)), this, SLOT(sliderBMoved(int)));
connect(ui_->spinBox_mesh_angleTolerance, SIGNAL(valueChanged(int)), this, SLOT(update3dView()));
connect(ui_->spinBox_mesh_fillDepthHoles, SIGNAL(valueChanged(int)), this, SLOT(update3dView()));
connect(ui_->spinBox_mesh_depthError, SIGNAL(valueChanged(int)), this, SLOT(update3dView()));
connect(ui_->checkBox_mesh_quad, SIGNAL(toggled(bool)), this, SLOT(update3dView()));
connect(ui_->spinBox_mesh_triangleSize, SIGNAL(valueChanged(int)), this, SLOT(update3dView()));
connect(ui_->checkBox_showMesh, SIGNAL(toggled(bool)), this, SLOT(update3dView()));
ui_->horizontalSlider_neighbors->setTracking(false);
ui_->horizontalSlider_loops->setTracking(false);
ui_->horizontalSlider_neighbors->setEnabled(false);
@@ -305,10 +312,12 @@ void DatabaseViewer::setupMainLayout(int vertical)
if(vertical)
{
qobject_cast<QHBoxLayout *>(ui_->horizontalLayout_imageViews->layout())->setDirection(QBoxLayout::TopToBottom);
qobject_cast<QHBoxLayout *>(ui_->horizontalLayout_3dviews->layout())->setDirection(QBoxLayout::TopToBottom);
}
else if(!vertical)
{
qobject_cast<QHBoxLayout *>(ui_->horizontalLayout_imageViews->layout())->setDirection(QBoxLayout::LeftToRight);
qobject_cast<QHBoxLayout *>(ui_->horizontalLayout_3dviews->layout())->setDirection(QBoxLayout::LeftToRight);
}
}
@@ -386,6 +395,14 @@ void DatabaseViewer::readSettings()
ui_->doubleSpinBox_posefilteringAngle->setValue(settings.value("poseFilteringAngle", ui_->doubleSpinBox_posefilteringAngle->value()).toDouble());
settings.endGroup();
settings.beginGroup("mesh");
ui_->checkBox_mesh_quad->setChecked(settings.value("quad", ui_->checkBox_mesh_quad->isChecked()).toBool());
ui_->spinBox_mesh_angleTolerance->setValue(settings.value("angleTolerance", ui_->spinBox_mesh_angleTolerance->value()).toInt());
ui_->spinBox_mesh_fillDepthHoles->setValue(settings.value("fillDepthHolesSize", ui_->spinBox_mesh_fillDepthHoles->value()).toInt());
ui_->spinBox_mesh_depthError->setValue(settings.value("fillDepthHolesError", ui_->spinBox_mesh_depthError->value()).toInt());
ui_->spinBox_mesh_triangleSize->setValue(settings.value("triangleSize", ui_->spinBox_mesh_triangleSize->value()).toInt());
settings.endGroup();
// ImageViews
//ui_->graphicsView_A->loadSettings(settings, "ImageViewA");
//ui_->graphicsView_B->loadSettings(settings, "ImageViewB");
@@ -464,6 +481,14 @@ void DatabaseViewer::writeSettings()
settings.setValue("poseFilteringAngle", ui_->doubleSpinBox_posefilteringAngle->value());
settings.endGroup();
settings.beginGroup("mesh");
settings.setValue("quad", ui_->checkBox_mesh_quad->isChecked());
settings.setValue("angleTolerance", ui_->spinBox_mesh_angleTolerance->value());
settings.setValue("fillDepthHolesSize", ui_->spinBox_mesh_fillDepthHoles->value());
settings.setValue("fillDepthHolesError", ui_->spinBox_mesh_depthError->value());
settings.setValue("triangleSize", ui_->spinBox_mesh_triangleSize->value());
settings.endGroup();
// ImageViews
//ui_->graphicsView_A->saveSettings(settings, "ImageViewA");
//ui_->graphicsView_B->saveSettings(settings, "ImageViewB");
@@ -2096,11 +2121,19 @@ void DatabaseViewer::update(int value,
data.uncompressData();
if(!data.imageRaw().empty())
{
img = uCvMat2QImage(data.imageRaw());
img = uCvMat2QImage(ui_->label_indexB==labelIndex?data.imageRaw():data.imageRaw());
}
if(!data.depthOrRightRaw().empty())
{
imgDepth = uCvMat2QImage(data.depthOrRightRaw());
cv::Mat depth =data.depthOrRightRaw();
if(!data.depthRaw().empty())
{
if(ui_->spinBox_mesh_fillDepthHoles->value() > 0)
{
depth = util2d::fillDepthHoles(depth, ui_->spinBox_mesh_fillDepthHoles->value(), float(ui_->spinBox_mesh_depthError->value())/100.0f);
}
}
imgDepth = uCvMat2QImage(depth);
}
std::list<int> ids;
@@ -2123,7 +2156,9 @@ void DatabaseViewer::update(int value,
weight->setNum(w);
label->setText(l.c_str());
labelPose->setText(QString("%1%2, %3, %4").arg(odomPose.isIdentity()?"* ":"").arg(odomPose.x()).arg(odomPose.y()).arg(odomPose.z()));
float x,y,z,roll,pitch,yaw;
odomPose.getTranslationAndEulerAngles(x,y,z,roll, pitch,yaw);
labelPose->setText(QString("%1xyz=(%2,%3,%4)\nrpy=(%5,%6,%7)").arg(odomPose.isIdentity()?"* ":"").arg(x).arg(y).arg(z).arg(roll).arg(pitch).arg(yaw));
if(s!=0.0)
{
stamp->setText(QDateTime::fromMSecsSinceEpoch(s*1000.0).toString("dd.MM.yyyy hh:mm:ss.zzz"));
@@ -2150,10 +2185,35 @@ void DatabaseViewer::update(int value,
if(!data.imageRaw().empty())
{
pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud;
cloud = util3d::cloudRGBFromSensorData(data);
if(!data.depthRaw().empty() && data.cameraModels().size()==1)
{
cv::Mat depth = data.depthRaw();
if(ui_->spinBox_mesh_fillDepthHoles->value() > 0)
{
depth = util2d::fillDepthHoles(depth, ui_->spinBox_mesh_fillDepthHoles->value(), float(ui_->spinBox_mesh_depthError->value())/100.0f);
}
cloud = util3d::cloudFromDepthRGB(data.imageRaw(), depth, data.cameraModels()[0].cx(), data.cameraModels()[0].cy(), data.cameraModels()[0].fx(), data.cameraModels()[0].fy());
}
else
{
cloud = util3d::cloudRGBFromSensorData(data);
}
if(cloud->size())
{
view3D->addOrUpdateCloud("0", cloud);
if(ui_->checkBox_showMesh->isChecked() && !cloud->is_dense)
{
std::vector<pcl::Vertices> polygons = util3d::organizedFastMesh(
cloud,
float(ui_->spinBox_mesh_angleTolerance->value())*M_PI/180.0f,
ui_->checkBox_mesh_quad->isChecked(),
ui_->spinBox_mesh_triangleSize->value());
view3D->removeCloud("0");
view3D->addCloudMesh("0", cloud, polygons);
}
else
{
view3D->addCloud("0", cloud);
}
}
}
else
@@ -2162,7 +2222,7 @@ void DatabaseViewer::update(int value,
cloud = util3d::cloudFromSensorData(data);
if(cloud->size())
{
view3D->addOrUpdateCloud("0", cloud);
view3D->addCloud("0", cloud);
}
}
}
@@ -2171,7 +2231,7 @@ void DatabaseViewer::update(int value,
pcl::PointCloud<pcl::PointXYZ>::Ptr scan = util3d::laserScanToPointCloud(data.laserScanRaw());
if(scan->size())
{
view3D->addOrUpdateCloud("1", scan);
view3D->addCloud("1", scan);
}
view3D->update();
@@ -2447,7 +2507,7 @@ void DatabaseViewer::updateStereo(const SensorData * data)
(int)cloud->size(), (int)leftCorners.size(), float(cloud->size())/float(leftCorners.size()), timeKpt, timeStereo);
ui_->stereoViewer->updateCameraTargetPosition(Transform::getIdentity());
ui_->stereoViewer->addOrUpdateCloud("stereo", cloud);
ui_->stereoViewer->addCloud("stereo", cloud);
ui_->stereoViewer->update();
ui_->label_stereo_inliers->setNum(inliers);
@@ -2609,6 +2669,15 @@ void DatabaseViewer::sliderBMoved(int value)
}
}
void DatabaseViewer::update3dView()
{
if(ui_->dockWidget_view3d->isVisible())
{
sliderAValueChanged(ui_->horizontalSlider_A->value());
sliderBValueChanged(ui_->horizontalSlider_B->value());
}
}
void DatabaseViewer::sliderNeighborValueChanged(int value)
{
this->updateConstraintView(neighborLinks_.at(value));
@@ -2784,12 +2853,12 @@ void DatabaseViewer::updateConstraintView(
if(cloudFrom.get() && cloudFrom->size())
{
ui_->constraintsViewer->addOrUpdateCloud("cloud0", cloudFrom, Transform::getIdentity(), Qt::red);
ui_->constraintsViewer->addCloud("cloud0", cloudFrom, Transform::getIdentity(), Qt::red);
}
if(cloudTo.get() && cloudTo->size())
{
cloudTo = rtabmap::util3d::transformPointCloud(cloudTo, t);
ui_->constraintsViewer->addOrUpdateCloud("cloud1", cloudTo, Transform::getIdentity(), Qt::cyan);
ui_->constraintsViewer->addCloud("cloud1", cloudTo, Transform::getIdentity(), Qt::cyan);
}
}
else
@@ -2843,7 +2912,7 @@ void DatabaseViewer::updateConstraintView(
if(cloudFrom->size())
{
ui_->constraintsViewer->addOrUpdateCloud("words0", cloudFrom, Transform::getIdentity(), Qt::red);
ui_->constraintsViewer->addCloud("words0", cloudFrom, Transform::getIdentity(), Qt::red);
}
else
{
@@ -2852,7 +2921,7 @@ void DatabaseViewer::updateConstraintView(
}
if(cloudTo->size())
{
ui_->constraintsViewer->addOrUpdateCloud("words1", cloudTo, Transform::getIdentity(), Qt::cyan);
ui_->constraintsViewer->addCloud("words1", cloudTo, Transform::getIdentity(), Qt::cyan);
}
else
{
@@ -2882,11 +2951,11 @@ void DatabaseViewer::updateConstraintView(
{
if(cloudFrom->size())
{
ui_->constraintsViewer->addOrUpdateCloud("cloud0", cloudFrom, Transform::getIdentity(), Qt::red);
ui_->constraintsViewer->addCloud("cloud0", cloudFrom, Transform::getIdentity(), Qt::red);
}
if(cloudTo->size())
{
ui_->constraintsViewer->addOrUpdateCloud("cloud1", cloudTo, Transform::getIdentity(), Qt::cyan);
ui_->constraintsViewer->addCloud("cloud1", cloudTo, Transform::getIdentity(), Qt::cyan);
}
}
@@ -2995,7 +3064,7 @@ void DatabaseViewer::updateConstraintView(
if(assembledScans->size())
{
ui_->constraintsViewer->addOrUpdateCloud("scan2", assembledScans, Transform::getIdentity(), Qt::cyan);
ui_->constraintsViewer->addCloud("scan2", assembledScans, Transform::getIdentity(), Qt::cyan);
}
if(graph->size())
{
@@ -3012,7 +3081,7 @@ void DatabaseViewer::updateConstraintView(
scanB = rtabmap::util3d::transformPointCloud(scanB, t);
if(scanA->size())
{
ui_->constraintsViewer->addOrUpdateCloud("scan0", scanA, Transform::getIdentity(), Qt::yellow);
ui_->constraintsViewer->addCloud("scan0", scanA, Transform::getIdentity(), Qt::yellow);
}
else
{
@@ -3020,7 +3089,7 @@ void DatabaseViewer::updateConstraintView(
}
if(scanB->size())
{
ui_->constraintsViewer->addOrUpdateCloud("scan1", scanB, Transform::getIdentity(), Qt::magenta);
ui_->constraintsViewer->addCloud("scan1", scanB, Transform::getIdentity(), Qt::magenta);
}
else
{
@@ -3038,7 +3107,7 @@ void DatabaseViewer::updateConstraintView(
{
if(scanFrom->size())
{
ui_->constraintsViewer->addOrUpdateCloud("scan0", scanFrom, Transform::getIdentity(), Qt::yellow);
ui_->constraintsViewer->addCloud("scan0", scanFrom, Transform::getIdentity(), Qt::yellow);
}
else
{
@@ -3046,7 +3115,7 @@ void DatabaseViewer::updateConstraintView(
}
if(scanTo->size())
{
ui_->constraintsViewer->addOrUpdateCloud("scan1", scanTo, Transform::getIdentity(), Qt::magenta);
ui_->constraintsViewer->addCloud("scan1", scanTo, Transform::getIdentity(), Qt::magenta);
}
else
{

File diff suppressed because it is too large Load Diff

View File

@@ -29,12 +29,22 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define EXPORTCLOUDSDIALOG_H_
#include <QDialog>
#include <QMap>
#include <QtCore/QSettings>
#include <rtabmap/core/Signature.h>
#include <pcl/point_cloud.h>
#include <pcl/point_types.h>
#include <pcl/PolygonMesh.h>
#include <pcl/TextureMesh.h>
#include <pcl/pcl_base.h>
class Ui_ExportCloudsDialog;
class QAbstractButton;
namespace rtabmap {
class ProgressDialog;
class ExportCloudsDialog : public QDialog
{
@@ -48,41 +58,19 @@ public:
void saveSettings(QSettings & settings, const QString & group = "") const;
void loadSettings(QSettings & settings, const QString & group = "");
void setSaveButton();
void setOkButton();
void enableRegeneration(bool enabled);
void exportClouds(
const std::map<int, Transform> & poses,
const std::map<int, int> & mapIds,
const QMap<int, Signature> & cachedSignatures,
const std::map<int, std::pair<pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr, pcl::IndicesPtr> > & createdClouds,
const QString & workingDirectory);
//getters
bool getBinaryFile() const;
int getNormalKSearch() const;
bool getGenerate() const;
int getGenerateDecimation() const;
double getGenerateVoxel() const;
double getGenerateMaxDepth() const;
bool getFiltering() const;
double getFilteringRadius() const;
int getFilteringMinNeighbors() const;
bool getAssemble() const;
double getAssembleVoxel() const;
bool getMLS() const;
double getMLSRadius() const;
int getMLSPolygonialOrder() const;
int getMLSUpsamplingMethod() const;
double getMLSUpsamplingRadius() const;
double getMLSUpsamplingStep() const;
int getMLSPointDensity() const;
double getMLSDilationVoxelSize() const;
int getMLSDilationIterations() const;
bool getMesh() const;
double getMeshGp3Radius() const;
double getMeshGp3Mu() const;
double getMeshDecimationFactor() const;
bool getMeshTexture() const;
void viewClouds(
const std::map<int, Transform> & poses,
const std::map<int, int> & mapIds,
const QMap<int, Signature> & cachedSignatures,
const std::map<int, std::pair<pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr, pcl::IndicesPtr> > & createdClouds,
const QString & workingDirectory);
signals:
void configChanged();
@@ -91,10 +79,34 @@ public slots:
void restoreDefaults();
private slots:
void updateReconstructionFlavor();
void updateMLSGrpVisibility();
private:
std::map<int, std::pair<pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr, pcl::IndicesPtr> > getClouds(
const std::map<int, Transform> & poses,
const QMap<int, Signature> & cachedSignatures,
const std::map<int, std::pair<pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr, pcl::IndicesPtr> > & createdClouds) const;
bool getExportedClouds(
const std::map<int, Transform> & poses,
const std::map<int, int> & mapIds,
const QMap<int, Signature> & cachedSignatures,
const std::map<int, std::pair<pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr, pcl::IndicesPtr> > & createdClouds,
const QString & workingDirectory,
std::map<int, pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr> & clouds,
std::map<int, pcl::PolygonMesh::Ptr> & meshes,
std::map<int, pcl::TextureMesh::Ptr> & textureMeshes);
void saveClouds(const QString & workingDirectory, const std::map<int, Transform> & poses, const std::map<int, pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr> & clouds, bool binaryMode = true);
void saveMeshes(const QString & workingDirectory, const std::map<int, Transform> & poses, const std::map<int, pcl::PolygonMesh::Ptr> & meshes, bool binaryMode = true);
void saveTextureMeshes(const QString & workingDirectory, const std::map<int, Transform> & poses, const std::map<int, pcl::TextureMesh::Ptr> & meshes);
void setSaveButton();
void setOkButton();
void enableRegeneration(bool enabled);
private:
Ui_ExportCloudsDialog * _ui;
ProgressDialog * _progressDialog;
};
}

View File

@@ -739,6 +739,18 @@ void ImageView::setImage(const QImage & image)
void ImageView::setImageDepth(const QImage & imageDepth)
{
_imageDepth = QPixmap::fromImage(imageDepth);
if( _image.width() > 0 &&
_image.width() > _imageDepth.width() &&
_image.height() > _imageDepth.height() &&
_image.width() % _imageDepth.width() == 0 &&
_image.height() % _imageDepth.height() == 0 &&
_image.width() / _imageDepth.width() == _image.height() / _imageDepth.height())
{
// scale depth to rgb
_imageDepth = _imageDepth.scaledToWidth(_image.width());
}
if(_graphicsView->isVisible())
{
if(_imageDepthItem)
@@ -755,7 +767,10 @@ void ImageView::setImageDepth(const QImage & imageDepth)
}
else
{
this->setSceneRect(imageDepth.rect());
if(_image.isNull())
{
this->setSceneRect(imageDepth.rect());
}
this->update();
}
}

View File

@@ -119,20 +119,20 @@ void LoopClosureViewer::updateView(const Transform & transform)
ui_->label_idA->setText(QString("[%1 (%2) -> %3 (%4)]").arg(sB_.id()).arg(cloudB->size()).arg(sA_.id()).arg(cloudA->size()));
if(cloudA->size())
{
{
ui_->cloudViewerTransform->addCloud("cloud0", cloudA);
}
if(cloudB->size())
{
cloudB = util3d::transformPointCloud(cloudB, t);
cloudB = util3d::transformPointCloud(cloudB, t);
ui_->cloudViewerTransform->addCloud("cloud1", cloudB);
}
if(scanA->size())
{
{
ui_->cloudViewerTransform->addCloud("scan0", scanA);
}
if(scanB->size())
{
{
ui_->cloudViewerTransform->addCloud("scan1", scanB);
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -249,7 +249,7 @@ void OdometryViewer::processData(const rtabmap::OdometryEvent & odom)
}
else
{
cloudView_->addOrUpdateCloud("cloudtmp", cloud, lastOdomPose_);
cloudView_->addCloud("cloudtmp", cloud, lastOdomPose_);
}
}
}
@@ -271,7 +271,7 @@ void OdometryViewer::processData(const rtabmap::OdometryEvent & odom)
(*cloud)[i].y = iter->second.y;
(*cloud)[i++].z = iter->second.z;
}
cloudView_->addOrUpdateCloud("localmap", cloud);
cloudView_->addCloud("localmap", cloud);
}
if(!odom.data().imageRaw().empty())

View File

@@ -58,6 +58,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "rtabmap/core/Memory.h"
#include "rtabmap/core/VWDictionary.h"
#include "rtabmap/core/Optimizer.h"
#include "rtabmap/core/OptimizerG2O.h"
#include "rtabmap/core/DBReader.h"
#include "rtabmap/gui/LoopClosureViewer.h"
@@ -175,6 +176,14 @@ PreferencesDialog::PreferencesDialog(QWidget * parent) :
{
_ui->graphOptimization_type->setItemData(1, 0, Qt::UserRole - 1);
}
if(!OptimizerG2O::isCSparseAvailable())
{
_ui->comboBox_g2o_solver->setItemData(0, 0, Qt::UserRole - 1);
}
if(!OptimizerG2O::isCholmodAvailable())
{
_ui->comboBox_g2o_solver->setItemData(2, 0, Qt::UserRole - 1);
}
if(!Optimizer::isAvailable(Optimizer::kTypeGTSAM))
{
_ui->graphOptimization_type->setItemData(2, 0, Qt::UserRole - 1);
@@ -253,10 +262,6 @@ PreferencesDialog::PreferencesDialog(QWidget * parent) :
_3dRenderingShowClouds[0] = _ui->checkBox_showClouds;
_3dRenderingShowClouds[1] = _ui->checkBox_showOdomClouds;
_3dRenderingVoxelSize.resize(2);
_3dRenderingVoxelSize[0] = _ui->doubleSpinBox_voxelSize;
_3dRenderingVoxelSize[1] = _ui->doubleSpinBox_voxelSize_odom;
_3dRenderingDecimation.resize(2);
_3dRenderingDecimation[0] = _ui->spinBox_decimation;
_3dRenderingDecimation[1] = _ui->spinBox_decimation_odom;
@@ -296,7 +301,6 @@ PreferencesDialog::PreferencesDialog(QWidget * parent) :
for(int i=0; i<2; ++i)
{
connect(_3dRenderingShowClouds[i], SIGNAL(stateChanged(int)), this, SLOT(makeObsoleteCloudRenderingPanel()));
connect(_3dRenderingVoxelSize[i], SIGNAL(valueChanged(double)), this, SLOT(makeObsoleteCloudRenderingPanel()));
connect(_3dRenderingDecimation[i], SIGNAL(valueChanged(int)), this, SLOT(makeObsoleteCloudRenderingPanel()));
connect(_3dRenderingMaxDepth[i], SIGNAL(valueChanged(double)), this, SLOT(makeObsoleteCloudRenderingPanel()));
connect(_3dRenderingShowScans[i], SIGNAL(stateChanged(int)), this, SLOT(makeObsoleteCloudRenderingPanel()));
@@ -312,18 +316,14 @@ PreferencesDialog::PreferencesDialog(QWidget * parent) :
connect(_ui->checkBox_showGraphs, SIGNAL(stateChanged(int)), this, SLOT(makeObsoleteCloudRenderingPanel()));
connect(_ui->checkBox_showLabels, SIGNAL(stateChanged(int)), this, SLOT(makeObsoleteCloudRenderingPanel()));
connect(_ui->checkBox_meshing, SIGNAL(stateChanged(int)), this, SLOT(makeObsoleteCloudRenderingPanel()));
connect(_ui->doubleSpinBox_gp3Radius, SIGNAL(valueChanged(double)), this, SLOT(makeObsoleteCloudRenderingPanel()));
connect(_ui->doubleSpinBox_gp3Mu, SIGNAL(valueChanged(double)), this, SLOT(makeObsoleteCloudRenderingPanel()));
connect(_ui->spinBox_normalKSearch, SIGNAL(valueChanged(int)), this, SLOT(makeObsoleteCloudRenderingPanel()));
connect(_ui->checkBox_mls, SIGNAL(stateChanged(int)), this, SLOT(makeObsoleteCloudRenderingPanel()));
connect(_ui->doubleSpinBox_mlsRadius, SIGNAL(valueChanged(double)), this, SLOT(makeObsoleteCloudRenderingPanel()));
connect(_ui->checkBox_nodeFiltering, SIGNAL(stateChanged(int)), this, SLOT(makeObsoleteCloudRenderingPanel()));
connect(_ui->checkBox_subtractFiltering, SIGNAL(stateChanged(int)), this, SLOT(makeObsoleteCloudRenderingPanel()));
connect(_ui->radioButton_noFiltering, SIGNAL(toggled(bool)), this, SLOT(makeObsoleteCloudRenderingPanel()));
connect(_ui->radioButton_nodeFiltering, SIGNAL(toggled(bool)), this, SLOT(makeObsoleteCloudRenderingPanel()));
connect(_ui->radioButton_subtractFiltering, SIGNAL(toggled(bool)), this, SLOT(makeObsoleteCloudRenderingPanel()));
connect(_ui->doubleSpinBox_cloudFilterRadius, SIGNAL(valueChanged(double)), this, SLOT(makeObsoleteCloudRenderingPanel()));
connect(_ui->doubleSpinBox_cloudFilterAngle, SIGNAL(valueChanged(double)), this, SLOT(makeObsoleteCloudRenderingPanel()));
connect(_ui->spinBox_substractFilteringMinPts, 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_subtractFilteringAngle, SIGNAL(valueChanged(double)), 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()));
@@ -331,6 +331,11 @@ PreferencesDialog::PreferencesDialog(QWidget * parent) :
connect(_ui->checkBox_map_occupancyFrom3DCloud, SIGNAL(stateChanged(int)), this, SLOT(makeObsoleteCloudRenderingPanel()));
connect(_ui->checkBox_map_erode, SIGNAL(stateChanged(int)), this, SLOT(makeObsoleteCloudRenderingPanel()));
connect(_ui->groupBox_organized, SIGNAL(clicked(bool)), this, SLOT(makeObsoleteCloudRenderingPanel()));
connect(_ui->doubleSpinBox_mesh_angleTolerance, SIGNAL(valueChanged(double)), this, SLOT(makeObsoleteCloudRenderingPanel()));
connect(_ui->checkBox_mesh_quad, SIGNAL(stateChanged(int)), this, SLOT(makeObsoleteCloudRenderingPanel()));
connect(_ui->spinBox_mesh_triangleSize, SIGNAL(valueChanged(int)), this, SLOT(makeObsoleteCloudRenderingPanel()));
//Logging panel
connect(_ui->comboBox_loggerLevel, SIGNAL(currentIndexChanged(int)), this, SLOT(makeObsoleteLoggingPanel()));
connect(_ui->comboBox_loggerEventLevel, SIGNAL(currentIndexChanged(int)), this, SLOT(makeObsoleteLoggingPanel()));
@@ -487,6 +492,7 @@ PreferencesDialog::PreferencesDialog(QWidget * parent) :
// Memory
_ui->general_checkBox_keepRawData->setObjectName(Parameters::kMemImageKept().c_str());
_ui->general_checkBox_keepBinaryData->setObjectName(Parameters::kMemBinDataKept().c_str());
_ui->general_checkBox_keepDescriptors->setObjectName(Parameters::kMemRawDescriptorsKept().c_str());
_ui->general_checkBox_saveDepth16bits->setObjectName(Parameters::kMemSaveDepth16Format().c_str());
_ui->general_checkBox_reduceGraph->setObjectName(Parameters::kMemReduceGraph().c_str());
_ui->general_checkBox_keepNotLinkedNodes->setObjectName(Parameters::kMemNotLinkedNodesKept().c_str());
@@ -627,6 +633,9 @@ PreferencesDialog::PreferencesDialog(QWidget * parent) :
_ui->graphOptimization_stopEpsilon->setObjectName(Parameters::kOptimizerEpsilon().c_str());
_ui->graphOptimization_robust->setObjectName(Parameters::kOptimizerRobust().c_str());
_ui->comboBox_g2o_solver->setObjectName(Parameters::kg2oSolver().c_str());
_ui->comboBox_g2o_optimizer->setObjectName(Parameters::kg2oOptimizer().c_str());
_ui->graphPlan_goalReachedRadius->setObjectName(Parameters::kRGBDGoalReachedRadius().c_str());
_ui->graphPlan_goalsSavedInUserData->setObjectName(Parameters::kRGBDGoalsSavedInUserData().c_str());
_ui->graphPlan_stuckIterations->setObjectName(Parameters::kRGBDPlanStuckIterations().c_str());
@@ -753,7 +762,11 @@ PreferencesDialog::PreferencesDialog(QWidget * parent) :
_ui->stereobm_tetureThreshold->setObjectName(Parameters::kStereoBMTextureThreshold().c_str());
_ui->stereobm_uniquessRatio->setObjectName(Parameters::kStereoBMUniquenessRatio().c_str());
// reset default settings for the gui
resetSettings(_ui->groupBox_generalSettingsGui0);
resetSettings(_ui->groupBox_cloudRendering1);
resetSettings(_ui->groupBox_logging1);
resetSettings(_ui->groupBox_source0);
setupSignals();
// custom signals
@@ -761,6 +774,7 @@ PreferencesDialog::PreferencesDialog(QWidget * parent) :
connect(_ui->doubleSpinBox_kp_roi1, SIGNAL(valueChanged(double)), this, SLOT(updateKpROI()));
connect(_ui->doubleSpinBox_kp_roi2, SIGNAL(valueChanged(double)), this, SLOT(updateKpROI()));
connect(_ui->doubleSpinBox_kp_roi3, SIGNAL(valueChanged(double)), this, SLOT(updateKpROI()));
connect(_ui->graphOptimization_type, SIGNAL(currentIndexChanged(int)), this, SLOT(updateG2oVisibility()));
//Create a model from the stacked widgets
// This will add all parameters to the parameters Map
@@ -1092,40 +1106,40 @@ void PreferencesDialog::resetSettings(QGroupBox * groupBox)
for(int i=0; i<2; ++i)
{
_3dRenderingShowClouds[i]->setChecked(true);
_3dRenderingVoxelSize[i]->setValue(i==0?0.01:0.0); // voxel of 1 cm for cloud substracting
_3dRenderingDecimation[i]->setValue(i==0?4:2);
_3dRenderingDecimation[i]->setValue(8);
_3dRenderingMaxDepth[i]->setValue(0.0);
_3dRenderingShowScans[i]->setChecked(true);
_3dRenderingDownsamplingScan[i]->setValue(1);
_3dRenderingVoxelSizeScan[i]->setValue(0.0);
_3dRenderingOpacity[i]->setValue(i==0?1.0:0.5);
_3dRenderingOpacity[i]->setValue(i==0?1.0:0.75);
_3dRenderingPtSize[i]->setValue(2);
_3dRenderingOpacityScan[i]->setValue(i==0?1.0:0.5);
_3dRenderingPtSizeScan[i]->setValue(2);
}
_ui->checkBox_showGraphs->setChecked(true);
_ui->checkBox_showLabels->setChecked(true);
_ui->checkBox_showLabels->setChecked(false);
_ui->checkBox_meshing->setChecked(false);
_ui->doubleSpinBox_gp3Radius->setValue(0.04);
_ui->doubleSpinBox_gp3Mu->setValue(2.5);
_ui->spinBox_normalKSearch->setValue(20);
_ui->checkBox_mls->setChecked(false);
_ui->doubleSpinBox_mlsRadius->setValue(0.04);
_ui->checkBox_nodeFiltering->setChecked(false);
_ui->checkBox_subtractFiltering->setChecked(true);
_ui->radioButton_noFiltering->setChecked(true);
_ui->radioButton_nodeFiltering->setChecked(false);
_ui->radioButton_subtractFiltering->setChecked(false);
_ui->doubleSpinBox_cloudFilterRadius->setValue(0.1);
_ui->doubleSpinBox_cloudFilterAngle->setValue(30);
_ui->spinBox_substractFilteringMinPts->setValue(1);
_ui->spinBox_subtractFilteringMinPts->setValue(5);
_ui->doubleSpinBox_subtractFilteringRadius->setValue(0.02);
_ui->doubleSpinBox_subtractFilteringAngle->setValue(45.0);
_ui->checkBox_map_shown->setChecked(false);
_ui->doubleSpinBox_map_resolution->setValue(0.05);
_ui->checkBox_map_occupancyFrom3DCloud->setChecked(false);
_ui->checkBox_map_erode->setChecked(false);
_ui->doubleSpinBox_map_opacity->setValue(0.75);
_ui->groupBox_organized->setChecked(true);
_ui->doubleSpinBox_mesh_angleTolerance->setValue(15.0);
_ui->checkBox_mesh_quad->setChecked(true);
_ui->spinBox_mesh_triangleSize->setValue(2);
}
else if(groupBox->objectName() == _ui->groupBox_logging1->objectName())
{
@@ -1265,7 +1279,14 @@ void PreferencesDialog::resetSettings(QGroupBox * groupBox)
key = children.at(i)->objectName().toStdString();
if(uContains(defaults, key))
{
this->setParameter(key, defaults.at(key));
if(key.compare(Parameters::kRtabmapWorkingDirectory().c_str()) == 0)
{
this->setParameter(key, Parameters::createDefaultWorkingDirectory());
}
else
{
this->setParameter(key, defaults.at(key));
}
if(qobject_cast<const QGroupBox*>(children.at(i)))
{
this->resetSettings((QGroupBox*)children.at(i));
@@ -1415,7 +1436,6 @@ void PreferencesDialog::readGuiSettings(const QString & filePath)
for(int i=0; i<2; ++i)
{
_3dRenderingShowClouds[i]->setChecked(settings.value(QString("showClouds%1").arg(i), _3dRenderingShowClouds[i]->isChecked()).toBool());
_3dRenderingVoxelSize[i]->setValue(settings.value(QString("voxelSize%1").arg(i), _3dRenderingVoxelSize[i]->value()).toDouble());
_3dRenderingDecimation[i]->setValue(settings.value(QString("decimation%1").arg(i), _3dRenderingDecimation[i]->value()).toInt());
_3dRenderingMaxDepth[i]->setValue(settings.value(QString("maxDepth%1").arg(i), _3dRenderingMaxDepth[i]->value()).toDouble());
_3dRenderingShowScans[i]->setChecked(settings.value(QString("showScans%1").arg(i), _3dRenderingShowScans[i]->isChecked()).toBool());
@@ -1430,18 +1450,14 @@ void PreferencesDialog::readGuiSettings(const QString & filePath)
_ui->checkBox_showGraphs->setChecked(settings.value("showGraphs", _ui->checkBox_showGraphs->isChecked()).toBool());
_ui->checkBox_showLabels->setChecked(settings.value("showLabels", _ui->checkBox_showLabels->isChecked()).toBool());
_ui->checkBox_meshing->setChecked(settings.value("meshing", _ui->checkBox_meshing->isChecked()).toBool());
_ui->doubleSpinBox_gp3Radius->setValue(settings.value("meshGP3Radius", _ui->doubleSpinBox_gp3Radius->value()).toDouble());
_ui->doubleSpinBox_gp3Mu->setValue(settings.value("meshGP3Mu", _ui->doubleSpinBox_gp3Mu->value()).toDouble());
_ui->spinBox_normalKSearch->setValue(settings.value("meshNormalKSearch", _ui->spinBox_normalKSearch->value()).toInt());
_ui->checkBox_mls->setChecked(settings.value("meshSmoothing", _ui->checkBox_mls->isChecked()).toBool());
_ui->doubleSpinBox_mlsRadius->setValue(settings.value("meshSmoothingRadius", _ui->doubleSpinBox_mlsRadius->value()).toDouble());
_ui->checkBox_nodeFiltering->setChecked(settings.value("cloudFiltering", _ui->checkBox_nodeFiltering->isChecked()).toBool());
_ui->checkBox_subtractFiltering->setChecked(settings.value("subtractFiltering", _ui->checkBox_subtractFiltering->isChecked()).toBool());
_ui->radioButton_noFiltering->setChecked(settings.value("noFiltering", _ui->radioButton_noFiltering->isChecked()).toBool());
_ui->radioButton_nodeFiltering->setChecked(settings.value("cloudFiltering", _ui->radioButton_nodeFiltering->isChecked()).toBool());
_ui->doubleSpinBox_cloudFilterRadius->setValue(settings.value("cloudFilteringRadius", _ui->doubleSpinBox_cloudFilterRadius->value()).toDouble());
_ui->doubleSpinBox_cloudFilterAngle->setValue(settings.value("cloudFilteringAngle", _ui->doubleSpinBox_cloudFilterAngle->value()).toDouble());
_ui->spinBox_substractFilteringMinPts->setValue(settings.value("cloudFilteringAngleMinPts", _ui->spinBox_substractFilteringMinPts->value()).toDouble());
_ui->radioButton_subtractFiltering->setChecked(settings.value("subtractFiltering", _ui->radioButton_subtractFiltering->isChecked()).toBool());
_ui->spinBox_subtractFilteringMinPts->setValue(settings.value("subtractFilteringMinPts", _ui->spinBox_subtractFilteringMinPts->value()).toInt());
_ui->doubleSpinBox_subtractFilteringRadius->setValue(settings.value("subtractFilteringRadius", _ui->doubleSpinBox_subtractFilteringRadius->value()).toDouble());
_ui->doubleSpinBox_subtractFilteringAngle->setValue(settings.value("subtractFilteringAngle", _ui->doubleSpinBox_subtractFilteringAngle->value()).toDouble());
_ui->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());
@@ -1449,6 +1465,11 @@ void PreferencesDialog::readGuiSettings(const QString & filePath)
_ui->checkBox_map_erode->setChecked(settings.value("gridMapEroded", _ui->checkBox_map_erode->isChecked()).toBool());
_ui->doubleSpinBox_map_opacity->setValue(settings.value("gridMapOpacity", _ui->doubleSpinBox_map_opacity->value()).toDouble());
_ui->groupBox_organized->setChecked(settings.value("meshing", _ui->groupBox_organized->isChecked()).toBool());
_ui->doubleSpinBox_mesh_angleTolerance->setValue(settings.value("meshing_angle", _ui->doubleSpinBox_mesh_angleTolerance->value()).toDouble());
_ui->checkBox_mesh_quad->setChecked(settings.value("meshing_quad", _ui->checkBox_mesh_quad->isChecked()).toBool());
_ui->spinBox_mesh_triangleSize->setValue(settings.value("meshing_triangle_size", _ui->spinBox_mesh_triangleSize->value()).toInt());
settings.endGroup(); // General
settings.endGroup(); // rtabmap
@@ -1653,7 +1674,7 @@ bool PreferencesDialog::readCoreSettings(const QString & filePath)
if(key.toStdString().compare(Parameters::kRtabmapWorkingDirectory()) == 0)
{
// The directory should exist if not the default one
if(!QDir(value).exists() && value.compare(Parameters::defaultRtabmapWorkingDirectory().c_str()) != 0)
if(!QDir(value).exists() && value.compare(Parameters::createDefaultWorkingDirectory().c_str()) != 0)
{
if(QDir(this->getWorkingDirectory().toStdString().c_str()).exists())
{
@@ -1675,11 +1696,6 @@ bool PreferencesDialog::readCoreSettings(const QString & filePath)
}
else
{
UDEBUG("key.toStdString()=%s", key.toStdString().c_str());
// Use the default value if the key doesn't exist yet
this->setParameter(key.toStdString(), (*iter).second);
// Add information about the working directory if not in the config file
if(key.toStdString().compare(Parameters::kRtabmapWorkingDirectory()) == 0)
{
@@ -1691,8 +1707,16 @@ bool PreferencesDialog::readCoreSettings(const QString & filePath)
"By default, the directory \"%1\" is used.\n\n"
"The working directory can be changed any time in the "
"preferences menu.").arg(
Parameters::defaultRtabmapWorkingDirectory().c_str()));
Parameters::createDefaultWorkingDirectory().c_str()));
}
this->setParameter(key.toStdString(), Parameters::createDefaultWorkingDirectory());
UDEBUG("key.toStdString()=%s", Parameters::createDefaultWorkingDirectory().c_str());
}
else
{
// Use the default value if the key doesn't exist yet
this->setParameter(key.toStdString(), (*iter).second);
UDEBUG("key.toStdString()=%s", key.toStdString().c_str());
}
}
}
@@ -1788,7 +1812,6 @@ void PreferencesDialog::writeGuiSettings(const QString & filePath) const
for(int i=0; i<2; ++i)
{
settings.setValue(QString("showClouds%1").arg(i), _3dRenderingShowClouds[i]->isChecked());
settings.setValue(QString("voxelSize%1").arg(i), _3dRenderingVoxelSize[i]->value());
settings.setValue(QString("decimation%1").arg(i), _3dRenderingDecimation[i]->value());
settings.setValue(QString("maxDepth%1").arg(i), _3dRenderingMaxDepth[i]->value());
settings.setValue(QString("showScans%1").arg(i), _3dRenderingShowScans[i]->isChecked());
@@ -1803,24 +1826,26 @@ void PreferencesDialog::writeGuiSettings(const QString & filePath) const
settings.setValue("showGraphs", _ui->checkBox_showGraphs->isChecked());
settings.setValue("showLabels", _ui->checkBox_showLabels->isChecked());
settings.setValue("meshing", _ui->checkBox_meshing->isChecked());
settings.setValue("meshGP3Radius", _ui->doubleSpinBox_gp3Radius->value());
settings.setValue("meshGP3Mu", _ui->doubleSpinBox_gp3Mu->value());
settings.setValue("meshNormalKSearch", _ui->spinBox_normalKSearch->value());
settings.setValue("meshSmoothing", _ui->checkBox_mls->isChecked());
settings.setValue("meshSmoothingRadius", _ui->doubleSpinBox_mlsRadius->value());
settings.setValue("cloudFiltering", _ui->checkBox_nodeFiltering->isChecked());
settings.setValue("subtractFiltering", _ui->checkBox_subtractFiltering->isChecked());
settings.setValue("noFiltering", _ui->radioButton_noFiltering->isChecked());
settings.setValue("cloudFiltering", _ui->radioButton_nodeFiltering->isChecked());
settings.setValue("cloudFilteringRadius", _ui->doubleSpinBox_cloudFilterRadius->value());
settings.setValue("cloudFilteringAngle", _ui->doubleSpinBox_cloudFilterAngle->value());
settings.setValue("subtractFilteringMinPts", _ui->spinBox_substractFilteringMinPts->value());
settings.setValue("subtractFiltering", _ui->radioButton_subtractFiltering->isChecked());
settings.setValue("subtractFilteringMinPts", _ui->spinBox_subtractFilteringMinPts->value());
settings.setValue("subtractFilteringRadius", _ui->doubleSpinBox_subtractFilteringRadius->value());
settings.setValue("subtractFilteringAngle", _ui->doubleSpinBox_subtractFilteringAngle->value());
settings.setValue("gridMapShown", _ui->checkBox_map_shown->isChecked());
settings.setValue("gridMapResolution", _ui->doubleSpinBox_map_resolution->value());
settings.setValue("gridMapOccupancyFrom3DCloud", _ui->checkBox_map_occupancyFrom3DCloud->isChecked());
settings.setValue("gridMapEroded", _ui->checkBox_map_erode->isChecked());
settings.setValue("gridMapOpacity", _ui->doubleSpinBox_map_opacity->value());
settings.setValue("meshing", _ui->groupBox_organized->isChecked());
settings.setValue("meshing_angle", _ui->doubleSpinBox_mesh_angleTolerance->value());
settings.setValue("meshing_quad", _ui->checkBox_mesh_quad->isChecked());
settings.setValue("meshing_triangle_size", _ui->spinBox_mesh_triangleSize->value());
settings.endGroup(); // General
settings.endGroup(); // rtabmap
@@ -2073,13 +2098,6 @@ bool PreferencesDialog::validateForm()
"cannot be LSH (used for binary descriptor). KD-tree is set instead for the bag-of-words dictionary."));
_ui->comboBox_dictionary_strategy->setCurrentIndex(VWDictionary::kNNFlannKdTree);
}
else if(_ui->comboBox_dictionary_strategy->currentIndex() == VWDictionary::kNNFlannKdTree && _ui->comboBox_detector_strategy->currentIndex() >1)
{
QMessageBox::warning(this, tr("Parameter warning"),
tr("With the selected feature type (ORB, FAST, FREAK or BRIEF), parameter \"Visual word->Nearest Neighbor\" "
"cannot be KD-Tree (used for float descriptor). BruteForce matching is set instead for the bag-of-words dictionary."));
_ui->comboBox_dictionary_strategy->setCurrentIndex(VWDictionary::kNNBruteForce);
}
// BOW Reextract features type
if(_ui->reextract_nn->currentIndex() == VWDictionary::kNNFlannLSH && _ui->reextract_type->currentIndex() <= 1)
@@ -2090,14 +2108,6 @@ bool PreferencesDialog::validateForm()
"of features on loop closure."));
_ui->reextract_nn->setCurrentIndex(VWDictionary::kNNFlannKdTree);
}
else if(_ui->reextract_nn->currentIndex() == VWDictionary::kNNFlannKdTree && _ui->reextract_type->currentIndex() >1)
{
QMessageBox::warning(this, tr("Parameter warning"),
tr("With the selected feature type (ORB, FAST, FREAK or BRIEF), parameter \"Visual word->Nearest Neighbor\" "
"cannot be KD-Tree (used for float descriptor). BruteForce matching is set instead for the re-extraction "
"of features on loop closure."));
_ui->reextract_nn->setCurrentIndex(VWDictionary::kNNBruteForce);
}
if(_ui->doubleSpinBox_freenect2MinDepth->value() >= _ui->doubleSpinBox_freenect2MaxDepth->value())
{
@@ -3237,6 +3247,11 @@ void PreferencesDialog::updateKpROI()
_ui->lineEdit_kp_roi->setText(strings.join(" "));
}
void PreferencesDialog::updateG2oVisibility()
{
_ui->groupBox_g2o->setVisible(_ui->graphOptimization_type->currentIndex() == 1);
}
void PreferencesDialog::changeWorkingDirectory()
{
QString directory = QFileDialog::getExistingDirectory(this, tr("Working directory"), _ui->lineEdit_workingDirectory->text());
@@ -3387,12 +3402,19 @@ bool PreferencesDialog::isLabelsShown() const
}
bool PreferencesDialog::isCloudMeshing() const
{
return _ui->checkBox_meshing->isChecked();
return _ui->groupBox_organized->isChecked();
}
double PreferencesDialog::getCloudVoxelSize(int index) const
double PreferencesDialog::getCloudMeshingAngle() const
{
UASSERT(index >= 0 && index <= 1);
return _3dRenderingVoxelSize[index]->value();
return _ui->doubleSpinBox_mesh_angleTolerance->value()*M_PI/180.0f;
}
bool PreferencesDialog::isCloudMeshingQuad() const
{
return _ui->checkBox_mesh_quad->isChecked();
}
int PreferencesDialog::getCloudMeshingTriangleSize()
{
return _ui->spinBox_mesh_triangleSize->value();
}
int PreferencesDialog::getCloudDecimation(int index) const
{
@@ -3440,33 +3462,13 @@ int PreferencesDialog::getScanPointSize(int index) const
UASSERT(index >= 0 && index <= 1);
return _3dRenderingPtSizeScan[index]->value();
}
int PreferencesDialog::getMeshNormalKSearch() const
{
return _ui->spinBox_normalKSearch->value();
}
double PreferencesDialog::getMeshGP3Radius() const
{
return _ui->doubleSpinBox_gp3Radius->value();
}
double PreferencesDialog::getMeshGP3Mu() const
{
return _ui->doubleSpinBox_gp3Mu->value();
}
bool PreferencesDialog::getMeshSmoothing() const
{
return _ui->checkBox_mls->isChecked();
}
double PreferencesDialog::getMeshSmoothingRadius() const
{
return _ui->doubleSpinBox_mlsRadius->value();
}
bool PreferencesDialog::isCloudFiltering() const
{
return _ui->checkBox_nodeFiltering->isChecked();
return _ui->radioButton_nodeFiltering->isChecked();
}
bool PreferencesDialog::isSubtractFiltering() const
{
return _ui->checkBox_subtractFiltering->isChecked();
return _ui->radioButton_subtractFiltering->isChecked();
}
double PreferencesDialog::getCloudFilteringRadius() const
{
@@ -3476,9 +3478,17 @@ double PreferencesDialog::getCloudFilteringAngle() const
{
return _ui->doubleSpinBox_cloudFilterAngle->value();
}
int PreferencesDialog::getSubstractFilteringMinPts() const
int PreferencesDialog::getSubtractFilteringMinPts() const
{
return _ui->spinBox_substractFilteringMinPts->value();
return _ui->spinBox_subtractFilteringMinPts->value();
}
double PreferencesDialog::getSubtractFilteringRadius() const
{
return _ui->doubleSpinBox_subtractFilteringRadius->value();
}
double PreferencesDialog::getSubtractFilteringAngle() const
{
return _ui->doubleSpinBox_subtractFilteringAngle->value()*M_PI/180.0;
}
bool PreferencesDialog::getGridMapShown() const
{
@@ -4077,7 +4087,7 @@ void PreferencesDialog::testOdometry()
OdometryViewer * odomViewer = new OdometryViewer(10,
_ui->spinBox_decimation_odom->value(),
_ui->doubleSpinBox_voxelSize_odom->value(),
0.0f,
_ui->doubleSpinBox_maxDepth_odom->value(),
this->getOdomQualityWarnThr(),
this);

View File

@@ -17,7 +17,7 @@
<enum>Qt::LeftToRight</enum>
</property>
<widget class="QWidget" name="centralwidget">
<layout class="QVBoxLayout" name="verticalLayout_5" stretch="1,0,0">
<layout class="QVBoxLayout" name="verticalLayout_6" stretch="1,0,0">
<property name="spacing">
<number>0</number>
</property>
@@ -35,7 +35,7 @@
</layout>
</item>
<item>
<layout class="QGridLayout" name="gridLayout_11">
<layout class="QGridLayout" name="gridLayout_11" rowstretch="1,0">
<property name="spacing">
<number>0</number>
</property>
@@ -52,11 +52,11 @@
<rect>
<x>0</x>
<y>0</y>
<width>189</width>
<width>205</width>
<height>184</height>
</rect>
</property>
<layout class="QGridLayout" name="gridLayout" columnstretch="0,1">
<layout class="QGridLayout" name="gridLayout" rowstretch="0,0,0,0,0,0,0" columnstretch="1,1">
<item row="0" column="0">
<widget class="QLabel" name="label_parentsA_2">
<property name="text">
@@ -172,7 +172,7 @@
<rect>
<x>0</x>
<y>0</y>
<width>187</width>
<width>203</width>
<height>184</height>
</rect>
</property>
@@ -820,6 +820,13 @@
<layout class="QVBoxLayout" name="verticalLayout_10">
<item>
<layout class="QGridLayout" name="gridLayout_4">
<item row="1" column="2">
<widget class="QLabel" name="label_logger_level_2">
<property name="text">
<string>Vertical layout</string>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QLabel" name="label_logger_level">
<property name="text">
@@ -861,19 +868,12 @@
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QLabel" name="label_logger_level_2">
<property name="text">
<string>Vertical layout</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QToolBox" name="toolBox">
<property name="currentIndex">
<number>3</number>
<number>1</number>
</property>
<widget class="QWidget" name="page_3">
<property name="geometry">
@@ -1016,8 +1016,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>297</width>
<height>411</height>
<width>280</width>
<height>628</height>
</rect>
</property>
<attribute name="label">
@@ -1266,6 +1266,131 @@
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>Organized Fast Mesh</string>
</property>
<layout class="QGridLayout" name="gridLayout_13">
<item row="2" column="1">
<widget class="QLabel" name="label_14">
<property name="text">
<string>Triangle size</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLabel" name="label_12">
<property name="text">
<string>Angle tolerance</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QCheckBox" name="checkBox_mesh_quad">
<property name="text">
<string/>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QLabel" name="label_15">
<property name="text">
<string>Fill depth holes: size</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QSpinBox" name="spinBox_mesh_fillDepthHoles">
<property name="suffix">
<string> pix</string>
</property>
<property name="minimum">
<number>0</number>
</property>
<property name="maximum">
<number>99</number>
</property>
<property name="value">
<number>0</number>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QSpinBox" name="spinBox_mesh_angleTolerance">
<property name="suffix">
<string> deg</string>
</property>
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>180</number>
</property>
<property name="value">
<number>15</number>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QSpinBox" name="spinBox_mesh_triangleSize">
<property name="suffix">
<string> pix</string>
</property>
<property name="minimum">
<number>2</number>
</property>
<property name="maximum">
<number>99</number>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLabel" name="label_13">
<property name="text">
<string>Quad</string>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QLabel" name="label_17">
<property name="text">
<string>Fill depth holes: error</string>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QSpinBox" name="spinBox_mesh_depthError">
<property name="suffix">
<string> %</string>
</property>
<property name="minimum">
<number>1</number>
</property>
<property name="value">
<number>10</number>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<widget class="QWidget" name="page_5">
@@ -1273,7 +1398,7 @@
<rect>
<x>0</x>
<y>0</y>
<width>297</width>
<width>201</width>
<height>126</height>
</rect>
</property>
@@ -1373,8 +1498,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>297</width>
<height>134</height>
<width>173</width>
<height>166</height>
</rect>
</property>
<attribute name="label">
@@ -1572,12 +1697,35 @@
<number>4</number>
</attribute>
<widget class="QWidget" name="dockWidgetContents_6">
<layout class="QHBoxLayout" name="horizontalLayout_8" stretch="1,1">
<layout class="QVBoxLayout" name="verticalLayout_5" stretch="1,0">
<property name="spacing">
<number>0</number>
</property>
<property name="margin">
<number>0</number>
</property>
<item>
<widget class="rtabmap::CloudViewer" name="widget_cloudA" native="true"/>
<layout class="QHBoxLayout" name="horizontalLayout_3dviews" stretch="1,1">
<property name="spacing">
<number>1</number>
</property>
<item>
<widget class="rtabmap::CloudViewer" name="widget_cloudA" native="true"/>
</item>
<item>
<widget class="rtabmap::CloudViewer" name="widget_cloudB" native="true"/>
</item>
</layout>
</item>
<item>
<widget class="rtabmap::CloudViewer" name="widget_cloudB" native="true"/>
<widget class="QCheckBox" name="checkBox_showMesh">
<property name="text">
<string>Mesh</string>
</property>
<property name="checked">
<bool>false</bool>
</property>
</widget>
</item>
</layout>
</widget>

View File

@@ -718,9 +718,6 @@
</widget>
</item>
</layout>
<zorder>buttonBox</zorder>
<zorder>groupBox</zorder>
<zorder></zorder>
</widget>
<customwidgets>
<customwidget>

View File

@@ -7,11 +7,11 @@
<x>0</x>
<y>0</y>
<width>814</width>
<height>898</height>
<height>667</height>
</rect>
</property>
<property name="windowTitle">
<string>Export 3D clouds</string>
<string>Export 3D Clouds</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2" stretch="1,0,0">
<item>
@@ -23,14 +23,51 @@
<property name="geometry">
<rect>
<x>0</x>
<y>-242</y>
<y>0</y>
<width>773</width>
<height>1064</height>
<height>1422</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_13">
<item>
<layout class="QGridLayout" name="gridLayout_8" columnstretch="0,1">
<item row="1" column="1">
<widget class="QLabel" name="label_binaryFile_2">
<property name="text">
<string>Assemble clouds/meshes to a single output cloud/mesh.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QLabel" name="label_12">
<property name="text">
<string>Reconstruction flavor.</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLabel" name="label_111">
<property name="text">
<string>Set the number of k nearest neighbors to use for the normal estimation.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QSpinBox" name="spinBox_normalKSearch">
<property name="minimum">
<number>0</number>
</property>
<property name="value">
<number>20</number>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLabel" name="label_binaryFile">
<property name="text">
@@ -51,23 +88,53 @@
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLabel" name="label_111">
<item row="4" column="0">
<widget class="QComboBox" name="comboBox_pipeline">
<item>
<property name="text">
<string>Organized Point Cloud</string>
</property>
</item>
<item>
<property name="text">
<string>Dense Point Cloud</string>
</property>
</item>
</widget>
</item>
<item row="1" column="0">
<widget class="QCheckBox" name="checkBox_assemble">
<property name="text">
<string>Set the number of k nearest neighbors to use for the normal estimation.</string>
<string/>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QLabel" name="label_109">
<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>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QSpinBox" name="spinBox_normalKSearch">
<property name="minimum">
<number>0</number>
<item row="3" column="0">
<widget class="QDoubleSpinBox" name="doubleSpinBox_voxelSize_assembled">
<property name="suffix">
<string> m</string>
</property>
<property name="decimals">
<number>3</number>
</property>
<property name="maximum">
<double>1.000000000000000</double>
</property>
<property name="singleStep">
<double>0.010000000000000</double>
</property>
<property name="value">
<number>20</number>
<double>0.005000000000000</double>
</property>
</widget>
</item>
@@ -76,91 +143,159 @@
<item>
<widget class="QGroupBox" name="groupBox_regenerate">
<property name="title">
<string>Regenerate clouds</string>
<string>Regenerate Clouds</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<layout class="QGridLayout" name="gridLayout" columnstretch="0,1">
<item row="1" column="0">
<widget class="QDoubleSpinBox" name="doubleSpinBox_voxelSize">
<property name="suffix">
<string> m</string>
</property>
<property name="decimals">
<number>3</number>
</property>
<property name="maximum">
<double>1.000000000000000</double>
</property>
<property name="singleStep">
<double>0.010000000000000</double>
</property>
<property name="value">
<double>0.005000000000000</double>
</property>
</widget>
<layout class="QVBoxLayout" name="verticalLayout_14">
<item>
<layout class="QGridLayout" name="gridLayout" columnstretch="0,1">
<item row="0" column="0">
<widget class="QSpinBox" name="spinBox_decimation">
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>32</number>
</property>
<property name="value">
<number>1</number>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLabel" name="label_108">
<property name="text">
<string>3D cloud decimation (1-2-4-8-...).</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QDoubleSpinBox" name="doubleSpinBox_maxDepth">
<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>4.000000000000000</double>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLabel" name="label_132">
<property name="text">
<string>3D cloud maximum depth (0 means no limit).</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
<item row="2" column="0">
<widget class="QSpinBox" name="spinBox_decimation">
<property name="minimum">
<number>1</number>
<item>
<widget class="QGroupBox" name="groupBox_subtraction">
<property name="title">
<string>Cloud Subtraction</string>
</property>
<property name="maximum">
<number>32</number>
</property>
<property name="value">
<number>1</number>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLabel" name="label_108">
<property name="text">
<string>3D cloud decimation (1-2-4-8-...).</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLabel" name="label_107">
<property name="text">
<string>3D cloud voxel size.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QDoubleSpinBox" name="doubleSpinBox_maxDepth">
<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>4.000000000000000</double>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QLabel" name="label_132">
<property name="text">
<string>3D cloud maximum depth (0 means no limit).</string>
</property>
<property name="wordWrap">
<property name="checkable">
<bool>true</bool>
</property>
<layout class="QGridLayout" name="gridLayout_11" columnstretch="0,1">
<item row="2" column="1">
<widget class="QLabel" name="label_174">
<property name="text">
<string>Minimum points of the previous cloud in the fixed point radius in order to substract the point in the new cloud. Increasing this value reduces the black contours between clouds.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLabel" name="label_193">
<property name="text">
<string>Point angle used to keep only points with similar normal between the current cloud and the previous one.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QDoubleSpinBox" name="doubleSpinBox_subtractPointFilteringRadius">
<property name="suffix">
<string/>
</property>
<property name="minimum">
<double>0.010000000000000</double>
</property>
<property name="maximum">
<double>1.000000000000000</double>
</property>
<property name="singleStep">
<double>0.010000000000000</double>
</property>
<property name="value">
<double>0.020000000000000</double>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLabel" name="label_192">
<property name="text">
<string>Point radius used to find close points between the current cloud and the previous one.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QSpinBox" name="spinBox_subtractFilteringMinPts">
<property name="minimum">
<number>1</number>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QDoubleSpinBox" name="doubleSpinBox_subtractPointFilteringAngle">
<property name="suffix">
<string> degrees</string>
</property>
<property name="decimals">
<number>0</number>
</property>
<property name="maximum">
<double>180.000000000000000</double>
</property>
<property name="value">
<double>30.000000000000000</double>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
@@ -169,22 +304,12 @@
<item>
<widget class="QGroupBox" name="groupBox_filtering">
<property name="title">
<string>Cloud filtering (remove noisy points)</string>
<string>Cloud Filtering (remove noisy points)</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<layout class="QGridLayout" name="gridLayout_9" columnstretch="0,1">
<item row="0" column="1">
<widget class="QLabel" name="label_110">
<property name="text">
<string>Radius search.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QDoubleSpinBox" name="doubleSpinBox_filteringRadius">
<property name="suffix">
@@ -207,6 +332,16 @@
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLabel" name="label_110">
<property name="text">
<string>Radius search.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QSpinBox" name="spinBox_filteringMinNeighbors">
<property name="minimum">
@@ -233,51 +368,10 @@
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox_assemble">
<property name="title">
<string>Assemble clouds to a single output cloud</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<layout class="QGridLayout" name="gridLayout_2" columnstretch="0,1">
<item row="0" column="0">
<widget class="QDoubleSpinBox" name="doubleSpinBox_voxelSize_assembled">
<property name="suffix">
<string> m</string>
</property>
<property name="decimals">
<number>3</number>
</property>
<property name="maximum">
<double>1.000000000000000</double>
</property>
<property name="singleStep">
<double>0.010000000000000</double>
</property>
<property name="value">
<double>0.005000000000000</double>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLabel" name="label_109">
<property name="text">
<string>Voxel size.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox_mls">
<property name="title">
<string>Cloud smoothing using Moving Least Squares algorithm (MLS)</string>
<string>Cloud Smoothing using Moving Least Squares algorithm (MLS)</string>
</property>
<property name="checkable">
<bool>true</bool>
@@ -660,125 +754,243 @@ Guidelines: 4 times the voxel size, 0.025 for voxel=0.</string>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox_gp3">
<widget class="QGroupBox" name="groupBox_meshing">
<property name="title">
<string>Meshing using Greedy Projection Triangulation algorithm (GP3)</string>
<string>Meshing</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>true</bool>
</property>
<layout class="QGridLayout" name="gridLayout_4" columnstretch="0,1">
<item row="2" column="1">
<widget class="QLabel" name="label_169">
<property name="text">
<string>Set the multiplier of the nearest neighbor distance to obtain the final search radius for each point (this will make the algorithm adapt to different point densities in the cloud).</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
<layout class="QVBoxLayout" name="verticalLayout_15">
<item>
<layout class="QGridLayout" name="gridLayout_10" columnstretch="0,1">
<item row="0" column="0">
<widget class="QDoubleSpinBox" name="doubleSpinBox_meshDecimationFactor">
<property name="decimals">
<number>2</number>
</property>
<property name="minimum">
<double>0.000000000000000</double>
</property>
<property name="maximum">
<double>0.990000000000000</double>
</property>
<property name="singleStep">
<double>0.100000000000000</double>
</property>
<property name="value">
<double>0.000000000000000</double>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLabel" name="label_170">
<property name="text">
<string>Mesh quadric decimation factor (0=no decimation). Used to reduce the number of polygons.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QCheckBox" name="checkBox_textureMapping">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLabel" name="label_textureMapping">
<property name="text">
<string>Texture mapping. Images of the cameras will be projected on the mesh(es). Output is a *.obj format.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
<item row="1" column="0">
<widget class="QDoubleSpinBox" name="doubleSpinBox_gp3Radius">
<property name="suffix">
<string> m</string>
<item>
<widget class="QGroupBox" name="groupBox_gp3">
<property name="title">
<string>Greedy Projection Triangulation (GP3) Meshing</string>
</property>
<property name="decimals">
<number>3</number>
<property name="checkable">
<bool>false</bool>
</property>
<property name="maximum">
<double>1.000000000000000</double>
<property name="checked">
<bool>false</bool>
</property>
<property name="singleStep">
<double>0.010000000000000</double>
</property>
<property name="value">
<double>0.040000000000000</double>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLabel" name="label_168">
<property name="text">
<string>Sphere radius that is to be used for determining the k-nearest neighbors used for triangulating (GP3).
<layout class="QGridLayout" name="gridLayout_4" columnstretch="0,1">
<item row="2" column="1">
<widget class="QLabel" name="label_169">
<property name="text">
<string>Set the multiplier of the nearest neighbor distance to obtain the final search radius for each point (this will make the algorithm adapt to different point densities in the cloud).</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QDoubleSpinBox" name="doubleSpinBox_gp3Radius">
<property name="suffix">
<string> m</string>
</property>
<property name="decimals">
<number>3</number>
</property>
<property name="maximum">
<double>1.000000000000000</double>
</property>
<property name="singleStep">
<double>0.010000000000000</double>
</property>
<property name="value">
<double>0.040000000000000</double>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLabel" name="label_168">
<property name="text">
<string>Sphere radius that is to be used for determining the k-nearest neighbors used for triangulating (GP3).
Guidelines: 4 times the voxel size, 0.025 for voxel=0.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QDoubleSpinBox" name="doubleSpinBox_gp3Mu">
<property name="decimals">
<number>1</number>
</property>
<property name="minimum">
<double>0.100000000000000</double>
</property>
<property name="maximum">
<double>100.000000000000000</double>
</property>
<property name="singleStep">
<double>1.000000000000000</double>
</property>
<property name="value">
<double>2.500000000000000</double>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="2" column="0">
<widget class="QDoubleSpinBox" name="doubleSpinBox_gp3Mu">
<property name="decimals">
<number>1</number>
</property>
<property name="minimum">
<double>0.100000000000000</double>
</property>
<property name="maximum">
<double>100.000000000000000</double>
</property>
<property name="singleStep">
<double>1.000000000000000</double>
</property>
<property name="value">
<double>2.500000000000000</double>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QCheckBox" name="checkBox_textureMapping">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QLabel" name="label_textureMapping">
<property name="text">
<string>Texture mapping. Images of the cameras will be projected on the mesh(es). Output is a *.obj format.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QLabel" name="label_170">
<property name="text">
<string>Mesh quadric decimation factor (0=no decimation). Used to reduce the number of polygons.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QDoubleSpinBox" name="doubleSpinBox_meshDecimationFactor">
<property name="decimals">
<number>2</number>
</property>
<property name="minimum">
<double>0.000000000000000</double>
</property>
<property name="maximum">
<double>0.990000000000000</double>
</property>
<property name="singleStep">
<double>0.100000000000000</double>
</property>
<property name="value">
<double>0.000000000000000</double>
<item>
<widget class="QGroupBox" name="groupBox_organized">
<property name="title">
<string>Organized Meshing</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_17">
<item>
<layout class="QGridLayout" name="gridLayout_2" columnstretch="0,1">
<item row="0" column="1">
<widget class="QLabel" name="label_14">
<property name="text">
<string>Angle tolerance</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QCheckBox" name="checkBox_mesh_quad">
<property name="text">
<string/>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLabel" name="label_quad">
<property name="text">
<string>Quad</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QSpinBox" name="spinBox_mesh_triangleSize">
<property name="suffix">
<string> pix</string>
</property>
<property name="minimum">
<number>2</number>
</property>
<property name="maximum">
<number>99</number>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLabel" name="label_15">
<property name="text">
<string>Triangle size</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QDoubleSpinBox" name="doubleSpinBox_mesh_angleTolerance">
<property name="suffix">
<string> deg</string>
</property>
<property name="decimals">
<number>0</number>
</property>
<property name="minimum">
<double>1.000000000000000</double>
</property>
<property name="maximum">
<double>99.000000000000000</double>
</property>
<property name="value">
<double>15.000000000000000</double>
</property>
</widget>
</item>
</layout>
</item>
<item>
<spacer name="verticalSpacer_8">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<spacer name="verticalSpacer_9">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
</spacer>
</item>
<item>
<spacer name="verticalSpacer_7">
<property name="orientation">

File diff suppressed because it is too large Load Diff