summaryrefslogtreecommitdiff
path: root/common/gyro_cal.c
diff options
context:
space:
mode:
Diffstat (limited to 'common/gyro_cal.c')
-rw-r--r--common/gyro_cal.c630
1 files changed, 0 insertions, 630 deletions
diff --git a/common/gyro_cal.c b/common/gyro_cal.c
deleted file mode 100644
index 572e401b18..0000000000
--- a/common/gyro_cal.c
+++ /dev/null
@@ -1,630 +0,0 @@
-/* Copyright 2020 The Chromium OS Authors. All rights reserved.
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "gyro_cal.h"
-#include "string.h"
-#include <stdbool.h>
-
-/*
- * Maximum gyro bias correction (should be set based on expected max bias
- * of the given sensor). [rad/sec]
- */
-#define MAX_GYRO_BIAS FLOAT_TO_FP(0.2f)
-
-static void device_stillness_check(struct gyro_cal *gyro_cal,
- uint32_t sample_time_us);
-
-static void compute_gyro_cal(struct gyro_cal *gyro_cal,
- uint32_t calibration_time_us);
-
-static void check_window(struct gyro_cal *gyro_cal, uint32_t sample_time_us);
-
-/** Data tracker command enumeration. */
-enum gyro_cal_tracker_command {
- /** Resets the local data used for data tracking. */
- DO_RESET = 0,
- /** Updates the local tracking data. */
- DO_UPDATE_DATA,
- /** Stores intermediate results for later recall. */
- DO_STORE_DATA,
- /** Computes and provides the results of the gate function. */
- DO_EVALUATE
-};
-
-/**
- * Reset the gyro_cal's temperature statistics.
- *
- * @param gyro_cal Pointer to the gyro_cal data structure.
- */
-static void gyro_temperature_stats_tracker_reset(struct gyro_cal *gyro_cal);
-
-/**
- * Updates the temperature min/max and mean during the stillness period.
- *
- * @param gyro_cal Pointer to the gyro_cal data structure.
- * @param temperature_kelvin New temperature sample to include.
- */
-static void gyro_temperature_stats_tracker_update(struct gyro_cal *gyro_cal,
- int temperature_kelvin);
-
-/**
- * Store the tracker data to be used for calculation.
- *
- * @param gyro_cal Pointer to the gyro_cal data structure.
- */
-static void gyro_temperature_stats_tracker_store(struct gyro_cal *gyro_cal);
-
-/**
- * Compute whether or not the temperature values are in range.
- *
- * @param gyro_cal Pointer to the gyro_cal data structure.
- * @return 'true' if the min and max temperature values exceed the
- * range set by 'temperature_delta_limit_kelvin'.
- */
-static bool gyro_temperature_stats_tracker_eval(struct gyro_cal *gyro_cal);
-
-/**
- * Tracks the minimum and maximum gyroscope stillness window means.
- * Returns
- *
- * @param gyro_cal Pointer to the gyro_cal data structure.
- * @param do_this Command enumerator that controls function behavior.
- */
-static void gyro_still_mean_tracker_reset(struct gyro_cal *gyro_cal);
-
-/**
- * Compute the min/max window mean values according to 'window_mean_tracker'.
- *
- * @param gyro_cal Pointer to the gyro_cal data structure.
- */
-static void gyro_still_mean_tracker_update(struct gyro_cal *gyro_cal);
-
-/**
- * Store the most recent "stillness" mean data to the gyro_cal data structure.
- *
- * @param gyro_cal Pointer to the gyro_cal data structure.
- */
-static void gyro_still_mean_tracker_store(struct gyro_cal *gyro_cal);
-
-/**
- * Compute whether or not the gyroscope window range is within the valid range.
- *
- * @param gyro_cal Pointer to the gyro_cal data structure.
- * @return 'true' when the difference between gyroscope min and max
- * window means are outside the range set by
- * 'stillness_mean_delta_limit'.
- */
-static bool gyro_still_mean_tracker_eval(struct gyro_cal *gyro_cal);
-
-void init_gyro_cal(struct gyro_cal *gyro_cal)
-{
- gyro_still_mean_tracker_reset(gyro_cal);
- gyro_temperature_stats_tracker_reset(gyro_cal);
-}
-
-void gyro_cal_get_bias(struct gyro_cal *gyro_cal, fpv3_t bias,
- int *temperature_kelvin, uint32_t *calibration_time_us)
-{
- bias[X] = gyro_cal->bias_x;
- bias[Y] = gyro_cal->bias_y;
- bias[Z] = gyro_cal->bias_z;
- *calibration_time_us = gyro_cal->calibration_time_us;
- *temperature_kelvin = gyro_cal->bias_temperature_kelvin;
-}
-
-void gyro_cal_set_bias(struct gyro_cal *gyro_cal, fpv3_t bias,
- int temperature_kelvin, uint32_t calibration_time_us)
-{
- gyro_cal->bias_x = bias[X];
- gyro_cal->bias_y = bias[Y];
- gyro_cal->bias_z = bias[Z];
- gyro_cal->calibration_time_us = calibration_time_us;
- gyro_cal->bias_temperature_kelvin = temperature_kelvin;
-}
-
-void gyro_cal_remove_bias(struct gyro_cal *gyro_cal, fpv3_t in, fpv3_t out)
-{
- if (gyro_cal->gyro_calibration_enable) {
- out[X] = in[X] - gyro_cal->bias_x;
- out[Y] = in[Y] - gyro_cal->bias_y;
- out[Z] = in[Z] - gyro_cal->bias_z;
- }
-}
-
-bool gyro_cal_new_bias_available(struct gyro_cal *gyro_cal)
-{
- bool new_gyro_cal_available = (gyro_cal->gyro_calibration_enable &&
- gyro_cal->new_gyro_cal_available);
-
- /* Clear the flag. */
- gyro_cal->new_gyro_cal_available = false;
-
- return new_gyro_cal_available;
-}
-
-void gyro_cal_update_gyro(struct gyro_cal *gyro_cal, uint32_t sample_time_us,
- fp_t x, fp_t y, fp_t z, int temperature_kelvin)
-{
- /*
- * Make sure that a valid window end-time is set, and start the window
- * timer.
- */
- if (gyro_cal->stillness_win_endtime_us <= 0) {
- gyro_cal->stillness_win_endtime_us =
- sample_time_us + gyro_cal->window_time_duration_us;
-
- /* Start the window timer. */
- gyro_cal->gyro_window_start_us = sample_time_us;
- }
-
- /* Update the temperature statistics. */
- gyro_temperature_stats_tracker_update(gyro_cal, temperature_kelvin);
-
- /* Pass gyro data to stillness detector */
- gyro_still_det_update(&gyro_cal->gyro_stillness_detect,
- gyro_cal->stillness_win_endtime_us,
- sample_time_us, x, y, z);
-
- /*
- * Perform a device stillness check, set next window end-time, and
- * possibly do a gyro bias calibration and stillness detector reset.
- */
- device_stillness_check(gyro_cal, sample_time_us);
-}
-
-void gyro_cal_update_mag(struct gyro_cal *gyro_cal, uint32_t sample_time_us,
- fp_t x, fp_t y, fp_t z)
-{
- /* Pass magnetometer data to stillness detector. */
- gyro_still_det_update(&gyro_cal->mag_stillness_detect,
- gyro_cal->stillness_win_endtime_us,
- sample_time_us, x, y, z);
-
- /* Received a magnetometer sample; incorporate it into detection. */
- gyro_cal->using_mag_sensor = true;
-
- /*
- * Perform a device stillness check, set next window end-time, and
- * possibly do a gyro bias calibration and stillness detector reset.
- */
- device_stillness_check(gyro_cal, sample_time_us);
-}
-
-void gyro_cal_update_accel(struct gyro_cal *gyro_cal, uint32_t sample_time_us,
- fp_t x, fp_t y, fp_t z)
-{
- /* Pass accelerometer data to stillnesss detector. */
- gyro_still_det_update(&gyro_cal->accel_stillness_detect,
- gyro_cal->stillness_win_endtime_us,
- sample_time_us, x, y, z);
-
- /*
- * Perform a device stillness check, set next window end-time, and
- * possibly do a gyro bias calibration and stillness detector reset.
- */
- device_stillness_check(gyro_cal, sample_time_us);
-}
-
-/**
- * Handle the case where the device is found to be still. This function should
- * be called from device_stillness_check.
- *
- * @param gyro_cal Pointer to the gyroscope calibration struct.
- */
-static void handle_device_is_still(struct gyro_cal *gyro_cal)
-{
- /*
- * Device is "still" logic:
- * If not previously still, then record the start time.
- * If stillness period is too long, then do a calibration.
- * Otherwise, continue collecting stillness data.
- */
- bool stillness_duration_exceeded = false;
-
- /*
- * If device was not previously still, set new start timestamp.
- */
- if (!gyro_cal->prev_still) {
- /*
- * Record the starting timestamp of the current stillness
- * window. This enables the calculation of total duration of
- * the stillness period.
- */
- gyro_cal->start_still_time_us =
- gyro_cal->gyro_stillness_detect.window_start_time;
- }
-
- /*
- * Check to see if current stillness period exceeds the desired limit.
- */
- stillness_duration_exceeded =
- gyro_cal->gyro_stillness_detect.last_sample_time >=
- (gyro_cal->start_still_time_us +
- gyro_cal->max_still_duration_us);
-
- /* Track the new stillness mean and temperature data. */
- gyro_still_mean_tracker_store(gyro_cal);
- gyro_temperature_stats_tracker_store(gyro_cal);
-
- if (stillness_duration_exceeded) {
- /*
- * The current stillness has gone too long. Do a calibration
- * with the current data and reset.
- */
-
- /*
- * Updates the gyro bias estimate with the current window data
- * and resets the stats.
- */
- gyro_still_det_reset(&gyro_cal->accel_stillness_detect,
- /*reset_stats=*/true);
- gyro_still_det_reset(&gyro_cal->gyro_stillness_detect,
- /*reset_stats=*/true);
- gyro_still_det_reset(&gyro_cal->mag_stillness_detect,
- /*reset_stats=*/true);
-
- /*
- * Resets the local calculations because the stillness
- * period is over.
- */
- gyro_still_mean_tracker_reset(gyro_cal);
- gyro_temperature_stats_tracker_reset(gyro_cal);
-
- /* Computes a new gyro offset estimate. */
- compute_gyro_cal(
- gyro_cal,
- gyro_cal->gyro_stillness_detect.last_sample_time);
-
- /*
- * Update stillness flag. Force the start of a new
- * stillness period.
- */
- gyro_cal->prev_still = false;
- } else {
- /* Continue collecting stillness data. */
-
- /* Extend the stillness period. */
- gyro_still_det_reset(&gyro_cal->accel_stillness_detect,
- /*reset_stats=*/false);
- gyro_still_det_reset(&gyro_cal->gyro_stillness_detect,
- /*reset_stats=*/false);
- gyro_still_det_reset(&gyro_cal->mag_stillness_detect,
- /*reset_stats=*/false);
-
- /* Update the stillness flag. */
- gyro_cal->prev_still = true;
- }
-}
-
-static void handle_device_not_still(struct gyro_cal *gyro_cal)
-{
- /* Device is NOT still; motion detected. */
-
- /*
- * If device was previously still and the total stillness
- * duration is not "too short", then do a calibration with the
- * data accumulated thus far.
- */
- bool stillness_duration_too_short =
- gyro_cal->gyro_stillness_detect.window_start_time <
- (gyro_cal->start_still_time_us +
- gyro_cal->min_still_duration_us);
-
- if (gyro_cal->prev_still && !stillness_duration_too_short)
- compute_gyro_cal(
- gyro_cal,
- gyro_cal->gyro_stillness_detect.window_start_time);
-
- /* Reset the stillness detectors and the stats. */
- gyro_still_det_reset(&gyro_cal->accel_stillness_detect,
- /*reset_stats=*/true);
- gyro_still_det_reset(&gyro_cal->gyro_stillness_detect,
- /*reset_stats=*/true);
- gyro_still_det_reset(&gyro_cal->mag_stillness_detect,
- /*reset_stats=*/true);
-
- /* Resets the temperature and sensor mean data. */
- gyro_temperature_stats_tracker_reset(gyro_cal);
- gyro_still_mean_tracker_reset(gyro_cal);
-
- /* Update stillness flag. */
- gyro_cal->prev_still = false;
-}
-
-void device_stillness_check(struct gyro_cal *gyro_cal, uint32_t sample_time_us)
-{
- bool min_max_temp_exceeded = false;
- bool mean_not_stable = false;
- bool device_is_still = false;
- fp_t conf_not_rot = INT_TO_FP(0);
- fp_t conf_not_accel = INT_TO_FP(0);
- fp_t conf_still = INT_TO_FP(0);
-
- /* Check the window timer. */
- check_window(gyro_cal, sample_time_us);
-
- /* Is there enough data to do a stillness calculation? */
- if ((!gyro_cal->mag_stillness_detect.stillness_window_ready &&
- gyro_cal->using_mag_sensor) ||
- !gyro_cal->accel_stillness_detect.stillness_window_ready ||
- !gyro_cal->gyro_stillness_detect.stillness_window_ready)
- return; /* Not yet, wait for more data. */
-
- /* Set the next window end-time for the stillness detectors. */
- gyro_cal->stillness_win_endtime_us =
- sample_time_us + gyro_cal->window_time_duration_us;
-
- /* Update the confidence scores for all sensors. */
- gyro_still_det_compute(&gyro_cal->accel_stillness_detect);
- gyro_still_det_compute(&gyro_cal->gyro_stillness_detect);
- if (gyro_cal->using_mag_sensor) {
- gyro_still_det_compute(&gyro_cal->mag_stillness_detect);
- } else {
- /*
- * Not using magnetometer, force stillness confidence to 100%.
- */
- gyro_cal->mag_stillness_detect.stillness_confidence =
- INT_TO_FP(1);
- }
-
- /* Updates the mean tracker data. */
- gyro_still_mean_tracker_update(gyro_cal);
-
- /*
- * Determine motion confidence scores (rotation, accelerating, and
- * stillness).
- */
- conf_not_rot =
- fp_mul(gyro_cal->gyro_stillness_detect.stillness_confidence,
- gyro_cal->mag_stillness_detect.stillness_confidence);
- conf_not_accel = gyro_cal->accel_stillness_detect.stillness_confidence;
- conf_still = fp_mul(conf_not_rot, conf_not_accel);
-
- /* Evaluate the mean and temperature gate functions. */
- mean_not_stable = gyro_still_mean_tracker_eval(gyro_cal);
- min_max_temp_exceeded = gyro_temperature_stats_tracker_eval(gyro_cal);
-
- /* Determines if the device is currently still. */
- device_is_still = (conf_still > gyro_cal->stillness_threshold) &&
- !mean_not_stable && !min_max_temp_exceeded;
-
- if (device_is_still)
- handle_device_is_still(gyro_cal);
- else
- handle_device_not_still(gyro_cal);
-
- /* Reset the window timer after we have processed data. */
- gyro_cal->gyro_window_start_us = sample_time_us;
-}
-
-void compute_gyro_cal(struct gyro_cal *gyro_cal, uint32_t calibration_time_us)
-{
- /* Check to see if new calibration values is within acceptable range. */
- if (!(gyro_cal->gyro_stillness_detect.prev_mean[X] < MAX_GYRO_BIAS &&
- gyro_cal->gyro_stillness_detect.prev_mean[X] > -MAX_GYRO_BIAS &&
- gyro_cal->gyro_stillness_detect.prev_mean[Y] < MAX_GYRO_BIAS &&
- gyro_cal->gyro_stillness_detect.prev_mean[Y] > -MAX_GYRO_BIAS &&
- gyro_cal->gyro_stillness_detect.prev_mean[Z] < MAX_GYRO_BIAS &&
- gyro_cal->gyro_stillness_detect.prev_mean[Z] > -MAX_GYRO_BIAS))
- /* Outside of range. Ignore, reset, and continue. */
- return;
-
- /* Record the new gyro bias offset calibration. */
- gyro_cal->bias_x = gyro_cal->gyro_stillness_detect.prev_mean[X];
- gyro_cal->bias_y = gyro_cal->gyro_stillness_detect.prev_mean[Y];
- gyro_cal->bias_z = gyro_cal->gyro_stillness_detect.prev_mean[Z];
-
- /*
- * Store the calibration temperature (using the mean temperature over
- * the "stillness" period).
- */
- gyro_cal->bias_temperature_kelvin = gyro_cal->temperature_mean_kelvin;
-
- /* Store the calibration time stamp. */
- gyro_cal->calibration_time_us = calibration_time_us;
-
- /* Record the final stillness confidence. */
- gyro_cal->stillness_confidence = fp_mul(
- gyro_cal->gyro_stillness_detect.prev_stillness_confidence,
- gyro_cal->accel_stillness_detect.prev_stillness_confidence);
- gyro_cal->stillness_confidence = fp_mul(
- gyro_cal->stillness_confidence,
- gyro_cal->mag_stillness_detect.prev_stillness_confidence);
-
- /* Set flag to indicate a new gyro calibration value is available. */
- gyro_cal->new_gyro_cal_available = true;
-}
-
-void check_window(struct gyro_cal *gyro_cal, uint32_t sample_time_us)
-{
- bool window_timeout;
-
- /* Check for initialization of the window time (=0). */
- if (gyro_cal->gyro_window_start_us <= 0)
- return;
-
- /*
- * Checks for the following window timeout conditions:
- * i. The current timestamp has exceeded the allowed window duration.
- * ii. A timestamp was received that has jumped backwards by more than
- * the allowed window duration (e.g., timestamp clock roll-over).
- */
- window_timeout =
- (sample_time_us > gyro_cal->gyro_window_timeout_duration_us +
- gyro_cal->gyro_window_start_us) ||
- (sample_time_us + gyro_cal->gyro_window_timeout_duration_us <
- gyro_cal->gyro_window_start_us);
-
- /* If a timeout occurred then reset to known good state. */
- if (window_timeout) {
- /* Reset stillness detectors and restart data capture. */
- gyro_still_det_reset(&gyro_cal->accel_stillness_detect,
- /*reset_stats=*/true);
- gyro_still_det_reset(&gyro_cal->gyro_stillness_detect,
- /*reset_stats=*/true);
- gyro_still_det_reset(&gyro_cal->mag_stillness_detect,
- /*reset_stats=*/true);
-
- /* Resets the temperature and sensor mean data. */
- gyro_temperature_stats_tracker_reset(gyro_cal);
- gyro_still_mean_tracker_reset(gyro_cal);
-
- /* Resets the stillness window end-time. */
- gyro_cal->stillness_win_endtime_us = 0;
-
- /* Force stillness confidence to zero. */
- gyro_cal->accel_stillness_detect.prev_stillness_confidence = 0;
- gyro_cal->gyro_stillness_detect.prev_stillness_confidence = 0;
- gyro_cal->mag_stillness_detect.prev_stillness_confidence = 0;
- gyro_cal->stillness_confidence = 0;
- gyro_cal->prev_still = false;
-
- /*
- * If there are no magnetometer samples being received then
- * operate the calibration algorithm without this sensor.
- */
- if (!gyro_cal->mag_stillness_detect.stillness_window_ready &&
- gyro_cal->using_mag_sensor) {
- gyro_cal->using_mag_sensor = false;
- }
-
- /* Assert window timeout flags. */
- gyro_cal->gyro_window_start_us = 0;
- }
-}
-
-void gyro_temperature_stats_tracker_reset(struct gyro_cal *gyro_cal)
-{
- /* Resets the mean accumulator. */
- gyro_cal->temperature_mean_tracker.num_points = 0;
- gyro_cal->temperature_mean_tracker.mean_accumulator = INT_TO_FP(0);
-
- /* Initializes the min/max temperatures values. */
- gyro_cal->temperature_mean_tracker.temperature_min_kelvin = 0x7fff;
- gyro_cal->temperature_mean_tracker.temperature_max_kelvin = 0xffff;
-}
-
-void gyro_temperature_stats_tracker_update(struct gyro_cal *gyro_cal,
- int temperature_kelvin)
-{
- /* Does the mean accumulation. */
- gyro_cal->temperature_mean_tracker.mean_accumulator +=
- temperature_kelvin;
- gyro_cal->temperature_mean_tracker.num_points++;
-
- /* Tracks the min, max, and latest temperature values. */
- gyro_cal->temperature_mean_tracker.latest_temperature_kelvin =
- temperature_kelvin;
- if (gyro_cal->temperature_mean_tracker.temperature_min_kelvin >
- temperature_kelvin) {
- gyro_cal->temperature_mean_tracker.temperature_min_kelvin =
- temperature_kelvin;
- }
- if (gyro_cal->temperature_mean_tracker.temperature_max_kelvin <
- temperature_kelvin) {
- gyro_cal->temperature_mean_tracker.temperature_max_kelvin =
- temperature_kelvin;
- }
-}
-
-void gyro_temperature_stats_tracker_store(struct gyro_cal *gyro_cal)
-{
- /*
- * Store the most recent temperature statistics data to the
- * gyro_cal data structure. This functionality allows previous
- * results to be recalled when the device suddenly becomes "not
- * still".
- */
- if (gyro_cal->temperature_mean_tracker.num_points > 0)
- gyro_cal->temperature_mean_kelvin =
- gyro_cal->temperature_mean_tracker.mean_accumulator /
- gyro_cal->temperature_mean_tracker.num_points;
- else
- gyro_cal->temperature_mean_kelvin =
- gyro_cal->temperature_mean_tracker
- .latest_temperature_kelvin;
-}
-
-bool gyro_temperature_stats_tracker_eval(struct gyro_cal *gyro_cal)
-{
- bool min_max_temp_exceeded = false;
-
- /* Determines if the min/max delta exceeded the set limit. */
- if (gyro_cal->temperature_mean_tracker.num_points > 0) {
- min_max_temp_exceeded =
- (gyro_cal->temperature_mean_tracker
- .temperature_max_kelvin -
- gyro_cal->temperature_mean_tracker
- .temperature_min_kelvin) >
- gyro_cal->temperature_delta_limit_kelvin;
- }
-
- return min_max_temp_exceeded;
-}
-
-void gyro_still_mean_tracker_reset(struct gyro_cal *gyro_cal)
-{
- size_t i;
-
- /* Resets the min/max window mean values to a default value. */
- for (i = 0; i < 3; i++) {
- gyro_cal->window_mean_tracker.gyro_winmean_min[i] = FLT_MAX;
- gyro_cal->window_mean_tracker.gyro_winmean_max[i] = -FLT_MAX;
- }
-}
-
-void gyro_still_mean_tracker_update(struct gyro_cal *gyro_cal)
-{
- int i;
-
- /* Computes the min/max window mean values. */
- for (i = 0; i < 3; ++i) {
- if (gyro_cal->window_mean_tracker.gyro_winmean_min[i] >
- gyro_cal->gyro_stillness_detect.win_mean[i]) {
- gyro_cal->window_mean_tracker.gyro_winmean_min[i] =
- gyro_cal->gyro_stillness_detect.win_mean[i];
- }
- if (gyro_cal->window_mean_tracker.gyro_winmean_max[i] <
- gyro_cal->gyro_stillness_detect.win_mean[i]) {
- gyro_cal->window_mean_tracker.gyro_winmean_max[i] =
- gyro_cal->gyro_stillness_detect.win_mean[i];
- }
- }
-}
-
-void gyro_still_mean_tracker_store(struct gyro_cal *gyro_cal)
-{
- /*
- * Store the most recent "stillness" mean data to the gyro_cal
- * data structure. This functionality allows previous results to
- * be recalled when the device suddenly becomes "not still".
- */
- memcpy(gyro_cal->gyro_winmean_min,
- gyro_cal->window_mean_tracker.gyro_winmean_min,
- sizeof(gyro_cal->window_mean_tracker.gyro_winmean_min));
- memcpy(gyro_cal->gyro_winmean_max,
- gyro_cal->window_mean_tracker.gyro_winmean_max,
- sizeof(gyro_cal->window_mean_tracker.gyro_winmean_max));
-}
-
-bool gyro_still_mean_tracker_eval(struct gyro_cal *gyro_cal)
-{
- bool mean_not_stable = false;
- size_t i;
-
- /*
- * Performs the stability check and returns the 'true' if the
- * difference between min/max window mean value is outside the
- * stable range.
- */
- for (i = 0; i < 3 && !mean_not_stable; i++) {
- mean_not_stable |=
- (gyro_cal->window_mean_tracker.gyro_winmean_max[i] -
- gyro_cal->window_mean_tracker.gyro_winmean_min[i]) >
- gyro_cal->stillness_mean_delta_limit;
- }
-
- return mean_not_stable;
-}