sensor_fusion_ekf.h 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. /*
  2. * Copyright 2019 Google Inc. All Rights Reserved.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #ifndef CARDBOARD_SDK_SENSORS_SENSOR_FUSION_EKF_H_
  17. #define CARDBOARD_SDK_SENSORS_SENSOR_FUSION_EKF_H_
  18. #include <array>
  19. #include <atomic>
  20. #include <cstdint>
  21. #include "accelerometer_data.h"
  22. #include "gyroscope_bias_estimator.h"
  23. #include "gyroscope_data.h"
  24. #include "pose_state.h"
  25. #include "../util/matrix_3x3.h"
  26. #include "../util/rotation.h"
  27. #include "../util/vector.h"
  28. namespace cardboard {
  29. // Sensor fusion class that implements an Extended Kalman Filter (EKF) to
  30. // estimate a 3D rotation from a gyroscope and an accelerometer.
  31. // This system only has one state, the pose. It does not estimate any velocity
  32. // or acceleration.
  33. //
  34. // To learn more about Kalman filtering one can read this article which is a
  35. // good introduction: https://en.wikipedia.org/wiki/Kalman_filter
  36. class SensorFusionEkf {
  37. public:
  38. SensorFusionEkf();
  39. // Resets the state of the sensor fusion. It sets the velocity for
  40. // prediction to zero. The reset will happen with the next
  41. // accelerometer sample. Gyroscope sample will be discarded until a new
  42. // accelerometer sample arrives.
  43. void Reset();
  44. // Gets the PoseState representing the latest pose and derivatives at a
  45. // particular timestamp as estimated by SensorFusion.
  46. PoseState GetLatestPoseState() const;
  47. // Processes one gyroscope sample event. This updates the pose of the system
  48. // and the prediction model. The gyroscope data is assumed to be in axis angle
  49. // form. Angle = ||v|| and Axis = v / ||v||, with v = [v_x, v_y, v_z]^T.
  50. //
  51. // @param sample gyroscope sample data.
  52. void ProcessGyroscopeSample(const GyroscopeData& sample);
  53. // Processes one accelerometer sample event. This updates the pose of the
  54. // system. If the Accelerometer norm changes too much between sample it is not
  55. // trusted as much.
  56. //
  57. // @param sample accelerometer sample data.
  58. void ProcessAccelerometerSample(const AccelerometerData& sample);
  59. // Enables or disables the drift correction by estimating the gyroscope bias.
  60. //
  61. // @param enable Enable drift correction.
  62. void SetBiasEstimationEnabled(bool enable);
  63. // Returns a boolean that indicates if bias estimation is enabled or disabled.
  64. //
  65. // @return true if bias estimation is enabled, false otherwise.
  66. bool IsBiasEstimationEnabled() const;
  67. // Returns the current gyroscope bias estimate from GyroscopeBiasEstimator.
  68. Vector3 GetGyroscopeBias() const {
  69. return {
  70. gyroscope_bias_estimate_[0], gyroscope_bias_estimate_[1], gyroscope_bias_estimate_[2]};
  71. }
  72. // Returns true after receiving the first accelerometer measurement.
  73. bool IsFullyInitialized() const {
  74. return is_aligned_with_gravity_;
  75. }
  76. private:
  77. // Estimates the average timestep between gyroscope event.
  78. void FilterGyroscopeTimestep(double gyroscope_timestep);
  79. // Updates the state covariance with an incremental motion. It changes the
  80. // space of the quadric.
  81. void UpdateStateCovariance(const Matrix3x3& motion_update);
  82. // Computes the innovation vector of the Kalman based on the input pose.
  83. // It uses the latest measurement vector (i.e. accelerometer data), which must
  84. // be set prior to calling this function.
  85. Vector3 ComputeInnovation(const Rotation& pose);
  86. // This computes the measurement_jacobian_ via numerical differentiation based
  87. // on the current value of sensor_from_start_rotation_.
  88. void ComputeMeasurementJacobian();
  89. // Updates the accelerometer covariance matrix.
  90. //
  91. // This looks at the norm of recent accelerometer readings. If it has changed
  92. // significantly, it means the phone receives additional acceleration than
  93. // just gravity, and so the down vector information gravity signal is noisier.
  94. void UpdateMeasurementCovariance();
  95. // Reset all internal states. This is not thread safe. Lock should be acquired
  96. // outside of it. This function is called in ProcessAccelerometerSample.
  97. void ResetState();
  98. // Current transformation from Sensor Space to Start Space.
  99. // x_sensor = sensor_from_start_rotation_ * x_start;
  100. PoseState current_state_;
  101. // Filtering of the gyroscope timestep started?
  102. bool is_timestep_filter_initialized_;
  103. // Filtered gyroscope timestep valid?
  104. bool is_gyroscope_filter_valid_;
  105. // Sensor fusion currently aligned with gravity? After initialization
  106. // it will requires a couple of accelerometer data for the system to get
  107. // aligned.
  108. std::atomic<bool> is_aligned_with_gravity_;
  109. // Covariance of Kalman filter state (P in common formulation).
  110. Matrix3x3 state_covariance_;
  111. // Covariance of the process noise (Q in common formulation).
  112. Matrix3x3 process_covariance_;
  113. // Covariance of the accelerometer measurement (R in common formulation).
  114. Matrix3x3 accelerometer_measurement_covariance_;
  115. // Covariance of innovation (S in common formulation).
  116. Matrix3x3 innovation_covariance_;
  117. // Jacobian of the measurements (H in common formulation).
  118. Matrix3x3 accelerometer_measurement_jacobian_;
  119. // Gain of the Kalman filter (K in common formulation).
  120. Matrix3x3 kalman_gain_;
  121. // Parameter update a.k.a. innovation vector. (\nu in common formulation).
  122. Vector3 innovation_;
  123. // Measurement vector (z in common formulation).
  124. Vector3 accelerometer_measurement_;
  125. // Current prediction vector (g in common formulation).
  126. Vector3 prediction_;
  127. // Control input, currently this is only the gyroscope data (\mu in common
  128. // formulation).
  129. Vector3 control_input_;
  130. // Update of the state vector. (x in common formulation).
  131. Vector3 state_update_;
  132. // Sensor time of the last gyroscope processed event.
  133. uint64_t current_gyroscope_sensor_timestamp_ns_;
  134. // Sensor time of the last accelerometer processed event.
  135. uint64_t current_accelerometer_sensor_timestamp_ns_;
  136. // Estimates of the timestep between gyroscope event in seconds.
  137. double filtered_gyroscope_timestep_s_;
  138. // Number of timestep samples processed so far by the filter.
  139. uint32_t num_gyroscope_timestep_samples_;
  140. // Norm of the accelerometer for the previous measurement.
  141. double previous_accelerometer_norm_;
  142. // Moving average of the accelerometer norm changes. It is computed for every
  143. // sensor datum.
  144. double moving_average_accelerometer_norm_change_;
  145. // Flag indicating if a state reset should be executed with the next
  146. // accelerometer sample.
  147. std::atomic<bool> execute_reset_with_next_accelerometer_sample_;
  148. // Flag indicating if bias estimation is enabled (enabled by default).
  149. std::atomic<bool> bias_estimation_enabled_;
  150. // Bias estimator and static device detector.
  151. GyroscopeBiasEstimator gyroscope_bias_estimator_;
  152. // Current bias estimate_;
  153. Vector3 gyroscope_bias_estimate_;
  154. SensorFusionEkf(const SensorFusionEkf&) = delete;
  155. SensorFusionEkf& operator=(const SensorFusionEkf&) = delete;
  156. };
  157. } // namespace cardboard
  158. #endif // CARDBOARD_SDK_SENSORS_SENSOR_FUSION_EKF_H_