summaryrefslogtreecommitdiffhomepage
path: root/tracker-easy/kalman-filter-pose.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tracker-easy/kalman-filter-pose.cpp')
-rw-r--r--tracker-easy/kalman-filter-pose.cpp118
1 files changed, 118 insertions, 0 deletions
diff --git a/tracker-easy/kalman-filter-pose.cpp b/tracker-easy/kalman-filter-pose.cpp
new file mode 100644
index 00000000..42346bb5
--- /dev/null
+++ b/tracker-easy/kalman-filter-pose.cpp
@@ -0,0 +1,118 @@
+/* Copyright (c) 2019, Stephane Lenclud <github@lenclud.com>
+
+ * Permission to use, copy, modify, and/or distribute this
+ * software for any purpose with or without fee is hereby granted,
+ * provided that the above copyright notice and this permission
+ * notice appear in all copies.
+ */
+
+#include "kalman-filter-pose.h"
+
+namespace EasyTracker
+{
+
+ KalmanFilterPose::KalmanFilterPose()
+ {
+
+ }
+
+
+ void KalmanFilterPose::Init(int nStates, int nMeasurements, int nInputs, double dt)
+ {
+ iMeasurements = cv::Mat(nMeasurements, 1, CV_64FC1);
+
+ init(nStates, nMeasurements, nInputs, CV_64F); // init Kalman Filter
+
+ // TODO: Use parameters instead of magic numbers
+ setIdentity(processNoiseCov, cv::Scalar::all(1)); //1e-5 // set process noise
+ setIdentity(measurementNoiseCov, cv::Scalar::all(1)); //1e-2 // set measurement noise
+ setIdentity(errorCovPost, cv::Scalar::all(1)); // error covariance
+
+ /** DYNAMIC MODEL **/
+
+ // [1 0 0 dt 0 0 dt2 0 0 0 0 0 0 0 0 0 0 0]
+ // [0 1 0 0 dt 0 0 dt2 0 0 0 0 0 0 0 0 0 0]
+ // [0 0 1 0 0 dt 0 0 dt2 0 0 0 0 0 0 0 0 0]
+ // [0 0 0 1 0 0 dt 0 0 0 0 0 0 0 0 0 0 0]
+ // [0 0 0 0 1 0 0 dt 0 0 0 0 0 0 0 0 0 0]
+ // [0 0 0 0 0 1 0 0 dt 0 0 0 0 0 0 0 0 0]
+ // [0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0]
+ // [0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0]
+ // [0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0]
+ // [0 0 0 0 0 0 0 0 0 1 0 0 dt 0 0 dt2 0 0]
+ // [0 0 0 0 0 0 0 0 0 0 1 0 0 dt 0 0 dt2 0]
+ // [0 0 0 0 0 0 0 0 0 0 0 1 0 0 dt 0 0 dt2]
+ // [0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 dt 0 0]
+ // [0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 dt 0]
+ // [0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 dt]
+ // [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0]
+ // [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0]
+ // [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1]
+
+ // position
+ transitionMatrix.at<double>(0, 3) = dt;
+ transitionMatrix.at<double>(1, 4) = dt;
+ transitionMatrix.at<double>(2, 5) = dt;
+ transitionMatrix.at<double>(3, 6) = dt;
+ transitionMatrix.at<double>(4, 7) = dt;
+ transitionMatrix.at<double>(5, 8) = dt;
+ transitionMatrix.at<double>(0, 6) = 0.5*pow(dt, 2);
+ transitionMatrix.at<double>(1, 7) = 0.5*pow(dt, 2);
+ transitionMatrix.at<double>(2, 8) = 0.5*pow(dt, 2);
+
+ // orientation
+ transitionMatrix.at<double>(9, 12) = dt;
+ transitionMatrix.at<double>(10, 13) = dt;
+ transitionMatrix.at<double>(11, 14) = dt;
+ transitionMatrix.at<double>(12, 15) = dt;
+ transitionMatrix.at<double>(13, 16) = dt;
+ transitionMatrix.at<double>(14, 17) = dt;
+ transitionMatrix.at<double>(9, 15) = 0.5*pow(dt, 2);
+ transitionMatrix.at<double>(10, 16) = 0.5*pow(dt, 2);
+ transitionMatrix.at<double>(11, 17) = 0.5*pow(dt, 2);
+
+
+ /** MEASUREMENT MODEL **/
+
+ // [1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
+ // [0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
+ // [0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
+ // [0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0]
+ // [0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0]
+ // [0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0]
+
+ // Those will scale the filtered values, 2 will give you half the raw input
+ measurementMatrix.at<double>(0, 0) = 1; // x
+ measurementMatrix.at<double>(1, 1) = 1; // y
+ measurementMatrix.at<double>(2, 2) = 1; // z
+ measurementMatrix.at<double>(3, 9) = 1; // roll
+ measurementMatrix.at<double>(4, 10) = 1; // pitch
+ measurementMatrix.at<double>(5, 11) = 1; // yaw
+ }
+
+ void KalmanFilterPose::Update(double& aX, double& aY, double& aZ, double& aRoll, double& aPitch, double& aYaw)
+ {
+ // Set measurement to predict
+ iMeasurements.at<double>(0) = aX; // x
+ iMeasurements.at<double>(1) = aY; // y
+ iMeasurements.at<double>(2) = aZ; // z
+ iMeasurements.at<double>(3) = aRoll; // roll
+ iMeasurements.at<double>(4) = aPitch; // pitch
+ iMeasurements.at<double>(5) = aYaw; // yaw
+
+ // First predict, to update the internal statePre variable
+ cv::Mat prediction = predict();
+ // The "correct" phase that is going to use the predicted value and our measurement
+ cv::Mat estimated = correct(iMeasurements);
+ // Estimated translation
+ aX = estimated.at<double>(0);
+ aY = estimated.at<double>(1);
+ aZ = estimated.at<double>(2);
+ // Estimated euler angles
+ aRoll = estimated.at<double>(9);
+ aPitch = estimated.at<double>(10);
+ aYaw = estimated.at<double>(11);
+ }
+
+}
+