KalmanFilterFusion.cpp
Go to the documentation of this file.
1 #include "KalmanFilterFusion.h"
2 
5 
7 
11 
12 namespace memoryx
13 {
14 
16  {
17  }
18 
19  EntityBasePtr
20  KalmanFilterFusion::initEntity(const EntityBasePtr& updateEntity, const Ice::Current&)
21  {
22  return updateEntity;
23  }
24 
25  EntityBasePtr
26  KalmanFilterFusion::fuseEntity(const EntityBasePtr& oldEntity,
27  const EntityBasePtr& newEntity,
28  const Ice::Current&)
29  {
30  ARMARX_DEBUG_S << "KalmanFilterFusion::fuseEntity() called";
31 
32  ObjectInstancePtr oldInstance = ObjectInstancePtr::dynamicCast(oldEntity);
33  ObjectInstancePtr newInstance = ObjectInstancePtr::dynamicCast(newEntity);
34  ObjectInstancePtr fusedInstance;
35 
36  ARMARX_CHECK_EXPRESSION(oldInstance);
37  ARMARX_CHECK_EXPRESSION(newInstance);
38 
39  if (!oldInstance->getMotionModel())
40  {
41  return newInstance;
42  }
43 
44  armarx::LinkedPoseBasePtr oldPoseBase =
45  oldInstance->getMotionModel()->getPredictedPoseAtStartOfCurrentLocalization();
46 
47  if (oldPoseBase)
48  {
49  armarx::LinkedPosePtr oldPose =
50  armarx::LinkedPosePtr::dynamicCast(oldPoseBase->clone());
51  ARMARX_CHECK_EXPRESSION(oldPose);
52  ARMARX_DEBUG_S << "Pose before fusion " << oldPose->output();
53  ARMARX_DEBUG_S << "Pose of update " << newInstance->getPose()->output();
54 
55  oldPose->changeFrame(newInstance->getPosition()->frame);
56 
57 
58  // make sure nothing is lost. TODO: clone new instance here instead of old one? -> Does not seem to work with newInstance->clone(); Then multiple instances appear
59  fusedInstance = oldInstance->clone();
60 
61 
62  // update existence certainty
63 
64  float oldExistenceCertainty = std::max(oldInstance->getExistenceCertainty(), 0.1f);
65  float newExistenceCertainty = std::max(newInstance->getExistenceCertainty(), 0.1f);
66  float fusedExistenceCertainty =
67  (oldExistenceCertainty * newExistenceCertainty) /
68  ((oldExistenceCertainty * newExistenceCertainty) +
69  (1 - oldExistenceCertainty) * (1 - newExistenceCertainty));
70  fusedInstance->setExistenceCertainty(fusedExistenceCertainty);
71 
72 
73  // update position and orientation
74 
75  // setup filter
76  NoMotionFilter filter;
77  Eigen::MatrixXd i(3, 3);
78  i.setIdentity();
79 
80  MultivariateNormalDistributionBasePtr newUncertainty =
81  newInstance->getPositionUncertainty();
82  MultivariateNormalDistributionBasePtr oldUncertainty =
83  oldInstance->getPositionUncertainty();
84 
85  if (!newUncertainty)
86  {
87  ARMARX_ERROR_S << "new instance's position uncertainty is zero! - instance name: "
88  << newInstance->getName();
89  return newInstance->clone();
90  }
91 
92  if (!oldUncertainty)
93  {
94  ARMARX_ERROR_S << "old instance's position uncertainty is zero! - instance name: "
95  << oldInstance->getName();
96  return newInstance->clone();
97  }
98 
99  Gaussian measurement = EarlyVisionConverters::convertToGaussian(newUncertainty);
100  filter.setMeasurementModel(i, measurement);
101  Gaussian believe = EarlyVisionConverters::convertToGaussian(oldUncertainty);
102  Gaussian posterior = filter.update(believe, measurement.getMean());
103 
104  // as the kalman filter position update canhave weird effects when the error is not actually coming from a normal distribution,
105  // we do a simple linear interpolation instead
106  const float meanRadiusOfMeasurementEllipsoid =
107  pow(measurement.getCovariance().determinant(), 0.5 / measurement.getDimensions());
108  const float meanRadiusOfOldBelieveEllipsoid =
109  pow(believe.getCovariance().determinant(), 0.5 / believe.getDimensions());
110  ARMARX_DEBUG_S << "Std dev of old believe: " << meanRadiusOfOldBelieveEllipsoid
111  << ", std dev of measurement: " << meanRadiusOfMeasurementEllipsoid;
112  const float interpolationFactor =
113  0.01f + 0.99f * meanRadiusOfOldBelieveEllipsoid /
114  (meanRadiusOfMeasurementEllipsoid + meanRadiusOfOldBelieveEllipsoid);
115  Eigen::Vector3f fusedPosition =
116  interpolationFactor * newInstance->getPosition()->toEigen() +
117  (1.0f - interpolationFactor) * oldPose->toEigen().block<3, 1>(0, 3);
119  new armarx::FramedPosition(fusedPosition, oldPose->frame, oldPose->agent);
120  fusedInstance->setPosition(pos);
121 
122  Eigen::Quaternionf measurementOrientation(newInstance->getOrientation()->qw,
123  newInstance->getOrientation()->qx,
124  newInstance->getOrientation()->qy,
125  newInstance->getOrientation()->qz);
126  Eigen::Quaternionf oldBelieveOrientation(oldPose->orientation->qw,
127  oldPose->orientation->qx,
128  oldPose->orientation->qy,
129  oldPose->orientation->qz);
130  Eigen::Quaternionf fusedOrientation =
131  oldBelieveOrientation.slerp(interpolationFactor, measurementOrientation);
132  fusedOrientation.normalize();
134  fusedOrientation.toRotationMatrix(), oldPose->frame, oldPose->agent);
135  fusedInstance->setOrientation(ori);
136 
137  // set position uncertainty of fused entity
138  fusedInstance->setPositionUncertainty(
140 
141  ARMARX_DEBUG_S << "Position after fusion: " << fusedInstance->getPosition()->output();
142  ARMARX_DEBUG_S << "Orientation after fusion: "
143  << fusedInstance->getOrientation()->output();
144  }
145  else
146  {
147  ARMARX_VERBOSE_S << "No old pose estimation available, using new measurement.";
148  fusedInstance = newInstance->clone();
149  }
150 
151  return fusedInstance;
152  }
153 
154 
155 } // namespace memoryx
Gaussian::getCovariance
const covariance_type & getCovariance() const
Definition: Gaussian.h:82
LinkedPose.h
memoryx::KalmanFilterFusion::initEntity
EntityBasePtr initEntity(const EntityBasePtr &updateEntity, const ::Ice::Current &=Ice::emptyCurrent) override
Definition: KalmanFilterFusion.cpp:20
memoryx::KalmanFilterFusion::KalmanFilterFusion
KalmanFilterFusion()
Creates a new KalmanFilterFusion.
Definition: KalmanFilterFusion.cpp:15
KalmanFilter::setMeasurementModel
void setMeasurementModel(const Eigen::MatrixXd &measurement_C, const Gaussian &measurement_noise)
Definition: KalmanFilter.cpp:34
memoryx
VirtualRobot headers.
Definition: CommonPlacesTester.cpp:48
memoryx::KalmanFilterFusion::fuseEntity
EntityBasePtr fuseEntity(const EntityBasePtr &oldEntity, const EntityBasePtr &newEntity, const ::Ice::Current &=Ice::emptyCurrent) override
Fusion method.
Definition: KalmanFilterFusion.cpp:26
Gaussian::getDimensions
int getDimensions() const
Definition: Gaussian.h:94
memoryx::EntityFusionMethod
Interface for fusion methods used for entities in working memory.
Definition: EntityFusionMethod.h:46
NoMotionFilter.h
IceInternal::Handle< ObjectInstance >
armarx::Quaternion::slerp
Eigen::Matrix3f slerp(float, const Eigen::Matrix3f &)
Definition: Pose.cpp:233
memoryx::EarlyVisionConverters::convertToGaussian
Gaussian convertToGaussian(const NormalDistributionBasePtr &normalDistribution)
Definition: EarlyVisionConverters.cpp:30
ARMARX_DEBUG_S
#define ARMARX_DEBUG_S
Definition: Logging.h:205
ARMARX_ERROR_S
#define ARMARX_ERROR_S
Definition: Logging.h:216
max
T max(T t1, T t2)
Definition: gdiam.h:51
ExpressionException.h
ARMARX_CHECK_EXPRESSION
#define ARMARX_CHECK_EXPRESSION(expression)
This macro evaluates the expression and if it turns out to be false it will throw an ExpressionExcept...
Definition: ExpressionException.h:73
AbstractMotionModel.h
armarx::VariantType::FramedOrientation
const VariantTypeId FramedOrientation
Definition: FramedPose.h:39
armarx::Quaternion< float, 0 >
EarlyVisionConverters.h
ARMARX_VERBOSE_S
#define ARMARX_VERBOSE_S
Definition: Logging.h:207
NoMotionFilter
Definition: NoMotionFilter.h:27
memoryx::EarlyVisionConverters::convertToMemoryX_MULTI
MultivariateNormalDistributionPtr convertToMemoryX_MULTI(const Gaussian &gaussian)
Definition: EarlyVisionConverters.cpp:61
Logging.h
Gaussian::getMean
const value_type & getMean() const
Definition: Gaussian.h:88
armarx::VariantType::FramedPosition
const VariantTypeId FramedPosition
Definition: FramedPose.h:38
Gaussian
Definition: Gaussian.h:50
KalmanFilterFusion.h
KalmanFilter::update
Gaussian update(const Gaussian &predicted_believe, const Eigen::VectorXd &perceptZ)
Definition: KalmanFilter.cpp:74