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
33namespace memoryx
34{
35 /**
36 * @class GaussianMixturePositionFusion
37 * @ingroup CommonPlacesLearner
38 */
40 {
41 public:
42 /**
43 * Creates a new GaussianMixturePositionFusion
44 */
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);
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
#define ARMARXCORE_IMPORT_EXPORT
The FramedPosition class.
Definition FramedPose.h:158
EntityFusionMethod(std::string methodName)
Constructs a new fusion method.
static GaussianMixtureDistributionPtr FromProbabilityMeasure(const ProbabilityMeasureBasePtr &probMeasure)
Convert or approximate given ProbabilityMeasure to a gaussian mixture.
EntityBasePtr fuseEntity(const EntityBasePtr &oldEntity, const EntityBasePtr &newEntity, const ::Ice::Current &=Ice::emptyCurrent) override
GaussianMixturePositionFusion(float agingFactor, float pruningThreshold, const GaussianMixtureAssociationMethodBasePtr &assMethod)
Creates a new GaussianMixturePositionFusion.
EntityBasePtr initEntity(const EntityBasePtr &updateEntity, const ::Ice::Current &=Ice::emptyCurrent) override
The MultivariateNormalDistribution class.
IceInternal::Handle< FramedPosition > FramedPositionPtr
Definition FramedPose.h:149
VirtualRobot headers.
IceInternal::Handle< NormalDistribution > NormalDistributionPtr
IceInternal::Handle< GaussianMixtureDistribution > GaussianMixtureDistributionPtr
IceInternal::Handle< ObjectInstance > ObjectInstancePtr
IceInternal::Handle< GaussianMixturePositionFusion > GaussianMixturePositionFusionPtr