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 
27 #include <pcl/PointIndices.h>
28 #include <pcl/common/centroid.h>
29 #include <pcl/filters/statistical_outlier_removal.h>
30 #include <pcl/sample_consensus/mlesac.h>
31 #include <pcl/segmentation/extract_clusters.h>
32 
35 
36 using namespace armarx;
37 
38 namespace visionx
39 {
40  void
41  MaskRCNNPointCloudObjectLocalizer::onInitPointCloudProcessor()
42  {
43  pcl::console::setVerbosityLevel(pcl::console::L_ALWAYS);
44 
45 
46  agentName = getProperty<std::string>("agentName").getValue();
47 
48  sourceNodeName = getProperty<std::string>("sourceNodeName").getValue();
49 
50  offeringTopic(getProperty<std::string>("DebugDrawerTopic").getValue());
51 
52  offeringTopic("ServiceRequests");
53  }
54 
55  void
56  MaskRCNNPointCloudObjectLocalizer::onConnectPointCloudProcessor()
57  {
58  serviceTopic = getTopic<armarx::RequestableServiceListenerInterfacePrx>("ServiceRequests");
59 
60  enableResultPointClouds<PointL>();
61  }
62 
63  void
64  MaskRCNNPointCloudObjectLocalizer::onDisconnectPointCloudProcessor()
65  {
66  }
67 
68  void
69  MaskRCNNPointCloudObjectLocalizer::onExitPointCloudProcessor()
70  {
71  }
72 
73  void
74  MaskRCNNPointCloudObjectLocalizer::process()
75  {
76  usleep(100000);
77  }
78 
79  memoryx::ObjectLocalizationResultList
80  MaskRCNNPointCloudObjectLocalizer::localizeObjectClasses(
81  const memoryx::ObjectClassNameList& objectClassNames,
82  const Ice::Current& c)
83  {
84  // boost::mutex::scoped_lock lock(localizeMutex);
85  ARMARX_VERBOSE << "localizing objects " << objectClassNames;
86  serviceTopic->requestService("MaskRCNNImageProcessor", 1000);
87  std::scoped_lock lock2(pointCloudMutex);
88  memoryx::ObjectLocalizationResultList resultList;
89  pcl::PointCloud<PointL>::Ptr cloudPtr(new pcl::PointCloud<PointL>());
90  pcl::PointCloud<PointL>::Ptr resultCloud(new pcl::PointCloud<PointL>());
91 
92 
93  if (!waitForPointClouds(10000))
94  {
95  ARMARX_WARNING << "Timeout or error while waiting for point cloud data"
96  << armarx::flush;
97  return resultList;
98  }
99  else
100  {
101  getPointClouds(cloudPtr);
102  }
103  ARMARX_VERBOSE << "Got pointcloud";
104  uint32_t backgroundLabel = getProperty<uint32_t>("BackgroundLabelId").getValue();
105  auto mapping = armarx::Split(getProperty<std::string>("ObjectNameIdMap"), ";", true, true);
106  std::map<std::string, int> nameIdMap;
107  std::map<int, std::string> idNameMap;
108  for (auto entry : mapping)
109  {
110  auto pair = armarx::Split(entry, ":");
111  ARMARX_CHECK_EQUAL(pair.size(), 2) << entry;
112  nameIdMap[pair.at(0)] = armarx::toInt(pair.at(1));
113  idNameMap[armarx::toInt(pair.at(1))] = pair.at(0);
114  }
115 
116 
117  cloudPtr->is_dense = false;
118  std::vector<int> index;
119  ARMARX_INFO << "Cloud size with NaN: " << cloudPtr->size();
120  pcl::removeNaNFromPointCloud(*cloudPtr, *cloudPtr, index);
121  ARMARX_INFO << "Cloud size without NaN: " << cloudPtr->size();
122 
123 
124  std::map<uint32_t, pcl::PointIndices> labeledPointMap;
125  visionx::tools::fillLabelMap<pcl::PointCloud<PointL>::Ptr>(cloudPtr, labeledPointMap);
126  std::map<std::string, Eigen::Vector3f> positionMap;
127 
128 
129  pcl::search::KdTree<PointL>::Ptr tree(new pcl::search::KdTree<PointL>);
130  tree->setInputCloud(cloudPtr);
131 
132  pcl::EuclideanClusterExtraction<PointL> ec;
133  ec.setClusterTolerance(20); // 2cm
134  ec.setMinClusterSize(100);
135  ec.setMaxClusterSize(25000);
136  ec.setInputCloud(cloudPtr);
137  ec.setSearchMethod(tree);
138 
139  // std::set<int> labelIds;
140  for (auto& it : labeledPointMap)
141  {
142  auto label = it.first;
143  if (label == backgroundLabel)
144  {
145  // ARMARX_VERBOSE << "Skipping background label with " << allPoints.size() << " points";
146  continue;
147  }
148 
149  if (!idNameMap.count(label))
150  {
151  ARMARX_INFO << "Unknown label: " << label;
152  continue;
153  }
154  auto labelName = idNameMap.at(label);
155  ARMARX_VERBOSE << "Checking cloud of " << labelName;
156  if (std::find(objectClassNames.begin(), objectClassNames.end(), labelName) ==
157  objectClassNames.end())
158  {
159  ARMARX_VERBOSE << "Object was not asked for: " << labelName;
160  continue;
161  }
162 
163  auto labelIndices = it.second.indices;
164 
165  pcl::IndicesPtr i(new std::vector<int>(it.second.indices));
166  ec.setIndices(i);
167  std::vector<pcl::PointIndices> cluster_indices;
168  ec.extract(cluster_indices);
169  ARMARX_VERBOSE << "Found " << cluster_indices.size() << " clusters";
170 
171  if (!cluster_indices.size())
172  {
173  ARMARX_VERBOSE << "Skipping " << labelName;
174  continue;
175  }
176 
177  int j = 0;
178  size_t maxClusterSize = 0;
179  size_t indexBiggestCluster = 0;
180  for (auto& cluster : cluster_indices)
181  {
182  ARMARX_VERBOSE << "Cluster size: " << cluster.indices.size();
183  if (cluster.indices.size() > maxClusterSize)
184  {
185  indexBiggestCluster = j;
186  maxClusterSize = cluster.indices.size();
187  }
188  j++;
189  }
190  labelIndices = cluster_indices.at(indexBiggestCluster).indices;
191 
192  ARMARX_DEBUG << " checking label " << labelName;
193  pcl::PointCloud<PointL>::Ptr segment(new pcl::PointCloud<PointL>());
194  copyPointCloud(*cloudPtr, labelIndices, *segment);
195  *resultCloud += *segment;
196 
197 
198  Eigen::Vector4f centroid;
199  pcl::compute3DCentroid(*segment, centroid);
200  positionMap[labelName] = centroid.head<3>();
201  }
202 
203  ARMARX_VERBOSE << "object positions for " << positionMap;
204  for (auto pair : positionMap)
205  {
206  auto name = pair.first;
207  Eigen::Vector3f position = pair.second;
208 
209  memoryx::ObjectLocalizationResult result;
210  result.position = new FramedPosition(position, sourceNodeName, agentName);
211  // ARMARX_VERBOSE << name << ": " << result.position->output();
213  result.orientation = new FramedOrientation(id, GlobalFrame, "");
214  result.objectClassName = name;
215  result.recognitionCertainty = 0.6;
216  result.timeStamp = new TimestampVariant(cloudPtr->header.stamp);
217 
218  Eigen::Vector3f cov(500, 500, 500);
219  result.positionNoise = new memoryx::MultivariateNormalDistribution(
220  Eigen::Vector3f::Zero(), cov.asDiagonal());
221  resultList.push_back(result);
222  }
223 
224  provideResultPointClouds(resultCloud);
225 
226  return resultList;
227  }
228 
229  void
230  MaskRCNNPointCloudObjectLocalizer::getLocation(FramedOrientationBasePtr& orientation,
231  FramedPositionBasePtr& position,
232  const Ice::Current& c)
233  {
234  throw LocalException("NYI");
235  }
236 
238  MaskRCNNPointCloudObjectLocalizer::createPropertyDefinitions()
239  {
240  return PropertyDefinitionsPtr(
241  new MaskRCNNPointCloudObjectLocalizerPropertyDefinitions(getConfigIdentifier()));
242  }
243 } // namespace visionx
MaskRCNNPointCloudObjectLocalizer.h
ARMARX_VERBOSE
#define ARMARX_VERBOSE
Definition: Logging.h:187
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:111
armarx::GlobalFrame
const std::string GlobalFrame
Definition: FramedPose.h:65
armarx::Split
std::vector< std::string > Split(const std::string &source, const std::string &splitBy, bool trimElements=false, bool removeEmptyElements=false)
Definition: StringHelperTemplates.h:36
armarx::TimestampVariant
Definition: TimestampVariant.h:54
c
constexpr T c
Definition: UnscentedKalmanFilterTest.cpp:46
GfxTL::Identity
void Identity(MatrixXX< N, N, T > *a)
Definition: MatrixXX.h:570
armarx::flush
const LogSender::manipulator flush
Definition: LogSender.h:251
ARMARX_DEBUG
#define ARMARX_DEBUG
Definition: Logging.h:184
TimestampVariant.h
visionx::MaskRCNNPointCloudObjectLocalizerPropertyDefinitions
Definition: MaskRCNNPointCloudObjectLocalizer.h:87
CMakePackageFinder.h
armarx::VariantType::FramedOrientation
const VariantTypeId FramedOrientation
Definition: FramedPose.h:39
ARMARX_INFO
#define ARMARX_INFO
Definition: Logging.h:181
IceUtil::Handle< class PropertyDefinitionContainer >
GfxTL::Matrix3f
MatrixXX< 3, 3, float > Matrix3f
Definition: MatrixXX.h:649
armarx::VariantType::FramedPosition
const VariantTypeId FramedPosition
Definition: FramedPose.h:38
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:193
armarx::PropertyDefinitionsPtr
IceUtil::Handle< class PropertyDefinitionContainer > PropertyDefinitionsPtr
PropertyDefinitions smart pointer type.
Definition: forward_declarations.h:35
armarx
This file offers overloads of toIce() and fromIce() functions for STL container types.
Definition: ArmarXTimeserver.cpp:27
armarx::VariantType::MultivariateNormalDistribution
const armarx::VariantTypeId MultivariateNormalDistribution
Definition: ProbabilityMeasures.h:40