Android基于G-Sensor的计步算法

一、写在分享之前
写在前面,最近项目需求研究计步功能,借鉴了一下别人的算法写了一个小例子,本文最后有源码地址。算法的准确度大概可以达到95.7%,综合起来觉得是比春雨略好,但是赢不了乐动力(可以达到97.7%),希望大家提一些意见,让这个算法可以得到改进。

二、计步器算法的总体思路以及辅助调试的工具
人在走路时大致分为下面几种场景:
1、正常走路,手机拿在手上(边走边看、甩手、不甩手)
2、慢步走,手机拿在手上(边走边看、甩手、不甩手)
3、快步走,手机拿在手上(甩手、不甩手、走的很快一般不会看手机吧)
4、手机放在裤袋里(慢走、快走、正常走)
5、手机放在上衣口袋里(慢走、快走、正常走)
6、上下楼梯(上面五中场景可以在这个场景中再次适用一遍)
以上,不管出于哪一种场景(其实对应手机不同的运动规律),g-sensor的三轴数据都是有规律可以寻找的。
每一步都有特征点,找到这个特征点,就是识别出来一步。
下面推荐一个工具,叫gsensor-debug,可以观察三轴的曲线,下面是手机上下摆动的曲线
这里写图片描述
这是很规律曲线只要检测波峰就行了,实际的走路曲线会有很多杂波,算法的作用就是滤除这些杂波(走路的波形可以用工具自己看,可以保存为文件,用excel打开有数据,将数据转换为波形就可以自己看)

三、算法的介绍(贴出核心代码)
1、变量的定义

//存放三轴数据
float[] oriValues = new float[3];
final int valueNum = 4;
//用于存放计算阈值的波峰波谷差值
float[] tempValue = new float[valueNum];
int tempCount = 0;
//是否上升的标志位
boolean isDirectionUp = false;
//持续上升次数
int continueUpCount = 0;
//上一点的持续上升的次数,为了记录波峰的上升次数
int continueUpFormerCount = 0;
//上一点的状态,上升还是下降
boolean lastStatus = false;
//波峰值
float peakOfWave = 0;
//波谷值
float valleyOfWave = 0;
//此次波峰的时间
long timeOfThisPeak = 0;
//上次波峰的时间
long timeOfLastPeak = 0;
//当前的时间
long timeOfNow = 0;
//当前传感器的值
float gravityNew = 0;
//上次传感器的值
float gravityOld = 0;
//动态阈值需要动态的数据,这个值用于这些动态数据的阈值
final float initialValue = (float) 1.3;
//初始阈值
float ThreadValue = (float) 2.0;
private StepListener mStepListeners;
  1. 代码,结合注释看
    检测步子就是检测波峰,但是要滤除无效的波峰,主要采用了如下三种措施

a、规定曲线连续上升的次数

b、波峰波谷的差值需要大于阈值

c、阈值是动态改变的

另一个是一些参数的初始值,比如initialValue 以及ThreadValue 的初始值,以及averageValue函数的梯度化范围值

需要结合各种场景的波形图来统计,还有几十实际的测试来调试参数,这些参数大概前后调了两个星期,其实总体思路不复杂。

下面贴出核心代码以及一些注释:

