summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Jacobs <davejacobs@google.com>2018-04-17 16:55:46 -0400
committerDavid Jacobs <davejacobs@google.com>2018-05-02 06:16:58 +0000
commitce2dd9290fce64fad2ad6cf8a8342de40e6cbcaa (patch)
treec8037e3620298f6ea23a6ba7969e3be71032e8b2
parentb4766557d14eef22527ca54417a158a2cccb7648 (diff)
downloadcontexthub-ce2dd9290fce64fad2ad6cf8a8342de40e6cbcaa.tar.gz
[IMU_Cal] Runtime sensor calibration code update.
This code updates all of the refactored changes developed and tested in Google3. This update includes setting calibration accuracy level. Tip of G3 CL: 195047378 Bug: 75333210 (refactor updates) Bug: 75335561 (calibration accuracy) Test: ./load_app.sh and verified calibrations on device. Change-Id: I48bd61b6610a7cc7ce9a88bfdde51552c509d763
-rw-r--r--firmware/os/algos/calibration/accelerometer/accel_cal.c385
-rw-r--r--firmware/os/algos/calibration/gyroscope/gyro_cal.c77
-rw-r--r--firmware/os/algos/calibration/gyroscope/gyro_stillness_detect.c1
-rw-r--r--firmware/os/algos/calibration/magnetometer/mag_cal/mag_cal.c (renamed from firmware/os/algos/calibration/magnetometer/mag_cal.c)127
-rw-r--r--firmware/os/algos/calibration/magnetometer/mag_cal/mag_cal.h (renamed from firmware/os/algos/calibration/magnetometer/mag_cal.h)29
-rw-r--r--firmware/os/algos/calibration/magnetometer/mag_sphere_fit_cal/mag_sphere_fit.c (renamed from firmware/os/algos/calibration/magnetometer/mag_sphere_fit.c)4
-rw-r--r--firmware/os/algos/calibration/magnetometer/mag_sphere_fit_cal/mag_sphere_fit.h (renamed from firmware/os/algos/calibration/magnetometer/mag_sphere_fit.h)8
-rw-r--r--firmware/os/algos/calibration/nano_calibration/aosp_nano_cal_parameters.h2
-rw-r--r--firmware/os/algos/calibration/nano_calibration/nano_calibration.cc177
-rw-r--r--firmware/os/algos/calibration/nano_calibration/nano_calibration.h12
-rw-r--r--firmware/os/algos/calibration/online_calibration/accelerometer/accel_offset_cal/accel_offset_cal.cc22
-rw-r--r--firmware/os/algos/calibration/online_calibration/accelerometer/accel_offset_cal/accel_offset_cal.h27
-rw-r--r--firmware/os/algos/calibration/online_calibration/common_data/calibration_callback.h16
-rw-r--r--firmware/os/algos/calibration/online_calibration/common_data/calibration_data.cc16
-rw-r--r--firmware/os/algos/calibration/online_calibration/common_data/calibration_data.h52
-rw-r--r--firmware/os/algos/calibration/online_calibration/common_data/calibration_quality.h96
-rw-r--r--firmware/os/algos/calibration/online_calibration/common_data/online_calibration.h16
-rw-r--r--firmware/os/algos/calibration/online_calibration/common_data/sensor_data.h16
-rw-r--r--firmware/os/algos/calibration/online_calibration/gyroscope/gyro_offset_over_temp_cal/gyro_offset_over_temp_cal.cc30
-rw-r--r--firmware/os/algos/calibration/online_calibration/gyroscope/gyro_offset_over_temp_cal/gyro_offset_over_temp_cal.h29
-rw-r--r--firmware/os/algos/calibration/online_calibration/magnetometer/mag_diverse_cal/mag_diverse_cal.cc26
-rw-r--r--firmware/os/algos/calibration/online_calibration/magnetometer/mag_diverse_cal/mag_diverse_cal.h31
-rw-r--r--firmware/os/algos/calibration/over_temp/over_temp_cal.c96
-rw-r--r--firmware/os/algos/calibration/over_temp/over_temp_model.h16
-rw-r--r--firmware/os/algos/calibration/sample_rate_estimator/sample_rate_estimator.c4
-rw-r--r--firmware/os/algos/calibration/sphere_fit/calibration_data.c52
-rw-r--r--firmware/os/algos/calibration/sphere_fit/calibration_data.h73
-rw-r--r--firmware/os/algos/calibration/sphere_fit/sphere_fit_calibration.c264
-rw-r--r--firmware/os/algos/calibration/sphere_fit/sphere_fit_calibration.h144
-rw-r--r--firmware/os/algos/calibration/util/cal_log.h50
30 files changed, 1384 insertions, 514 deletions
diff --git a/firmware/os/algos/calibration/accelerometer/accel_cal.c b/firmware/os/algos/calibration/accelerometer/accel_cal.c
index 3c3160f5..99e96ef7 100644
--- a/firmware/os/algos/calibration/accelerometer/accel_cal.c
+++ b/firmware/os/algos/calibration/accelerometer/accel_cal.c
@@ -17,6 +17,7 @@
#include "calibration/accelerometer/accel_cal.h"
#include <errno.h>
+#include <inttypes.h>
#include <math.h>
#include <stdio.h>
#include <string.h>
@@ -458,12 +459,13 @@ void accelCalRun(struct AccelCal *acc, uint64_t sample_time_nanos, float x,
#ifdef IMU_TEMP_DBG_ENABLED
if ((sample_time_nanos - acc->temp_time_nanos) > IMU_TEMP_DELTA_TIME_NANOS) {
CAL_DEBUG_LOG("IMU Temp Data: ",
- ", %s%d.%02d, %llu, %s%d.%05d, %s%d.%05d, %s%d.%05d \n",
- CAL_ENCODE_FLOAT(temp, 2),
- (unsigned long long int)sample_time_nanos,
- CAL_ENCODE_FLOAT(acc->x_bias_new, 5),
- CAL_ENCODE_FLOAT(acc->y_bias_new, 5),
- CAL_ENCODE_FLOAT(acc->z_bias_new, 5));
+ ", " CAL_FORMAT_3DIGITS ", %" PRIu64
+ ", " CAL_FORMAT_6DIGITS_TRIPLET " \n",
+ CAL_ENCODE_FLOAT(temp, 3),
+ sample_time_nanos,
+ CAL_ENCODE_FLOAT(acc->x_bias_new, 6),
+ CAL_ENCODE_FLOAT(acc->y_bias_new, 6),
+ CAL_ENCODE_FLOAT(acc->z_bias_new, 6));
acc->temp_time_nanos = sample_time_nanos;
}
#endif
@@ -548,231 +550,216 @@ void accelCalRun(struct AccelCal *acc, uint64_t sample_time_nanos, float x,
}
#ifdef ACCEL_CAL_DBG_ENABLED
+
+// Local helper macro for printing log messages.
+#ifdef CAL_NO_FLOAT_FORMAT_STRINGS
+#define CAL_FORMAT_ACCEL_HISTORY \
+ "%s%d.%06d,%s%d.%06d,%s%d.%06d,%s%d.%06d,%s%d.%06d,%s%d.%06d,%s%d.%06d," \
+ "%s%d.%06d,%s%d.%06d,%s%d.%06d"
+#else
+#define CAL_FORMAT_ACCEL_HISTORY \
+ "%.6f,%.6f,%.6f,%.6f,%.6f,%.6f,%.6f,%.6f,%.6f,%.6f"
+#endif // CAL_NO_FLOAT_FORMAT_STRINGS
+
// Debug Print Output
void accelCalDebPrint(struct AccelCal *acc, float temp) {
static int32_t kk = 0;
if (++kk == 1000) {
// X offset history last 10 values.
- CAL_DEBUG_LOG(
- "[BMI160]",
- "{MK_ACCEL,11,%s%d.%06d,%s%d.%06d,%s%d.%06d,%s%d.%06d,%s%d.%06d,%s%d.%"
- "06d,%s%d.%06d,%s%d.%06d,%s%d.%06d,%s%d.%06d,}(x_off history)\n",
- CAL_ENCODE_FLOAT(acc->adf.x_o[0], 6),
- CAL_ENCODE_FLOAT(acc->adf.x_o[1], 6),
- CAL_ENCODE_FLOAT(acc->adf.x_o[2], 6),
- CAL_ENCODE_FLOAT(acc->adf.x_o[3], 6),
- CAL_ENCODE_FLOAT(acc->adf.x_o[4], 6),
- CAL_ENCODE_FLOAT(acc->adf.x_o[5], 6),
- CAL_ENCODE_FLOAT(acc->adf.x_o[6], 6),
- CAL_ENCODE_FLOAT(acc->adf.x_o[7], 6),
- CAL_ENCODE_FLOAT(acc->adf.x_o[8], 6),
- CAL_ENCODE_FLOAT(acc->adf.x_o[9], 6));
+ CAL_DEBUG_LOG("[ACCEL_CAL]",
+ "{11," CAL_FORMAT_ACCEL_HISTORY "}(x_off history)\n",
+ CAL_ENCODE_FLOAT(acc->adf.x_o[0], 6),
+ CAL_ENCODE_FLOAT(acc->adf.x_o[1], 6),
+ CAL_ENCODE_FLOAT(acc->adf.x_o[2], 6),
+ CAL_ENCODE_FLOAT(acc->adf.x_o[3], 6),
+ CAL_ENCODE_FLOAT(acc->adf.x_o[4], 6),
+ CAL_ENCODE_FLOAT(acc->adf.x_o[5], 6),
+ CAL_ENCODE_FLOAT(acc->adf.x_o[6], 6),
+ CAL_ENCODE_FLOAT(acc->adf.x_o[7], 6),
+ CAL_ENCODE_FLOAT(acc->adf.x_o[8], 6),
+ CAL_ENCODE_FLOAT(acc->adf.x_o[9], 6));
// Y offset history last 10 values.
- CAL_DEBUG_LOG(
- "[BMI160]",
- "{MK_ACCEL,12,%s%d.%06d,%s%d.%06d,%s%d.%06d,%s%d.%06d,%s%d.%06d,%s%d.%"
- "06d,%s%d.%06d,%s%d.%06d,%s%d.%06d,%s%d.%06d,}(y_off history)\n",
- CAL_ENCODE_FLOAT(acc->adf.y_o[0], 6),
- CAL_ENCODE_FLOAT(acc->adf.y_o[1], 6),
- CAL_ENCODE_FLOAT(acc->adf.y_o[2], 6),
- CAL_ENCODE_FLOAT(acc->adf.y_o[3], 6),
- CAL_ENCODE_FLOAT(acc->adf.y_o[4], 6),
- CAL_ENCODE_FLOAT(acc->adf.y_o[5], 6),
- CAL_ENCODE_FLOAT(acc->adf.y_o[6], 6),
- CAL_ENCODE_FLOAT(acc->adf.y_o[7], 6),
- CAL_ENCODE_FLOAT(acc->adf.y_o[8], 6),
- CAL_ENCODE_FLOAT(acc->adf.y_o[9], 6));
+ CAL_DEBUG_LOG("[ACCEL_CAL]",
+ "{12," CAL_FORMAT_ACCEL_HISTORY "}(y_off history)\n",
+ CAL_ENCODE_FLOAT(acc->adf.y_o[0], 6),
+ CAL_ENCODE_FLOAT(acc->adf.y_o[1], 6),
+ CAL_ENCODE_FLOAT(acc->adf.y_o[2], 6),
+ CAL_ENCODE_FLOAT(acc->adf.y_o[3], 6),
+ CAL_ENCODE_FLOAT(acc->adf.y_o[4], 6),
+ CAL_ENCODE_FLOAT(acc->adf.y_o[5], 6),
+ CAL_ENCODE_FLOAT(acc->adf.y_o[6], 6),
+ CAL_ENCODE_FLOAT(acc->adf.y_o[7], 6),
+ CAL_ENCODE_FLOAT(acc->adf.y_o[8], 6),
+ CAL_ENCODE_FLOAT(acc->adf.y_o[9], 6));
// Z offset history last 10 values.
- CAL_DEBUG_LOG(
- "[BMI160]",
- "{MK_ACCEL,13,%s%d.%06d,%s%d.%06d,%s%d.%06d,%s%d.%06d,%s%d.%06d,%s%d.%"
- "06d,%s%d.%06d,%s%d.%06d,%s%d.%06d,%s%d.%06d,}(z_off history)\n",
- CAL_ENCODE_FLOAT(acc->adf.z_o[0], 6),
- CAL_ENCODE_FLOAT(acc->adf.z_o[1], 6),
- CAL_ENCODE_FLOAT(acc->adf.z_o[2], 6),
- CAL_ENCODE_FLOAT(acc->adf.z_o[3], 6),
- CAL_ENCODE_FLOAT(acc->adf.z_o[4], 6),
- CAL_ENCODE_FLOAT(acc->adf.z_o[5], 6),
- CAL_ENCODE_FLOAT(acc->adf.z_o[6], 6),
- CAL_ENCODE_FLOAT(acc->adf.z_o[7], 6),
- CAL_ENCODE_FLOAT(acc->adf.z_o[8], 6),
- CAL_ENCODE_FLOAT(acc->adf.z_o[9], 6));
+ CAL_DEBUG_LOG("[ACCEL_CAL]",
+ "{13," CAL_FORMAT_ACCEL_HISTORY "}(z_off history)\n",
+ CAL_ENCODE_FLOAT(acc->adf.z_o[0], 6),
+ CAL_ENCODE_FLOAT(acc->adf.z_o[1], 6),
+ CAL_ENCODE_FLOAT(acc->adf.z_o[2], 6),
+ CAL_ENCODE_FLOAT(acc->adf.z_o[3], 6),
+ CAL_ENCODE_FLOAT(acc->adf.z_o[4], 6),
+ CAL_ENCODE_FLOAT(acc->adf.z_o[5], 6),
+ CAL_ENCODE_FLOAT(acc->adf.z_o[6], 6),
+ CAL_ENCODE_FLOAT(acc->adf.z_o[7], 6),
+ CAL_ENCODE_FLOAT(acc->adf.z_o[8], 6),
+ CAL_ENCODE_FLOAT(acc->adf.z_o[9], 6));
// Temp history variation VAR of offset.
- CAL_DEBUG_LOG(
- "[BMI160]",
- "{MK_ACCEL,14,%s%d.%06d,%s%d.%06d,%s%d.%06d,%s%d.%06d,%s%d.%06d,%s%d.%"
- "06d,%s%d.%06d,%s%d.%06d,%s%d.%06d,%s%d.%06d,}(VAR temp history)\n",
- CAL_ENCODE_FLOAT(acc->adf.var_t[0], 6),
- CAL_ENCODE_FLOAT(acc->adf.var_t[1], 6),
- CAL_ENCODE_FLOAT(acc->adf.var_t[2], 6),
- CAL_ENCODE_FLOAT(acc->adf.var_t[3], 6),
- CAL_ENCODE_FLOAT(acc->adf.var_t[4], 6),
- CAL_ENCODE_FLOAT(acc->adf.var_t[5], 6),
- CAL_ENCODE_FLOAT(acc->adf.var_t[6], 6),
- CAL_ENCODE_FLOAT(acc->adf.var_t[7], 6),
- CAL_ENCODE_FLOAT(acc->adf.var_t[8], 6),
- CAL_ENCODE_FLOAT(acc->adf.var_t[9], 6));
+ CAL_DEBUG_LOG("[ACCEL_CAL]",
+ "{14," CAL_FORMAT_ACCEL_HISTORY "}(VAR temp history)\n",
+ CAL_ENCODE_FLOAT(acc->adf.var_t[0], 6),
+ CAL_ENCODE_FLOAT(acc->adf.var_t[1], 6),
+ CAL_ENCODE_FLOAT(acc->adf.var_t[2], 6),
+ CAL_ENCODE_FLOAT(acc->adf.var_t[3], 6),
+ CAL_ENCODE_FLOAT(acc->adf.var_t[4], 6),
+ CAL_ENCODE_FLOAT(acc->adf.var_t[5], 6),
+ CAL_ENCODE_FLOAT(acc->adf.var_t[6], 6),
+ CAL_ENCODE_FLOAT(acc->adf.var_t[7], 6),
+ CAL_ENCODE_FLOAT(acc->adf.var_t[8], 6),
+ CAL_ENCODE_FLOAT(acc->adf.var_t[9], 6));
// Temp mean history of offset.
- CAL_DEBUG_LOG(
- "[BMI160]",
- "{MK_ACCEL,15,%s%d.%06d,%s%d.%06d,%s%d.%06d,%s%d.%06d,%s%d.%06d,%s%d.%"
- "06d,%s%d.%06d,%s%d.%06d,%s%d.%06d,%s%d.%06d,}(MEAN Temp history)\n",
- CAL_ENCODE_FLOAT(acc->adf.mean_t[0], 6),
- CAL_ENCODE_FLOAT(acc->adf.mean_t[1], 6),
- CAL_ENCODE_FLOAT(acc->adf.mean_t[2], 6),
- CAL_ENCODE_FLOAT(acc->adf.mean_t[3], 6),
- CAL_ENCODE_FLOAT(acc->adf.mean_t[4], 6),
- CAL_ENCODE_FLOAT(acc->adf.mean_t[5], 6),
- CAL_ENCODE_FLOAT(acc->adf.mean_t[6], 6),
- CAL_ENCODE_FLOAT(acc->adf.mean_t[7], 6),
- CAL_ENCODE_FLOAT(acc->adf.mean_t[8], 6),
- CAL_ENCODE_FLOAT(acc->adf.mean_t[9], 6));
+ CAL_DEBUG_LOG("[ACCEL_CAL]",
+ "{15," CAL_FORMAT_ACCEL_HISTORY "}(MEAN Temp history)\n",
+ CAL_ENCODE_FLOAT(acc->adf.mean_t[0], 6),
+ CAL_ENCODE_FLOAT(acc->adf.mean_t[1], 6),
+ CAL_ENCODE_FLOAT(acc->adf.mean_t[2], 6),
+ CAL_ENCODE_FLOAT(acc->adf.mean_t[3], 6),
+ CAL_ENCODE_FLOAT(acc->adf.mean_t[4], 6),
+ CAL_ENCODE_FLOAT(acc->adf.mean_t[5], 6),
+ CAL_ENCODE_FLOAT(acc->adf.mean_t[6], 6),
+ CAL_ENCODE_FLOAT(acc->adf.mean_t[7], 6),
+ CAL_ENCODE_FLOAT(acc->adf.mean_t[8], 6),
+ CAL_ENCODE_FLOAT(acc->adf.mean_t[9], 6));
// KASA radius history.
- CAL_DEBUG_LOG(
- "[BMI160]",
- "{MK_ACCEL,16,%s%d.%06d,%s%d.%06d,%s%d.%06d,%s%d.%06d,%s%d.%06d,%s%d.%"
- "06d,%s%d.%06d,%s%d.%06d,%s%d.%06d,%s%d.%06d,}(radius)\n",
- CAL_ENCODE_FLOAT(acc->adf.rad[0], 6),
- CAL_ENCODE_FLOAT(acc->adf.rad[1], 6),
- CAL_ENCODE_FLOAT(acc->adf.rad[2], 6),
- CAL_ENCODE_FLOAT(acc->adf.rad[3], 6),
- CAL_ENCODE_FLOAT(acc->adf.rad[4], 6),
- CAL_ENCODE_FLOAT(acc->adf.rad[5], 6),
- CAL_ENCODE_FLOAT(acc->adf.rad[6], 6),
- CAL_ENCODE_FLOAT(acc->adf.rad[7], 6),
- CAL_ENCODE_FLOAT(acc->adf.rad[8], 6),
- CAL_ENCODE_FLOAT(acc->adf.rad[9], 6));
+ CAL_DEBUG_LOG("[ACCEL_CAL]", "{16," CAL_FORMAT_ACCEL_HISTORY "}(radius)\n",
+ CAL_ENCODE_FLOAT(acc->adf.rad[0], 6),
+ CAL_ENCODE_FLOAT(acc->adf.rad[1], 6),
+ CAL_ENCODE_FLOAT(acc->adf.rad[2], 6),
+ CAL_ENCODE_FLOAT(acc->adf.rad[3], 6),
+ CAL_ENCODE_FLOAT(acc->adf.rad[4], 6),
+ CAL_ENCODE_FLOAT(acc->adf.rad[5], 6),
+ CAL_ENCODE_FLOAT(acc->adf.rad[6], 6),
+ CAL_ENCODE_FLOAT(acc->adf.rad[7], 6),
+ CAL_ENCODE_FLOAT(acc->adf.rad[8], 6),
+ CAL_ENCODE_FLOAT(acc->adf.rad[9], 6));
kk = 0;
}
if (kk == 750) {
// Eigen Vector X.
- CAL_DEBUG_LOG(
- "[BMI160]",
- "{MK_ACCEL, "
- "7,%s%d.%06d,%s%d.%06d,%s%d.%06d,%s%d.%06d,%s%d.%06d,%s%d.%06d,%s%d.%"
- "06d,%s%d.%06d,%s%d.%06d,%s%d.%06d,}(eigen x)\n",
- CAL_ENCODE_FLOAT(acc->adf.e_x[0], 6),
- CAL_ENCODE_FLOAT(acc->adf.e_x[1], 6),
- CAL_ENCODE_FLOAT(acc->adf.e_x[2], 6),
- CAL_ENCODE_FLOAT(acc->adf.e_x[3], 6),
- CAL_ENCODE_FLOAT(acc->adf.e_x[4], 6),
- CAL_ENCODE_FLOAT(acc->adf.e_x[5], 6),
- CAL_ENCODE_FLOAT(acc->adf.e_x[6], 6),
- CAL_ENCODE_FLOAT(acc->adf.e_x[7], 6),
- CAL_ENCODE_FLOAT(acc->adf.e_x[8], 6),
- CAL_ENCODE_FLOAT(acc->adf.e_x[9], 6));
+ CAL_DEBUG_LOG("[ACCEL_CAL]", "{ 7," CAL_FORMAT_ACCEL_HISTORY "}(eigen x)\n",
+ CAL_ENCODE_FLOAT(acc->adf.e_x[0], 6),
+ CAL_ENCODE_FLOAT(acc->adf.e_x[1], 6),
+ CAL_ENCODE_FLOAT(acc->adf.e_x[2], 6),
+ CAL_ENCODE_FLOAT(acc->adf.e_x[3], 6),
+ CAL_ENCODE_FLOAT(acc->adf.e_x[4], 6),
+ CAL_ENCODE_FLOAT(acc->adf.e_x[5], 6),
+ CAL_ENCODE_FLOAT(acc->adf.e_x[6], 6),
+ CAL_ENCODE_FLOAT(acc->adf.e_x[7], 6),
+ CAL_ENCODE_FLOAT(acc->adf.e_x[8], 6),
+ CAL_ENCODE_FLOAT(acc->adf.e_x[9], 6));
// Y.
- CAL_DEBUG_LOG(
- "[BMI160]",
- "{MK_ACCEL, "
- "8,%s%d.%06d,%s%d.%06d,%s%d.%06d,%s%d.%06d,%s%d.%06d,%s%d.%06d,%s%d.%"
- "06d,%s%d.%06d,%s%d.%06d,%s%d.%06d,}(eigen y)\n",
- CAL_ENCODE_FLOAT(acc->adf.e_y[0], 6),
- CAL_ENCODE_FLOAT(acc->adf.e_y[1], 6),
- CAL_ENCODE_FLOAT(acc->adf.e_y[2], 6),
- CAL_ENCODE_FLOAT(acc->adf.e_y[3], 6),
- CAL_ENCODE_FLOAT(acc->adf.e_y[4], 6),
- CAL_ENCODE_FLOAT(acc->adf.e_y[5], 6),
- CAL_ENCODE_FLOAT(acc->adf.e_y[6], 6),
- CAL_ENCODE_FLOAT(acc->adf.e_y[7], 6),
- CAL_ENCODE_FLOAT(acc->adf.e_y[8], 6),
- CAL_ENCODE_FLOAT(acc->adf.e_y[9], 6));
+ CAL_DEBUG_LOG("[ACCEL_CAL]", "{ 8," CAL_FORMAT_ACCEL_HISTORY "}(eigen y)\n",
+ CAL_ENCODE_FLOAT(acc->adf.e_y[0], 6),
+ CAL_ENCODE_FLOAT(acc->adf.e_y[1], 6),
+ CAL_ENCODE_FLOAT(acc->adf.e_y[2], 6),
+ CAL_ENCODE_FLOAT(acc->adf.e_y[3], 6),
+ CAL_ENCODE_FLOAT(acc->adf.e_y[4], 6),
+ CAL_ENCODE_FLOAT(acc->adf.e_y[5], 6),
+ CAL_ENCODE_FLOAT(acc->adf.e_y[6], 6),
+ CAL_ENCODE_FLOAT(acc->adf.e_y[7], 6),
+ CAL_ENCODE_FLOAT(acc->adf.e_y[8], 6),
+ CAL_ENCODE_FLOAT(acc->adf.e_y[9], 6));
// Z.
- CAL_DEBUG_LOG(
- "[BMI160]",
- "{MK_ACCEL, "
- "9,%s%d.%06d,%s%d.%06d,%s%d.%06d,%s%d.%06d,%s%d.%06d,%s%d.%06d,%s%d.%"
- "06d,%s%d.%06d,%s%d.%06d,%s%d.%06d,}(eigen z)\n",
- CAL_ENCODE_FLOAT(acc->adf.e_z[0], 6),
- CAL_ENCODE_FLOAT(acc->adf.e_z[1], 6),
- CAL_ENCODE_FLOAT(acc->adf.e_z[2], 6),
- CAL_ENCODE_FLOAT(acc->adf.e_z[3], 6),
- CAL_ENCODE_FLOAT(acc->adf.e_z[4], 6),
- CAL_ENCODE_FLOAT(acc->adf.e_z[5], 6),
- CAL_ENCODE_FLOAT(acc->adf.e_z[6], 6),
- CAL_ENCODE_FLOAT(acc->adf.e_z[7], 6),
- CAL_ENCODE_FLOAT(acc->adf.e_z[8], 6),
- CAL_ENCODE_FLOAT(acc->adf.e_z[9], 6));
+ CAL_DEBUG_LOG("[ACCEL_CAL]", "{ 9," CAL_FORMAT_ACCEL_HISTORY "}(eigen z)\n",
+ CAL_ENCODE_FLOAT(acc->adf.e_z[0], 6),
+ CAL_ENCODE_FLOAT(acc->adf.e_z[1], 6),
+ CAL_ENCODE_FLOAT(acc->adf.e_z[2], 6),
+ CAL_ENCODE_FLOAT(acc->adf.e_z[3], 6),
+ CAL_ENCODE_FLOAT(acc->adf.e_z[4], 6),
+ CAL_ENCODE_FLOAT(acc->adf.e_z[5], 6),
+ CAL_ENCODE_FLOAT(acc->adf.e_z[6], 6),
+ CAL_ENCODE_FLOAT(acc->adf.e_z[7], 6),
+ CAL_ENCODE_FLOAT(acc->adf.e_z[8], 6),
+ CAL_ENCODE_FLOAT(acc->adf.e_z[9], 6));
// Accel Time in ns.
- CAL_DEBUG_LOG(
- "[BMI160]",
- "{MK_ACCEL,10,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu,}("
- "timestamp ns)\n",
- acc->adf.cal_time[0], acc->adf.cal_time[1], acc->adf.cal_time[2],
- acc->adf.cal_time[3], acc->adf.cal_time[4], acc->adf.cal_time[5],
- acc->adf.cal_time[6], acc->adf.cal_time[7], acc->adf.cal_time[8],
- acc->adf.cal_time[9]);
+ CAL_DEBUG_LOG("[ACCEL_CAL]",
+ "{10,%" PRIu64 ",%" PRIu64 ",%" PRIu64 ",%" PRIu64 ",%" PRIu64
+ ",%" PRIu64 ",%" PRIu64 ",%" PRIu64 ",%" PRIu64 ",%" PRIu64
+ "}(timestamp ns)\n",
+ acc->adf.cal_time[0], acc->adf.cal_time[1],
+ acc->adf.cal_time[2], acc->adf.cal_time[3],
+ acc->adf.cal_time[4], acc->adf.cal_time[5],
+ acc->adf.cal_time[6], acc->adf.cal_time[7],
+ acc->adf.cal_time[8], acc->adf.cal_time[9]);
}
if (kk == 500) {
// Total bucket count.
- CAL_DEBUG_LOG(
- "[BMI160]",
- "{MK_ACCEL, 0,%2d, %2d, %2d, %2d, %2d, %2d, %2d,}(Total Bucket #)\n",
- (unsigned)acc->adf.ntx, (unsigned)acc->adf.ntxb, (unsigned)acc->adf.nty,
- (unsigned)acc->adf.ntyb, (unsigned)acc->adf.ntz,
- (unsigned)acc->adf.ntzb, (unsigned)acc->adf.ntle);
+ CAL_DEBUG_LOG("[ACCEL_CAL]",
+ "{ 0,%2d, %2d, %2d, %2d, %2d, %2d, %2d}(Total Bucket #)\n",
+ (unsigned)acc->adf.ntx, (unsigned)acc->adf.ntxb,
+ (unsigned)acc->adf.nty, (unsigned)acc->adf.ntyb,
+ (unsigned)acc->adf.ntz, (unsigned)acc->adf.ntzb,
+ (unsigned)acc->adf.ntle);
// Live bucket count lower.
- CAL_DEBUG_LOG(
- "[BMI160]",
- "{MK_ACCEL, 1,%2d, %2d, %2d, %2d, %2d, %2d, %2d, %3d,}(Bucket # "
- "lower)\n",
- (unsigned)acc->ac1[0].agd.nx, (unsigned)acc->ac1[0].agd.nxb,
- (unsigned)acc->ac1[0].agd.ny, (unsigned)acc->ac1[0].agd.nyb,
- (unsigned)acc->ac1[0].agd.nz, (unsigned)acc->ac1[0].agd.nzb,
- (unsigned)acc->ac1[0].agd.nle, (unsigned)acc->ac1[0].akf.nsamples);
+ CAL_DEBUG_LOG("[ACCEL_CAL]",
+ "{ 1,%2d, %2d, %2d, %2d, %2d, %2d, %2d, %3d}(Bucket # "
+ "lower)\n",
+ (unsigned)acc->ac1[0].agd.nx, (unsigned)acc->ac1[0].agd.nxb,
+ (unsigned)acc->ac1[0].agd.ny, (unsigned)acc->ac1[0].agd.nyb,
+ (unsigned)acc->ac1[0].agd.nz, (unsigned)acc->ac1[0].agd.nzb,
+ (unsigned)acc->ac1[0].agd.nle,
+ (unsigned)acc->ac1[0].akf.nsamples);
// Live bucket count hogher.
- CAL_DEBUG_LOG(
- "[BMI160]",
- "{MK_ACCEL, 2,%2d, %2d, %2d, %2d, %2d, %2d, %2d, %3d,}(Bucket # "
- "higher)\n",
- (unsigned)acc->ac1[1].agd.nx, (unsigned)acc->ac1[1].agd.nxb,
- (unsigned)acc->ac1[1].agd.ny, (unsigned)acc->ac1[1].agd.nyb,
- (unsigned)acc->ac1[1].agd.nz, (unsigned)acc->ac1[1].agd.nzb,
- (unsigned)acc->ac1[1].agd.nle, (unsigned)acc->ac1[1].akf.nsamples);
+ CAL_DEBUG_LOG("[ACCEL_CAL]",
+ "{ 2,%2d, %2d, %2d, %2d, %2d, %2d, %2d, %3d}(Bucket # "
+ "higher)\n",
+ (unsigned)acc->ac1[1].agd.nx, (unsigned)acc->ac1[1].agd.nxb,
+ (unsigned)acc->ac1[1].agd.ny, (unsigned)acc->ac1[1].agd.nyb,
+ (unsigned)acc->ac1[1].agd.nz, (unsigned)acc->ac1[1].agd.nzb,
+ (unsigned)acc->ac1[1].agd.nle,
+ (unsigned)acc->ac1[1].akf.nsamples);
// Offset used.
- CAL_DEBUG_LOG(
- "[BMI160]",
- "{MK_ACCEL, 3,%s%d.%06d, %s%d.%06d, %s%d.%06d, %2d,}(updated offset "
- "x,y,z, total # of offsets)\n",
- CAL_ENCODE_FLOAT(acc->x_bias, 6), CAL_ENCODE_FLOAT(acc->y_bias, 6),
- CAL_ENCODE_FLOAT(acc->z_bias, 6), (unsigned)acc->adf.noff);
+ CAL_DEBUG_LOG("[ACCEL_CAL]",
+ "{ 3,"CAL_FORMAT_6DIGITS_TRIPLET", %2d}(updated offset "
+ "x,y,z, total # of offsets)\n",
+ CAL_ENCODE_FLOAT(acc->x_bias, 6),
+ CAL_ENCODE_FLOAT(acc->y_bias, 6),
+ CAL_ENCODE_FLOAT(acc->z_bias, 6), (unsigned)acc->adf.noff);
// Offset New.
- CAL_DEBUG_LOG(
- "[BMI160]",
- "{MK_ACCEL, 4,%s%d.%06d, %s%d.%06d, %s%d.%06d, %s%d.%06d,}(New offset "
- "x,y,z, live temp)\n",
- CAL_ENCODE_FLOAT(acc->x_bias_new, 6),
- CAL_ENCODE_FLOAT(acc->y_bias_new, 6),
- CAL_ENCODE_FLOAT(acc->z_bias_new, 6), CAL_ENCODE_FLOAT(temp, 6));
+ CAL_DEBUG_LOG("[ACCEL_CAL]",
+ "{ 4," CAL_FORMAT_6DIGITS_TRIPLET ", " CAL_FORMAT_6DIGITS
+ "}(New offset x,y,z, live temp)\n",
+ CAL_ENCODE_FLOAT(acc->x_bias_new, 6),
+ CAL_ENCODE_FLOAT(acc->y_bias_new, 6),
+ CAL_ENCODE_FLOAT(acc->z_bias_new, 6),
+ CAL_ENCODE_FLOAT(temp, 6));
// Temp Histogram.
- CAL_DEBUG_LOG(
- "[BMI160]",
- "{MK_ACCEL, 5,%7d, %7d, %7d, %7d, %7d, %7d, %7d, %7d, %7d, %7d, %7d, "
- "%7d, %7d,}(temp histo)\n",
- (unsigned)acc->adf.t_hist[0], (unsigned)acc->adf.t_hist[1],
- (unsigned)acc->adf.t_hist[2], (unsigned)acc->adf.t_hist[3],
- (unsigned)acc->adf.t_hist[4], (unsigned)acc->adf.t_hist[5],
- (unsigned)acc->adf.t_hist[6], (unsigned)acc->adf.t_hist[7],
- (unsigned)acc->adf.t_hist[8], (unsigned)acc->adf.t_hist[9],
- (unsigned)acc->adf.t_hist[10], (unsigned)acc->adf.t_hist[11],
- (unsigned)acc->adf.t_hist[12]);
- CAL_DEBUG_LOG(
- "[BMI160]",
- "M{K_ACCEL, 6,%7d, %7d, %7d,%7d, %7d, %7d, %7d, %7d, %7d, %7d, %7d, "
- "%7d,}(temp histo)\n",
- (unsigned)acc->adf.t_hist[13], (unsigned)acc->adf.t_hist[14],
- (unsigned)acc->adf.t_hist[15], (unsigned)acc->adf.t_hist[16],
- (unsigned)acc->adf.t_hist[17], (unsigned)acc->adf.t_hist[18],
- (unsigned)acc->adf.t_hist[19], (unsigned)acc->adf.t_hist[20],
- (unsigned)acc->adf.t_hist[21], (unsigned)acc->adf.t_hist[22],
- (unsigned)acc->adf.t_hist[23], (unsigned)acc->adf.t_hist[24]);
+ CAL_DEBUG_LOG("[ACCEL_CAL]",
+ "{ 5,%7d, %7d, %7d, %7d, %7d, %7d, %7d, %7d, %7d, %7d, %7d, "
+ "%7d, %7d}(temp histo)\n",
+ (unsigned)acc->adf.t_hist[0], (unsigned)acc->adf.t_hist[1],
+ (unsigned)acc->adf.t_hist[2], (unsigned)acc->adf.t_hist[3],
+ (unsigned)acc->adf.t_hist[4], (unsigned)acc->adf.t_hist[5],
+ (unsigned)acc->adf.t_hist[6], (unsigned)acc->adf.t_hist[7],
+ (unsigned)acc->adf.t_hist[8], (unsigned)acc->adf.t_hist[9],
+ (unsigned)acc->adf.t_hist[10], (unsigned)acc->adf.t_hist[11],
+ (unsigned)acc->adf.t_hist[12]);
+ CAL_DEBUG_LOG("[ACCEL_CAL]",
+ "{ 6,%7d, %7d, %7d, %7d, %7d, %7d, %7d, %7d, %7d, %7d, %7d, "
+ "%7d}(temp histo)\n",
+ (unsigned)acc->adf.t_hist[13], (unsigned)acc->adf.t_hist[14],
+ (unsigned)acc->adf.t_hist[15], (unsigned)acc->adf.t_hist[16],
+ (unsigned)acc->adf.t_hist[17], (unsigned)acc->adf.t_hist[18],
+ (unsigned)acc->adf.t_hist[19], (unsigned)acc->adf.t_hist[20],
+ (unsigned)acc->adf.t_hist[21], (unsigned)acc->adf.t_hist[22],
+ (unsigned)acc->adf.t_hist[23], (unsigned)acc->adf.t_hist[24]);
}
}
#endif
diff --git a/firmware/os/algos/calibration/gyroscope/gyro_cal.c b/firmware/os/algos/calibration/gyroscope/gyro_cal.c
index 9da7aa45..90b25446 100644
--- a/firmware/os/algos/calibration/gyroscope/gyro_cal.c
+++ b/firmware/os/algos/calibration/gyroscope/gyro_cal.c
@@ -17,6 +17,7 @@
#include "calibration/gyroscope/gyro_cal.h"
#include <float.h>
+#include <inttypes.h>
#include <math.h>
#include <string.h>
@@ -222,12 +223,12 @@ void gyroCalSetBias(struct GyroCal* gyro_cal, float bias_x, float bias_y,
#ifdef GYRO_CAL_DBG_ENABLED
CAL_DEBUG_LOG("[GYRO_CAL:SET BIAS]",
"Offset|Temp|Time [mDPS|C|nsec]: " CAL_FORMAT_3DIGITS_TRIPLET
- ", " CAL_FORMAT_3DIGITS ", %llu",
+ ", " CAL_FORMAT_3DIGITS ", %" PRIu64,
CAL_ENCODE_FLOAT(bias_x * RAD_TO_MDEG, 3),
CAL_ENCODE_FLOAT(bias_y * RAD_TO_MDEG, 3),
CAL_ENCODE_FLOAT(bias_z * RAD_TO_MDEG, 3),
CAL_ENCODE_FLOAT(temperature_celsius, 3),
- (unsigned long long int)calibration_time_nanos);
+ calibration_time_nanos);
#endif // GYRO_CAL_DBG_ENABLED
}
@@ -471,7 +472,7 @@ void computeGyroCal(struct GyroCal* gyro_cal, uint64_t calibration_time_nanos) {
CAL_DEBUG_LOG(
"[GYRO_CAL:REJECT]",
"Offset|Temp|Time [mDPS|C|nsec]: " CAL_FORMAT_3DIGITS_TRIPLET
- ", " CAL_FORMAT_3DIGITS ", %llu",
+ ", " CAL_FORMAT_3DIGITS ", %" PRIu64,
CAL_ENCODE_FLOAT(
gyro_cal->gyro_stillness_detect.prev_mean_x * RAD_TO_MDEG, 3),
CAL_ENCODE_FLOAT(
@@ -479,7 +480,7 @@ void computeGyroCal(struct GyroCal* gyro_cal, uint64_t calibration_time_nanos) {
CAL_ENCODE_FLOAT(
gyro_cal->gyro_stillness_detect.prev_mean_z * RAD_TO_MDEG, 3),
CAL_ENCODE_FLOAT(gyro_cal->temperature_mean_celsius, 3),
- (unsigned long long int)calibration_time_nanos);
+ calibration_time_nanos);
#endif // GYRO_CAL_DBG_ENABLED
// Outside of range. Ignore, reset, and continue.
@@ -540,21 +541,17 @@ void checkWatchdog(struct GyroCal* gyro_cal, uint64_t sample_time_nanos) {
#ifdef GYRO_CAL_DBG_ENABLED
gyro_cal->debug_watchdog_count++;
if (sample_time_nanos < gyro_cal->gyro_watchdog_start_nanos) {
- CAL_DEBUG_LOG(
- "[GYRO_CAL:WATCHDOG]",
- "Total#, Timestamp | Delta [nsec]: %lu, %llu, -%llu",
- (unsigned long int)gyro_cal->debug_watchdog_count,
- (unsigned long long int)sample_time_nanos,
- (unsigned long long int)(gyro_cal->gyro_watchdog_start_nanos -
- sample_time_nanos));
+ CAL_DEBUG_LOG("[GYRO_CAL:WATCHDOG]",
+ "Total#, Timestamp | Delta [nsec]: %zu, %" PRIu64
+ ", -%" PRIu64,
+ gyro_cal->debug_watchdog_count, sample_time_nanos,
+ gyro_cal->gyro_watchdog_start_nanos - sample_time_nanos);
} else {
- CAL_DEBUG_LOG(
- "[GYRO_CAL:WATCHDOG]",
- "Total#, Timestamp | Delta [nsec]: %lu, %llu, %llu",
- (unsigned long int)gyro_cal->debug_watchdog_count,
- (unsigned long long int)sample_time_nanos,
- (unsigned long long int)(sample_time_nanos -
- gyro_cal->gyro_watchdog_start_nanos));
+ CAL_DEBUG_LOG("[GYRO_CAL:WATCHDOG]",
+ "Total#, Timestamp | Delta [nsec]: %zu, %" PRIu64
+ ", %" PRIu64,
+ gyro_cal->debug_watchdog_count, sample_time_nanos,
+ sample_time_nanos - gyro_cal->gyro_watchdog_start_nanos);
}
#endif // GYRO_CAL_DBG_ENABLED
@@ -884,8 +881,9 @@ void gyroCalDebugPrintData(const struct GyroCal* gyro_cal, char* debug_tag,
CAL_DEBUG_LOG(
debug_tag,
"Cal#|Offset|Temp|Time [mDPS|C|nsec]: "
- "%lu, " CAL_FORMAT_3DIGITS_TRIPLET ", " CAL_FORMAT_3DIGITS ", %llu",
- (unsigned long int)gyro_cal->debug_calibration_count,
+ "%zu, " CAL_FORMAT_3DIGITS_TRIPLET ", " CAL_FORMAT_3DIGITS
+ ", %" PRIu64,
+ gyro_cal->debug_calibration_count,
CAL_ENCODE_FLOAT(
gyro_cal->debug_gyro_cal.calibration[0] * RAD_TO_MDEG, 3),
CAL_ENCODE_FLOAT(
@@ -894,8 +892,7 @@ void gyroCalDebugPrintData(const struct GyroCal* gyro_cal, char* debug_tag,
gyro_cal->debug_gyro_cal.calibration[2] * RAD_TO_MDEG, 3),
CAL_ENCODE_FLOAT(gyro_cal->debug_gyro_cal.temperature_mean_celsius,
3),
- (unsigned long long int)
- gyro_cal->debug_gyro_cal.end_still_time_nanos);
+ gyro_cal->debug_gyro_cal.end_still_time_nanos);
break;
case STILLNESS_DATA:
@@ -904,13 +901,11 @@ void gyroCalDebugPrintData(const struct GyroCal* gyro_cal, char* debug_tag,
: -1.0f; // Signals that magnetometer was not used.
CAL_DEBUG_LOG(
debug_tag,
- "Cal#|Stillness|Confidence [nsec]: %lu, "
- "%llu, " CAL_FORMAT_3DIGITS_TRIPLET,
- (unsigned long int)gyro_cal->debug_calibration_count,
- (unsigned long long int)(gyro_cal->debug_gyro_cal
- .end_still_time_nanos -
- gyro_cal->debug_gyro_cal
- .start_still_time_nanos),
+ "Cal#|Stillness|Confidence [nsec]: %zu, "
+ "%" PRIu64 ", " CAL_FORMAT_3DIGITS_TRIPLET,
+ gyro_cal->debug_calibration_count,
+ gyro_cal->debug_gyro_cal.end_still_time_nanos -
+ gyro_cal->debug_gyro_cal.start_still_time_nanos,
CAL_ENCODE_FLOAT(gyro_cal->debug_gyro_cal.gyro_stillness_conf, 3),
CAL_ENCODE_FLOAT(gyro_cal->debug_gyro_cal.accel_stillness_conf, 3),
CAL_ENCODE_FLOAT(mag_data, 3));
@@ -920,9 +915,9 @@ void gyroCalDebugPrintData(const struct GyroCal* gyro_cal, char* debug_tag,
CAL_DEBUG_LOG(
debug_tag,
"Cal#|Mean|Min|Max|Delta|Sample Rate [C|Hz]: "
- "%lu, " CAL_FORMAT_3DIGITS_TRIPLET ", " CAL_FORMAT_3DIGITS
+ "%zu, " CAL_FORMAT_3DIGITS_TRIPLET ", " CAL_FORMAT_3DIGITS
", " CAL_FORMAT_3DIGITS,
- (unsigned long int)gyro_cal->debug_calibration_count,
+ gyro_cal->debug_calibration_count,
CAL_ENCODE_FLOAT(gyro_cal->debug_gyro_cal.temperature_mean_celsius,
3),
CAL_ENCODE_FLOAT(gyro_cal->debug_gyro_cal.temperature_min_celsius, 3),
@@ -939,8 +934,8 @@ void gyroCalDebugPrintData(const struct GyroCal* gyro_cal, char* debug_tag,
CAL_DEBUG_LOG(
debug_tag,
"Cal#|Gyro Peak Stillness Variation [mDPS]: "
- "%lu, " CAL_FORMAT_3DIGITS_TRIPLET,
- (unsigned long int)gyro_cal->debug_calibration_count,
+ "%zu, " CAL_FORMAT_3DIGITS_TRIPLET,
+ gyro_cal->debug_calibration_count,
CAL_ENCODE_FLOAT((gyro_cal->debug_gyro_cal.gyro_winmean_max[0] -
gyro_cal->debug_gyro_cal.gyro_winmean_min[0]) *
RAD_TO_MDEG,
@@ -958,9 +953,9 @@ void gyroCalDebugPrintData(const struct GyroCal* gyro_cal, char* debug_tag,
case ACCEL_STATS:
CAL_DEBUG_LOG(debug_tag,
"Cal#|Accel Mean|Var [m/sec^2|(m/sec^2)^2]: "
- "%lu, " CAL_FORMAT_3DIGITS_TRIPLET
+ "%zu, " CAL_FORMAT_3DIGITS_TRIPLET
", " CAL_FORMAT_6DIGITS_TRIPLET,
- (unsigned long int)gyro_cal->debug_calibration_count,
+ gyro_cal->debug_calibration_count,
CAL_ENCODE_FLOAT(gyro_cal->debug_gyro_cal.accel_mean[0], 3),
CAL_ENCODE_FLOAT(gyro_cal->debug_gyro_cal.accel_mean[1], 3),
CAL_ENCODE_FLOAT(gyro_cal->debug_gyro_cal.accel_mean[2], 3),
@@ -972,9 +967,9 @@ void gyroCalDebugPrintData(const struct GyroCal* gyro_cal, char* debug_tag,
case GYRO_STATS:
CAL_DEBUG_LOG(
debug_tag,
- "Cal#|Gyro Mean|Var [mDPS|mDPS^2]: %lu, " CAL_FORMAT_3DIGITS_TRIPLET
+ "Cal#|Gyro Mean|Var [mDPS|mDPS^2]: %zu, " CAL_FORMAT_3DIGITS_TRIPLET
", " CAL_FORMAT_3DIGITS_TRIPLET,
- (unsigned long int)gyro_cal->debug_calibration_count,
+ gyro_cal->debug_calibration_count,
CAL_ENCODE_FLOAT(gyro_cal->debug_gyro_cal.gyro_mean[0] * RAD_TO_MDEG,
3),
CAL_ENCODE_FLOAT(gyro_cal->debug_gyro_cal.gyro_mean[1] * RAD_TO_MDEG,
@@ -996,9 +991,9 @@ void gyroCalDebugPrintData(const struct GyroCal* gyro_cal, char* debug_tag,
if (gyro_cal->debug_gyro_cal.using_mag_sensor) {
CAL_DEBUG_LOG(
debug_tag,
- "Cal#|Mag Mean|Var [uT|uT^2]: %lu, " CAL_FORMAT_3DIGITS_TRIPLET
+ "Cal#|Mag Mean|Var [uT|uT^2]: %zu, " CAL_FORMAT_3DIGITS_TRIPLET
", " CAL_FORMAT_6DIGITS_TRIPLET,
- (unsigned long int)gyro_cal->debug_calibration_count,
+ gyro_cal->debug_calibration_count,
CAL_ENCODE_FLOAT(gyro_cal->debug_gyro_cal.mag_mean[0], 3),
CAL_ENCODE_FLOAT(gyro_cal->debug_gyro_cal.mag_mean[1], 3),
CAL_ENCODE_FLOAT(gyro_cal->debug_gyro_cal.mag_mean[2], 3),
@@ -1007,9 +1002,9 @@ void gyroCalDebugPrintData(const struct GyroCal* gyro_cal, char* debug_tag,
CAL_ENCODE_FLOAT(gyro_cal->debug_gyro_cal.mag_var[2], 6));
} else {
CAL_DEBUG_LOG(debug_tag,
- "Cal#|Mag Mean|Var [uT|uT^2]: %lu, 0, 0, 0, -1.0, -1.0, "
+ "Cal#|Mag Mean|Var [uT|uT^2]: %zu, 0, 0, 0, -1.0, -1.0, "
"-1.0",
- (unsigned long int)gyro_cal->debug_calibration_count);
+ gyro_cal->debug_calibration_count);
}
break;
diff --git a/firmware/os/algos/calibration/gyroscope/gyro_stillness_detect.c b/firmware/os/algos/calibration/gyroscope/gyro_stillness_detect.c
index deb26b3f..bb2063b6 100644
--- a/firmware/os/algos/calibration/gyroscope/gyro_stillness_detect.c
+++ b/firmware/os/algos/calibration/gyroscope/gyro_stillness_detect.c
@@ -15,6 +15,7 @@
*/
#include "calibration/gyroscope/gyro_stillness_detect.h"
+
#include <string.h>
/////// FORWARD DECLARATIONS /////////////////////////////////////////
diff --git a/firmware/os/algos/calibration/magnetometer/mag_cal.c b/firmware/os/algos/calibration/magnetometer/mag_cal/mag_cal.c
index 40749e1a..c3f12ae6 100644
--- a/firmware/os/algos/calibration/magnetometer/mag_cal.c
+++ b/firmware/os/algos/calibration/magnetometer/mag_cal/mag_cal.c
@@ -14,23 +14,30 @@
* limitations under the License.
*/
-#include "calibration/magnetometer/mag_cal.h"
+#include "calibration/magnetometer/mag_cal/mag_cal.h"
#include <errno.h>
+#include <inttypes.h>
#include <string.h>
#include "calibration/util/cal_log.h"
-// clang-format off
-#ifdef MAG_CAL_ORIGINAL_TUNING
-#define MAX_EIGEN_RATIO 25.0f
-#define MAX_EIGEN_MAG 80.0f // uT
-#define MIN_EIGEN_MAG 10.0f // uT
-#define MAX_FIT_MAG 80.0f
-#define MIN_FIT_MAG 10.0f
-#define MAX_BATCH_WINDOW 15000000UL // 15 sec
-#define MIN_BATCH_SIZE 25 // samples
+// Local helper macro for printing log messages.
+#ifdef MAG_CAL_DEBUG_ENABLE
+#ifdef CAL_NO_FLOAT_FORMAT_STRINGS
+#define CAL_FORMAT_MAG_MEMORY \
+ "%s%d.%03d, %s%d.%03d, %s%d.%03d, %s%d.%03d, %s%d.%03d, %s%d.%03d, " \
+ "%s%d.%03d, %s%d.%03d, %s%d.%03d, %s%d.%03d, %s%d.%03d, %s%d.%03d, " \
+ "%s%d.%03d, %s%d.%03d, %s%d.%03d, %s%d.%03d, %s%d.%03d, %s%d.%03d, " \
+ "%s%d.%03d, %s%d.%03d"
#else
+#define CAL_FORMAT_MAG_MEMORY \
+ "%.3f, %.3f, %.3f, %.3f, %.3f, %.3f, %.3f, %.3f, %.3f, %.3f, %.3f, %.3f, " \
+ "%.3f, %.3f, %.3f, %.3f, %.3f, %.3f, %.3f, %.3f"
+#endif // CAL_NO_FLOAT_FORMAT_STRINGS
+#endif // MAG_CAL_DEBUG_ENABLE
+
+// clang-format off
#define MAX_EIGEN_RATIO 15.0f
#define MAX_EIGEN_MAG 70.0f // uT
#define MIN_EIGEN_MAG 20.0f // uT
@@ -38,23 +45,12 @@
#define MIN_FIT_MAG 20.0f
#define MAX_BATCH_WINDOW 15000000UL // 15 sec
#define MIN_BATCH_SIZE 25 // samples
-#endif
-
-#ifdef DIVERSITY_CHECK_ENABLED
#define MAX_DISTANCE_VIOLATIONS 2
-#ifdef SPHERE_FIT_ENABLED
-#define MAX_ITERATIONS 30
-#define INITIAL_U_SCALE 1.0e-4f
-#define GRADIENT_THRESHOLD 1.0e-16f
-#define RELATIVE_STEP_THRESHOLD 1.0e-7f
-#define FROM_MICRO_SEC_TO_SEC 1.0e-6f
-#endif
-#endif
// clang-format
-// eigen value magnitude and ratio test
+// eigen value magnitude and ratio test.
static int moc_eigen_test(struct KasaFit *kasa) {
- // covariance matrix
+ // covariance matrix.
struct Mat33 S;
S.elem[0][0] = kasa->acc_xx - kasa->acc_x * kasa->acc_x;
S.elem[0][1] = S.elem[1][0] = kasa->acc_xy - kasa->acc_x * kasa->acc_y;
@@ -86,9 +82,7 @@ static int moc_eigen_test(struct KasaFit *kasa) {
void magCalReset(struct MagCal *moc) {
kasaReset(&moc->kasa);
-#ifdef DIVERSITY_CHECK_ENABLED
diversityCheckerReset(&moc->diversity_checker);
-#endif
moc->start_time = 0;
moc->kasa_batching = false;
}
@@ -110,12 +104,8 @@ static bool moc_batch_complete(struct MagCal *moc, uint64_t sample_time_us) {
}
void initMagCal(struct MagCal *moc,
- const struct MagCalParameters *mag_cal_parameters
-#ifdef DIVERSITY_CHECK_ENABLED
- ,
- const struct DiversityCheckerParameters *diverse_parameters
-#endif
-) {
+ const struct MagCalParameters *mag_cal_parameters,
+ const struct DiversityCheckerParameters *diverse_parameters) {
magCalReset(moc);
moc->update_time = 0;
moc->min_batch_window_in_micros =
@@ -139,12 +129,10 @@ void initMagCal(struct MagCal *moc,
#ifdef MAG_CAL_DEBUG_ENABLE
moc->mag_dbg.mag_trigger_count = 0;
moc->mag_dbg.kasa_count = 0;
-#endif
+#endif // MAG_CAL_DEBUG_ENABLE
-#ifdef DIVERSITY_CHECK_ENABLED
// Diversity Checker
diversityCheckerInit(&moc->diversity_checker, diverse_parameters);
-#endif
}
void magCalDestroy(struct MagCal *moc) { (void)moc; }
@@ -153,10 +141,8 @@ enum MagUpdate magCalUpdate(struct MagCal *moc, uint64_t sample_time_us,
float x, float y, float z) {
enum MagUpdate new_bias = NO_UPDATE;
-#ifdef DIVERSITY_CHECK_ENABLED
// Diversity Checker Update.
diversityCheckerUpdate(&moc->diversity_checker, x, y, z);
-#endif
// 1. run accumulators
kasaAccumulate(&moc->kasa, x, y, z);
@@ -178,15 +164,13 @@ enum MagUpdate magCalUpdate(struct MagCal *moc, uint64_t sample_time_us,
if (kasaFit(&moc->kasa, &bias, &radius, MAX_FIT_MAG, MIN_FIT_MAG)) {
#ifdef MAG_CAL_DEBUG_ENABLE
moc->mag_dbg.kasa_count++;
- CAL_DEBUG_LOG("[MAG_CAL:KASA UPDATE] :,",
- "%s%d.%03d, %s%d.%03d, %s%d.%03d, %s%d.%03d, %lu, %lu",
+ CAL_DEBUG_LOG("[MAG_CAL:KASA UPDATE] :", CAL_FORMAT_3DIGITS_TRIPLET
+ ", " CAL_FORMAT_3DIGITS ", %" PRIu32 ", %" PRIu32,
CAL_ENCODE_FLOAT(bias.x, 3), CAL_ENCODE_FLOAT(bias.y, 3),
CAL_ENCODE_FLOAT(bias.z, 3), CAL_ENCODE_FLOAT(radius, 3),
- (unsigned long int)moc->mag_dbg.kasa_count,
- (unsigned long int)moc->mag_dbg.mag_trigger_count);
-#endif
+ moc->mag_dbg.kasa_count, moc->mag_dbg.mag_trigger_count);
+#endif // MAG_CAL_DEBUG_ENABLE
-#ifdef DIVERSITY_CHECK_ENABLED
// Update the local field.
diversityCheckerLocalFieldUpdate(&moc->diversity_checker, radius);
@@ -198,14 +182,13 @@ enum MagUpdate magCalUpdate(struct MagCal *moc, uint64_t sample_time_us,
// DEBUG PRINT OUT.
#ifdef MAG_CAL_DEBUG_ENABLE
moc->mag_dbg.mag_trigger_count++;
-#ifdef DIVERSE_DEBUG_ENABLE
moc->diversity_checker.diversity_dbg.new_trigger = 1;
CAL_DEBUG_LOG(
- "[MAG_CAL:BIAS UPDATE] :, ",
- "%s%d.%03d, %s%d.%03d, %s%d.%03d, %s%d.%03d, %s%d.%06d,"
- "%s%d.%03d, %s%d.%03d, %s%d.%03d, %zu, %s%d.%03d, "
- "%s%d.%03d, %lu, %lu, %llu, %s%d.%03d, %s%d.%03d, "
- "%s%d.%03d, %llu",
+ "[MAG_CAL:BIAS UPDATE] :", CAL_FORMAT_3DIGITS_TRIPLET ", "
+ CAL_FORMAT_3DIGITS ", " CAL_FORMAT_6DIGITS ", "
+ CAL_FORMAT_3DIGITS_TRIPLET ", %zu, " CAL_FORMAT_3DIGITS ", "
+ CAL_FORMAT_3DIGITS ", %" PRIu32 ", %" PRIu32 ", %" PRIu64 ", "
+ CAL_FORMAT_3DIGITS_TRIPLET ", %" PRIu64 "",
CAL_ENCODE_FLOAT(bias.x, 3), CAL_ENCODE_FLOAT(bias.y, 3),
CAL_ENCODE_FLOAT(bias.z, 3), CAL_ENCODE_FLOAT(radius, 3),
CAL_ENCODE_FLOAT(moc->diversity_checker.diversity_dbg.var_log, 6),
@@ -216,16 +199,14 @@ enum MagUpdate magCalUpdate(struct MagCal *moc, uint64_t sample_time_us,
moc->diversity_checker.num_points,
CAL_ENCODE_FLOAT(moc->diversity_checker.threshold, 3),
CAL_ENCODE_FLOAT(moc->diversity_checker.max_distance, 3),
- (unsigned long int)moc->mag_dbg.mag_trigger_count,
- (unsigned long int)moc->mag_dbg.kasa_count,
- (unsigned long long int)sample_time_us,
+ moc->mag_dbg.mag_trigger_count,
+ moc->mag_dbg.kasa_count,
+ sample_time_us,
CAL_ENCODE_FLOAT(moc->x_bias, 3),
CAL_ENCODE_FLOAT(moc->y_bias, 3),
CAL_ENCODE_FLOAT(moc->z_bias, 3),
- (unsigned long long int)moc->update_time);
-#endif
-#endif
-#endif
+ moc->update_time);
+#endif // MAG_CAL_DEBUG_ENABLE
moc->x_bias = bias.x;
moc->y_bias = bias.y;
moc->z_bias = bias.z;
@@ -234,13 +215,9 @@ enum MagUpdate magCalUpdate(struct MagCal *moc, uint64_t sample_time_us,
moc->update_time = sample_time_us;
new_bias = UPDATE_BIAS;
-
-#ifdef DIVERSITY_CHECK_ENABLED
}
-#endif
}
}
-
// 5. reset for next batch
magCalReset(moc);
}
@@ -248,7 +225,7 @@ enum MagUpdate magCalUpdate(struct MagCal *moc, uint64_t sample_time_us,
return new_bias;
}
-void magCalGetBias(struct MagCal *moc, float *x, float *y, float *z) {
+void magCalGetBias(const struct MagCal *moc, float *x, float *y, float *z) {
*x = moc->x_bias;
*y = moc->y_bias;
*z = moc->z_bias;
@@ -288,7 +265,7 @@ void magCalRemoveSoftiron(struct MagCal *moc, float xi, float yi, float zi,
*zo = moc->c20 * xi + moc->c21 * yi + moc->c22 * zi;
}
-#if defined MAG_CAL_DEBUG_ENABLE && defined DIVERSE_DEBUG_ENABLE
+#if defined MAG_CAL_DEBUG_ENABLE
// This function prints every second sample parts of the dbg diverse_data_log,
// which ensures that all the messages get printed into the log file.
void magLogPrint(struct DiversityChecker *diverse_data, float temp) {
@@ -299,13 +276,9 @@ void magLogPrint(struct DiversityChecker *diverse_data, float temp) {
sample_counter++;
if (sample_counter == 2) {
CAL_DEBUG_LOG(
- "[MAG_CAL:MEMORY X] :,",
- "%lu, %s%d.%03d, %s%d.%03d, %s%d.%03d, %s%d.%03d, %s%d.%03d"
- ", %s%d.%03d, %s%d.%03d, %s%d.%03d, %s%d.%03d, %s%d.%03d, "
- "%s%d.%03d, %s%d.%03d, %s%d.%03d, %s%d.%03d, %s%d.%03d, "
- "%s%d.%03d, %s%d.%03d, %s%d.%03d, %s%d.%03d, %s%d.%03d, "
- "%s%d.%03d",
- (unsigned long int)diverse_data->diversity_dbg.diversity_count,
+ "[MAG_CAL:MEMORY X] :", "%" PRIu32 ", " CAL_FORMAT_MAG_MEMORY ", "
+ CAL_FORMAT_3DIGITS,
+ diverse_data->diversity_dbg.diversity_count,
CAL_ENCODE_FLOAT(data_log_ptr[0 * 3], 3),
CAL_ENCODE_FLOAT(data_log_ptr[1 * 3], 3),
CAL_ENCODE_FLOAT(data_log_ptr[2 * 3], 3),
@@ -330,12 +303,8 @@ void magLogPrint(struct DiversityChecker *diverse_data, float temp) {
if (sample_counter == 4) {
CAL_DEBUG_LOG(
- "[MAG_CAL:MEMORY Y] :,",
- "%lu, %s%d.%03d, %s%d.%03d, %s%d.%03d, %s%d.%03d, %s%d.%03d"
- ", %s%d.%03d, %s%d.%03d, %s%d.%03d, %s%d.%03d, %s%d.%03d, "
- "%s%d.%03d, %s%d.%03d, %s%d.%03d, %s%d.%03d, %s%d.%03d, "
- "%s%d.%03d, %s%d.%03d, %s%d.%03d, %s%d.%03d, %s%d.%03d, ",
- (unsigned long int)diverse_data->diversity_dbg.diversity_count,
+ "[MAG_CAL:MEMORY Y] :", "%" PRIu32 ", " CAL_FORMAT_MAG_MEMORY,
+ diverse_data->diversity_dbg.diversity_count,
CAL_ENCODE_FLOAT(data_log_ptr[0 * 3 + 1], 3),
CAL_ENCODE_FLOAT(data_log_ptr[1 * 3 + 1], 3),
CAL_ENCODE_FLOAT(data_log_ptr[2 * 3 + 1], 3),
@@ -359,12 +328,8 @@ void magLogPrint(struct DiversityChecker *diverse_data, float temp) {
}
if (sample_counter == 6) {
CAL_DEBUG_LOG(
- "[MAG_CAL:MEMORY Z] :,",
- "%lu, %s%d.%03d, %s%d.%03d, %s%d.%03d, %s%d.%03d, %s%d.%03d"
- ", %s%d.%03d, %s%d.%03d, %s%d.%03d, %s%d.%03d, %s%d.%03d, "
- "%s%d.%03d, %s%d.%03d, %s%d.%03d, %s%d.%03d, %s%d.%03d, "
- "%s%d.%03d, %s%d.%03d, %s%d.%03d, %s%d.%03d, %s%d.%03d, ",
- (unsigned long int)diverse_data->diversity_dbg.diversity_count,
+ "[MAG_CAL:MEMORY Z] :", "%" PRIu32 ", " CAL_FORMAT_MAG_MEMORY,
+ diverse_data->diversity_dbg.diversity_count,
CAL_ENCODE_FLOAT(data_log_ptr[0 * 3 + 2], 3),
CAL_ENCODE_FLOAT(data_log_ptr[1 * 3 + 2], 3),
CAL_ENCODE_FLOAT(data_log_ptr[2 * 3 + 2], 3),
@@ -390,4 +355,4 @@ void magLogPrint(struct DiversityChecker *diverse_data, float temp) {
}
}
}
-#endif
+#endif // MAG_CAL_DEBUG_ENABLE
diff --git a/firmware/os/algos/calibration/magnetometer/mag_cal.h b/firmware/os/algos/calibration/magnetometer/mag_cal/mag_cal.h
index 381a925b..bbc079cb 100644
--- a/firmware/os/algos/calibration/magnetometer/mag_cal.h
+++ b/firmware/os/algos/calibration/magnetometer/mag_cal/mag_cal.h
@@ -14,21 +14,19 @@
* limitations under the License.
*/
-#ifndef LOCATION_LBS_CONTEXTHUB_NANOAPPS_CALIBRATION_MAGNETOMETER_MAG_CAL_H_
-#define LOCATION_LBS_CONTEXTHUB_NANOAPPS_CALIBRATION_MAGNETOMETER_MAG_CAL_H_
+#ifndef LOCATION_LBS_CONTEXTHUB_NANOAPPS_CALIBRATION_MAGNETOMETER_MAG_CAL_MAG_CAL_H_
+#define LOCATION_LBS_CONTEXTHUB_NANOAPPS_CALIBRATION_MAGNETOMETER_MAG_CAL_MAG_CAL_H_
-#ifdef SPHERE_FIT_ENABLED
-#ifndef DIVERSITY_CHECK_ENABLED
-#define DIVERSITY_CHECK_ENABLED
-#endif
-#endif
+#ifdef MAG_CAL_DEBUG_ENABLE
+// Enables diversity debug messages if mag_cal debugging is enabled.
+#define DIVERSE_DEBUG_ENABLE
+#endif // MAG_CAL_DEBUG_ENABLE
#include <stdbool.h>
#include <stdint.h>
#include <sys/types.h>
-#ifdef DIVERSITY_CHECK_ENABLED
+
#include "calibration/diversity_checker/diversity_checker.h"
-#endif
#include "common/math/kasa.h"
#include "common/math/mat.h"
#include "common/math/vec.h"
@@ -71,9 +69,7 @@ struct MagCalParameters {
};
struct MagCal {
-#ifdef DIVERSITY_CHECK_ENABLED
struct DiversityChecker diversity_checker;
-#endif
struct KasaFit kasa;
uint64_t start_time; // [micro-seconds]
@@ -89,21 +85,16 @@ struct MagCal {
#endif
};
-#ifdef DIVERSITY_CHECK_ENABLED
void initMagCal(struct MagCal *moc,
const struct MagCalParameters *mag_cal_parameters,
const struct DiversityCheckerParameters *diverse_parameters);
-#else
-void initMagCal(struct MagCal *moc,
- const struct MagCalParameters *mag_cal_parameters);
-#endif
void magCalDestroy(struct MagCal *moc);
enum MagUpdate magCalUpdate(struct MagCal *moc, uint64_t sample_time_us,
float x, float y, float z);
-void magCalGetBias(struct MagCal *moc, float *x, float *y, float *z);
+void magCalGetBias(const struct MagCal *moc, float *x, float *y, float *z);
void magCalAddBias(struct MagCal *moc, float x, float y, float z);
@@ -119,7 +110,7 @@ void magCalRemoveSoftiron(struct MagCal *moc, float xi, float yi, float zi,
void magCalReset(struct MagCal *moc);
-#if defined MAG_CAL_DEBUG_ENABLE && defined DIVERSITY_CHECK_ENABLED
+#if defined MAG_CAL_DEBUG_ENABLE
void magLogPrint(struct DiversityChecker *moc, float temp);
#endif
@@ -127,4 +118,4 @@ void magLogPrint(struct DiversityChecker *moc, float temp);
}
#endif
-#endif // LOCATION_LBS_CONTEXTHUB_NANOAPPS_CALIBRATION_MAGNETOMETER_MAG_CAL_H_
+#endif // LOCATION_LBS_CONTEXTHUB_NANOAPPS_CALIBRATION_MAGNETOMETER_MAG_CAL_MAG_CAL_H_
diff --git a/firmware/os/algos/calibration/magnetometer/mag_sphere_fit.c b/firmware/os/algos/calibration/magnetometer/mag_sphere_fit_cal/mag_sphere_fit.c
index 3e23dcfd..93c2ac61 100644
--- a/firmware/os/algos/calibration/magnetometer/mag_sphere_fit.c
+++ b/firmware/os/algos/calibration/magnetometer/mag_sphere_fit_cal/mag_sphere_fit.c
@@ -14,13 +14,11 @@
* limitations under the License.
*/
-#include "calibration/magnetometer/mag_sphere_fit.h"
+#include "calibration/magnetometer/mag_sphere_fit_cal/mag_sphere_fit.h"
#include <errno.h>
#include <string.h>
-#include "calibration/util/cal_log.h"
-
#define MAX_ITERATIONS 30
#define INITIAL_U_SCALE 1.0e-4f
#define GRADIENT_THRESHOLD 1.0e-16f
diff --git a/firmware/os/algos/calibration/magnetometer/mag_sphere_fit.h b/firmware/os/algos/calibration/magnetometer/mag_sphere_fit_cal/mag_sphere_fit.h
index 7c2fc864..3ae4687b 100644
--- a/firmware/os/algos/calibration/magnetometer/mag_sphere_fit.h
+++ b/firmware/os/algos/calibration/magnetometer/mag_sphere_fit_cal/mag_sphere_fit.h
@@ -14,10 +14,10 @@
* limitations under the License.
*/
-#ifndef LOCATION_LBS_CONTEXTHUB_NANOAPPS_CALIBRATION_MAGNETOMETER_MAG_SPHERE_FIT_H_
-#define LOCATION_LBS_CONTEXTHUB_NANOAPPS_CALIBRATION_MAGNETOMETER_MAG_SPHERE_FIT_H_
+#ifndef LOCATION_LBS_CONTEXTHUB_NANOAPPS_CALIBRATION_MAGNETOMETER_MAG_SPHERE_FIT_CAL_MAG_SPHERE_FIT_H_
+#define LOCATION_LBS_CONTEXTHUB_NANOAPPS_CALIBRATION_MAGNETOMETER_MAG_SPHERE_FIT_CAL_MAG_SPHERE_FIT_H_
-#include "calibration/magnetometer/mag_cal.h"
+#include "calibration/magnetometer/mag_cal/mag_cal.h"
#include "calibration/sphere_fit/sphere_fit_calibration.h"
#define NUM_SPHERE_FIT_DATA 50
@@ -69,4 +69,4 @@ void magCalSphereOdrUpdate(struct MagCalSphere *mocs, float odr_in_hz);
}
#endif
-#endif // LOCATION_LBS_CONTEXTHUB_NANOAPPS_CALIBRATION_MAGNETOMETER_MAG_SPHERE_FIT_H_
+#endif // LOCATION_LBS_CONTEXTHUB_NANOAPPS_CALIBRATION_MAGNETOMETER_MAG_SPHERE_FIT_CAL_MAG_SPHERE_FIT_H_
diff --git a/firmware/os/algos/calibration/nano_calibration/aosp_nano_cal_parameters.h b/firmware/os/algos/calibration/nano_calibration/aosp_nano_cal_parameters.h
index 88557ad9..12b84701 100644
--- a/firmware/os/algos/calibration/nano_calibration/aosp_nano_cal_parameters.h
+++ b/firmware/os/algos/calibration/nano_calibration/aosp_nano_cal_parameters.h
@@ -28,7 +28,7 @@
#ifdef MAG_CAL_ENABLED
#include "calibration/diversity_checker/diversity_checker.h"
-#include "calibration/magnetometer/mag_cal.h"
+#include "calibration/magnetometer/mag_cal/mag_cal.h"
#endif // MAG_CAL_ENABLED
#include "common/math/macros.h"
diff --git a/firmware/os/algos/calibration/nano_calibration/nano_calibration.cc b/firmware/os/algos/calibration/nano_calibration/nano_calibration.cc
index 68b477b7..a5de5d7e 100644
--- a/firmware/os/algos/calibration/nano_calibration/nano_calibration.cc
+++ b/firmware/os/algos/calibration/nano_calibration/nano_calibration.cc
@@ -39,10 +39,10 @@ using ::online_calibration::SensorType;
#define NANO_CAL_LOGW(tag, format, ...) LOGW("%s " format, tag, ##__VA_ARGS__)
#define NANO_CAL_LOGE(tag, format, ...) LOGE("%s " format, tag, ##__VA_ARGS__)
#else
-#define NANO_CAL_LOGD(tag, format, ...) chreLogNull(format, ##__VA_ARGS__)
-#define NANO_CAL_LOGI(tag, format, ...) chreLogNull(format, ##__VA_ARGS__)
-#define NANO_CAL_LOGW(tag, format, ...) chreLogNull(format, ##__VA_ARGS__)
-#define NANO_CAL_LOGE(tag, format, ...) chreLogNull(format, ##__VA_ARGS__)
+#define NANO_CAL_LOGD(tag, format, ...) CHRE_LOG_NULL(format, ##__VA_ARGS__)
+#define NANO_CAL_LOGI(tag, format, ...) CHRE_LOG_NULL(format, ##__VA_ARGS__)
+#define NANO_CAL_LOGW(tag, format, ...) CHRE_LOG_NULL(format, ##__VA_ARGS__)
+#define NANO_CAL_LOGE(tag, format, ...) CHRE_LOG_NULL(format, ##__VA_ARGS__)
#endif // NANO_SENSOR_CAL_DBG_ENABLED
} // namespace
@@ -54,11 +54,7 @@ void NanoSensorCal::Initialize(OnlineCalibrationThreeAxis *accel_cal,
accel_cal_ = accel_cal;
if (accel_cal_ != nullptr) {
if (accel_cal_->get_sensor_type() == SensorType::kAccelerometerMps2) {
- if (LoadAshCalibration(CHRE_SENSOR_TYPE_ACCELEROMETER, accel_cal_,
- kAccelTag)) {
- PrintCalibration(accel_cal_->GetSensorCalibration(),
- CalibrationTypeFlags::BIAS, kAccelTag);
- }
+ LoadAshCalibration(CHRE_SENSOR_TYPE_ACCELEROMETER, accel_cal_, kAccelTag);
NANO_CAL_LOGI(kAccelTag,
"Accelerometer runtime calibration initialized.");
} else {
@@ -70,12 +66,7 @@ void NanoSensorCal::Initialize(OnlineCalibrationThreeAxis *accel_cal,
gyro_cal_ = gyro_cal;
if (gyro_cal_ != nullptr) {
if (gyro_cal_->get_sensor_type() == SensorType::kGyroscopeRps) {
- if (LoadAshCalibration(CHRE_SENSOR_TYPE_GYROSCOPE, gyro_cal_, kGyroTag)) {
- PrintCalibration(
- gyro_cal_->GetSensorCalibration(),
- CalibrationTypeFlags::BIAS | CalibrationTypeFlags::OVER_TEMP,
- kGyroTag);
- }
+ LoadAshCalibration(CHRE_SENSOR_TYPE_GYROSCOPE, gyro_cal_, kGyroTag);
NANO_CAL_LOGI(kGyroTag, "Gyroscope runtime calibration initialized.");
} else {
gyro_cal_ = nullptr;
@@ -86,11 +77,7 @@ void NanoSensorCal::Initialize(OnlineCalibrationThreeAxis *accel_cal,
mag_cal_ = mag_cal;
if (mag_cal != nullptr) {
if (mag_cal->get_sensor_type() == SensorType::kMagnetometerUt) {
- if (LoadAshCalibration(CHRE_SENSOR_TYPE_GEOMAGNETIC_FIELD, mag_cal_,
- kMagTag)) {
- PrintCalibration(mag_cal_->GetSensorCalibration(),
- CalibrationTypeFlags::BIAS, kMagTag);
- }
+ LoadAshCalibration(CHRE_SENSOR_TYPE_GEOMAGNETIC_FIELD, mag_cal_, kMagTag);
NANO_CAL_LOGI(kMagTag, "Magnetometer runtime calibration initialized.");
} else {
mag_cal_ = nullptr;
@@ -188,8 +175,11 @@ void NanoSensorCal::ProcessSample(const SensorData &sample) {
sample.timestamp_nanos, gyro_notification_time_nanos_,
kNanoSensorCalMessageIntervalNanos)) {
gyro_notification_time_nanos_ = sample.timestamp_nanos;
- PrintCalibration(gyro_cal_->GetSensorCalibration(), gyro_cal_flags,
- kGyroTag);
+ PrintCalibration(
+ gyro_cal_->GetSensorCalibration(),
+ // Ensures that both bias and over-temp parameters are printed.
+ CalibrationTypeFlags::BIAS | CalibrationTypeFlags::OVER_TEMP,
+ kGyroTag);
}
}
}
@@ -217,7 +207,23 @@ bool NanoSensorCal::NotifyAshCalibration(
ash_cal_info.compMatrix[4] = 1.0f;
ash_cal_info.compMatrix[8] = 1.0f;
memcpy(ash_cal_info.bias, cal_data.offset, sizeof(ash_cal_info.bias));
- ash_cal_info.accuracy = ASH_CAL_ACCURACY_HIGH;
+
+ // Sets the appropriate calibration accuracy level.
+ switch (cal_data.calibration_quality.level) {
+ case online_calibration::CalibrationQualityLevel::HIGH_QUALITY:
+ ash_cal_info.accuracy = ASH_CAL_ACCURACY_HIGH;
+ break;
+
+ case online_calibration::CalibrationQualityLevel::MEDIUM_QUALITY:
+ ash_cal_info.accuracy = ASH_CAL_ACCURACY_MEDIUM;
+ break;
+
+ case online_calibration::CalibrationQualityLevel::LOW_QUALITY:
+ // FALLTHROUGH_INTENTIONAL.
+ default:
+ ash_cal_info.accuracy = ASH_CAL_ACCURACY_LOW;
+ break;
+ }
if (!ashSetCalibration(chreSensorType, &ash_cal_info)) {
NANO_CAL_LOGE(sensor_tag, "ASH failed to apply calibration update.");
@@ -307,56 +313,38 @@ bool NanoSensorCal::DetectRuntimeCalibration(uint8_t chreSensorType,
const char *sensor_tag,
CalibrationTypeFlags *flags,
ashCalParams *ash_cal_parameters) {
- // Analyzes calibration source flags to determine whether factory calibration
- // data was received. A valid factory calibration source will include at least
- // an offset.
- bool factory_cal_detected =
- ash_cal_parameters->offsetSource == ASH_CAL_PARAMS_SOURCE_NONE &&
+ // Analyzes calibration source flags to determine whether runtime
+ // calibration values have been loaded and may be used for initialization. A
+ // valid runtime calibration source will include at least an offset.
+
+ // Uses the ASH calibration source flags to set the appropriate
+ // CalibrationTypeFlags. These will be used to determine which values to copy
+ // from 'ash_cal_parameters' and provide to the calibration algorithms for
+ // initialization.
+ bool runtime_cal_detected = false;
+ if (ash_cal_parameters->offsetSource == ASH_CAL_PARAMS_SOURCE_RUNTIME &&
ash_cal_parameters->offsetTempCelsiusSource ==
- ASH_CAL_PARAMS_SOURCE_FACTORY;
+ ASH_CAL_PARAMS_SOURCE_RUNTIME) {
+ runtime_cal_detected = true;
+ *flags = CalibrationTypeFlags::BIAS;
+ }
- bool runtime_cal_detected = false;
- if (factory_cal_detected) {
- // Prints the retrieved factory calibration data.
- NANO_CAL_LOGI(sensor_tag, "Factory calibration detected.");
- PrintAshCalParams(*ash_cal_parameters, sensor_tag);
+ if (ash_cal_parameters->tempSensitivitySource ==
+ ASH_CAL_PARAMS_SOURCE_RUNTIME &&
+ ash_cal_parameters->tempInterceptSource ==
+ ASH_CAL_PARAMS_SOURCE_RUNTIME) {
+ *flags |= CalibrationTypeFlags::OVER_TEMP;
+ }
- // Since the factory calibration is applied lower in the sensor framework,
- // initialization using these parameters must be skipped to avoid the
- // possibility of double calibration. Returns 'false' to avoid further
- // initialization. Note, the runtime calibration algorithms dynamically
- // correct the residuals that the factory calibration doesn't or can't
- // account for (e.g., aging induced error charateristics).
- return false;
+ if (runtime_cal_detected) {
+ // Prints the retrieved runtime calibration data.
+ NANO_CAL_LOGI(sensor_tag, "Runtime calibration data detected.");
+ PrintAshCalParams(*ash_cal_parameters, sensor_tag);
} else {
- // Analyzes calibration source flags to determine whether runtime
- // calibration values have been loaded and may be used for initialization. A
- // valid runtime calibration source will include at least an offset.
-
- // Converts the ASH calibration source flags to CalibrationTypeFlags. These
- // will be used to determine which values to copy from 'ash_cal_parameters'
- // and provide to the calibration algorithms for initialization.
- if (ash_cal_parameters->offsetSource == ASH_CAL_PARAMS_SOURCE_RUNTIME &&
- ash_cal_parameters->offsetTempCelsiusSource ==
- ASH_CAL_PARAMS_SOURCE_RUNTIME) {
- runtime_cal_detected = true;
- *flags = CalibrationTypeFlags::BIAS;
- }
-
- if (ash_cal_parameters->tempSensitivitySource ==
- ASH_CAL_PARAMS_SOURCE_RUNTIME &&
- ash_cal_parameters->tempInterceptSource ==
- ASH_CAL_PARAMS_SOURCE_RUNTIME) {
- runtime_cal_detected = true;
- *flags |= CalibrationTypeFlags::OVER_TEMP;
- }
-
- if (!runtime_cal_detected) {
- // This is a warning (not an error) since the runtime algorithms will
- // function correctly with no recalled calibration values. They will
- // eventually trigger and update the system with valid calibration data.
- NANO_CAL_LOGW(sensor_tag, "No runtime offset calibration data found.");
- }
+ // This is a warning (not an error) since the runtime algorithms will
+ // function correctly with no recalled calibration values. They will
+ // eventually trigger and update the system with valid calibration data.
+ NANO_CAL_LOGW(sensor_tag, "No runtime offset calibration data found.");
}
return runtime_cal_detected;
@@ -365,26 +353,37 @@ bool NanoSensorCal::DetectRuntimeCalibration(uint8_t chreSensorType,
// Helper functions for logging calibration information.
void NanoSensorCal::PrintAshCalParams(const ashCalParams &cal_params,
const char *sensor_tag) {
- NANO_CAL_LOGI(sensor_tag, "Offset | Temperature [C]: %.6f, %.6f, %.6f | %.2f",
- cal_params.offset[0], cal_params.offset[1],
- cal_params.offset[2], cal_params.offsetTempCelsius);
-
- NANO_CAL_LOGI(sensor_tag, "Temp Sensitivity [units/C]: %.6f, %.6f, %.6f",
- cal_params.tempSensitivity[0], cal_params.tempSensitivity[1],
- cal_params.tempSensitivity[2]);
-
- NANO_CAL_LOGI(sensor_tag, "Temp Intercept [units]: %.6f, %.6f, %.6f",
- cal_params.tempIntercept[0], cal_params.tempIntercept[1],
- cal_params.tempIntercept[2]);
-
- NANO_CAL_LOGI(sensor_tag, "Scale Factor: %.6f, %.6f, %.6f",
- cal_params.scaleFactor[0], cal_params.scaleFactor[1],
- cal_params.scaleFactor[2]);
-
- NANO_CAL_LOGI(sensor_tag,
- "Cross-Axis in [yx, zx, zy] order: %.6f, %.6f, %.6f",
- cal_params.crossAxis[0], cal_params.crossAxis[1],
- cal_params.crossAxis[2]);
+ if (cal_params.offsetSource == ASH_CAL_PARAMS_SOURCE_RUNTIME) {
+ NANO_CAL_LOGI(sensor_tag,
+ "Offset | Temperature [C]: %.6f, %.6f, %.6f | %.2f",
+ cal_params.offset[0], cal_params.offset[1],
+ cal_params.offset[2], cal_params.offsetTempCelsius);
+ }
+
+ if (cal_params.tempSensitivitySource == ASH_CAL_PARAMS_SOURCE_RUNTIME) {
+ NANO_CAL_LOGI(sensor_tag, "Temp Sensitivity [units/C]: %.6f, %.6f, %.6f",
+ cal_params.tempSensitivity[0], cal_params.tempSensitivity[1],
+ cal_params.tempSensitivity[2]);
+ }
+
+ if (cal_params.tempInterceptSource == ASH_CAL_PARAMS_SOURCE_RUNTIME) {
+ NANO_CAL_LOGI(sensor_tag, "Temp Intercept [units]: %.6f, %.6f, %.6f",
+ cal_params.tempIntercept[0], cal_params.tempIntercept[1],
+ cal_params.tempIntercept[2]);
+ }
+
+ if (cal_params.scaleFactorSource == ASH_CAL_PARAMS_SOURCE_RUNTIME) {
+ NANO_CAL_LOGI(sensor_tag, "Scale Factor: %.6f, %.6f, %.6f",
+ cal_params.scaleFactor[0], cal_params.scaleFactor[1],
+ cal_params.scaleFactor[2]);
+ }
+
+ if (cal_params.crossAxisSource == ASH_CAL_PARAMS_SOURCE_RUNTIME) {
+ NANO_CAL_LOGI(sensor_tag,
+ "Cross-Axis in [yx, zx, zy] order: %.6f, %.6f, %.6f",
+ cal_params.crossAxis[0], cal_params.crossAxis[1],
+ cal_params.crossAxis[2]);
+ }
}
void NanoSensorCal::PrintCalibration(const CalibrationDataThreeAxis &cal_data,
diff --git a/firmware/os/algos/calibration/nano_calibration/nano_calibration.h b/firmware/os/algos/calibration/nano_calibration/nano_calibration.h
index 59850545..6b19f7ef 100644
--- a/firmware/os/algos/calibration/nano_calibration/nano_calibration.h
+++ b/firmware/os/algos/calibration/nano_calibration/nano_calibration.h
@@ -81,8 +81,8 @@ class NanoSensorCal {
NanoSensorCal() = default;
// Sets the sensor calibration object pointers and initializes the algorithms
- // using factory or runtime values recalled using Android Sensor Hub (ASH). A
- // nullptr may be passed in to disable a particular sensor calibration.
+ // using runtime values recalled using Android Sensor Hub (ASH). A nullptr may
+ // be passed in to disable a particular sensor calibration.
void Initialize(OnlineCalibrationThreeAxis *accel_cal,
OnlineCalibrationThreeAxis *gyro_cal,
OnlineCalibrationThreeAxis *mag_cal);
@@ -99,10 +99,10 @@ class NanoSensorCal {
// Passes sensor data to the runtime calibration algorithms.
void ProcessSample(const online_calibration::SensorData &sample);
- // Loads factory and runtime calibration data using the Android Sensor Hub
- // API. Returns 'true' when runtime calibration values were successfully
- // recalled and used for algorithm initialization. 'sensor_tag' is a string
- // that identifies a sensor-specific identifier for log meassages.
+ // Loads runtime calibration data using the Android Sensor Hub API. Returns
+ // 'true' when runtime calibration values were successfully recalled and used
+ // for algorithm initialization. 'sensor_tag' is a string that identifies a
+ // sensor-specific identifier for log meassages.
bool LoadAshCalibration(uint8_t chreSensorType,
OnlineCalibrationThreeAxis *online_cal,
const char *sensor_tag);
diff --git a/firmware/os/algos/calibration/online_calibration/accelerometer/accel_offset_cal/accel_offset_cal.cc b/firmware/os/algos/calibration/online_calibration/accelerometer/accel_offset_cal/accel_offset_cal.cc
index 3958ae85..e9def4e6 100644
--- a/firmware/os/algos/calibration/online_calibration/accelerometer/accel_offset_cal/accel_offset_cal.cc
+++ b/firmware/os/algos/calibration/online_calibration/accelerometer/accel_offset_cal/accel_offset_cal.cc
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
#include "calibration/online_calibration/accelerometer/accel_offset_cal/accel_offset_cal.h"
#include "calibration/util/cal_log.h"
@@ -40,6 +56,8 @@ CalibrationTypeFlags AccelOffsetCal::SetMeasurement(const SensorData& sample) {
accelCalUpdateBias(&accel_cal_, &cal_data_.offset[0], &cal_data_.offset[1],
&cal_data_.offset[2]);
+ cal_data_.calibration_quality.level = CalibrationQualityLevel::HIGH_QUALITY;
+ cal_data_.calibration_quality.value = kUndeterminedCalibrationQuality;
cal_data_.offset_temp_celsius = temperature_celsius_;
cal_data_.cal_update_time_nanos = sample.timestamp_nanos;
cal_update_polling_flags_ = CalibrationTypeFlags::BIAS;
@@ -65,6 +83,10 @@ bool AccelOffsetCal::SetInitialCalibration(
// Sync's all initial calibration data.
cal_data_ = input_cal_data;
+ // Sets the calibration quality.
+ cal_data_.calibration_quality.level = CalibrationQualityLevel::LOW_QUALITY;
+ cal_data_.calibration_quality.value = kUndeterminedCalibrationQuality;
+
return true;
}
diff --git a/firmware/os/algos/calibration/online_calibration/accelerometer/accel_offset_cal/accel_offset_cal.h b/firmware/os/algos/calibration/online_calibration/accelerometer/accel_offset_cal/accel_offset_cal.h
index d2ec494c..0256495a 100644
--- a/firmware/os/algos/calibration/online_calibration/accelerometer/accel_offset_cal/accel_offset_cal.h
+++ b/firmware/os/algos/calibration/online_calibration/accelerometer/accel_offset_cal/accel_offset_cal.h
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
#ifndef LOCATION_LBS_CONTEXTHUB_NANOAPPS_CALIBRATION_ONLINE_CALIBRATION_ACCELEROMETER_ACCEL_OFFSET_CAL_ACCEL_OFFSET_CAL_H_
#define LOCATION_LBS_CONTEXTHUB_NANOAPPS_CALIBRATION_ONLINE_CALIBRATION_ACCELEROMETER_ACCEL_OFFSET_CAL_ACCEL_OFFSET_CAL_H_
@@ -11,6 +27,17 @@ namespace online_calibration {
/*
* This class is a wrapper for accelerometer offset calibration.
+ *
+ * NOTE: Calibration quality reporting (quantitative metric is not used):
+ * Initialize --> CalibrationQualityLevel::UNDETERMINED
+ * CalibrationQuality.value =
+ * kUndeterminedCalibrationQuality
+ * SetInitialCalibration --> CalibrationQualityLevel::LOW_QUALITY
+ * CalibrationQuality.value =
+ * kUndeterminedCalibrationQuality
+ * New Calibration Update --> CalibrationQualityLevel::HIGH_QUALITY
+ * CalibrationQuality.value =
+ * kUndeterminedCalibrationQuality
*/
class AccelOffsetCal final
: public OnlineCalibration<CalibrationDataThreeAxis> {
diff --git a/firmware/os/algos/calibration/online_calibration/common_data/calibration_callback.h b/firmware/os/algos/calibration/online_calibration/common_data/calibration_callback.h
index 96c061f8..62bc443d 100644
--- a/firmware/os/algos/calibration/online_calibration/common_data/calibration_callback.h
+++ b/firmware/os/algos/calibration/online_calibration/common_data/calibration_callback.h
@@ -1,4 +1,20 @@
/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
* This module provides the callback functionality employed by the online sensor
* calibration algorithms.
*/
diff --git a/firmware/os/algos/calibration/online_calibration/common_data/calibration_data.cc b/firmware/os/algos/calibration/online_calibration/common_data/calibration_data.cc
index 23ebe4fa..8f1470a8 100644
--- a/firmware/os/algos/calibration/online_calibration/common_data/calibration_data.cc
+++ b/firmware/os/algos/calibration/online_calibration/common_data/calibration_data.cc
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
#include "calibration/online_calibration/common_data/calibration_data.h"
namespace online_calibration {
diff --git a/firmware/os/algos/calibration/online_calibration/common_data/calibration_data.h b/firmware/os/algos/calibration/online_calibration/common_data/calibration_data.h
index 8b95ef7f..0404936b 100644
--- a/firmware/os/algos/calibration/online_calibration/common_data/calibration_data.h
+++ b/firmware/os/algos/calibration/online_calibration/common_data/calibration_data.h
@@ -1,4 +1,20 @@
/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
* This module provides the component definitions used to represent sensor
* calibration data, labeled flags/enumerators, and the callback functionality
* employed by the online sensor calibration algorithms.
@@ -11,6 +27,7 @@
#include <string.h>
#include <sys/types.h>
+#include "calibration/online_calibration/common_data/calibration_quality.h"
#include "calibration/online_calibration/common_data/sensor_data.h"
#include "calibration/over_temp/over_temp_model.h"
@@ -21,14 +38,16 @@ namespace online_calibration {
* calibration update.
*
* [Bit Flag] | [Affected Sensor Calibration Value]
- * BIAS - Quasi-static non-zero sensor output (offset), given conditions
- * where the sensor should ideally output zero. Includes
- * corrections for over-temperature compensation.
- * SCALE_FACTOR - Sensor axis scaling (ideally unity).
- * CROSS_AXIS - Output sensitivity due to variations of perpendicular sensing
- * axes (ideally zero).
- * OVER_TEMP - Model parameters that capture variations in sensor behavior
- * with temperature (e.g., linear bias sensitivity model).
+ * BIAS - Quasi-static non-zero sensor output (offset), given
+ * conditions where the sensor should ideally output zero.
+ * Includes corrections for over-temperature compensation.
+ * SCALE_FACTOR - Sensor axis scaling (ideally unity).
+ * CROSS_AXIS - Output sensitivity due to variations of perpendicular
+ * sensing axes (ideally zero).
+ * OVER_TEMP - Model parameters that capture variations in sensor
+ * behavior with temperature (e.g., linear bias sensitivity
+ * model).
+ * QUALITY_DEGRADED - Indicates a degradation in calibration quality.
*/
enum class CalibrationTypeFlags : uint8_t {
NONE = 0x00,
@@ -36,6 +55,7 @@ enum class CalibrationTypeFlags : uint8_t {
SCALE_FACTOR = 0x02,
CROSS_AXIS = 0x04,
OVER_TEMP = 0x08,
+ QUALITY_DEGRADED = 0x10,
ALL = 0xFF
};
@@ -102,11 +122,16 @@ struct CalibrationDataThreeAxis {
// The cross-axis factors in order: [0=yx, 1=zx, 2=zy].
float cross_axis[3];
+ // Metrics used for the reported calibration accuracy. The behavior and
+ // definition depends on the sensor calibration type. See the calibration
+ // algorithm documentation for details.
+ CalibrationQuality calibration_quality;
+
// Indicates the type of sensing device being calibrated.
SensorType type = SensorType::kUndefined;
// Optional pointer to an array of over-temperature model data (null when not
- // used). For initialization, populating a model dataset will take precendence
+ // used). For initialization, populating a model dataset will take precedence
// over the linear model parameters provided in the calibration data.
OverTempModelThreeAxis* otc_model_data = nullptr;
int16_t num_model_pts = 0;
@@ -115,6 +140,7 @@ struct CalibrationDataThreeAxis {
// reference values where no calibration correction would be applied if used.
void reset() {
otc_model_data = nullptr;
+ calibration_quality.reset();
offset_temp_celsius = 0.0f;
scale_factor[0] = 1.0f;
scale_factor[1] = 1.0f;
@@ -168,11 +194,16 @@ struct CalibrationDataSingleAxis {
// The sensor's scale factor.
float scale_factor;
+ // Metrics used for the reported calibration accuracy. The behavior and
+ // definition depends on the sensor calibration type. See the calibration
+ // algorithm documentation for details.
+ CalibrationQuality calibration_quality;
+
// Indicates the type of sensing device being calibrated.
SensorType type = SensorType::kUndefined;
// Optional pointer to an array of over-temperature model data (null when not
- // used). For initialization, populating a model dataset will take precendence
+ // used). For initialization, populating a model dataset will take precedence
// over the linear model parameters provided in the calibration data.
OverTempModelSingleAxis* otc_model_data = nullptr;
int16_t num_model_pts = 0;
@@ -181,6 +212,7 @@ struct CalibrationDataSingleAxis {
// reference values where no calibration correction would be applied if used.
void reset() {
otc_model_data = nullptr;
+ calibration_quality.reset();
scale_factor = 1.0f;
offset_temp_celsius = 0.0f;
offset = 0.0f;
diff --git a/firmware/os/algos/calibration/online_calibration/common_data/calibration_quality.h b/firmware/os/algos/calibration/online_calibration/common_data/calibration_quality.h
new file mode 100644
index 00000000..d6475c78
--- /dev/null
+++ b/firmware/os/algos/calibration/online_calibration/common_data/calibration_quality.h
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * This module provides quality definitions that represent the accuracy
+ * associated with calibration data. This information may be used to affect how
+ * a system uses available sensor calibration data.
+ */
+
+#ifndef LOCATION_LBS_CONTEXTHUB_NANOAPPS_CALIBRATION_ONLINE_CALIBRATION_COMMON_DATA_CALIBRATION_QUALITY_H_
+#define LOCATION_LBS_CONTEXTHUB_NANOAPPS_CALIBRATION_ONLINE_CALIBRATION_COMMON_DATA_CALIBRATION_QUALITY_H_
+
+#include <float.h>
+#include <stdint.h>
+
+namespace online_calibration {
+
+/*
+ * In general, calibration quality values may be thought of in terms of
+ * something akin to an error standard deviation. That is, it's a non-negative
+ * value where lower values imply higher calibration quality, and larger values
+ * indicate poorer quality. However, the units and numerical interpretation is
+ * ultimately dictated by the sensor type and calibration algorithm. Consult the
+ * calibration code implementation for the actual calibration quality metric
+ * details.
+ */
+
+/*
+ * Bitmask used to provide a qualitative ranking of the calibration data's
+ * accuracy. Many systems use this sort of interpretation for calibration
+ * quality (e.g., Android).
+ *
+ * [Bit Flag] | [Qualitative Calibration Quality]
+ * UNDETERMINED - Calibration quality has not yet been determined (e.g., a
+ * calibration hasn't occurred, or a metric hasn't been
+ * established).
+ * LOW_QUALITY - Sensor calibration is needed. System properties have
+ * changed that may have affected the applicability of the
+ * current calibration (e.g., calibration data is old, anomaly
+ * detected, etc.).
+ * MEDIUM_QUALITY - The reported sensor calibration has an average level of
+ * accuracy, updated calibration may improve the readings.
+ * HIGH_QUALITY - The reported calibration has maximal accuracy.
+ */
+enum class CalibrationQualityLevel : uint8_t {
+ UNDETERMINED = 0x00,
+ LOW_QUALITY = 0x01,
+ MEDIUM_QUALITY = 0x02,
+ HIGH_QUALITY = 0x04,
+};
+
+// Sets the calibration quality value when this metric is either not
+// implemented, or has not yet been determined (e.g., a calibration hasn't
+// occurred).
+constexpr float kUndeterminedCalibrationQuality = -1.0f;
+
+/*
+ * Calibration quality structure that contains a quantitative (float) and
+ * qualitative (enum) measure of a sensor's calibration accuracy. Both entries
+ * should be co-defined by the algorithm providing the calibration update. The
+ * enum sets the qualitative interpretation of the float value, this is often
+ * used in systems (Android, etc.) to label quality and affect the use of the
+ * calibration data.
+ */
+struct CalibrationQuality {
+ // Provides a qualitative measure for sensor calibration accuracy.
+ CalibrationQualityLevel level = CalibrationQualityLevel::UNDETERMINED;
+
+ // Quantitative metric for the reported calibration accuracy. The behavior and
+ // definition depends on the sensor calibration type. See the calibration
+ // algorithm documentation for details.
+ float value = kUndeterminedCalibrationQuality;
+
+ // Helper function that resets the calibration quality to an initial state.
+ void reset() {
+ level = CalibrationQualityLevel::UNDETERMINED;
+ value = kUndeterminedCalibrationQuality;
+ }
+};
+
+} // namespace online_calibration
+
+#endif // LOCATION_LBS_CONTEXTHUB_NANOAPPS_CALIBRATION_ONLINE_CALIBRATION_COMMON_DATA_CALIBRATION_QUALITY_H_
diff --git a/firmware/os/algos/calibration/online_calibration/common_data/online_calibration.h b/firmware/os/algos/calibration/online_calibration/common_data/online_calibration.h
index bf348ac2..c8930652 100644
--- a/firmware/os/algos/calibration/online_calibration/common_data/online_calibration.h
+++ b/firmware/os/algos/calibration/online_calibration/common_data/online_calibration.h
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
#ifndef LOCATION_LBS_CONTEXTHUB_NANOAPPS_CALIBRATION_ONLINE_CALIBRATION_COMMON_DATA_ONLINE_CALIBRATION_H_
#define LOCATION_LBS_CONTEXTHUB_NANOAPPS_CALIBRATION_ONLINE_CALIBRATION_COMMON_DATA_ONLINE_CALIBRATION_H_
diff --git a/firmware/os/algos/calibration/online_calibration/common_data/sensor_data.h b/firmware/os/algos/calibration/online_calibration/common_data/sensor_data.h
index 9849ad2c..915554f3 100644
--- a/firmware/os/algos/calibration/online_calibration/common_data/sensor_data.h
+++ b/firmware/os/algos/calibration/online_calibration/common_data/sensor_data.h
@@ -1,4 +1,20 @@
/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
* This module provides the component definitions used to represent sensor
* data employed by the online sensor calibration algorithms.
*/
diff --git a/firmware/os/algos/calibration/online_calibration/gyroscope/gyro_offset_over_temp_cal/gyro_offset_over_temp_cal.cc b/firmware/os/algos/calibration/online_calibration/gyroscope/gyro_offset_over_temp_cal/gyro_offset_over_temp_cal.cc
index 67ea4974..26eef573 100644
--- a/firmware/os/algos/calibration/online_calibration/gyroscope/gyro_offset_over_temp_cal/gyro_offset_over_temp_cal.cc
+++ b/firmware/os/algos/calibration/online_calibration/gyroscope/gyro_offset_over_temp_cal/gyro_offset_over_temp_cal.cc
@@ -1,9 +1,29 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
#include "calibration/online_calibration/gyroscope/gyro_offset_over_temp_cal/gyro_offset_over_temp_cal.h"
#include "calibration/util/cal_log.h"
namespace online_calibration {
+// Estimated upper bounds on gyro offset error (i.e., 3-sigma values).
+constexpr float GyroOffsetOtcCal::kMediumQualityRps;
+constexpr float GyroOffsetOtcCal::kHighQualityRps;
+
void GyroOffsetOtcCal::Initialize(const GyroCalParameters& gyro_cal_parameters,
const OverTempCalParameters& otc_parameters) {
gyroCalInit(&gyro_cal_, &gyro_cal_parameters);
@@ -87,9 +107,11 @@ CalibrationTypeFlags GyroOffsetOtcCal::SetMeasurement(
cal_data_.temp_sensitivity, cal_data_.temp_intercept);
}
- // Sets the new-calibration polling flag, and notifies a calibration callback
- // listener of the new update.
+ // Sets the new calibration quality, polling flag, and notifies a calibration
+ // callback listener of the new update.
if (new_otc_model_update || new_otc_offset) {
+ cal_data_.calibration_quality.level = CalibrationQualityLevel::HIGH_QUALITY;
+ cal_data_.calibration_quality.value = kHighQualityRps;
cal_update_polling_flags_ |= cal_update_callback_flags;
OnNotifyCalibrationUpdate(cal_update_callback_flags);
}
@@ -128,6 +150,10 @@ bool GyroOffsetOtcCal::SetInitialCalibration(
cal_data_.temp_sensitivity, cal_data_.temp_intercept,
/*jump_start_model=*/false);
+ // Sets the calibration quality.
+ cal_data_.calibration_quality.level = CalibrationQualityLevel::MEDIUM_QUALITY;
+ cal_data_.calibration_quality.value = kMediumQualityRps;
+
const bool load_new_model_dataset =
(input_cal_data.otc_model_data != nullptr &&
input_cal_data.num_model_pts > 0);
diff --git a/firmware/os/algos/calibration/online_calibration/gyroscope/gyro_offset_over_temp_cal/gyro_offset_over_temp_cal.h b/firmware/os/algos/calibration/online_calibration/gyroscope/gyro_offset_over_temp_cal/gyro_offset_over_temp_cal.h
index 74ba9828..e21007b3 100644
--- a/firmware/os/algos/calibration/online_calibration/gyroscope/gyro_offset_over_temp_cal/gyro_offset_over_temp_cal.h
+++ b/firmware/os/algos/calibration/online_calibration/gyroscope/gyro_offset_over_temp_cal/gyro_offset_over_temp_cal.h
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
#ifndef LOCATION_LBS_CONTEXTHUB_NANOAPPS_CALIBRATION_ONLINE_CALIBRATION_GYROSCOPE_GYRO_OFFSET_OVER_TEMP_CAL_GYRO_OFFSET_OVER_TEMP_CAL_H_
#define LOCATION_LBS_CONTEXTHUB_NANOAPPS_CALIBRATION_ONLINE_CALIBRATION_GYROSCOPE_GYRO_OFFSET_OVER_TEMP_CAL_GYRO_OFFSET_OVER_TEMP_CAL_H_
@@ -13,10 +29,23 @@ namespace online_calibration {
/*
* This class is a wrapper for the gyroscope offset calibration with
* over-temperature compensation (OTC).
+ *
+ * NOTE: Calibration quality reporting:
+ * Initialize --> CalibrationQualityLevel::UNDETERMINED
+ * CalibrationQuality.value =
+ * kUndeterminedCalibrationQuality
+ * SetInitialCalibration --> CalibrationQualityLevel::MEDIUM_QUALITY
+ * CalibrationQuality.value = kMediumQualityRps
+ * New Calibration Update --> CalibrationQualityLevel::HIGH_QUALITY
+ * CalibrationQuality.value = kHighQualityRps
*/
class GyroOffsetOtcCal final
: public OnlineCalibration<CalibrationDataThreeAxis> {
public:
+ // Estimated upper bounds on gyro offset error (i.e., 3-sigma values).
+ static constexpr float kMediumQualityRps = 5.23599e-3f; // 300 mDPS
+ static constexpr float kHighQualityRps = 1.04720e-3f; // 60 mDPS
+
// Default constructor.
GyroOffsetOtcCal() = default;
diff --git a/firmware/os/algos/calibration/online_calibration/magnetometer/mag_diverse_cal/mag_diverse_cal.cc b/firmware/os/algos/calibration/online_calibration/magnetometer/mag_diverse_cal/mag_diverse_cal.cc
index a963dcd5..a4b4dfd7 100644
--- a/firmware/os/algos/calibration/online_calibration/magnetometer/mag_diverse_cal/mag_diverse_cal.cc
+++ b/firmware/os/algos/calibration/online_calibration/magnetometer/mag_diverse_cal/mag_diverse_cal.cc
@@ -1,9 +1,29 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
#include "calibration/online_calibration/magnetometer/mag_diverse_cal/mag_diverse_cal.h"
#include "calibration/util/cal_log.h"
namespace online_calibration {
+// Empirically estimated upper bounds on offset error.
+constexpr float MagDiverseCal::kLowQualityUt;
+constexpr float MagDiverseCal::kHighQualityUt;
+
void MagDiverseCal::Initialize(
const MagCalParameters& mag_cal_parameters,
const DiversityCheckerParameters& diversity_parameters) {
@@ -36,6 +56,8 @@ CalibrationTypeFlags MagDiverseCal::SetMeasurement(const SensorData& sample) {
magCalGetBias(&mag_cal_, &cal_data_.offset[0], &cal_data_.offset[1],
&cal_data_.offset[2]);
+ cal_data_.calibration_quality.level = CalibrationQualityLevel::HIGH_QUALITY;
+ cal_data_.calibration_quality.value = kHighQualityUt;
cal_data_.offset_temp_celsius = temperature_celsius_;
cal_data_.cal_update_time_nanos = sample.timestamp_nanos;
cal_update_polling_flags_ = CalibrationTypeFlags::BIAS;
@@ -62,6 +84,10 @@ bool MagDiverseCal::SetInitialCalibration(
// Sync's all initial calibration data.
cal_data_ = input_cal_data;
+ // Sets the calibration quality.
+ cal_data_.calibration_quality.level = CalibrationQualityLevel::LOW_QUALITY;
+ cal_data_.calibration_quality.value = kLowQualityUt;
+
return true;
}
diff --git a/firmware/os/algos/calibration/online_calibration/magnetometer/mag_diverse_cal/mag_diverse_cal.h b/firmware/os/algos/calibration/online_calibration/magnetometer/mag_diverse_cal/mag_diverse_cal.h
index 23ac3c49..212ffeb9 100644
--- a/firmware/os/algos/calibration/online_calibration/magnetometer/mag_diverse_cal/mag_diverse_cal.h
+++ b/firmware/os/algos/calibration/online_calibration/magnetometer/mag_diverse_cal/mag_diverse_cal.h
@@ -1,8 +1,24 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
#ifndef LOCATION_LBS_CONTEXTHUB_NANOAPPS_CALIBRATION_ONLINE_CALIBRATION_MAGNETOMETER_MAG_DIVERSE_CAL_MAG_DIVERSE_CAL_H_
#define LOCATION_LBS_CONTEXTHUB_NANOAPPS_CALIBRATION_ONLINE_CALIBRATION_MAGNETOMETER_MAG_DIVERSE_CAL_MAG_DIVERSE_CAL_H_
#include "calibration/diversity_checker/diversity_checker.h"
-#include "calibration/magnetometer/mag_cal.h"
+#include "calibration/magnetometer/mag_cal/mag_cal.h"
#include "calibration/online_calibration/common_data/calibration_callback.h"
#include "calibration/online_calibration/common_data/calibration_data.h"
#include "calibration/online_calibration/common_data/online_calibration.h"
@@ -13,9 +29,22 @@ namespace online_calibration {
/*
* This class is a wrapper for the magnetometer offset calibration with
* diversity checking.
+ *
+ * NOTE: Calibration quality reporting:
+ * Initialize --> CalibrationQualityLevel::UNDETERMINED
+ * CalibrationQuality.value =
+ * kUndeterminedCalibrationQuality
+ * SetInitialCalibration --> CalibrationQualityLevel::LOW_QUALITY
+ * CalibrationQuality.value = kLowQualityUt
+ * New Calibration Update --> CalibrationQualityLevel::HIGH_QUALITY
+ * CalibrationQuality.value = kHighQualityUt
*/
class MagDiverseCal final : public OnlineCalibration<CalibrationDataThreeAxis> {
public:
+ // Empirically estimated upper bounds on offset error.
+ static constexpr float kLowQualityUt = 1000.0f; // Units of micro Tesla
+ static constexpr float kHighQualityUt = 5.0f; // Units of micro Tesla
+
MagDiverseCal() = default;
// Creates an MagDiverseCal with specified algorithm parameters.
diff --git a/firmware/os/algos/calibration/over_temp/over_temp_cal.c b/firmware/os/algos/calibration/over_temp/over_temp_cal.c
index 908d383a..6b64cb8f 100644
--- a/firmware/os/algos/calibration/over_temp/over_temp_cal.c
+++ b/firmware/os/algos/calibration/over_temp/over_temp_cal.c
@@ -17,6 +17,7 @@
#include "calibration/over_temp/over_temp_cal.h"
#include <float.h>
+#include <inttypes.h>
#include <math.h>
#include <string.h>
@@ -582,13 +583,12 @@ void overTempCalUpdateSensorEstimate(struct OverTempCal *over_temp_cal,
CAL_DEBUG_LOG(
over_temp_cal->otc_debug_tag,
"Offset|Temperature|Time [%s|C|nsec]: " CAL_FORMAT_3DIGITS_TRIPLET
- ", " CAL_FORMAT_3DIGITS ", %llu",
+ ", " CAL_FORMAT_3DIGITS ", %" PRIu64,
over_temp_cal->otc_unit_tag,
CAL_ENCODE_FLOAT(offset[0] * over_temp_cal->otc_unit_conversion, 3),
CAL_ENCODE_FLOAT(offset[1] * over_temp_cal->otc_unit_conversion, 3),
CAL_ENCODE_FLOAT(offset[2] * over_temp_cal->otc_unit_conversion, 3),
- CAL_ENCODE_FLOAT(temperature_celsius, 3),
- (unsigned long long int)timestamp_nanos);
+ CAL_ENCODE_FLOAT(temperature_celsius, 3), timestamp_nanos);
#endif // OVERTEMPCAL_DBG_ENABLED
return; // Outlier detected: skips adding this offset to the model.
@@ -699,9 +699,9 @@ void overTempCalSetTemperature(struct OverTempCal *over_temp_cal,
// Prints out temperature and the current timestamp.
createDebugTag(over_temp_cal, ":TEMP]");
CAL_DEBUG_LOG(over_temp_cal->otc_debug_tag,
- "Temperature|Time [C|nsec] = " CAL_FORMAT_3DIGITS ", %llu",
- CAL_ENCODE_FLOAT(temperature_celsius, 3),
- (unsigned long long int)timestamp_nanos);
+ "Temperature|Time [C|nsec] = " CAL_FORMAT_3DIGITS
+ ", %" PRIu64,
+ CAL_ENCODE_FLOAT(temperature_celsius, 3), timestamp_nanos);
}
#endif // OVERTEMPCAL_DBG_LOG_TEMP
#endif // OVERTEMPCAL_DBG_ENABLED
@@ -969,16 +969,23 @@ void updateCalOffset(struct OverTempCal *over_temp_cal,
// To properly evaluate the logic paths that use the latest and nearest offset
// data below, the current age of the nearest and latest offset estimates are
// computed.
- const uint64_t latest_offset_age_nanos =
- (over_temp_cal->latest_offset != NULL)
- ? over_temp_cal->latest_offset->offset_age_nanos + timestamp_nanos -
- over_temp_cal->last_age_update_nanos
- : 0;
- const uint64_t nearest_offset_age_nanos =
- (over_temp_cal->nearest_offset != NULL)
- ? over_temp_cal->nearest_offset->offset_age_nanos + timestamp_nanos -
- over_temp_cal->last_age_update_nanos
- : 0;
+ uint64_t latest_offset_age_nanos = 0;
+ if (over_temp_cal->latest_offset != NULL) {
+ latest_offset_age_nanos =
+ (over_temp_cal->last_age_update_nanos < timestamp_nanos)
+ ? over_temp_cal->latest_offset->offset_age_nanos +
+ timestamp_nanos - over_temp_cal->last_age_update_nanos
+ : over_temp_cal->latest_offset->offset_age_nanos;
+ }
+
+ uint64_t nearest_offset_age_nanos = 0;
+ if (over_temp_cal->nearest_offset != NULL) {
+ nearest_offset_age_nanos =
+ (over_temp_cal->last_age_update_nanos < timestamp_nanos)
+ ? over_temp_cal->nearest_offset->offset_age_nanos +
+ timestamp_nanos - over_temp_cal->last_age_update_nanos
+ : over_temp_cal->nearest_offset->offset_age_nanos;
+ }
// True when the latest offset estimate will be used to compute a sensor
// offset calibration estimate.
@@ -1159,14 +1166,14 @@ void computeModelUpdate(struct OverTempCal *over_temp_cal,
CAL_DEBUG_LOG(
over_temp_cal->otc_debug_tag,
"%c-Axis Parameters|Time [%s/C|%s|nsec]: " CAL_FORMAT_3DIGITS
- ", " CAL_FORMAT_3DIGITS ", %llu",
+ ", " CAL_FORMAT_3DIGITS ", %" PRIu64,
kDebugAxisLabel[i], over_temp_cal->otc_unit_tag,
over_temp_cal->otc_unit_tag,
CAL_ENCODE_FLOAT(
temp_sensitivity[i] * over_temp_cal->otc_unit_conversion, 3),
CAL_ENCODE_FLOAT(
sensor_intercept[i] * over_temp_cal->otc_unit_conversion, 3),
- (unsigned long long int)timestamp_nanos);
+ timestamp_nanos);
#endif // OVERTEMPCAL_DBG_ENABLED
}
}
@@ -1251,7 +1258,7 @@ bool removeModelDataByIndex(struct OverTempCal *over_temp_cal,
CAL_DEBUG_LOG(
over_temp_cal->otc_debug_tag,
"Offset|Temp|Age [%s|C|nsec]: " CAL_FORMAT_3DIGITS_TRIPLET
- ", " CAL_FORMAT_3DIGITS ", %llu",
+ ", " CAL_FORMAT_3DIGITS ", %" PRIu64,
over_temp_cal->otc_unit_tag,
CAL_ENCODE_FLOAT(over_temp_cal->model_data[model_index].offset[0] *
over_temp_cal->otc_unit_conversion,
@@ -1264,8 +1271,7 @@ bool removeModelDataByIndex(struct OverTempCal *over_temp_cal,
3),
CAL_ENCODE_FLOAT(
over_temp_cal->model_data[model_index].offset_temp_celsius, 3),
- (unsigned long long int)over_temp_cal->model_data[model_index]
- .offset_age_nanos);
+ over_temp_cal->model_data[model_index].offset_age_nanos);
#endif // OVERTEMPCAL_DBG_ENABLED
// Remove the model data at 'model_index'.
@@ -1327,8 +1333,8 @@ bool jumpStartModelData(struct OverTempCal *over_temp_cal) {
createDebugTag(over_temp_cal, ":INIT]");
if (over_temp_cal->num_model_pts > 0) {
CAL_DEBUG_LOG(over_temp_cal->otc_debug_tag,
- "Model Jump-Start: #Points = %lu.",
- (unsigned long int)over_temp_cal->num_model_pts);
+ "Model Jump-Start: #Points = %zu.",
+ over_temp_cal->num_model_pts);
}
#endif // OVERTEMPCAL_DBG_ENABLED
@@ -1478,6 +1484,11 @@ float evaluateWeightingFunction(const struct OverTempCal *over_temp_cal,
void modelDataSetAgeUpdate(struct OverTempCal *over_temp_cal,
uint64_t timestamp_nanos) {
ASSERT_NOT_NULL(over_temp_cal);
+ if (over_temp_cal->last_age_update_nanos >= timestamp_nanos) {
+ // Age updates must be monotonic.
+ return;
+ }
+
uint64_t age_increment_nanos =
timestamp_nanos - over_temp_cal->last_age_update_nanos;
@@ -1589,10 +1600,9 @@ void overTempCalDebugPrint(struct OverTempCal *over_temp_cal,
// Prints out the latest offset estimate (input data).
CAL_DEBUG_LOG(
over_temp_cal->otc_debug_tag,
- "Cal#|Offset|Temp|Age [%s|C|nsec]: %lu, " CAL_FORMAT_3DIGITS_TRIPLET
- ", " CAL_FORMAT_3DIGITS ", %llu",
- over_temp_cal->otc_unit_tag,
- (unsigned long int)over_temp_cal->debug_num_estimates,
+ "Cal#|Offset|Temp|Age [%s|C|nsec]: %zu, " CAL_FORMAT_3DIGITS_TRIPLET
+ ", " CAL_FORMAT_3DIGITS ", %" PRIu64,
+ over_temp_cal->otc_unit_tag, over_temp_cal->debug_num_estimates,
CAL_ENCODE_FLOAT(
over_temp_cal->debug_overtempcal.latest_offset.offset[0] *
over_temp_cal->otc_unit_conversion,
@@ -1608,8 +1618,7 @@ void overTempCalDebugPrint(struct OverTempCal *over_temp_cal,
CAL_ENCODE_FLOAT(over_temp_cal->debug_overtempcal.latest_offset
.offset_temp_celsius,
3),
- (unsigned long long int)
- over_temp_cal->debug_overtempcal.latest_offset.offset_age_nanos);
+ over_temp_cal->debug_overtempcal.latest_offset.offset_age_nanos);
// clang-format off
over_temp_cal->wait_timer_nanos =
@@ -1623,9 +1632,9 @@ void overTempCalDebugPrint(struct OverTempCal *over_temp_cal,
case OTC_PRINT_MODEL_PARAMETERS:
// Prints out the model parameters.
CAL_DEBUG_LOG(over_temp_cal->otc_debug_tag,
- "Cal#|Sensitivity [%s/C]: %lu, " CAL_FORMAT_3DIGITS_TRIPLET,
+ "Cal#|Sensitivity [%s/C]: %zu, " CAL_FORMAT_3DIGITS_TRIPLET,
over_temp_cal->otc_unit_tag,
- (unsigned long int)over_temp_cal->debug_num_estimates,
+ over_temp_cal->debug_num_estimates,
CAL_ENCODE_FLOAT(
over_temp_cal->debug_overtempcal.temp_sensitivity[0] *
over_temp_cal->otc_unit_conversion,
@@ -1640,9 +1649,9 @@ void overTempCalDebugPrint(struct OverTempCal *over_temp_cal,
3));
CAL_DEBUG_LOG(over_temp_cal->otc_debug_tag,
- "Cal#|Intercept [%s]: %lu, " CAL_FORMAT_3DIGITS_TRIPLET,
+ "Cal#|Intercept [%s]: %zu, " CAL_FORMAT_3DIGITS_TRIPLET,
over_temp_cal->otc_unit_tag,
- (unsigned long int)over_temp_cal->debug_num_estimates,
+ over_temp_cal->debug_num_estimates,
CAL_ENCODE_FLOAT(
over_temp_cal->debug_overtempcal.sensor_intercept[0] *
over_temp_cal->otc_unit_conversion,
@@ -1667,12 +1676,11 @@ void overTempCalDebugPrint(struct OverTempCal *over_temp_cal,
// Computes the maximum error over all of the model data.
CAL_DEBUG_LOG(
over_temp_cal->otc_debug_tag,
- "Cal#|#Updates|#ModelPts|Model Error [%s]: %lu, "
- "%lu, %lu, " CAL_FORMAT_3DIGITS_TRIPLET,
- over_temp_cal->otc_unit_tag,
- (unsigned long int)over_temp_cal->debug_num_estimates,
- (unsigned long int)over_temp_cal->debug_num_model_updates,
- (unsigned long int)over_temp_cal->debug_overtempcal.num_model_pts,
+ "Cal#|#Updates|#ModelPts|Model Error [%s]: %zu, "
+ "%zu, %zu, " CAL_FORMAT_3DIGITS_TRIPLET,
+ over_temp_cal->otc_unit_tag, over_temp_cal->debug_num_estimates,
+ over_temp_cal->debug_num_model_updates,
+ over_temp_cal->debug_overtempcal.num_model_pts,
CAL_ENCODE_FLOAT(over_temp_cal->debug_overtempcal.max_error[0] *
over_temp_cal->otc_unit_conversion,
3),
@@ -1695,10 +1703,9 @@ void overTempCalDebugPrint(struct OverTempCal *over_temp_cal,
if (over_temp_cal->model_counter < over_temp_cal->num_model_pts) {
CAL_DEBUG_LOG(
over_temp_cal->otc_debug_tag,
- " Model[%lu] [%s|C|nsec] = " CAL_FORMAT_3DIGITS_TRIPLET
- ", " CAL_FORMAT_3DIGITS ", %llu",
- (unsigned long int)over_temp_cal->model_counter,
- over_temp_cal->otc_unit_tag,
+ " Model[%zu] [%s|C|nsec] = " CAL_FORMAT_3DIGITS_TRIPLET
+ ", " CAL_FORMAT_3DIGITS ", %" PRIu64,
+ over_temp_cal->model_counter, over_temp_cal->otc_unit_tag,
CAL_ENCODE_FLOAT(
over_temp_cal->model_data[over_temp_cal->model_counter]
.offset[0] *
@@ -1718,8 +1725,7 @@ void overTempCalDebugPrint(struct OverTempCal *over_temp_cal,
over_temp_cal->model_data[over_temp_cal->model_counter]
.offset_temp_celsius,
3),
- (unsigned long long int)over_temp_cal
- ->model_data[over_temp_cal->model_counter]
+ over_temp_cal->model_data[over_temp_cal->model_counter]
.offset_age_nanos);
over_temp_cal->model_counter++;
diff --git a/firmware/os/algos/calibration/over_temp/over_temp_model.h b/firmware/os/algos/calibration/over_temp/over_temp_model.h
index 18e2befd..1f849442 100644
--- a/firmware/os/algos/calibration/over_temp/over_temp_model.h
+++ b/firmware/os/algos/calibration/over_temp/over_temp_model.h
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
#ifndef LOCATION_LBS_CONTEXTHUB_NANOAPPS_CALIBRATION_OVER_TEMP_OVER_TEMP_MODEL_H_
#define LOCATION_LBS_CONTEXTHUB_NANOAPPS_CALIBRATION_OVER_TEMP_OVER_TEMP_MODEL_H_
diff --git a/firmware/os/algos/calibration/sample_rate_estimator/sample_rate_estimator.c b/firmware/os/algos/calibration/sample_rate_estimator/sample_rate_estimator.c
index a501331e..d1b66195 100644
--- a/firmware/os/algos/calibration/sample_rate_estimator/sample_rate_estimator.c
+++ b/firmware/os/algos/calibration/sample_rate_estimator/sample_rate_estimator.c
@@ -85,8 +85,8 @@ void sampleRateEstimatorUpdate(
if (sample_rate_estimator->num_intervals_collected >
sample_rate_estimator->num_intervals_to_collect) {
sample_rate_estimator->mean_sampling_rate_estimate_hz =
- SEC_TO_NANOS(1) * sample_rate_estimator->num_intervals_collected /
- sample_rate_estimator->interval_accumulator_nanos;
+ sample_rate_estimator->num_intervals_collected *
+ (SEC_TO_NANOS(1) / sample_rate_estimator->interval_accumulator_nanos);
// Sets the polling flag to indicate that a new estimate is ready.
sample_rate_estimator->new_sampling_rate_estimate_ready = true;
diff --git a/firmware/os/algos/calibration/sphere_fit/calibration_data.c b/firmware/os/algos/calibration/sphere_fit/calibration_data.c
new file mode 100644
index 00000000..2de4a8c0
--- /dev/null
+++ b/firmware/os/algos/calibration/sphere_fit/calibration_data.c
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "calibration/sphere_fit/calibration_data.h"
+
+#include <string.h>
+
+#include "common/math/vec.h"
+
+// FUNCTION IMPLEMENTATIONS
+//////////////////////////////////////////////////////////////////////////////
+
+// Set calibration data to identity scale factors, zero skew and
+// zero bias.
+void calDataReset(struct ThreeAxisCalData* calstruct) {
+ memset(calstruct, 0, sizeof(struct ThreeAxisCalData));
+ calstruct->scale_factor_x = 1.0f;
+ calstruct->scale_factor_y = 1.0f;
+ calstruct->scale_factor_z = 1.0f;
+}
+
+void calDataCorrectData(const struct ThreeAxisCalData* calstruct,
+ const float x_impaired[THREE_AXIS_DIM],
+ float* x_corrected) {
+ // x_temp = (x_impaired - bias).
+ float x_temp[THREE_AXIS_DIM];
+ vecSub(x_temp, x_impaired, calstruct->bias, THREE_AXIS_DIM);
+
+ // x_corrected = scale_skew_mat * x_temp, where:
+ // scale_skew_mat = [scale_factor_x 0 0
+ // skew_yx scale_factor_y 0
+ // skew_zx skew_zy scale_factor_z].
+ x_corrected[0] = calstruct->scale_factor_x * x_temp[0];
+ x_corrected[1] =
+ calstruct->skew_yx * x_temp[0] + calstruct->scale_factor_y * x_temp[1];
+ x_corrected[2] = calstruct->skew_zx * x_temp[0] +
+ calstruct->skew_zy * x_temp[1] +
+ calstruct->scale_factor_z * x_temp[2];
+}
diff --git a/firmware/os/algos/calibration/sphere_fit/calibration_data.h b/firmware/os/algos/calibration/sphere_fit/calibration_data.h
new file mode 100644
index 00000000..405d0acc
--- /dev/null
+++ b/firmware/os/algos/calibration/sphere_fit/calibration_data.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * This module contains a data structure and corresponding helper functions for
+ * a three-axis sensor calibration. The calibration consists of a bias vector,
+ * bias, and a lower-diagonal scaling and skew matrix, scale_skew_mat.
+ *
+ * The calibration is applied to impaired sensor data as follows:
+ *
+ * corrected_data = scale_skew_mat * (impaired_data - bias).
+ */
+
+#ifndef LOCATION_LBS_CONTEXTHUB_NANOAPPS_CALIBRATION_SPHERE_FIT_CALIBRATION_DATA_H_
+#define LOCATION_LBS_CONTEXTHUB_NANOAPPS_CALIBRATION_SPHERE_FIT_CALIBRATION_DATA_H_
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define THREE_AXIS_DIM (3)
+
+// Calibration data structure.
+struct ThreeAxisCalData {
+ // Scale factor and skew terms. Used to construct the following lower
+ // diagonal scale_skew_mat:
+ // scale_skew_mat = [scale_factor_x 0 0
+ // skew_yx scale_factor_y 0
+ // skew_zx skew_zy scale_factor_z].
+ float scale_factor_x;
+ float scale_factor_y;
+ float scale_factor_z;
+ float skew_yx;
+ float skew_zx;
+ float skew_zy;
+
+ // Sensor bias offset.
+ float bias[THREE_AXIS_DIM];
+
+ // Calibration time.
+ uint64_t calibration_time_nanos;
+};
+
+// Set calibration data to identity scale factors, zero skew and
+// zero bias.
+void calDataReset(struct ThreeAxisCalData* calstruct);
+
+// Apply a stored calibration to correct a single sample of impaired sensor
+// data.
+void calDataCorrectData(const struct ThreeAxisCalData* calstruct,
+ const float x_impaired[THREE_AXIS_DIM],
+ float* x_corrected);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // LOCATION_LBS_CONTEXTHUB_NANOAPPS_CALIBRATION_SPHERE_FIT_CALIBRATION_DATA_H_
diff --git a/firmware/os/algos/calibration/sphere_fit/sphere_fit_calibration.c b/firmware/os/algos/calibration/sphere_fit/sphere_fit_calibration.c
new file mode 100644
index 00000000..853a73d5
--- /dev/null
+++ b/firmware/os/algos/calibration/sphere_fit/sphere_fit_calibration.c
@@ -0,0 +1,264 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "calibration/sphere_fit/sphere_fit_calibration.h"
+
+#include <errno.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "calibration/util/cal_log.h"
+#include "common/math/mat.h"
+#include "common/math/vec.h"
+
+// FORWARD DECLARATIONS
+///////////////////////////////////////////////////////////////////////////////
+// Utility for converting solver state to a calibration data structure.
+static void convertStateToCalStruct(const float x[SF_STATE_DIM],
+ struct ThreeAxisCalData *calstruct);
+
+static bool runCalibration(struct SphereFitCal *sphere_cal,
+ const struct SphereFitData *data,
+ uint64_t timestamp_nanos);
+
+#define MIN_VALID_DATA_NORM (1e-4f)
+
+// FUNCTION IMPLEMENTATIONS
+//////////////////////////////////////////////////////////////////////////////
+void sphereFitInit(struct SphereFitCal *sphere_cal,
+ const struct LmParams *lm_params,
+ const size_t min_num_points_for_cal) {
+ ASSERT_NOT_NULL(sphere_cal);
+ ASSERT_NOT_NULL(lm_params);
+
+ // Initialize LM solver.
+ lmSolverInit(&sphere_cal->lm_solver, lm_params,
+ &sphereFitResidAndJacobianFunc);
+
+ // Reset other parameters.
+ sphereFitReset(sphere_cal);
+
+ // Set num points for calibration, checking that it is above min.
+ if (min_num_points_for_cal < MIN_NUM_SPHERE_FIT_POINTS) {
+ sphere_cal->min_points_for_cal = MIN_NUM_SPHERE_FIT_POINTS;
+ } else {
+ sphere_cal->min_points_for_cal = min_num_points_for_cal;
+ }
+}
+
+void sphereFitReset(struct SphereFitCal *sphere_cal) {
+ ASSERT_NOT_NULL(sphere_cal);
+
+ // Set state to default (diagonal scale matrix and zero offset).
+ memset(&sphere_cal->x0[0], 0, sizeof(float) * SF_STATE_DIM);
+ sphere_cal->x0[eParamScaleMatrix11] = 1.f;
+ sphere_cal->x0[eParamScaleMatrix22] = 1.f;
+ sphere_cal->x0[eParamScaleMatrix33] = 1.f;
+ memcpy(sphere_cal->x, sphere_cal->x0, sizeof(sphere_cal->x));
+
+ // Reset time.
+ sphere_cal->estimate_time_nanos = 0;
+}
+
+void sphereFitSetSolverData(struct SphereFitCal *sphere_cal,
+ struct LmData *lm_data) {
+ ASSERT_NOT_NULL(sphere_cal);
+ ASSERT_NOT_NULL(lm_data);
+
+ // Set solver data.
+ lmSolverSetData(&sphere_cal->lm_solver, lm_data);
+}
+
+bool sphereFitRunCal(struct SphereFitCal *sphere_cal,
+ const struct SphereFitData *data,
+ uint64_t timestamp_nanos) {
+ ASSERT_NOT_NULL(sphere_cal);
+ ASSERT_NOT_NULL(data);
+
+ // Run calibration if have enough points.
+ if (data->num_fit_points >= sphere_cal->min_points_for_cal) {
+ return runCalibration(sphere_cal, data, timestamp_nanos);
+ }
+
+ return false;
+}
+
+void sphereFitSetInitialBias(struct SphereFitCal *sphere_cal,
+ const float initial_bias[THREE_AXIS_DIM]) {
+ ASSERT_NOT_NULL(sphere_cal);
+ sphere_cal->x0[eParamOffset1] = initial_bias[0];
+ sphere_cal->x0[eParamOffset2] = initial_bias[1];
+ sphere_cal->x0[eParamOffset3] = initial_bias[2];
+}
+
+void sphereFitGetLatestCal(const struct SphereFitCal *sphere_cal,
+ struct ThreeAxisCalData *cal_data) {
+ ASSERT_NOT_NULL(sphere_cal);
+ ASSERT_NOT_NULL(cal_data);
+ convertStateToCalStruct(sphere_cal->x, cal_data);
+ cal_data->calibration_time_nanos = sphere_cal->estimate_time_nanos;
+}
+
+void sphereFitResidAndJacobianFunc(const float *state, const void *f_data,
+ float *residual, float *jacobian) {
+ ASSERT_NOT_NULL(state);
+ ASSERT_NOT_NULL(f_data);
+ ASSERT_NOT_NULL(residual);
+
+ const struct SphereFitData *data = (const struct SphereFitData *)f_data;
+
+ // Verify that expected norm is non-zero, else use default of 1.0.
+ float expected_norm = 1.0;
+ ASSERT(data->expected_norm > MIN_VALID_DATA_NORM);
+ if (data->expected_norm > MIN_VALID_DATA_NORM) {
+ expected_norm = data->expected_norm;
+ }
+
+ // Convert parameters to calibration structure.
+ struct ThreeAxisCalData calstruct;
+ convertStateToCalStruct(state, &calstruct);
+
+ // Compute Jacobian helper matrix if Jacobian requested.
+ //
+ // J = d(||M(x_data - bias)|| - expected_norm)/dstate
+ // = (M(x_data - bias) / ||M(x_data - bias)||) * d(M(x_data - bias))/dstate
+ // = x_corr / ||x_corr|| * A
+ // A = d(M(x_data - bias))/dstate
+ // = [dy/dM11, dy/dM21, dy/dM22, dy/dM31, dy/dM32, dy/dM3,...
+ // dy/db1, dy/db2, dy/db3]'
+ // where:
+ // dy/dM11 = [x_data[0] - bias[0], 0, 0]
+ // dy/dM21 = [0, x_data[0] - bias[0], 0]
+ // dy/dM22 = [0, x_data[1] - bias[1], 0]
+ // dy/dM31 = [0, 0, x_data[0] - bias[0]]
+ // dy/dM32 = [0, 0, x_data[1] - bias[1]]
+ // dy/dM33 = [0, 0, x_data[2] - bias[2]]
+ // dy/db1 = [-scale_factor_x, 0, 0]
+ // dy/db2 = [0, -scale_factor_y, 0]
+ // dy/db3 = [0, 0, -scale_factor_z]
+ float A[SF_STATE_DIM * THREE_AXIS_DIM];
+ if (jacobian) {
+ memset(jacobian, 0, sizeof(float) * SF_STATE_DIM * data->num_fit_points);
+ memset(A, 0, sizeof(A));
+ A[0 * SF_STATE_DIM + eParamOffset1] = -calstruct.scale_factor_x;
+ A[1 * SF_STATE_DIM + eParamOffset2] = -calstruct.scale_factor_y;
+ A[2 * SF_STATE_DIM + eParamOffset3] = -calstruct.scale_factor_z;
+ }
+
+ // Loop over all data points to compute residual and Jacobian.
+ // TODO(dvitus): Use fit_data_std when available to weight residuals.
+ float x_corr[THREE_AXIS_DIM];
+ float x_bias_corr[THREE_AXIS_DIM];
+ size_t i;
+ for (i = 0; i < data->num_fit_points; ++i) {
+ const float *x_data = &data->fit_data[i * THREE_AXIS_DIM];
+
+ // Compute corrected sensor data
+ calDataCorrectData(&calstruct, x_data, x_corr);
+
+ // Compute norm of x_corr.
+ const float norm = vecNorm(x_corr, THREE_AXIS_DIM);
+
+ // Compute residual error: f_x = norm - exp_norm
+ residual[i] = norm - data->expected_norm;
+
+ // Compute Jacobian if valid pointer.
+ if (jacobian) {
+ if (norm < MIN_VALID_DATA_NORM) {
+ return;
+ }
+ const float scale = 1.f / norm;
+
+ // Compute bias corrected data.
+ vecSub(x_bias_corr, x_data, calstruct.bias, THREE_AXIS_DIM);
+
+ // Populate non-bias terms for A
+ A[0 + eParamScaleMatrix11] = x_bias_corr[0];
+ A[1 * SF_STATE_DIM + eParamScaleMatrix21] = x_bias_corr[0];
+ A[1 * SF_STATE_DIM + eParamScaleMatrix22] = x_bias_corr[1];
+ A[2 * SF_STATE_DIM + eParamScaleMatrix31] = x_bias_corr[0];
+ A[2 * SF_STATE_DIM + eParamScaleMatrix32] = x_bias_corr[1];
+ A[2 * SF_STATE_DIM + eParamScaleMatrix33] = x_bias_corr[2];
+
+ // Compute J = x_corr / ||x_corr|| * A
+ matTransposeMultiplyVec(&jacobian[i * SF_STATE_DIM], A, x_corr,
+ THREE_AXIS_DIM, SF_STATE_DIM);
+ vecScalarMulInPlace(&jacobian[i * SF_STATE_DIM], scale, SF_STATE_DIM);
+ }
+ }
+}
+
+void convertStateToCalStruct(const float x[SF_STATE_DIM],
+ struct ThreeAxisCalData *calstruct) {
+ memcpy(&calstruct->bias[0], &x[eParamOffset1],
+ sizeof(float) * THREE_AXIS_DIM);
+ calstruct->scale_factor_x = x[eParamScaleMatrix11];
+ calstruct->skew_yx = x[eParamScaleMatrix21];
+ calstruct->scale_factor_y = x[eParamScaleMatrix22];
+ calstruct->skew_zx = x[eParamScaleMatrix31];
+ calstruct->skew_zy = x[eParamScaleMatrix32];
+ calstruct->scale_factor_z = x[eParamScaleMatrix33];
+}
+
+bool runCalibration(struct SphereFitCal *sphere_cal,
+ const struct SphereFitData *data,
+ uint64_t timestamp_nanos) {
+ float x_sol[SF_STATE_DIM];
+
+ // Run calibration
+ const enum LmStatus status =
+ lmSolverSolve(&sphere_cal->lm_solver, sphere_cal->x0, (void *)data,
+ SF_STATE_DIM, data->num_fit_points, x_sol);
+
+ // Check if solver was successful
+ if (status == RELATIVE_STEP_SUFFICIENTLY_SMALL ||
+ status == GRADIENT_SUFFICIENTLY_SMALL) {
+ // TODO(dvitus): Check quality of new fit before using.
+ // Store new fit.
+#ifdef SPHERE_FIT_DBG_ENABLED
+ CAL_DEBUG_LOG("[SPHERE CAL]",
+ "Solution found in %d iterations with status %d.\n",
+ sphere_cal->lm_solver.num_iter, status);
+ CAL_DEBUG_LOG("[SPHERE CAL]", "Solution:\n {"
+ CAL_FORMAT_6DIGITS " [M(1,1)], "
+ CAL_FORMAT_6DIGITS " [M(2,1)], "
+ CAL_FORMAT_6DIGITS " [M(2,2)], \n"
+ CAL_FORMAT_6DIGITS " [M(3,1)], "
+ CAL_FORMAT_6DIGITS " [M(3,2)], "
+ CAL_FORMAT_6DIGITS " [M(3,3)], \n"
+ CAL_FORMAT_6DIGITS " [b(1)], "
+ CAL_FORMAT_6DIGITS " [b(2)], "
+ CAL_FORMAT_6DIGITS " [b(3)]}.",
+ CAL_ENCODE_FLOAT(x_sol[0], 6), CAL_ENCODE_FLOAT(x_sol[1], 6),
+ CAL_ENCODE_FLOAT(x_sol[2], 6), CAL_ENCODE_FLOAT(x_sol[3], 6),
+ CAL_ENCODE_FLOAT(x_sol[4], 6), CAL_ENCODE_FLOAT(x_sol[5], 6),
+ CAL_ENCODE_FLOAT(x_sol[6], 6), CAL_ENCODE_FLOAT(x_sol[7], 6),
+ CAL_ENCODE_FLOAT(x_sol[8], 6));
+#endif // SPHERE_FIT_DBG_ENABLED
+ memcpy(sphere_cal->x, x_sol, sizeof(x_sol));
+ sphere_cal->estimate_time_nanos = timestamp_nanos;
+ return true;
+ } else {
+#ifdef SPHERE_FIT_DBG_ENABLED
+ CAL_DEBUG_LOG("[SPHERE CAL]",
+ "Solution failed in %d iterations with status %d.\n",
+ sphere_cal->lm_solver.num_iter, status);
+#endif // SPHERE_FIT_DBG_ENABLED
+ }
+
+ return false;
+}
diff --git a/firmware/os/algos/calibration/sphere_fit/sphere_fit_calibration.h b/firmware/os/algos/calibration/sphere_fit/sphere_fit_calibration.h
new file mode 100644
index 00000000..d3bbf7f1
--- /dev/null
+++ b/firmware/os/algos/calibration/sphere_fit/sphere_fit_calibration.h
@@ -0,0 +1,144 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * This module contains an algorithm for performing a sphere fit calibration.
+ * A sphere fit calibration solves the following non-linear least squares
+ * problem:
+ *
+ * arg min || ||M(x - b)|| - exp_norm ||
+ * M,b
+ *
+ * where:
+ * x is a 3xN matrix containing N 3-dimensional uncalibrated data points,
+ * M is a 3x3 lower diagonal scaling matrix
+ * b is a 3x1 offset vector.
+ * exp_norm is the expected norm of an individual calibration data point.
+ * M and b are solved such that the norm of the calibrated data (M(x - b)) is
+ * near exp_norm.
+ *
+ * This module uses a Levenberg-Marquardt nonlinear least squares solver to find
+ * M and b. M is assumed to be a lower diagonal, consisting of 6 parameters.
+ *
+ */
+
+#ifndef LOCATION_LBS_CONTEXTHUB_NANOAPPS_CALIBRATION_SPHERE_FIT_SPHERE_FIT_CALIBRATION_H_
+#define LOCATION_LBS_CONTEXTHUB_NANOAPPS_CALIBRATION_SPHERE_FIT_SPHERE_FIT_CALIBRATION_H_
+
+#include <stdbool.h>
+#include <stdint.h>
+
+#include "calibration/sphere_fit/calibration_data.h"
+#include "common/math/levenberg_marquardt.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define MIN_NUM_SPHERE_FIT_POINTS (14)
+
+// Enum defining the meaning of the state parameters. The 9-parameter
+// sphere fit calibration computes a lower-diagonal scaling matrix (M) and
+// an offset such that:
+// x_corrected = M * (x_impaired - offset)
+enum SphereFitParams {
+ eParamScaleMatrix11 = 0,
+ eParamScaleMatrix21,
+ eParamScaleMatrix22,
+ eParamScaleMatrix31,
+ eParamScaleMatrix32,
+ eParamScaleMatrix33,
+ eParamOffset1,
+ eParamOffset2,
+ eParamOffset3,
+ SF_STATE_DIM
+};
+
+// Structure containing the data to be used for the sphere fit calibration.
+struct SphereFitData {
+ // Data for fit (assumed to be a matrix of size num_fit_points x SF_DATA_DIM)
+ const float *fit_data;
+
+ // Pointer to standard deviations of the fit data, used to weight individual
+ // data points. Assumed to point to a matrix of dimensions
+ // num_fit_points x THREE_AXIS_DIM.
+ // If NULL, data will all be used with equal weighting in the fit.
+ const float *fit_data_std;
+
+ // Number of fit points.
+ size_t num_fit_points;
+
+ // Expected data norm.
+ float expected_norm;
+};
+
+// Structure for a sphere fit calibration, including a non-linear least squares
+// solver and the latest state estimate.
+struct SphereFitCal {
+ // Levenberg-Marquardt solver.
+ struct LmSolver lm_solver;
+
+ // Minimum number of points for computing a calibration.
+ size_t min_points_for_cal;
+
+ // State estimate.
+ float x[SF_STATE_DIM];
+ uint64_t estimate_time_nanos;
+
+ // Initial state for solver.
+ float x0[SF_STATE_DIM];
+};
+
+// Initialize sphere fit calibration structure with solver and fit params.
+void sphereFitInit(struct SphereFitCal *sphere_cal,
+ const struct LmParams *lm_params,
+ const size_t min_num_points_for_cal);
+
+// Clears state estimate and initial state.
+void sphereFitReset(struct SphereFitCal *sphere_cal);
+
+// Sets data pointer for single solve of the Levenberg-Marquardt solver.
+// Must be called before calling sphereFitRunCal().
+void sphereFitSetSolverData(struct SphereFitCal *sphere_cal,
+ struct LmData *lm_data);
+
+// Sends in a set of calibration data and attempts to run calibration.
+// Returns true if a calibration was successfully triggered with this data.
+bool sphereFitRunCal(struct SphereFitCal *sphere_cal,
+ const struct SphereFitData *data,
+ uint64_t timestamp_nanos);
+
+// Set an initial condition for the bias state.
+void sphereFitSetInitialBias(struct SphereFitCal *sphere_cal,
+ const float initial_bias[THREE_AXIS_DIM]);
+
+// Returns the latest calibration data in a ThreeAxisCalData structure.
+void sphereFitGetLatestCal(const struct SphereFitCal *sphere_cal,
+ struct ThreeAxisCalData *cal_data);
+
+///////////////// TEST UTILITIES ///////////////////////////////////////////
+// The following functions are exposed in the header for testing only.
+
+// The ResidualAndJacobianFunction for sphere calibration in the
+// Levenberg-Marquardt solver.
+void sphereFitResidAndJacobianFunc(const float *state, const void *f_data,
+ float *residual, float *jacobian);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // LOCATION_LBS_CONTEXTHUB_NANOAPPS_CALIBRATION_SPHERE_FIT_SPHERE_FIT_CALIBRATION_H_
diff --git a/firmware/os/algos/calibration/util/cal_log.h b/firmware/os/algos/calibration/util/cal_log.h
index 593c0876..46297dbb 100644
--- a/firmware/os/algos/calibration/util/cal_log.h
+++ b/firmware/os/algos/calibration/util/cal_log.h
@@ -16,7 +16,7 @@
///////////////////////////////////////////////////////////////
/*
- * Logging macros for printing formatted strings to Nanohub.
+ * Logging macros for printing user-debug messages.
*/
///////////////////////////////////////////////////////////////
#ifndef LOCATION_LBS_CONTEXTHUB_NANOAPPS_CALIBRATION_UTIL_CAL_LOG_H_
@@ -36,10 +36,18 @@
LOG_FUNC(LOG_DEBUG, "%s " fmt "\n", tag, ##__VA_ARGS__)
# define CAL_DEBUG_LOG(tag, fmt, ...) \
osLog(LOG_DEBUG, "%s " fmt, tag, ##__VA_ARGS__);
-#else // _OS_BUILD_
+#elif NANOHUB_DEBUG_LOG
# include <chre.h>
# define CAL_DEBUG_LOG(tag, fmt, ...) \
chreLog(CHRE_LOG_INFO, "%s " fmt, tag, ##__VA_ARGS__)
+#else
+// CHRE/SLPI Nanoapp Logging.
+# include "chre/util/nanoapp/log.h"
+# ifndef LOG_TAG
+# define LOG_TAG ""
+# endif // LOG_TAG
+# define CAL_DEBUG_LOG(tag, format, ...) \
+ LOGI("%s " format, tag, ##__VA_ARGS__)
#endif // GCC_DEBUG_LOG
// clang-format on
@@ -47,22 +55,42 @@
extern "C" {
#endif
-// Using this macro because floorf() is not currently implemented by the Nanohub
-// firmware.
+// Floor macro implementation for platforms that do not supply the standard
+// floorf() math function.
#define CAL_FLOOR(x) ((int)(x) - ((x) < (int)(x))) // NOLINT
+/*
+ * On some embedded software platforms numerical string formatting is not fully
+ * supported. Defining CAL_NO_FLOAT_FORMAT_STRINGS will enable a workaround that
+ * prints floating-point values having a specified number of digits using the
+ * CAL_ENCODE_FLOAT macro.
+ * Examples:
+ * - Nanohub does not support floating-point format strings.
+ * - CHRE/SLPI allows %.Xf for printing float values.
+ */
+#ifdef CAL_NO_FLOAT_FORMAT_STRINGS
// Macro used to print floating point numbers with a specified number of digits.
-#define CAL_ENCODE_FLOAT(x, num_digits) \
- ((x < 0) ? "-" : ""), (int)CAL_FLOOR(fabsf(x)), \
- (int)((fabsf(x) - CAL_FLOOR(fabsf(x))) * \
+# define CAL_ENCODE_FLOAT(x, num_digits) \
+ ((x < 0) ? "-" : ""), (int)CAL_FLOOR(fabsf(x)), \
+ (int)((fabsf(x) - CAL_FLOOR(fabsf(x))) * \
powf(10, num_digits)) // NOLINT
// Helper definitions for CAL_ENCODE_FLOAT to specify the print format with
// desired significant digits.
-#define CAL_FORMAT_3DIGITS "%s%d.%03d"
-#define CAL_FORMAT_6DIGITS "%s%d.%06d"
-#define CAL_FORMAT_3DIGITS_TRIPLET "%s%d.%03d, %s%d.%03d, %s%d.%03d"
-#define CAL_FORMAT_6DIGITS_TRIPLET "%s%d.%06d, %s%d.%06d, %s%d.%06d"
+# define CAL_FORMAT_3DIGITS "%s%d.%03d"
+# define CAL_FORMAT_6DIGITS "%s%d.%06d"
+# define CAL_FORMAT_3DIGITS_TRIPLET "%s%d.%03d, %s%d.%03d, %s%d.%03d"
+# define CAL_FORMAT_6DIGITS_TRIPLET "%s%d.%06d, %s%d.%06d, %s%d.%06d"
+#else
+// Pass-through when float string formatting (e.g., %.6f) is available.
+# define CAL_ENCODE_FLOAT(x, num_digits) (x)
+
+// Float string formatting helpers.
+# define CAL_FORMAT_3DIGITS "%.3f"
+# define CAL_FORMAT_6DIGITS "%.6f"
+# define CAL_FORMAT_3DIGITS_TRIPLET "%.3f, %.3f, %.3f"
+# define CAL_FORMAT_6DIGITS_TRIPLET "%.6f, %.6f, %.6f"
+#endif // CAL_NO_FLOAT_FORMAT_STRINGS
#ifdef __cplusplus
}