27 #include <pcl/PointIndices.h>
39 PointCloudObjectLocalizer::onInitPointCloudProcessor()
41 std::scoped_lock lock(pointCloudMutex);
43 pcl::console::setVerbosityLevel(pcl::console::L_ALWAYS);
45 providerName = getProperty<std::string>(
"providerName").getValue();
49 agentName = getProperty<std::string>(
"agentName").getValue();
51 sourceNodeName = getProperty<std::string>(
"sourceNodeName").getValue();
53 icpOnly = getProperty<bool>(
"icpOnly").getValue();
55 icp.setMaximumIterations(100);
56 icp.setMaxCorrespondenceDistance(500.0);
58 modelKeypoints.reset(
new pcl::PointCloud<PointT>);
60 std::string modelFileName = getProperty<std::string>(
"modelFileName").getValue();
63 pcl::PointCloud<PointT>::Ptr cloudPtr(
new pcl::PointCloud<PointT>());
66 ARMARX_FATAL <<
"Could not find point cloud file in ArmarXDataPath: " << modelFileName;
69 else if (pcl::io::loadPCDFile<PointT>(modelFileName.c_str(), *cloudPtr) == -1)
71 ARMARX_FATAL <<
"unable to load point cloud from file " << modelFileName;
75 float leafSize = getProperty<float>(
"sceneLeafSize").getValue();
76 grid.setLeafSize(Eigen::Vector3f(leafSize, leafSize, leafSize));
78 grid.setInputCloud(cloudPtr);
79 grid.filter(*modelKeypoints);
84 modelDescriptors.reset(
new pcl::PointCloud<PointD>());
86 pcl::PointCloud<pcl::Normal>::Ptr pointCloudModelNormals(
87 new pcl::PointCloud<pcl::Normal>);
89 normalEstimation.setInputCloud(cloudPtr);
90 normalEstimation.setRadiusSearch(10.0);
91 normalEstimation.compute(*pointCloudModelNormals);
94 featureEstimation.setInputCloud(modelKeypoints);
95 featureEstimation.setInputNormals(pointCloudModelNormals);
96 featureEstimation.setSearchSurface(cloudPtr);
97 featureEstimation.setRadiusSearch(20.0);
98 featureEstimation.compute(*modelDescriptors);
100 matchSearchTree.setInputCloud(modelDescriptors);
102 clusterer.setGCSize(getProperty<double>(
"recGCSize").getValue());
103 clusterer.setGCThreshold(getProperty<int>(
"recGCThreshold").getValue());
104 clusterer.setInputCloud(modelKeypoints);
108 offeringTopic(getProperty<std::string>(
"DebugDrawerTopic").getValue());
110 usingPointCloudProvider(providerName);
114 PointCloudObjectLocalizer::onConnectPointCloudProcessor()
116 std::scoped_lock lock(pointCloudMutex);
118 debugDrawerPrx = getTopic<DebugDrawerInterfacePrx>(
119 getProperty<std::string>(
"DebugDrawerTopic").getValue());
121 enableResultPointClouds<PointT>(
"Input");
122 enableResultPointClouds<PointT>(
"BeforeICPResult");
123 enableResultPointClouds<PointT>(
"AfterICPResult");
124 enableResultPointClouds<PointT>(
"BestMatch");
128 PointCloudObjectLocalizer::onDisconnectPointCloudProcessor()
133 PointCloudObjectLocalizer::onExitPointCloudProcessor()
138 PointCloudObjectLocalizer::process()
141 std::scoped_lock lock(pointCloudMutex);
143 pcl::PointCloud<PointL>::Ptr cloudPtr(
new pcl::PointCloud<PointL>());
145 if (!waitForPointClouds(providerName, 10000))
147 ARMARX_WARNING <<
"Timeout or error while waiting for point cloud data"
153 getPointClouds(providerName, cloudPtr);
159 pcl::PointCloud<PointT>::Ptr afterICPResultPointCloud(
new pcl::PointCloud<PointT>());
160 pcl::PointCloud<PointT>::Ptr beforeICPResultPointCloud(
new pcl::PointCloud<PointT>());
162 std::map<uint32_t, pcl::PointIndices> labeledPointMap;
163 visionx::tools::fillLabelMap<pcl::PointCloud<PointL>::Ptr>(cloudPtr, labeledPointMap);
165 for (
auto& it : labeledPointMap)
170 pcl::PointCloud<PointT>::Ptr segment(
new pcl::PointCloud<PointT>());
171 copyPointCloud(*cloudPtr, it.second, *segment);
173 pcl::PointCloud<PointT>::Ptr transformedCloudPtr(
new pcl::PointCloud<PointT>());
174 pcl::PointCloud<PointT>::Ptr cloudDownsampledPtr(
new pcl::PointCloud<PointT>());
175 pcl::PointCloud<pcl::Normal>::Ptr normalPtr(
new pcl::PointCloud<pcl::Normal>());
176 pcl::PointCloud<PointD>::Ptr descriptorPtr(
new pcl::PointCloud<PointD>());
177 pcl::CorrespondencesPtr correspondencesPtr(
new pcl::Correspondences());
179 pcl::copyPointCloud(*segment, *transformedCloudPtr);
181 grid.setInputCloud(transformedCloudPtr);
182 grid.filter(*cloudDownsampledPtr);
184 provideResultPointClouds(cloudDownsampledPtr,
"Input");
186 std::vector<Eigen::Matrix4f, Eigen::aligned_allocator<Eigen::Matrix4f>> transformations;
190 Eigen::Vector4f centroid;
191 pcl::compute3DCentroid(*cloudDownsampledPtr, centroid);
193 for (
float i = 0.0; i < 360.0; i += 45.0)
196 Eigen::AngleAxisf(i * 180.0 /
M_PI, Eigen::Vector3f::UnitZ()));
199 transform2.col(3) = centroid;
200 transformations.push_back(transform2);
206 normalEstimation.setInputCloud(transformedCloudPtr);
207 normalEstimation.compute(*normalPtr);
210 featureEstimation.setInputCloud(cloudDownsampledPtr);
211 featureEstimation.setInputNormals(normalPtr);
212 featureEstimation.setSearchSurface(transformedCloudPtr);
213 featureEstimation.compute(*descriptorPtr);
214 ARMARX_LOG <<
"found " << descriptorPtr->size() <<
" features";
218 for (
PointD& d : descriptorPtr->points)
225 std::vector<int> k_indices(k);
226 std::vector<float> k_sqr_distances(k);
227 int numNeighborsFound =
228 matchSearchTree.nearestKSearch(d, k, k_indices, k_sqr_distances);
230 if (numNeighborsFound == 1)
232 pcl::Correspondence corr(k_indices[0], i, k_sqr_distances[0]);
233 correspondencesPtr->push_back(corr);
238 std::vector<pcl::Correspondences> clusteredCorrespondences;
240 clusterer.setSceneCloud(cloudDownsampledPtr);
241 clusterer.setModelSceneCorrespondences(correspondencesPtr);
242 clusterer.recognize(transformations, clusteredCorrespondences);
244 ARMARX_LOG <<
" found " << transformations.size() <<
" transformations";
250 pcl::PointCloud<PointT>::Ptr transformedModelPtr3(
new pcl::PointCloud<PointT>());
251 pcl::transformPointCloud(*modelKeypoints, *transformedModelPtr3, t);
253 *beforeICPResultPointCloud += *transformedModelPtr3;
255 icp.setInputTarget(cloudDownsampledPtr);
256 icp.setInputSource(modelKeypoints);
257 pcl::PointCloud<PointT>::Ptr registered(
new pcl::PointCloud<PointT>);
258 icp.align(*registered, t);
260 if (icp.hasConverged())
262 float fitnessScore = icp.getFitnessScore();
266 ARMARX_LOG <<
"fitness score " << fitnessScore;
268 pcl::PointCloud<PointT>::Ptr transformedModelPtr2(
269 new pcl::PointCloud<PointT>());
270 pcl::transformPointCloud(*modelKeypoints, *transformedModelPtr2,
transform);
272 *afterICPResultPointCloud += *transformedModelPtr2;
274 if (fitnessScore <= bestFitnessScore)
276 bestFitnessScore = fitnessScore;
279 std::scoped_lock lock(localizeMutex);
286 debugDrawerPrx->setPoseVisu(
287 "PointCloudLocalizer",
"label " + it.first, pose);
293 provideResultPointClouds(beforeICPResultPointCloud,
"BeforeICPResult");
294 provideResultPointClouds(afterICPResultPointCloud,
"AfterICPResult");
296 if (bestFitnessScore < 2000.0)
298 ARMARX_LOG <<
"best transformation " << bestTransform;
299 pcl::PointCloud<PointT>::Ptr BestResultPointCloud(
new pcl::PointCloud<PointT>());
300 pcl::transformPointCloud(*modelKeypoints, *BestResultPointCloud, bestTransform);
301 provideResultPointClouds(BestResultPointCloud,
"BestMatch");
305 memoryx::ObjectLocalizationResultList
306 PointCloudObjectLocalizer::localizeObjectClasses(
307 const memoryx::ObjectClassNameList& objectClassNames,
308 const Ice::Current&
c)
310 std::scoped_lock lock(localizeMutex);
313 memoryx::ObjectLocalizationResultList resultList;
315 std::string objectClassName = getProperty<std::string>(
"objectClassName").getValue();
317 for (std::string name : objectClassNames)
319 if (name == objectClassName && pose)
321 memoryx::ObjectLocalizationResult result;
322 result.position = pose->getPosition();
323 result.orientation = pose->getOrientation();
324 result.objectClassName = objectClassName;
325 result.recognitionCertainty = 1.0f;
326 Eigen::Vector3f
mean;
327 mean << 0.0, 0.0, 0.0;
329 memoryx::MultivariateNormalDistributionBasePtr dummy(
331 result.positionNoise = dummy;
332 resultList.push_back(result);
340 PointCloudObjectLocalizer::getLocation(FramedOrientationBasePtr& orientation,
341 FramedPositionBasePtr& position,
342 const Ice::Current&
c)
344 std::scoped_lock lock(localizeMutex);
346 orientation = this->pose->getOrientation();
347 position = this->pose->getPosition();
351 PointCloudObjectLocalizer::createPropertyDefinitions()