blob: 0b30fc32fe2213e786bf94002af5ce4a90d97042 [file] [log] [blame]
/*
* 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 <algos/gyro_cal.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.096f // [rad/sec]
// Helper constants for converting units.
#define RAD_TO_MDEG (float)(1e3*180.0/M_PI)
#define GRAVITY_TO_G (float)(1.0/9.80665)
/////// FORWARD DECLARATIONS /////////////////////////////////////////
static void deviceStillnessCheck(struct gyroCal_t* gyro_cal,
uint64_t sample_time);
static void computeGyroCal(struct gyroCal_t* gyro_cal,
uint64_t calibration_time);
static void checkWatchdog(struct gyroCal_t* gyro_cal,
uint64_t sample_time);
#ifdef GYRO_CAL_DBG_ENABLED
static void gyroCalUpdateDebug(struct gyroCal_t* gyro_cal,
struct debugGyroCal_t* debug_gyro_cal);
static void gyroCalTuneDebugPrint(struct gyroCal_t* gyro_cal,
uint64_t sample_time);
static void gyroCalDebugPrintData(int count,
struct debugGyroCal_t *debug_data);
// Information print macro.
#define GYRO_INFO_PRINT(fmt, ...) do { \
osLog(LOG_INFO, "%s " fmt, "[GYRO CAL]", ##__VA_ARGS__); \
} while (0);
// Macro used to print out floating point numbers.
#define GYRO_ENCODE_FLOAT(x, num_digits) ((x < 0) ? "-" : ""), \
(int)floorf(fabsf(x)), \
(int)((fabsf(x) - floorf(fabsf(x))) * powf(10,num_digits))
#endif
/////// FUNCTION DEFINITIONS /////////////////////////////////////////
// Initialize the gyro calibration data structure.
void gyroCalInit(struct gyroCal_t* gyro_cal, uint64_t min_still_duration,
uint64_t max_still_duration,
float bias_x, float bias_y, float bias_z,
uint64_t calibration_time,
uint64_t window_time_duration,
float gyro_var_threshold,
float gyro_confidence_delta,
float accel_var_threshold,
float accel_confidence_delta,
float mag_var_threshold,
float mag_confidence_delta,
float stillness_threshold,
int remove_bias_enable) {
// Clear gyro_cal structure memory.
memset(gyro_cal, 0, sizeof(struct gyroCal_t));
// 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,
gyro_var_threshold,
gyro_confidence_delta);
gyroStillDetInit(&gyro_cal->accel_stillness_detect,
accel_var_threshold,
accel_confidence_delta);
gyroStillDetInit(&gyro_cal->mag_stillness_detect,
mag_var_threshold,
mag_confidence_delta);
// Reset stillness flag and start timestamp.
gyro_cal->prev_still = false;
gyro_cal->start_still_time = 0;
// Set the min and max window stillness duration.
gyro_cal->min_still_duration = min_still_duration;
gyro_cal->max_still_duration = max_still_duration;
// Sets the duration of the stillness processing windows.
gyro_cal->window_time_duration = window_time_duration;
// Set the watchdog timeout duration.
gyro_cal->gyro_watchdog_timeout_duration =
2 * window_time_duration;
// Load the last valid cal from system memory.
gyro_cal->bias_x = bias_x; // [rad/sec]
gyro_cal->bias_y = bias_y; // [rad/sec]
gyro_cal->bias_z = bias_z; // [rad/sec]
gyro_cal->calibration_time = calibration_time;
// Set the stillness threshold required for gyro bias calibration.
gyro_cal->stillness_threshold = 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 = 0;
// Gyro calibrations will be applied (see, gyroCalRemoveBias()).
gyro_cal->gyro_calibration_enable = (remove_bias_enable > 0);
#ifdef GYRO_CAL_DBG_ENABLED
GYRO_INFO_PRINT("Gyro Cal: Initialized.");
#endif
}
// Void all pointers in the gyro calibration data structure
// (prevents compiler warnings).
void gyroCalDestroy(struct gyroCal_t* gyro_cal) {
(void)gyro_cal;
}
// Get the most recent bias calibration value.
void gyroCalGetBias(struct gyroCal_t* gyro_cal,
float* bias_x, float* bias_y, float* bias_z) {
if (gyro_cal->gyro_calibration_enable) {
*bias_x = gyro_cal->bias_x;
*bias_y = gyro_cal->bias_y;
*bias_z = gyro_cal->bias_z;
}
}
// Set an initial bias calibration value.
void gyroCalSetBias(struct gyroCal_t* gyro_cal,
float bias_x, float bias_y, float bias_z,
uint64_t calibration_time) {
gyro_cal->bias_x = bias_x;
gyro_cal->bias_y = bias_y;
gyro_cal->bias_z = bias_z;
gyro_cal->calibration_time = calibration_time;
}
// Remove bias from a gyro measurement [rad/sec].
void gyroCalRemoveBias(struct gyroCal_t* 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_t* 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_t* gyro_cal,
uint64_t sample_time,
float x, float y, float z,
float temperature) {
// Make sure that a valid window end time is set,
// and start the watchdog timer.
if (gyro_cal->stillness_win_endtime <= 0) {
gyro_cal->stillness_win_endtime =
sample_time + gyro_cal->window_time_duration;
// Start the watchdog timer.
gyro_cal->gyro_watchdog_start = sample_time;
}
// Record the latest temperture sample.
gyro_cal->latest_temperature_celcius = temperature;
// Pass gyro data to stillness detector
gyroStillDetUpdate(&gyro_cal->gyro_stillness_detect,
gyro_cal->stillness_win_endtime,
sample_time, 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);
}
// Update the gyro calibration with mag data [micro Tesla].
void gyroCalUpdateMag(struct gyroCal_t* gyro_cal,
uint64_t sample_time,
float x, float y, float z) {
// Pass magnetometer data to stillness detector.
gyroStillDetUpdate(&gyro_cal->mag_stillness_detect,
gyro_cal->stillness_win_endtime,
sample_time, 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);
}
// Update the gyro calibration with accel data [m/sec^2].
void gyroCalUpdateAccel(struct gyroCal_t* gyro_cal,
uint64_t sample_time,
float x, float y, float z) {
// Pass accelerometer data to stillnesss detector.
gyroStillDetUpdate(&gyro_cal->accel_stillness_detect,
gyro_cal->stillness_win_endtime,
sample_time, 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);
}
// Checks the state of all stillness detectors to determine
// whether the device is "still".
void deviceStillnessCheck(struct gyroCal_t* gyro_cal,
uint64_t sample_time) {
bool stillness_duration_exceeded = false;
bool stillness_duration_too_short = 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);
// 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 =
sample_time + gyro_cal->window_time_duration;
// 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;
}
// 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;
// determine if the device is currently still.
device_is_still = (conf_still > gyro_cal->stillness_threshold);
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 =
gyro_cal->gyro_stillness_detect.window_start_time;
}
// Check to see if current stillness period exceeds the desired limit
// to avoid corrupting the .
stillness_duration_exceeded =
((gyro_cal->gyro_stillness_detect.last_sample_time -
gyro_cal->start_still_time) >
gyro_cal->max_still_duration);
if (stillness_duration_exceeded) {
// The current stillness has gone too long. Do a calibration with the
// current data and reset.
// Update the gyro bias estimate with the current window data and
// reset the stats.
gyroStillDetReset(&gyro_cal->accel_stillness_detect, true);
gyroStillDetReset(&gyro_cal->gyro_stillness_detect, true);
gyroStillDetReset(&gyro_cal->mag_stillness_detect, true);
// Perform calibration.
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.
// Reset stillness detectors, and extend stillness period.
gyroStillDetReset(&gyro_cal->accel_stillness_detect, false);
gyroStillDetReset(&gyro_cal->gyro_stillness_detect, false);
gyroStillDetReset(&gyro_cal->mag_stillness_detect, false);
// Update 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) < gyro_cal->min_still_duration);
if (gyro_cal->prev_still && !stillness_duration_too_short) {
computeGyroCal(gyro_cal,
gyro_cal->gyro_stillness_detect.window_start_time);
}
// Reset stillness detectors and the stats.
gyroStillDetReset(&gyro_cal->accel_stillness_detect, true);
gyroStillDetReset(&gyro_cal->gyro_stillness_detect, true);
gyroStillDetReset(&gyro_cal->mag_stillness_detect, true);
// Update stillness flag.
gyro_cal->prev_still = false;
}
// Reset the watchdog timer after we have processed data.
gyro_cal->gyro_watchdog_start = sample_time;
#ifdef GYRO_CAL_DBG_ENABLED
// Debug information available.
gyro_cal->debug_processed_data_available = true;
gyro_cal->debug_processed_data_time = sample_time;
#endif
}
// Calculates a new gyro bias offset calibration value.
void computeGyroCal(struct gyroCal_t* gyro_cal,
uint64_t calibration_time) {
// Current calibration duration.
uint64_t cur_cal_dur =
calibration_time - gyro_cal->start_still_time;
// 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 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;
// Record 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;
// Store calibration stillness duration.
gyro_cal->calibration_time_duration = cur_cal_dur;
// Store calibration time stamp.
gyro_cal->calibration_time = calibration_time;
// 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++;
// Store the last 'DEBUG_GYRO_SHORTTERM_NUM_CAL' calibration debug data
// in a circular buffer, 'debug_cal_data[]'. 'debug_head' is the index
// of the last valid calibration.
gyro_cal->debug_head++;
if (gyro_cal->debug_head >= DEBUG_GYRO_SHORTTERM_NUM_CAL) {
gyro_cal->debug_head = 0;
}
if (gyro_cal->debug_num_cals < DEBUG_GYRO_SHORTTERM_NUM_CAL) {
gyro_cal->debug_num_cals++;
}
// Update the calibration debug information.
gyroCalUpdateDebug(gyro_cal,
&gyro_cal->debug_cal_data[gyro_cal->debug_head]);
// Improve the collection of historic calibrations. Limit frequency to
// every N hours.
if ((gyro_cal->debug_num_cals_hist <= 0) ||
(calibration_time -
gyro_cal->
debug_cal_data_hist[gyro_cal->debug_head_hist].calibration_time)
>= DEBUG_GYRO_CAL_LIMIT) {
gyro_cal->debug_head_hist++;
if (gyro_cal->debug_head_hist >= DEBUG_GYRO_LONGTERM_NUM_CAL) {
gyro_cal->debug_head_hist = 0;
}
if (gyro_cal->debug_num_cals_hist < DEBUG_GYRO_LONGTERM_NUM_CAL) {
gyro_cal->debug_num_cals_hist++;
}
// Update the calibration debug information.
gyroCalUpdateDebug(gyro_cal,
&gyro_cal->
debug_cal_data_hist[gyro_cal->debug_head_hist]);
}
#endif
}
// Check for a watchdog timeout condition.
void checkWatchdog(struct gyroCal_t* gyro_cal, uint64_t sample_time) {
bool watchdog_timeout;
// Check for initialization of the watchdog time (=0).
if (gyro_cal->gyro_watchdog_start <= 0) {
return;
}
// Check for timeout condition of watchdog.
watchdog_timeout = ((sample_time - gyro_cal->gyro_watchdog_start) >
gyro_cal->gyro_watchdog_timeout_duration);
// If a timeout occurred then reset to known good state.
if (watchdog_timeout) {
// Reset stillness detectors and restart data capture.
gyroStillDetReset(&gyro_cal->accel_stillness_detect, true);
gyroStillDetReset(&gyro_cal->gyro_stillness_detect, true);
gyroStillDetReset(&gyro_cal->mag_stillness_detect, true);
gyro_cal->mag_stillness_detect.stillness_confidence = 0;
gyro_cal->stillness_win_endtime = 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_timeout |= watchdog_timeout;
gyro_cal->gyro_watchdog_start = 0;
#ifdef GYRO_CAL_DBG_ENABLED
gyro_cal->debug_watchdog_count++;
#endif
}
}
#ifdef GYRO_CAL_DBG_ENABLED
// Update the calibration debug information.
void gyroCalUpdateDebug(struct gyroCal_t* gyro_cal,
struct debugGyroCal_t* debug_gyro_cal) {
// Probability of stillness (acc, rot, still), duration, timestamp.
debug_gyro_cal->accel_stillness_conf =
gyro_cal->accel_stillness_detect.prev_stillness_confidence;
debug_gyro_cal->gyro_stillness_conf =
gyro_cal->gyro_stillness_detect.prev_stillness_confidence;
debug_gyro_cal->mag_stillness_conf =
gyro_cal->mag_stillness_detect.prev_stillness_confidence;
// Magnetometer usage.
debug_gyro_cal->used_mag_sensor = gyro_cal->using_mag_sensor;
// Temperature at calibration time.
debug_gyro_cal->temperature_celcius =
gyro_cal->latest_temperature_celcius;
// Calibration time and stillness duration.
debug_gyro_cal->calibration_time_duration =
gyro_cal->calibration_time_duration;
debug_gyro_cal->calibration_time =
gyro_cal->calibration_time;
// Record the current calibration values
debug_gyro_cal->calibration[0] = gyro_cal->bias_x;
debug_gyro_cal->calibration[1] = gyro_cal->bias_y;
debug_gyro_cal->calibration[2] = gyro_cal->bias_z;
// Record the previous window means
debug_gyro_cal->accel_mean[0] =
gyro_cal->accel_stillness_detect.prev_mean_x;
debug_gyro_cal->accel_mean[1] =
gyro_cal->accel_stillness_detect.prev_mean_y;
debug_gyro_cal->accel_mean[2] =
gyro_cal->accel_stillness_detect.prev_mean_z;
debug_gyro_cal->gyro_mean[0] =
gyro_cal->gyro_stillness_detect.prev_mean_x;
debug_gyro_cal->gyro_mean[1] =
gyro_cal->gyro_stillness_detect.prev_mean_y;
debug_gyro_cal->gyro_mean[2] =
gyro_cal->gyro_stillness_detect.prev_mean_z;
debug_gyro_cal->mag_mean[0] =
gyro_cal->mag_stillness_detect.prev_mean_x;
debug_gyro_cal->mag_mean[1] =
gyro_cal->mag_stillness_detect.prev_mean_y;
debug_gyro_cal->mag_mean[2] =
gyro_cal->mag_stillness_detect.prev_mean_z;
// Record the variance data.
debug_gyro_cal->accel_var[0] =
gyro_cal->accel_stillness_detect.win_var_x;
debug_gyro_cal->accel_var[1] =
gyro_cal->accel_stillness_detect.win_var_y;
debug_gyro_cal->accel_var[2] =
gyro_cal->accel_stillness_detect.win_var_z;
debug_gyro_cal->gyro_var[0] =
gyro_cal->gyro_stillness_detect.win_var_x;
debug_gyro_cal->gyro_var[1] =
gyro_cal->gyro_stillness_detect.win_var_y;
debug_gyro_cal->gyro_var[2] =
gyro_cal->gyro_stillness_detect.win_var_z;
debug_gyro_cal->mag_var[0] =
gyro_cal->mag_stillness_detect.win_var_x;
debug_gyro_cal->mag_var[1] =
gyro_cal->mag_stillness_detect.win_var_y;
debug_gyro_cal->mag_var[2] =
gyro_cal->mag_stillness_detect.win_var_z;
}
// Helper function to print debug statements.
void gyroCalDebugPrintData(int count,
struct debugGyroCal_t *debug_data) {
GYRO_INFO_PRINT(
"#%d Gyro Bias Calibration = {%s%d.%06d, %s%d.%06d, %s%d.%06d} [mdps]\n",
count,
GYRO_ENCODE_FLOAT(debug_data->calibration[0] * RAD_TO_MDEG, 6),
GYRO_ENCODE_FLOAT(debug_data->calibration[1] * RAD_TO_MDEG, 6),
GYRO_ENCODE_FLOAT(debug_data->calibration[2] * RAD_TO_MDEG, 6)
);
if (debug_data->used_mag_sensor) {
GYRO_INFO_PRINT(" Using Magnetometer.\n");
} else {
GYRO_INFO_PRINT(" Not Using Magnetometer.\n");
}
GYRO_INFO_PRINT(" Temperature = %s%d.%06d [C]\n",
GYRO_ENCODE_FLOAT(debug_data->temperature_celcius, 6));
GYRO_INFO_PRINT(" Calibration Timestamp = %llu [nsec]\n",
debug_data->calibration_time);
GYRO_INFO_PRINT(" Stillness Duration = %llu [nsec]\n",
debug_data->calibration_time_duration);
GYRO_INFO_PRINT(" Accel Mean = {%s%d.%06d, %s%d.%06d, %s%d.%06d} [g]\n",
GYRO_ENCODE_FLOAT(debug_data->accel_mean[0] *
GRAVITY_TO_G, 6),
GYRO_ENCODE_FLOAT(debug_data->accel_mean[1] *
GRAVITY_TO_G, 6),
GYRO_ENCODE_FLOAT(debug_data->accel_mean[2] *
GRAVITY_TO_G, 6));
GYRO_INFO_PRINT(" Mag Mean = {%s%d.%06d, %s%d.%06d, %s%d.%06d} [uT]\n",
GYRO_ENCODE_FLOAT(debug_data->mag_mean[0], 6),
GYRO_ENCODE_FLOAT(debug_data->mag_mean[1], 6),
GYRO_ENCODE_FLOAT(debug_data->mag_mean[2], 6)
);
}
// Print Debug data useful for tuning the stillness detectors.
void gyroCalTuneDebugPrint(struct gyroCal_t* gyro_cal, uint64_t sample_time) {
static uint64_t counter = 0;
// Output sensor variance levels to assist with tuning thresholds
// every N seconds.
if ((sample_time - counter) > 10000000000) { //nsec
GYRO_INFO_PRINT("");
GYRO_INFO_PRINT(
" Gyro Variance = {%s%d.%08d, %s%d.%08d, %s%d.%08d} [rad/sec]^2\n",
GYRO_ENCODE_FLOAT(
gyro_cal->gyro_stillness_detect.win_var_x, 8),
GYRO_ENCODE_FLOAT(
gyro_cal->gyro_stillness_detect.win_var_y, 8),
GYRO_ENCODE_FLOAT(
gyro_cal->gyro_stillness_detect.win_var_z, 8));
GYRO_INFO_PRINT(
" Accel Variance = {%s%d.%08d, %s%d.%08d, %s%d.%08d} [m/sec^2]^2\n",
GYRO_ENCODE_FLOAT(
gyro_cal->accel_stillness_detect.win_var_x, 8),
GYRO_ENCODE_FLOAT(
gyro_cal->accel_stillness_detect.win_var_y, 8),
GYRO_ENCODE_FLOAT(
gyro_cal->accel_stillness_detect.win_var_z, 8));
GYRO_INFO_PRINT(
" Mag Variance = {%s%d.%06d, %s%d.%06d, %s%d.%06d} [uT]^2\n",
GYRO_ENCODE_FLOAT(
gyro_cal->mag_stillness_detect.win_var_x, 6),
GYRO_ENCODE_FLOAT(
gyro_cal->mag_stillness_detect.win_var_y, 6),
GYRO_ENCODE_FLOAT(
gyro_cal->mag_stillness_detect.win_var_z, 6));
GYRO_INFO_PRINT(
" Stillness = {G%s%d.%06d, A%s%d.%06d, M%s%d.%06d}\n",
GYRO_ENCODE_FLOAT(
gyro_cal->
gyro_stillness_detect.stillness_confidence, 6),
GYRO_ENCODE_FLOAT(
gyro_cal->
accel_stillness_detect.stillness_confidence, 6),
GYRO_ENCODE_FLOAT(
gyro_cal->
mag_stillness_detect.stillness_confidence, 6));
GYRO_INFO_PRINT(
" Temperature = %s%d.%06d [C]\n",
GYRO_ENCODE_FLOAT(
gyro_cal->latest_temperature_celcius, 6));
GYRO_INFO_PRINT("Total Gyro Calibrations: %lu\n",
gyro_cal->debug_calibration_count);
counter = sample_time; //reset
}
}
// Print Debug data report.
void gyroCalDebugPrint(struct gyroCal_t* gyro_cal,
int* state,
uint64_t sample_time) {
static int head_index;
static int i, j;
if (gyro_cal->debug_num_cals == 0) {
*state = -1; // idle state.
}
// State machine to control reporting out debug print data.
switch (*state) {
case 0:
// STATE 0 : Print out header
GYRO_INFO_PRINT("");
GYRO_INFO_PRINT(
"---DEBUG REPORT-------------------------------------\n");
GYRO_INFO_PRINT("Gyro Calibrations To Report (newest to oldest): %d\n",
gyro_cal->debug_num_cals);
head_index = gyro_cal->debug_head;
i = 1; // initialize report count
*state = 1; // set next state.
break;
case 1:
// STATE 1: Print out past N recent calibrations.
if (i <= gyro_cal->debug_num_cals) {
// Print the data.
gyroCalDebugPrintData(i, &gyro_cal->debug_cal_data[head_index]);
// Move to the previous calibration data set.
head_index--;
if (head_index < 0) {
head_index = DEBUG_GYRO_SHORTTERM_NUM_CAL-1;
}
// Increment the report count.
i++;
// Go to wait state.
j = 0;
*state = 2;
} else {
// Print out the footer data.
*state = 3;
}
break;
case 2:
// STATE 2 : Wait state.
// Wait for N cycles of gyro samples before printing out more data.
// This helps throttle the print statements.
if (j <= 50) {
j++;
} else {
*state = 1;
}
break;
case 3:
// STATE 3 : Print the end of the debug report.
GYRO_INFO_PRINT("Total Gyro Calibrations: %lu\n",
gyro_cal->debug_calibration_count);
GYRO_INFO_PRINT("Total Watchdog Timeouts: %lu\n",
gyro_cal->debug_watchdog_count);
GYRO_INFO_PRINT(
"---END DEBUG REPORT---------------------------------\n");
*state = 4;
break;
case 4:
// STATE 4 : Print out header (historic data)
GYRO_INFO_PRINT("");
GYRO_INFO_PRINT(
"---DEBUG REPORT (HISTORY)---------------------------\n");
GYRO_INFO_PRINT("Gyro Calibrations To Report (newest to oldest): %d\n",
gyro_cal->debug_num_cals_hist);
head_index = gyro_cal->debug_head_hist;
i = 1; // initialize report count
*state = 5; // set next state.
break;
case 5:
// STATE 5: Print out past N historic calibrations.
if (i <= gyro_cal->debug_num_cals_hist) {
// Print the data.
gyroCalDebugPrintData(i, &gyro_cal->debug_cal_data_hist[head_index]);
// Move to the previous calibration data set.
head_index--;
if (head_index < 0) {
head_index = DEBUG_GYRO_LONGTERM_NUM_CAL-1;
}
// Increment the report count.
i++;
// Go to wait state.
j = 0;
*state = 6;
} else {
// Print out the footer data.
*state = 7;
}
break;
case 6:
// STATE 6 : Wait state.
// Wait for N cycles of gyro samples before printing out more data.
// This helps throttle the print statements.
if (j <= 50) {
j++;
} else {
*state = 5;
}
break;
case 7:
// STATE 3 : Print the end of the debug report.
GYRO_INFO_PRINT("Total Gyro Calibrations: %lu\n",
gyro_cal->debug_calibration_count);
GYRO_INFO_PRINT("Total Watchdog Timeouts: %lu\n",
gyro_cal->debug_watchdog_count);
GYRO_INFO_PRINT(
"---END DEBUG REPORT---------------------------------\n");
*state = -1;
break;
default :
// Idle state.
*state = -1;
// Report periodic data useful for tuning the stillness detectors.
//gyroCalTuneDebugPrint(gyro_cal, sample_time);
}
}
#endif