前言
在之前我也写过两篇关于计步器的博客,一篇介绍原理,一篇给出封装好的类型。这里是新算法Android工程github地址。
之前的那套算法自己平时玩玩其实还是没问题的,但是在大工程里面运用遇到了一些不得不优化的问题:
- 定时器太耗资源
- 每次计算的时间间隔短(几十毫秒),但计算量大
因此针对这两个问题需要再一次修改算法。新算法相比过去优点在于:
- 大大降低计算量
- 不需要使用计时器,减小系统负担
算法实现的意义
现实原因
对于大部分的开发者来说,自己写一套计步器算法是非常没有必要的,调用系统自带的计步器即可。那么我又为什么要自己动手呢?实际是有几个原因的:
- 自己实现的算法有利于做步长估计
- 鉴于国内Android手机碎片化严重,不同厂商的手机计步表现差异(下面说明)很大,自己实现的算法便于控制差异性
不同厂商的手机计步器主要差异在这几个方面:
- 计步器的敏感度,较敏感的算法会把手部的轻微抖动也算成走步,敏感度低的算法则计步丢失会比较严重
- 计步器每次返回的步数,因为Android手机用的是系统回调的方式而不是查询的方式,因此有的手机是走一步就回调(大部分Android手机),而有的则是走四步回调(苹果手机和少部分Android手机),还有些非固定数值返回的手机就不提了
- 计步器判决人在行走的时间长短,所有系统级算法都会等人走了一定步数后才能确定人确实在行走,然后才开始回调(此时会把之前走的步数一起返回)。大部分手机算法需要等十步左右才开始,华为手机一般要等二三十步
优缺点
自己实现算法的意义就是希望避开上面说的差异性问题,实现算法上的统一。个人认为优点在于:
- 多了步长估计
- 每走一步就提示步态变化
缺点在于:
- 精度略微降低(每百步差一步左右)
- 没有步行的预判时间
算法原理
运动状态判断
判断人的运动状态。简单做,利用滑动窗求方差,方差超过一定门限就判断在运动中。
计步原理
计步算法原理实际上相当简单。我们来看走路时候的波形(加速度数据):
这个是处理过的信号,但是真实信号实际上就是这么简单。我们只要把每个峰值从中抓出来然后加点判决门限就大功告成了。
步长计算原理
这里用到了两个参数H和T,见图:
H对应峰谷值的差值,T对应两个波谷之间的时间差。带入公式得到步长:
l e n g t h = 0.37 − 0.000155 T + 0.1638 H ; length=0.37-0.000155T+0.1638\sqrt{H}; length=0.37−0.000155T+0.1638H;
公式还不是最优的,需要验证改进。
Java实现
public class StepController {
//状态:静止
public static int STAY=0;
//状态:运动
public static int MOVE=1;
//运动状态判断数组
private float[] stateValue=new float[20];
//加速度数组
private float[] Accs=new float[100];
//每次传入加速度的时间,省去定时器
private long[] time=new long[100];
//数组下标
private int count=0;
//行走步数
private int Step=0;
//步长
private float Length=0;
//行进距离
private