12
12
import java .util .TimerTask ;
13
13
14
14
public class StepDcretor implements SensorEventListener {
15
+ //存放三轴数据
16
+ float [] oriValues = new float [3 ];
17
+ final int valueNum = 4 ;
18
+ //用于存放计算阈值的波峰波谷差值
19
+ float [] tempValue = new float [valueNum ];
20
+ int tempCount = 0 ;
21
+ //是否上升的标志位
22
+ boolean isDirectionUp = false ;
23
+ //持续上升次数
24
+ int continueUpCount = 0 ;
25
+ //上一点的持续上升的次数,为了记录波峰的上升次数
26
+ int continueUpFormerCount = 0 ;
27
+ //上一点的状态,上升还是下降
28
+ boolean lastStatus = false ;
29
+ //波峰值
30
+ float peakOfWave = 0 ;
31
+ //波谷值
32
+ float valleyOfWave = 0 ;
33
+ //此次波峰的时间
34
+ long timeOfThisPeak = 0 ;
35
+ //上次波峰的时间
36
+ long timeOfLastPeak = 0 ;
37
+ //当前的时间
38
+ long timeOfNow = 0 ;
39
+ //当前传感器的值
40
+ float gravityNew = 0 ;
41
+ //上次传感器的值
42
+ float gravityOld = 0 ;
43
+ //动态阈值需要动态的数据,这个值用于这些动态数据的阈值
44
+ final float initialValue = (float ) 1.8 ;
45
+ //初始阈值
46
+ float ThreadValue = (float ) 2.0 ;
47
+
48
+
15
49
float avg_v = 0 ;
16
50
float min_v = 0 ;
17
51
float max_v = 0 ;
@@ -65,15 +99,10 @@ public void onSensorChanged(SensorEvent event) {
65
99
synchronized (this ) {
66
100
if (sensor .getType () == Sensor .TYPE_ACCELEROMETER ) {
67
101
calc_step (event );
68
-
69
102
}
70
103
}
71
104
}
72
105
73
-
74
-
75
-
76
-
77
106
public void onAccuracyChanged (Sensor arg0 , int arg1 ) {
78
107
79
108
}
@@ -143,12 +172,12 @@ void avg_check_v(float v) {
143
172
acc_count ++;
144
173
//求移动平均线
145
174
//50ms 1 second 20 , 3 sec60;
146
- if (acc_count < 64 ) {
175
+ if (acc_count < 34 ) {
147
176
//avg_v=((acc_count-1)*avg_v+v)/acc_count;
148
177
avg_v = avg_v + (v - avg_v ) / acc_count ;
149
178
} else {
150
179
//avg_v=(avg_v*99+v)/100;
151
- avg_v = avg_v * 63 / 64 + v / 64 ;
180
+ avg_v = avg_v * 33 / 34 + v / 34 ;
152
181
}
153
182
154
183
if (v > avg_v ) {
@@ -178,27 +207,25 @@ void avg_check_v(float v) {
178
207
if (up_c == 2 && (max_v - min_v ) > 2 ) {
179
208
//
180
209
long cur_time = System .currentTimeMillis ();
181
- if (cur_time - pre_time > 250 ) {
210
+ if (cur_time - pre_time >= 500
211
+ ) {
182
212
pre_time = cur_time ;
183
213
preStep ();
184
- // StepDcretor.CURRENT_SETP++;
185
- // //记步,通知ui
186
- // if (onSensorChangeListener != null) {
187
- // onSensorChangeListener.onChange();
188
- // }
189
- Log .e ("xfblog" ,"CURRENT_SETP:" +CURRENT_SETP );
214
+ Log .e ("xfblog" , "CURRENT_SETP:" + CURRENT_SETP );
190
215
} else {
191
216
up_c = 1 ;
192
217
}
193
218
}
194
219
}
195
220
196
- synchronized private void calc_step (SensorEvent arg0 ) {
197
- float v = (float ) Math .sqrt (arg0 .values [0 ] * arg0 .values [0 ] + arg0 .values [1 ] * arg0 .values [1 ] + arg0 .values [2 ] * arg0 .values [2 ]);
198
- avg_check_v (v );
221
+ synchronized private void calc_step (SensorEvent event ) {
222
+ average = (float ) Math .sqrt (Math .pow (event .values [0 ], 2 )
223
+ + Math .pow (event .values [1 ], 2 ) + Math .pow (event .values [2 ], 2 ));
224
+ // avg_check_v(average);
225
+ DetectorNewStep (average );
199
226
}
200
227
201
- private void preStep (){
228
+ private void preStep () {
202
229
if (CountTimeState == 0 ) {
203
230
// 开启计时器
204
231
time = new TimeCount (duration , 700 );
@@ -216,9 +243,7 @@ private void preStep(){
216
243
}
217
244
}
218
245
219
-
220
-
221
- private void oldCalStep (SensorEvent event ){
246
+ private void oldCalStep (SensorEvent event ) {
222
247
// 用低通滤波器分离出重力加速度
223
248
gravity [0 ] = alpha * gravity [0 ] + (1 - alpha ) * event .values [0 ];
224
249
gravity [1 ] = alpha * gravity [1 ] + (1 - alpha ) * event .values [1 ];
@@ -229,12 +254,12 @@ private void oldCalStep(SensorEvent event){
229
254
230
255
// if (average <= verminValue) {
231
256
if (average <= minValue ) {
232
- Log .v ("xfblog" ,"低" );
257
+ Log .v ("xfblog" , "低" );
233
258
perCalTime = System .currentTimeMillis ();
234
259
}
235
260
// } else if (average >= vermaxValue) {
236
261
else if (average >= maxValue ) {
237
- Log .v ("xfblog" ,"高" );
262
+ Log .v ("xfblog" , "高" );
238
263
float betweentime = System .currentTimeMillis ()
239
264
- perCalTime ;
240
265
if (betweentime >= minTime && betweentime < maxTime ) {
@@ -275,9 +300,128 @@ else if (CountTimeState == 3) {
275
300
}
276
301
277
302
278
-
279
303
}
280
304
}
281
305
// }
282
306
}
307
+
308
+
309
+ /*
310
+ * 检测步子,并开始计步
311
+ * 1.传入sersor中的数据
312
+ * 2.如果检测到了波峰,并且符合时间差以及阈值的条件,则判定为1步
313
+ * 3.符合时间差条件,波峰波谷差值大于initialValue,则将该差值纳入阈值的计算中
314
+ * */
315
+ public void DetectorNewStep (float values ) {
316
+ if (gravityOld == 0 ) {
317
+ gravityOld = values ;
318
+ } else {
319
+ if (DetectorPeak (values , gravityOld )) {
320
+ timeOfLastPeak = timeOfThisPeak ;
321
+ timeOfNow = System .currentTimeMillis ();
322
+ if (timeOfNow - timeOfLastPeak >= 250
323
+ && (peakOfWave - valleyOfWave >= ThreadValue ) && timeOfNow - timeOfLastPeak <= 2000 ) {
324
+ timeOfThisPeak = timeOfNow ;
325
+ /*
326
+ * 更新界面的处理,不涉及到算法
327
+ * 一般在通知更新界面之前,增加下面处理,为了处理无效运动:
328
+ * 1.连续记录10才开始计步
329
+ * 2.例如记录的9步用户停住超过3秒,则前面的记录失效,下次从头开始
330
+ * 3.连续记录了9步用户还在运动,之前的数据才有效
331
+ * */
332
+ StepDcretor .CURRENT_SETP ++;
333
+ if (onSensorChangeListener != null ) {
334
+ onSensorChangeListener .onChange ();
335
+ }
336
+ }
337
+ if (timeOfNow - timeOfLastPeak >= 250
338
+ && (peakOfWave - valleyOfWave >= initialValue )) {
339
+ timeOfThisPeak = timeOfNow ;
340
+ ThreadValue = Peak_Valley_Thread (peakOfWave - valleyOfWave );
341
+ }
342
+ }
343
+ }
344
+ gravityOld = values ;
345
+ }
346
+
347
+ /*
348
+ * 检测波峰
349
+ * 以下四个条件判断为波峰:
350
+ * 1.目前点为下降的趋势:isDirectionUp为false
351
+ * 2.之前的点为上升的趋势:lastStatus为true
352
+ * 3.到波峰为止,持续上升大于等于2次
353
+ * 4.波峰值大于20
354
+ * 记录波谷值
355
+ * 1.观察波形图,可以发现在出现步子的地方,波谷的下一个就是波峰,有比较明显的特征以及差值
356
+ * 2.所以要记录每次的波谷值,为了和下次的波峰做对比
357
+ * */
358
+ public boolean DetectorPeak (float newValue , float oldValue ) {
359
+ lastStatus = isDirectionUp ;
360
+ if (newValue >= oldValue ) {
361
+ isDirectionUp = true ;
362
+ continueUpCount ++;
363
+ } else {
364
+ continueUpFormerCount = continueUpCount ;
365
+ continueUpCount = 0 ;
366
+ isDirectionUp = false ;
367
+ }
368
+
369
+ if (!isDirectionUp && lastStatus
370
+ && (continueUpFormerCount >= 2 || oldValue >= 15 )) {
371
+ peakOfWave = oldValue ;
372
+ return true ;
373
+ } else if (!lastStatus && isDirectionUp ) {
374
+ valleyOfWave = oldValue ;
375
+ return false ;
376
+ } else {
377
+ return false ;
378
+ }
379
+ }
380
+
381
+ /*
382
+ * 阈值的计算
383
+ * 1.通过波峰波谷的差值计算阈值
384
+ * 2.记录4个值,存入tempValue[]数组中
385
+ * 3.在将数组传入函数averageValue中计算阈值
386
+ * */
387
+ public float Peak_Valley_Thread (float value ) {
388
+ float tempThread = ThreadValue ;
389
+ if (tempCount < valueNum ) {
390
+ tempValue [tempCount ] = value ;
391
+ tempCount ++;
392
+ } else {
393
+ tempThread = averageValue (tempValue , valueNum );
394
+ for (int i = 1 ; i < valueNum ; i ++) {
395
+ tempValue [i - 1 ] = tempValue [i ];
396
+ }
397
+ tempValue [valueNum - 1 ] = value ;
398
+ }
399
+ return tempThread ;
400
+
401
+ }
402
+
403
+ /*
404
+ * 梯度化阈值
405
+ * 1.计算数组的均值
406
+ * 2.通过均值将阈值梯度化在一个范围里
407
+ * */
408
+ public float averageValue (float value [], int n ) {
409
+ float ave = 0 ;
410
+ for (int i = 0 ; i < n ; i ++) {
411
+ ave += value [i ];
412
+ }
413
+ ave = ave / valueNum ;
414
+ if (ave >= 8 )
415
+ ave = (float ) 4.3 ;
416
+ else if (ave >= 7 && ave < 8 )
417
+ ave = (float ) 3.3 ;
418
+ else if (ave >= 4 && ave < 7 )
419
+ ave = (float ) 2.3 ;
420
+ else if (ave >= 3 && ave < 4 )
421
+ ave = (float ) 2.0 ;
422
+ else {
423
+ ave = (float ) 1.3 ;
424
+ }
425
+ return ave ;
426
+ }
283
427
}
0 commit comments