加速度传感器

借用别人的图片,以及理解:

线性加速度传感器求速度android 手机线性加速度传感器_线性加速度传感器求速度android


加速度传感器分为 x,y,z;

我们可以借助三轴上的值来确定设备的状态(请参考上面的坐标图),比如:

1、当x轴的值接近重力加速度时,说明设备的左边朝下。

2、当x轴的值接近负的g值时,说明设备的右边朝下。

3、当y轴的值接近g值时,说明设备的下边超下(与上图一样)。

4、当y轴的值接近负的g值时,说明设备的上边朝下(倒置)。

5、当z轴的值接近g值时,说明设备的屏幕朝上。

6、当z轴的值接近负的g值时,说明设备屏幕朝下。

说到加速都传感器,还有一个线性加速都传感器:

线性加速度传感器简称LA-sensor。

线性加速度传感器是加速度传感器减去重力影响获取的数据。

单位是m/s^2,坐标系统与加速度传感器相同。

加速度传感器、重力传感器和线性加速度传感器的计算公式如下:

加速度 = 重力 + 线性加速度

加速度传感器计算步数

大概的想法是取得加速度传感器的矢量和,如果不动,他应该是一个g。
当我们抬脚落脚属于一步,这时候加速度传感器会有一个一个波峰和波谷。我们计算出两者之间的差值,就可以判断是否为一步。
下面是我看到别人写的:

每50ms取一个加速度的采样点作为一个交易日。
如果连续两个交易日保持在均线之上,上涨趋势成立,可能是波峰
如果连续两个交易日保持在均线之下,下跌趋势成立,可能是波谷
波谷之后,才可能有波峰
波峰之后,才可能有波谷
记录到的高底两点,差值大于某个值时更可能是真正行走的一步(剔除轻微抖动)
两步间隔不少于250ms。容忍高达240每分钟的步频。一般人走路步频100上下,跑步180上下。

另外移动平均线取64个采用点的移动平均线。(尽量取多一点,确保不受瞬时影响,尽量取少一点,确保响应跟得上。取了64个点,3秒多,刚好)。

如何判断波峰呢,应该有下面几个条件:
1 当前的点处于下降状态,也就是说比上次记录的数值要低。
2 上一个点是上升状态,只有上升下降只有才可能到达波峰
3 上升的点数为n个,这个次数要具体测试,因为可能是手动的上下移动手机
4 记录波谷的数值,波峰和波谷的值要在一定的范围之内。

检测的一个简单算法,从网上看到的

/*
     * 检测步子,并开始计步
     * 1.传入sersor中的数据
     * 2.如果检测到了波峰,并且符合时间差以及阈值的条件,则判定为1步
     * 3.符合时间差条件,波峰波谷差值大于initialValue,则将该差值纳入阈值的计算中
     * */
    public void detectorNewStep(float values) {
//        需要看一下上次的数值是什么,也就是说判断是上升还是下降
        if (gravityOld == 0) {
            gravityOld = values;
        } else {
//如果是波峰,如果不为0  那么检测是否为波峰
            if (DetectorPeak(values, gravityOld)) {
                /*
                *这个是设置波峰的时间,也就是说把这次波峰的时间设置
                * */
                timeOfLastPeak = timeOfThisPeak;
                timeOfNow = System.currentTimeMillis();
/*
* 如果两次波峰的时间大于200
* 波峰和波谷的差值大于 阈值
* 波峰的时间差小于连两秒
* */
                if (timeOfNow - timeOfLastPeak >= 200
                        && (peakOfWave - valleyOfWave >= ThreadValue) && (timeOfNow - timeOfLastPeak) <= 2000) {
                    timeOfThisPeak = timeOfNow;
                    //更新界面的处理,不涉及到算法
                    preStep();
                }
                if (timeOfNow - timeOfLastPeak >= 200
                        && (peakOfWave - valleyOfWave >= initialValue)) {
                    timeOfThisPeak = timeOfNow;
                    ThreadValue = Peak_Valley_Thread(peakOfWave - valleyOfWave);
                }
            }
        }
        gravityOld = values;
    }

    private void preStep() {
        if (CountTimeState == 0) {
            // 开启计时器
            time = new TimeCount(duration, 700);
            time.start();
            CountTimeState = 1;
            Log.v(TAG, "开启计时器");
        } else if (CountTimeState == 1) {
            TEMP_STEP++;
            Log.v(TAG, "计步中 TEMP_STEP:" + TEMP_STEP);
        } else if (CountTimeState == 2) {
            CURRENT_SETP++;
            if (onSensorChangeListener != null) {
                onSensorChangeListener.onChange();
            }
        }
    }

    /*
     * 检测波峰
     * 以下四个条件判断为波峰:
     * 1.目前点为下降的趋势:isDirectionUp为false
     * 2.之前的点为上升的趋势:lastStatus为true
     * 3.到波峰为止,持续上升大于等于2次
     * 4.波峰值大于1.2g,小于2g
     * 记录波谷值
     * 1.观察波形图,可以发现在出现步子的地方,波谷的下一个就是波峰,有比较明显的特征以及差值
     * 2.所以要记录每次的波谷值,为了和下次的波峰做对比
     * */


    public boolean DetectorPeak(float newValue, float oldValue) {
        lastStatus = isDirectionUp;
        /*
        * 如果新的数值大于旧的,则可以看作是上升、
        * 上升的次数加1
        * */
        if (newValue >= oldValue) {
            isDirectionUp = true;
            continueUpCount++;
        } else {
            /*
            * 持续上升的次数
            * 因为这次是下降,所以我们把上升清零
            * */
            continueUpFormerCount = continueUpCount;
            continueUpCount = 0;
            isDirectionUp = false;
        }

        Log.v(TAG, "oldValue:" + oldValue);
        if (!isDirectionUp && lastStatus
                && (continueUpFormerCount >= 2 && (oldValue >= minValue && oldValue < maxValue))) {
//            检测到波峰,则设置波峰的值
            peakOfWave = oldValue;
            return true;
//            上一点的位置
            /*
            * 上一个点的状态是下降   并且当前点为上升  则认为是i波谷
            * */
        } else if (!lastStatus && isDirectionUp) {
            valleyOfWave = oldValue;
            return false;
        } else {
            return false;
        }
    }