29 #include <boost/lexical_cast.hpp>
33 #include <pcl/common/colors.h>
41 #include <AffordanceKit/PrimitiveExtractor.h>
42 #include <AffordanceKit/primitives/Box.h>
43 #include <AffordanceKit/primitives/Cylinder.h>
44 #include <AffordanceKit/primitives/Plane.h>
45 #include <AffordanceKit/primitives/Sphere.h>
52 PrimitiveExtractor::onInitPointCloudProcessor()
54 lastProcessedTimestamp = 0;
56 providerName = getProperty<std::string>(
"segmenterName").getValue();
59 minSegmentSize = getProperty<double>(
"minimumSegmentSize").getValue();
60 maxSegmentSize = getProperty<double>(
"maximumSegmentSize").getValue();
61 pMaxIter = getProperty<double>(
"planeMaximumIteration").getValue();
62 pDistThres = getProperty<float>(
"planeDistanceThreshold").getValue();
63 pNorDist = getProperty<float>(
"planeNormalDistance").getValue();
64 cMaxIter = getProperty<double>(
"cylinderMaximumIteration").getValue();
65 cDistThres = getProperty<float>(
"cylinderDistanceThreshold").getValue();
66 cRadLim = getProperty<float>(
"cylinderRadiousLimit").getValue();
67 sMaxIter = getProperty<double>(
"sphereMaximumIteration").getValue();
68 sDistThres = getProperty<float>(
"sphereDistanceThreshold").getValue();
69 sNorDist = getProperty<float>(
"sphereNormalDistance").getValue();
70 verbose = getProperty<bool>(
"vebose").getValue();
71 euclideanClusteringTolerance = getProperty<float>(
"euclideanClusteringTolerance").getValue();
72 outlierThreshold = getProperty<float>(
"outlierThreshold").getValue();
73 circleDistThres = getProperty<float>(
"circularDistanceThreshold").getValue();
75 spatialSamplingDistance = getProperty<float>(
"SpatialSamplingDistance").getValue();
76 numOrientationalSamplings = getProperty<int>(
"NumOrientationalSamplings").getValue();
84 primitiveExtractor.reset(
new AffordanceKit::PrimitiveExtractor());
85 primitiveExtractor->updateParameters(verbose,
97 euclideanClusteringTolerance,
100 usingPointCloudProvider(providerName);
102 if (getProperty<std::string>(
"RobotStateComponentName").getValue() !=
"")
104 usingProxy(getProperty<std::string>(
"RobotStateComponentName").getValue());
105 sourceFrameName = getProperty<std::string>(
"sourceFrameName").getValue();
107 usingProxy(getProperty<std::string>(
"WorkingMemoryName").getValue());
109 mappingEnabled =
true;
111 enablePrimitiveFusion = getProperty<bool>(
"enablePrimitiveFusion").getValue();
113 offeringTopic(getProperty<std::string>(
"DebugDrawerTopicName").getValue());
114 offeringTopic(getProperty<std::string>(
"SegmentedPointCloudTopicName").getValue());
116 offeringTopic(getProperty<std::string>(
"DebugObserverName").getValue());
120 PrimitiveExtractor::onConnectPointCloudProcessor()
122 enableResultPointClouds<PointXYZL>(
"GraspPointCloudResult");
123 enableResultPointClouds<PointXYZL>(
"PrimitiveExtractorResult");
124 enableResultPointClouds<PointXYZL>(
"Inliers");
126 workingMemory = getProxy<memoryx::WorkingMemoryInterfacePrx>(
127 getProperty<std::string>(
"WorkingMemoryName").getValue());
130 ARMARX_ERROR <<
"Failed to obtain working memory proxy";
133 environmentalPrimitiveSegment = workingMemory->getEnvironmentalPrimitiveSegment();
134 if (!environmentalPrimitiveSegment)
136 ARMARX_ERROR <<
"Failed to obtain environmental primitive segment pointer";
139 pointCloudSegmentationPrx = getTopic<visionx::PointCloudSegmentationListenerPrx>(
140 getProperty<std::string>(
"SegmentedPointCloudTopicName").getValue());
142 debugDrawerTopicPrx = getTopic<DebugDrawerInterfacePrx>(
143 getProperty<std::string>(
"DebugDrawerTopicName").getValue());
145 if (getProperty<std::string>(
"RobotStateComponentName").getValue() !=
"")
147 robotStateComponent = getProxy<RobotStateComponentInterfacePrx>(
148 getProperty<std::string>(
"RobotStateComponentName").getValue());
149 if (!robotStateComponent->getSynchronizedRobot()->hasRobotNode(sourceFrameName))
152 robotStateComponent =
nullptr;
158 debugDrawerTopicPrx->clearLayer(
"primitiveMapper");
160 debugObserver = getTopic<DebugObserverInterfacePrx>(
161 getProperty<std::string>(
"DebugObserverName").getValue());
166 debugValues[
"processingTime"] =
new Variant(0.0);
167 debugValues[
"oldPrimitives"] =
new Variant(0.0);
168 debugValues[
"visiblePrimitives"] =
new Variant(0.0);
169 debugValues[
"newPrimitives"] =
new Variant(0.0);
170 debugValues[
"modifiedPrimitives"] =
new Variant(0.0);
171 debugValues[
"unmodifiedPrimitives"] =
new Variant(0.0);
172 debugValues[
"removedPrimitives"] =
new Variant(0.0);
173 debugValues[
"numViews"] =
new Variant(0.0);
174 debugObserver->setDebugChannel(getName(), debugValues);
178 PrimitiveExtractor::onDisconnectPointCloudProcessor()
183 PrimitiveExtractor::onExitPointCloudProcessor()
188 PrimitiveExtractor::enablePipelineStep(
const Ice::Current&
c)
190 std::unique_lock lock(enableMutex);
191 mappingEnabled =
true;
195 PrimitiveExtractor::disablePipelineStep(
const Ice::Current&
c)
197 std::unique_lock lock(enableMutex);
198 mappingEnabled =
false;
202 PrimitiveExtractor::process()
204 if (!waitForPointClouds(providerName, 10000))
210 std::unique_lock lock(enableMutex);
221 pcl::PointCloud<pcl::PointXYZRGBL>::Ptr temp(
new pcl::PointCloud<pcl::PointXYZRGBL>());
222 if (!getPointClouds(providerName, temp))
228 pcl::copyPointCloud(*temp, *labeledCloudPtr);
229 if (labeledCloudPtr->size() == 0)
233 provideResultPointClouds(labeledCloudPtr,
"GraspPointCloudResult");
234 provideResultPointClouds(labeledCloudPtr,
"PrimitiveExtractorResult");
240 inliersCloudPtr = primitiveExtractor->computeScenePrimitives(labeledCloudPtr);
241 graspCloudPtr = primitiveExtractor->getDetectedGraspPoints();
244 const std::vector<pcl::PointCloud<pcl::PointXYZL>::Ptr>& planeInliers =
245 primitiveExtractor->getPlaneInliers();
246 const std::vector<pcl::PointCloud<pcl::PointXYZL>::Ptr>& cylinderInliers =
247 primitiveExtractor->getCylinderInliers();
248 const std::vector<pcl::PointCloud<pcl::PointXYZL>::Ptr>& sphereInliers =
249 primitiveExtractor->getSphereInliers();
250 const std::vector<float>& circularityProbabilities =
251 primitiveExtractor->getCircularityProbabilities();
253 ARMARX_INFO <<
" ********* Detected Plane number: " << planeInliers.size();
254 ARMARX_INFO <<
" ********* Detected Cylinder number: " << cylinderInliers.size();
255 ARMARX_INFO <<
" ********* Detected Sphere number: " << sphereInliers.size();
256 ARMARX_INFO <<
" ********* Detected Circle Probabilities: " << circularityProbabilities.size();
259 provideResultPointClouds(graspCloudPtr,
"GraspPointCloudResult");
260 provideResultPointClouds(inliersCloudPtr,
"PrimitiveExtractorResult");
263 << (IceUtil::Time::now() - startTime).toSecondsDouble() <<
" secs";
266 startTime = IceUtil::Time::now();
270 std::unique_lock lock(enableMutex);
276 if (getProperty<bool>(
"UseAffordanceExtractionLibExport").getValue())
278 pushPrimitivesToMemoryAffordanceKit(temp->header.stamp);
282 pushPrimitivesToMemory(temp->header.stamp);
286 std::unique_lock lock(timestampMutex);
287 lastProcessedTimestamp = temp->header.stamp;
292 pointCloudSegmentationPrx->reportNewPointCloudSegmentation();
295 ARMARX_INFO <<
"Mapping took " << (IceUtil::Time::now() - startTime).toSecondsDouble()
300 PrimitiveExtractor::getGraspPointInlierRatio(memoryx::EnvironmentalPrimitiveBasePtr leftPrimitive,
301 memoryx::EnvironmentalPrimitiveBasePtr rightPrimitive)
303 FramedPosePtr pose = FramedPosePtr::dynamicCast(rightPrimitive->getPose());
306 Eigen::Vector3f oBBDimensions =
307 Vector3Ptr::dynamicCast(rightPrimitive->getOBBDimensions())->toEigen();
308 Eigen::Vector3f extent = 0.5 * oBBDimensions + (Eigen::Vector3f::Ones() * 50);
310 float numPoints = 0.0;
311 memoryx::PointList graspPoints = leftPrimitive->getGraspPoints();
313 for (Vector3BasePtr& p : graspPoints)
315 Eigen::Vector4f temp = Eigen::Vector4f(p->x, p->y, p->z, 1.0);
316 Eigen::Vector3f point = (worldToPrimitive * temp).head<3>();
318 if ((point.array().abs() < extent.array()).all())
324 return numPoints / graspPoints.size();
328 PrimitiveExtractor::fusePrimitives(std::vector<memoryx::EntityBasePtr>& newPrimitives,
332 std::vector<EnvironmentalPrimitiveBasePtr> primitives =
333 environmentalPrimitiveSegment->getEnvironmentalPrimitives();
336 std::vector<memoryx::EnvironmentalPrimitiveBasePtr> nonVisiblePrimitives;
337 std::vector<memoryx::EnvironmentalPrimitiveBasePtr> visiblePrimitives;
339 std::vector<memoryx::EnvironmentalPrimitiveBasePtr> modifiedPrimitives;
340 std::set<std::string> processedPrimitives;
341 std::set<std::string> primitivesToRemove;
343 if (robotStateComponent)
348 auto snapshot = robotStateComponent->getRobotSnapshotAtTimestamp(timestamp);
350 FramedPoseBasePtr pose = snapshot->getRobotNode(sourceFrameName)->getGlobalPose();
352 cameraToWorld = armarx::FramedPosePtr::dynamicCast(pose)->toEigen();
355 primitiveFilter.updateCameraPosition(cameraToWorld);
358 primitiveFilter.visualizeFrustum(debugDrawerTopicPrx);
360 primitiveFilter.getPrimitivesInFieldOfView(
361 primitives, visiblePrimitives, nonVisiblePrimitives);
366 ARMARX_ERROR <<
"Frustum culling not possible without RobotStateComponent assuming that "
367 "all primitives are visible";
368 visiblePrimitives = primitives;
372 if (getProperty<bool>(
"EnableBoxPrimitives").
getValue())
376 for (
const EnvironmentalPrimitiveBasePtr& p : primitives)
378 if (p->ice_isA(memoryx::BoxPrimitiveBase::ice_staticId()))
380 primitivesToRemove.insert(p->getId());
385 if (nonVisiblePrimitives.size())
387 ARMARX_INFO <<
"found " << nonVisiblePrimitives.size()
388 <<
" non visible primitives in field of view.";
389 for (memoryx::EnvironmentalPrimitiveBasePtr& p : nonVisiblePrimitives)
391 p->setProbability(
std::max(0.0, p->getProbability() - 0.1));
392 if (p->getProbability() <= 0.4)
394 primitivesToRemove.insert(p->getId());
398 modifiedPrimitives.push_back(p);
404 ARMARX_DEBUG <<
"total primitives " << primitives.size() <<
" visible primitives "
405 << visiblePrimitives.size() <<
"new primitives" << newPrimitives.size();
407 std::vector<memoryx::EntityBasePtr> uniqueEntities;
408 for (
const memoryx::EntityBasePtr& newEntity : newPrimitives)
410 memoryx::EnvironmentalPrimitiveBasePtr newPrimitive =
411 memoryx::EnvironmentalPrimitiveBasePtr::dynamicCast(newEntity);
413 std::vector<EnvironmentalPrimitiveBasePtr> intersectingPrimitives;
414 fusionStrategy.getIntersectingSimilarPrimitives(
415 primitives, newPrimitive, intersectingPrimitives, 50.0);
419 bool addPrimitive =
true;
420 for (EnvironmentalPrimitiveBasePtr& intersectingPrimitive : intersectingPrimitives)
422 if (primitivesToRemove.count(intersectingPrimitive->getId()))
427 int currentLabel = 0;
428 float inlierRatioLeft = getGraspPointInlierRatio(newPrimitive, intersectingPrimitive);
429 float inlierRatioRight = getGraspPointInlierRatio(intersectingPrimitive, newPrimitive);
431 if (inlierRatioLeft <= 0.1 && inlierRatioRight <= 0.1)
433 processedPrimitives.insert(intersectingPrimitive->getId());
436 if (inlierRatioLeft >= 0.9 && inlierRatioRight >= 0.9)
438 intersectingPrimitive->setTime(newPrimitive->getTime());
439 float newProbability = std::fmax(newPrimitive->getProbability(),
440 intersectingPrimitive->getProbability() + 0.15);
441 intersectingPrimitive->setProbability(std::fmin(1.0, newProbability));
442 modifiedPrimitives.push_back(intersectingPrimitive);
444 addPrimitive =
false;
447 else if (inlierRatioLeft <= 0.3 && inlierRatioRight >= 0.7)
450 primitivesToRemove.insert(intersectingPrimitive->getId());
452 else if (inlierRatioLeft >= 0.7 && inlierRatioRight <= 0.3)
455 addPrimitive =
false;
458 else if ((inlierRatioLeft + inlierRatioRight) >= 1.4)
460 if ((newPrimitive->getOBBDimensions()->x * newPrimitive->getOBBDimensions()->y) >
461 (intersectingPrimitive->getOBBDimensions()->x *
462 intersectingPrimitive->getOBBDimensions()->y))
464 primitivesToRemove.insert(intersectingPrimitive->getId());
468 addPrimitive =
false;
476 else if (intersectingPrimitive->getLabel())
478 currentLabel = intersectingPrimitive->getLabel();
481 if (currentLabel == 0 && intersectingPrimitives.size())
483 currentLabel = ++lastUsedLabel;
485 newPrimitive->setLabel(currentLabel);
487 for (EnvironmentalPrimitiveBasePtr& x : intersectingPrimitives)
489 x->setLabel(currentLabel);
490 modifiedPrimitives.push_back(x);
495 uniqueEntities.push_back(newPrimitive);
499 if (robotStateComponent)
502 for (memoryx::EnvironmentalPrimitiveBasePtr& p : visiblePrimitives)
505 if (processedPrimitives.count(p->getId()) || primitivesToRemove.count(p->getId()))
510 float probability = p->getProbability();
511 p->setProbability(
std::max(0.0, p->getProbability() - 0.5));
512 ARMARX_LOG <<
"reducing probability for primitive in field of view: " << p->getId()
513 <<
" from " << probability <<
" to " << p->getProbability();
515 if (p->getProbability() <= 0.4)
517 ARMARX_LOG <<
"scheduling primitive " << p->getId() <<
" for removal";
518 primitivesToRemove.insert(p->getId());
522 modifiedPrimitives.push_back(p);
528 ARMARX_INFO <<
"removing " << primitivesToRemove.size() <<
" primitives";
530 for (
const std::string& x : primitivesToRemove)
532 environmentalPrimitiveSegment->removeEntity(x);
536 processedPrimitives.clear();
537 for (EnvironmentalPrimitiveBasePtr& x : modifiedPrimitives)
539 if (!primitivesToRemove.count(x->getId()) && !processedPrimitives.count(x->getId()))
542 environmentalPrimitiveSegment->updateEntity(x->getId(), x);
543 processedPrimitives.insert(x->getId());
547 float unmodified = primitives.size() - modified - primitivesToRemove.size();
549 ARMARX_INFO <<
"Writing segmentation (" << uniqueEntities.size() <<
" primitives) to memory";
551 environmentalPrimitiveSegment->addEntityList(uniqueEntities);
554 debugValues[
"processingTime"] =
555 new Variant((TimeUtil::GetTime().toMicroSeconds() - timestamp) / (1000.0 * 1000.0));
556 debugValues[
"oldPrimitives"] =
new Variant((
float)primitives.size());
557 debugValues[
"visiblePrimitives"] =
new Variant((
float)visiblePrimitives.size());
558 debugValues[
"newPrimitives"] =
new Variant((
float)uniqueEntities.size());
559 debugValues[
"modifiedPrimitives"] =
new Variant(modified);
560 debugValues[
"unmodifiedPrimitives"] =
new Variant(unmodified);
561 debugValues[
"removedPrimitives"] =
new Variant((
float)primitivesToRemove.size());
563 debugValues[
"numViews"] =
new Variant((
int)numViews);
564 debugObserver->setDebugChannel(getName(), debugValues);
566 pcl::PointCloud<pcl::PointXYZL>::Ptr inliers(
new pcl::PointCloud<pcl::PointXYZL>());
567 for (
const EnvironmentalPrimitiveBasePtr& x : primitives)
569 if (primitivesToRemove.count(x->getId()))
574 for (
const armarx::Vector3BasePtr&
v : x->getInliers())
577 p.label = x->getLabel();
581 inliers->points.push_back(p);
585 for (
const memoryx::EntityBasePtr& e : uniqueEntities)
589 for (
const armarx::Vector3BasePtr&
v : x->getInliers())
592 p.label = x->getLabel();
596 inliers->points.push_back(p);
602 inliers->width = inliers->points.size();
605 provideResultPointClouds(inliers,
"Inliers");
612 PrimitiveExtractor::pushPrimitivesToMemory(IceUtil::Int64 originalTimestamp)
614 std::vector<memoryx::EntityBasePtr> newPrimitives;
616 const std::vector<pcl::ModelCoefficients::Ptr>& planeCoefficients =
617 primitiveExtractor->getPlaneCoefficients();
618 const std::vector<pcl::ModelCoefficients::Ptr>& cylinderCoefficients =
619 primitiveExtractor->getCylinderCoefficients();
620 const std::vector<pcl::ModelCoefficients::Ptr>& sphereCoefficients =
621 primitiveExtractor->getSphereCoefficients();
622 const std::vector<float>& circularityProbabilities =
623 primitiveExtractor->getCircularityProbabilities();
625 const std::vector<pcl::PointCloud<pcl::PointXYZL>::Ptr>& planeInliers =
626 primitiveExtractor->getPlaneInliers();
627 const std::vector<pcl::PointCloud<pcl::PointXYZL>::Ptr>& cylinderInliers =
628 primitiveExtractor->getCylinderInliers();
629 const std::vector<pcl::PointCloud<pcl::PointXYZL>::Ptr>& sphereInliers =
630 primitiveExtractor->getSphereInliers();
632 const std::vector<pcl::PointCloud<pcl::PointXYZL>::Ptr>& cylinderGraspPoints =
633 primitiveExtractor->getCylinderGraspPoints();
634 const std::vector<pcl::PointCloud<pcl::PointXYZL>::Ptr>& sphereGraspPoints =
635 primitiveExtractor->getSphereGraspPoints();
640 for (
size_t i = 0; i < planeCoefficients.size(); i++)
643 pcl::ModelCoefficients::Ptr coefficients = planeCoefficients[i];
644 pcl::PointCloud<pcl::PointXYZL>::Ptr inliers = planeInliers[i];
646 pcl::PointCloud<pcl::PointXYZL>::Ptr graspPoints(
new pcl::PointCloud<pcl::PointXYZL>());
648 pcl::PointCloud<pcl::PointXYZL>::Ptr temp(
new pcl::PointCloud<pcl::PointXYZL>());
649 pcl::ProjectInliers<PointL> proj;
650 proj.setModelType(pcl::SACMODEL_PLANE);
651 proj.setInputCloud(inliers);
652 proj.setModelCoefficients(coefficients);
657 pcl::ConcaveHull<PointL> concaveHull;
658 concaveHull.setInputCloud(temp);
659 concaveHull.setDimension(2);
660 concaveHull.setAlpha(69.0);
662 concaveHull.reconstruct(*graspPoints);
665 ARMARX_LOG << __LINE__ <<
" done computing hull";
668 pcl::MomentOfInertiaEstimation<pcl::PointXYZL> bb;
669 pcl::PointXYZL min_point_OBB, max_point_OBB, position_OBB;
672 bb.setInputCloud(graspPoints);
674 bb.getOBB(min_point_OBB, max_point_OBB, position_OBB, rotational_matrix_OBB);
676 Eigen::Vector3f position(position_OBB.x, position_OBB.y, position_OBB.z);
678 new Vector3(max_point_OBB.x * 2, max_point_OBB.y * 2, max_point_OBB.z * 2);
683 pcl::PointXYZL pointMin, pointMax;
684 pcl::getMinMax3D<pcl::PointXYZL>(*inliers, pointMin, pointMax);
685 float length = (pointMax.getVector3fMap() - pointMin.getVector3fMap()).
norm();
688 EnvironmentalPrimitiveBasePtr primitive;
690 primitive->setOBBDimensions(dimension);
691 primitive->setPose(pose);
692 primitive->setProbability(0.75);
693 primitive->setLabel(0);
695 primitive->setLength(length);
696 primitive->setCircularityProbability(circularityProbabilities[i]);
698 primitive->setName(
"environmentalPrimitive_" + boost::lexical_cast<std::string>(label++));
701 PointList graspPointList(graspPoints->points.size());
702 for (
size_t p = 0; p < graspPoints->points.size(); p++)
705 graspPoints->points[p].x, graspPoints->points[p].y, graspPoints->points[p].z);
706 graspPointList[p] = currPoint;
708 primitive->setGraspPoints(graspPointList);
710 PointList inlierList(inliers->points.size());
711 for (
size_t p = 0; p < inliers->points.size(); p++)
713 const Eigen::Vector3f& f = inliers->points[p].getVector3fMap();
714 inlierList[p] =
new Vector3(f);
716 primitive->setInliers(inlierList);
722 std::vector<Eigen::Vector3f>
convexHull(graspPointList.size());
723 for (
unsigned int i = 0; i < graspPointList.size(); i++)
725 convexHull[i] = armarx::Vector3Ptr::dynamicCast(graspPointList[i])->toEigen();
727 AffordanceKit::PlanePtr plane(
new AffordanceKit::Plane(
convexHull));
728 plane->sample(spatialSamplingDistance, numOrientationalSamplings);
730 primitive->setSampling(
s);
734 newPrimitives.push_back(primitive);
740 for (
size_t i = 0; i < cylinderCoefficients.size(); i++)
743 pcl::ModelCoefficients::Ptr coefficients = cylinderCoefficients[i];
744 pcl::PointCloud<pcl::PointXYZL>::Ptr inliers = cylinderInliers[i];
745 pcl::PointCloud<pcl::PointXYZL>::Ptr graspPoints = cylinderGraspPoints[i];
747 pcl::PointCloud<pcl::PointXYZL>::Ptr temp(
new pcl::PointCloud<pcl::PointXYZL>());
748 pcl::ProjectInliers<PointL> proj;
749 proj.setModelType(pcl::SACMODEL_PLANE);
750 proj.setInputCloud(inliers);
751 proj.setModelCoefficients(coefficients);
754 pcl::ConcaveHull<PointL> concaveHull;
755 concaveHull.setInputCloud(temp);
756 concaveHull.setDimension(2);
757 concaveHull.setAlpha(69.0);
758 concaveHull.setKeepInformation(
true);
759 concaveHull.reconstruct(*graspPoints);
762 pcl::MomentOfInertiaEstimation<pcl::PointXYZL> bb;
763 pcl::PointXYZL min_point_OBB, max_point_OBB, position_OBB;
766 bb.setInputCloud(inliers);
768 bb.getOBB(min_point_OBB, max_point_OBB, position_OBB, rotational_matrix_OBB);
770 Eigen::Vector3f position(position_OBB.x, position_OBB.y, position_OBB.z);
772 new Vector3(max_point_OBB.x * 2, max_point_OBB.y * 2, max_point_OBB.z * 2);
778 float min_t = std::numeric_limits<float>::infinity();
779 float max_t = -std::numeric_limits<float>::infinity();
782 coefficients->values[0], coefficients->values[1], coefficients->values[2]);
784 coefficients->values[3], coefficients->values[4], coefficients->values[5]);
787 for (
unsigned int i = 0; i < inliers->points.size(); i++)
789 Eigen::Vector3f
v(inliers->points[i].x, inliers->points[i].y, inliers->points[i].z);
791 float t = (
v - b).
dot(d) / d.dot(d);
797 float length = max_t - min_t;
798 Eigen::Vector3f base = b + min_t * d + 0.5 * length * d;
799 Eigen::Vector3f direction = d;
800 float radius = coefficients->values[6];
803 CylinderPrimitiveBasePtr primitive;
805 primitive->setCylinderPoint(
new Vector3(base));
806 primitive->setCylinderAxisDirection(
new Vector3(direction));
807 primitive->setCylinderRadius(radius);
808 primitive->setLength(length);
809 primitive->setOBBDimensions(dimension);
810 primitive->setPose(pose);
811 primitive->setProbability(0.75);
812 primitive->setLabel(0);
814 primitive->setCircularityProbability(0.0);
818 PointList graspPointList(graspPoints->points.size());
820 for (
size_t p = 0; p < graspPoints->points.size(); p++)
823 graspPoints->points[p].x, graspPoints->points[p].y, graspPoints->points[p].z);
824 graspPointList[p] = currPoint;
827 primitive->setName(
"environmentalPrimitive_" +
828 boost::lexical_cast<std::string>(planeCoefficients.size() + i));
829 primitive->setGraspPoints(graspPointList);
832 AffordanceKit::CylinderPtr cylinder(
833 new AffordanceKit::Cylinder(base, direction, length, radius));
834 cylinder->sample(spatialSamplingDistance, numOrientationalSamplings);
836 primitive->setSampling(
s);
840 newPrimitives.push_back(primitive);
846 for (
size_t i = 0; i < sphereCoefficients.size(); i++)
849 pcl::ModelCoefficients::Ptr coefficients = sphereCoefficients[i];
850 pcl::PointCloud<pcl::PointXYZL>::Ptr inliers = sphereInliers[i];
851 pcl::PointCloud<pcl::PointXYZL>::Ptr graspPoints = sphereGraspPoints[i];
858 pcl::MomentOfInertiaEstimation<pcl::PointXYZL> bb;
859 pcl::PointXYZL min_point_OBB, max_point_OBB, position_OBB;
862 bb.setInputCloud(inliers);
864 bb.getOBB(min_point_OBB, max_point_OBB, position_OBB, rotational_matrix_OBB);
866 Eigen::Vector3f position(position_OBB.x, position_OBB.y, position_OBB.z);
868 new Vector3(max_point_OBB.x * 2, max_point_OBB.y * 2, max_point_OBB.z * 2);
874 pcl::PointXYZL pointMin, pointMax;
875 pcl::getMinMax3D<pcl::PointXYZL>(*inliers, pointMin, pointMax);
876 float length = (pointMax.getVector3fMap() - pointMin.getVector3fMap()).
norm();
879 EnvironmentalPrimitiveBasePtr primitive = {};
881 primitive->setOBBDimensions(dimension);
882 primitive->setPose(pose);
883 primitive->setLabel(0);
884 primitive->setProbability(0.75);
886 primitive->setLength(length);
887 primitive->setCircularityProbability(0.0);
891 PointList graspPointList(graspPoints->points.size());
893 for (
size_t p = 0; p < graspPoints->points.size(); p++)
896 graspPoints->points[p].x, graspPoints->points[p].y, graspPoints->points[p].z);
897 graspPointList[p] = currPoint;
900 primitive->setName(
"environmentalPrimitive_" +
901 boost::lexical_cast<std::string>(cylinderCoefficients.size() +
902 planeCoefficients.size() + i));
903 primitive->setGraspPoints(graspPointList);
906 Eigen::Vector3f center(
907 coefficients->values[0], coefficients->values[1], coefficients->values[2]);
908 float radius = coefficients->values[3];
909 AffordanceKit::SpherePtr sphere(
new AffordanceKit::Sphere(center, radius));
910 sphere->sample(spatialSamplingDistance, numOrientationalSamplings);
912 primitive->setSampling(
s);
916 newPrimitives.push_back(primitive);
920 ARMARX_LOG << __LINE__ <<
" writing primitives to memory.";
922 if (enablePrimitiveFusion)
924 fusePrimitives(newPrimitives, originalTimestamp);
928 ARMARX_LOG << __LINE__ <<
" removing previous primitives from memory.";
929 environmentalPrimitiveSegment->removeAllEntities();
931 environmentalPrimitiveSegment->addEntityList(newPrimitives);
935 ARMARX_LOG << __LINE__ <<
"done writing primitives to memory.";
937 if (getProperty<bool>(
"EnableBoxPrimitives").
getValue())
939 newPrimitives.clear();
941 std::vector<EnvironmentalPrimitiveBasePtr> primitives =
942 environmentalPrimitiveSegment->getEnvironmentalPrimitives();
945 unsigned int sz = newPrimitives.size();
946 fusionStrategy.findBoxPrimitives(primitives, newPrimitives, environmentalPrimitiveSegment);
949 for (
auto& primitive : newPrimitives)
957 Eigen::Matrix4f pose = PosePtr::dynamicCast(box->getPose())->toEigen();
958 Eigen::Vector3f dimensions =
959 Vector3Ptr::dynamicCast(box->getOBBDimensions())->toEigen();
960 AffordanceKit::BoxPtr b(
new AffordanceKit::Box(pose, dimensions));
961 b->sample(getProperty<float>(
"SpatialSamplingDistance").
getValue(),
962 getProperty<int>(
"NumOrientationalSamplings").
getValue());
967 ARMARX_INFO <<
"Found " << (newPrimitives.size() - sz) <<
" Box primitives";
969 environmentalPrimitiveSegment->addEntityList(newPrimitives);
974 PrimitiveExtractor::pushPrimitivesToMemoryAffordanceKit(IceUtil::Int64 originalTimestamp)
976 AffordanceKit::PrimitiveSetPtr ps = primitiveExtractor->getPrimitiveSet(
977 getProperty<float>(
"SpatialSamplingDistance").
getValue(),
978 getProperty<int>(
"NumOrientationalSamplings").
getValue(),
981 primitiveSet.writeToMemory(environmentalPrimitiveSegment);
985 PrimitiveExtractor::createPropertyDefinitions()
993 std::unique_lock lock(enableMutex);
994 return mappingEnabled;
997 armarx::TimestampBasePtr
1000 std::unique_lock lock(timestampMutex);
1006 const Ice::Current&
c)
1009 primitiveExtractor->updateParameters(verbose,
1010 parameters.minSegmentSize,
1011 parameters.maxSegmentSize,
1012 parameters.planeMaxIterations,
1013 parameters.planeDistanceThreshold,
1014 parameters.planeNormalDistance,
1015 parameters.cylinderMaxIterations,
1016 parameters.cylinderDistanceThreshold,
1017 parameters.cylinderRadiusLimit,
1018 parameters.sphereMaxIterations,
1019 parameters.sphereDistanceThreshold,
1020 parameters.sphereNormalDistance,
1021 parameters.euclideanClusteringTolerance,
1022 parameters.outlierThreshold,
1023 parameters.circularDistanceThreshold);
1027 PrimitiveExtractor::loadParametersFromFile(
const std::string&
filename,
const Ice::Current&
c)
1029 std::string absolute_filename;
1030 ArmarXDataPath::getAbsolutePath(
filename, absolute_filename);
1032 ARMARX_INFO <<
"Loading parameter setup from " << absolute_filename;
1033 QSettings config(QString::fromStdString(absolute_filename), QSettings::IniFormat);
1035 config.beginGroup(
"PrimitiveExtraction");
1037 primitiveExtractor->updateParameters(
1039 config.value(
"MinPrimitiveSize", getProperty<double>(
"minimumSegmentSize").getValue())
1041 config.value(
"MaxPrimitiveSize", getProperty<double>(
"maximumSegmentSize").getValue())
1043 config.value(
"PlaneMaxIterations", getProperty<double>(
"planeMaximumIteration").getValue())
1046 .value(
"PlaneDistanceThreshold",
1047 getProperty<float>(
"planeDistanceThreshold").getValue())
1049 config.value(
"PlaneNormalDistance", getProperty<float>(
"planeNormalDistance").getValue())
1052 .value(
"CylinderMaxIterations",
1053 getProperty<double>(
"cylinderMaximumIteration").getValue())
1056 .value(
"CylinderDistanceThreshold",
1057 getProperty<float>(
"cylinderDistanceThreshold").getValue())
1059 config.value(
"CylinderRadiusLimit", getProperty<float>(
"cylinderRadiousLimit").getValue())
1062 .value(
"SphereMaxIterations", getProperty<double>(
"sphereMaximumIteration").getValue())
1065 .value(
"SphereDistanceThreshold",
1066 getProperty<float>(
"sphereDistanceThreshold").getValue())
1068 config.value(
"SphereNormalDistance", getProperty<float>(
"sphereNormalDistance").getValue())
1071 .value(
"EuclideanClusteringTolerance",
1072 getProperty<float>(
"euclideanClusteringTolerance").getValue())
1074 config.value(
"OutlierDistanceThreshold", getProperty<float>(
"outlierThreshold").getValue())
1077 .value(
"PlaneCircularDistanceThreshold",
1078 getProperty<float>(
"circularDistanceThreshold").getValue())
1084 visionx::PrimitiveExtractorParameters
1087 visionx::PrimitiveExtractorParameters parameters;
1088 parameters.minSegmentSize = primitiveExtractor->minSegmentSize;
1089 parameters.maxSegmentSize = primitiveExtractor->maxSegmentSize;
1090 parameters.planeMaxIterations = primitiveExtractor->planeMaxIteration;
1091 parameters.planeDistanceThreshold = primitiveExtractor->planeMaxIteration;
1092 parameters.planeNormalDistance = primitiveExtractor->planeNormalDistanceWeight;
1093 parameters.cylinderMaxIterations = primitiveExtractor->cylinderMaxIteration;
1094 parameters.cylinderDistanceThreshold = primitiveExtractor->cylinderDistanceThreshold;
1095 parameters.cylinderRadiusLimit = primitiveExtractor->cylinderRadiusLimit;
1097 parameters.sphereMaxIterations = primitiveExtractor->sphereMaxIteration;
1098 parameters.sphereDistanceThreshold = primitiveExtractor->sphereDistanceThreshold;
1099 parameters.sphereNormalDistance = primitiveExtractor->sphereNormalDistanceWeight;
1100 parameters.euclideanClusteringTolerance = primitiveExtractor->euclideanClusteringTolerance;
1101 parameters.outlierThreshold = primitiveExtractor->outlierThreshold;
1102 parameters.circularDistanceThreshold = primitiveExtractor->circleDistanceThreshold;