KalmanFilterFusion.cpp
Go to the documentation of this file.
1 #include "KalmanFilterFusion.h"
2 
6 
9 
11 
14 
15 
16 namespace memoryx
17 {
18 
20  EntityFusionMethod("KalmanFilterFusion")
21  {
22  }
23 
24  EntityBasePtr KalmanFilterFusion::initEntity(const EntityBasePtr& updateEntity, const Ice::Current&)
25  {
26  return updateEntity;
27  }
28 
29  EntityBasePtr KalmanFilterFusion::fuseEntity(const EntityBasePtr& oldEntity, const EntityBasePtr& newEntity, const Ice::Current&)
30  {
31  ARMARX_DEBUG_S << "KalmanFilterFusion::fuseEntity() called";
32 
33  ObjectInstancePtr oldInstance = ObjectInstancePtr::dynamicCast(oldEntity);
34  ObjectInstancePtr newInstance = ObjectInstancePtr::dynamicCast(newEntity);
35  ObjectInstancePtr fusedInstance;
36 
37  ARMARX_CHECK_EXPRESSION(oldInstance);
38  ARMARX_CHECK_EXPRESSION(newInstance);
39 
40  if (!oldInstance->getMotionModel())
41  {
42  return newInstance;
43  }
44 
45  armarx::LinkedPoseBasePtr oldPoseBase = oldInstance->getMotionModel()->getPredictedPoseAtStartOfCurrentLocalization();
46 
47  if (oldPoseBase)
48  {
49  armarx::LinkedPosePtr oldPose = armarx::LinkedPosePtr::dynamicCast(oldPoseBase->clone());
50  ARMARX_CHECK_EXPRESSION(oldPose);
51  ARMARX_DEBUG_S << "Pose before fusion " << oldPose->output();
52  ARMARX_DEBUG_S << "Pose of update " << newInstance->getPose()->output();
53 
54  oldPose->changeFrame(newInstance->getPosition()->frame);
55 
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 = (oldExistenceCertainty * newExistenceCertainty) / ((oldExistenceCertainty * newExistenceCertainty) + (1 - oldExistenceCertainty) * (1 - newExistenceCertainty));
67  fusedInstance->setExistenceCertainty(fusedExistenceCertainty);
68 
69 
70  // update position and orientation
71 
72  // setup filter
73  NoMotionFilter filter;
74  Eigen::MatrixXd i(3, 3);
75  i.setIdentity();
76 
77  MultivariateNormalDistributionBasePtr newUncertainty = newInstance->getPositionUncertainty();
78  MultivariateNormalDistributionBasePtr oldUncertainty = oldInstance->getPositionUncertainty();
79 
80  if (!newUncertainty)
81  {
82  ARMARX_ERROR_S << "new instance's position uncertainty is zero! - instance name: " << newInstance->getName();
83  return newInstance->clone();
84  }
85 
86  if (!oldUncertainty)
87  {
88  ARMARX_ERROR_S << "old instance's position uncertainty is zero! - instance name: " << oldInstance->getName();
89  return newInstance->clone();
90  }
91 
92  Gaussian measurement = EarlyVisionConverters::convertToGaussian(newUncertainty);
93  filter.setMeasurementModel(i, measurement);
94  Gaussian believe = EarlyVisionConverters::convertToGaussian(oldUncertainty);
95  Gaussian posterior = filter.update(believe, measurement.getMean());
96 
97  // as the kalman filter position update canhave weird effects when the error is not actually coming from a normal distribution,
98  // we do a simple linear interpolation instead
99  const float meanRadiusOfMeasurementEllipsoid = pow(measurement.getCovariance().determinant(), 0.5 / measurement.getDimensions());
100  const float meanRadiusOfOldBelieveEllipsoid = pow(believe.getCovariance().determinant(), 0.5 / believe.getDimensions());
101  ARMARX_DEBUG_S << "Std dev of old believe: " << meanRadiusOfOldBelieveEllipsoid << ", std dev of measurement: " << meanRadiusOfMeasurementEllipsoid;
102  const float interpolationFactor = 0.01f + 0.99f * meanRadiusOfOldBelieveEllipsoid / (meanRadiusOfMeasurementEllipsoid + meanRadiusOfOldBelieveEllipsoid);
103  Eigen::Vector3f fusedPosition = interpolationFactor * newInstance->getPosition()->toEigen() + (1.0f - interpolationFactor) * oldPose->toEigen().block<3, 1>(0, 3);
104  armarx::FramedPositionPtr pos = new armarx::FramedPosition(fusedPosition, oldPose->frame, oldPose->agent);
105  fusedInstance->setPosition(pos);
106 
107  Eigen::Quaternionf measurementOrientation(newInstance->getOrientation()->qw, newInstance->getOrientation()->qx, newInstance->getOrientation()->qy, newInstance->getOrientation()->qz);
108  Eigen::Quaternionf oldBelieveOrientation(oldPose->orientation->qw, oldPose->orientation->qx, oldPose->orientation->qy, oldPose->orientation->qz);
109  Eigen::Quaternionf fusedOrientation = oldBelieveOrientation.slerp(interpolationFactor, measurementOrientation);
110  fusedOrientation.normalize();
111  armarx::FramedOrientationPtr ori = new armarx::FramedOrientation(fusedOrientation.toRotationMatrix(), oldPose->frame, oldPose->agent);
112  fusedInstance->setOrientation(ori);
113 
114  // set position uncertainty of fused entity
115  fusedInstance->setPositionUncertainty(EarlyVisionConverters::convertToMemoryX_MULTI(posterior));
116 
117  ARMARX_DEBUG_S << "Position after fusion: " << fusedInstance->getPosition()->output();
118  ARMARX_DEBUG_S << "Orientation after fusion: " << fusedInstance->getOrientation()->output();
119  }
120  else
121  {
122  ARMARX_VERBOSE_S << "No old pose estimation available, using new measurement.";
123  fusedInstance = newInstance->clone();
124  }
125 
126  return fusedInstance;
127  }
128 
129 
130 }
131 
Gaussian::getCovariance
const covariance_type & getCovariance() const
Definition: Gaussian.h:77
LinkedPose.h
memoryx::KalmanFilterFusion::initEntity
EntityBasePtr initEntity(const EntityBasePtr &updateEntity, const ::Ice::Current &=Ice::emptyCurrent) override
Definition: KalmanFilterFusion.cpp:24
memoryx::KalmanFilterFusion::KalmanFilterFusion
KalmanFilterFusion()
Creates a new KalmanFilterFusion.
Definition: KalmanFilterFusion.cpp:19
KalmanFilter::setMeasurementModel
void setMeasurementModel(const Eigen::MatrixXd &measurement_C, const Gaussian &measurement_noise)
Definition: KalmanFilter.cpp:29
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:29
Gaussian::getDimensions
int getDimensions() const
Definition: Gaussian.h:85
memoryx::EntityFusionMethod
Interface for fusion methods used for entities in working memory.
Definition: EntityFusionMethod.h:43
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:29
ARMARX_DEBUG_S
#define ARMARX_DEBUG_S
Definition: Logging.h:198
ARMARX_ERROR_S
#define ARMARX_ERROR_S
Definition: Logging.h:209
max
T max(T t1, T t2)
Definition: gdiam.h:48
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:40
armarx::Quaternion< float, 0 >
EarlyVisionConverters.h
ARMARX_VERBOSE_S
#define ARMARX_VERBOSE_S
Definition: Logging.h:200
NoMotionFilter
Definition: NoMotionFilter.h:27
memoryx::EarlyVisionConverters::convertToMemoryX_MULTI
MultivariateNormalDistributionPtr convertToMemoryX_MULTI(const Gaussian &gaussian)
Definition: EarlyVisionConverters.cpp:59
Logging.h
Gaussian::getMean
const value_type & getMean() const
Definition: Gaussian.h:81
armarx::VariantType::FramedPosition
const VariantTypeId FramedPosition
Definition: FramedPose.h:39
Gaussian
Definition: Gaussian.h:46
KalmanFilterFusion.h
KalmanFilter::update
Gaussian update(const Gaussian &predicted_believe, const Eigen::VectorXd &perceptZ)
Definition: KalmanFilter.cpp:63