1100 lines
45 KiB
C
1100 lines
45 KiB
C
|
/*
|
||
|
* 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/gyroscope/gyro_cal.h"
|
||
|
|
||
|
#include <float.h>
|
||
|
#include <inttypes.h>
|
||
|
#include <math.h>
|
||
|
#include <string.h>
|
||
|
|
||
|
#ifdef GYRO_CAL_DBG_ENABLED
|
||
|
#include "calibration/util/cal_log.h"
|
||
|
#endif // GYRO_CAL_DBG_ENABLED
|
||
|
|
||
|
#include "common/math/macros.h"
|
||
|
|
||
|
/////// DEFINITIONS AND MACROS ///////////////////////////////////////
|
||
|
|
||
|
// Maximum gyro bias correction (should be set based on expected max bias
|
||
|
// of the given sensor).
|
||
|
#define MAX_GYRO_BIAS (0.2f) // [rad/sec]
|
||
|
|
||
|
// Watchdog timeout value (5 seconds). Monitors dropouts in sensor data and
|
||
|
// resets when exceeded.
|
||
|
#define GYRO_WATCHDOG_TIMEOUT_NANOS (SEC_TO_NANOS(5))
|
||
|
|
||
|
#ifdef GYRO_CAL_DBG_ENABLED
|
||
|
// The time value used to throttle debug messaging.
|
||
|
#define GYROCAL_WAIT_TIME_NANOS (MSEC_TO_NANOS(100))
|
||
|
|
||
|
// A debug version label to help with tracking results.
|
||
|
#define GYROCAL_DEBUG_VERSION_STRING "[July 05, 2017]"
|
||
|
|
||
|
// Parameters used for sample rate estimation.
|
||
|
#define GYROCAL_DEBUG_SAMPLE_RATE_NUM_INTERVALS (100)
|
||
|
#define GYROCAL_DEBUG_SAMPLE_RATE_GAP_SEC (1.0f)
|
||
|
|
||
|
// Debug log tag string used to identify debug report output data.
|
||
|
#define GYROCAL_REPORT_TAG "[GYRO_CAL:REPORT]"
|
||
|
#endif // GYRO_CAL_DBG_ENABLED
|
||
|
|
||
|
/////// FORWARD DECLARATIONS /////////////////////////////////////////
|
||
|
|
||
|
static void deviceStillnessCheck(struct GyroCal* gyro_cal,
|
||
|
uint64_t sample_time_nanos);
|
||
|
|
||
|
static void computeGyroCal(struct GyroCal* gyro_cal,
|
||
|
uint64_t calibration_time_nanos);
|
||
|
|
||
|
static void checkWatchdog(struct GyroCal* gyro_cal, uint64_t sample_time_nanos);
|
||
|
|
||
|
// Data tracker command enumeration.
|
||
|
enum GyroCalTrackerCommand {
|
||
|
DO_RESET = 0, // Resets the local data used for data tracking.
|
||
|
DO_UPDATE_DATA, // Updates the local tracking data.
|
||
|
DO_STORE_DATA, // Stores intermediate results for later recall.
|
||
|
DO_EVALUATE // Computes and provides the results of the gate function.
|
||
|
};
|
||
|
|
||
|
/*
|
||
|
* Updates the temperature min/max and mean during the stillness period. Returns
|
||
|
* 'true' if the min and max temperature values exceed the range set by
|
||
|
* 'temperature_delta_limit_celsius'.
|
||
|
*
|
||
|
* INPUTS:
|
||
|
* gyro_cal: Pointer to the GyroCal data structure.
|
||
|
* temperature_celsius: New temperature sample to include.
|
||
|
* do_this: Command enumerator that controls function behavior:
|
||
|
*/
|
||
|
static bool gyroTemperatureStatsTracker(struct GyroCal* gyro_cal,
|
||
|
float temperature_celsius,
|
||
|
enum GyroCalTrackerCommand do_this);
|
||
|
|
||
|
/*
|
||
|
* Tracks the minimum and maximum gyroscope stillness window means.
|
||
|
* Returns 'true' when the difference between gyroscope min and max window
|
||
|
* means are outside the range set by 'stillness_mean_delta_limit'.
|
||
|
*
|
||
|
* INPUTS:
|
||
|
* gyro_cal: Pointer to the GyroCal data structure.
|
||
|
* do_this: Command enumerator that controls function behavior.
|
||
|
*/
|
||
|
static bool gyroStillMeanTracker(struct GyroCal* gyro_cal,
|
||
|
enum GyroCalTrackerCommand do_this);
|
||
|
|
||
|
#ifdef GYRO_CAL_DBG_ENABLED
|
||
|
// Defines the type of debug data to print.
|
||
|
enum DebugPrintData {
|
||
|
OFFSET = 0,
|
||
|
STILLNESS_DATA,
|
||
|
SAMPLE_RATE_AND_TEMPERATURE,
|
||
|
GYRO_MINMAX_STILLNESS_MEAN,
|
||
|
ACCEL_STATS,
|
||
|
GYRO_STATS,
|
||
|
MAG_STATS,
|
||
|
ACCEL_STATS_TUNING,
|
||
|
GYRO_STATS_TUNING,
|
||
|
MAG_STATS_TUNING
|
||
|
};
|
||
|
|
||
|
// Updates the information used for debug printouts.
|
||
|
static void gyroCalUpdateDebug(struct GyroCal* gyro_cal);
|
||
|
|
||
|
// Helper function for printing out common debug data.
|
||
|
static void gyroCalDebugPrintData(const struct GyroCal* gyro_cal,
|
||
|
char* debug_tag,
|
||
|
enum DebugPrintData print_data);
|
||
|
#endif // GYRO_CAL_DBG_ENABLED
|
||
|
|
||
|
/////// FUNCTION DEFINITIONS /////////////////////////////////////////
|
||
|
|
||
|
// Initialize the gyro calibration data structure.
|
||
|
void gyroCalInit(struct GyroCal* gyro_cal,
|
||
|
const struct GyroCalParameters* parameters) {
|
||
|
// Clear gyro_cal structure memory.
|
||
|
memset(gyro_cal, 0, sizeof(struct GyroCal));
|
||
|
|
||
|
// Initialize the stillness detectors.
|
||
|
// Gyro parameter input units are [rad/sec].
|
||
|
// Accel parameter input units are [m/sec^2].
|
||
|
// Magnetometer parameter input units are [uT].
|
||
|
gyroStillDetInit(&gyro_cal->gyro_stillness_detect,
|
||
|
parameters->gyro_var_threshold,
|
||
|
parameters->gyro_confidence_delta);
|
||
|
gyroStillDetInit(&gyro_cal->accel_stillness_detect,
|
||
|
parameters->accel_var_threshold,
|
||
|
parameters->accel_confidence_delta);
|
||
|
gyroStillDetInit(&gyro_cal->mag_stillness_detect,
|
||
|
parameters->mag_var_threshold,
|
||
|
parameters->mag_confidence_delta);
|
||
|
|
||
|
// Reset stillness flag and start timestamp.
|
||
|
gyro_cal->prev_still = false;
|
||
|
gyro_cal->start_still_time_nanos = 0;
|
||
|
|
||
|
// Set the min and max window stillness duration.
|
||
|
gyro_cal->min_still_duration_nanos = parameters->min_still_duration_nanos;
|
||
|
gyro_cal->max_still_duration_nanos = parameters->max_still_duration_nanos;
|
||
|
|
||
|
// Sets the duration of the stillness processing windows.
|
||
|
gyro_cal->window_time_duration_nanos = parameters->window_time_duration_nanos;
|
||
|
|
||
|
// Set the watchdog timeout duration.
|
||
|
gyro_cal->gyro_watchdog_timeout_duration_nanos = GYRO_WATCHDOG_TIMEOUT_NANOS;
|
||
|
|
||
|
// Load the last valid cal from system memory.
|
||
|
gyro_cal->bias_x = parameters->bias_x; // [rad/sec]
|
||
|
gyro_cal->bias_y = parameters->bias_y; // [rad/sec]
|
||
|
gyro_cal->bias_z = parameters->bias_z; // [rad/sec]
|
||
|
gyro_cal->calibration_time_nanos = parameters->calibration_time_nanos;
|
||
|
|
||
|
// Set the stillness threshold required for gyro bias calibration.
|
||
|
gyro_cal->stillness_threshold = parameters->stillness_threshold;
|
||
|
|
||
|
// Current window end-time used to assist in keeping sensor data collection in
|
||
|
// sync. Setting this to zero signals that sensor data will be dropped until a
|
||
|
// valid end-time is set from the first gyro timestamp received.
|
||
|
gyro_cal->stillness_win_endtime_nanos = 0;
|
||
|
|
||
|
// Gyro calibrations will be applied (see, gyroCalRemoveBias()).
|
||
|
gyro_cal->gyro_calibration_enable = (parameters->gyro_calibration_enable > 0);
|
||
|
|
||
|
// Sets the stability limit for the stillness window mean acceptable delta.
|
||
|
gyro_cal->stillness_mean_delta_limit = parameters->stillness_mean_delta_limit;
|
||
|
|
||
|
// Sets the min/max temperature delta limit for the stillness period.
|
||
|
gyro_cal->temperature_delta_limit_celsius =
|
||
|
parameters->temperature_delta_limit_celsius;
|
||
|
|
||
|
// Ensures that the data tracking functionality is reset.
|
||
|
gyroStillMeanTracker(gyro_cal, DO_RESET);
|
||
|
gyroTemperatureStatsTracker(gyro_cal, 0.0f, DO_RESET);
|
||
|
|
||
|
#ifdef GYRO_CAL_DBG_ENABLED
|
||
|
if (gyro_cal->gyro_calibration_enable) {
|
||
|
CAL_DEBUG_LOG("[GYRO_CAL:INIT]", "Online gyroscope calibration ENABLED.");
|
||
|
} else {
|
||
|
CAL_DEBUG_LOG("[GYRO_CAL:INIT]", "Online gyroscope calibration DISABLED.");
|
||
|
}
|
||
|
|
||
|
// Initializes the gyro sampling rate estimator.
|
||
|
sampleRateEstimatorInit(&gyro_cal->debug_gyro_cal.sample_rate_estimator,
|
||
|
GYROCAL_DEBUG_SAMPLE_RATE_NUM_INTERVALS,
|
||
|
GYROCAL_DEBUG_SAMPLE_RATE_GAP_SEC);
|
||
|
#endif // GYRO_CAL_DBG_ENABLED
|
||
|
}
|
||
|
|
||
|
// Get the most recent bias calibration value.
|
||
|
void gyroCalGetBias(struct GyroCal* gyro_cal, float* bias_x, float* bias_y,
|
||
|
float* bias_z, float* temperature_celsius,
|
||
|
uint64_t* calibration_time_nanos) {
|
||
|
*bias_x = gyro_cal->bias_x;
|
||
|
*bias_y = gyro_cal->bias_y;
|
||
|
*bias_z = gyro_cal->bias_z;
|
||
|
*calibration_time_nanos = gyro_cal->calibration_time_nanos;
|
||
|
*temperature_celsius = gyro_cal->bias_temperature_celsius;
|
||
|
}
|
||
|
|
||
|
// Set an initial bias calibration value.
|
||
|
void gyroCalSetBias(struct GyroCal* gyro_cal, float bias_x, float bias_y,
|
||
|
float bias_z, float temperature_celsius,
|
||
|
uint64_t calibration_time_nanos) {
|
||
|
gyro_cal->bias_x = bias_x;
|
||
|
gyro_cal->bias_y = bias_y;
|
||
|
gyro_cal->bias_z = bias_z;
|
||
|
gyro_cal->calibration_time_nanos = calibration_time_nanos;
|
||
|
gyro_cal->bias_temperature_celsius = temperature_celsius;
|
||
|
|
||
|
#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 ", %" 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),
|
||
|
calibration_time_nanos);
|
||
|
#endif // GYRO_CAL_DBG_ENABLED
|
||
|
}
|
||
|
|
||
|
// Remove bias from a gyro measurement [rad/sec].
|
||
|
void gyroCalRemoveBias(struct GyroCal* gyro_cal, float xi, float yi, float zi,
|
||
|
float* xo, float* yo, float* zo) {
|
||
|
if (gyro_cal->gyro_calibration_enable) {
|
||
|
*xo = xi - gyro_cal->bias_x;
|
||
|
*yo = yi - gyro_cal->bias_y;
|
||
|
*zo = zi - gyro_cal->bias_z;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Returns true when a new gyro calibration is available.
|
||
|
bool gyroCalNewBiasAvailable(struct GyroCal* 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;
|
||
|
}
|
||
|
|
||
|
// Update the gyro calibration with gyro data [rad/sec].
|
||
|
void gyroCalUpdateGyro(struct GyroCal* gyro_cal, uint64_t sample_time_nanos,
|
||
|
float x, float y, float z, float temperature_celsius) {
|
||
|
// Make sure that a valid window end-time is set, and start the watchdog
|
||
|
// timer.
|
||
|
if (gyro_cal->stillness_win_endtime_nanos <= 0) {
|
||
|
gyro_cal->stillness_win_endtime_nanos =
|
||
|
sample_time_nanos + gyro_cal->window_time_duration_nanos;
|
||
|
|
||
|
// Start the watchdog timer.
|
||
|
gyro_cal->gyro_watchdog_start_nanos = sample_time_nanos;
|
||
|
}
|
||
|
|
||
|
// Update the temperature statistics.
|
||
|
gyroTemperatureStatsTracker(gyro_cal, temperature_celsius, DO_UPDATE_DATA);
|
||
|
|
||
|
#ifdef GYRO_CAL_DBG_ENABLED
|
||
|
// Update the gyro sampling rate estimate.
|
||
|
sampleRateEstimatorUpdate(&gyro_cal->debug_gyro_cal.sample_rate_estimator,
|
||
|
sample_time_nanos);
|
||
|
#endif // GYRO_CAL_DBG_ENABLED
|
||
|
|
||
|
// Pass gyro data to stillness detector
|
||
|
gyroStillDetUpdate(&gyro_cal->gyro_stillness_detect,
|
||
|
gyro_cal->stillness_win_endtime_nanos, sample_time_nanos,
|
||
|
x, y, z);
|
||
|
|
||
|
// Perform a device stillness check, set next window end-time, and
|
||
|
// possibly do a gyro bias calibration and stillness detector reset.
|
||
|
deviceStillnessCheck(gyro_cal, sample_time_nanos);
|
||
|
}
|
||
|
|
||
|
// Update the gyro calibration with mag data [micro Tesla].
|
||
|
void gyroCalUpdateMag(struct GyroCal* gyro_cal, uint64_t sample_time_nanos,
|
||
|
float x, float y, float z) {
|
||
|
// Pass magnetometer data to stillness detector.
|
||
|
gyroStillDetUpdate(&gyro_cal->mag_stillness_detect,
|
||
|
gyro_cal->stillness_win_endtime_nanos, sample_time_nanos,
|
||
|
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.
|
||
|
deviceStillnessCheck(gyro_cal, sample_time_nanos);
|
||
|
}
|
||
|
|
||
|
// Update the gyro calibration with accel data [m/sec^2].
|
||
|
void gyroCalUpdateAccel(struct GyroCal* gyro_cal, uint64_t sample_time_nanos,
|
||
|
float x, float y, float z) {
|
||
|
// Pass accelerometer data to stillnesss detector.
|
||
|
gyroStillDetUpdate(&gyro_cal->accel_stillness_detect,
|
||
|
gyro_cal->stillness_win_endtime_nanos, sample_time_nanos,
|
||
|
x, y, z);
|
||
|
|
||
|
// Perform a device stillness check, set next window end-time, and
|
||
|
// possibly do a gyro bias calibration and stillness detector reset.
|
||
|
deviceStillnessCheck(gyro_cal, sample_time_nanos);
|
||
|
}
|
||
|
|
||
|
// TODO: Consider breaking this function up to improve readability.
|
||
|
// Checks the state of all stillness detectors to determine
|
||
|
// whether the device is "still".
|
||
|
void deviceStillnessCheck(struct GyroCal* gyro_cal,
|
||
|
uint64_t sample_time_nanos) {
|
||
|
bool stillness_duration_exceeded = false;
|
||
|
bool stillness_duration_too_short = false;
|
||
|
bool min_max_temp_exceeded = false;
|
||
|
bool mean_not_stable = false;
|
||
|
bool device_is_still = false;
|
||
|
float conf_not_rot = 0;
|
||
|
float conf_not_accel = 0;
|
||
|
float conf_still = 0;
|
||
|
|
||
|
// Check the watchdog timer.
|
||
|
checkWatchdog(gyro_cal, sample_time_nanos);
|
||
|
|
||
|
// 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_nanos =
|
||
|
sample_time_nanos + gyro_cal->window_time_duration_nanos;
|
||
|
|
||
|
// Update the confidence scores for all sensors.
|
||
|
gyroStillDetCompute(&gyro_cal->accel_stillness_detect);
|
||
|
gyroStillDetCompute(&gyro_cal->gyro_stillness_detect);
|
||
|
if (gyro_cal->using_mag_sensor) {
|
||
|
gyroStillDetCompute(&gyro_cal->mag_stillness_detect);
|
||
|
} else {
|
||
|
// Not using magnetometer, force stillness confidence to 100%.
|
||
|
gyro_cal->mag_stillness_detect.stillness_confidence = 1.0f;
|
||
|
}
|
||
|
|
||
|
// Updates the mean tracker data.
|
||
|
gyroStillMeanTracker(gyro_cal, DO_UPDATE_DATA);
|
||
|
|
||
|
// Determine motion confidence scores (rotation, accelerating, and stillness).
|
||
|
conf_not_rot = 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 = conf_not_rot * conf_not_accel;
|
||
|
|
||
|
// Evaluate the mean and temperature gate functions.
|
||
|
mean_not_stable = gyroStillMeanTracker(gyro_cal, DO_EVALUATE);
|
||
|
min_max_temp_exceeded =
|
||
|
gyroTemperatureStatsTracker(gyro_cal, 0.0f, DO_EVALUATE);
|
||
|
|
||
|
// 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) {
|
||
|
// 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.
|
||
|
|
||
|
// 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_nanos =
|
||
|
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_nanos + gyro_cal->max_still_duration_nanos);
|
||
|
|
||
|
// Track the new stillness mean and temperature data.
|
||
|
gyroStillMeanTracker(gyro_cal, DO_STORE_DATA);
|
||
|
gyroTemperatureStatsTracker(gyro_cal, 0.0f, DO_STORE_DATA);
|
||
|
|
||
|
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.
|
||
|
gyroStillDetReset(&gyro_cal->accel_stillness_detect,
|
||
|
/*reset_stats=*/true);
|
||
|
gyroStillDetReset(&gyro_cal->gyro_stillness_detect, /*reset_stats=*/true);
|
||
|
gyroStillDetReset(&gyro_cal->mag_stillness_detect, /*reset_stats=*/true);
|
||
|
|
||
|
// Resets the local calculations because the stillness period is over.
|
||
|
gyroStillMeanTracker(gyro_cal, DO_RESET);
|
||
|
gyroTemperatureStatsTracker(gyro_cal, 0.0f, DO_RESET);
|
||
|
|
||
|
// Computes a new gyro offset estimate.
|
||
|
computeGyroCal(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.
|
||
|
gyroStillDetReset(&gyro_cal->accel_stillness_detect,
|
||
|
/*reset_stats=*/false);
|
||
|
gyroStillDetReset(&gyro_cal->gyro_stillness_detect,
|
||
|
/*reset_stats=*/false);
|
||
|
gyroStillDetReset(&gyro_cal->mag_stillness_detect, /*reset_stats=*/false);
|
||
|
|
||
|
// Update the stillness flag.
|
||
|
gyro_cal->prev_still = true;
|
||
|
}
|
||
|
} else {
|
||
|
// 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.
|
||
|
stillness_duration_too_short =
|
||
|
(gyro_cal->gyro_stillness_detect.window_start_time <
|
||
|
gyro_cal->start_still_time_nanos + gyro_cal->min_still_duration_nanos);
|
||
|
|
||
|
if (gyro_cal->prev_still && !stillness_duration_too_short) {
|
||
|
computeGyroCal(gyro_cal,
|
||
|
gyro_cal->gyro_stillness_detect.window_start_time);
|
||
|
}
|
||
|
|
||
|
// Reset the stillness detectors and the stats.
|
||
|
gyroStillDetReset(&gyro_cal->accel_stillness_detect, /*reset_stats=*/true);
|
||
|
gyroStillDetReset(&gyro_cal->gyro_stillness_detect, /*reset_stats=*/true);
|
||
|
gyroStillDetReset(&gyro_cal->mag_stillness_detect, /*reset_stats=*/true);
|
||
|
|
||
|
// Resets the temperature and sensor mean data.
|
||
|
gyroTemperatureStatsTracker(gyro_cal, 0.0f, DO_RESET);
|
||
|
gyroStillMeanTracker(gyro_cal, DO_RESET);
|
||
|
|
||
|
// Update stillness flag.
|
||
|
gyro_cal->prev_still = false;
|
||
|
}
|
||
|
|
||
|
// Reset the watchdog timer after we have processed data.
|
||
|
gyro_cal->gyro_watchdog_start_nanos = sample_time_nanos;
|
||
|
}
|
||
|
|
||
|
// Calculates a new gyro bias offset calibration value.
|
||
|
void computeGyroCal(struct GyroCal* gyro_cal, uint64_t calibration_time_nanos) {
|
||
|
// 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)) {
|
||
|
#ifdef GYRO_CAL_DBG_ENABLED
|
||
|
CAL_DEBUG_LOG(
|
||
|
"[GYRO_CAL:REJECT]",
|
||
|
"Offset|Temp|Time [mDPS|C|nsec]: " CAL_FORMAT_3DIGITS_TRIPLET
|
||
|
", " CAL_FORMAT_3DIGITS ", %" PRIu64,
|
||
|
CAL_ENCODE_FLOAT(
|
||
|
gyro_cal->gyro_stillness_detect.prev_mean_x * RAD_TO_MDEG, 3),
|
||
|
CAL_ENCODE_FLOAT(
|
||
|
gyro_cal->gyro_stillness_detect.prev_mean_y * RAD_TO_MDEG, 3),
|
||
|
CAL_ENCODE_FLOAT(
|
||
|
gyro_cal->gyro_stillness_detect.prev_mean_z * RAD_TO_MDEG, 3),
|
||
|
CAL_ENCODE_FLOAT(gyro_cal->temperature_mean_celsius, 3),
|
||
|
calibration_time_nanos);
|
||
|
#endif // GYRO_CAL_DBG_ENABLED
|
||
|
|
||
|
// 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_celsius = gyro_cal->temperature_mean_celsius;
|
||
|
|
||
|
// Store the calibration time stamp.
|
||
|
gyro_cal->calibration_time_nanos = calibration_time_nanos;
|
||
|
|
||
|
// Record the final stillness confidence.
|
||
|
gyro_cal->stillness_confidence =
|
||
|
gyro_cal->gyro_stillness_detect.prev_stillness_confidence *
|
||
|
gyro_cal->accel_stillness_detect.prev_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;
|
||
|
|
||
|
#ifdef GYRO_CAL_DBG_ENABLED
|
||
|
// Increment the total count of calibration updates.
|
||
|
gyro_cal->debug_calibration_count++;
|
||
|
|
||
|
// Update the calibration debug information and trigger a printout.
|
||
|
gyroCalUpdateDebug(gyro_cal);
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
// Check for a watchdog timeout condition.
|
||
|
void checkWatchdog(struct GyroCal* gyro_cal, uint64_t sample_time_nanos) {
|
||
|
bool watchdog_timeout;
|
||
|
|
||
|
// Check for initialization of the watchdog time (=0).
|
||
|
if (gyro_cal->gyro_watchdog_start_nanos <= 0) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// Checks for the following watchdog timeout conditions:
|
||
|
// i. The current timestamp has exceeded the allowed watchdog duration.
|
||
|
// ii. A timestamp was received that has jumped backwards by more than the
|
||
|
// allowed watchdog duration (e.g., timestamp clock roll-over).
|
||
|
watchdog_timeout =
|
||
|
(sample_time_nanos > gyro_cal->gyro_watchdog_timeout_duration_nanos +
|
||
|
gyro_cal->gyro_watchdog_start_nanos) ||
|
||
|
(sample_time_nanos + gyro_cal->gyro_watchdog_timeout_duration_nanos <
|
||
|
gyro_cal->gyro_watchdog_start_nanos);
|
||
|
|
||
|
// If a timeout occurred then reset to known good state.
|
||
|
if (watchdog_timeout) {
|
||
|
#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]: %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]: %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
|
||
|
|
||
|
// Reset stillness detectors and restart data capture.
|
||
|
gyroStillDetReset(&gyro_cal->accel_stillness_detect, /*reset_stats=*/true);
|
||
|
gyroStillDetReset(&gyro_cal->gyro_stillness_detect, /*reset_stats=*/true);
|
||
|
gyroStillDetReset(&gyro_cal->mag_stillness_detect, /*reset_stats=*/true);
|
||
|
|
||
|
// Resets the temperature and sensor mean data.
|
||
|
gyroTemperatureStatsTracker(gyro_cal, 0.0f, DO_RESET);
|
||
|
gyroStillMeanTracker(gyro_cal, DO_RESET);
|
||
|
|
||
|
// Resets the stillness window end-time.
|
||
|
gyro_cal->stillness_win_endtime_nanos = 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 watchdog timeout flags.
|
||
|
gyro_cal->gyro_watchdog_start_nanos = 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// TODO -- Combine the following two functions into one or consider
|
||
|
// implementing a separate helper module for tracking the temperature and mean
|
||
|
// statistics.
|
||
|
bool gyroTemperatureStatsTracker(struct GyroCal* gyro_cal,
|
||
|
float temperature_celsius,
|
||
|
enum GyroCalTrackerCommand do_this) {
|
||
|
bool min_max_temp_exceeded = false;
|
||
|
|
||
|
switch (do_this) {
|
||
|
case DO_RESET:
|
||
|
// Resets the mean accumulator.
|
||
|
gyro_cal->temperature_mean_tracker.num_points = 0;
|
||
|
gyro_cal->temperature_mean_tracker.mean_accumulator = 0.0f;
|
||
|
|
||
|
// Initializes the min/max temperatures values.
|
||
|
gyro_cal->temperature_mean_tracker.temperature_min_celsius = FLT_MAX;
|
||
|
gyro_cal->temperature_mean_tracker.temperature_max_celsius = -FLT_MAX;
|
||
|
break;
|
||
|
|
||
|
case DO_UPDATE_DATA:
|
||
|
// Does the mean accumulation.
|
||
|
gyro_cal->temperature_mean_tracker.mean_accumulator +=
|
||
|
temperature_celsius;
|
||
|
gyro_cal->temperature_mean_tracker.num_points++;
|
||
|
|
||
|
// Tracks the min, max, and latest temperature values.
|
||
|
gyro_cal->temperature_mean_tracker.latest_temperature_celsius =
|
||
|
temperature_celsius;
|
||
|
if (gyro_cal->temperature_mean_tracker.temperature_min_celsius >
|
||
|
temperature_celsius) {
|
||
|
gyro_cal->temperature_mean_tracker.temperature_min_celsius =
|
||
|
temperature_celsius;
|
||
|
}
|
||
|
if (gyro_cal->temperature_mean_tracker.temperature_max_celsius <
|
||
|
temperature_celsius) {
|
||
|
gyro_cal->temperature_mean_tracker.temperature_max_celsius =
|
||
|
temperature_celsius;
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case DO_STORE_DATA:
|
||
|
// Store the most recent temperature statistics data to the GyroCal 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_celsius =
|
||
|
gyro_cal->temperature_mean_tracker.mean_accumulator /
|
||
|
gyro_cal->temperature_mean_tracker.num_points;
|
||
|
} else {
|
||
|
gyro_cal->temperature_mean_celsius =
|
||
|
gyro_cal->temperature_mean_tracker.latest_temperature_celsius;
|
||
|
#ifdef GYRO_CAL_DBG_ENABLED
|
||
|
CAL_DEBUG_LOG("[GYRO_CAL:TEMP_GATE]",
|
||
|
"Insufficient statistics (num_points = 0), using latest "
|
||
|
"measured temperature as the mean value.");
|
||
|
#endif // GYRO_CAL_DBG_ENABLED
|
||
|
}
|
||
|
#ifdef GYRO_CAL_DBG_ENABLED
|
||
|
// Records the min/max and mean temperature values for debug purposes.
|
||
|
gyro_cal->debug_gyro_cal.temperature_mean_celsius =
|
||
|
gyro_cal->temperature_mean_celsius;
|
||
|
gyro_cal->debug_gyro_cal.temperature_min_celsius =
|
||
|
gyro_cal->temperature_mean_tracker.temperature_min_celsius;
|
||
|
gyro_cal->debug_gyro_cal.temperature_max_celsius =
|
||
|
gyro_cal->temperature_mean_tracker.temperature_max_celsius;
|
||
|
#endif
|
||
|
break;
|
||
|
|
||
|
case DO_EVALUATE:
|
||
|
// 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_celsius -
|
||
|
gyro_cal->temperature_mean_tracker.temperature_min_celsius) >
|
||
|
gyro_cal->temperature_delta_limit_celsius;
|
||
|
|
||
|
#ifdef GYRO_CAL_DBG_ENABLED
|
||
|
if (min_max_temp_exceeded) {
|
||
|
CAL_DEBUG_LOG(
|
||
|
"[GYRO_CAL:TEMP_GATE]",
|
||
|
"Exceeded the max temperature variation during stillness.");
|
||
|
}
|
||
|
#endif // GYRO_CAL_DBG_ENABLED
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
return min_max_temp_exceeded;
|
||
|
}
|
||
|
|
||
|
bool gyroStillMeanTracker(struct GyroCal* gyro_cal,
|
||
|
enum GyroCalTrackerCommand do_this) {
|
||
|
bool mean_not_stable = false;
|
||
|
|
||
|
switch (do_this) {
|
||
|
case DO_RESET:
|
||
|
// Resets the min/max window mean values to a default value.
|
||
|
for (size_t 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;
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case DO_UPDATE_DATA:
|
||
|
// Computes the min/max window mean values.
|
||
|
if (gyro_cal->window_mean_tracker.gyro_winmean_min[0] >
|
||
|
gyro_cal->gyro_stillness_detect.win_mean_x) {
|
||
|
gyro_cal->window_mean_tracker.gyro_winmean_min[0] =
|
||
|
gyro_cal->gyro_stillness_detect.win_mean_x;
|
||
|
}
|
||
|
if (gyro_cal->window_mean_tracker.gyro_winmean_max[0] <
|
||
|
gyro_cal->gyro_stillness_detect.win_mean_x) {
|
||
|
gyro_cal->window_mean_tracker.gyro_winmean_max[0] =
|
||
|
gyro_cal->gyro_stillness_detect.win_mean_x;
|
||
|
}
|
||
|
|
||
|
if (gyro_cal->window_mean_tracker.gyro_winmean_min[1] >
|
||
|
gyro_cal->gyro_stillness_detect.win_mean_y) {
|
||
|
gyro_cal->window_mean_tracker.gyro_winmean_min[1] =
|
||
|
gyro_cal->gyro_stillness_detect.win_mean_y;
|
||
|
}
|
||
|
if (gyro_cal->window_mean_tracker.gyro_winmean_max[1] <
|
||
|
gyro_cal->gyro_stillness_detect.win_mean_y) {
|
||
|
gyro_cal->window_mean_tracker.gyro_winmean_max[1] =
|
||
|
gyro_cal->gyro_stillness_detect.win_mean_y;
|
||
|
}
|
||
|
|
||
|
if (gyro_cal->window_mean_tracker.gyro_winmean_min[2] >
|
||
|
gyro_cal->gyro_stillness_detect.win_mean_z) {
|
||
|
gyro_cal->window_mean_tracker.gyro_winmean_min[2] =
|
||
|
gyro_cal->gyro_stillness_detect.win_mean_z;
|
||
|
}
|
||
|
if (gyro_cal->window_mean_tracker.gyro_winmean_max[2] <
|
||
|
gyro_cal->gyro_stillness_detect.win_mean_z) {
|
||
|
gyro_cal->window_mean_tracker.gyro_winmean_max[2] =
|
||
|
gyro_cal->gyro_stillness_detect.win_mean_z;
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case DO_STORE_DATA:
|
||
|
// Store the most recent "stillness" mean data to the GyroCal 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));
|
||
|
break;
|
||
|
|
||
|
case DO_EVALUATE:
|
||
|
// Performs the stability check and returns the 'true' if the difference
|
||
|
// between min/max window mean value is outside the stable range.
|
||
|
for (size_t i = 0; i < 3; 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;
|
||
|
}
|
||
|
#ifdef GYRO_CAL_DBG_ENABLED
|
||
|
if (mean_not_stable) {
|
||
|
CAL_DEBUG_LOG(
|
||
|
"[GYRO_CAL:MEAN_STABILITY_GATE]",
|
||
|
"Variation Limit|Delta [mDPS]: " CAL_FORMAT_3DIGITS
|
||
|
" | " CAL_FORMAT_3DIGITS_TRIPLET,
|
||
|
CAL_ENCODE_FLOAT(gyro_cal->stillness_mean_delta_limit * RAD_TO_MDEG,
|
||
|
3),
|
||
|
CAL_ENCODE_FLOAT(
|
||
|
(gyro_cal->window_mean_tracker.gyro_winmean_max[0] -
|
||
|
gyro_cal->window_mean_tracker.gyro_winmean_min[0]) *
|
||
|
RAD_TO_MDEG,
|
||
|
3),
|
||
|
CAL_ENCODE_FLOAT(
|
||
|
(gyro_cal->window_mean_tracker.gyro_winmean_max[1] -
|
||
|
gyro_cal->window_mean_tracker.gyro_winmean_min[1]) *
|
||
|
RAD_TO_MDEG,
|
||
|
3),
|
||
|
CAL_ENCODE_FLOAT(
|
||
|
(gyro_cal->window_mean_tracker.gyro_winmean_max[2] -
|
||
|
gyro_cal->window_mean_tracker.gyro_winmean_min[2]) *
|
||
|
RAD_TO_MDEG,
|
||
|
3));
|
||
|
}
|
||
|
#endif // GYRO_CAL_DBG_ENABLED
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
return mean_not_stable;
|
||
|
}
|
||
|
|
||
|
#ifdef GYRO_CAL_DBG_ENABLED
|
||
|
void gyroCalUpdateDebug(struct GyroCal* gyro_cal) {
|
||
|
// Only update this data if debug printing is not currently in progress
|
||
|
// (i.e., don't want to risk overwriting debug information that is actively
|
||
|
// being reported).
|
||
|
if (gyro_cal->debug_state != GYRO_IDLE) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// Probability of stillness (acc, rot, still), duration, timestamp.
|
||
|
gyro_cal->debug_gyro_cal.accel_stillness_conf =
|
||
|
gyro_cal->accel_stillness_detect.prev_stillness_confidence;
|
||
|
gyro_cal->debug_gyro_cal.gyro_stillness_conf =
|
||
|
gyro_cal->gyro_stillness_detect.prev_stillness_confidence;
|
||
|
gyro_cal->debug_gyro_cal.mag_stillness_conf =
|
||
|
gyro_cal->mag_stillness_detect.prev_stillness_confidence;
|
||
|
|
||
|
// Magnetometer usage.
|
||
|
gyro_cal->debug_gyro_cal.using_mag_sensor = gyro_cal->using_mag_sensor;
|
||
|
|
||
|
// Stillness start, stop, and duration times.
|
||
|
gyro_cal->debug_gyro_cal.start_still_time_nanos =
|
||
|
gyro_cal->start_still_time_nanos;
|
||
|
gyro_cal->debug_gyro_cal.end_still_time_nanos =
|
||
|
gyro_cal->calibration_time_nanos;
|
||
|
gyro_cal->debug_gyro_cal.stillness_duration_nanos =
|
||
|
gyro_cal->calibration_time_nanos - gyro_cal->start_still_time_nanos;
|
||
|
|
||
|
// Records the current calibration values.
|
||
|
gyro_cal->debug_gyro_cal.calibration[0] = gyro_cal->bias_x;
|
||
|
gyro_cal->debug_gyro_cal.calibration[1] = gyro_cal->bias_y;
|
||
|
gyro_cal->debug_gyro_cal.calibration[2] = gyro_cal->bias_z;
|
||
|
|
||
|
// Records the min/max gyroscope window stillness mean values.
|
||
|
memcpy(gyro_cal->debug_gyro_cal.gyro_winmean_min, gyro_cal->gyro_winmean_min,
|
||
|
sizeof(gyro_cal->gyro_winmean_min));
|
||
|
memcpy(gyro_cal->debug_gyro_cal.gyro_winmean_max, gyro_cal->gyro_winmean_max,
|
||
|
sizeof(gyro_cal->gyro_winmean_max));
|
||
|
|
||
|
// Records the previous stillness window means.
|
||
|
gyro_cal->debug_gyro_cal.accel_mean[0] =
|
||
|
gyro_cal->accel_stillness_detect.prev_mean_x;
|
||
|
gyro_cal->debug_gyro_cal.accel_mean[1] =
|
||
|
gyro_cal->accel_stillness_detect.prev_mean_y;
|
||
|
gyro_cal->debug_gyro_cal.accel_mean[2] =
|
||
|
gyro_cal->accel_stillness_detect.prev_mean_z;
|
||
|
|
||
|
gyro_cal->debug_gyro_cal.gyro_mean[0] =
|
||
|
gyro_cal->gyro_stillness_detect.prev_mean_x;
|
||
|
gyro_cal->debug_gyro_cal.gyro_mean[1] =
|
||
|
gyro_cal->gyro_stillness_detect.prev_mean_y;
|
||
|
gyro_cal->debug_gyro_cal.gyro_mean[2] =
|
||
|
gyro_cal->gyro_stillness_detect.prev_mean_z;
|
||
|
|
||
|
gyro_cal->debug_gyro_cal.mag_mean[0] =
|
||
|
gyro_cal->mag_stillness_detect.prev_mean_x;
|
||
|
gyro_cal->debug_gyro_cal.mag_mean[1] =
|
||
|
gyro_cal->mag_stillness_detect.prev_mean_y;
|
||
|
gyro_cal->debug_gyro_cal.mag_mean[2] =
|
||
|
gyro_cal->mag_stillness_detect.prev_mean_z;
|
||
|
|
||
|
// Records the variance data.
|
||
|
// NOTE: These statistics include the final captured window, which may be
|
||
|
// outside of the "stillness" period. Therefore, these values may exceed the
|
||
|
// stillness thresholds.
|
||
|
gyro_cal->debug_gyro_cal.accel_var[0] =
|
||
|
gyro_cal->accel_stillness_detect.win_var_x;
|
||
|
gyro_cal->debug_gyro_cal.accel_var[1] =
|
||
|
gyro_cal->accel_stillness_detect.win_var_y;
|
||
|
gyro_cal->debug_gyro_cal.accel_var[2] =
|
||
|
gyro_cal->accel_stillness_detect.win_var_z;
|
||
|
|
||
|
gyro_cal->debug_gyro_cal.gyro_var[0] =
|
||
|
gyro_cal->gyro_stillness_detect.win_var_x;
|
||
|
gyro_cal->debug_gyro_cal.gyro_var[1] =
|
||
|
gyro_cal->gyro_stillness_detect.win_var_y;
|
||
|
gyro_cal->debug_gyro_cal.gyro_var[2] =
|
||
|
gyro_cal->gyro_stillness_detect.win_var_z;
|
||
|
|
||
|
gyro_cal->debug_gyro_cal.mag_var[0] =
|
||
|
gyro_cal->mag_stillness_detect.win_var_x;
|
||
|
gyro_cal->debug_gyro_cal.mag_var[1] =
|
||
|
gyro_cal->mag_stillness_detect.win_var_y;
|
||
|
gyro_cal->debug_gyro_cal.mag_var[2] =
|
||
|
gyro_cal->mag_stillness_detect.win_var_z;
|
||
|
|
||
|
// Trigger a printout of the debug information.
|
||
|
gyro_cal->debug_print_trigger = true;
|
||
|
}
|
||
|
|
||
|
void gyroCalDebugPrintData(const struct GyroCal* gyro_cal, char* debug_tag,
|
||
|
enum DebugPrintData print_data) {
|
||
|
// Prints out the desired debug data.
|
||
|
float mag_data;
|
||
|
switch (print_data) {
|
||
|
case OFFSET:
|
||
|
CAL_DEBUG_LOG(
|
||
|
debug_tag,
|
||
|
"Cal#|Offset|Temp|Time [mDPS|C|nsec]: "
|
||
|
"%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(
|
||
|
gyro_cal->debug_gyro_cal.calibration[1] * RAD_TO_MDEG, 3),
|
||
|
CAL_ENCODE_FLOAT(
|
||
|
gyro_cal->debug_gyro_cal.calibration[2] * RAD_TO_MDEG, 3),
|
||
|
CAL_ENCODE_FLOAT(gyro_cal->debug_gyro_cal.temperature_mean_celsius,
|
||
|
3),
|
||
|
gyro_cal->debug_gyro_cal.end_still_time_nanos);
|
||
|
break;
|
||
|
|
||
|
case STILLNESS_DATA:
|
||
|
mag_data = (gyro_cal->debug_gyro_cal.using_mag_sensor)
|
||
|
? gyro_cal->debug_gyro_cal.mag_stillness_conf
|
||
|
: -1.0f; // Signals that magnetometer was not used.
|
||
|
CAL_DEBUG_LOG(
|
||
|
debug_tag,
|
||
|
"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));
|
||
|
break;
|
||
|
|
||
|
case SAMPLE_RATE_AND_TEMPERATURE:
|
||
|
CAL_DEBUG_LOG(
|
||
|
debug_tag,
|
||
|
"Cal#|Mean|Min|Max|Delta|Sample Rate [C|Hz]: "
|
||
|
"%zu, " CAL_FORMAT_3DIGITS_TRIPLET ", " CAL_FORMAT_3DIGITS
|
||
|
", " CAL_FORMAT_3DIGITS,
|
||
|
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),
|
||
|
CAL_ENCODE_FLOAT(gyro_cal->debug_gyro_cal.temperature_max_celsius, 3),
|
||
|
CAL_ENCODE_FLOAT(gyro_cal->debug_gyro_cal.temperature_max_celsius -
|
||
|
gyro_cal->debug_gyro_cal.temperature_min_celsius,
|
||
|
3),
|
||
|
CAL_ENCODE_FLOAT(gyro_cal->debug_gyro_cal.sample_rate_estimator
|
||
|
.mean_sampling_rate_estimate_hz,
|
||
|
3));
|
||
|
break;
|
||
|
|
||
|
case GYRO_MINMAX_STILLNESS_MEAN:
|
||
|
CAL_DEBUG_LOG(
|
||
|
debug_tag,
|
||
|
"Cal#|Gyro Peak Stillness Variation [mDPS]: "
|
||
|
"%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,
|
||
|
3),
|
||
|
CAL_ENCODE_FLOAT((gyro_cal->debug_gyro_cal.gyro_winmean_max[1] -
|
||
|
gyro_cal->debug_gyro_cal.gyro_winmean_min[1]) *
|
||
|
RAD_TO_MDEG,
|
||
|
3),
|
||
|
CAL_ENCODE_FLOAT((gyro_cal->debug_gyro_cal.gyro_winmean_max[2] -
|
||
|
gyro_cal->debug_gyro_cal.gyro_winmean_min[2]) *
|
||
|
RAD_TO_MDEG,
|
||
|
3));
|
||
|
break;
|
||
|
|
||
|
case ACCEL_STATS:
|
||
|
CAL_DEBUG_LOG(debug_tag,
|
||
|
"Cal#|Accel Mean|Var [m/sec^2|(m/sec^2)^2]: "
|
||
|
"%zu, " CAL_FORMAT_3DIGITS_TRIPLET
|
||
|
", " CAL_FORMAT_6DIGITS_TRIPLET,
|
||
|
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),
|
||
|
CAL_ENCODE_FLOAT(gyro_cal->debug_gyro_cal.accel_var[0], 6),
|
||
|
CAL_ENCODE_FLOAT(gyro_cal->debug_gyro_cal.accel_var[1], 6),
|
||
|
CAL_ENCODE_FLOAT(gyro_cal->debug_gyro_cal.accel_var[2], 6));
|
||
|
break;
|
||
|
|
||
|
case GYRO_STATS:
|
||
|
CAL_DEBUG_LOG(
|
||
|
debug_tag,
|
||
|
"Cal#|Gyro Mean|Var [mDPS|mDPS^2]: %zu, " CAL_FORMAT_3DIGITS_TRIPLET
|
||
|
", " CAL_FORMAT_3DIGITS_TRIPLET,
|
||
|
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,
|
||
|
3),
|
||
|
CAL_ENCODE_FLOAT(gyro_cal->debug_gyro_cal.gyro_mean[2] * RAD_TO_MDEG,
|
||
|
3),
|
||
|
CAL_ENCODE_FLOAT(
|
||
|
gyro_cal->debug_gyro_cal.gyro_var[0] * RAD_TO_MDEG * RAD_TO_MDEG,
|
||
|
3),
|
||
|
CAL_ENCODE_FLOAT(
|
||
|
gyro_cal->debug_gyro_cal.gyro_var[1] * RAD_TO_MDEG * RAD_TO_MDEG,
|
||
|
3),
|
||
|
CAL_ENCODE_FLOAT(
|
||
|
gyro_cal->debug_gyro_cal.gyro_var[2] * RAD_TO_MDEG * RAD_TO_MDEG,
|
||
|
3));
|
||
|
break;
|
||
|
|
||
|
case MAG_STATS:
|
||
|
if (gyro_cal->debug_gyro_cal.using_mag_sensor) {
|
||
|
CAL_DEBUG_LOG(
|
||
|
debug_tag,
|
||
|
"Cal#|Mag Mean|Var [uT|uT^2]: %zu, " CAL_FORMAT_3DIGITS_TRIPLET
|
||
|
", " CAL_FORMAT_6DIGITS_TRIPLET,
|
||
|
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),
|
||
|
CAL_ENCODE_FLOAT(gyro_cal->debug_gyro_cal.mag_var[0], 6),
|
||
|
CAL_ENCODE_FLOAT(gyro_cal->debug_gyro_cal.mag_var[1], 6),
|
||
|
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]: %zu, 0, 0, 0, -1.0, -1.0, "
|
||
|
"-1.0",
|
||
|
gyro_cal->debug_calibration_count);
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void gyroCalDebugPrint(struct GyroCal* gyro_cal, uint64_t timestamp_nanos) {
|
||
|
// This is a state machine that controls the reporting out of debug data.
|
||
|
switch (gyro_cal->debug_state) {
|
||
|
case GYRO_IDLE:
|
||
|
// Wait for a trigger and start the debug printout sequence.
|
||
|
if (gyro_cal->debug_print_trigger) {
|
||
|
CAL_DEBUG_LOG(GYROCAL_REPORT_TAG, "");
|
||
|
CAL_DEBUG_LOG(GYROCAL_REPORT_TAG, "Debug Version: %s",
|
||
|
GYROCAL_DEBUG_VERSION_STRING);
|
||
|
gyro_cal->debug_print_trigger = false; // Resets trigger.
|
||
|
gyro_cal->debug_state = GYRO_PRINT_OFFSET;
|
||
|
} else {
|
||
|
gyro_cal->debug_state = GYRO_IDLE;
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case GYRO_WAIT_STATE:
|
||
|
// This helps throttle the print statements.
|
||
|
if (NANO_TIMER_CHECK_T1_GEQUAL_T2_PLUS_DELTA(timestamp_nanos,
|
||
|
gyro_cal->wait_timer_nanos,
|
||
|
GYROCAL_WAIT_TIME_NANOS)) {
|
||
|
gyro_cal->debug_state = gyro_cal->next_state;
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case GYRO_PRINT_OFFSET:
|
||
|
gyroCalDebugPrintData(gyro_cal, GYROCAL_REPORT_TAG, OFFSET);
|
||
|
gyro_cal->wait_timer_nanos = timestamp_nanos; // Starts the wait timer.
|
||
|
gyro_cal->next_state = GYRO_PRINT_STILLNESS_DATA; // Sets the next state.
|
||
|
gyro_cal->debug_state = GYRO_WAIT_STATE; // First, go to wait state.
|
||
|
break;
|
||
|
|
||
|
case GYRO_PRINT_STILLNESS_DATA:
|
||
|
gyroCalDebugPrintData(gyro_cal, GYROCAL_REPORT_TAG, STILLNESS_DATA);
|
||
|
gyro_cal->wait_timer_nanos = timestamp_nanos; // Starts the wait timer.
|
||
|
gyro_cal->next_state =
|
||
|
GYRO_PRINT_SAMPLE_RATE_AND_TEMPERATURE; // Sets next state.
|
||
|
gyro_cal->debug_state = GYRO_WAIT_STATE; // First, go to wait state.
|
||
|
break;
|
||
|
|
||
|
case GYRO_PRINT_SAMPLE_RATE_AND_TEMPERATURE:
|
||
|
gyroCalDebugPrintData(gyro_cal, GYROCAL_REPORT_TAG,
|
||
|
SAMPLE_RATE_AND_TEMPERATURE);
|
||
|
gyro_cal->wait_timer_nanos = timestamp_nanos; // Starts the wait timer.
|
||
|
gyro_cal->next_state =
|
||
|
GYRO_PRINT_GYRO_MINMAX_STILLNESS_MEAN; // Sets next state.
|
||
|
gyro_cal->debug_state = GYRO_WAIT_STATE; // First, go to wait state.
|
||
|
break;
|
||
|
|
||
|
case GYRO_PRINT_GYRO_MINMAX_STILLNESS_MEAN:
|
||
|
gyroCalDebugPrintData(gyro_cal, GYROCAL_REPORT_TAG,
|
||
|
GYRO_MINMAX_STILLNESS_MEAN);
|
||
|
gyro_cal->wait_timer_nanos = timestamp_nanos; // Starts the wait timer.
|
||
|
gyro_cal->next_state = GYRO_PRINT_ACCEL_STATS; // Sets the next state.
|
||
|
gyro_cal->debug_state = GYRO_WAIT_STATE; // First, go to wait state.
|
||
|
break;
|
||
|
|
||
|
case GYRO_PRINT_ACCEL_STATS:
|
||
|
gyroCalDebugPrintData(gyro_cal, GYROCAL_REPORT_TAG, ACCEL_STATS);
|
||
|
gyro_cal->wait_timer_nanos = timestamp_nanos; // Starts the wait timer.
|
||
|
gyro_cal->next_state = GYRO_PRINT_GYRO_STATS; // Sets the next state.
|
||
|
gyro_cal->debug_state = GYRO_WAIT_STATE; // First, go to wait state.
|
||
|
break;
|
||
|
|
||
|
case GYRO_PRINT_GYRO_STATS:
|
||
|
gyroCalDebugPrintData(gyro_cal, GYROCAL_REPORT_TAG, GYRO_STATS);
|
||
|
gyro_cal->wait_timer_nanos = timestamp_nanos; // Starts the wait timer.
|
||
|
gyro_cal->next_state = GYRO_PRINT_MAG_STATS; // Sets the next state.
|
||
|
gyro_cal->debug_state = GYRO_WAIT_STATE; // First, go to wait state.
|
||
|
break;
|
||
|
|
||
|
case GYRO_PRINT_MAG_STATS:
|
||
|
gyroCalDebugPrintData(gyro_cal, GYROCAL_REPORT_TAG, MAG_STATS);
|
||
|
gyro_cal->wait_timer_nanos = timestamp_nanos; // Starts the wait timer.
|
||
|
gyro_cal->next_state = GYRO_IDLE; // Sets the next state.
|
||
|
gyro_cal->debug_state = GYRO_WAIT_STATE; // First, go to wait state.
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
// Sends this state machine to its idle state.
|
||
|
gyro_cal->wait_timer_nanos = timestamp_nanos; // Starts the wait timer.
|
||
|
gyro_cal->debug_state = GYRO_IDLE; // Go to idle state.
|
||
|
}
|
||
|
}
|
||
|
#endif // GYRO_CAL_DBG_ENABLED
|