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 /*
18  * This module contains the algorithms for producing a gyroscope offset
19  * calibration. The algorithm looks for periods of stillness as indicated by
20  * accelerometer, magnetometer and gyroscope, and computes a bias estimate by
21  * taking the average of the gyroscope during the stillness times.
22  *
23  * Currently, this algorithm is tuned such that the device is only considered
24  * still when the device is on a stationary surface (e.g., not on a person).
25  *
26  * NOTE - Time units are agnostic (i.e., determined by the user's application
27  * and usage). However, typical time units are nanoseconds.
28  *
29  * Required Sensors and Units:
30  *       - Gyroscope     [rad/sec]
31  *       - Accelerometer [m/sec^2]
32  *
33  * Optional Sensors and Units:
34  *       - Magnetometer  [micro-Tesla, uT]
35  *       - Temperature   [Celsius]
36  *
37  * #define GYRO_CAL_DBG_ENABLED to enable debug printout statements.
38  */
39 
40 #ifndef LOCATION_LBS_CONTEXTHUB_NANOAPPS_CALIBRATION_GYROSCOPE_GYRO_CAL_H_
41 #define LOCATION_LBS_CONTEXTHUB_NANOAPPS_CALIBRATION_GYROSCOPE_GYRO_CAL_H_
42 
43 #include "calibration/gyroscope/gyro_stillness_detect.h"
44 
45 #ifdef GYRO_CAL_DBG_ENABLED
46 #include "calibration/sample_rate_estimator/sample_rate_estimator.h"
47 #endif  // GYRO_CAL_DBG_ENABLED
48 
49 #ifdef __cplusplus
50 extern "C" {
51 #endif
52 
53 #ifdef GYRO_CAL_DBG_ENABLED
54 // Debug printout state enumeration.
55 enum GyroCalDebugState {
56   GYRO_IDLE = 0,
57   GYRO_WAIT_STATE,
58   GYRO_PRINT_OFFSET,
59   GYRO_PRINT_STILLNESS_DATA,
60   GYRO_PRINT_SAMPLE_RATE_AND_TEMPERATURE,
61   GYRO_PRINT_GYRO_MINMAX_STILLNESS_MEAN,
62   GYRO_PRINT_ACCEL_STATS,
63   GYRO_PRINT_GYRO_STATS,
64   GYRO_PRINT_MAG_STATS
65 };
66 
67 // Gyro Cal debug information/data tracking structure.
68 struct DebugGyroCal {
69   struct SampleRateEstimator sample_rate_estimator;
70   uint64_t start_still_time_nanos;
71   uint64_t end_still_time_nanos;
72   uint64_t stillness_duration_nanos;
73   float accel_stillness_conf;
74   float gyro_stillness_conf;
75   float mag_stillness_conf;
76   float calibration[3];
77   float accel_mean[3];
78   float gyro_mean[3];
79   float mag_mean[3];
80   float accel_var[3];
81   float gyro_var[3];
82   float mag_var[3];
83   float gyro_winmean_min[3];
84   float gyro_winmean_max[3];
85   float temperature_min_celsius;
86   float temperature_max_celsius;
87   float temperature_mean_celsius;
88   bool using_mag_sensor;
89 };
90 #endif  // GYRO_CAL_DBG_ENABLED
91 
92 // GyroCal algorithm parameters (see GyroCal and GyroStillDet for details).
93 struct GyroCalParameters {
94   uint64_t min_still_duration_nanos;
95   uint64_t max_still_duration_nanos;
96   uint64_t calibration_time_nanos;
97   uint64_t window_time_duration_nanos;
98   float bias_x;  // units: radians per second
99   float bias_y;
100   float bias_z;
101   float stillness_threshold;         // units: (radians per second)^2
102   float stillness_mean_delta_limit;  // units: radians per second
103   float gyro_var_threshold;          // units: (radians per second)^2
104   float gyro_confidence_delta;       // units: (radians per second)^2
105   float accel_var_threshold;         // units: (meters per second)^2
106   float accel_confidence_delta;      // units: (meters per second)^2
107   float mag_var_threshold;           // units: micro-tesla^2
108   float mag_confidence_delta;        // units: micro-tesla^2
109   float temperature_delta_limit_celsius;
110   bool gyro_calibration_enable;
111 };
112 
113 // Data structure for tracking min/max window mean during device stillness.
114 struct MinMaxWindowMeanData {
115   float gyro_winmean_min[3];
116   float gyro_winmean_max[3];
117 };
118 
119 // Data structure for tracking temperature data during device stillness.
120 struct TemperatureMeanData {
121   float temperature_min_celsius;
122   float temperature_max_celsius;
123   float latest_temperature_celsius;
124   float mean_accumulator;
125   size_t num_points;
126 };
127 
128 struct GyroCal {
129   // Stillness detectors.
130   struct GyroStillDet accel_stillness_detect;
131   struct GyroStillDet mag_stillness_detect;
132   struct GyroStillDet gyro_stillness_detect;
133 
134   // Data for tracking temperature mean during periods of device stillness.
135   struct TemperatureMeanData temperature_mean_tracker;
136 
137   // Data for tracking gyro mean during periods of device stillness.
138   struct MinMaxWindowMeanData window_mean_tracker;
139 
140   // Aggregated sensor stillness threshold required for gyro bias calibration.
141   float stillness_threshold;
142 
143   // Min and max durations for gyro bias calibration.
144   uint64_t min_still_duration_nanos;
145   uint64_t max_still_duration_nanos;
146 
147   // Duration of the stillness processing windows.
148   uint64_t window_time_duration_nanos;
149 
150   // Timestamp when device started a still period.
151   uint64_t start_still_time_nanos;
152 
153   // Gyro offset estimate, and the associated calibration temperature,
154   // timestamp, and stillness confidence values.
155   float bias_x, bias_y, bias_z;  // [rad/sec]
156   float bias_temperature_celsius;
157   float stillness_confidence;
158   uint64_t calibration_time_nanos;
159 
160   // Current window end-time for all sensors. Used to assist in keeping
161   // sensor data collection in sync. On initialization this will be set to
162   // zero indicating that sensor data will be dropped until a valid end-time
163   // is set from the first gyro timestamp received.
164   uint64_t stillness_win_endtime_nanos;
165 
166   // Watchdog timer to reset to a known good state when data capture stalls.
167   uint64_t gyro_watchdog_start_nanos;
168   uint64_t gyro_watchdog_timeout_duration_nanos;
169 
170   // Flag is "true" when the magnetometer is used.
171   bool using_mag_sensor;
172 
173   // Flag set by user to control whether calibrations are used (default:
174   // "true").
175   bool gyro_calibration_enable;
176 
177   // Flag is 'true' when a new calibration update is ready.
178   bool new_gyro_cal_available;
179 
180   // Flag to indicate if device was previously still.
181   bool prev_still;
182 
183   // Min and maximum stillness window mean. This is used to check the stability
184   // of the mean values computed for the gyroscope (i.e., provides further
185   // validation for stillness).
186   float gyro_winmean_min[3];
187   float gyro_winmean_max[3];
188   float stillness_mean_delta_limit;
189 
190   // The mean temperature over the stillness period. The limit is used to check
191   // for temperature stability and provide a gate for when temperature is
192   // rapidly changing.
193   float temperature_mean_celsius;
194   float temperature_delta_limit_celsius;
195 
196   //----------------------------------------------------------------
197 
198 #ifdef GYRO_CAL_DBG_ENABLED
199   // Debug info.
200   struct DebugGyroCal debug_gyro_cal;  // Debug data structure.
201   enum GyroCalDebugState debug_state;  // Debug printout state machine.
202   enum GyroCalDebugState next_state;   // Debug state machine next state.
203   uint64_t wait_timer_nanos;           // Debug message throttle timer.
204   size_t debug_calibration_count;      // Total number of cals performed.
205   size_t debug_watchdog_count;         // Total number of watchdog timeouts.
206   bool debug_print_trigger;            // Flag used to trigger data printout.
207 #endif                                 // GYRO_CAL_DBG_ENABLED
208 };
209 
210 /////// FUNCTION PROTOTYPES //////////////////////////////////////////
211 
212 // Initialize the gyro calibration data structure.
213 void gyroCalInit(struct GyroCal* gyro_cal,
214                  const struct GyroCalParameters* parameters);
215 
216 // Void all pointers in the gyro calibration data structure.
217 void gyroCalDestroy(struct GyroCal* gyro_cal);
218 
219 // Get the most recent bias calibration value.
220 void gyroCalGetBias(struct GyroCal* gyro_cal, float* bias_x, float* bias_y,
221                     float* bias_z, float* temperature_celsius,
222                     uint64_t* calibration_time_nanos);
223 
224 // Set an initial bias calibration value.
225 void gyroCalSetBias(struct GyroCal* gyro_cal, float bias_x, float bias_y,
226                     float bias_z, float temperature_celsius,
227                     uint64_t calibration_time_nanos);
228 
229 // Remove gyro bias from the calibration [rad/sec].
230 void gyroCalRemoveBias(struct GyroCal* gyro_cal, float xi, float yi, float zi,
231                        float* xo, float* yo, float* zo);
232 
233 // Returns true when a new gyro calibration is available.
234 bool gyroCalNewBiasAvailable(struct GyroCal* gyro_cal);
235 
236 // Update the gyro calibration with gyro data [rad/sec].
237 void gyroCalUpdateGyro(struct GyroCal* gyro_cal, uint64_t sample_time_nanos,
238                        float x, float y, float z, float temperature_celsius);
239 
240 // Update the gyro calibration with mag data [micro Tesla].
241 void gyroCalUpdateMag(struct GyroCal* gyro_cal, uint64_t sample_time_nanos,
242                       float x, float y, float z);
243 
244 // Update the gyro calibration with accel data [m/sec^2].
245 void gyroCalUpdateAccel(struct GyroCal* gyro_cal, uint64_t sample_time_nanos,
246                         float x, float y, float z);
247 
248 #ifdef GYRO_CAL_DBG_ENABLED
249 // Print debug data report.
250 void gyroCalDebugPrint(struct GyroCal* gyro_cal,
251                        uint64_t timestamp_nanos_nanos);
252 #endif
253 
254 #ifdef __cplusplus
255 }
256 #endif
257 
258 #endif  // LOCATION_LBS_CONTEXTHUB_NANOAPPS_CALIBRATION_GYROSCOPE_GYRO_CAL_H_
259