MaskRCNNPointCloudObjectLocalizer.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of ArmarX.
3  *
4  * Copyright (C) 2011-2016, High Performance Humanoid Technologies (H2T), Karlsruhe Institute of Technology (KIT), all rights reserved.
5  *
6  * ArmarX is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 as
8  * published by the Free Software Foundation.
9  *
10  * ArmarX is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program. If not, see <http://www.gnu.org/licenses/>.
17  *
18  * @package VisionX::ArmarXObjects::MaskRCNNPointCloudObjectLocalizer
19  * @author Markus Grotz ( markus dot grotz at kit dot edu )
20  * @date 2015
21  * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
22  * GNU General Public License
23  */
24 
26 
28 
30 #include <pcl/PointIndices.h>
31 #include <pcl/filters/statistical_outlier_removal.h>
32 #include <pcl/sample_consensus/mlesac.h>
33 #include <pcl/segmentation/extract_clusters.h>
34 #include <pcl/common/centroid.h>
35 
36 using namespace armarx;
37 
38 namespace visionx
39 {
40  void MaskRCNNPointCloudObjectLocalizer::onInitPointCloudProcessor()
41  {
42  pcl::console::setVerbosityLevel(pcl::console::L_ALWAYS);
43 
44 
45  agentName = getProperty<std::string>("agentName").getValue();
46 
47  sourceNodeName = getProperty<std::string>("sourceNodeName").getValue();
48 
49  offeringTopic(getProperty<std::string>("DebugDrawerTopic").getValue());
50 
51  offeringTopic("ServiceRequests");
52  }
53 
54  void MaskRCNNPointCloudObjectLocalizer::onConnectPointCloudProcessor()
55  {
56  serviceTopic = getTopic<armarx::RequestableServiceListenerInterfacePrx>("ServiceRequests");
57 
58  enableResultPointClouds<PointL>();
59  }
60 
61  void MaskRCNNPointCloudObjectLocalizer::onDisconnectPointCloudProcessor()
62  {
63 
64  }
65 
66  void MaskRCNNPointCloudObjectLocalizer::onExitPointCloudProcessor()
67  {
68  }
69 
70  void MaskRCNNPointCloudObjectLocalizer::process()
71  {
72  usleep(100000);
73  }
74 
75 
76 
77 
78 
79  memoryx::ObjectLocalizationResultList MaskRCNNPointCloudObjectLocalizer::localizeObjectClasses(const memoryx::ObjectClassNameList& objectClassNames, const Ice::Current& c)
80  {
81  // boost::mutex::scoped_lock lock(localizeMutex);
82  ARMARX_VERBOSE << "localizing objects " << objectClassNames;
83  serviceTopic->requestService("MaskRCNNImageProcessor", 1000);
84  std::scoped_lock lock2(pointCloudMutex);
85  memoryx::ObjectLocalizationResultList resultList;
86  pcl::PointCloud<PointL>::Ptr cloudPtr(new pcl::PointCloud<PointL>());
87  pcl::PointCloud<PointL>::Ptr resultCloud(new pcl::PointCloud<PointL>());
88 
89 
90  if (!waitForPointClouds(10000))
91  {
92  ARMARX_WARNING << "Timeout or error while waiting for point cloud data" << armarx::flush;
93  return resultList;
94  }
95  else
96  {
97  getPointClouds(cloudPtr);
98  }
99  ARMARX_VERBOSE << "Got pointcloud";
100  uint32_t backgroundLabel = getProperty<uint32_t>("BackgroundLabelId").getValue();
101  auto mapping = armarx::Split(getProperty<std::string>("ObjectNameIdMap"), ";", true, true);
102  std::map<std::string, int> nameIdMap;
103  std::map<int, std::string> idNameMap;
104  for (auto entry : mapping)
105  {
106  auto pair = armarx::Split(entry, ":");
107  ARMARX_CHECK_EQUAL(pair.size(), 2) << entry;
108  nameIdMap[pair.at(0)] = armarx::toInt(pair.at(1));
109  idNameMap[armarx::toInt(pair.at(1))] = pair.at(0);
110  }
111 
112 
113 
114  cloudPtr->is_dense = false;
115  std::vector<int> index;
116  ARMARX_INFO << "Cloud size with NaN: " << cloudPtr->size();
117  pcl::removeNaNFromPointCloud(*cloudPtr, *cloudPtr, index);
118  ARMARX_INFO << "Cloud size without NaN: " << cloudPtr->size();
119 
120 
121  std::map<uint32_t, pcl::PointIndices> labeledPointMap;
122  visionx::tools::fillLabelMap<pcl::PointCloud<PointL>::Ptr>(cloudPtr, labeledPointMap);
123  std::map<std::string, Eigen::Vector3f> positionMap;
124 
125 
126  pcl::search::KdTree<PointL>::Ptr tree(new pcl::search::KdTree<PointL>);
127  tree->setInputCloud(cloudPtr);
128 
129  pcl::EuclideanClusterExtraction<PointL> ec;
130  ec.setClusterTolerance(20); // 2cm
131  ec.setMinClusterSize(100);
132  ec.setMaxClusterSize(25000);
133  ec.setInputCloud(cloudPtr);
134  ec.setSearchMethod(tree);
135 
136  // std::set<int> labelIds;
137  for (auto& it : labeledPointMap)
138  {
139  auto label = it.first;
140  if (label == backgroundLabel)
141  {
142  // ARMARX_VERBOSE << "Skipping background label with " << allPoints.size() << " points";
143  continue;
144  }
145 
146  if (!idNameMap.count(label))
147  {
148  ARMARX_INFO << "Unknown label: " << label;
149  continue;
150  }
151  auto labelName = idNameMap.at(label);
152  ARMARX_VERBOSE << "Checking cloud of " << labelName;
153  if (std::find(objectClassNames.begin(), objectClassNames.end(), labelName) == objectClassNames.end())
154  {
155  ARMARX_VERBOSE << "Object was not asked for: " << labelName;
156  continue;
157  }
158 
159  auto labelIndices = it.second.indices;
160 
161  pcl::IndicesPtr i(new std::vector<int>(it.second.indices));
162  ec.setIndices(i);
163  std::vector<pcl::PointIndices> cluster_indices;
164  ec.extract(cluster_indices);
165  ARMARX_VERBOSE << "Found " << cluster_indices.size() << " clusters";
166 
167  if (!cluster_indices.size())
168  {
169  ARMARX_VERBOSE << "Skipping " << labelName;
170  continue;
171  }
172 
173  int j = 0;
174  size_t maxClusterSize = 0;
175  size_t indexBiggestCluster = 0;
176  for (auto& cluster : cluster_indices)
177  {
178  ARMARX_VERBOSE << "Cluster size: " << cluster.indices.size();
179  if (cluster.indices.size() > maxClusterSize)
180  {
181  indexBiggestCluster = j;
182  maxClusterSize = cluster.indices.size();
183  }
184  j++;
185  }
186  labelIndices = cluster_indices.at(indexBiggestCluster).indices;
187 
188  ARMARX_DEBUG << " checking label " << labelName;
189  pcl::PointCloud<PointL>::Ptr segment(new pcl::PointCloud<PointL>());
190  copyPointCloud(*cloudPtr, labelIndices, *segment);
191  *resultCloud += *segment;
192 
193 
194  Eigen::Vector4f centroid;
195  pcl::compute3DCentroid(*segment, centroid);
196  positionMap[labelName] = centroid.head<3>();
197 
198  }
199 
200  ARMARX_VERBOSE << "object positions for " << positionMap;
201  for (auto pair : positionMap)
202  {
203  auto name = pair.first;
204  Eigen::Vector3f position = pair.second;
205 
206  memoryx::ObjectLocalizationResult result;
207  result.position = new FramedPosition(position, sourceNodeName, agentName);
208  // ARMARX_VERBOSE << name << ": " << result.position->output();
210  result.orientation = new FramedOrientation(id, GlobalFrame, "");
211  result.objectClassName = name;
212  result.recognitionCertainty = 0.6;
213  result.timeStamp = new TimestampVariant(cloudPtr->header.stamp);
214 
215  Eigen::Vector3f cov(500, 500, 500);
216  result.positionNoise = new memoryx::MultivariateNormalDistribution(Eigen::Vector3f::Zero(), cov.asDiagonal());
217  resultList.push_back(result);
218 
219  }
220 
221  provideResultPointClouds(resultCloud);
222 
223  return resultList;
224  }
225 
226 
227  void MaskRCNNPointCloudObjectLocalizer::getLocation(FramedOrientationBasePtr& orientation, FramedPositionBasePtr& position, const Ice::Current& c)
228  {
229  throw LocalException("NYI");
230  }
231 
232 
233  PropertyDefinitionsPtr MaskRCNNPointCloudObjectLocalizer::createPropertyDefinitions()
234  {
236  getConfigIdentifier()));
237  }
238 }
MaskRCNNPointCloudObjectLocalizer.h
ARMARX_VERBOSE
#define ARMARX_VERBOSE
Definition: Logging.h:180
visionx
ArmarX headers.
Definition: OpenPoseStressTest.h:38
index
uint8_t index
Definition: EtherCATFrame.h:59
armarx::toInt
int toInt(const std::string &input)
Definition: StringHelpers.cpp:108
armarx::GlobalFrame
const std::string GlobalFrame
Definition: FramedPose.h:62
armarx::Split
std::vector< std::string > Split(const std::string &source, const std::string &splitBy, bool trimElements=false, bool removeEmptyElements=false)
Definition: StringHelperTemplates.h:35
armarx::TimestampVariant
Definition: TimestampVariant.h:54
c
constexpr T c
Definition: UnscentedKalmanFilterTest.cpp:43
GfxTL::Identity
void Identity(MatrixXX< N, N, T > *a)
Definition: MatrixXX.h:523
armarx::flush
const LogSender::manipulator flush
Definition: LogSender.h:251
ARMARX_DEBUG
#define ARMARX_DEBUG
Definition: Logging.h:177
TimestampVariant.h
visionx::MaskRCNNPointCloudObjectLocalizerPropertyDefinitions
Definition: MaskRCNNPointCloudObjectLocalizer.h:88
CMakePackageFinder.h
GfxTL::Matrix3f
MatrixXX< 3, 3, float > Matrix3f
Definition: MatrixXX.h:600
armarx::VariantType::FramedOrientation
const VariantTypeId FramedOrientation
Definition: FramedPose.h:40
ARMARX_INFO
#define ARMARX_INFO
Definition: Logging.h:174
IceUtil::Handle< class PropertyDefinitionContainer >
armarx::VariantType::FramedPosition
const VariantTypeId FramedPosition
Definition: FramedPose.h:39
ARMARX_CHECK_EQUAL
#define ARMARX_CHECK_EQUAL(lhs, rhs)
This macro evaluates whether lhs is equal (==) rhs and if it turns out to be false it will throw an E...
Definition: ExpressionException.h:130
ARMARX_WARNING
#define ARMARX_WARNING
Definition: Logging.h:186
armarx::PropertyDefinitionsPtr
IceUtil::Handle< class PropertyDefinitionContainer > PropertyDefinitionsPtr
PropertyDefinitions smart pointer type.
Definition: forward_declarations.h:34
armarx
This file offers overloads of toIce() and fromIce() functions for STL container types.
Definition: ArmarXTimeserver.cpp:28
armarx::VariantType::MultivariateNormalDistribution
const armarx::VariantTypeId MultivariateNormalDistribution
Definition: ProbabilityMeasures.h:36