23 #include <pcl/filters/statistical_outlier_removal.h>
24 #include <pcl/common/transforms.h>
32 #include <VisionX/interface/components/Calibration.h>
33 #include <SimoxUtility/meta/type_name.h>
48 .
value(buf.outlierMeanK).min(1).max(1000))
52 .
value(buf.outlierStddevMulThresh).min(0).max(10))
59 .
value(buf.ransacEpsilon).min(1).max(1000))
63 .
value(buf.ransacBitmapEpsilon).min(1).max(10000))
67 .
value(buf.ransacNormalThresh).min(0).max(1).decimals(3))
71 .
value(buf.ransacProbability).min(0).max(1).decimals(3))
75 .
value(buf.ransacMinSupport).min(1).max(1000))
79 .
value(buf.ransacMaxruntimeMs).min(1).max(10000));
88 prx.
getValue(buf.outlierMeanK,
"outlierMeanK");
89 prx.
getValue(buf.outlierStddevMulThresh,
"outlierStddevMulThresh");
91 prx.
getValue(buf.ransacEpsilon,
"ransacEpsilon");
92 prx.
getValue(buf.ransacNormalThresh,
"ransacNormalThresh");
93 prx.
getValue(buf.ransacMinSupport,
"ransacMinSupport");
94 prx.
getValue(buf.ransacBitmapEpsilon,
"ransacBitmapEpsilon");
95 prx.
getValue(buf.ransacProbability,
"ransacProbability");
96 prx.
getValue(buf.ransacMaxruntimeMs,
"ransacMaxruntimeMs");
102 #define result_name_transformed getName() + "_Transformed"
103 #define result_name_filtered getName() + "_Filtered"
108 visionx::PointCloudProcessorPropertyDefinitions(prefix)
110 defineOptionalProperty<std::string>(
"ProviderReferenceFrame",
"",
"Name of the point cloud refence frame (empty = autodetect)");
116 return "EfficientRANSACPrimitiveExtractor";
121 _pointCloudProviderName = getProperty<std::string>(
"ProviderName");
132 _pointCloudProvider = _pointCloudProviderInfo.
proxy;
133 _pointCloudProviderRefFrame = getProperty<std::string>(
"ProviderReferenceFrame");
134 if (_pointCloudProviderRefFrame.empty())
136 _pointCloudProviderRefFrame =
"root";
137 auto frameprov = visionx::ReferenceFrameInterfacePrx::checkedCast(_pointCloudProvider);
140 _pointCloudProviderRefFrame = frameprov->getReferenceFrame();
147 addRobot(
"_localRobot", VirtualRobot::RobotIO::eStructure);
168 #define call_template_function(F) \
169 switch(_pointCloudProviderInfo.pointCloudFormat->type) \
171 case visionx::PointContentType::ePoints : F<pcl::PointXYZ>(); break; \
172 case visionx::PointContentType::eColoredPoints : F<pcl::PointXYZRGBA>(); break; \
173 case visionx::PointContentType::eColoredOrientedPoints : F<pcl::PointXYZRGBNormal>(); break; \
174 case visionx::PointContentType::eLabeledPoints : F<pcl::PointXYZL>(); break; \
175 case visionx::PointContentType::eColoredLabeledPoints : F<pcl::PointXYZRGBL>(); break; \
176 case visionx::PointContentType::eIntensity : F<pcl::PointXYZI>(); break; \
177 case visionx::PointContentType::eOrientedPoints : \
178 ARMARX_ERROR << "eOrientedPoints NOT HANDLED IN VISIONX"; \
179 [[fallthrough]]; default: \
180 ARMARX_ERROR << "Could not process point cloud, because format '" \
181 << _pointCloudProviderInfo.pointCloudFormat->type << "' is unknown"; \
212 template<
class Po
intType>
216 using cloud_t = pcl::PointCloud<PointType>;
217 using cloud_ptr_t =
typename cloud_t::Ptr;
218 const auto now = [] {
return std::chrono::high_resolution_clock::now();};
219 const auto timeBeg = now();
222 const auto dt = now() - timeBeg;
223 const int us = std::chrono::duration_cast<std::chrono::microseconds>(
dt).count();
228 cloud_ptr_t transformedCloud;
233 <<
"Timeout or error while waiting for point cloud data of provider "
234 << _pointCloudProviderName;
237 cloud_ptr_t inputCloud(
new cloud_t);
246 fp.changeFrame(_localRobot.
robot,
"Global");
250 transformedCloud = cloud_ptr_t(
new cloud_t);
251 pcl::transformPointCloud(*inputCloud, *transformedCloud, providerInRootFrame);
258 cloud_ptr_t filtered(
new cloud_t);
259 pcl::StatisticalOutlierRemoval<PointType> sor;
260 sor.setInputCloud(transformedCloud);
261 sor.setMeanK(buf.outlierMeanK);
262 sor.setStddevMulThresh(buf.outlierStddevMulThresh);
263 sor.filter(*filtered);
272 std::vector<Point> points;
273 points.reserve(transformedCloud->size());
274 static constexpr
float inf = std::numeric_limits<float>::infinity();
281 for (
const auto& p : *transformedCloud)
283 points.emplace_back(
Vec3f(p.x, p.y, p.z));
284 std::tie(minX, maxX) = std::minmax({minX, maxX, p.x});
285 std::tie(minY, maxY) = std::minmax({minY, maxY, p.y});
286 std::tie(minZ, maxZ) = std::minmax({minZ, maxZ, p.z});
290 pc.setBBox({minX, minY, minZ}, {maxX, maxY, maxZ});
339 .position(Eigen::Vector3f::Zero())
341 .pointSizeInPixels(8)
342 .pointCloud(*transformedCloud));
346 std::size_t numCyl = 0;
347 std::size_t numSph = 0;
348 std::size_t numPla = 0;
349 std::size_t numUnk = 0;
351 static int maxnum = 0;
355 const auto draw_cloud = [&](std::size_t num, std::string desc)
359 cloud.
position(Eigen::Vector3f::Zero());
363 for (std::size_t i2 = 0; i2 < num; ++i2, ++idx)
365 const auto& pt =
pc.at(
pc.size() - 1 - idx);
366 cloud.
addPoint(pt.pos.getValue()[0], pt.pos.getValue()[1], pt.pos.getValue()[2], i);
369 cloudLayer.
add(cloud);
373 for (; i <
shapes.size(); ++i)
379 const auto& [
s, sz] =
shapes.at(i);
382 if (plane_t* ptr =
dynamic_cast<plane_t*
>(
s.Ptr()); ptr)
386 ptr->Internal().getPosition().getValue(
c.x(),
c.y(),
c.z());
389 ptr->Internal().getNormal().getValue(n.x(), n.y(), n.z());
393 .lineColorGlasbeyLUT(i)
395 .circle(
c, n, 200, 64));
397 else if (sphere_t* ptr =
dynamic_cast<sphere_t*
>(
s.Ptr()); ptr)
401 ptr->Internal().Center().getValue(
c.x(),
c.y(),
c.z());
406 .radius(ptr->Internal().Radius()));
408 else if (cylinder_t* ptr =
dynamic_cast<cylinder_t*
>(
s.Ptr()); ptr)
412 ptr->Internal().AxisPosition().getValue(
c.x(),
c.y(),
c.z());
418 .radius(ptr->Internal().Radius())
424 ARMARX_WARNING <<
"UNKNOWN shape " << simox::meta::get_type_name(
s.Ptr());
428 draw_cloud(sz,
"dummy");
431 for (; i < maxnum; ++i)
433 draw_cloud(0,
"dummy");