KalmanFilterFusion.cpp
Go to the documentation of this file.
2
5
7
11
12namespace memoryx
13{
14
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());
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
const covariance_type & getCovariance() const
Definition Gaussian.h:82
int getDimensions() const
Definition Gaussian.h:94
const value_type & getMean() const
Definition Gaussian.h:88
void setMeasurementModel(const Eigen::MatrixXd &measurement_C, const Gaussian &measurement_noise)
Gaussian update(const Gaussian &predicted_believe, const Eigen::VectorXd &perceptZ)
The FramedOrientation class.
Definition FramedPose.h:216
The FramedPosition class.
Definition FramedPose.h:158
Eigen::Matrix3f slerp(float, const Eigen::Matrix3f &)
Definition Pose.cpp:233
EntityFusionMethod(std::string methodName)
Constructs a new fusion method.
KalmanFilterFusion()
Creates a new KalmanFilterFusion.
EntityBasePtr fuseEntity(const EntityBasePtr &oldEntity, const EntityBasePtr &newEntity, const ::Ice::Current &=Ice::emptyCurrent) override
Fusion method.
EntityBasePtr initEntity(const EntityBasePtr &updateEntity, const ::Ice::Current &=Ice::emptyCurrent) override
#define ARMARX_CHECK_EXPRESSION(expression)
This macro evaluates the expression and if it turns out to be false it will throw an ExpressionExcept...
#define ARMARX_DEBUG_S
The logging level for output that is only interesting while debugging.
Definition Logging.h:205
#define ARMARX_ERROR_S
The logging level for unexpected behaviour, that must be fixed.
Definition Logging.h:216
#define ARMARX_VERBOSE_S
Definition Logging.h:207
Quaternion< float, 0 > Quaternionf
IceInternal::Handle< LinkedPose > LinkedPosePtr
Definition LinkedPose.h:52
IceInternal::Handle< FramedPosition > FramedPositionPtr
Definition FramedPose.h:149
IceInternal::Handle< FramedOrientation > FramedOrientationPtr
Definition FramedPose.h:207
Gaussian convertToGaussian(const NormalDistributionBasePtr &normalDistribution)
MultivariateNormalDistributionPtr convertToMemoryX_MULTI(const Gaussian &gaussian)
VirtualRobot headers.
IceInternal::Handle< ObjectInstance > ObjectInstancePtr