AccelCalibrator.h 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. /*
  2. This program is free software: you can redistribute it and/or modify
  3. it under the terms of the GNU General Public License as published by
  4. the Free Software Foundation, either version 3 of the License, or
  5. (at your option) any later version.
  6. This program is distributed in the hope that it will be useful,
  7. but WITHOUT ANY WARRANTY; without even the implied warranty of
  8. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  9. GNU General Public License for more details.
  10. You should have received a copy of the GNU General Public License
  11. along with this program. If not, see <http://www.gnu.org/licenses/>.
  12. */
  13. #pragma once
  14. #include <AP_Math/AP_Math.h>
  15. #include <AP_Math/vectorN.h>
  16. #define ACCEL_CAL_MAX_NUM_PARAMS 9
  17. #define ACCEL_CAL_TOLERANCE 0.1
  18. #define MAX_ITERATIONS 50
  19. enum accel_cal_status_t {
  20. ACCEL_CAL_NOT_STARTED=0,
  21. ACCEL_CAL_WAITING_FOR_ORIENTATION=1,
  22. ACCEL_CAL_COLLECTING_SAMPLE=2,
  23. ACCEL_CAL_SUCCESS=3,
  24. ACCEL_CAL_FAILED=4
  25. };
  26. enum accel_cal_fit_type_t {
  27. ACCEL_CAL_AXIS_ALIGNED_ELLIPSOID=0,
  28. ACCEL_CAL_ELLIPSOID=1
  29. };
  30. class AccelCalibrator {
  31. public:
  32. AccelCalibrator();
  33. //Select options, initialise variables and initiate accel calibration
  34. void start(enum accel_cal_fit_type_t fit_type = ACCEL_CAL_AXIS_ALIGNED_ELLIPSOID, uint8_t num_samples = 6, float sample_time = 0.5f);
  35. void start(enum accel_cal_fit_type_t fit_type, uint8_t num_samples, float sample_time, Vector3f offset, Vector3f diag, Vector3f offdiag);
  36. // set Accel calibrator status to make itself ready for future accel cals
  37. void clear();
  38. // returns true if accel calibrator is running
  39. bool running();
  40. // set Accel calibrator to start collecting samples in the next cycle
  41. void collect_sample();
  42. // check if client's calibrator is active
  43. void check_for_timeout();
  44. // get diag,offset or offdiag parameters as per the selected fitting surface or request
  45. void get_calibration(Vector3f& offset) const;
  46. void get_calibration(Vector3f& offset, Vector3f& diag) const;
  47. void get_calibration(Vector3f& offset, Vector3f& diag, Vector3f& offdiag) const;
  48. // collect and avg sample to be passed onto LSQ estimator after all requisite orientations are done
  49. void new_sample(const Vector3f& delta_velocity, float dt);
  50. // interface for LSq estimator to read sample buffer sent after conversion from delta velocity
  51. // to averaged acc over time
  52. bool get_sample(uint8_t i, Vector3f& s) const;
  53. // returns truen and sample corrected with diag offdiag parameters as calculated by LSq estimation procedure
  54. // returns false if no correct parameter exists to be applied along with existing sample without corrections
  55. bool get_sample_corrected(uint8_t i, Vector3f& s) const;
  56. // set tolerance bar for parameter fitness value to cross so as to be deemed as correct values
  57. void set_tolerance(float tolerance) { _conf_tolerance = tolerance; }
  58. // returns current state of accel calibrators
  59. enum accel_cal_status_t get_status() const { return _status; }
  60. // returns number of samples collected
  61. uint8_t get_num_samples_collected() const { return _samples_collected; }
  62. // returns mean squared fitness of sample points to the selected surface
  63. float get_fitness() const { return _fitness; }
  64. struct param_t {
  65. Vector3f offset;
  66. Vector3f diag;
  67. Vector3f offdiag;
  68. };
  69. private:
  70. struct AccelSample {
  71. Vector3f delta_velocity;
  72. float delta_time;
  73. };
  74. typedef VectorN<float, ACCEL_CAL_MAX_NUM_PARAMS> VectorP;
  75. union param_u {
  76. struct param_t s;
  77. VectorN<float, ACCEL_CAL_MAX_NUM_PARAMS> a;
  78. param_u() : a{}
  79. {
  80. static_assert(sizeof(*this) == sizeof(struct param_t),
  81. "Invalid union members: sizes do not match");
  82. }
  83. };
  84. //configuration
  85. uint8_t _conf_num_samples;
  86. float _conf_sample_time;
  87. enum accel_cal_fit_type_t _conf_fit_type;
  88. float _conf_tolerance;
  89. // state
  90. accel_cal_status_t _status;
  91. struct AccelSample* _sample_buffer;
  92. uint8_t _samples_collected;
  93. union param_u _param;
  94. float _fitness;
  95. uint32_t _last_samp_frag_collected_ms;
  96. float _min_sample_dist;
  97. // private methods
  98. // check sanity of including the sample and add it to buffer if test is passed
  99. bool accept_sample(const Vector3f& sample);
  100. // reset to calibrator state before the start of calibration
  101. void reset_state();
  102. // sets status of calibrator and takes appropriate actions
  103. void set_status(enum accel_cal_status_t);
  104. // determines if the result is acceptable
  105. bool accept_result() const;
  106. // returns number of parameters are required for selected Fit type
  107. uint8_t get_num_params() const;
  108. // Function related to Gauss Newton Least square regression process
  109. float calc_residual(const Vector3f& sample, const struct param_t& params) const;
  110. float calc_mean_squared_residuals() const;
  111. float calc_mean_squared_residuals(const struct param_t& params) const;
  112. void calc_jacob(const Vector3f& sample, const struct param_t& params, VectorP& ret) const;
  113. void run_fit(uint8_t max_iterations, float& fitness);
  114. };