ObjectShapeClassification.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
19  * @author
20  * @date
21  * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
22  * GNU General Public License
23  */
24 
25 #include <Math/Math3d.h>
26 
28 
29 #include <sstream>
30 #include <iterator> //Needed for vector-to-string. CPP is ugly
31 #include <iostream>
32 #include <stdio.h>
33 #include <boost/filesystem.hpp>
34 
36 
39 
40 #include "Features/Features.h"
42 #include "convexHull.hpp"
43 #include "IVPointParser.hpp"
44 #include "ICP.h"
45 
46 
47 using std::cout;
48 using std::endl;
49 
50 const std::string ATTR_FEATURES = "RecognitionFeatures";
51 const std::string ATTR_IV_FILE = "IvFile";
52 
53 using namespace visionx;
54 using namespace memoryx;
55 
57 {
58  settings_priorMemory = getProperty<std::string>("PriorKnowledgeMemoryProxyName").getValue();
59  usingProxy(settings_priorMemory);
60 
61  featureCalculator.addFeature<CHArea>();
62  featureCalculator.addFeature<CHVolume>();
63 
64  featureCalculator.addFeature<BBVolume>();
65  featureCalculator.addFeature<BBArea>();
66  featureCalculator.addFeature<BBLongSide>();
67  featureCalculator.addFeature<BBShortSide>();
68  featureCalculator.addFeature<BBMediumSide>();
69  featureCalculator.addFeature<BBLongShortRatio>();
70  featureCalculator.addFeature<BBMediumShortRatio>();
71 
72  featureCalculator.addFeature<D2Histogram>();
73  featureCalculator.addFeature<A3Histogram>();
74 }
75 
77 {
78  memoryPrx = getProxy<PriorKnowledgeInterfacePrx>(settings_priorMemory);
79  classesSegmentPrx = memoryPrx->getObjectClassesSegment();
80  databasePrx = memoryPrx->getCommonStorage();
81 
82  fileManager.reset(new GridFileManager(databasePrx));
83 
84  connected = databasePrx->isConnected();
85 }
86 
87 void ObjectShapeClassification::refetchObjects()
88 {
89  ARMARX_VERBOSE << "Refetching objects from DB" << armarx::flush;
90  boost::recursive_mutex::scoped_lock lock(mutexEntities);
91  EntityIdList ids = classesSegmentPrx->getAllEntityIds();
92  dbObjects.clear();
93 
94  for (EntityIdList::const_iterator it = ids.begin(); it != ids.end(); ++it)
95  {
96  const EntityBasePtr entity = classesSegmentPrx->getEntityById(*it);
97  const ObjectClassPtr objClass = ObjectClassPtr::dynamicCast(entity);
98 
99  if (objClass)
100  {
101  ARMARX_VERBOSE << *objClass << armarx::flush;
102  dbObjects.push_back(objClass);
103  }
104  }
105 }
106 
107 void ObjectShapeClassification::checkFeatures()
108 {
109  for (auto optr : dbObjects)
110  {
111  //Check if the object has the feature attribute
112  if (!optr->hasAttribute(ATTR_FEATURES))
113  {
114  //Calculate the attributes for this object
115  }
116 
117  //Compare to the attributes of the current object
118  }
119 }
120 
121 Points ObjectShapeClassification::getPointsFromIV(ObjectClassPtr obj)
122 {
123  //Cache the file
124  std::string ivFile = "";
125  Points ps;
126 
127  if (obj->hasAttribute(ATTR_IV_FILE))
128  {
129  fileManager->ensureFileInCache(obj->getAttribute(ATTR_IV_FILE), ivFile, false);
130  ps = IVPointParser::fromFile(ivFile);
131  }
132  else
133  {
134  ARMARX_WARNING << "No IV file found for object" << obj->getName();
135  }
136 
137  return ps;
138 }
139 
140 struct by_second
141 {
142  template <typename Pair>
143  bool operator()(const Pair& a, const Pair& b)
144  {
145  return a.second < b.second;
146  }
147 };
148 
149 TaggedPoints ObjectShapeClassification::compareToDB(Points& points)
150 {
151  std::vector<std::pair<std::string, Points>> objectsPoints;
152 
153  //Get the points from every object
154  for (auto& obj : dbObjects)
155  {
156  auto points = getPointsFromIV(obj);
157 
158  if (points.size() != 0)
159  {
160  objectsPoints.push_back(TaggedPoints(obj->getName(), points));
161  }
162  }
163 
164  ARMARX_VERBOSE << "Calculating features of new points...";
165  //Calculuate the features of the new object
166  auto newObjectFeatures = featureCalculator.getFeatures(points);
167  ARMARX_VERBOSE << "Calculated new features";
168 
169  //Print the points and features (for parsing and learning) ======================
170  //Points pointsTransposed = Points(points.size());
171  //std::transform(points.begin(), points.end(), pointsTransposed.end(), [&](Point& p) {return p.transpose();}); //Transpose the points, so they are printed horizontally
172  //std::ostringstream oss;
173  //Put the vector into a string, so that we can give it to ARMARX_* in a single line....
174  //if (!pointsTransposed.empty()) {
175  // // Convert all but the last element to avoid a trailing ","
176  // std::copy(pointsTransposed.begin(), pointsTransposed.end()-1,
177  // std::ostream_iterator<Point>(oss, ","));
178  // // Now add the last element with no delimiter
179  // oss << pointsTransposed.back();
180  //}
181  //ARMARX_VERBOSE << "-- Points: [" << oss.str() << "]";
182  //Finished printing points =======================================================
183 
184  //Now also print the features of the new object
185  for (const auto& feat : newObjectFeatures)
186  {
187  ARMARX_VERBOSE << "-- " << feat.first << ": " << *(feat.second);
188  }
189 
190 
191  //Now actually go on doing useful work....
192  std::map<std::string, std::map<std::string, double>> objectDiffs;
193  std::map<std::string, double> maxDiffs;
194 
195  ARMARX_VERBOSE << "Now iterating over the db objects...";
196 
197  //For every object, get the features, or calculate them
198  for (const auto& obj : objectsPoints)
199  {
200  ARMARX_VERBOSE << " Getting features for: " << obj.first;
201  auto features = featureCalculator.getFeatures(obj.second);
202  std::map<std::string, double> diffs;
203 
204  //Compare to the new object, iterating over every feature
205  for (const auto& p : newObjectFeatures)
206  {
207  auto& feature = p.second;
208  double diff = feature->compare(*features[feature->name()]);
209  diffs[feature->name()] = diff;
210 
211  //Store the maximum value of each feature, to normalize later.
212  double oldValue = maxDiffs[feature->name()];
213  maxDiffs[feature->name()] = (diff > oldValue) ? diff : oldValue;
214  }
215 
216  objectDiffs[obj.first] = diffs;
217  }
218 
219  std::map<std::string, double> objectDiffsTotal;
220 
221  //For each object get the total diff
222  for (const auto& obj : objectDiffs)
223  {
224  //Get the sum of the differences of each feature, normalized.
225  ARMARX_VERBOSE << "--\n-- " << obj.first << ": ";
226  double totalDiff = std::accumulate(obj.second.begin(), obj.second.end(), 0.0, [&](double prev, const std::pair<std::string, double> p)
227  {
228  double diff = (p.second / maxDiffs[p.first]);
229  ARMARX_VERBOSE_S << "-- " << p.first << ": " << diff;
230  return prev + (p.second / maxDiffs[p.first]);
231  });
232  objectDiffsTotal[obj.first] = totalDiff;
233  ARMARX_VERBOSE << "--+ Total score(" << obj.first << "): " << totalDiff << "\n";
234  }
235 
236 
237  auto bestMatch = *std::min_element(objectDiffsTotal.begin(), objectDiffsTotal.end(), by_second());
238 
239  ARMARX_INFO << "Best match found: " << bestMatch.first << " with score of " << bestMatch.second;
240 
241  return bestMatch;
242 }
243 
244 void ObjectShapeClassification::matchToFoundPointCloud(const Points& newPoints, const Points& foundPointCloud)
245 {
246  ARMARX_VERBOSE << "Running ICP...";
247  ICP icp;
248  icp.SetScenePointcloud(foundPointCloud);
249  icp.SetObjectPointcloud(newPoints);
250 
251  Mat3d rotation;
252  Vec3d translation;
253  double msd = icp.SearchObject(rotation, translation);
254  ARMARX_IMPORTANT << "Mean square difference to found point cloud: " << msd;
255 }
256 
257 std::string ObjectShapeClassification::FindSimilarKnownObject(const types::PointList& segmentedObjectPoints, const Ice::Current&)
258 {
259  Points points;
260 
261  for (size_t i = 0; i < segmentedObjectPoints.size(); i++)
262  {
263  points.push_back(armarx::Vector3Ptr::dynamicCast(segmentedObjectPoints.at(i))->toEigen());
264  }
265 
266  ARMARX_VERBOSE << "Loaded "
267  << points.size()
268  << " data points.";
269 
270  if (connected)
271  {
272  ARMARX_INFO << "Connected to DB, starting classification";
273 
274  //Make sure we have all the objects
275  refetchObjects();
276 
277  //Compare to the database and return the name of the best matched object
278  TaggedPoints foundPointCloud = compareToDB(points);
279  matchToFoundPointCloud(points, foundPointCloud.second);
280 
281  ARMARX_IMPORTANT << "The hypothesis had "
282  << points.size()
283  << " points";
284 
285  return foundPointCloud.first;
286  }
287  else
288  {
289  ARMARX_WARNING << "No connection to DB. Unable to start classification";
290  }
291 
292  return "ERROR: No similar object found";
293 }
BBShortSide
Definition: BBShort.hpp:32
ICP.h
ARMARX_VERBOSE
#define ARMARX_VERBOSE
Definition: Logging.h:180
visionx::ObjectShapeClassification::FindSimilarKnownObject
std::string FindSimilarKnownObject(const ::visionx::types::PointList &segmentedObjectPoints, const ::Ice::Current &)
Definition: ObjectShapeClassification.cpp:257
ARMARX_IMPORTANT
#define ARMARX_IMPORTANT
Definition: Logging.h:183
visionx
ArmarX headers.
Definition: OpenPoseStressTest.h:38
by_second::operator()
bool operator()(const Pair &a, const Pair &b)
Definition: ObjectShapeClassification.cpp:143
visionx::ObjectShapeClassification::onInitComponent
void onInitComponent()
Pure virtual hook for the subclass.
Definition: ObjectShapeClassification.cpp:56
visionx::Points
std::vector< Point > Points
Definition: ObjectShapeClassification.h:70
BBMediumSide
Definition: BBMedium.hpp:32
convexHull.hpp
A3Histogram
Definition: A3Histogram.hpp:34
ObjectShapeClassification.h
memoryx
VirtualRobot headers.
Definition: CommonPlacesTester.cpp:48
BBArea
Definition: BBArea.hpp:33
CHArea
Definition: CHArea.hpp:33
visionx::ICP::SearchObject
float SearchObject(Mat3d &mRotation, Vec3d &vTranslation, const float fBestDistanceUntilNow=FLT_MAX)
Definition: ICP.cpp:103
BBVolume
Definition: BBVolume.hpp:32
IceInternal::Handle< ObjectClass >
visionx::ICP::SetScenePointcloud
void SetScenePointcloud(const std::vector< Eigen::Vector3f > &aScenePoints)
Definition: ICP.cpp:57
armarx::ctrlutil::a
double a(double t, double a0, double j)
Definition: CtrlUtil.h:45
armarx::flush
const LogSender::manipulator flush
Definition: LogSender.h:251
GfxTL::Vec3d
VectorXD< 3, double > Vec3d
Definition: VectorXD.h:695
ATTR_IV_FILE
const std::string ATTR_IV_FILE
Definition: ObjectShapeClassification.cpp:51
BBMediumShortRatio
Definition: BBMediumShort.hpp:32
IVPointParser.hpp
FeatureCalculator.hpp
visionx::ICP
Definition: ICP.h:36
BBLongShortRatio
Definition: BBLongShort.hpp:32
MemoryXCoreObjectFactories.h
D2Histogram
Definition: D2Histogram.hpp:34
CHVolume
Definition: CHVolume.hpp:32
visionx::TaggedPoints
std::pair< std::string, Points > TaggedPoints
Definition: ObjectShapeClassification.h:71
ARMARX_INFO
#define ARMARX_INFO
Definition: Logging.h:174
ATTR_FEATURES
const std::string ATTR_FEATURES
Definition: ObjectShapeClassification.cpp:50
memoryx::GridFileManager
GridFileManager provides utility functions for working with files in Mongo GridFS and links to them s...
Definition: GridFileManager.h:42
MemoryXTypesObjectFactories.h
Logging.h
ARMARX_WARNING
#define ARMARX_WARNING
Definition: Logging.h:186
BBLongSide
Definition: BBLong.hpp:32
visionx::ObjectShapeClassification::onConnectComponent
void onConnectComponent()
Pure virtual hook for the subclass.
Definition: ObjectShapeClassification.cpp:76
by_second
Definition: ObjectShapeClassification.cpp:140
Features.h
visionx::ICP::SetObjectPointcloud
void SetObjectPointcloud(const std::vector< Eigen::Vector3f > &aObjectPoints)
Definition: ICP.cpp:94
TaggedPoints
std::pair< std::string, std::vector< Eigen::Vector3f > > TaggedPoints
Definition: Memoizer.hpp:10
IVPointParser::fromFile
static std::vector< Eigen::Vector3f > fromFile(const std::string &fileName)
Definition: IVPointParser.hpp:40