CommonPlacesLearner.cpp
Go to the documentation of this file.
1 /*
2 * This file is part of ArmarX.
3 *
4 * ArmarX is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 *
8 * ArmarX is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * @package MemoryX::CommonPlacesLearner
17 * @author Alexey Kozlov ( kozlov at kit dot edu)
18 * @date 2013
19 * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
20 * GNU General Public License
21 */
22 
23 // memoryx interface
24 #include <MemoryX/interface/core/EntityBase.h>
25 #include <MemoryX/interface/memorytypes/MemoryEntities.h>
26 
27 // memoryx helpers
34 
35 // Object Factories
37 
38 #include "CommonPlacesLearner.h"
43 
44 namespace memoryx
45 {
46  void
48  {
49  usingProxy("LongtermMemory");
50  usingProxy("PriorKnowledge");
51  }
52 
53  void
55  {
56  Ice::CommunicatorPtr ic = getIceManager()->getCommunicator();
57 
58 
59  longtermMemoryPrx = getProxy<LongtermMemoryInterfacePrx>("LongtermMemory");
60  priorKnowledgePrx = getProxy<PriorKnowledgeInterfacePrx>("PriorKnowledge");
61 
62  std::string segmentName = getProperty<std::string>("LTMSegment").getValue();
63  setLTMSegmentName(segmentName);
64 
65  if (!ltmInstancesSegmentPrx)
66  {
67  ARMARX_FATAL << "LTM segment not found or has an invalid type: " << segmentName;
68  }
69 
70  const float agingFactor = getProperty<float>("AgingFactor").getValue();
71  const float pruningThreshold = getProperty<float>("PruningThreshold").getValue();
72 
73  const float distanceThreshold = getProperty<float>("MergingThreshold").getValue();
74  const std::string distanceName = getProperty<std::string>("MergingDistanceType").getValue();
76 
77  if (distanceName == "Mahalanobis")
78  {
79  distance.reset(new MahalanobisDistance());
80  }
81  else if (distanceName == "KL")
82  {
83  distance.reset(new RunnallsKLDistance());
84  }
85  else if (distanceName == "ISD")
86  {
87  distance.reset(new ISDDistance);
88  }
89  else
90  {
91  ARMARX_WARNING << "Unknown MergingDistanceType: " << distanceName
92  << ". Will use Kullback-Leibler instead.";
93  distance.reset(new RunnallsKLDistance());
94  }
95 
96  assMethod = new GaussianMixtureAssociationMethod(distanceThreshold, distance);
97  fusionMethod = new GaussianMixturePositionFusion(agingFactor, pruningThreshold, assMethod);
98 
99  const std::string reducerName = getProperty<std::string>("GMMReducerAlgorithm").getValue();
100  ARMARX_INFO << "Using GMM reduction algorithm: " << reducerName;
101 
102  if (reducerName == "West")
103  {
104  gmmReducer.reset(new WestGMMReducer());
105  }
106  else if (reducerName == "Runnalls")
107  {
108  gmmReducer.reset(new RunnallsGMMReducer());
109  }
110  else if (reducerName == "Williams")
111  {
112  gmmReducer.reset(new WilliamsGMMReducer());
113  }
114  else
115  {
116  ARMARX_WARNING << "Unknown GMMReducerAlgorithm: " << reducerName
117  << ". Will use WestReducer instead.";
118  gmmReducer.reset(new WestGMMReducer());
119  }
120  }
121 
122  void
124  {
125  }
126 
127  void
128  CommonPlacesLearner::setLTMSegmentName(const ::std::string& segmentName,
129  const ::Ice::Current& c)
130  {
131  if (!ltmInstancesSegmentPrx || ltmInstancesSegmentPrx->getSegmentName() != segmentName)
132  {
133  ltmInstancesSegmentPrx =
134  longtermMemoryPrx->getCustomInstancesSegment(segmentName, true);
135  }
136  }
137 
138  void
139  CommonPlacesLearner::setAgingFactor(float factor, const ::Ice::Current& c)
140  {
141  fusionMethod->setAgingFactor(factor);
142  }
143 
144  void
145  CommonPlacesLearner::setMergingThreshold(float threshold, const ::Ice::Current& c)
146  {
147  assMethod->setThreshold(threshold);
148  }
149 
150  void
151  CommonPlacesLearner::learnFromObjectMCA(const ::std::string& objectName,
152  const MultivariateNormalDistributionBasePtr& posDist,
153  const ::Ice::Current& c)
154  {
155  ObjectInstancePtr instance = new ObjectInstance(objectName);
156  FloatVector mean = posDist->getMean();
158  posMean->x = mean[0];
159  posMean->y = mean[1];
160  posMean->z = mean[2];
161  posMean->frame = "world";
162 
163  instance->setPosition(posMean);
164  instance->setPositionUncertainty(posDist);
165  instance->setClass(objectName, 1.);
166  learnFromObject(instance, c);
167  }
168 
169  void
170  CommonPlacesLearner::learnFromObject(const ObjectInstanceBasePtr& newObject,
171  const ::Ice::Current& c)
172  {
173  const std::string clsName = newObject->getMostProbableClass();
174  ObjectInstanceList ltmObjects = ltmInstancesSegmentPrx->getObjectInstancesByClass(clsName);
175 
176  if (ltmObjects.size() > 0)
177  {
178  for (ObjectInstanceList::const_iterator it = ltmObjects.begin(); it != ltmObjects.end();
179  ++it)
180  {
181  // update existing
182  EntityBasePtr fusedEntity = fusionMethod->fuseEntity(*it, newObject);
183  ltmInstancesSegmentPrx->updateEntity((*it)->getId(), fusedEntity);
184  ARMARX_INFO << "Updated existing object: " << newObject->getName();
185  }
186  }
187  else
188  {
189  // add new
190  EntityBasePtr fusedEntity = fusionMethod->initEntity(newObject);
191  ltmInstancesSegmentPrx->addEntity(fusedEntity);
192  ARMARX_INFO << "Added new object: " << newObject->getName();
193  }
194  }
195 
196  void
197  CommonPlacesLearner::learnFromSnapshot(const ::std::string& snapshotName,
198  const ::Ice::Current& c)
199  {
200  WorkingMemorySnapshotInterfacePrx snapshot =
201  longtermMemoryPrx->openWorkingMemorySnapshot(snapshotName);
202 
203  if (!snapshot)
204  {
205  ARMARX_ERROR << "Snapshot not found in LTM: " << snapshotName;
206  return;
207  }
208 
209  const std::string segmentName = "objectInstances";
210  PersistentEntitySegmentBasePrx segInstances = snapshot->getSegment(segmentName);
211 
212  if (!segInstances)
213  {
214  ARMARX_ERROR << "Segment not found in snapshot: " << segmentName;
215  return;
216  }
217 
218  EntityIdList ids = segInstances->getAllEntityIds();
219 
220  // sort ids
221  struct EntityIdComparator
222  {
223  static bool
224  compare(const std::string& i, const std::string& j)
225  {
226  return (std::stoi(i) < std::stoi(j));
227  }
228  };
229 
230  std::sort(ids.begin(), ids.end(), EntityIdComparator::compare);
231 
232  for (EntityIdList::const_iterator it = ids.begin(); it != ids.end(); ++it)
233  {
234  EntityBasePtr snapEntity = segInstances->getEntityById(*it);
235  ObjectInstancePtr snapInstance = ObjectInstancePtr::dynamicCast(snapEntity);
236  learnFromObject(snapInstance, c);
237  }
238 
239  ARMARX_INFO << "Processing complete! Learned objects: " << ids.size();
240  }
241 
242  GaussianMixtureDistributionBasePtr
243  CommonPlacesLearner::getPositionFull(const ::std::string& className, const ::Ice::Current&)
244  {
245  GaussianMixtureDistributionBasePtr result = GaussianMixtureDistributionBasePtr();
246 
247  // get subclassses
248  NameList clsList;
249  clsList.push_back(className);
250  getChildClasses(className, clsList);
251 
252  // get all objects with the class specified or one of its subclasses
253  ObjectInstanceList ltmObjects =
254  ltmInstancesSegmentPrx->getObjectInstancesByClassList(clsList);
255  ObjectInstanceList::const_iterator it = ltmObjects.begin();
256 
257  if (it != ltmObjects.end())
258  {
259  ObjectInstancePtr inst = ObjectInstancePtr::dynamicCast(*it);
261  inst->getPositionAttribute()->getUncertainty());
262 
263  for (++it; it != ltmObjects.end(); ++it)
264  {
265  inst = ObjectInstancePtr::dynamicCast(*it);
266  ARMARX_VERBOSE_S << "Processing " << inst->getName() << "..." << std::endl;
268  inst->getPositionAttribute()->getUncertainty()));
269  }
270  }
271 
272  return result;
273  }
274 
275  GaussianMixtureDistributionBasePtr
277  Ice::Int compCount,
278  const ::Ice::Current&)
279  {
280  GaussianMixtureDistributionBasePtr fullGMM = getPositionFull(objectName);
281 
282  if (fullGMM)
283  {
284  return gmmReducer->reduceByComponentCount(fullGMM, compCount);
285  }
286  else
287  {
288  return GaussianMixtureDistributionBasePtr();
289  }
290  }
291 
292  GaussianMixtureDistributionBasePtr
294  Ice::Float maxDeviation,
295  DeviationType devType,
296  const ::Ice::Current&)
297  {
298  GaussianMixtureDistributionBasePtr fullGMM = getPositionFull(objectName);
299 
300  if (fullGMM)
301  {
302  return gmmReducer->reduceByMaxDeviation(
303  fullGMM, maxDeviation, convertDeviationType(devType));
304  }
305  else
306  {
307  return GaussianMixtureDistributionBasePtr();
308  }
309  }
310 
311  NormalDistributionBasePtr
312  CommonPlacesLearner::getPositionAsGaussian(const ::std::string& objectName,
313  const ::Ice::Current&)
314  {
315  GaussianMixtureDistributionBasePtr result =
316  getPositionReducedByComponentCount(objectName, 1);
317 
318  if (result)
319  {
320  return result->getModalComponent().gaussian;
321  }
322  else
323  {
324  return NormalDistributionBasePtr();
325  }
326  }
327 
328  Cluster3DList
330  Ice::Int compCount,
331  const ::Ice::Current& c)
332  {
333  GaussianMixtureDistributionBasePtr reducedGMM =
334  getPositionReducedByComponentCount(objectName, compCount, c);
335  return gmmToClusterList(reducedGMM);
336  }
337 
338  Cluster3DList
340  Ice::Float maxDeviation,
341  DeviationType devType,
342  const ::Ice::Current& c)
343  {
344  GaussianMixtureDistributionBasePtr reducedGMM =
345  getPositionReducedByMaxDeviation(objectName, maxDeviation, devType, c);
346  return gmmToClusterList(reducedGMM);
347  }
348 
349  // the only purpose of this dummy function is to avoid making GaussianMixtureHelpers an Ice component or
350  // making it dependent from CommonPlacesLearner
352  CommonPlacesLearner::convertDeviationType(DeviationType devType)
353  {
354  switch (devType)
355  {
356  case eDevAABB:
357  return eAABB;
358 
359  case eDevOrientedBBox:
360  return eOrientedBBox;
361 
362  case eDevEqualSphere:
363  return eEqualSphere;
364 
365  default:
366  return eAABB;
367  }
368  }
369 
370  Cluster3DList
371  CommonPlacesLearner::gmmToClusterList(const GaussianMixtureDistributionBasePtr& gmm)
372  {
373  Cluster3DList result;
374 
375  if (gmm)
376  {
377  for (int i = 0; i < gmm->size(); ++i)
378  {
379  Cluster3D cluster;
380  FloatVector compMean = gmm->getComponent(i).gaussian->getMean();
381  cluster.center.x = compMean[0];
382  cluster.center.y = compMean[1];
383  cluster.center.z = compMean[2];
384  cluster.weight = gmm->getComponent(i).weight;
385  result.push_back(cluster);
386  }
387  }
388 
389  // sort cluster with descending weights
390  struct Cluster3DComparator
391  {
392  static bool
393  compare(const Cluster3D& i, const Cluster3D& j)
394  {
395  return (i.weight > j.weight);
396  }
397  };
398 
399  std::sort(result.begin(), result.end(), Cluster3DComparator::compare);
400 
401  return result;
402  }
403 
404  void
405  CommonPlacesLearner::getChildClasses(std::string className, NameList& result)
406  {
407  ObjectClassList children =
408  priorKnowledgePrx->getObjectClassesSegment()->getChildClasses(className);
409  ARMARX_VERBOSE_S << "Found " << children.size() << " subclasses for " << className
410  << std::endl;
411 
412  for (ObjectClassList::const_iterator it = children.begin(); it != children.end(); ++it)
413  {
414  result.push_back((*it)->getName());
415  }
416  }
417 } // namespace memoryx
memoryx::CommonPlacesLearner::setLTMSegmentName
void setLTMSegmentName(const ::std::string &segmentName, const ::Ice::Current &=Ice::emptyCurrent) override
Definition: CommonPlacesLearner.cpp:128
armarx::ManagedIceObject::getIceManager
IceManagerPtr getIceManager() const
Returns the IceManager.
Definition: ManagedIceObject.cpp:366
cyberglove_with_calib_22dof.ic
ic
Definition: cyberglove_with_calib_22dof.py:22
memoryx::eOrientedBBox
@ eOrientedBBox
Definition: GMMReducer.h:40
armarx::VariantType::Float
const VariantTypeId Float
Definition: Variant.h:919
memoryx::CommonPlacesLearner::setMergingThreshold
void setMergingThreshold(float threshold, const ::Ice::Current &=Ice::emptyCurrent) override
Definition: CommonPlacesLearner.cpp:145
memoryx::CommonPlacesLearner::getPositionClustersByMaxDeviation
Cluster3DList getPositionClustersByMaxDeviation(const ::std::string &objectName, Ice::Float maxDeviation, DeviationType devType, const ::Ice::Current &=Ice::emptyCurrent) override
Definition: CommonPlacesLearner.cpp:339
memoryx::CommonPlacesLearner::getPositionAsGaussian
NormalDistributionBasePtr getPositionAsGaussian(const ::std::string &objectName, const ::Ice::Current &=Ice::emptyCurrent) override
Definition: CommonPlacesLearner.cpp:312
GaussianMixtureAssociationMethod.h
ISDDistance.h
memoryx::MahalanobisDistance
Definition: MahalanobisDistance.h:41
memoryx::GaussianMixturePositionFusion
Definition: GaussianMixturePositionFusion.h:39
memoryx::CommonPlacesLearner::onConnectComponent
void onConnectComponent() override
Pure virtual hook for the subclass.
Definition: CommonPlacesLearner.cpp:54
memoryx
VirtualRobot headers.
Definition: CommonPlacesTester.cpp:48
c
constexpr T c
Definition: UnscentedKalmanFilterTest.cpp:46
memoryx::ObjectInstance
Definition: ObjectInstance.h:48
RunnallsGMMReducer.h
memoryx::DeviationMeasure
DeviationMeasure
Definition: GMMReducer.h:37
ARMARX_FATAL
#define ARMARX_FATAL
Definition: Logging.h:199
memoryx::RunnallsGMMReducer
Definition: RunnallsGMMReducer.h:39
IceInternal::Handle<::Ice::Communicator >
armarx::FloatVector
::std::vector<::Ice::Float > FloatVector
Definition: KinematicUnitGuiPlugin.h:325
memoryx::CommonPlacesLearner::onInitComponent
void onInitComponent() override
Pure virtual hook for the subclass.
Definition: CommonPlacesLearner.cpp:47
ObserverObjectFactories.h
memoryx::CommonPlacesLearner::learnFromSnapshot
void learnFromSnapshot(const ::std::string &snapshotName, const ::Ice::Current &=Ice::emptyCurrent) override
Definition: CommonPlacesLearner.cpp:197
WilliamsGMMReducer.h
memoryx::CommonPlacesLearner::getPositionFull
GaussianMixtureDistributionBasePtr getPositionFull(const ::std::string &objectName, const ::Ice::Current &=Ice::emptyCurrent) override
Definition: CommonPlacesLearner.cpp:243
memoryx::WilliamsGMMReducer
Definition: WilliamsGMMReducer.h:40
armarx::mean
std::optional< float > mean(const boost::circular_buffer< NameValueMap > &buffer, const std::string &key)
Definition: KinematicUnitGuiPlugin.cpp:1620
memoryx::CommonPlacesLearner::onExitComponent
void onExitComponent() override
Hook for subclass.
Definition: CommonPlacesLearner.cpp:123
MahalanobisDistance.h
memoryx::CommonPlacesLearner::getPositionReducedByComponentCount
GaussianMixtureDistributionBasePtr getPositionReducedByComponentCount(const ::std::string &objectName, Ice::Int compCount, const ::Ice::Current &=Ice::emptyCurrent) override
Definition: CommonPlacesLearner.cpp:276
GaussianMixturePositionFusion.h
memoryx::eAABB
@ eAABB
Definition: GMMReducer.h:39
MemoryXCoreObjectFactories.h
ARMARX_ERROR
#define ARMARX_ERROR
Definition: Logging.h:196
memoryx::eEqualSphere
@ eEqualSphere
Definition: GMMReducer.h:41
CommonPlacesLearner.h
memoryx::WestGMMReducer
Definition: WestGMMReducer.h:39
armarx::detail::compare
int compare(const T &lhs, const T &rhs)
Definition: TreeWidgetBuilder.h:321
memoryx::GaussianMixtureDistribution::FromProbabilityMeasure
static GaussianMixtureDistributionPtr FromProbabilityMeasure(const ProbabilityMeasureBasePtr &probMeasure)
Convert or approximate given ProbabilityMeasure to a gaussian mixture.
Definition: ProbabilityMeasures.cpp:760
WestGMMReducer.h
ARMARX_INFO
#define ARMARX_INFO
Definition: Logging.h:181
memoryx::GaussianMixtureAssociationMethod
Definition: GaussianMixtureAssociationMethod.h:40
RunnallsKLDistance.h
memoryx::CommonPlacesLearner::learnFromObjectMCA
void learnFromObjectMCA(const ::std::string &objectName, const MultivariateNormalDistributionBasePtr &posDist, const ::Ice::Current &=Ice::emptyCurrent) override
Definition: CommonPlacesLearner.cpp:151
memoryx::CommonPlacesLearner::getPositionClustersByComponentCount
Cluster3DList getPositionClustersByComponentCount(const ::std::string &objectName, Ice::Int compCount, const ::Ice::Current &=Ice::emptyCurrent) override
Definition: CommonPlacesLearner.cpp:329
memoryx::GMMDistancePtr
std::shared_ptr< GMMDistance > GMMDistancePtr
Definition: GMMDistance.h:62
armarx::VariantType::Int
const VariantTypeId Int
Definition: Variant.h:917
MemoryXTypesObjectFactories.h
ARMARX_VERBOSE_S
#define ARMARX_VERBOSE_S
Definition: Logging.h:207
distance
double distance(const Point &a, const Point &b)
Definition: point.hpp:95
armarx::VariantType::FramedPosition
const VariantTypeId FramedPosition
Definition: FramedPose.h:38
ARMARX_WARNING
#define ARMARX_WARNING
Definition: Logging.h:193
memoryx::CommonPlacesLearner::getPositionReducedByMaxDeviation
GaussianMixtureDistributionBasePtr getPositionReducedByMaxDeviation(const ::std::string &objectName, Ice::Float maxDeviation, DeviationType devType, const ::Ice::Current &=Ice::emptyCurrent) override
Definition: CommonPlacesLearner.cpp:293
armarx::ManagedIceObject::usingProxy
bool usingProxy(const std::string &name, const std::string &endpoints="")
Registers a proxy for retrieval after initialization and adds it to the dependency list.
Definition: ManagedIceObject.cpp:154
memoryx::ISDDistance
Definition: ISDDistance.h:42
memoryx::CommonPlacesLearner::learnFromObject
void learnFromObject(const ObjectInstanceBasePtr &newObject, const ::Ice::Current &=Ice::emptyCurrent) override
Definition: CommonPlacesLearner.cpp:170
memoryx::RunnallsKLDistance
Definition: RunnallsKLDistance.h:41
memoryx::CommonPlacesLearner::setAgingFactor
void setAgingFactor(float factor, const ::Ice::Current &=Ice::emptyCurrent) override
Definition: CommonPlacesLearner.cpp:139