如何使用Android加速度计检测行走

时间:2011-02-14 15:32:41

标签: android filter accelerometer kalman-filter

我正在编写一个应用程序,我的目标是检测用户何时行走。 我正在使用这样的卡尔曼滤波器:

float kFilteringFactor=0.6f;

        gravity[0] = (accelerometer_values[0] * kFilteringFactor) + (gravity[0] * (1.0f - kFilteringFactor));
        gravity[1] = (accelerometer_values[1] * kFilteringFactor) + (gravity[1] * (1.0f - kFilteringFactor));
        gravity[2] = (accelerometer_values[2] * kFilteringFactor) + (gravity[2] * (1.0f - kFilteringFactor));

        linear_acceleration[0] = (accelerometer_values[0] - gravity[0]);
        linear_acceleration[1] = (accelerometer_values[1] - gravity[1]);
        linear_acceleration[2] = (accelerometer_values[2] - gravity[2]);

        float magnitude = 0.0f;
        magnitude = (float)Math.sqrt(linear_acceleration[0]*linear_acceleration[0]+linear_acceleration[1]*linear_acceleration[1]+linear_acceleration[2]*linear_acceleration[2]);
        magnitude = Math.abs(magnitude);
if(magnitude>0.2)
  //walking

数组gravity []初始化为0。

我可以检测到用户何时走路(看加速度矢量幅度的值),但我的问题是,当用户不走路并且他移动手机时,似乎他走路了

我使用的是正确的过滤器吗?

仅观察矢量的大小是否正确,还是让我看一下单值?

5 个答案:

答案 0 :(得分:20)

Google为此DetectedActivity提供了一个API,可以使用ActivityRecognitionApi获取。可以访问这些文档herehere

DetectedActivity使用方法public int getType()来获取用户的当前活动,并使用public int getConfidence()返回0到100之间的值。{{1}返回的值越高},用户执行返回活动的API越确定。

以下是getConfidence()

返回内容的常量摘要
  • int IN_VEHICLE设备位于车辆中,例如汽车。
  • int ON_BICYCLE设备在自行车上。
  • int ON_FOOT设备位于正在行走或正在跑步的用户上。
  • int RUNNING设备位于正在运行的用户上。
  • int STILL设备仍在(不移动)。
  • int TILTING相对于重力的设备角度发生了显着变化。
  • int UNKNOWN无法检测当前活动。
  • int WALKING设备位于正在行走的用户身上。

答案 1 :(得分:5)

我的第一个直觉是对传感器历史进行FFT分析,看看哪些频率在行走时有很高的幅度。

基本上看到行走的“听起来像”,将加速计传感器输入视为麦克风,并观察行走时响亮的频率(换句话说,发生最大加速度的频率)。

我猜你会在一些低频率(如足迹率)或其他东西上寻找高强度。看到这些数据会很有趣。

我的猜测是你运行FFT并查找某个频率的幅度大于某个阈值,或者两个频率的幅度之差大于某个数量。同样,实际数据将决定您如何检测它。

答案 2 :(得分:4)

对于步行检测,我使用应用于加速度计的平滑信号的导数。当导数大于阈值时,我可以建议它是一个步骤。但我想这不是最好的做法,而且只有当手机放在裤子口袋里时它才有效。

此应用中使用了以下代码https://play.google.com/store/apps/details?id=com.tartakynov.robotnoise

    @Override
    public void onSensorChanged(SensorEvent event) {
        if (event.sensor.getType() != Sensor.TYPE_ACCELEROMETER){
            return;
        }
        final float z = smooth(event.values[2]); // scalar kalman filter                               
        if (Math.abs(z - mLastZ) > LEG_THRSHOLD_AMPLITUDE)
        {
            mInactivityCount = 0;
            int currentActivity = (z > mLastZ) ? LEG_MOVEMENT_FORWARD : LEG_MOVEMENT_BACKWARD;                  
            if (currentActivity != mLastActivity){
                mLastActivity = currentActivity;
                notifyListeners(currentActivity);
            }                   
        } else {
            if (mInactivityCount > LEG_THRSHOLD_INACTIVITY) {
                if (mLastActivity != LEG_MOVEMENT_NONE){
                    mLastActivity = LEG_MOVEMENT_NONE;
                    notifyListeners(LEG_MOVEMENT_NONE);                                 
                }
            } else {
                mInactivityCount++;
            }
        }
        mLastZ = z;
    }

答案 3 :(得分:0)

编辑:我不认为它足够准确,因为当正常行走时,平均加速度将接近0.测量加速度的最大值是检测到有人开始行走或停止时(但正如你所说,过滤很困难)它是由站在一个地方的人移动的设备)

所以...我之前写的内容,可能无论如何都不会起作用:

你可以“预测”用户是否在移动用户不移动时移动(显而易见),我想到的前两个选项是:
使用接近和光线传感器(可选)检查手机是否“隐藏”。这种方法不太准确,但更容易 控制机芯的连续性,如果手机移动超过10秒并且机芯不可鄙视,那么你认为他正在行走。我知道也不是穿孔,但是很难使用任何类型的定位,顺便说一下......为什么不使用LocationManager

答案 4 :(得分:0)

尝试检测上下振动,前后振动以及每个振动的频率,并确保它们平均保持在边界内,因为您会检测到步行,尤其是该人的步态,这对于多个步态应保持相对恒定立刻采取行动以符合资格。 只要最后3个振荡在合理范围内排列,只要结论也是如此,就可以得出结论:正在行走:-

您可以测量水平加速度并用其更新速度值。速度会随着时间而漂移,但是您需要在一步的时间内保持平稳的移动平均速度,只要它的漂移不超过每3次振荡的一半步行速度,就可以行走,但前提是最初在短时间内上升到步行速度,也许是半秒或2次振荡。
所有这些都应该涵盖它。 当然,如果您将所有这些都考虑作为NN的输入,那么一点点AI就能使事情变得简单或复杂,但出奇的准确。即预处理。