calibration_data.cc 2.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  1. #include <furi.h>
  2. #include <furi_hal.h>
  3. #define TAG "tracker"
  4. #include "calibration_data.h"
  5. #include <cmath>
  6. #include <algorithm>
  7. // Student's distribution T value for 95% (two-sided) confidence interval.
  8. static const double Tn = 1.960;
  9. // Number of samples (degrees of freedom) for the corresponding T values.
  10. static const int Nn = 200;
  11. void CalibrationData::reset()
  12. {
  13. complete = false;
  14. count = 0;
  15. sum = Vector::Zero();
  16. sumSq = Vector::Zero();
  17. mean = Vector::Zero();
  18. median = Vector::Zero();
  19. sigma = Vector::Zero();
  20. delta = Vector::Zero();
  21. xData.clear();
  22. yData.clear();
  23. zData.clear();
  24. }
  25. bool CalibrationData::add(Vector& data)
  26. {
  27. if (complete) {
  28. return true;
  29. }
  30. xData.push_back(data[0]);
  31. yData.push_back(data[1]);
  32. zData.push_back(data[2]);
  33. sum += data;
  34. sumSq += data * data;
  35. count++;
  36. if (count >= Nn) {
  37. calcDelta();
  38. complete = true;
  39. }
  40. return complete;
  41. }
  42. static inline double medianOf(std::vector<double>& list)
  43. {
  44. std::sort(list.begin(), list.end());
  45. int count = list.size();
  46. int middle = count / 2;
  47. return (count % 2 == 1) ? list[middle] : (list[middle - 1] + list[middle]) / 2.0l;
  48. }
  49. void CalibrationData::calcDelta()
  50. {
  51. median.Set(medianOf(xData), medianOf(yData), medianOf(zData));
  52. mean = sum / count;
  53. Vector m2 = mean * mean;
  54. Vector d = sumSq / count - m2;
  55. Vector s2 = (d * count) / (count - 1);
  56. sigma = Vector(std::sqrt(d[0]), std::sqrt(d[1]), std::sqrt(d[2]));
  57. Vector s = Vector(std::sqrt(s2[0]), std::sqrt(s2[1]), std::sqrt(s2[2]));
  58. delta = s * Tn / std::sqrt((double)count);
  59. Vector low = mean - delta;
  60. Vector high = mean + delta;
  61. FURI_LOG_I(TAG,
  62. "M[x] = { %f ... %f } // median = %f // avg = %f // delta = %f // sigma = %f",
  63. low[0], high[0], median[0], mean[0], delta[0], sigma[0]);
  64. FURI_LOG_I(TAG,
  65. "M[y] = { %f ... %f } // median = %f // avg = %f // delta = %f // sigma = %f",
  66. low[1], high[1], median[1], mean[1], delta[1], sigma[1]);
  67. FURI_LOG_I(TAG,
  68. "M[z] = { %f ... %f } // median = %f // avg = %f // delta = %f // sigma = %f",
  69. low[2], high[2], median[2], mean[2], delta[2], sigma[2]);
  70. }