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
36using namespace armarx;
37
38namespace visionx
39{
40 void
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
62
63 void
67
68 void
72
73 void
75 {
76 usleep(100000);
77 }
78
79 memoryx::ObjectLocalizationResultList
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"
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;
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();
212 Eigen::Matrix3f id = Eigen::Matrix3f::Identity();
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
243} // namespace visionx
uint8_t index
constexpr T c
std::string getConfigIdentifier()
Retrieve config identifier for this component as set in constructor.
Definition Component.cpp:90
Property< PropertyType > getProperty(const std::string &name)
The FramedOrientation class.
Definition FramedPose.h:216
The FramedPosition class.
Definition FramedPose.h:158
void offeringTopic(const std::string &name)
Registers a topic for retrival after initialization.
TopicProxyType getTopic(const std::string &name)
Returns a proxy of the specified topic.
Implements a Variant type for timestamps.
The MultivariateNormalDistribution class.
void getLocation(armarx::FramedOrientationBasePtr &orientation, armarx::FramedPositionBasePtr &position, const Ice::Current &c=::Ice::Current()) override
armarx::PropertyDefinitionsPtr createPropertyDefinitions() override
memoryx::ObjectLocalizationResultList localizeObjectClasses(const memoryx::ObjectClassNameList &objectClassNames, const Ice::Current &c=::Ice::Current()) override
void enableResultPointClouds(std::string resultProviderName="")
Enables visualization.
int getPointClouds(const PointCloudPtrT &pointCloudPtr)
Poll PointClouds from provider.
bool waitForPointClouds(int milliseconds=1000)
Wait for new PointClouds.
void provideResultPointClouds(const PointCloudPtrT &pointClouds, std::string providerName="")
sends result PointClouds for visualization
#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...
#define ARMARX_INFO
The normal logging level.
Definition Logging.h:181
#define ARMARX_DEBUG
The logging level for output that is only interesting while debugging.
Definition Logging.h:184
#define ARMARX_WARNING
The logging level for unexpected behaviour, but not a serious problem.
Definition Logging.h:193
#define ARMARX_VERBOSE
The logging level for verbose information.
Definition Logging.h:187
std::string const GlobalFrame
Variable of the global coordinate system.
Definition FramedPose.h:65
This file offers overloads of toIce() and fromIce() functions for STL container types.
std::vector< std::string > Split(const std::string &source, const std::string &splitBy, bool trimElements=false, bool removeEmptyElements=false)
IceUtil::Handle< class PropertyDefinitionContainer > PropertyDefinitionsPtr
PropertyDefinitions smart pointer type.
const LogSender::manipulator flush
Definition LogSender.h:251
int toInt(const std::string &input)
std::enable_if< is_shared_ptr< LabeledPointCloudPtrT >::value, void >::type fillLabelMap(LabeledPointCloudPtrT labeledCloudPtr, std::map< uint32_t, pcl::PointIndices > &labelIndicesMap, bool excludeZero=true)
ArmarX headers.