31 #include <QDoubleSpinBox>
33 #include <pcl/common/transforms.h>
34 #include <pcl/io/pcd_io.h>
35 #include <pcl/point_types.h>
40 #include <VisionX/interface/core/PointCloudProviderInterface.h>
43 #include <AffordanceKit/primitives/Plane.h>
45 #define PI 3.141592654
61 pointCloudProviderName =
62 settings->value(
"pointCloudProviderName",
"").toString().toStdString();
63 pointCloudSegmenterName =
64 settings->value(
"pointCloudSegmenterName",
"").toString().toStdString();
65 primitiveExtractorName =
66 settings->value(
"primitiveExtractorName",
"").toString().toStdString();
67 pipelineVisualizationName =
68 settings->value(
"pipelineVisualizationName",
"").toString().toStdString();
69 workingMemoryName = settings->value(
"workingMemoryName",
"").toString().toStdString();
75 settings->setValue(
"pointCloudProviderName",
76 QString::fromStdString(pointCloudProviderName));
77 settings->setValue(
"pointCloudSegmenterName",
78 QString::fromStdString(pointCloudSegmenterName));
79 settings->setValue(
"primitiveExtractorName",
80 QString::fromStdString(primitiveExtractorName));
81 settings->setValue(
"pipelineVisualizationName",
82 QString::fromStdString(pipelineVisualizationName));
83 settings->setValue(
"workingMemoryName", QString::fromStdString(workingMemoryName));
94 return qobject_cast<PrimitiveExtractionConfigDialog*>(configDialog);
100 pointCloudProviderName =
101 configDialog->pointCloudProviderProxyFinder->getSelectedProxyName().toStdString();
102 pointCloudSegmenterName =
103 configDialog->pointCloudSegmenterProxyFinder->getSelectedProxyName().toStdString();
104 primitiveExtractorName =
105 configDialog->primitiveExtractorProxyFinder->getSelectedProxyName().toStdString();
106 pipelineVisualizationName =
107 configDialog->pipelineVisualizationProxyFinder->getSelectedProxyName().toStdString();
109 configDialog->pipelineVisualizationProxyFinder->getSelectedProxyName().toStdString();
121 getProxy<visionx::PointCloudProviderInterfacePrx>(pointCloudProviderName);
122 if (!pointCloudProvider)
124 ARMARX_ERROR <<
"Could not obtain point cloud provider proxy";
128 visionx::FakePointCloudProviderInterfacePrx _fakePointCloudProvider =
129 visionx::FakePointCloudProviderInterfacePrx::checkedCast(pointCloudProvider);
130 if (_fakePointCloudProvider)
132 widget.pushButtonLoadPointCloud->setEnabled(
true);
136 widget.pushButtonLoadPointCloud->setEnabled(
false);
140 if (pointCloudSegmenterName !=
"")
144 pointCloudSegmenter =
145 getProxy<visionx::PointCloudSegmenterInterfacePrx>(pointCloudSegmenterName);
147 catch (
const armarx::UserException& e)
149 ARMARX_INFO <<
"No segmenter found, assuming ground truth segmentation";
153 primitiveExtractor = getProxy<visionx::PrimitiveMapperInterfacePrx>(primitiveExtractorName);
154 if (!primitiveExtractor)
156 ARMARX_ERROR <<
"Could not obtain primitive extractor proxy";
160 pipelineVisualization =
161 getProxy<AffordancePipelineVisualizationInterfacePrx>(pipelineVisualizationName);
162 if (!pipelineVisualization)
164 ARMARX_ERROR <<
"Could not obtain affordance pipeline visualization proxy";
168 workingMemory = getProxy<memoryx::WorkingMemoryInterfacePrx>(workingMemoryName);
171 ARMARX_ERROR <<
"Could not obtain point working memory proxy";
175 debugDrawer = getTopic<DebugDrawerInterfacePrx>(
"DebugDrawerUpdates");
182 connect(widget.pushButtonLoadPointCloud, SIGNAL(clicked()),
this, SLOT(
loadPointCloud()));
183 connect(widget.pushButtonRun, SIGNAL(clicked()),
this, SLOT(
run()));
184 connect(widget.pushButtonSetParam, SIGNAL(clicked()),
this, SLOT(
setParameters()));
185 connect(widget.pushButtonApplyTransformation,
190 widget.pushButtonApplyAutoRotate, SIGNAL(clicked()),
this, SLOT(
applyAutoRotation()));
191 connect(widget.checkBoxShowPrimitives,
192 SIGNAL(toggled(
bool)),
195 connect(widget.checkBoxShowRootPose,
196 SIGNAL(toggled(
bool)),
199 connect(widget.pushButtonImportConfig, SIGNAL(clicked()),
this, SLOT(
importConfig()));
200 connect(widget.pushButtonExportConfig, SIGNAL(clicked()),
this, SLOT(
exportConfig()));
202 if (pointCloudSegmenter)
204 visionx::LccpParameters lccpParameters = pointCloudSegmenter->getLccpParameters();
205 widget.doubleSpinBoxLccpMinSegmentSize->setValue(lccpParameters.minSegmentSize);
206 widget.doubleSpinBoxLccpVoxelResolution->setValue(lccpParameters.voxelResolution);
207 widget.doubleSpinBoxLccpSeedResolution->setValue(lccpParameters.seedResolution);
208 widget.doubleSpinBoxLccpColorImportance->setValue(lccpParameters.colorImportance);
209 widget.doubleSpinBoxLccpSpatialImportance->setValue(lccpParameters.spatialImportance);
210 widget.doubleSpinBoxLccpNormalImportance->setValue(lccpParameters.normalImportance);
211 widget.doubleSpinBoxLccpConcavityThreshold->setValue(lccpParameters.concavityThreshold);
212 widget.doubleSpinBoxLccpSmoothnessThreshold->setValue(
213 lccpParameters.smoothnessThreshold);
217 widget.doubleSpinBoxLccpMinSegmentSize->setEnabled(
false);
218 widget.doubleSpinBoxLccpVoxelResolution->setEnabled(
false);
219 widget.doubleSpinBoxLccpSeedResolution->setEnabled(
false);
220 widget.doubleSpinBoxLccpColorImportance->setEnabled(
false);
221 widget.doubleSpinBoxLccpSpatialImportance->setEnabled(
false);
222 widget.doubleSpinBoxLccpNormalImportance->setEnabled(
false);
223 widget.doubleSpinBoxLccpConcavityThreshold->setEnabled(
false);
224 widget.doubleSpinBoxLccpSmoothnessThreshold->setEnabled(
false);
227 visionx::PrimitiveExtractorParameters primtiveParameters =
228 primitiveExtractor->getParameters();
229 ARMARX_LOG <<
"parameters " << primtiveParameters.minSegmentSize;
230 widget.doubleSpinBoxMinPrimitiveSize->setValue(primtiveParameters.minSegmentSize);
231 widget.doubleSpinBoxMaxPrimitiveSize->setValue(primtiveParameters.maxSegmentSize);
232 widget.doubleSpinBoxEuclideanClusteringTolerance->setValue(
233 primtiveParameters.euclideanClusteringTolerance);
234 widget.doubleSpinBoxOutlierDistanceThreshold->setValue(primtiveParameters.outlierThreshold);
236 widget.doubleSpinBoxPlaneMaxIterations->setValue(primtiveParameters.planeMaxIterations);
237 widget.doubleSpinBoxPlaneDistanceThreshold->setValue(
238 primtiveParameters.planeDistanceThreshold);
239 widget.doubleSpinBoxPlaneNormalDistance->setValue(primtiveParameters.planeNormalDistance);
240 widget.doubleSpinBoxPlaneCircularDistanceThreshold->setValue(
241 primtiveParameters.circularDistanceThreshold);
243 widget.doubleSpinBoxCylinderMaxIterations->setValue(
244 primtiveParameters.cylinderMaxIterations);
245 widget.doubleSpinBoxCylinderDistanceThreshold->setValue(
246 primtiveParameters.cylinderDistanceThreshold);
247 widget.doubleSpinBoxCylinderRadiusLimit->setValue(primtiveParameters.cylinderRadiusLimit);
249 widget.doubleSpinBoxSphereMaxIterations->setValue(primtiveParameters.sphereMaxIterations);
250 widget.doubleSpinBoxSphereDistanceThreshold->setValue(
251 primtiveParameters.sphereDistanceThreshold);
252 widget.doubleSpinBoxSphereNormalDistance->setValue(primtiveParameters.sphereNormalDistance);
259 QObject::disconnect(
this, SLOT(
run()));
270 QFileDialog::getOpenFileName(NULL,
"Open Point Cloud",
"",
"Point Cloud Files (*.pcd)");
273 widget.lineEditPointCloud->setText(
filename);
280 visionx::FakePointCloudProviderInterfacePrx _fakePointCloudProvider =
281 visionx::FakePointCloudProviderInterfacePrx::checkedCast(pointCloudProvider);
282 if (_fakePointCloudProvider)
284 std::string path = widget.lineEditPointCloud->text().toStdString();
285 _fakePointCloudProvider->setPointCloudFilename(path);
288 if (pointCloudSegmenter)
290 visionx::LccpParameters segmenterPrm;
291 segmenterPrm.minSegmentSize = widget.doubleSpinBoxLccpMinSegmentSize->value();
292 segmenterPrm.voxelResolution = widget.doubleSpinBoxLccpVoxelResolution->value();
293 segmenterPrm.seedResolution = widget.doubleSpinBoxLccpSeedResolution->value();
294 segmenterPrm.colorImportance = widget.doubleSpinBoxLccpColorImportance->value();
295 segmenterPrm.spatialImportance = widget.doubleSpinBoxLccpSpatialImportance->value();
296 segmenterPrm.normalImportance = widget.doubleSpinBoxLccpNormalImportance->value();
297 segmenterPrm.concavityThreshold = widget.doubleSpinBoxLccpConcavityThreshold->value();
298 segmenterPrm.smoothnessThreshold = widget.doubleSpinBoxLccpSmoothnessThreshold->value();
299 pointCloudSegmenter->setLccpParameters(segmenterPrm);
302 visionx::PrimitiveExtractorParameters primitiveExtractionPrm;
303 primitiveExtractionPrm.minSegmentSize = widget.doubleSpinBoxMinPrimitiveSize->value();
304 primitiveExtractionPrm.maxSegmentSize = widget.doubleSpinBoxMaxPrimitiveSize->value();
305 primitiveExtractionPrm.planeMaxIterations = widget.doubleSpinBoxPlaneMaxIterations->value();
306 primitiveExtractionPrm.planeDistanceThreshold =
307 widget.doubleSpinBoxPlaneDistanceThreshold->value();
308 primitiveExtractionPrm.planeNormalDistance =
309 widget.doubleSpinBoxPlaneNormalDistance->value();
310 primitiveExtractionPrm.cylinderMaxIterations =
311 widget.doubleSpinBoxCylinderMaxIterations->value();
312 primitiveExtractionPrm.cylinderDistanceThreshold =
313 widget.doubleSpinBoxCylinderDistanceThreshold->value();
314 primitiveExtractionPrm.cylinderRadiusLimit =
315 widget.doubleSpinBoxCylinderRadiusLimit->value();
316 primitiveExtractionPrm.sphereMaxIterations =
317 widget.doubleSpinBoxSphereMaxIterations->value();
318 primitiveExtractionPrm.sphereDistanceThreshold =
319 widget.doubleSpinBoxSphereDistanceThreshold->value();
320 primitiveExtractionPrm.sphereNormalDistance =
321 widget.doubleSpinBoxSphereNormalDistance->value();
322 primitiveExtractionPrm.euclideanClusteringTolerance =
323 widget.doubleSpinBoxEuclideanClusteringTolerance->value();
324 primitiveExtractionPrm.outlierThreshold =
325 widget.doubleSpinBoxOutlierDistanceThreshold->value();
326 primitiveExtractionPrm.circularDistanceThreshold =
327 widget.doubleSpinBoxPlaneCircularDistanceThreshold->value();
328 primitiveExtractor->setParameters(primitiveExtractionPrm);
336 visionx::CapturingPointCloudProviderInterfacePrx cx =
337 visionx::CapturingPointCloudProviderInterfacePrx::checkedCast(pointCloudProvider);
340 cx->begin_startCaptureForNumFrames(1);
347 pipelineVisualization->begin_enableVisualization(
348 widget.checkBoxShowPrimitives->isChecked(),
false,
false);
350 if (widget.checkBoxShowRootPose->isChecked())
352 debugDrawer->setPoseVisu(
357 debugDrawer->removePoseVisu(
"PrimitiveExtractorGuiLayer",
"RootPose");
364 std::string
filename = widget.lineEditPointCloud->text().toStdString();
367 !std::filesystem::is_regular_file(
filename))
373 pcl::PointCloud<pcl::PointXYZRGBA>::Ptr
pc(
new pcl::PointCloud<pcl::PointXYZRGBA>());
374 if (pcl::io::loadPCDFile<pcl::PointXYZRGBA>(
filename.c_str(), *
pc) == -1)
381 Eigen::Affine3f scaling(Eigen::Scaling((
float)widget.doubleSpinBoxScaling->value()));
382 pcl::transformPointCloud(*
pc, *
pc, scaling);
384 std::string out_filename =
385 QFileDialog::getSaveFileName(
386 NULL,
"Save transformed PCD",
filename.c_str(),
"Point Cloud Files (*.pcd)")
390 pcl::io::savePCDFileASCII(out_filename, *
pc);
398 QString
filename = QFileDialog::getOpenFileName(
399 NULL,
"Open Pipeline Configuration file",
"",
"Config file (*.cfg)");
405 QSettings config(
filename, QSettings::IniFormat);
407 config.beginGroup(
"LCCP");
408 widget.doubleSpinBoxLccpMinSegmentSize->setValue(
409 config.value(
"MinSegmentSize", widget.doubleSpinBoxLccpMinSegmentSize->value())
411 widget.doubleSpinBoxLccpVoxelResolution->setValue(
412 config.value(
"VoxelResolution", widget.doubleSpinBoxLccpVoxelResolution->value())
414 widget.doubleSpinBoxLccpSeedResolution->setValue(
415 config.value(
"SeedResolution", widget.doubleSpinBoxLccpSeedResolution->value())
417 widget.doubleSpinBoxLccpColorImportance->setValue(
418 config.value(
"ColorImportance", widget.doubleSpinBoxLccpColorImportance->value())
420 widget.doubleSpinBoxLccpSpatialImportance->setValue(
421 config.value(
"SpatialImportance", widget.doubleSpinBoxLccpSpatialImportance->value())
423 widget.doubleSpinBoxLccpNormalImportance->setValue(
424 config.value(
"NormalImportance", widget.doubleSpinBoxLccpNormalImportance->value())
426 widget.doubleSpinBoxLccpConcavityThreshold->setValue(
427 config.value(
"ConcavityThreshold", widget.doubleSpinBoxLccpConcavityThreshold->value())
429 widget.doubleSpinBoxLccpSmoothnessThreshold->setValue(
431 .
value(
"SmoothnessThreshold", widget.doubleSpinBoxLccpSmoothnessThreshold->value())
435 config.beginGroup(
"PrimitiveExtraction");
436 widget.doubleSpinBoxMinPrimitiveSize->setValue(
437 config.value(
"MinPrimitiveSize", widget.doubleSpinBoxMinPrimitiveSize->value())
439 widget.doubleSpinBoxMaxPrimitiveSize->setValue(
440 config.value(
"MaxPrimitiveSize", widget.doubleSpinBoxMaxPrimitiveSize->value())
442 widget.doubleSpinBoxPlaneMaxIterations->setValue(
443 config.value(
"PlaneMaxIterations", widget.doubleSpinBoxPlaneMaxIterations->value())
445 widget.doubleSpinBoxPlaneDistanceThreshold->setValue(
447 .
value(
"PlaneDistanceThreshold",
448 widget.doubleSpinBoxPlaneDistanceThreshold->value())
450 widget.doubleSpinBoxPlaneNormalDistance->setValue(
451 config.value(
"PlaneNormalDistance", widget.doubleSpinBoxPlaneNormalDistance->value())
453 widget.doubleSpinBoxPlaneCircularDistanceThreshold->setValue(
455 .
value(
"PlaneCircularDistanceThreshold",
456 widget.doubleSpinBoxPlaneCircularDistanceThreshold->value())
458 widget.doubleSpinBoxCylinderMaxIterations->setValue(
460 .
value(
"CylinderMaxIterations", widget.doubleSpinBoxCylinderMaxIterations->value())
462 widget.doubleSpinBoxCylinderDistanceThreshold->setValue(
464 .
value(
"CylinderDistanceThreshold",
465 widget.doubleSpinBoxCylinderDistanceThreshold->value())
467 widget.doubleSpinBoxCylinderRadiusLimit->setValue(
468 config.value(
"CylinderRadiusLimit", widget.doubleSpinBoxSphereMaxIterations->value())
470 widget.doubleSpinBoxSphereMaxIterations->setValue(
471 config.value(
"SphereMaxIterations", widget.doubleSpinBoxSphereMaxIterations->value())
473 widget.doubleSpinBoxSphereDistanceThreshold->setValue(
475 .
value(
"SphereDistanceThreshold",
476 widget.doubleSpinBoxSphereDistanceThreshold->value())
478 widget.doubleSpinBoxSphereNormalDistance->setValue(
479 config.value(
"SphereNormalDistance", widget.doubleSpinBoxSphereNormalDistance->value())
481 widget.doubleSpinBoxEuclideanClusteringTolerance->setValue(
483 .
value(
"EuclideanClusteringTolerance",
484 widget.doubleSpinBoxEuclideanClusteringTolerance->value())
486 widget.doubleSpinBoxOutlierDistanceThreshold->setValue(
488 .
value(
"OutlierDistanceThreshold",
489 widget.doubleSpinBoxOutlierDistanceThreshold->value())
499 QString
filename = QFileDialog::getSaveFileName(
500 NULL,
"Save Pipeline Configuration file",
"",
"Config file (*.cfg)");
506 QSettings config(
filename, QSettings::IniFormat);
508 config.beginGroup(
"LCCP");
509 config.setValue(
"MinSegmentSize", widget.doubleSpinBoxLccpMinSegmentSize->value());
510 config.setValue(
"VoxelResolution", widget.doubleSpinBoxLccpVoxelResolution->value());
511 config.setValue(
"SeedResolution", widget.doubleSpinBoxLccpSeedResolution->value());
512 config.setValue(
"ColorImportance", widget.doubleSpinBoxLccpColorImportance->value());
513 config.setValue(
"SpatialImportance", widget.doubleSpinBoxLccpSpatialImportance->value());
514 config.setValue(
"NormalImportance", widget.doubleSpinBoxLccpNormalImportance->value());
515 config.setValue(
"ConcavityThreshold", widget.doubleSpinBoxLccpConcavityThreshold->value());
516 config.setValue(
"SmoothnessThreshold",
517 widget.doubleSpinBoxLccpSmoothnessThreshold->value());
520 config.beginGroup(
"PrimitiveExtraction");
521 config.setValue(
"MinPrimitiveSize", widget.doubleSpinBoxMinPrimitiveSize->value());
522 config.setValue(
"MaxPrimitiveSize", widget.doubleSpinBoxMaxPrimitiveSize->value());
523 config.setValue(
"PlaneMaxIterations", widget.doubleSpinBoxPlaneMaxIterations->value());
524 config.setValue(
"PlaneDistanceThreshold",
525 widget.doubleSpinBoxPlaneDistanceThreshold->value());
526 config.setValue(
"PlaneNormalDistance", widget.doubleSpinBoxPlaneNormalDistance->value());
527 config.setValue(
"PlaneCircularDistanceThreshold",
528 widget.doubleSpinBoxPlaneCircularDistanceThreshold->value());
529 config.setValue(
"CylinderMaxIterations",
530 widget.doubleSpinBoxCylinderMaxIterations->value());
531 config.setValue(
"CylinderDistanceThreshold",
532 widget.doubleSpinBoxCylinderDistanceThreshold->value());
533 config.setValue(
"CylinderRadiusLimit", widget.doubleSpinBoxSphereMaxIterations->value());
534 config.setValue(
"SphereMaxIterations", widget.doubleSpinBoxSphereMaxIterations->value());
535 config.setValue(
"SphereDistanceThreshold",
536 widget.doubleSpinBoxSphereDistanceThreshold->value());
537 config.setValue(
"SphereNormalDistance", widget.doubleSpinBoxSphereNormalDistance->value());
538 config.setValue(
"EuclideanClusteringTolerance",
539 widget.doubleSpinBoxEuclideanClusteringTolerance->value());
540 config.setValue(
"OutlierDistanceThreshold",
541 widget.doubleSpinBoxOutlierDistanceThreshold->value());
556 workingMemory->getEnvironmentalPrimitiveSegment()));
559 unsigned int indexOfBiggestPrimitive;
560 unsigned int maxSampleSize = 0;
562 using boost::dynamic_pointer_cast;
563 using std::dynamic_pointer_cast;
566 for (
unsigned int i = 0; i < primitives->size(); i++)
568 AffordanceKit::PrimitivePtr primitive = primitives->at(i);
569 if (!dynamic_pointer_cast<AffordanceKit::Plane>(primitive))
573 AffordanceKit::PlanePtr plane = dynamic_pointer_cast<AffordanceKit::Plane>(primitive);
574 plane->sample(20, 1);
575 unsigned int curPlaneSize = plane->getSamplingSize();
576 if (curPlaneSize > maxSampleSize)
579 maxSampleSize = curPlaneSize;
580 indexOfBiggestPrimitive = i;
586 ARMARX_WARNING <<
"Did not find any plane-shaped primitives to rotate upon!";
591 AffordanceKit::PrimitivePtr primitive = primitives->at(indexOfBiggestPrimitive);
592 if (!dynamic_pointer_cast<AffordanceKit::Plane>(primitive))
594 ARMARX_ERROR <<
"Could not convert to planar primitive";
597 AffordanceKit::PlanePtr plane = dynamic_pointer_cast<AffordanceKit::Plane>(primitive);
600 debugDrawer->setPoseVisu(
601 "PrimitiveExtractorGuiLayer",
"BiggestPlaneRotation",
new Pose(gp));
606 std::string
filename = widget.lineEditPointCloud->text().toStdString();
607 pcl::PointCloud<pcl::PointXYZRGBA>::Ptr
pc(
new pcl::PointCloud<pcl::PointXYZRGBA>());
608 if (pcl::io::loadPCDFile<pcl::PointXYZRGBA>(
filename.c_str(), *
pc) == -1)
615 pcl::transformPointCloud(*
pc, *
pc, gpi);
619 for (
unsigned int i = 0; i <
pc->points.size(); i++)
621 balance += (
pc->points[i].z >= 0) ? 1 : -1;
624 ARMARX_INFO <<
"Z-axis balance after transformation: " << balance;
628 Eigen::Affine3f rotation(Eigen::AngleAxisf(
M_PI, Eigen::Vector3f::UnitX()));
629 pcl::transformPointCloud(*
pc, *
pc, rotation);
635 debugDrawer->setPoseVisu(
636 "PrimitiveExtractorGuiLayer",
"BiggestPlaneRotation",
new Pose(
T * gp));
639 std::string out_filename =
640 QFileDialog::getSaveFileName(
641 NULL,
"Save transformed PCD",
filename.c_str(),
"Point Cloud Files (*.pcd)")
645 pcl::io::savePCDFileASCII(out_filename, *
pc);