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 <string.h>
18 #include <algos/gyro_stillness_detect.h>
19
20 /////// FORWARD DECLARATIONS /////////////////////////////////////////
21
22 // Enforces the limits of an input value [0,1].
23 static float gyroStillDetLimit(float value);
24
25 /////// FUNCTION DEFINITIONS /////////////////////////////////////////
26
27 // Initialize the gyroStillDet_t structure.
gyroStillDetInit(struct gyroStillDet_t * gyro_still_det,float var_threshold,float confidence_delta)28 void gyroStillDetInit(struct gyroStillDet_t* gyro_still_det,
29 float var_threshold,
30 float confidence_delta) {
31
32 // Clear all data structure variables to 0.
33 memset(gyro_still_det, 0, sizeof(struct gyroStillDet_t));
34
35 // Set the delta about the variance threshold for calculation
36 // of the stillness confidence score.
37 if (confidence_delta < var_threshold) {
38 gyro_still_det->confidence_delta = confidence_delta;
39 } else {
40 gyro_still_det->confidence_delta = var_threshold;
41 }
42
43 // Set the variance threshold parameter for the stillness
44 // confidence score.
45 gyro_still_det->var_threshold = var_threshold;
46
47 // Signal to start capture of next stillness data window.
48 gyro_still_det->start_new_window = true;
49 }
50
51 // Update the stillness detector with a new sample.
gyroStillDetUpdate(struct gyroStillDet_t * gyro_still_det,uint64_t stillness_win_endtime,uint64_t sample_time,float x,float y,float z)52 void gyroStillDetUpdate(struct gyroStillDet_t* gyro_still_det,
53 uint64_t stillness_win_endtime,
54 uint64_t sample_time,
55 float x, float y, float z) {
56
57 // Using the method of the assumed mean to preserve some numerical
58 // stability while avoiding per-sample divisions that the more
59 // numerically stabe Welford method would afford.
60
61 // Reference for the numerical method used below to compute the
62 // online mean and variance statistics:
63 // 1). en.wikipedia.org/wiki/assumed_mean
64
65 float delta = 0;
66
67 // If the window end time is not valid then wait till it is.
68 if (stillness_win_endtime <= 0) {
69 return;
70 }
71
72 // Increment the number of samples.
73 gyro_still_det->num_acc_samples++;
74
75 // Online computation of mean for the running stillness period.
76 gyro_still_det->mean_x += x;
77 gyro_still_det->mean_y += y;
78 gyro_still_det->mean_z += z;
79
80 // Is this the first sample of a new window?
81 if (gyro_still_det->start_new_window) {
82
83 // Record the window start time.
84 gyro_still_det->window_start_time = sample_time;
85 gyro_still_det->start_new_window = false;
86
87 // Update assumed mean values.
88 gyro_still_det->assumed_mean_x = x;
89 gyro_still_det->assumed_mean_y = y;
90 gyro_still_det->assumed_mean_z = z;
91
92 // Reset current window mean and variance.
93 gyro_still_det->num_acc_win_samples = 0;
94 gyro_still_det->win_mean_x = 0;
95 gyro_still_det->win_mean_y = 0;
96 gyro_still_det->win_mean_z = 0;
97 gyro_still_det->acc_var_x = 0;
98 gyro_still_det->acc_var_y = 0;
99 gyro_still_det->acc_var_z = 0;
100 } else {
101
102 // Check to see if we have enough samples to compute a stillness
103 // confidence score.
104 gyro_still_det->stillness_window_ready =
105 (sample_time >= stillness_win_endtime) &&
106 (gyro_still_det->num_acc_samples > 1);
107 }
108
109 // Record the most recent sample time stamp.
110 gyro_still_det->last_sample_time = sample_time;
111
112 // Online window mean and variance ("one-pass" accumulation).
113 gyro_still_det->num_acc_win_samples++;
114
115 delta = (x - gyro_still_det->assumed_mean_x);
116 gyro_still_det->win_mean_x += delta;
117 gyro_still_det->acc_var_x += delta * delta;
118
119 delta = (y - gyro_still_det->assumed_mean_y);
120 gyro_still_det->win_mean_y += delta;
121 gyro_still_det->acc_var_y += delta * delta;
122
123 delta = (z - gyro_still_det->assumed_mean_z);
124 gyro_still_det->win_mean_z += delta;
125 gyro_still_det->acc_var_z += delta * delta;
126 }
127
128 // Calculates and returns the stillness confidence score [0,1].
gyroStillDetCompute(struct gyroStillDet_t * gyro_still_det)129 float gyroStillDetCompute(struct gyroStillDet_t* gyro_still_det) {
130
131 float tmp_denom = 1.f;
132 float tmp_mean = 1.f;
133
134 // Don't divide by zero (not likely, but a precaution).
135 if (gyro_still_det->num_acc_win_samples > 1) {
136 tmp_denom = 1.f / (gyro_still_det->num_acc_win_samples - 1);
137 } else {
138 // Return zero stillness confidence.
139 gyro_still_det->stillness_confidence = 0;
140 return gyro_still_det->stillness_confidence;
141 }
142
143 // Update the final calculation of variance.
144 // variance_x = win_var_x / (num_samples - 1).
145 tmp_mean = gyro_still_det->win_mean_x * tmp_denom;
146 gyro_still_det->win_var_x = (gyro_still_det->acc_var_x * tmp_denom) -
147 tmp_mean * tmp_mean;
148 tmp_mean = gyro_still_det->win_mean_y * tmp_denom;
149 gyro_still_det->win_var_y = (gyro_still_det->acc_var_y * tmp_denom) -
150 tmp_mean * tmp_mean;
151 tmp_mean = gyro_still_det->win_mean_z * tmp_denom;
152 gyro_still_det->win_var_z = (gyro_still_det->acc_var_z * tmp_denom) -
153 tmp_mean * tmp_mean;
154
155 // Define the variance thresholds.
156 float upper_var_thresh = (gyro_still_det->var_threshold +
157 gyro_still_det->confidence_delta);
158
159 float lower_var_thresh = (gyro_still_det->var_threshold -
160 gyro_still_det->confidence_delta);
161
162 // Compute the stillness confidence score.
163 if ((gyro_still_det->win_var_x > upper_var_thresh) ||
164 (gyro_still_det->win_var_y > upper_var_thresh) ||
165 (gyro_still_det->win_var_z > upper_var_thresh)) {
166
167 // Sensor variance exceeds the upper threshold (i.e., motion detected).
168 // Set stillness confidence equal to 0.
169 gyro_still_det->stillness_confidence = 0;
170
171 } else {
172
173 if ((gyro_still_det->win_var_x <= lower_var_thresh) &&
174 (gyro_still_det->win_var_y <= lower_var_thresh) &&
175 (gyro_still_det->win_var_z <= lower_var_thresh)) {
176
177 // Sensor variance is below the lower threshold (i.e., stillness detected).
178 // Set stillness confidence equal to 1.
179 gyro_still_det->stillness_confidence = 1.f;
180
181 } else {
182 // Motion detection thresholds not exceeded. Compute the stillness
183 // confidence score.
184
185 float var_thresh = gyro_still_det->var_threshold;
186
187 // Compute the stillness confidence score.
188 // Each axis score is limited [0,1].
189 tmp_denom = 1.f / (upper_var_thresh - lower_var_thresh);
190 gyro_still_det->stillness_confidence =
191 gyroStillDetLimit(
192 0.5 - (gyro_still_det->win_var_x - var_thresh) * tmp_denom) *
193 gyroStillDetLimit(
194 0.5 - (gyro_still_det->win_var_y - var_thresh) * tmp_denom) *
195 gyroStillDetLimit(
196 0.5 - (gyro_still_det->win_var_z - var_thresh) * tmp_denom);
197 }
198 }
199
200 // Return the stillness confidence.
201 return gyro_still_det->stillness_confidence;
202 }
203
204 // Resets the stillness detector and initiates a new detection window.
205 // 'reset_stats' determines whether the stillness statistics are reset.
gyroStillDetReset(struct gyroStillDet_t * gyro_still_det,bool reset_stats)206 void gyroStillDetReset(struct gyroStillDet_t* gyro_still_det,
207 bool reset_stats) {
208
209 float tmp_denom = 1.f;
210
211 // Reset the stillness data ready flag.
212 gyro_still_det->stillness_window_ready = false;
213
214 // Signal to start capture of next stillness data window.
215 gyro_still_det->start_new_window = true;
216
217 // Track the stillness confidence (current->previous).
218 gyro_still_det->prev_stillness_confidence =
219 gyro_still_det->stillness_confidence;
220
221 // Track changes in the mean estimate.
222 if (gyro_still_det->num_acc_samples > 1) {
223 tmp_denom = 1.f / gyro_still_det->num_acc_samples;
224 }
225 gyro_still_det->prev_mean_x = gyro_still_det->mean_x * tmp_denom;
226 gyro_still_det->prev_mean_y = gyro_still_det->mean_y * tmp_denom;
227 gyro_still_det->prev_mean_z = gyro_still_det->mean_z * tmp_denom;
228
229 // Reset the current statistics to zero.
230 if (reset_stats) {
231 gyro_still_det->num_acc_samples = 0;
232 gyro_still_det->mean_x = 0;
233 gyro_still_det->mean_y = 0;
234 gyro_still_det->mean_z = 0;
235 gyro_still_det->acc_var_x = 0;
236 gyro_still_det->acc_var_y = 0;
237 gyro_still_det->acc_var_z = 0;
238 }
239 }
240
241 // Enforces the limits of an input value [0,1].
gyroStillDetLimit(float value)242 float gyroStillDetLimit(float value) {
243
244 // Fix limits [0,1].
245 if (value < 0) {
246 value = 0;
247 } else {
248 if (value > 1.f) {
249 value = 1.f;
250 }
251 }
252
253 return value;
254 }
255