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

Posted

技术标签:

【中文标题】如何使用 Android 加速度计检测步行【英文标题】:How to detect walking with Android accelerometer 【发布时间】:2011-06-27 00:16:12 【问题描述】:

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

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。

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

我是否使用了正确的过滤器?

只看向量的大小是正确的还是让我看单个值??

【问题讨论】:

您是在考虑向前移动的加速度,还是只是“上下”? 我正在考虑上下和旋转手机。当用户不走路时,他可以做这些动作;但我不希望这些被检测为行走。 用户是拿着手机走路,还是放在口袋里走路? 用户手里拿着手机 您可以尝试使用相机来代替加速度计来检测运动吗,正如您所说的,用户在使用您的应用/游戏时应将手机握在手中! 【参考方案1】:

尝试检测上下摆动、前后摆动以及每种摆动的频率,并确保它们在平均范围内保持对齐,因为您会检测到步行,特别是该人的步态风格,该步态风格应在数次内保持相对恒定立即采取步骤,以符合移动的条件。 只要最后 3 次振荡在合理范围内排列,那么只要这也是正确的,就可以得出结论:-

您测量水平加速度并用它更新速度值。速度会随时间漂移,但你需要保持一个移动平均速度在一个步骤的时间内平滑,只要它的漂移不超过每 3 次振荡行走速度的一半,那么它就是行走,但前提是它最初在很短的时间内上升到步行速度,即半秒或 2 次振荡。 所有这些都应该涵盖它。 当然,如果您将所有这些都视为 NN 的输入,那么一点点 AI 将有助于使事情变得更简单或同样复杂但惊人的准确。即预处理。

【讨论】:

【参考方案2】:

Google 为此提供了一个名为 DetectedActivity 的 API,可以使用 ActivityRecognitionApi 获取该 API。可以通过here 和here 访问这些文档。

DetectedActivity 有方法public int getType() 来获取用户的当前活动,还有public int getConfidence(),它返回一个从0 到100 的值。getConfidence() 返回的值越高,API 越确定用户正在执行返回的活动。

这是getType()返回的内容的不断总结:

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

【讨论】:

太棒了!你知道是否有一个谷歌 API 可以让你通过 javascript 做或多或少相同的事情? @PrintlnParams 否。这些 API 仅适用于 android,Google 目前不为 Android 开发 javascript API。【参考方案3】:

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

它本质上是查看行走的“声音”,将加速度计传感器输入视为麦克风,并查看行走时响亮的频率(换句话说,最大加速度发生的频率)。

我猜你会在某个低频(如脚步率)或其他东西上寻找高幅度。看看数据会很有趣。

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

【讨论】:

【参考方案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;
    

【讨论】:

您可能应该使用向量长度,而不是仅使用 Z 加速度:Math.sqrt(pow(x,2) + pow(y,2) + (z,2)) - 9.8 .这样,您将获得所有 3 个方向的总加速度,并且不会依赖于设备在空间中的位置/旋转。 能添加平滑函数的源码吗? github.com/tartakynov/robowalk/blob/master/src/com/tartakynov/…【参考方案5】:

编辑:我认为它不够准确,因为当正常行走时,平均加速度将接近 0。测量加速度最多可以检测某人何时开始行走或停止(但正如您所说,很难过滤它来自站在一个地方的人移动的设备)

所以...我之前写的,可能无论如何都行不通:

您可以通过在用户不移动时丢弃来“预测”用户是否在移动(很明显),我想到的前两个选项是: 使用接近和光传感器(可选)检查手机是否“隐藏”。这种方法不太准确,但更容易。 控制动作的连续性,如果手机在移动超过... 10秒并且动作不卑鄙,那么你认为他在走路。我知道也不完美,但是不使用任何定位都很难,顺便说一句……你为什么不直接使用LocationManager

【讨论】:

我无法使用 LocationManager,因为我想在用户不走路时停止获取位置更新。用户将使用我的游戏/应用程序查看手机。但是使用加速度计检测步行是否正确? @havanakoda ,现在我深思熟虑,它的准确度真的很低,因为当你走路时,你几乎没有加速,所以加速度计会得到相当低的值。不知道是否值得一试。 人类上下摆动,脚步冲击的冲击力穿过你的身体。即使手机因拿在手中而受潮,如果您没有从中获得可合理识别的信号,我也会感到惊讶。 @doug65536 所说的。而且,如果您重新启动加速度计电路,它会检测到速度增加,而不是一直保持开启,因为它必须重新测量您当前的矢量并假设之前的矢量为零。

以上是关于如何使用 Android 加速度计检测步行的主要内容,如果未能解决你的问题,请参考以下文章

使用加速度计和机器学习的运动类型检测

利用三轴加速器的计步测算方法

Android 检测运动

检测加速度计震动android

如何使用 Android 中的加速度计测量手机在 XY 平面上的倾斜度

双足步行机器人的ZMP与CoP检测