28 #include <VisionX/interface/core/PointCloudProviderInterface.h>
30 #include <AffordanceKit/primitives/Plane.h>
34 #include <QDoubleSpinBox>
38 #include <pcl/io/pcd_io.h>
39 #include <pcl/point_types.h>
40 #include <pcl/common/transforms.h>
46 #define PI 3.141592654
64 pointCloudProviderName = settings->value(
"pointCloudProviderName",
"").toString().toStdString();
65 pointCloudSegmenterName = settings->value(
"pointCloudSegmenterName",
"").toString().toStdString();
66 primitiveExtractorName = settings->value(
"primitiveExtractorName",
"").toString().toStdString();
67 pipelineVisualizationName = settings->value(
"pipelineVisualizationName",
"").toString().toStdString();
68 workingMemoryName = settings->value(
"workingMemoryName",
"").toString().toStdString();
73 settings->setValue(
"pointCloudProviderName", QString::fromStdString(pointCloudProviderName));
74 settings->setValue(
"pointCloudSegmenterName", QString::fromStdString(pointCloudSegmenterName));
75 settings->setValue(
"primitiveExtractorName", QString::fromStdString(primitiveExtractorName));
76 settings->setValue(
"pipelineVisualizationName", QString::fromStdString(pipelineVisualizationName));
77 settings->setValue(
"workingMemoryName", QString::fromStdString(workingMemoryName));
87 return qobject_cast<PrimitiveExtractionConfigDialog*>(configDialog);
92 pointCloudProviderName = configDialog->pointCloudProviderProxyFinder->getSelectedProxyName().toStdString();
93 pointCloudSegmenterName = configDialog->pointCloudSegmenterProxyFinder->getSelectedProxyName().toStdString();
94 primitiveExtractorName = configDialog->primitiveExtractorProxyFinder->getSelectedProxyName().toStdString();
95 pipelineVisualizationName = configDialog->pipelineVisualizationProxyFinder->getSelectedProxyName().toStdString();
96 workingMemoryName = configDialog->pipelineVisualizationProxyFinder->getSelectedProxyName().toStdString();
106 pointCloudProvider = getProxy<visionx::PointCloudProviderInterfacePrx>(pointCloudProviderName);
107 if (!pointCloudProvider)
109 ARMARX_ERROR <<
"Could not obtain point cloud provider proxy";
113 visionx::FakePointCloudProviderInterfacePrx _fakePointCloudProvider = visionx::FakePointCloudProviderInterfacePrx::checkedCast(pointCloudProvider);
114 if (_fakePointCloudProvider)
116 widget.pushButtonLoadPointCloud->setEnabled(
true);
120 widget.pushButtonLoadPointCloud->setEnabled(
false);
124 if (pointCloudSegmenterName !=
"")
128 pointCloudSegmenter = getProxy<visionx::PointCloudSegmenterInterfacePrx>(pointCloudSegmenterName);
130 catch (
const armarx::UserException& e)
132 ARMARX_INFO <<
"No segmenter found, assuming ground truth segmentation";
136 primitiveExtractor = getProxy<visionx::PrimitiveMapperInterfacePrx>(primitiveExtractorName);
137 if (!primitiveExtractor)
139 ARMARX_ERROR <<
"Could not obtain primitive extractor proxy";
143 pipelineVisualization = getProxy<AffordancePipelineVisualizationInterfacePrx>(pipelineVisualizationName);
144 if (!pipelineVisualization)
146 ARMARX_ERROR <<
"Could not obtain affordance pipeline visualization proxy";
150 workingMemory = getProxy<memoryx::WorkingMemoryInterfacePrx>(workingMemoryName);
153 ARMARX_ERROR <<
"Could not obtain point working memory proxy";
157 debugDrawer = getTopic<DebugDrawerInterfacePrx>(
"DebugDrawerUpdates");
164 connect(widget.pushButtonLoadPointCloud, SIGNAL(clicked()),
this, SLOT(
loadPointCloud()));
165 connect(widget.pushButtonRun, SIGNAL(clicked()),
this, SLOT(
run()));
166 connect(widget.pushButtonSetParam, SIGNAL(clicked()),
this, SLOT(
setParameters()));
168 connect(widget.pushButtonApplyAutoRotate, SIGNAL(clicked()),
this, SLOT(
applyAutoRotation()));
171 connect(widget.pushButtonImportConfig, SIGNAL(clicked()),
this, SLOT(
importConfig()));
172 connect(widget.pushButtonExportConfig, SIGNAL(clicked()),
this, SLOT(
exportConfig()));
174 if (pointCloudSegmenter)
176 visionx::LccpParameters lccpParameters = pointCloudSegmenter->getLccpParameters();
177 widget.doubleSpinBoxLccpMinSegmentSize->setValue(lccpParameters.minSegmentSize);
178 widget.doubleSpinBoxLccpVoxelResolution->setValue(lccpParameters.voxelResolution);
179 widget.doubleSpinBoxLccpSeedResolution->setValue(lccpParameters.seedResolution);
180 widget.doubleSpinBoxLccpColorImportance->setValue(lccpParameters.colorImportance);
181 widget.doubleSpinBoxLccpSpatialImportance->setValue(lccpParameters.spatialImportance);
182 widget.doubleSpinBoxLccpNormalImportance->setValue(lccpParameters.normalImportance);
183 widget.doubleSpinBoxLccpConcavityThreshold->setValue(lccpParameters.concavityThreshold);
184 widget.doubleSpinBoxLccpSmoothnessThreshold->setValue(lccpParameters.smoothnessThreshold);
188 widget.doubleSpinBoxLccpMinSegmentSize->setEnabled(
false);
189 widget.doubleSpinBoxLccpVoxelResolution->setEnabled(
false);
190 widget.doubleSpinBoxLccpSeedResolution->setEnabled(
false);
191 widget.doubleSpinBoxLccpColorImportance->setEnabled(
false);
192 widget.doubleSpinBoxLccpSpatialImportance->setEnabled(
false);
193 widget.doubleSpinBoxLccpNormalImportance->setEnabled(
false);
194 widget.doubleSpinBoxLccpConcavityThreshold->setEnabled(
false);
195 widget.doubleSpinBoxLccpSmoothnessThreshold->setEnabled(
false);
198 visionx::PrimitiveExtractorParameters primtiveParameters = primitiveExtractor->getParameters();
199 ARMARX_LOG <<
"parameters " << primtiveParameters.minSegmentSize;
200 widget.doubleSpinBoxMinPrimitiveSize->setValue(primtiveParameters.minSegmentSize);
201 widget.doubleSpinBoxMaxPrimitiveSize->setValue(primtiveParameters.maxSegmentSize);
202 widget.doubleSpinBoxEuclideanClusteringTolerance->setValue(primtiveParameters.euclideanClusteringTolerance);
203 widget.doubleSpinBoxOutlierDistanceThreshold->setValue(primtiveParameters.outlierThreshold);
205 widget.doubleSpinBoxPlaneMaxIterations->setValue(primtiveParameters.planeMaxIterations);
206 widget.doubleSpinBoxPlaneDistanceThreshold->setValue(primtiveParameters.planeDistanceThreshold);
207 widget.doubleSpinBoxPlaneNormalDistance->setValue(primtiveParameters.planeNormalDistance);
208 widget.doubleSpinBoxPlaneCircularDistanceThreshold->setValue(primtiveParameters.circularDistanceThreshold);
210 widget.doubleSpinBoxCylinderMaxIterations->setValue(primtiveParameters.cylinderMaxIterations);
211 widget.doubleSpinBoxCylinderDistanceThreshold->setValue(primtiveParameters.cylinderDistanceThreshold);
212 widget.doubleSpinBoxCylinderRadiusLimit->setValue(primtiveParameters.cylinderRadiusLimit);
214 widget.doubleSpinBoxSphereMaxIterations->setValue(primtiveParameters.sphereMaxIterations);
215 widget.doubleSpinBoxSphereDistanceThreshold->setValue(primtiveParameters.sphereDistanceThreshold);
216 widget.doubleSpinBoxSphereNormalDistance->setValue(primtiveParameters.sphereNormalDistance);
222 QObject::disconnect(
this, SLOT(
run()));
231 QString
filename = QFileDialog::getOpenFileName(NULL,
"Open Point Cloud",
"",
"Point Cloud Files (*.pcd)");
234 widget.lineEditPointCloud->setText(
filename);
240 visionx::FakePointCloudProviderInterfacePrx _fakePointCloudProvider = visionx::FakePointCloudProviderInterfacePrx::checkedCast(pointCloudProvider);
241 if (_fakePointCloudProvider)
243 std::string path = widget.lineEditPointCloud->text().toStdString();
244 _fakePointCloudProvider->setPointCloudFilename(path);
247 if (pointCloudSegmenter)
249 visionx::LccpParameters segmenterPrm;
250 segmenterPrm.minSegmentSize = widget.doubleSpinBoxLccpMinSegmentSize->value();
251 segmenterPrm.voxelResolution = widget.doubleSpinBoxLccpVoxelResolution->value();
252 segmenterPrm.seedResolution = widget.doubleSpinBoxLccpSeedResolution->value();
253 segmenterPrm.colorImportance = widget.doubleSpinBoxLccpColorImportance->value();
254 segmenterPrm.spatialImportance = widget.doubleSpinBoxLccpSpatialImportance->value();
255 segmenterPrm.normalImportance = widget.doubleSpinBoxLccpNormalImportance->value();
256 segmenterPrm.concavityThreshold = widget.doubleSpinBoxLccpConcavityThreshold->value();
257 segmenterPrm.smoothnessThreshold = widget.doubleSpinBoxLccpSmoothnessThreshold->value();
258 pointCloudSegmenter->setLccpParameters(segmenterPrm);
261 visionx::PrimitiveExtractorParameters primitiveExtractionPrm;
262 primitiveExtractionPrm.minSegmentSize = widget.doubleSpinBoxMinPrimitiveSize->value();
263 primitiveExtractionPrm.maxSegmentSize = widget.doubleSpinBoxMaxPrimitiveSize->value();
264 primitiveExtractionPrm.planeMaxIterations = widget.doubleSpinBoxPlaneMaxIterations->value();
265 primitiveExtractionPrm.planeDistanceThreshold = widget.doubleSpinBoxPlaneDistanceThreshold->value();
266 primitiveExtractionPrm.planeNormalDistance = widget.doubleSpinBoxPlaneNormalDistance->value();
267 primitiveExtractionPrm.cylinderMaxIterations = widget.doubleSpinBoxCylinderMaxIterations->value();
268 primitiveExtractionPrm.cylinderDistanceThreshold = widget.doubleSpinBoxCylinderDistanceThreshold->value();
269 primitiveExtractionPrm.cylinderRadiusLimit = widget.doubleSpinBoxCylinderRadiusLimit->value();
270 primitiveExtractionPrm.sphereMaxIterations = widget.doubleSpinBoxSphereMaxIterations->value();
271 primitiveExtractionPrm.sphereDistanceThreshold = widget.doubleSpinBoxSphereDistanceThreshold->value();
272 primitiveExtractionPrm.sphereNormalDistance = widget.doubleSpinBoxSphereNormalDistance->value();
273 primitiveExtractionPrm.euclideanClusteringTolerance = widget.doubleSpinBoxEuclideanClusteringTolerance->value();
274 primitiveExtractionPrm.outlierThreshold = widget.doubleSpinBoxOutlierDistanceThreshold->value();
275 primitiveExtractionPrm.circularDistanceThreshold = widget.doubleSpinBoxPlaneCircularDistanceThreshold->value();
276 primitiveExtractor->setParameters(primitiveExtractionPrm);
283 visionx::CapturingPointCloudProviderInterfacePrx cx = visionx::CapturingPointCloudProviderInterfacePrx::checkedCast(pointCloudProvider);
286 cx->begin_startCaptureForNumFrames(1);
293 pipelineVisualization->begin_enableVisualization(widget.checkBoxShowPrimitives->isChecked(),
false,
false);
295 if (widget.checkBoxShowRootPose->isChecked())
301 debugDrawer->removePoseVisu(
"PrimitiveExtractorGuiLayer",
"RootPose");
307 std::string
filename = widget.lineEditPointCloud->text().toStdString();
315 pcl::PointCloud<pcl::PointXYZRGBA>::Ptr
pc(
new pcl::PointCloud<pcl::PointXYZRGBA>());
316 if (pcl::io::loadPCDFile<pcl::PointXYZRGBA>(
filename.c_str(), *
pc) == -1)
323 Eigen::Affine3f scaling(Eigen::Scaling((
float)widget.doubleSpinBoxScaling->value()));
324 pcl::transformPointCloud(*
pc, *
pc, scaling);
326 std::string out_filename = QFileDialog::getSaveFileName(NULL,
"Save transformed PCD",
filename.c_str(),
"Point Cloud Files (*.pcd)").toStdString();
329 pcl::io::savePCDFileASCII(out_filename, *
pc);
336 QString
filename = QFileDialog::getOpenFileName(NULL,
"Open Pipeline Configuration file",
"",
"Config file (*.cfg)");
342 QSettings config(
filename, QSettings::IniFormat);
344 config.beginGroup(
"LCCP");
345 widget.doubleSpinBoxLccpMinSegmentSize->setValue(config.value(
"MinSegmentSize", widget.doubleSpinBoxLccpMinSegmentSize->value()).toDouble());
346 widget.doubleSpinBoxLccpVoxelResolution->setValue(config.value(
"VoxelResolution", widget.doubleSpinBoxLccpVoxelResolution->value()).toDouble());
347 widget.doubleSpinBoxLccpSeedResolution->setValue(config.value(
"SeedResolution", widget.doubleSpinBoxLccpSeedResolution->value()).toDouble());
348 widget.doubleSpinBoxLccpColorImportance->setValue(config.value(
"ColorImportance", widget.doubleSpinBoxLccpColorImportance->value()).toDouble());
349 widget.doubleSpinBoxLccpSpatialImportance->setValue(config.value(
"SpatialImportance", widget.doubleSpinBoxLccpSpatialImportance->value()).toDouble());
350 widget.doubleSpinBoxLccpNormalImportance->setValue(config.value(
"NormalImportance", widget.doubleSpinBoxLccpNormalImportance->value()).toDouble());
351 widget.doubleSpinBoxLccpConcavityThreshold->setValue(config.value(
"ConcavityThreshold", widget.doubleSpinBoxLccpConcavityThreshold->value()).toDouble());
352 widget.doubleSpinBoxLccpSmoothnessThreshold->setValue(config.value(
"SmoothnessThreshold", widget.doubleSpinBoxLccpSmoothnessThreshold->value()).toDouble());
355 config.beginGroup(
"PrimitiveExtraction");
356 widget.doubleSpinBoxMinPrimitiveSize->setValue(config.value(
"MinPrimitiveSize", widget.doubleSpinBoxMinPrimitiveSize->value()).toDouble());
357 widget.doubleSpinBoxMaxPrimitiveSize->setValue(config.value(
"MaxPrimitiveSize", widget.doubleSpinBoxMaxPrimitiveSize->value()).toDouble());
358 widget.doubleSpinBoxPlaneMaxIterations->setValue(config.value(
"PlaneMaxIterations", widget.doubleSpinBoxPlaneMaxIterations->value()).toDouble());
359 widget.doubleSpinBoxPlaneDistanceThreshold->setValue(config.value(
"PlaneDistanceThreshold", widget.doubleSpinBoxPlaneDistanceThreshold->value()).toDouble());
360 widget.doubleSpinBoxPlaneNormalDistance->setValue(config.value(
"PlaneNormalDistance", widget.doubleSpinBoxPlaneNormalDistance->value()).toDouble());
361 widget.doubleSpinBoxPlaneCircularDistanceThreshold->setValue(config.value(
"PlaneCircularDistanceThreshold", widget.doubleSpinBoxPlaneCircularDistanceThreshold->value()).toDouble());
362 widget.doubleSpinBoxCylinderMaxIterations->setValue(config.value(
"CylinderMaxIterations", widget.doubleSpinBoxCylinderMaxIterations->value()).toDouble());
363 widget.doubleSpinBoxCylinderDistanceThreshold->setValue(config.value(
"CylinderDistanceThreshold", widget.doubleSpinBoxCylinderDistanceThreshold->value()).toDouble());
364 widget.doubleSpinBoxCylinderRadiusLimit->setValue(config.value(
"CylinderRadiusLimit", widget.doubleSpinBoxSphereMaxIterations->value()).toDouble());
365 widget.doubleSpinBoxSphereMaxIterations->setValue(config.value(
"SphereMaxIterations", widget.doubleSpinBoxSphereMaxIterations->value()).toDouble());
366 widget.doubleSpinBoxSphereDistanceThreshold->setValue(config.value(
"SphereDistanceThreshold", widget.doubleSpinBoxSphereDistanceThreshold->value()).toDouble());
367 widget.doubleSpinBoxSphereNormalDistance->setValue(config.value(
"SphereNormalDistance", widget.doubleSpinBoxSphereNormalDistance->value()).toDouble());
368 widget.doubleSpinBoxEuclideanClusteringTolerance->setValue(config.value(
"EuclideanClusteringTolerance", widget.doubleSpinBoxEuclideanClusteringTolerance->value()).toDouble());
369 widget.doubleSpinBoxOutlierDistanceThreshold->setValue(config.value(
"OutlierDistanceThreshold", widget.doubleSpinBoxOutlierDistanceThreshold->value()).toDouble());
377 QString
filename = QFileDialog::getSaveFileName(NULL,
"Save Pipeline Configuration file",
"",
"Config file (*.cfg)");
383 QSettings config(
filename, QSettings::IniFormat);
385 config.beginGroup(
"LCCP");
386 config.setValue(
"MinSegmentSize", widget.doubleSpinBoxLccpMinSegmentSize->value());
387 config.setValue(
"VoxelResolution", widget.doubleSpinBoxLccpVoxelResolution->value());
388 config.setValue(
"SeedResolution", widget.doubleSpinBoxLccpSeedResolution->value());
389 config.setValue(
"ColorImportance", widget.doubleSpinBoxLccpColorImportance->value());
390 config.setValue(
"SpatialImportance", widget.doubleSpinBoxLccpSpatialImportance->value());
391 config.setValue(
"NormalImportance", widget.doubleSpinBoxLccpNormalImportance->value());
392 config.setValue(
"ConcavityThreshold", widget.doubleSpinBoxLccpConcavityThreshold->value());
393 config.setValue(
"SmoothnessThreshold", widget.doubleSpinBoxLccpSmoothnessThreshold->value());
396 config.beginGroup(
"PrimitiveExtraction");
397 config.setValue(
"MinPrimitiveSize", widget.doubleSpinBoxMinPrimitiveSize->value());
398 config.setValue(
"MaxPrimitiveSize", widget.doubleSpinBoxMaxPrimitiveSize->value());
399 config.setValue(
"PlaneMaxIterations", widget.doubleSpinBoxPlaneMaxIterations->value());
400 config.setValue(
"PlaneDistanceThreshold", widget.doubleSpinBoxPlaneDistanceThreshold->value());
401 config.setValue(
"PlaneNormalDistance", widget.doubleSpinBoxPlaneNormalDistance->value());
402 config.setValue(
"PlaneCircularDistanceThreshold", widget.doubleSpinBoxPlaneCircularDistanceThreshold->value());
403 config.setValue(
"CylinderMaxIterations", widget.doubleSpinBoxCylinderMaxIterations->value());
404 config.setValue(
"CylinderDistanceThreshold", widget.doubleSpinBoxCylinderDistanceThreshold->value());
405 config.setValue(
"CylinderRadiusLimit", widget.doubleSpinBoxSphereMaxIterations->value());
406 config.setValue(
"SphereMaxIterations", widget.doubleSpinBoxSphereMaxIterations->value());
407 config.setValue(
"SphereDistanceThreshold", widget.doubleSpinBoxSphereDistanceThreshold->value());
408 config.setValue(
"SphereNormalDistance", widget.doubleSpinBoxSphereNormalDistance->value());
409 config.setValue(
"EuclideanClusteringTolerance", widget.doubleSpinBoxEuclideanClusteringTolerance->value());
410 config.setValue(
"OutlierDistanceThreshold", widget.doubleSpinBoxOutlierDistanceThreshold->value());
426 unsigned int indexOfBiggestPrimitive;
427 unsigned int maxSampleSize = 0;
429 using boost::dynamic_pointer_cast;
430 using std::dynamic_pointer_cast;
433 for (
unsigned int i = 0; i < primitives->size(); i++)
435 AffordanceKit::PrimitivePtr primitive = primitives->at(i);
436 if (!dynamic_pointer_cast<AffordanceKit::Plane>(primitive))
440 AffordanceKit::PlanePtr plane = dynamic_pointer_cast<AffordanceKit::Plane>(primitive);
441 plane->sample(20, 1);
442 unsigned int curPlaneSize = plane->getSamplingSize();
443 if (curPlaneSize > maxSampleSize)
446 maxSampleSize = curPlaneSize;
447 indexOfBiggestPrimitive = i;
453 ARMARX_WARNING <<
"Did not find any plane-shaped primitives to rotate upon!";
458 AffordanceKit::PrimitivePtr primitive = primitives->at(indexOfBiggestPrimitive);
459 if (!dynamic_pointer_cast<AffordanceKit::Plane>(primitive))
461 ARMARX_ERROR <<
"Could not convert to planar primitive";
464 AffordanceKit::PlanePtr plane = dynamic_pointer_cast<AffordanceKit::Plane>(primitive);
467 debugDrawer->setPoseVisu(
"PrimitiveExtractorGuiLayer",
"BiggestPlaneRotation",
new Pose(gp));
472 std::string
filename = widget.lineEditPointCloud->text().toStdString();
473 pcl::PointCloud<pcl::PointXYZRGBA>::Ptr
pc(
new pcl::PointCloud<pcl::PointXYZRGBA>());
474 if (pcl::io::loadPCDFile<pcl::PointXYZRGBA>(
filename.c_str(), *
pc) == -1)
481 pcl::transformPointCloud(*
pc, *
pc, gpi);
485 for (
unsigned int i = 0; i <
pc->points.size(); i++)
487 balance += (
pc->points[i].z >= 0) ? 1 : -1;
490 ARMARX_INFO <<
"Z-axis balance after transformation: " << balance;
494 Eigen::Affine3f rotation(Eigen::AngleAxisf(
M_PI, Eigen::Vector3f::UnitX()));
495 pcl::transformPointCloud(*
pc, *
pc, rotation);
501 debugDrawer->setPoseVisu(
"PrimitiveExtractorGuiLayer",
"BiggestPlaneRotation",
new Pose(
T * gp));
504 std::string out_filename = QFileDialog::getSaveFileName(NULL,
"Save transformed PCD",
filename.c_str(),
"Point Cloud Files (*.pcd)").toStdString();
507 pcl::io::savePCDFileASCII(out_filename, *
pc);