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