GaussianMixturePositionFusion.h
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::Core
17 * @author Alexey Kozlov <kozlov@kit.edu>
18 * @copyright 2013 Alexey Kozlov
19 * @license http://www.gnu.org/licenses/gpl-2.0.txt
20 * GNU General Public License
21 */
22 
23 #pragma once
24 
25 #include <string>
28 
31 
32 namespace memoryx
33 {
34  /**
35  * @class GaussianMixturePositionFusion
36  * @ingroup CommonPlacesLearner
37  */
39  virtual public EntityFusionMethod
40  {
41  public:
42  /**
43  * Creates a new GaussianMixturePositionFusion
44  */
45  GaussianMixturePositionFusion(float agingFactor, float pruningThreshold, const GaussianMixtureAssociationMethodBasePtr& assMethod) :
46  EntityFusionMethod("GaussianMixturePositionFusion"), agingFactor(agingFactor), pruningThreshold(pruningThreshold),
47  associationMethod(assMethod)
48  {
49  }
50 
51  void setAgingFactor(float factor)
52  {
53  agingFactor = factor;
54  }
55 
56  /**
57  *
58  * @param updateEntity entity
59  * @return entity with position as GM, ready to be stored in LTM
60  */
61  EntityBasePtr initEntity(const EntityBasePtr& updateEntity, const ::Ice::Current& = Ice::emptyCurrent) override
62  {
63  ObjectInstancePtr instance = ObjectInstancePtr::dynamicCast(updateEntity);
64 
65  if (!instance)
66  {
67  return EntityBasePtr(); // TODO exception
68  }
69 
70  MultivariateNormalDistributionBasePtr posGaussian = instance->getPositionUncertainty();
71 
72  if (posGaussian)
73  {
74  ObjectInstancePtr fusedInstance = ObjectInstancePtr::dynamicCast(instance->ice_clone());
75 
76  // clear id to allow it to be auto-generated (ids in snapshots are ints, not MongoIds!)
77  fusedInstance->setId("");
78 
79  // convert position uncertainty to GM
81  // posGM->scaleComponents(0.8);
82  fusedInstance->getPositionAttribute()->setValueWithUncertainty(instance->getPositionAttribute()->getValue(), posGM);
83  return fusedInstance;
84  }
85  else
86  {
87  return updateEntity;
88  }
89  };
90 
91  /**
92  *
93  * @param oldEntity entity before update
94  * @param newEntity entity after update
95  *
96  * @return entity with fusioned position
97  */
98  EntityBasePtr fuseEntity(const EntityBasePtr& oldEntity, const EntityBasePtr& newEntity, const ::Ice::Current& = Ice::emptyCurrent) override
99  {
100  ObjectInstancePtr fusedInstance = ObjectInstancePtr::dynamicCast(oldEntity->ice_clone());
101  EntityAttributeBasePtr posAttr = fusedInstance->getPositionAttribute();
102  GaussianMixtureDistributionPtr posGM = GaussianMixtureDistributionPtr::dynamicCast(posAttr->getUncertainty());
103 
104  if (posGM)
105  {
106  ObjectInstancePtr newInstance = ObjectInstancePtr::dynamicCast(newEntity);
107 
108  // apply aging
109  posGM->scaleComponents(agingFactor);
110 
111  MultivariateNormalDistributionBasePtr newUncertainty = newInstance->getPositionUncertainty();
112  GaussianMixtureComponent newComp;
113  newComp.gaussian = newUncertainty;
114  newComp.weight = 1.;
115 
116  GaussianMixtureDistributionPtr normGM = GaussianMixtureDistributionPtr::dynamicCast(posGM->clone());
117  // normGM->normalize();
118  int associatedCompIndex = associationMethod->getAssociatedComponentIndex(normGM, newComp);
119 
120  if (associatedCompIndex >= 0)
121  {
122  GaussianMixtureComponent associatedComp = posGM->getComponent(associatedCompIndex);
123  GaussianMixtureComponent associatedNormComp = normGM->getComponent(associatedCompIndex);
124  GaussianMixtureComponent newNormComp = normGM->getComponent(posGM->size() - 1);
125  GaussianMixtureComponent fusedComp = fuseGaussianComponents(associatedNormComp, newNormComp);
126  fusedComp.weight = newComp.weight + associatedComp.weight;
127  posGM->setComponent(associatedCompIndex, fusedComp);
128  }
129  else
130  {
131  posGM->addComponent(newComp);
132  }
133 
134  // perform pruning
135  if (pruningThreshold > 0)
136  {
137  posGM->pruneComponents(pruningThreshold);
138  }
139 
140  // normalize weights
141  // posGM->normalize();
142 
143  // set mean and uncertainty back to entity
144  GaussianMixtureComponent modalComp = posGM->getModalComponent();
145 
146  if (modalComp.gaussian)
147  {
148  NormalDistributionPtr gaussian = NormalDistributionPtr::dynamicCast(modalComp.gaussian);
149  armarx::FramedPositionPtr posMean = new armarx::FramedPosition(Eigen::Vector3f(gaussian->toEigenMean()), fusedInstance->getPosition()->getFrame(), fusedInstance->getPosition()->agent);
150  fusedInstance->setPosition(posMean);
151  fusedInstance->getPositionAttribute()->setValueWithUncertainty(fusedInstance->getPositionAttribute()->getValue(), posGM);
152  return fusedInstance;
153  }
154  else
155  {
156  return EntityBasePtr(); // TODO exception
157  }
158  }
159  else
160  {
161  return EntityBasePtr(); // TODO exception
162  }
163  };
164 
165  private:
166  float agingFactor;
167  float pruningThreshold;
168  GaussianMixtureAssociationMethodBasePtr associationMethod;
169 
170  GaussianMixtureComponent fuseGaussianComponents(const GaussianMixtureComponent& oldComp, const GaussianMixtureComponent& newComp)
171  {
172  NormalDistributionPtr oldGaussian = NormalDistributionPtr::dynamicCast(oldComp.gaussian);
173  NormalDistributionPtr newGaussian = NormalDistributionPtr::dynamicCast(newComp.gaussian);
174 
175  const Eigen::VectorXf x1 = oldGaussian->toEigenMean();
176  const Eigen::VectorXf x2 = newGaussian->toEigenMean();
177  const Eigen::MatrixXf p1 = oldGaussian->toEigenCovariance();
178  const Eigen::MatrixXf p2 = newGaussian->toEigenCovariance();
179 
180  const float w1 = oldComp.weight;
181  const float w2 = newComp.weight;
182 
183  const float k = 1. / (w1 + w2);
184  const Eigen::VectorXf d = x1 - x2;
185 
186  const Eigen::VectorXf mean = k * (w1 * x1 + w2 * x2);
187  const Eigen::MatrixXf cov = k * (w1 * p1 + w2 * p2 + k * w1 * w2 * d * d.transpose());
188 
189  GaussianMixtureComponent result;
190  result.gaussian = new MultivariateNormalDistribution(mean, cov);
191  result.weight = w1 + w2;
192  return result;
193  }
194  };
195 
197 }
198 
memoryx::GaussianMixturePositionFusion::GaussianMixturePositionFusion
GaussianMixturePositionFusion(float agingFactor, float pruningThreshold, const GaussianMixtureAssociationMethodBasePtr &assMethod)
Creates a new GaussianMixturePositionFusion.
Definition: GaussianMixturePositionFusion.h:45
memoryx::GaussianMixturePositionFusion
Definition: GaussianMixturePositionFusion.h:38
memoryx
VirtualRobot headers.
Definition: CommonPlacesTester.cpp:48
memoryx::EntityFusionMethod
Interface for fusion methods used for entities in working memory.
Definition: EntityFusionMethod.h:43
IceInternal::Handle< ObjectInstance >
armarx::mean
std::optional< float > mean(const boost::circular_buffer< NameValueMap > &buffer, const std::string &key)
Definition: KinematicUnitGuiPlugin.cpp:1615
memoryx::GaussianMixturePositionFusion::fuseEntity
EntityBasePtr fuseEntity(const EntityBasePtr &oldEntity, const EntityBasePtr &newEntity, const ::Ice::Current &=Ice::emptyCurrent) override
Definition: GaussianMixturePositionFusion.h:98
memoryx::GaussianMixtureDistribution::FromProbabilityMeasure
static GaussianMixtureDistributionPtr FromProbabilityMeasure(const ProbabilityMeasureBasePtr &probMeasure)
Convert or approximate given ProbabilityMeasure to a gaussian mixture.
Definition: ProbabilityMeasures.cpp:658
ProbabilityMeasures.h
ObjectInstance.h
ImportExport.h
memoryx::GaussianMixturePositionFusion::initEntity
EntityBasePtr initEntity(const EntityBasePtr &updateEntity, const ::Ice::Current &=Ice::emptyCurrent) override
Definition: GaussianMixturePositionFusion.h:61
ARMARXCORE_IMPORT_EXPORT
#define ARMARXCORE_IMPORT_EXPORT
Definition: ImportExport.h:38
armarx::VariantType::FramedPosition
const VariantTypeId FramedPosition
Definition: FramedPose.h:39
memoryx::GaussianMixturePositionFusion::setAgingFactor
void setAgingFactor(float factor)
Definition: GaussianMixturePositionFusion.h:51
EntityFusionMethod.h
armarx::VariantType::MultivariateNormalDistribution
const armarx::VariantTypeId MultivariateNormalDistribution
Definition: ProbabilityMeasures.h:36