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

20

我正在编写一个应用程序,我的目标是检测用户何时在走路。 我使用类似于以下方式的卡尔曼滤波器:

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。

我可以检测用户是否在行走(查看加速度向量的大小值),但我的问题是,当用户没有在行走时移动手机时,似乎他正在行走。

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

只关注向量的大小值是正确的吗,还是我需要查看单个数值?


你是在考虑向前运动的加速度,还是只是“上下”的运动? - gnclmorais
用户是握着手机在走路,还是把它放在口袋里走路? - jcwenger
用户双手握着手机 - havanakoda
我鼓励用户查看我的答案,该答案概述了谷歌提供的API,用于检测各种不同的活动。 - Dick Lucas
QQ:accelerometer_values[0] 表示 x 轴;accelerometer_values[1] 表示 y 轴,而 accelerometer_values[2] 表示 z 轴。 - Dev.K.
显示剩余2条评论
5个回答

24

谷歌提供了一个称为DetectedActivity的API,可以使用ActivityRecognitionApi获得。这些文档可以在这里这里访问。

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完成类似的事情吗? - SeriousLee
@PrintlnParams 不可以。这些API仅适用于Android,而Google目前并没有为Android开发JavaScript API。 - Dick Lucas

5

我的第一反应是对传感器历史记录进行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;
    }

2
不要仅仅使用Z轴的加速度,你应该使用向量长度:Math.sqrt(pow(x,2) + pow(y,2) + (z,2)) - 9.8。这样你将得到所有三个方向的合加速度,并且不会受到设备在空间中位置/旋转的影响。 - Nikolay Tsenkov
1
你能添加平滑函数的源代码吗? - Guy Fawkes
2
https://github.com/tartakynov/robowalk/blob/master/src/com/tartakynov/robotnoise/leg/LegMovementDetector.java - tartakynov

0

编辑:我认为这并不准确,因为正常行走时平均加速度接近于0。你能做的最多只是通过测量加速度来检测某人何时开始行走或停止(但正如你所说,很难从设备移动的人中过滤出来)。

所以...我之前写的可能也行不通:

你可以通过丢弃用户不移动时的数据(显而易见),“预测”用户是否在移动。我脑海中首先想到的两个选项是:
使用接近传感器和光传感器检查手机是否“隐藏”。这种方法不太准确,但更容易实现。
控制运动的连续性,如果手机移动超过... 10秒,并且运动不可忽略,则认为他正在行走。我知道这也不完美,但如果不使用任何定位方式,这很困难...顺便问一下,为什么不直接使用LocationManager呢?


我不能使用LocationManager,因为我想在用户不行走时停止获取位置更新。用户将使用我的游戏/应用程序观看手机。但是使用加速度计来检测步行是否正确? - havanakoda
@havanakoda,现在我仔细考虑了一下,它的准确性实际上很低,因为当你走路时,你几乎没有加速度,所以加速计会得到非常低的数值。我不知道是否值得尝试。 - mdelolmo
2
人类上下晃动,脚步冲击的震动穿过你的身体。即使手机被人握在手中减震,如果你无法从中得到一个相当可识别的信号,我会感到惊讶。 - doug65536
@doug65536所说的没错。如果你重新启动加速度计电路,它会检测到速度增加,而不是一直保持开启状态,因为它必须重新测量你当前的向量并假设先前的向量为零。 - nurettin

0
尝试检测上下振荡、前后振荡及其频率,并确保它们在平均范围内保持对齐,因为您将会检测到行走,特别是那个人的步态风格,这应该在连续几步中保持相对恒定以合格为行走状态。 只要最后3个振荡在合理范围内对齐,那么只要满足以下条件就可以得出正在行走:-

您测量水平加速度并用其更新速度值。速度会随着时间漂移,但是您需要保持平均移动速度在一步的时间内平滑,并且只要它不超过每三个振荡半个行走速度,那么就是行走,但前提是它最初在短时间内即半秒或2个振荡内增加到行走速度。
所有这些都应该差不多解决了。 当然,一点人工智能会使事情变得更简单,或者如果您将所有这些视为神经网络的输入,则同样复杂但令人惊讶地准确。即预处理。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接