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
39 
42 #include "CommonPlacesLearner.h"
43 
44 namespace memoryx
45 {
47  {
48  usingProxy("LongtermMemory");
49  usingProxy("PriorKnowledge");
50  }
51 
53  {
54  Ice::CommunicatorPtr ic = getIceManager()->getCommunicator();
55 
56 
57  longtermMemoryPrx = getProxy<LongtermMemoryInterfacePrx>("LongtermMemory");
58  priorKnowledgePrx = getProxy<PriorKnowledgeInterfacePrx>("PriorKnowledge");
59 
60  std::string segmentName = getProperty<std::string>("LTMSegment").getValue();
61  setLTMSegmentName(segmentName);
62 
63  if (!ltmInstancesSegmentPrx)
64  {
65  ARMARX_FATAL << "LTM segment not found or has an invalid type: " << segmentName;
66  }
67 
68  const float agingFactor = getProperty<float>("AgingFactor").getValue();
69  const float pruningThreshold = getProperty<float>("PruningThreshold").getValue();
70 
71  const float distanceThreshold = getProperty<float>("MergingThreshold").getValue();
72  const std::string distanceName = getProperty<std::string>("MergingDistanceType").getValue();
74 
75  if (distanceName == "Mahalanobis")
76  {
77  distance.reset(new MahalanobisDistance());
78  }
79  else if (distanceName == "KL")
80  {
81  distance.reset(new RunnallsKLDistance());
82  }
83  else if (distanceName == "ISD")
84  {
85  distance.reset(new ISDDistance);
86  }
87  else
88  {
89  ARMARX_WARNING << "Unknown MergingDistanceType: " << distanceName << ". Will use Kullback-Leibler instead.";
90  distance.reset(new RunnallsKLDistance());
91  }
92 
93  assMethod = new GaussianMixtureAssociationMethod(distanceThreshold, distance);
94  fusionMethod = new GaussianMixturePositionFusion(agingFactor, pruningThreshold, assMethod);
95 
96  const std::string reducerName = getProperty<std::string>("GMMReducerAlgorithm").getValue();
97  ARMARX_INFO << "Using GMM reduction algorithm: " << reducerName;
98 
99  if (reducerName == "West")
100  {
101  gmmReducer.reset(new WestGMMReducer());
102  }
103  else if (reducerName == "Runnalls")
104  {
105  gmmReducer.reset(new RunnallsGMMReducer());
106  }
107  else if (reducerName == "Williams")
108  {
109  gmmReducer.reset(new WilliamsGMMReducer());
110  }
111  else
112  {
113  ARMARX_WARNING << "Unknown GMMReducerAlgorithm: " << reducerName << ". Will use WestReducer instead.";
114  gmmReducer.reset(new WestGMMReducer());
115  }
116  }
117 
119  {
120  }
121 
122  void CommonPlacesLearner::setLTMSegmentName(const ::std::string& segmentName, const ::Ice::Current& c)
123  {
124  if (!ltmInstancesSegmentPrx || ltmInstancesSegmentPrx->getSegmentName() != segmentName)
125  {
126  ltmInstancesSegmentPrx = longtermMemoryPrx->getCustomInstancesSegment(segmentName, true);
127  }
128  }
129 
130  void CommonPlacesLearner::setAgingFactor(float factor, const ::Ice::Current& c)
131  {
132  fusionMethod->setAgingFactor(factor);
133  }
134 
135  void CommonPlacesLearner::setMergingThreshold(float threshold, const ::Ice::Current& c)
136  {
137  assMethod->setThreshold(threshold);
138  }
139 
140  void CommonPlacesLearner::learnFromObjectMCA(const ::std::string& objectName, const MultivariateNormalDistributionBasePtr& posDist,
141  const ::Ice::Current& c)
142  {
143  ObjectInstancePtr instance = new ObjectInstance(objectName);
144  FloatVector mean = posDist->getMean();
146  posMean->x = mean[0];
147  posMean->y = mean[1];
148  posMean->z = mean[2];
149  posMean->frame = "world";
150 
151  instance->setPosition(posMean);
152  instance->setPositionUncertainty(posDist);
153  instance->setClass(objectName, 1.);
154  learnFromObject(instance, c);
155  }
156 
157  void CommonPlacesLearner::learnFromObject(const ObjectInstanceBasePtr& newObject, const ::Ice::Current& c)
158  {
159  const std::string clsName = newObject->getMostProbableClass();
160  ObjectInstanceList ltmObjects = ltmInstancesSegmentPrx->getObjectInstancesByClass(clsName);
161 
162  if (ltmObjects.size() > 0)
163  {
164  for (ObjectInstanceList::const_iterator it = ltmObjects.begin(); it != ltmObjects.end(); ++it)
165  {
166  // update existing
167  EntityBasePtr fusedEntity = fusionMethod->fuseEntity(*it, newObject);
168  ltmInstancesSegmentPrx->updateEntity((*it)->getId(), fusedEntity);
169  ARMARX_INFO << "Updated existing object: " << newObject->getName();
170  }
171  }
172  else
173  {
174  // add new
175  EntityBasePtr fusedEntity = fusionMethod->initEntity(newObject);
176  ltmInstancesSegmentPrx->addEntity(fusedEntity);
177  ARMARX_INFO << "Added new object: " << newObject->getName();
178  }
179  }
180 
181  void CommonPlacesLearner::learnFromSnapshot(const ::std::string& snapshotName, const ::Ice::Current& c)
182  {
183  WorkingMemorySnapshotInterfacePrx snapshot = longtermMemoryPrx->openWorkingMemorySnapshot(snapshotName);
184 
185  if (!snapshot)
186  {
187  ARMARX_ERROR << "Snapshot not found in LTM: " << snapshotName;
188  return;
189  }
190 
191  const std::string segmentName = "objectInstances";
192  PersistentEntitySegmentBasePrx segInstances = snapshot->getSegment(segmentName);
193 
194  if (!segInstances)
195  {
196  ARMARX_ERROR << "Segment not found in snapshot: " << segmentName;
197  return;
198  }
199 
200  EntityIdList ids = segInstances->getAllEntityIds();
201 
202  // sort ids
203  struct EntityIdComparator
204  {
205  static bool compare(const std::string& i, const std::string& j)
206  {
207  return (std::stoi(i) < std::stoi(j));
208  }
209  };
210  std::sort(ids.begin(), ids.end(), EntityIdComparator::compare);
211 
212  for (EntityIdList::const_iterator it = ids.begin(); it != ids.end(); ++it)
213  {
214  EntityBasePtr snapEntity = segInstances->getEntityById(*it);
215  ObjectInstancePtr snapInstance = ObjectInstancePtr::dynamicCast(snapEntity);
216  learnFromObject(snapInstance, c);
217  }
218 
219  ARMARX_INFO << "Processing complete! Learned objects: " << ids.size();
220  }
221 
222  GaussianMixtureDistributionBasePtr CommonPlacesLearner::getPositionFull(const ::std::string& className, const ::Ice::Current&)
223  {
224  GaussianMixtureDistributionBasePtr result = GaussianMixtureDistributionBasePtr();
225 
226  // get subclassses
227  NameList clsList;
228  clsList.push_back(className);
229  getChildClasses(className, clsList);
230 
231  // get all objects with the class specified or one of its subclasses
232  ObjectInstanceList ltmObjects = ltmInstancesSegmentPrx->getObjectInstancesByClassList(clsList);
233  ObjectInstanceList::const_iterator it = ltmObjects.begin();
234 
235  if (it != ltmObjects.end())
236  {
237  ObjectInstancePtr inst = ObjectInstancePtr::dynamicCast(*it);
238  result = GaussianMixtureDistribution::FromProbabilityMeasure(inst->getPositionAttribute()->getUncertainty());
239 
240  for (++it; it != ltmObjects.end(); ++it)
241  {
242  inst = ObjectInstancePtr::dynamicCast(*it);
243  ARMARX_VERBOSE_S << "Processing " << inst->getName() << "..." << std::endl;
244  result->addComponents(GaussianMixtureDistribution::FromProbabilityMeasure(inst->getPositionAttribute()->getUncertainty()));
245  }
246  }
247 
248  return result;
249  }
250 
251  GaussianMixtureDistributionBasePtr CommonPlacesLearner::getPositionReducedByComponentCount(const ::std::string& objectName, Ice::Int compCount, const ::Ice::Current&)
252  {
253  GaussianMixtureDistributionBasePtr fullGMM = getPositionFull(objectName);
254 
255  if (fullGMM)
256  {
257  return gmmReducer->reduceByComponentCount(fullGMM, compCount);
258  }
259  else
260  {
261  return GaussianMixtureDistributionBasePtr();
262  }
263  }
264 
265  GaussianMixtureDistributionBasePtr CommonPlacesLearner::getPositionReducedByMaxDeviation(const ::std::string& objectName, Ice::Float maxDeviation,
266  DeviationType devType, const ::Ice::Current&)
267  {
268  GaussianMixtureDistributionBasePtr fullGMM = getPositionFull(objectName);
269 
270  if (fullGMM)
271  {
272  return gmmReducer->reduceByMaxDeviation(fullGMM, maxDeviation, convertDeviationType(devType));
273  }
274  else
275  {
276  return GaussianMixtureDistributionBasePtr();
277  }
278  }
279 
280  NormalDistributionBasePtr CommonPlacesLearner::getPositionAsGaussian(const ::std::string& objectName, const ::Ice::Current&)
281  {
282  GaussianMixtureDistributionBasePtr result = getPositionReducedByComponentCount(objectName, 1);
283 
284  if (result)
285  {
286  return result->getModalComponent().gaussian;
287  }
288  else
289  {
290  return NormalDistributionBasePtr();
291  }
292  }
293 
294  Cluster3DList CommonPlacesLearner::getPositionClustersByComponentCount(const ::std::string& objectName, Ice::Int compCount, const ::Ice::Current& c)
295  {
296  GaussianMixtureDistributionBasePtr reducedGMM = getPositionReducedByComponentCount(objectName, compCount, c);
297  return gmmToClusterList(reducedGMM);
298  }
299 
300  Cluster3DList CommonPlacesLearner::getPositionClustersByMaxDeviation(const ::std::string& objectName, Ice::Float maxDeviation,
301  DeviationType devType, const ::Ice::Current& c)
302  {
303  GaussianMixtureDistributionBasePtr reducedGMM = getPositionReducedByMaxDeviation(objectName, maxDeviation, devType, c);
304  return gmmToClusterList(reducedGMM);
305  }
306 
307  // the only purpose of this dummy function is to avoid making GaussianMixtureHelpers an Ice component or
308  // making it dependent from CommonPlacesLearner
309  DeviationMeasure CommonPlacesLearner::convertDeviationType(DeviationType devType)
310  {
311  switch (devType)
312  {
313  case eDevAABB:
314  return eAABB;
315 
316  case eDevOrientedBBox:
317  return eOrientedBBox;
318 
319  case eDevEqualSphere:
320  return eEqualSphere;
321 
322  default:
323  return eAABB;
324  }
325  }
326 
327  Cluster3DList CommonPlacesLearner::gmmToClusterList(const GaussianMixtureDistributionBasePtr& gmm)
328  {
329  Cluster3DList result;
330 
331  if (gmm)
332  {
333  for (int i = 0; i < gmm->size(); ++i)
334  {
335  Cluster3D cluster;
336  FloatVector compMean = gmm->getComponent(i).gaussian->getMean();
337  cluster.center.x = compMean[0];
338  cluster.center.y = compMean[1];
339  cluster.center.z = compMean[2];
340  cluster.weight = gmm->getComponent(i).weight;
341  result.push_back(cluster);
342  }
343  }
344 
345  // sort cluster with descending weights
346  struct Cluster3DComparator
347  {
348  static bool compare(const Cluster3D& i, const Cluster3D& j)
349  {
350  return (i.weight > j.weight);
351  }
352  };
353  std::sort(result.begin(), result.end(), Cluster3DComparator::compare);
354 
355  return result;
356  }
357 
358  void CommonPlacesLearner::getChildClasses(std::string className, NameList& result)
359  {
360  ObjectClassList children = priorKnowledgePrx->getObjectClassesSegment()->getChildClasses(className);
361  ARMARX_VERBOSE_S << "Found " << children.size() << " subclasses for " << className << std::endl;
362 
363  for (ObjectClassList::const_iterator it = children.begin(); it != children.end(); ++it)
364  {
365  result.push_back((*it)->getName());
366  }
367  }
368 }
369 
memoryx::CommonPlacesLearner::setLTMSegmentName
void setLTMSegmentName(const ::std::string &segmentName, const ::Ice::Current &=Ice::emptyCurrent) override
Definition: CommonPlacesLearner.cpp:122
armarx::ManagedIceObject::getIceManager
IceManagerPtr getIceManager() const
Returns the IceManager.
Definition: ManagedIceObject.cpp:353
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:918
memoryx::CommonPlacesLearner::setMergingThreshold
void setMergingThreshold(float threshold, const ::Ice::Current &=Ice::emptyCurrent) override
Definition: CommonPlacesLearner.cpp:135
memoryx::CommonPlacesLearner::getPositionClustersByMaxDeviation
Cluster3DList getPositionClustersByMaxDeviation(const ::std::string &objectName, Ice::Float maxDeviation, DeviationType devType, const ::Ice::Current &=Ice::emptyCurrent) override
Definition: CommonPlacesLearner.cpp:300
memoryx::CommonPlacesLearner::getPositionAsGaussian
NormalDistributionBasePtr getPositionAsGaussian(const ::std::string &objectName, const ::Ice::Current &=Ice::emptyCurrent) override
Definition: CommonPlacesLearner.cpp:280
GaussianMixtureAssociationMethod.h
ISDDistance.h
memoryx::MahalanobisDistance
Definition: MahalanobisDistance.h:40
memoryx::GaussianMixturePositionFusion
Definition: GaussianMixturePositionFusion.h:38
memoryx::CommonPlacesLearner::onConnectComponent
void onConnectComponent() override
Pure virtual hook for the subclass.
Definition: CommonPlacesLearner.cpp:52
memoryx
VirtualRobot headers.
Definition: CommonPlacesTester.cpp:48
c
constexpr T c
Definition: UnscentedKalmanFilterTest.cpp:43
memoryx::ObjectInstance
Definition: ObjectInstance.h:47
RunnallsGMMReducer.h
memoryx::DeviationMeasure
DeviationMeasure
Definition: GMMReducer.h:37
ARMARX_FATAL
#define ARMARX_FATAL
Definition: Logging.h:192
memoryx::RunnallsGMMReducer
Definition: RunnallsGMMReducer.h:38
IceInternal::Handle< ::Ice::Communicator >
memoryx::CommonPlacesLearner::onInitComponent
void onInitComponent() override
Pure virtual hook for the subclass.
Definition: CommonPlacesLearner.cpp:46
ObserverObjectFactories.h
memoryx::CommonPlacesLearner::learnFromSnapshot
void learnFromSnapshot(const ::std::string &snapshotName, const ::Ice::Current &=Ice::emptyCurrent) override
Definition: CommonPlacesLearner.cpp:181
WilliamsGMMReducer.h
memoryx::CommonPlacesLearner::getPositionFull
GaussianMixtureDistributionBasePtr getPositionFull(const ::std::string &objectName, const ::Ice::Current &=Ice::emptyCurrent) override
Definition: CommonPlacesLearner.cpp:222
memoryx::WilliamsGMMReducer
Definition: WilliamsGMMReducer.h:39
armarx::mean
std::optional< float > mean(const boost::circular_buffer< NameValueMap > &buffer, const std::string &key)
Definition: KinematicUnitGuiPlugin.cpp:1615
memoryx::CommonPlacesLearner::onExitComponent
void onExitComponent() override
Hook for subclass.
Definition: CommonPlacesLearner.cpp:118
MahalanobisDistance.h
memoryx::CommonPlacesLearner::getPositionReducedByComponentCount
GaussianMixtureDistributionBasePtr getPositionReducedByComponentCount(const ::std::string &objectName, Ice::Int compCount, const ::Ice::Current &=Ice::emptyCurrent) override
Definition: CommonPlacesLearner.cpp:251
armarx::FloatVector
::std::vector< ::Ice::Float > FloatVector
Definition: KinematicUnitGuiPlugin.h:327
GaussianMixturePositionFusion.h
memoryx::eAABB
@ eAABB
Definition: GMMReducer.h:39
MemoryXCoreObjectFactories.h
ARMARX_ERROR
#define ARMARX_ERROR
Definition: Logging.h:189
memoryx::eEqualSphere
@ eEqualSphere
Definition: GMMReducer.h:41
CommonPlacesLearner.h
memoryx::WestGMMReducer
Definition: WestGMMReducer.h:38
armarx::detail::compare
int compare(const T &lhs, const T &rhs)
Definition: TreeWidgetBuilder.h:278
memoryx::GaussianMixtureDistribution::FromProbabilityMeasure
static GaussianMixtureDistributionPtr FromProbabilityMeasure(const ProbabilityMeasureBasePtr &probMeasure)
Convert or approximate given ProbabilityMeasure to a gaussian mixture.
Definition: ProbabilityMeasures.cpp:658
WestGMMReducer.h
ARMARX_INFO
#define ARMARX_INFO
Definition: Logging.h:174
memoryx::GaussianMixtureAssociationMethod
Definition: GaussianMixtureAssociationMethod.h:38
RunnallsKLDistance.h
memoryx::CommonPlacesLearner::learnFromObjectMCA
void learnFromObjectMCA(const ::std::string &objectName, const MultivariateNormalDistributionBasePtr &posDist, const ::Ice::Current &=Ice::emptyCurrent) override
Definition: CommonPlacesLearner.cpp:140
memoryx::CommonPlacesLearner::getPositionClustersByComponentCount
Cluster3DList getPositionClustersByComponentCount(const ::std::string &objectName, Ice::Int compCount, const ::Ice::Current &=Ice::emptyCurrent) override
Definition: CommonPlacesLearner.cpp:294
memoryx::GMMDistancePtr
std::shared_ptr< GMMDistance > GMMDistancePtr
Definition: GMMDistance.h:61
armarx::VariantType::Int
const VariantTypeId Int
Definition: Variant.h:916
MemoryXTypesObjectFactories.h
ARMARX_VERBOSE_S
#define ARMARX_VERBOSE_S
Definition: Logging.h:200
distance
double distance(const Point &a, const Point &b)
Definition: point.hpp:88
armarx::VariantType::FramedPosition
const VariantTypeId FramedPosition
Definition: FramedPose.h:39
ARMARX_WARNING
#define ARMARX_WARNING
Definition: Logging.h:186
memoryx::CommonPlacesLearner::getPositionReducedByMaxDeviation
GaussianMixtureDistributionBasePtr getPositionReducedByMaxDeviation(const ::std::string &objectName, Ice::Float maxDeviation, DeviationType devType, const ::Ice::Current &=Ice::emptyCurrent) override
Definition: CommonPlacesLearner.cpp:265
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:151
memoryx::ISDDistance
Definition: ISDDistance.h:42
memoryx::CommonPlacesLearner::learnFromObject
void learnFromObject(const ObjectInstanceBasePtr &newObject, const ::Ice::Current &=Ice::emptyCurrent) override
Definition: CommonPlacesLearner.cpp:157
memoryx::RunnallsKLDistance
Definition: RunnallsKLDistance.h:41
memoryx::CommonPlacesLearner::setAgingFactor
void setAgingFactor(float factor, const ::Ice::Current &=Ice::emptyCurrent) override
Definition: CommonPlacesLearner.cpp:130