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