23 #include <VirtualRobot/VirtualRobot.h>
27 #include <SemanticObjectRelations/Shapes.h>
28 #include <SemanticObjectRelations/Hooks/VisualizerInterface.h>
44 defineOptionalProperty<std::string>(
"ice.DebugObserverName",
"DebugObserver",
45 "Name of the topic the DebugObserver listens to.");
47 defineOptionalProperty<std::string>(
"ice.ShapesTopicName",
"ShapesTopic",
48 "Name of the topic on which shapes are reported.");
49 defineOptionalProperty<std::string>(
"ice.ShapesName",
"SegmentRansacShapes",
50 "Name to use when reporting the extracted shapes.");
55 defineOptionalProperty<bool>(
56 "mode.AsPipeline",
false,
57 "Extract shapes on each new point cloud and publish them to the shapes topic.");
59 defineOptionalProperty<std::string>(
60 "ransac.TargetShapes",
"box, cylinder, sphere",
61 "Shapes to be extracted (any combination of: box, cylinder, sphere).");
63 defineOptionalProperty<float>(
64 "ransac.maxModelError", 1000.,
65 "Discard a model if its error is above this threshold.")
68 defineOptionalProperty<int>(
69 "ransac.maxIterations", 100,
70 "Maximal number of iterations of each RANSAC run.")
73 defineOptionalProperty<float>(
74 "ransac.distanceThresholdBox", 5.,
75 "A point with a distance below this threshold is considererd an inlier. (Box)")
77 defineOptionalProperty<float>(
78 "ransac.distanceThresholdPCL", 0.5,
79 "A point with a distance below this threshold is considererd an inlier. "
80 "(PCL, i.e. cylinder and sphere)")
82 defineOptionalProperty<float>(
83 "ransac.outlierRate", 0.0125f,
84 "The percentage of points that may be considered as outliers and may be ignored for fitting. "
85 "This affects box extents, cylinder height, and error computation.")
86 .setMin(0).setMax(1.);
87 defineOptionalProperty<float>(
88 "ransac.minInlierRate", 0.75,
89 "A model is considered a good fit, if this fraction of all points are "
90 "inliers for that model. (0.0 ... 1.0)")
91 .setMin(0.).setMax(1.0);
92 defineOptionalProperty<float>(
93 "ransac.sizePenaltyFactor", 0.000125f,
94 "Weight of the size penalty (relative to distance error). "
95 "Size penalty inhibits shapes with huge radius (cyl, sph) or extents (box)."
96 "Set to 0 to disable size penalty.")
98 defineOptionalProperty<float>(
99 "ransac.sizePenaltyExponent", 2.0,
100 "Exponent of the of the size penalty (as in s^x, with size measure s and exponent x). "
101 "Size penalty inhibits shapes with huge radius (cyl, sph) or extents (box).")
109 semrel::VisuLevel::RESULT);
124 shapeExtraction.setMaxModelError(getProperty<float>(
"ransac.maxModelError"));
125 shapeExtraction.setMaxIterations(getProperty<int>(
"ransac.maxIterations"));
127 shapeExtraction.setDistanceThresholdBox(getProperty<float>(
"ransac.distanceThresholdBox"));
128 shapeExtraction.setDistanceThresholdPCL(getProperty<float>(
"ransac.distanceThresholdPCL"));
130 shapeExtraction.setOutlierRate(getProperty<float>(
"ransac.outlierRate"));
132 shapeExtraction.setMinInlierRate(getProperty<float>(
"ransac.minInlierRate"));
134 shapeExtraction.setSizePenaltyFactor(getProperty<float>(
"ransac.sizePenaltyFactor"));
135 shapeExtraction.setSizePenaltyExponent(getProperty<float>(
"ransac.sizePenaltyExponent"));
139 std::string targetShapes = getProperty<std::string>(
"ransac.TargetShapes");
142 std::transform(targetShapes.begin(), targetShapes.end(), targetShapes.begin(), ::tolower);
145 shapeExtraction.setBoxExtractionEnabled(targetShapes.find(
"box") != std::string::npos);
146 shapeExtraction.setCylinderExtractionEnabled(targetShapes.find(
"cylinder") != std::string::npos);
147 shapeExtraction.setSphereExtractionEnabled(targetShapes.find(
"sphere") != std::string::npos);
176 pcl::PointCloud<PointT>::Ptr receivedPointCloud(
new pcl::PointCloud<PointT>());
187 ARMARX_VERBOSE <<
"Timeout or error while waiting for pointclouds.";
193 debugObserver->setDebugChannel(
getName(),
195 {
"Point Cloud Size",
new armarx::Variant(
static_cast<int>(receivedPointCloud->size())) },
196 {
"Point Cloud Time",
new armarx::Variant(
static_cast<int>(receivedPointCloud->header.stamp)) },
202 std::scoped_lock lock(inputPointCloudMutex);
203 this->inputPointCloud = receivedPointCloud;
206 if (getProperty<bool>(
"mode.AsPipeline"))
208 armarx::semantic::data::ShapeList
shapes;
210 std::scoped_lock lockInputPointCloud(inputPointCloudMutex, extractionMutex);
212 ARMARX_INFO <<
"Running shape extraction (" << inputPointCloud->size() <<
" points) ...";
213 const semrel::ShapeExtractionResult extractionResult = shapeExtraction.extract(*inputPointCloud);
218 debugObserver->setDebugChannel(
getName(),
223 shapesTopic->reportShapes(shapesName,
shapes);
230 if (!inputPointCloud)
232 ARMARX_WARNING <<
"No point cloud received. Not running shape extraction.";
237 std::scoped_lock lockInputPointCloud(inputPointCloudMutex, extractionMutex);
239 ARMARX_INFO <<
"Running shape extraction (" << inputPointCloud->size() <<
" points) ...";
240 semrel::ShapeExtractionResult extractionResult = shapeExtraction.extract(*inputPointCloud);
242 armarx::semantic::data::ShapeList result;
245 std::scoped_lock lock(extractedShapes.mutex);
247 extractedShapes.shapes = std::move(extractionResult.objects);
250 ARMARX_INFO <<
"Extracted " << extractedShapes.shapes.size() <<
" shapes. \n"
251 << extractedShapes.shapes;
253 result = extractedShapes.shapesIce;
257 debugObserver->setDebugChannel(
getName(),
259 {
"Num Extracted Shapes",
new armarx::Variant(
static_cast<int>(result.size())) },
267 std::lock_guard<std::mutex> lock(extractedShapes.mutex);
268 return extractedShapes.shapesIce;
274 return "SegmentRansacShapeExtractor";