Kalman2DPositionFilter.cs 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. using Emgu.CV;
  2. using Emgu.CV.Structure;
  3. namespace bbiwarg.Utility
  4. {
  5. /// <summary>
  6. /// Filter used to smooth a series of 2d positions.
  7. /// </summary>
  8. internal class Kalman2DPositionFilter
  9. {
  10. /// <summary>
  11. /// number of measurements per second
  12. /// </summary>
  13. private float fps;
  14. /// <summary>
  15. /// the emgu kalman filter
  16. /// </summary>
  17. private Kalman kalman;
  18. /// <summary>
  19. /// xx entry for the measurement noise covariance matrix
  20. /// </summary>
  21. private float mXX;
  22. /// <summary>
  23. /// xy and yx entry for the measurement noise covariance matrix
  24. /// </summary>
  25. private float mXY;
  26. /// <summary>
  27. /// yy entry for the measurement noise covariance matrix
  28. /// </summary>
  29. private float mYY;
  30. /// <summary>
  31. /// value used for all entries in the process noise covariance matrix
  32. /// </summary>
  33. private float processNoiseFactor;
  34. /// <summary>
  35. /// true iff the kalman filter is initialized
  36. /// </summary>
  37. public bool Initialized { get; private set; }
  38. // state: x, y, v_x, v_y
  39. // x: current x position
  40. // y: current y position
  41. // v_x: velocity in x direction
  42. // v_y: velocity in y direction
  43. // a_x: acceleration in x direction
  44. // a_y: acceleration in y direction
  45. /// <summary>
  46. /// Creates a Kalman2DPositionFilter.
  47. /// </summary>
  48. /// <param name="mXX">xx entry for the measurement noise covariance matrix</param>
  49. /// <param name="mXY">xy and yx entry for the measurement noise covariance matrix</param>
  50. /// <param name="mYY">yy entry for the measurement noise covariance matrix</param>
  51. /// <param name="processNoiseFactor">value used for all entries in the process noise covariance matrix</param>
  52. /// <param name="fps">number of measurements per second</param>
  53. public Kalman2DPositionFilter(float mXX, float mXY, float mYY, float processNoiseFactor = 1.0e-4f, int fps = 30)
  54. {
  55. this.mXX = mXX;
  56. this.mXY = mXY;
  57. this.mYY = mYY;
  58. this.processNoiseFactor = processNoiseFactor;
  59. this.fps = fps;
  60. reset();
  61. }
  62. /// <summary>
  63. /// Computes a smoothed position for a measurement and updates the filter.
  64. /// </summary>
  65. /// <param name="rawPosition">the measurement</param>
  66. /// <returns>the smoothed position</returns>
  67. public Vector2D getCorrectedPosition(Vector2D rawPosition)
  68. {
  69. Matrix<float> rawPositionMatrix = new Matrix<float>(new float[,]
  70. { {rawPosition.X},
  71. {rawPosition.Y}});
  72. // prediction according to model
  73. kalman.Predict();
  74. // corrected point
  75. Matrix<float> estimate = kalman.Correct(rawPositionMatrix);
  76. return new Vector2D(estimate[0, 0], estimate[1, 0]);
  77. }
  78. /// <summary>
  79. /// Computes a prediction for the next position based on the previous positions.
  80. /// </summary>
  81. /// <returns>prediction for the next position</returns>
  82. public Vector2D getPrediction()
  83. {
  84. Matrix<float> predicton = kalman.Predict();
  85. return new Vector2D(predicton[0, 0], predicton[1, 0]);
  86. }
  87. /// <summary>
  88. /// Resets the kalman filter.
  89. /// </summary>
  90. public void reset()
  91. {
  92. // 6 state variables and 2 measurements (0 controls)
  93. kalman = new Kalman(2, 2, 0);
  94. // time step (s)
  95. float t = 1 / fps;
  96. // transition matrix
  97. Matrix<float> transitionMatrix = new Matrix<float>(new float[,]
  98. { {1.0f, 0.0f},
  99. {0.0f, 1.0f}});
  100. kalman.TransitionMatrix = transitionMatrix;
  101. // measurement matrix
  102. Matrix<float> measurementMatrix = new Matrix<float>(new float[,]
  103. { {1.0f, 0.0f}, // first measurement = x
  104. {0.0f, 1.0f} // second measurement = y
  105. });
  106. kalman.MeasurementMatrix = measurementMatrix;
  107. // measurement noise covariance matrix
  108. Matrix<float> measurementNoiseCovarianceMatrix = new Matrix<float>(2, 2);
  109. measurementNoiseCovarianceMatrix[0, 0] = mXX;
  110. measurementNoiseCovarianceMatrix[0, 1] = measurementNoiseCovarianceMatrix[1, 0] = mXY;
  111. measurementNoiseCovarianceMatrix[1, 1] = mYY;
  112. kalman.MeasurementNoiseCovariance = measurementNoiseCovarianceMatrix;
  113. // process noise covariance matrix
  114. Matrix<float> processNoiseCovarianceMatrix = new Matrix<float>(2, 2);
  115. processNoiseCovarianceMatrix.SetIdentity(new MCvScalar(processNoiseFactor));
  116. kalman.ProcessNoiseCovariance = processNoiseCovarianceMatrix;
  117. // error covariance post matrix (initial value)
  118. Matrix<float> errorCovariancePostMatrix = new Matrix<float>(2, 2);
  119. errorCovariancePostMatrix.SetIdentity(new MCvScalar(processNoiseFactor));
  120. kalman.ErrorCovariancePost = errorCovariancePostMatrix;
  121. Initialized = false;
  122. }
  123. /// <summary>
  124. /// Sets the initial position.
  125. /// </summary>
  126. /// <param name="initialPosition">initial position</param>
  127. public void setInitialPosition(Vector2D initialPosition)
  128. {
  129. // initial state (x, y, v_x, v_y)
  130. Matrix<float> initialState = new Matrix<float>(new float[] { initialPosition.X, initialPosition.Y });
  131. kalman.CorrectedState = initialState;
  132. Initialized = true;
  133. }
  134. }
  135. }