跑步-计步器实现(二)

247 阅读3分钟

在上面的例子[跑步-计步器实现(一)] 中,我们看到某跑步app通过加速传感器onSensorChanged 参数进行了处理,并结合实际时间,判断用户是否在运动,那具体的运动算法思路呢,我们今天就来讲一讲。

一、StepDetector 1.1、算法的主体,用于检测“步点”。 实现 SensorEventListener 接口,对传感器进行注册: this.mSensorManager = ((SensorManager)getSystemService(Context.SENSOR_SERVICE)); this.mSensor = this.mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); this.mSensorManager.registerListener(this.mStepDetector, this.mSensor, SensorManager.SENSOR_DELAY_UI); 注册后传感器就会上报三轴的原始数据,即 SensorEvent 中的三个数值, float[] fArr = sensorEvent.values;

    float f2 = fArr[0] / 9.78049f;

    float f3 = fArr[1] / 9.78049f;

    float f4 = fArr[2] / 9.78049f;

1.2 误差 用于数“步子”,连续的 10 步才是会生效,两个步点之间的时间差超过 3 秒,之 前的计数清空。

1.3 RunService

用于计步的后台服务,服务要采用灰色保活的方法保证存活率。

1.4 几个接口 StepCountListener:将数步子的方法抽象到接口里 StepValuePassListener:有效步数改变时,调用的方法抽象到接口里 UpdateUiCallBack:更新 UI 的方法抽象到接口里

二、跑步场景 人在走路时大致分为下面几种场景:

1、正常走路,手机拿在手上(边走边看、甩手、不甩手) 2、慢步走,手机拿在手上(边走边看、甩手、不甩手) 3、快步走,手机拿在手上(甩手、不甩手、走的很快一般不会看手机吧) 4、手机放在裤袋里(慢走、快走、正常走) 5、手机放在上衣口袋里(慢走、快走、正常走) 6、上下楼梯(上面五中场景可以在这个场景中再次适用一遍)

所有场景的原始数据通过分析,其实是正弦波,每一个波峰为一个步点,算法其 实就是找到这些步点,分析波形特点寻找特征值,找到如下三个原则: a、规定曲线连续上升的次数 b、波峰波谷的差值需要大于阈值 c、阈值是动态改变的 在 StepDetector 的 onSensorChanged 会一直产生原始数据,经过一定变换后传入 detectorNewStep 中,会判断值是否是波峰值,具体流程图如下:

image.png

关于参数以及调节 1.检测波峰 在检测到是波峰时,波峰和相邻前一个波谷差值大于 ThreadValue(过滤掉抖动 的情况,时间差很小),并且时间差为 TimeInterval 以上,则认为是有效步点 同时,阈值大于 InitialValue 以上的情况,都会被纳入动态计算 ThreadValue 值。

2.有效值 规定连续上升两次,并且波峰值大于 20 才认为是一个有效波峰(目的也是过滤 掉波形上的抖动)

3.在 peakValleyThread averageValue 中 滚动记录四个有效波峰波谷差值并计算平均值,再梯度化。合适的 ThreadValue 会过滤抖动,且识别步点。

4.关于参数调节 ThreadValue InitialValue TimeInterval 已经比较成熟,可以不做修改。 averageValue 中的梯度化的一些具体参数,对于部分特殊场景,例如跑步,上下 楼梯等,应该还有提高的空间。

5.参数调节的方法: a.尽可能多的采集各种场景的原始数据(gsensor-debug),分析波形(excel 即可) b.调整梯度化的参数 c.通过实测,验证计步的准确率 d.重复 b,c 的过程知道准确度提高