1 /*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "calibration/gyroscope/gyro_cal.h"
18
19 #include <float.h>
20 #include <math.h>
21 #include <string.h>
22
23 #include "calibration/util/cal_log.h"
24 #include "common/math/vec.h"
25
26 /////// DEFINITIONS AND MACROS ///////////////////////////////////////
27
28 // Maximum gyro bias correction (should be set based on expected max bias
29 // of the given sensor).
30 #define MAX_GYRO_BIAS (0.1f) // [rad/sec]
31
32 // Converts units of radians to milli-degrees.
33 #define RAD_TO_MILLI_DEGREES (float)(1e3f * 180.0f / NANO_PI)
34
35 #ifdef GYRO_CAL_DBG_ENABLED
36 // The time value used to throttle debug messaging.
37 #define GYROCAL_WAIT_TIME_NANOS (300000000)
38
39 // Unit conversion: nanoseconds to seconds.
40 #define NANOS_TO_SEC (1.0e-9f)
41
42 // A debug version label to help with tracking results.
43 #define GYROCAL_DEBUG_VERSION_STRING "[Jan 20, 2017]"
44
45 // Debug log tag string used to identify debug report output data.
46 #define GYROCAL_REPORT_TAG "[GYRO_CAL:REPORT]"
47
48 // Debug log tag string used to identify debug tuning output data.
49 #define GYROCAL_TUNE_TAG "[GYRO_CAL:TUNE]"
50 #endif // GYRO_CAL_DBG_ENABLED
51
52 /////// FORWARD DECLARATIONS /////////////////////////////////////////
53
54 static void deviceStillnessCheck(struct GyroCal* gyro_cal,
55 uint64_t sample_time_nanos);
56
57 static void computeGyroCal(struct GyroCal* gyro_cal,
58 uint64_t calibration_time_nanos);
59
60 static void checkWatchdog(struct GyroCal* gyro_cal, uint64_t sample_time_nanos);
61
62 // Data tracker command enumeration.
63 enum GyroCalTrackerCommand {
64 DO_RESET = 0, // Resets the local data used for data tracking.
65 DO_UPDATE_DATA, // Updates the local tracking data.
66 DO_STORE_DATA, // Stores intermediate results for later recall.
67 DO_EVALUATE // Computes and provides the results of the gate function.
68 };
69
70 /*
71 * Updates the temperature min/max and mean during the stillness period. Returns
72 * 'true' if the min and max temperature values exceed the range set by
73 * 'temperature_delta_limit_celsius'.
74 *
75 * INPUTS:
76 * gyro_cal: Pointer to the GyroCal data structure.
77 * temperature_celsius: New temperature sample to include.
78 * do_this: Command enumerator that controls function behavior:
79 */
80 static bool gyroTemperatureStatsTracker(struct GyroCal* gyro_cal,
81 float temperature_celsius,
82 enum GyroCalTrackerCommand do_this);
83
84 /*
85 * Tracks the minimum and maximum gyroscope stillness window means.
86 * Returns 'true' when the difference between gyroscope min and max window
87 * means are outside the range set by 'stillness_mean_delta_limit'.
88 *
89 * INPUTS:
90 * gyro_cal: Pointer to the GyroCal data structure.
91 * do_this: Command enumerator that controls function behavior.
92 */
93 static bool gyroStillMeanTracker(struct GyroCal* gyro_cal,
94 enum GyroCalTrackerCommand do_this);
95
96 #ifdef GYRO_CAL_DBG_ENABLED
97 // Defines the type of debug data to print.
98 enum DebugPrintData {
99 OFFSET = 0,
100 STILLNESS_DATA,
101 SAMPLE_RATE_AND_TEMPERATURE,
102 GYRO_MINMAX_STILLNESS_MEAN,
103 ACCEL_STATS,
104 GYRO_STATS,
105 MAG_STATS,
106 ACCEL_STATS_TUNING,
107 GYRO_STATS_TUNING,
108 MAG_STATS_TUNING
109 };
110
111 /*
112 * Updates running calculation of the gyro's mean sampling rate.
113 *
114 * Behavior:
115 * 1) If 'debug_mean_sampling_rate_hz' pointer is not NULL then the local
116 * calculation of the sampling rate is copied, and the function returns.
117 * 2) Else, if 'reset_stats' is 'true' then the local estimate is reset and
118 * the function returns.
119 * 3) Otherwise, the local estimate of the mean sampling rates is updated.
120 *
121 * INPUTS:
122 * debug_mean_sampling_rate_hz: Pointer to the mean sampling rate to update.
123 * timestamp_nanos: Time stamp (nanoseconds).
124 * reset_stats: Flag that signals a reset of the sampling rate estimate.
125 */
126 static void gyroSamplingRateUpdate(float* debug_mean_sampling_rate_hz,
127 uint64_t timestamp_nanos, bool reset_stats);
128
129 // Updates the information used for debug printouts.
130 static void gyroCalUpdateDebug(struct GyroCal* gyro_cal);
131
132 // Helper function for printing out common debug data.
133 static void gyroCalDebugPrintData(const struct GyroCal* gyro_cal,
134 char* debug_tag,
135 enum DebugPrintData print_data);
136
137 // This conversion function is necessary for Nanohub firmware compilation (i.e.,
138 // can't cast a uint64_t to a float directly). This conversion function was
139 // copied from: /third_party/contexthub/firmware/src/floatRt.c
floatFromUint64(uint64_t v)140 static float floatFromUint64(uint64_t v)
141 {
142 uint32_t hi = v >> 32, lo = v;
143
144 if (!hi) //this is very fast for cases where we fit into a uint32_t
145 return(float)lo;
146 else {
147 return ((float)hi) * 4294967296.0f + (float)lo;
148 }
149 }
150
151 #ifdef GYRO_CAL_DBG_TUNE_ENABLED
152 // Prints debug information useful for tuning the GyroCal parameters.
153 static void gyroCalTuneDebugPrint(const struct GyroCal* gyro_cal,
154 uint64_t timestamp_nanos);
155 #endif // GYRO_CAL_DBG_TUNE_ENABLED
156 #endif // GYRO_CAL_DBG_ENABLED
157
158 /////// FUNCTION DEFINITIONS /////////////////////////////////////////
159
160 // Initialize the gyro calibration data structure.
gyroCalInit(struct GyroCal * gyro_cal,uint64_t min_still_duration_nanos,uint64_t max_still_duration_nanos,float bias_x,float bias_y,float bias_z,uint64_t calibration_time_nanos,uint64_t window_time_duration_nanos,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,float stillness_mean_delta_limit,float temperature_delta_limit_celsius,bool gyro_calibration_enable)161 void gyroCalInit(struct GyroCal* gyro_cal, uint64_t min_still_duration_nanos,
162 uint64_t max_still_duration_nanos, float bias_x, float bias_y,
163 float bias_z, uint64_t calibration_time_nanos,
164 uint64_t window_time_duration_nanos, float gyro_var_threshold,
165 float gyro_confidence_delta, float accel_var_threshold,
166 float accel_confidence_delta, float mag_var_threshold,
167 float mag_confidence_delta, float stillness_threshold,
168 float stillness_mean_delta_limit,
169 float temperature_delta_limit_celsius,
170 bool gyro_calibration_enable) {
171 // Clear gyro_cal structure memory.
172 memset(gyro_cal, 0, sizeof(struct GyroCal));
173
174 // Initialize the stillness detectors.
175 // Gyro parameter input units are [rad/sec].
176 // Accel parameter input units are [m/sec^2].
177 // Magnetometer parameter input units are [uT].
178 gyroStillDetInit(&gyro_cal->gyro_stillness_detect, gyro_var_threshold,
179 gyro_confidence_delta);
180 gyroStillDetInit(&gyro_cal->accel_stillness_detect, accel_var_threshold,
181 accel_confidence_delta);
182 gyroStillDetInit(&gyro_cal->mag_stillness_detect, mag_var_threshold,
183 mag_confidence_delta);
184
185 // Reset stillness flag and start timestamp.
186 gyro_cal->prev_still = false;
187 gyro_cal->start_still_time_nanos = 0;
188
189 // Set the min and max window stillness duration.
190 gyro_cal->min_still_duration_nanos = min_still_duration_nanos;
191 gyro_cal->max_still_duration_nanos = max_still_duration_nanos;
192
193 // Sets the duration of the stillness processing windows.
194 gyro_cal->window_time_duration_nanos = window_time_duration_nanos;
195
196 // Set the watchdog timeout duration.
197 gyro_cal->gyro_watchdog_timeout_duration_nanos =
198 2 * window_time_duration_nanos;
199
200 // Load the last valid cal from system memory.
201 gyro_cal->bias_x = bias_x; // [rad/sec]
202 gyro_cal->bias_y = bias_y; // [rad/sec]
203 gyro_cal->bias_z = bias_z; // [rad/sec]
204 gyro_cal->calibration_time_nanos = calibration_time_nanos;
205
206 // Set the stillness threshold required for gyro bias calibration.
207 gyro_cal->stillness_threshold = stillness_threshold;
208
209 // Current window end-time used to assist in keeping sensor data collection in
210 // sync. Setting this to zero signals that sensor data will be dropped until a
211 // valid end-time is set from the first gyro timestamp received.
212 gyro_cal->stillness_win_endtime_nanos = 0;
213
214 // Gyro calibrations will be applied (see, gyroCalRemoveBias()).
215 gyro_cal->gyro_calibration_enable = (gyro_calibration_enable > 0);
216
217 // Sets the stability limit for the stillness window mean acceptable delta.
218 gyro_cal->stillness_mean_delta_limit = stillness_mean_delta_limit;
219
220 // Sets the min/max temperature delta limit for the stillness period.
221 gyro_cal->temperature_delta_limit_celsius = temperature_delta_limit_celsius;
222
223 // Ensures that the data tracking functionality is reset.
224 gyroStillMeanTracker(gyro_cal, DO_RESET);
225 gyroTemperatureStatsTracker(gyro_cal, 0.0f, DO_RESET);
226
227 #ifdef GYRO_CAL_DBG_ENABLED
228 CAL_DEBUG_LOG("[GYRO_CAL:MEMORY]", "sizeof(struct GyroCal): %lu",
229 (unsigned long int)sizeof(struct GyroCal));
230
231 if (gyro_cal->gyro_calibration_enable) {
232 CAL_DEBUG_LOG("[GYRO_CAL:INIT]", "Online gyroscope calibration ENABLED.");
233 } else {
234 CAL_DEBUG_LOG("[GYRO_CAL:INIT]", "Online gyroscope calibration DISABLED.");
235 }
236
237 // Ensures that the gyro sampling rate estimate is reset.
238 gyroSamplingRateUpdate(NULL, 0, /*reset_stats=*/true);
239 #endif // GYRO_CAL_DBG_ENABLED
240 }
241
242 // Void pointer in the gyro calibration data structure (doesn't do anything
243 // except prevent compiler warnings).
gyroCalDestroy(struct GyroCal * gyro_cal)244 void gyroCalDestroy(struct GyroCal* gyro_cal) {
245 (void)gyro_cal;
246 }
247
248 // Get the most recent bias calibration value.
gyroCalGetBias(struct GyroCal * gyro_cal,float * bias_x,float * bias_y,float * bias_z,float * temperature_celsius)249 void gyroCalGetBias(struct GyroCal* gyro_cal, float* bias_x, float* bias_y,
250 float* bias_z, float* temperature_celsius) {
251 *bias_x = gyro_cal->bias_x;
252 *bias_y = gyro_cal->bias_y;
253 *bias_z = gyro_cal->bias_z;
254 *temperature_celsius = gyro_cal->bias_temperature_celsius;
255 }
256
257 // Set an initial bias calibration value.
gyroCalSetBias(struct GyroCal * gyro_cal,float bias_x,float bias_y,float bias_z,uint64_t calibration_time_nanos)258 void gyroCalSetBias(struct GyroCal* gyro_cal, float bias_x, float bias_y,
259 float bias_z, uint64_t calibration_time_nanos) {
260 gyro_cal->bias_x = bias_x;
261 gyro_cal->bias_y = bias_y;
262 gyro_cal->bias_z = bias_z;
263 gyro_cal->calibration_time_nanos = calibration_time_nanos;
264
265 #ifdef GYRO_CAL_DBG_ENABLED
266 CAL_DEBUG_LOG("[GYRO_CAL:RECALL]",
267 "Gyro Bias Calibration [mdps]: %s%d.%06d, %s%d.%06d, %s%d.%06d",
268 CAL_ENCODE_FLOAT(gyro_cal->bias_x * RAD_TO_MILLI_DEGREES, 6),
269 CAL_ENCODE_FLOAT(gyro_cal->bias_y * RAD_TO_MILLI_DEGREES, 6),
270 CAL_ENCODE_FLOAT(gyro_cal->bias_z * RAD_TO_MILLI_DEGREES, 6));
271 #endif // GYRO_CAL_DBG_ENABLED
272 }
273
274 // Remove bias from a gyro measurement [rad/sec].
gyroCalRemoveBias(struct GyroCal * gyro_cal,float xi,float yi,float zi,float * xo,float * yo,float * zo)275 void gyroCalRemoveBias(struct GyroCal* gyro_cal, float xi, float yi, float zi,
276 float* xo, float* yo, float* zo) {
277 if (gyro_cal->gyro_calibration_enable) {
278 *xo = xi - gyro_cal->bias_x;
279 *yo = yi - gyro_cal->bias_y;
280 *zo = zi - gyro_cal->bias_z;
281 }
282 }
283
284 // Returns true when a new gyro calibration is available.
gyroCalNewBiasAvailable(struct GyroCal * gyro_cal)285 bool gyroCalNewBiasAvailable(struct GyroCal* gyro_cal) {
286 bool new_gyro_cal_available =
287 (gyro_cal->gyro_calibration_enable && gyro_cal->new_gyro_cal_available);
288
289 // Clear the flag.
290 gyro_cal->new_gyro_cal_available = false;
291
292 return new_gyro_cal_available;
293 }
294
295 // Update the gyro calibration with gyro data [rad/sec].
gyroCalUpdateGyro(struct GyroCal * gyro_cal,uint64_t sample_time_nanos,float x,float y,float z,float temperature_celsius)296 void gyroCalUpdateGyro(struct GyroCal* gyro_cal, uint64_t sample_time_nanos,
297 float x, float y, float z, float temperature_celsius) {
298 static float latest_temperature_celsius = 0.0f;
299
300 // Make sure that a valid window end-time is set, and start the watchdog
301 // timer.
302 if (gyro_cal->stillness_win_endtime_nanos <= 0) {
303 gyro_cal->stillness_win_endtime_nanos =
304 sample_time_nanos + gyro_cal->window_time_duration_nanos;
305
306 // Start the watchdog timer.
307 gyro_cal->gyro_watchdog_start_nanos = sample_time_nanos;
308 }
309
310 // Update the temperature statistics (only on a temperature change).
311 if (NANO_ABS(temperature_celsius - latest_temperature_celsius) > FLT_MIN) {
312 gyroTemperatureStatsTracker(gyro_cal, temperature_celsius, DO_UPDATE_DATA);
313 }
314
315 #ifdef GYRO_CAL_DBG_ENABLED
316 // Update the gyro sampling rate estimate.
317 gyroSamplingRateUpdate(NULL, sample_time_nanos, /*reset_stats=*/false);
318 #endif // GYRO_CAL_DBG_ENABLED
319
320 // Pass gyro data to stillness detector
321 gyroStillDetUpdate(&gyro_cal->gyro_stillness_detect,
322 gyro_cal->stillness_win_endtime_nanos, sample_time_nanos,
323 x, y, z);
324
325 // Perform a device stillness check, set next window end-time, and
326 // possibly do a gyro bias calibration and stillness detector reset.
327 deviceStillnessCheck(gyro_cal, sample_time_nanos);
328 }
329
330 // Update the gyro calibration with mag data [micro Tesla].
gyroCalUpdateMag(struct GyroCal * gyro_cal,uint64_t sample_time_nanos,float x,float y,float z)331 void gyroCalUpdateMag(struct GyroCal* gyro_cal, uint64_t sample_time_nanos,
332 float x, float y, float z) {
333 // Pass magnetometer data to stillness detector.
334 gyroStillDetUpdate(&gyro_cal->mag_stillness_detect,
335 gyro_cal->stillness_win_endtime_nanos, sample_time_nanos,
336 x, y, z);
337
338 // Received a magnetometer sample; incorporate it into detection.
339 gyro_cal->using_mag_sensor = true;
340
341 // Perform a device stillness check, set next window end-time, and
342 // possibly do a gyro bias calibration and stillness detector reset.
343 deviceStillnessCheck(gyro_cal, sample_time_nanos);
344 }
345
346 // Update the gyro calibration with accel data [m/sec^2].
gyroCalUpdateAccel(struct GyroCal * gyro_cal,uint64_t sample_time_nanos,float x,float y,float z)347 void gyroCalUpdateAccel(struct GyroCal* gyro_cal, uint64_t sample_time_nanos,
348 float x, float y, float z) {
349 // Pass accelerometer data to stillnesss detector.
350 gyroStillDetUpdate(&gyro_cal->accel_stillness_detect,
351 gyro_cal->stillness_win_endtime_nanos, sample_time_nanos,
352 x, y, z);
353
354 // Perform a device stillness check, set next window end-time, and
355 // possibly do a gyro bias calibration and stillness detector reset.
356 deviceStillnessCheck(gyro_cal, sample_time_nanos);
357 }
358
359 // TODO(davejacobs): Consider breaking this function up to improve readability.
360 // Checks the state of all stillness detectors to determine
361 // whether the device is "still".
deviceStillnessCheck(struct GyroCal * gyro_cal,uint64_t sample_time_nanos)362 void deviceStillnessCheck(struct GyroCal* gyro_cal,
363 uint64_t sample_time_nanos) {
364 bool stillness_duration_exceeded = false;
365 bool stillness_duration_too_short = false;
366 bool min_max_temp_exceeded = false;
367 bool mean_not_stable = false;
368 bool device_is_still = false;
369 float conf_not_rot = 0;
370 float conf_not_accel = 0;
371 float conf_still = 0;
372
373 // Check the watchdog timer.
374 checkWatchdog(gyro_cal, sample_time_nanos);
375
376 // Is there enough data to do a stillness calculation?
377 if ((!gyro_cal->mag_stillness_detect.stillness_window_ready &&
378 gyro_cal->using_mag_sensor) ||
379 !gyro_cal->accel_stillness_detect.stillness_window_ready ||
380 !gyro_cal->gyro_stillness_detect.stillness_window_ready) {
381 return; // Not yet, wait for more data.
382 }
383
384 // Set the next window end-time for the stillness detectors.
385 gyro_cal->stillness_win_endtime_nanos =
386 sample_time_nanos + gyro_cal->window_time_duration_nanos;
387
388 // Update the confidence scores for all sensors.
389 gyroStillDetCompute(&gyro_cal->accel_stillness_detect);
390 gyroStillDetCompute(&gyro_cal->gyro_stillness_detect);
391 if (gyro_cal->using_mag_sensor) {
392 gyroStillDetCompute(&gyro_cal->mag_stillness_detect);
393 } else {
394 // Not using magnetometer, force stillness confidence to 100%.
395 gyro_cal->mag_stillness_detect.stillness_confidence = 1.0f;
396 }
397
398 // Updates the mean tracker data.
399 gyroStillMeanTracker(gyro_cal, DO_UPDATE_DATA);
400
401 // Determine motion confidence scores (rotation, accelerating, and stillness).
402 conf_not_rot = gyro_cal->gyro_stillness_detect.stillness_confidence *
403 gyro_cal->mag_stillness_detect.stillness_confidence;
404 conf_not_accel = gyro_cal->accel_stillness_detect.stillness_confidence;
405 conf_still = conf_not_rot * conf_not_accel;
406
407 // Evaluate the mean and temperature gate functions.
408 mean_not_stable = gyroStillMeanTracker(gyro_cal, DO_EVALUATE);
409 min_max_temp_exceeded =
410 gyroTemperatureStatsTracker(gyro_cal, 0.0f, DO_EVALUATE);
411
412 // Determines if the device is currently still.
413 device_is_still = (conf_still > gyro_cal->stillness_threshold) &&
414 !mean_not_stable && !min_max_temp_exceeded ;
415
416 if (device_is_still) {
417 // Device is "still" logic:
418 // If not previously still, then record the start time.
419 // If stillness period is too long, then do a calibration.
420 // Otherwise, continue collecting stillness data.
421
422 // If device was not previously still, set new start timestamp.
423 if (!gyro_cal->prev_still) {
424 // Record the starting timestamp of the current stillness window.
425 // This enables the calculation of total duration of the stillness period.
426 gyro_cal->start_still_time_nanos =
427 gyro_cal->gyro_stillness_detect.window_start_time;
428 }
429
430 // Check to see if current stillness period exceeds the desired limit.
431 stillness_duration_exceeded =
432 ((gyro_cal->gyro_stillness_detect.last_sample_time -
433 gyro_cal->start_still_time_nanos) >
434 gyro_cal->max_still_duration_nanos);
435
436 // Track the new stillness mean and temperature data.
437 gyroStillMeanTracker(gyro_cal, DO_STORE_DATA);
438 gyroTemperatureStatsTracker(gyro_cal, 0.0f, DO_STORE_DATA);
439
440 if (stillness_duration_exceeded) {
441 // The current stillness has gone too long. Do a calibration with the
442 // current data and reset.
443
444 // Updates the gyro bias estimate with the current window data and
445 // resets the stats.
446 gyroStillDetReset(&gyro_cal->accel_stillness_detect,
447 /*reset_stats=*/true);
448 gyroStillDetReset(&gyro_cal->gyro_stillness_detect, /*reset_stats=*/true);
449 gyroStillDetReset(&gyro_cal->mag_stillness_detect, /*reset_stats=*/true);
450
451 // Resets the local calculations because the stillness period is over.
452 gyroStillMeanTracker(gyro_cal, DO_RESET);
453 gyroTemperatureStatsTracker(gyro_cal, 0.0f, DO_RESET);
454
455 // Computes a new gyro offset estimate.
456 computeGyroCal(gyro_cal,
457 gyro_cal->gyro_stillness_detect.last_sample_time);
458
459 #ifdef GYRO_CAL_DBG_ENABLED
460 // Resets the sampling rate estimate.
461 gyroSamplingRateUpdate(NULL, sample_time_nanos, /*reset_stats=*/true);
462 #endif // GYRO_CAL_DBG_ENABLED
463
464 // Update stillness flag. Force the start of a new stillness period.
465 gyro_cal->prev_still = false;
466 } else {
467 // Continue collecting stillness data.
468
469 // Extend the stillness period.
470 gyroStillDetReset(&gyro_cal->accel_stillness_detect,
471 /*reset_stats=*/false);
472 gyroStillDetReset(&gyro_cal->gyro_stillness_detect,
473 /*reset_stats=*/false);
474 gyroStillDetReset(&gyro_cal->mag_stillness_detect, /*reset_stats=*/false);
475
476 // Update the stillness flag.
477 gyro_cal->prev_still = true;
478 }
479 } else {
480 // Device is NOT still; motion detected.
481
482 // If device was previously still and the total stillness duration is not
483 // "too short", then do a calibration with the data accumulated thus far.
484 stillness_duration_too_short =
485 ((gyro_cal->gyro_stillness_detect.window_start_time -
486 gyro_cal->start_still_time_nanos) <
487 gyro_cal->min_still_duration_nanos);
488
489 if (gyro_cal->prev_still && !stillness_duration_too_short) {
490 computeGyroCal(gyro_cal,
491 gyro_cal->gyro_stillness_detect.window_start_time);
492 }
493
494 // Reset the stillness detectors and the stats.
495 gyroStillDetReset(&gyro_cal->accel_stillness_detect, /*reset_stats=*/true);
496 gyroStillDetReset(&gyro_cal->gyro_stillness_detect, /*reset_stats=*/true);
497 gyroStillDetReset(&gyro_cal->mag_stillness_detect, /*reset_stats=*/true);
498
499 // Resets the temperature and sensor mean data.
500 gyroTemperatureStatsTracker(gyro_cal, 0.0f, DO_RESET);
501 gyroStillMeanTracker(gyro_cal, DO_RESET);
502
503 #ifdef GYRO_CAL_DBG_ENABLED
504 // Resets the sampling rate estimate.
505 gyroSamplingRateUpdate(NULL, sample_time_nanos, /*reset_stats=*/true);
506 #endif // GYRO_CAL_DBG_ENABLED
507
508 // Update stillness flag.
509 gyro_cal->prev_still = false;
510 }
511
512 // Reset the watchdog timer after we have processed data.
513 gyro_cal->gyro_watchdog_start_nanos = sample_time_nanos;
514 }
515
516 // Calculates a new gyro bias offset calibration value.
computeGyroCal(struct GyroCal * gyro_cal,uint64_t calibration_time_nanos)517 void computeGyroCal(struct GyroCal* gyro_cal, uint64_t calibration_time_nanos) {
518 // Check to see if new calibration values is within acceptable range.
519 if (!(gyro_cal->gyro_stillness_detect.prev_mean_x < MAX_GYRO_BIAS &&
520 gyro_cal->gyro_stillness_detect.prev_mean_x > -MAX_GYRO_BIAS &&
521 gyro_cal->gyro_stillness_detect.prev_mean_y < MAX_GYRO_BIAS &&
522 gyro_cal->gyro_stillness_detect.prev_mean_y > -MAX_GYRO_BIAS &&
523 gyro_cal->gyro_stillness_detect.prev_mean_z < MAX_GYRO_BIAS &&
524 gyro_cal->gyro_stillness_detect.prev_mean_z > -MAX_GYRO_BIAS)) {
525 #ifdef GYRO_CAL_DBG_ENABLED
526 CAL_DEBUG_LOG("[GYRO_CAL:REJECT]",
527 "Offset|Temp|Time [mdps|C|nsec]: %s%d.%06d, %s%d.%06d, "
528 "%s%d.%06d, %s%d.%06d, %llu",
529 CAL_ENCODE_FLOAT(gyro_cal->gyro_stillness_detect.prev_mean_x *
530 RAD_TO_MILLI_DEGREES,
531 6),
532 CAL_ENCODE_FLOAT(gyro_cal->gyro_stillness_detect.prev_mean_y *
533 RAD_TO_MILLI_DEGREES,
534 6),
535 CAL_ENCODE_FLOAT(gyro_cal->gyro_stillness_detect.prev_mean_z *
536 RAD_TO_MILLI_DEGREES,
537 6),
538 CAL_ENCODE_FLOAT(gyro_cal->temperature_mean_celsius, 6),
539 (unsigned long long int)calibration_time_nanos);
540 #endif // GYRO_CAL_DBG_ENABLED
541
542 // Outside of range. Ignore, reset, and continue.
543 return;
544 }
545
546 // Record the new gyro bias offset calibration.
547 gyro_cal->bias_x = gyro_cal->gyro_stillness_detect.prev_mean_x;
548 gyro_cal->bias_y = gyro_cal->gyro_stillness_detect.prev_mean_y;
549 gyro_cal->bias_z = gyro_cal->gyro_stillness_detect.prev_mean_z;
550
551 // Store the calibration temperature (using the mean temperature over the
552 // "stillness" period).
553 gyro_cal->bias_temperature_celsius = gyro_cal->temperature_mean_celsius;
554
555 // Store the calibration time stamp.
556 gyro_cal->calibration_time_nanos = calibration_time_nanos;
557
558 // Record the final stillness confidence.
559 gyro_cal->stillness_confidence =
560 gyro_cal->gyro_stillness_detect.prev_stillness_confidence *
561 gyro_cal->accel_stillness_detect.prev_stillness_confidence *
562 gyro_cal->mag_stillness_detect.prev_stillness_confidence;
563
564 // Set flag to indicate a new gyro calibration value is available.
565 gyro_cal->new_gyro_cal_available = true;
566
567 #ifdef GYRO_CAL_DBG_ENABLED
568 // Increment the total count of calibration updates.
569 gyro_cal->debug_calibration_count++;
570
571 // Update the calibration debug information and trigger a printout.
572 gyroCalUpdateDebug(gyro_cal);
573 #endif
574 }
575
576 // Check for a watchdog timeout condition.
checkWatchdog(struct GyroCal * gyro_cal,uint64_t sample_time_nanos)577 void checkWatchdog(struct GyroCal* gyro_cal, uint64_t sample_time_nanos) {
578 bool watchdog_timeout;
579
580 // Check for initialization of the watchdog time (=0).
581 if (gyro_cal->gyro_watchdog_start_nanos <= 0) {
582 return;
583 }
584
585 // Check for the watchdog timeout condition (i.e., the time elapsed since the
586 // last received sample has exceeded the allowed watchdog duration).
587 watchdog_timeout =
588 (sample_time_nanos > gyro_cal->gyro_watchdog_timeout_duration_nanos +
589 gyro_cal->gyro_watchdog_start_nanos);
590
591 // If a timeout occurred then reset to known good state.
592 if (watchdog_timeout) {
593 // Reset stillness detectors and restart data capture.
594 gyroStillDetReset(&gyro_cal->accel_stillness_detect, /*reset_stats=*/true);
595 gyroStillDetReset(&gyro_cal->gyro_stillness_detect, /*reset_stats=*/true);
596 gyroStillDetReset(&gyro_cal->mag_stillness_detect, /*reset_stats=*/true);
597
598 // Resets the temperature and sensor mean data.
599 gyroTemperatureStatsTracker(gyro_cal, 0.0f, DO_RESET);
600 gyroStillMeanTracker(gyro_cal, DO_RESET);
601
602 #ifdef GYRO_CAL_DBG_ENABLED
603 // Resets the sampling rate estimate.
604 gyroSamplingRateUpdate(NULL, sample_time_nanos, /*reset_stats=*/true);
605 #endif // GYRO_CAL_DBG_ENABLED
606
607 // Resets the stillness window end-time.
608 gyro_cal->stillness_win_endtime_nanos = 0;
609
610 // Force stillness confidence to zero.
611 gyro_cal->accel_stillness_detect.prev_stillness_confidence = 0;
612 gyro_cal->gyro_stillness_detect.prev_stillness_confidence = 0;
613 gyro_cal->mag_stillness_detect.prev_stillness_confidence = 0;
614 gyro_cal->stillness_confidence = 0;
615 gyro_cal->prev_still = false;
616
617 // If there are no magnetometer samples being received then
618 // operate the calibration algorithm without this sensor.
619 if (!gyro_cal->mag_stillness_detect.stillness_window_ready &&
620 gyro_cal->using_mag_sensor) {
621 gyro_cal->using_mag_sensor = false;
622 }
623
624 // Assert watchdog timeout flags.
625 gyro_cal->gyro_watchdog_timeout |= watchdog_timeout;
626 gyro_cal->gyro_watchdog_start_nanos = 0;
627 #ifdef GYRO_CAL_DBG_ENABLED
628 gyro_cal->debug_watchdog_count++;
629 CAL_DEBUG_LOG("[GYRO_CAL:WATCHDOG]", "Total#, Timestamp [nsec]: %lu, %llu",
630 (unsigned long int)gyro_cal->debug_watchdog_count,
631 (unsigned long long int)sample_time_nanos);
632 #endif // GYRO_CAL_DBG_ENABLED
633 }
634 }
635
636 // TODO(davejacobs) -- Combine the following two functions into one or consider
637 // implementing a separate helper module for tracking the temperature and mean
638 // statistics.
gyroTemperatureStatsTracker(struct GyroCal * gyro_cal,float temperature_celsius,enum GyroCalTrackerCommand do_this)639 bool gyroTemperatureStatsTracker(struct GyroCal* gyro_cal,
640 float temperature_celsius,
641 enum GyroCalTrackerCommand do_this) {
642 // This is used for local calculations of the running mean.
643 static float mean_accumulator = 0.0f;
644 static float temperature_min_max_celsius[2] = {0.0f, 0.0f};
645 static size_t num_points = 0;
646 bool min_max_temp_exceeded = false;
647
648 switch (do_this) {
649 case DO_RESET:
650 // Resets the mean accumulator.
651 num_points = 0;
652 mean_accumulator = 0.0f;
653
654 // Initializes the min/max temperatures values.
655 temperature_min_max_celsius[0] = FLT_MAX;
656 temperature_min_max_celsius[1] = -1.0f * (FLT_MAX - 1.0f);
657 break;
658
659 case DO_UPDATE_DATA:
660 // Does the mean accumulation.
661 mean_accumulator += temperature_celsius;
662 num_points++;
663
664 // Tracks the min and max temperature values.
665 if (temperature_min_max_celsius[0] > temperature_celsius) {
666 temperature_min_max_celsius[0] = temperature_celsius;
667 }
668 if (temperature_min_max_celsius[1] < temperature_celsius) {
669 temperature_min_max_celsius[1] = temperature_celsius;
670 }
671 break;
672
673 case DO_STORE_DATA:
674 // Store the most recent "stillness" mean data to the GyroCal data
675 // structure. This functionality allows previous results to be recalled
676 // when the device suddenly becomes "not still".
677 if (num_points > 0) {
678 memcpy(gyro_cal->temperature_min_max_celsius,
679 temperature_min_max_celsius, 2 * sizeof(float));
680 gyro_cal->temperature_mean_celsius = mean_accumulator / num_points;
681 }
682 break;
683
684 case DO_EVALUATE:
685 // Determines if the min/max delta exceeded the set limit.
686 if (num_points > 0) {
687 min_max_temp_exceeded =
688 (temperature_min_max_celsius[1] -
689 temperature_min_max_celsius[0]) >
690 gyro_cal->temperature_delta_limit_celsius;
691
692 #ifdef GYRO_CAL_DBG_ENABLED
693 if (min_max_temp_exceeded) {
694 CAL_DEBUG_LOG(
695 "[GYRO_CAL:TEMP_GATE]",
696 "Exceeded the max temperature variation during stillness.");
697 }
698 #endif // GYRO_CAL_DBG_ENABLED
699 }
700 break;
701
702 default:
703 break;
704 }
705
706 return min_max_temp_exceeded;
707 }
708
gyroStillMeanTracker(struct GyroCal * gyro_cal,enum GyroCalTrackerCommand do_this)709 bool gyroStillMeanTracker(struct GyroCal* gyro_cal,
710 enum GyroCalTrackerCommand do_this) {
711 static float gyro_winmean_min[3] = {0.0f, 0.0f, 0.0f};
712 static float gyro_winmean_max[3] = {0.0f, 0.0f, 0.0f};
713 bool mean_not_stable = false;
714 size_t i;
715
716 switch (do_this) {
717 case DO_RESET:
718 // Resets the min/max window mean values to a default value.
719 for (i = 0; i < 3; i++) {
720 gyro_winmean_min[i] = FLT_MAX;
721 gyro_winmean_max[i] = -1.0f * (FLT_MAX - 1.0f);
722 }
723 break;
724
725 case DO_UPDATE_DATA:
726 // Computes the min/max window mean values.
727 if (gyro_winmean_min[0] > gyro_cal->gyro_stillness_detect.win_mean_x) {
728 gyro_winmean_min[0] = gyro_cal->gyro_stillness_detect.win_mean_x;
729 }
730 if (gyro_winmean_max[0] < gyro_cal->gyro_stillness_detect.win_mean_x) {
731 gyro_winmean_max[0] = gyro_cal->gyro_stillness_detect.win_mean_x;
732 }
733
734 if (gyro_winmean_min[1] > gyro_cal->gyro_stillness_detect.win_mean_y) {
735 gyro_winmean_min[1] = gyro_cal->gyro_stillness_detect.win_mean_y;
736 }
737 if (gyro_winmean_max[1] < gyro_cal->gyro_stillness_detect.win_mean_y) {
738 gyro_winmean_max[1] = gyro_cal->gyro_stillness_detect.win_mean_y;
739 }
740
741 if (gyro_winmean_min[2] > gyro_cal->gyro_stillness_detect.win_mean_z) {
742 gyro_winmean_min[2] = gyro_cal->gyro_stillness_detect.win_mean_z;
743 }
744 if (gyro_winmean_max[2] < gyro_cal->gyro_stillness_detect.win_mean_z) {
745 gyro_winmean_max[2] = gyro_cal->gyro_stillness_detect.win_mean_z;
746 }
747 break;
748
749 case DO_STORE_DATA:
750 // Store the most recent "stillness" mean data to the GyroCal data
751 // structure. This functionality allows previous results to be recalled
752 // when the device suddenly becomes "not still".
753 memcpy(gyro_cal->gyro_winmean_min, gyro_winmean_min, 3 * sizeof(float));
754 memcpy(gyro_cal->gyro_winmean_max, gyro_winmean_max, 3 * sizeof(float));
755 break;
756
757 case DO_EVALUATE:
758 // Performs the stability check and returns the 'true' if the difference
759 // between min/max window mean value is outside the stable range.
760 for (i = 0; i < 3; i++) {
761 mean_not_stable |= (gyro_winmean_max[i] - gyro_winmean_min[i]) >
762 gyro_cal->stillness_mean_delta_limit;
763 }
764 #ifdef GYRO_CAL_DBG_ENABLED
765 if (mean_not_stable) {
766 CAL_DEBUG_LOG("[GYRO_CAL:MEAN_STABILITY_GATE]",
767 "Exceeded the max variation in the gyro's stillness "
768 "window mean values.");
769 }
770 #endif // GYRO_CAL_DBG_ENABLED
771 break;
772
773 default:
774 break;
775 }
776
777 return mean_not_stable;
778 }
779
780 #ifdef GYRO_CAL_DBG_ENABLED
gyroSamplingRateUpdate(float * debug_mean_sampling_rate_hz,uint64_t timestamp_nanos,bool reset_stats)781 void gyroSamplingRateUpdate(float* debug_mean_sampling_rate_hz,
782 uint64_t timestamp_nanos, bool reset_stats) {
783 // This is used for local calculations of average sampling rate.
784 static uint64_t last_timestamp_nanos = 0;
785 static uint64_t time_delta_accumulator = 0;
786 static size_t num_samples = 0;
787
788 // If 'debug_mean_sampling_rate_hz' is not NULL then this function just reads
789 // out the estimate of the sampling rate.
790 if (debug_mean_sampling_rate_hz) {
791 if (num_samples > 1 && time_delta_accumulator > 0) {
792 // Computes the final mean calculation.
793 *debug_mean_sampling_rate_hz =
794 num_samples /
795 (floatFromUint64(time_delta_accumulator) * NANOS_TO_SEC);
796 } else {
797 // Not enough samples to compute a valid sample rate estimate. Indicate
798 // this with a -1 value.
799 *debug_mean_sampling_rate_hz = -1.0f;
800 }
801 reset_stats = true;
802 }
803
804 // Resets the sampling rate mean estimator data.
805 if (reset_stats) {
806 last_timestamp_nanos = 0;
807 time_delta_accumulator = 0;
808 num_samples = 0;
809 return;
810 }
811
812 // Skip adding this data to the accumulator if:
813 // 1. A bad timestamp was received (i.e., time not monotonic).
814 // 2. 'last_timestamp_nanos' is zero.
815 if (timestamp_nanos <= last_timestamp_nanos || last_timestamp_nanos == 0) {
816 last_timestamp_nanos = timestamp_nanos;
817 return;
818 }
819
820 // Increments the number of samples.
821 num_samples++;
822
823 // Accumulate the time steps.
824 time_delta_accumulator += timestamp_nanos - last_timestamp_nanos;
825 last_timestamp_nanos = timestamp_nanos;
826 }
827
gyroCalUpdateDebug(struct GyroCal * gyro_cal)828 void gyroCalUpdateDebug(struct GyroCal* gyro_cal) {
829 // Only update this data if debug printing is not currently in progress
830 // (i.e., don't want to risk overwriting debug information that is actively
831 // being reported).
832 if (gyro_cal->debug_state != GYRO_IDLE) {
833 return;
834 }
835
836 // Probability of stillness (acc, rot, still), duration, timestamp.
837 gyro_cal->debug_gyro_cal.accel_stillness_conf =
838 gyro_cal->accel_stillness_detect.prev_stillness_confidence;
839 gyro_cal->debug_gyro_cal.gyro_stillness_conf =
840 gyro_cal->gyro_stillness_detect.prev_stillness_confidence;
841 gyro_cal->debug_gyro_cal.mag_stillness_conf =
842 gyro_cal->mag_stillness_detect.prev_stillness_confidence;
843
844 // Magnetometer usage.
845 gyro_cal->debug_gyro_cal.using_mag_sensor = gyro_cal->using_mag_sensor;
846
847 // Stillness start, stop, and duration times.
848 gyro_cal->debug_gyro_cal.start_still_time_nanos =
849 gyro_cal->start_still_time_nanos;
850 gyro_cal->debug_gyro_cal.end_still_time_nanos =
851 gyro_cal->calibration_time_nanos;
852 gyro_cal->debug_gyro_cal.stillness_duration_nanos =
853 gyro_cal->calibration_time_nanos - gyro_cal->start_still_time_nanos;
854
855 // Records the current calibration values.
856 gyro_cal->debug_gyro_cal.calibration[0] = gyro_cal->bias_x;
857 gyro_cal->debug_gyro_cal.calibration[1] = gyro_cal->bias_y;
858 gyro_cal->debug_gyro_cal.calibration[2] = gyro_cal->bias_z;
859
860 // Records the mean gyroscope sampling rate.
861 gyroSamplingRateUpdate(&gyro_cal->debug_gyro_cal.mean_sampling_rate_hz, 0,
862 /*reset_stats=*/true);
863
864 // Records the min/max and mean temperature values.
865 gyro_cal->debug_gyro_cal.temperature_mean_celsius =
866 gyro_cal->temperature_mean_celsius;
867 memcpy(gyro_cal->debug_gyro_cal.temperature_min_max_celsius,
868 gyro_cal->temperature_min_max_celsius, 2 * sizeof(float));
869
870 // Records the min/max gyroscope window stillness mean values.
871 memcpy(gyro_cal->debug_gyro_cal.gyro_winmean_min, gyro_cal->gyro_winmean_min,
872 3 * sizeof(float));
873 memcpy(gyro_cal->debug_gyro_cal.gyro_winmean_max, gyro_cal->gyro_winmean_max,
874 3 * sizeof(float));
875
876 // Records the previous stillness window means.
877 gyro_cal->debug_gyro_cal.accel_mean[0] =
878 gyro_cal->accel_stillness_detect.prev_mean_x;
879 gyro_cal->debug_gyro_cal.accel_mean[1] =
880 gyro_cal->accel_stillness_detect.prev_mean_y;
881 gyro_cal->debug_gyro_cal.accel_mean[2] =
882 gyro_cal->accel_stillness_detect.prev_mean_z;
883
884 gyro_cal->debug_gyro_cal.gyro_mean[0] =
885 gyro_cal->gyro_stillness_detect.prev_mean_x;
886 gyro_cal->debug_gyro_cal.gyro_mean[1] =
887 gyro_cal->gyro_stillness_detect.prev_mean_y;
888 gyro_cal->debug_gyro_cal.gyro_mean[2] =
889 gyro_cal->gyro_stillness_detect.prev_mean_z;
890
891 gyro_cal->debug_gyro_cal.mag_mean[0] =
892 gyro_cal->mag_stillness_detect.prev_mean_x;
893 gyro_cal->debug_gyro_cal.mag_mean[1] =
894 gyro_cal->mag_stillness_detect.prev_mean_y;
895 gyro_cal->debug_gyro_cal.mag_mean[2] =
896 gyro_cal->mag_stillness_detect.prev_mean_z;
897
898 // Records the variance data.
899 // NOTE: These statistics include the final captured window, which may be
900 // outside of the "stillness" period. Therefore, these values may exceed the
901 // stillness thresholds.
902 gyro_cal->debug_gyro_cal.accel_var[0] =
903 gyro_cal->accel_stillness_detect.win_var_x;
904 gyro_cal->debug_gyro_cal.accel_var[1] =
905 gyro_cal->accel_stillness_detect.win_var_y;
906 gyro_cal->debug_gyro_cal.accel_var[2] =
907 gyro_cal->accel_stillness_detect.win_var_z;
908
909 gyro_cal->debug_gyro_cal.gyro_var[0] =
910 gyro_cal->gyro_stillness_detect.win_var_x;
911 gyro_cal->debug_gyro_cal.gyro_var[1] =
912 gyro_cal->gyro_stillness_detect.win_var_y;
913 gyro_cal->debug_gyro_cal.gyro_var[2] =
914 gyro_cal->gyro_stillness_detect.win_var_z;
915
916 gyro_cal->debug_gyro_cal.mag_var[0] =
917 gyro_cal->mag_stillness_detect.win_var_x;
918 gyro_cal->debug_gyro_cal.mag_var[1] =
919 gyro_cal->mag_stillness_detect.win_var_y;
920 gyro_cal->debug_gyro_cal.mag_var[2] =
921 gyro_cal->mag_stillness_detect.win_var_z;
922
923 // Trigger a printout of the debug information.
924 gyro_cal->debug_print_trigger = true;
925 }
926
gyroCalDebugPrintData(const struct GyroCal * gyro_cal,char * debug_tag,enum DebugPrintData print_data)927 void gyroCalDebugPrintData(const struct GyroCal* gyro_cal, char* debug_tag,
928 enum DebugPrintData print_data) {
929 // Prints out the desired debug data.
930 float mag_data;
931 switch (print_data) {
932 case OFFSET:
933 CAL_DEBUG_LOG(debug_tag,
934 "Cal#|Offset|Temp|Time [mdps|C|nsec]: %lu, %s%d.%06d, "
935 "%s%d.%06d, %s%d.%06d, %s%d.%03d, %llu",
936 (unsigned long int)gyro_cal->debug_calibration_count,
937 CAL_ENCODE_FLOAT(gyro_cal->debug_gyro_cal.calibration[0] *
938 RAD_TO_MILLI_DEGREES,
939 6),
940 CAL_ENCODE_FLOAT(gyro_cal->debug_gyro_cal.calibration[1] *
941 RAD_TO_MILLI_DEGREES,
942 6),
943 CAL_ENCODE_FLOAT(gyro_cal->debug_gyro_cal.calibration[2] *
944 RAD_TO_MILLI_DEGREES,
945 6),
946 CAL_ENCODE_FLOAT(
947 gyro_cal->debug_gyro_cal.temperature_mean_celsius, 3),
948 (unsigned long long int)
949 gyro_cal->debug_gyro_cal.end_still_time_nanos);
950 break;
951
952 case STILLNESS_DATA:
953 mag_data = (gyro_cal->debug_gyro_cal.using_mag_sensor)
954 ? gyro_cal->debug_gyro_cal.mag_stillness_conf
955 : -1.0f; // Signals that magnetometer was not used.
956 CAL_DEBUG_LOG(
957 debug_tag,
958 "Cal#|Start|End|Confidence [nsec]: %lu, %llu, %llu, "
959 "%s%d.%03d, %s%d.%03d, %s%d.%03d",
960 (unsigned long int)gyro_cal->debug_calibration_count,
961 (unsigned long long int)
962 gyro_cal->debug_gyro_cal.start_still_time_nanos,
963 (unsigned long long int)gyro_cal->debug_gyro_cal.end_still_time_nanos,
964 CAL_ENCODE_FLOAT(gyro_cal->debug_gyro_cal.gyro_stillness_conf, 3),
965 CAL_ENCODE_FLOAT(gyro_cal->debug_gyro_cal.accel_stillness_conf, 3),
966 CAL_ENCODE_FLOAT(mag_data, 3));
967 break;
968
969 case SAMPLE_RATE_AND_TEMPERATURE:
970 CAL_DEBUG_LOG(
971 debug_tag,
972 "Cal#|Mean|Min|Max|Delta|Sample Rate [C|Hz]: %lu, %s%d.%03d, "
973 "%s%d.%03d, %s%d.%03d, %s%d.%04d, %s%d.%03d",
974 (unsigned long int)gyro_cal->debug_calibration_count,
975 CAL_ENCODE_FLOAT(gyro_cal->debug_gyro_cal.temperature_mean_celsius,
976 3),
977 CAL_ENCODE_FLOAT(
978 gyro_cal->debug_gyro_cal.temperature_min_max_celsius[0], 3),
979 CAL_ENCODE_FLOAT(
980 gyro_cal->debug_gyro_cal.temperature_min_max_celsius[1], 3),
981 CAL_ENCODE_FLOAT(
982 gyro_cal->debug_gyro_cal.temperature_min_max_celsius[1] -
983 gyro_cal->debug_gyro_cal.temperature_min_max_celsius[0],
984 4),
985 CAL_ENCODE_FLOAT(gyro_cal->debug_gyro_cal.mean_sampling_rate_hz, 3));
986 break;
987
988 case GYRO_MINMAX_STILLNESS_MEAN:
989 CAL_DEBUG_LOG(
990 debug_tag,
991 "Cal#|Gyro Peak Stillness Variation [mdps]: %lu, %s%d.%06d, "
992 "%s%d.%06d, %s%d.%06d",
993 (unsigned long int)gyro_cal->debug_calibration_count,
994 CAL_ENCODE_FLOAT((gyro_cal->debug_gyro_cal.gyro_winmean_max[0] -
995 gyro_cal->debug_gyro_cal.gyro_winmean_min[0]) *
996 RAD_TO_MILLI_DEGREES,
997 6),
998 CAL_ENCODE_FLOAT((gyro_cal->debug_gyro_cal.gyro_winmean_max[1] -
999 gyro_cal->debug_gyro_cal.gyro_winmean_min[1]) *
1000 RAD_TO_MILLI_DEGREES,
1001 6),
1002 CAL_ENCODE_FLOAT((gyro_cal->debug_gyro_cal.gyro_winmean_max[2] -
1003 gyro_cal->debug_gyro_cal.gyro_winmean_min[2]) *
1004 RAD_TO_MILLI_DEGREES,
1005 6));
1006 break;
1007
1008 case ACCEL_STATS:
1009 CAL_DEBUG_LOG(
1010 debug_tag,
1011 "Cal#|Accel Mean|Var [m/sec^2|(m/sec^2)^2]: %lu, "
1012 "%s%d.%06d, %s%d.%06d, %s%d.%06d, %s%d.%08d, %s%d.%08d, %s%d.%08d",
1013 (unsigned long int)gyro_cal->debug_calibration_count,
1014 CAL_ENCODE_FLOAT(gyro_cal->debug_gyro_cal.accel_mean[0], 6),
1015 CAL_ENCODE_FLOAT(gyro_cal->debug_gyro_cal.accel_mean[1], 6),
1016 CAL_ENCODE_FLOAT(gyro_cal->debug_gyro_cal.accel_mean[2], 6),
1017 CAL_ENCODE_FLOAT(gyro_cal->debug_gyro_cal.accel_var[0], 8),
1018 CAL_ENCODE_FLOAT(gyro_cal->debug_gyro_cal.accel_var[1], 8),
1019 CAL_ENCODE_FLOAT(gyro_cal->debug_gyro_cal.accel_var[2], 8));
1020 break;
1021
1022 case GYRO_STATS:
1023 CAL_DEBUG_LOG(
1024 debug_tag,
1025 "Cal#|Gyro Mean|Var [mdps|(rad/sec)^2]: %lu, %s%d.%06d, "
1026 "%s%d.%06d, %s%d.%06d, %s%d.%08d, %s%d.%08d, %s%d.%08d",
1027 (unsigned long int)gyro_cal->debug_calibration_count,
1028 CAL_ENCODE_FLOAT(
1029 gyro_cal->debug_gyro_cal.gyro_mean[0] * RAD_TO_MILLI_DEGREES, 6),
1030 CAL_ENCODE_FLOAT(
1031 gyro_cal->debug_gyro_cal.gyro_mean[1] * RAD_TO_MILLI_DEGREES, 6),
1032 CAL_ENCODE_FLOAT(
1033 gyro_cal->debug_gyro_cal.gyro_mean[2] * RAD_TO_MILLI_DEGREES, 6),
1034 CAL_ENCODE_FLOAT(gyro_cal->debug_gyro_cal.gyro_var[0], 8),
1035 CAL_ENCODE_FLOAT(gyro_cal->debug_gyro_cal.gyro_var[1], 8),
1036 CAL_ENCODE_FLOAT(gyro_cal->debug_gyro_cal.gyro_var[2], 8));
1037 break;
1038
1039 case MAG_STATS:
1040 if (gyro_cal->debug_gyro_cal.using_mag_sensor) {
1041 CAL_DEBUG_LOG(debug_tag,
1042 "Cal#|Mag Mean|Var [uT|uT^2]: %lu, %s%d.%06d, "
1043 "%s%d.%06d, %s%d.%06d, %s%d.%08d, %s%d.%08d, %s%d.%08d",
1044 (unsigned long int)gyro_cal->debug_calibration_count,
1045 CAL_ENCODE_FLOAT(gyro_cal->debug_gyro_cal.mag_mean[0], 6),
1046 CAL_ENCODE_FLOAT(gyro_cal->debug_gyro_cal.mag_mean[1], 6),
1047 CAL_ENCODE_FLOAT(gyro_cal->debug_gyro_cal.mag_mean[2], 6),
1048 CAL_ENCODE_FLOAT(gyro_cal->debug_gyro_cal.mag_var[0], 8),
1049 CAL_ENCODE_FLOAT(gyro_cal->debug_gyro_cal.mag_var[1], 8),
1050 CAL_ENCODE_FLOAT(gyro_cal->debug_gyro_cal.mag_var[2], 8));
1051 } else {
1052 CAL_DEBUG_LOG(debug_tag,
1053 "Cal#|Mag Mean|Var [uT|uT^2]: %lu, 0, 0, 0, -1.0, -1.0, "
1054 "-1.0",
1055 (unsigned long int)gyro_cal->debug_calibration_count);
1056 }
1057 break;
1058
1059 #ifdef GYRO_CAL_DBG_TUNE_ENABLED
1060 case ACCEL_STATS_TUNING:
1061 CAL_DEBUG_LOG(
1062 debug_tag,
1063 "Accel Mean|Var [m/sec^2|(m/sec^2)^2]: %s%d.%06d, "
1064 "%s%d.%06d, %s%d.%06d, %s%d.%08d, %s%d.%08d, %s%d.%08d",
1065 CAL_ENCODE_FLOAT(gyro_cal->accel_stillness_detect.prev_mean_x, 6),
1066 CAL_ENCODE_FLOAT(gyro_cal->accel_stillness_detect.prev_mean_y, 6),
1067 CAL_ENCODE_FLOAT(gyro_cal->accel_stillness_detect.prev_mean_z, 6),
1068 CAL_ENCODE_FLOAT(gyro_cal->accel_stillness_detect.win_var_x, 8),
1069 CAL_ENCODE_FLOAT(gyro_cal->accel_stillness_detect.win_var_y, 8),
1070 CAL_ENCODE_FLOAT(gyro_cal->accel_stillness_detect.win_var_z, 8));
1071 break;
1072
1073 case GYRO_STATS_TUNING:
1074 CAL_DEBUG_LOG(
1075 debug_tag,
1076 "Gyro Mean|Var [mdps|(rad/sec)^2]: %s%d.%06d, %s%d.%06d, %s%d.%06d, "
1077 "%s%d.%08d, %s%d.%08d, %s%d.%08d",
1078 CAL_ENCODE_FLOAT(gyro_cal->gyro_stillness_detect.prev_mean_x *
1079 RAD_TO_MILLI_DEGREES,
1080 6),
1081 CAL_ENCODE_FLOAT(gyro_cal->gyro_stillness_detect.prev_mean_y *
1082 RAD_TO_MILLI_DEGREES,
1083 6),
1084 CAL_ENCODE_FLOAT(gyro_cal->gyro_stillness_detect.prev_mean_z *
1085 RAD_TO_MILLI_DEGREES,
1086 6),
1087 CAL_ENCODE_FLOAT(gyro_cal->gyro_stillness_detect.win_var_x, 8),
1088 CAL_ENCODE_FLOAT(gyro_cal->gyro_stillness_detect.win_var_y, 8),
1089 CAL_ENCODE_FLOAT(gyro_cal->gyro_stillness_detect.win_var_z, 8));
1090 break;
1091
1092 case MAG_STATS_TUNING:
1093 if (gyro_cal->using_mag_sensor) {
1094 CAL_DEBUG_LOG(
1095 debug_tag,
1096 "Mag Mean|Var [uT|uT^2]: %s%d.%06d, %s%d.%06d, %s%d.%06d, "
1097 "%s%d.%08d, %s%d.%08d, %s%d.%08d",
1098 CAL_ENCODE_FLOAT(gyro_cal->mag_stillness_detect.prev_mean_x, 6),
1099 CAL_ENCODE_FLOAT(gyro_cal->mag_stillness_detect.prev_mean_y, 6),
1100 CAL_ENCODE_FLOAT(gyro_cal->mag_stillness_detect.prev_mean_z, 6),
1101 CAL_ENCODE_FLOAT(gyro_cal->mag_stillness_detect.win_var_x, 8),
1102 CAL_ENCODE_FLOAT(gyro_cal->mag_stillness_detect.win_var_y, 8),
1103 CAL_ENCODE_FLOAT(gyro_cal->mag_stillness_detect.win_var_z, 8));
1104 } else {
1105 CAL_DEBUG_LOG(GYROCAL_TUNE_TAG,
1106 "Mag Mean|Var [uT|uT^2]: 0, 0, 0, -1.0, -1.0, -1.0");
1107 }
1108 break;
1109 #endif // GYRO_CAL_DBG_TUNE_ENABLED
1110
1111 default:
1112 break;
1113 }
1114 }
1115
gyroCalDebugPrint(struct GyroCal * gyro_cal,uint64_t timestamp_nanos)1116 void gyroCalDebugPrint(struct GyroCal* gyro_cal, uint64_t timestamp_nanos) {
1117 static enum GyroCalDebugState next_state = GYRO_IDLE;
1118 static uint64_t wait_timer_nanos = 0;
1119
1120 // This is a state machine that controls the reporting out of debug data.
1121 switch (gyro_cal->debug_state) {
1122 case GYRO_IDLE:
1123 // Wait for a trigger and start the debug printout sequence.
1124 if (gyro_cal->debug_print_trigger) {
1125 CAL_DEBUG_LOG(GYROCAL_REPORT_TAG, "");
1126 CAL_DEBUG_LOG(GYROCAL_REPORT_TAG, "Debug Version: %s",
1127 GYROCAL_DEBUG_VERSION_STRING);
1128 gyro_cal->debug_print_trigger = false; // Resets trigger.
1129 gyro_cal->debug_state = GYRO_PRINT_OFFSET;
1130 } else {
1131 gyro_cal->debug_state = GYRO_IDLE;
1132 }
1133 break;
1134
1135 case GYRO_WAIT_STATE:
1136 // This helps throttle the print statements.
1137 if (timestamp_nanos >= GYROCAL_WAIT_TIME_NANOS + wait_timer_nanos) {
1138 gyro_cal->debug_state = next_state;
1139 }
1140 break;
1141
1142 case GYRO_PRINT_OFFSET:
1143 gyroCalDebugPrintData(gyro_cal, GYROCAL_REPORT_TAG, OFFSET);
1144 wait_timer_nanos = timestamp_nanos; // Starts the wait timer.
1145 next_state = GYRO_PRINT_STILLNESS_DATA; // Sets the next state.
1146 gyro_cal->debug_state = GYRO_WAIT_STATE; // First, go to wait state.
1147 break;
1148
1149 case GYRO_PRINT_STILLNESS_DATA:
1150 gyroCalDebugPrintData(gyro_cal, GYROCAL_REPORT_TAG, STILLNESS_DATA);
1151 wait_timer_nanos = timestamp_nanos; // Starts the wait timer.
1152 next_state = GYRO_PRINT_SAMPLE_RATE_AND_TEMPERATURE; // Sets next state.
1153 gyro_cal->debug_state = GYRO_WAIT_STATE; // First, go to wait state.
1154 break;
1155
1156 case GYRO_PRINT_SAMPLE_RATE_AND_TEMPERATURE:
1157 gyroCalDebugPrintData(gyro_cal, GYROCAL_REPORT_TAG,
1158 SAMPLE_RATE_AND_TEMPERATURE);
1159 wait_timer_nanos = timestamp_nanos; // Starts the wait timer.
1160 next_state = GYRO_PRINT_GYRO_MINMAX_STILLNESS_MEAN; // Sets next state.
1161 gyro_cal->debug_state = GYRO_WAIT_STATE; // First, go to wait state.
1162 break;
1163
1164 case GYRO_PRINT_GYRO_MINMAX_STILLNESS_MEAN:
1165 gyroCalDebugPrintData(gyro_cal, GYROCAL_REPORT_TAG,
1166 GYRO_MINMAX_STILLNESS_MEAN);
1167 wait_timer_nanos = timestamp_nanos; // Starts the wait timer.
1168 next_state = GYRO_PRINT_ACCEL_STATS; // Sets the next state.
1169 gyro_cal->debug_state = GYRO_WAIT_STATE; // First, go to wait state.
1170 break;
1171
1172 case GYRO_PRINT_ACCEL_STATS:
1173 gyroCalDebugPrintData(gyro_cal, GYROCAL_REPORT_TAG, ACCEL_STATS);
1174 wait_timer_nanos = timestamp_nanos; // Starts the wait timer.
1175 next_state = GYRO_PRINT_GYRO_STATS; // Sets the next state.
1176 gyro_cal->debug_state = GYRO_WAIT_STATE; // First, go to wait state.
1177 break;
1178
1179 case GYRO_PRINT_GYRO_STATS:
1180 gyroCalDebugPrintData(gyro_cal, GYROCAL_REPORT_TAG, GYRO_STATS);
1181 wait_timer_nanos = timestamp_nanos; // Starts the wait timer.
1182 next_state = GYRO_PRINT_MAG_STATS; // Sets the next state.
1183 gyro_cal->debug_state = GYRO_WAIT_STATE; // First, go to wait state.
1184 break;
1185
1186 case GYRO_PRINT_MAG_STATS:
1187 gyroCalDebugPrintData(gyro_cal, GYROCAL_REPORT_TAG, MAG_STATS);
1188 wait_timer_nanos = timestamp_nanos; // Starts the wait timer.
1189 next_state = GYRO_IDLE; // Sets the next state.
1190 gyro_cal->debug_state = GYRO_WAIT_STATE; // First, go to wait state.
1191 break;
1192
1193 default:
1194 // Sends this state machine to its idle state.
1195 wait_timer_nanos = timestamp_nanos; // Starts the wait timer.
1196 gyro_cal->debug_state = GYRO_WAIT_STATE; // First, go to wait state.
1197 }
1198
1199 #ifdef GYRO_CAL_DBG_TUNE_ENABLED
1200 if (gyro_cal->debug_state == GYRO_IDLE) {
1201 // This check keeps the tuning printout from interleaving with the above
1202 // debug print data.
1203 gyroCalTuneDebugPrint(gyro_cal, timestamp_nanos);
1204 }
1205 #endif // GYRO_CAL_DBG_TUNE_ENABLED
1206 }
1207
1208 #ifdef GYRO_CAL_DBG_TUNE_ENABLED
gyroCalTuneDebugPrint(const struct GyroCal * gyro_cal,uint64_t timestamp_nanos)1209 void gyroCalTuneDebugPrint(const struct GyroCal* gyro_cal,
1210 uint64_t timestamp_nanos) {
1211 static enum GyroCalDebugState debug_state = GYRO_IDLE;
1212 static enum GyroCalDebugState next_state = GYRO_IDLE;
1213 static uint64_t wait_timer_nanos = 0;
1214
1215 // Output sensor variance levels to assist with tuning thresholds.
1216 // i. Within the first 300 seconds of boot: output interval = 5
1217 // seconds.
1218 // ii. Thereafter: output interval is 60 seconds.
1219 bool condition_i =
1220 ((timestamp_nanos <= 300000000000) &&
1221 (timestamp_nanos > 5000000000 + wait_timer_nanos)); // nsec
1222 bool condition_ii = (timestamp_nanos > 60000000000 + wait_timer_nanos);
1223
1224 // This is a state machine that controls the reporting out of tuning data.
1225 switch (debug_state) {
1226 case GYRO_IDLE:
1227 // Wait for a trigger and start the data tuning printout sequence.
1228 if (condition_i || condition_ii) {
1229 CAL_DEBUG_LOG(GYROCAL_TUNE_TAG, "Temp [C]: %s%d.%03d",
1230 CAL_ENCODE_FLOAT(gyro_cal->temperature_mean_celsius, 3));
1231 wait_timer_nanos = timestamp_nanos; // Starts the wait timer.
1232 next_state = GYRO_PRINT_ACCEL_STATS; // Sets the next state.
1233 debug_state = GYRO_WAIT_STATE; // First, go to wait state.
1234 } else {
1235 debug_state = GYRO_IDLE;
1236 }
1237 break;
1238
1239 case GYRO_WAIT_STATE:
1240 // This helps throttle the print statements.
1241 if (timestamp_nanos >= GYROCAL_WAIT_TIME_NANOS + wait_timer_nanos) {
1242 debug_state = next_state;
1243 }
1244 break;
1245
1246 case GYRO_PRINT_ACCEL_STATS:
1247 gyroCalDebugPrintData(gyro_cal, GYROCAL_TUNE_TAG, ACCEL_STATS_TUNING);
1248 wait_timer_nanos = timestamp_nanos; // Starts the wait timer.
1249 next_state = GYRO_PRINT_GYRO_STATS; // Sets the next state.
1250 debug_state = GYRO_WAIT_STATE; // First, go to wait state.
1251 break;
1252
1253 case GYRO_PRINT_GYRO_STATS:
1254 gyroCalDebugPrintData(gyro_cal, GYROCAL_TUNE_TAG, GYRO_STATS_TUNING);
1255 wait_timer_nanos = timestamp_nanos; // Starts the wait timer.
1256 next_state = GYRO_PRINT_MAG_STATS; // Sets the next state.
1257 debug_state = GYRO_WAIT_STATE; // First, go to wait state.
1258 break;
1259
1260 case GYRO_PRINT_MAG_STATS:
1261 gyroCalDebugPrintData(gyro_cal, GYROCAL_TUNE_TAG, MAG_STATS_TUNING);
1262 wait_timer_nanos = timestamp_nanos; // Starts the wait timer.
1263 next_state = GYRO_IDLE; // Sets the next state.
1264 debug_state = GYRO_WAIT_STATE; // First, go to wait state.
1265 break;
1266
1267 default:
1268 // Sends this state machine to its idle state.
1269 wait_timer_nanos = timestamp_nanos; // Starts the wait timer.
1270 debug_state = GYRO_IDLE;
1271 }
1272 }
1273 #endif // GYRO_CAL_DBG_TUNE_ENABLED
1274 #endif // GYRO_CAL_DBG_ENABLED
1275