/*
     * 注册了G-Sensor后一只会调用这个函数
     * 对三轴数据进行平方和开根号的处理
     * 调用DetectorNewStep检测步子
     * */
    @Override
    public void onSensorChanged(SensorEvent event) {
        for (int i = 0; i < 3; i++) {
            oriValues[i] = event.values[i];
        }
        gravityNew = (float) Math.sqrt(oriValues[0] * oriValues[0]
                + oriValues[1] * oriValues[1] + oriValues[2] * oriValues[2]);
        DetectorNewStep(gravityNew);
    }

    /*
     * 检测步子,并开始计步
     * 1.传入sersor中的数据
     * 2.如果检测到了波峰,并且符合时间差以及阈值的条件,则判定为1步
     * 3.符合时间差条件,波峰波谷差值大于initialValue,则将该差值纳入阈值的计算中
     * */
    public void DetectorNewStep(float values) {
        if (gravityOld == 0) {
            gravityOld = values;
        } else {
            if (DetectorPeak(values, gravityOld)) {
                timeOfLastPeak = timeOfThisPeak;
                timeOfNow = System.currentTimeMillis();
                if (timeOfNow - timeOfLastPeak >= 250
                        && (peakOfWave - valleyOfWave >= ThreadValue)) {
                    timeOfThisPeak = timeOfNow;
                    /*
                     * 更新界面的处理,不涉及到算法
                     * 一般在通知更新界面之前,增加下面处理,为了处理无效运动:
                     * 1.连续记录10才开始计步
                     * 2.例如记录的9步用户停住超过3秒,则前面的记录失效,下次从头开始
                     * 3.连续记录了9步用户还在运动,之前的数据才有效
                     * */
                    mStepListeners.onStep();
                }
                if (timeOfNow - timeOfLastPeak >= 250
                        && (peakOfWave - valleyOfWave >= initialValue)) {
                    timeOfThisPeak = timeOfNow;
                    ThreadValue = Peak_Valley_Thread(peakOfWave - valleyOfWave);
                }
            }
        }
        gravityOld = values;
    }

    /*
     * 检测波峰
     * 以下四个条件判断为波峰:
     * 1.目前点为下降的趋势:isDirectionUp为false
     * 2.之前的点为上升的趋势:lastStatus为true
     * 3.到波峰为止,持续上升大于等于2次
     * 4.波峰值大于20
     * 记录波谷值
     * 1.观察波形图,可以发现在出现步子的地方,波谷的下一个就是波峰,有比较明显的特征以及差值
     * 2.所以要记录每次的波谷值,为了和下次的波峰做对比
     * */
    public boolean DetectorPeak(float newValue, float oldValue) {
        lastStatus = isDirectionUp;
        if (newValue >= oldValue) {
            isDirectionUp = true;
            continueUpCount++;
        } else {
            continueUpFormerCount = continueUpCount;
            continueUpCount = 0;
            isDirectionUp = false;
        }

        if (!isDirectionUp && lastStatus
                && (continueUpFormerCount >= 2 || oldValue >= 20)) {
            peakOfWave = oldValue;
            return true;
        } else if (!lastStatus && isDirectionUp) {
            valleyOfWave = oldValue;
            return false;
        } else {
            return false;
        }
    }

    /*
     * 阈值的计算
     * 1.通过波峰波谷的差值计算阈值
     * 2.记录4个值,存入tempValue[]数组中
     * 3.在将数组传入函数averageValue中计算阈值
     * */
    public float Peak_Valley_Thread(float value) {
        float tempThread = ThreadValue;
        if (tempCount < valueNum) {
            tempValue[tempCount] = value;
            tempCount++;
        } else {
            tempThread = averageValue(tempValue, valueNum);
            for (int i = 1; i < valueNum; i++) {
                tempValue[i - 1] = tempValue[i];
            }
            tempValue[valueNum - 1] = value;
        }
        return tempThread;

    }

    /*
     * 梯度化阈值
     * 1.计算数组的均值
     * 2.通过均值将阈值梯度化在一个范围里
     * */
    public float averageValue(float value[], int n) {
        float ave = 0;
        for (int i = 0; i < n; i++) {
            ave += value[i];
        }
        ave = ave / valueNum;
        if (ave >= 8)
            ave = (float) 4.3;
        else if (ave >= 7 && ave < 8)
            ave = (float) 3.3;
        else if (ave >= 4 && ave < 7)
            ave = (float) 2.3;
        else if (ave >= 3 && ave < 4)
            ave = (float) 2.0;
        else {
            ave = (float) 1.3;
        }
        return ave;
    }

最后,附上我的项目地址:项目源码

  • 7
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
### 回答1: gsensor计步算法是一种通过使用手机或其他设备上的G-sensor(重力感应器)来计算用户走的步数的算法G-sensor是一种能够感知和测量物体加速度和重力加速度的传感器。 gsensor计步算法的原理是利用人体行走时身体的摆动来检测步伐。当用户走路时,身体会不断摆动,不同的步子会产生不同的摆动幅度和频率。通过监测G-sensor的变化,算法可以检测到这些摆动,并根据一定的规则和参数进行步数的计算。 计步算法中往往要解决的问题是如何准确地区分和计算摆动和其他因素引起的G-sensor变化。例如,手机摇晃或震动、跳跃等行为都可能产生类似于行走时的G-sensor变化,这些都需要被过滤掉。算法通常采用了一系列的过滤和判断策略,例如设置摆动幅度和时间周期的阈值,以及结合其他传感器数据进行校准和确认。 gsensor计步算法的准确性取决于算法的设计和实现、传感器的精度和噪声等因素。通常情况下,算法能够在正常行走情况下比较准确地计算步数,但在一些特殊情况下,如慢走、人数较多的拥挤场所或者在不平坦的地面上行走时,可能会出现误差。 总之,gsensor计步算法是一种利用移动设备上的G-sensor来计算步数的算法。它通过检测行走时身体的摆动来进行计算,并采用了一些过滤和判断策略来提高准确性。算法的准确性受到多种因素的影响,但通常情况下能够较为准确地计算步数。 ### 回答2: gsensor计步算法是一种利用手机或其他设备内置的加速度传感器(即gsensor)来统计用户步数的方法。gsensor计步算法的基本原理是通过检测设备在三维空间内的运动状态,来识别步行动作,从而实现步数的统计。 具体而言,gsensor计步算法基于人体步行过程中的动作特征,如摆动、落地和着地等。它通过监测设备在水平方向的加速度变化来捕捉用户的行走状态。当设备检测到持续的连续变化和震动,很可能是用户正在步行,而不是其他运动或抖动。算法还会剔除一些噪音信号,如突然的加速、设备旋转等,以确保计步的准确性。 在gsensor计步算法中,通过设定合适的阈值和规则来判断何时开始计步以及计为一步。例如,当加速度传感器检测到一次步行动作的振幅超过一定的阈值时,就会记录为一步。同时,算法也会考虑到步行的频率和步长等因素,以提高计步的准确性。 然而,gsensor计步算法也存在一些局限性。例如,它不能区分走楼梯、跳跃或其他运动模式,仅适用于步行计步。另外,由于设备的位置、使用方式等因素的差异,算法的准确性可能会有所下降。 总的来说,gsensor计步算法是一种通过使用加速度传感器来统计步数的方法。它可以帮助人们记录和分析日常步行活动,从而提供一些健康和运动的参考信息。然而,使用者在应用中还应考虑其他因素,如准确性、精度和个人习惯等。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值