如何使用Android加速计检测步行
我正在编写一个应用程序,我的目标是检测用户何时行走。 我使用的是这样的卡尔曼滤波器:如何使用Android加速计检测步行,android,filter,accelerometer,kalman-filter,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) +
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
数组重力[]初始化为0
我可以检测用户是否在行走(查看加速度向量的大小),但我的问题是,当用户不在行走并且移动手机时,他似乎在行走
我是否使用了正确的过滤器
仅仅观察向量的大小是正确的还是让我看单个值?编辑:我认为它不够精确,因为正常行走时平均加速度接近0。你能做的最多的测量加速度的方法就是检测某人何时开始行走或停止(但正如你所说的,很难从站在一个地方的人移动的设备中过滤出来) 所以。。。我之前写的东西可能无论如何都不管用: 当用户不移动时,您可以通过丢弃来“预测”用户是否正在移动(很明显),我想到的前两个选项是:
使用接近和光线传感器(可选)检查手机是否“隐藏”。这种方法精度较低,但更简单。
控制移动的连续性,如果手机移动超过。。。10秒的动作并不是卑鄙的,那么你认为他在走路。我知道这也不太好,但是如果不使用任何一种定位的话,顺便说一句。。。为什么不直接使用
LocationManager
?对于行走检测,我使用应用于加速计平滑信号的导数。当导数大于阈值时,我可以认为这是一个步骤。但我想这不是最好的做法,而且只有当手机放在裤子口袋里时,它才起作用
此应用程序中使用了以下代码
我的第一个直觉是对传感器历史进行FFT分析,看看哪些频率在行走时具有较高的量级 它本质上是观察行走“听起来像什么”,将加速度计传感器的输入像麦克风一样对待,并观察行走时的响亮频率(换句话说,最大加速度发生的频率是多少) 我猜你会在某个低频率下寻找一个高震级(比如脚步速度)或者其他东西。看到这些数据会很有趣
我的猜测是你运行FFT,寻找某个频率的幅值大于某个阈值,或者两个频率的幅值之差大于某个数值。同样,实际数据将决定您尝试检测它的方式。谷歌为这个名为
DetectedActivity
的API提供了一个API,可以使用ActivityRecognitionApi
获取该API。这些文档可以访问和保存
DetectedActivity
具有获取用户当前活动的方法public int getType()
,以及返回0到100之间的值的方法public int getConfidence()
。getConfidence()
返回的值越高,API越确定用户正在执行返回的活动
下面是由getType()
返回的内容的持续摘要:
- int IN_VEHICLE该设备位于车辆内,如汽车
- int ON_BICYCLE该设备位于自行车上
- int ON_FOOT该设备位于正在行走或跑步的用户身上
- int运行设备的用户正在运行
- int静止设备静止(不移动)
- int倾斜装置相对于重力的角度发生显著变化
- int UNKNOWN无法检测当前活动
- int WALKING设备位于正在行走的用户身上
所有这些都应该足以涵盖它。
当然,一点人工智能将有助于使事情变得更简单或同样复杂,但如果您将所有这些都视为神经网络的输入,则会令人惊讶地精确。Ie预处理 你是在考虑向前移动的加速度,还是只考虑“上下移动”?我在考虑手机的上下移动和旋转。当使用者不走路时,允许他做这种运动;但我不希望这些被检测为行走。用户是手持手机行走,还是将手机放在口袋中行走?用户是手持手机行走?您可以尝试使用摄像头来检测移动而不是加速计,正如你所说的,用户在使用你的应用程序/游戏时应将手机握在手中!我无法使用LocationManager,因为我想在用户不行走时停止获取位置更新。用户将使用我的游戏/应用程序查看手机。但使用加速度计检测行走是否正确?@havanakoda,现在我深入思考,它的准确度真的很低,因为当你行走时,你几乎没有加速,所以加速度计的值会很低。我不知道这是否值得一试。人类上下摆动,脚步声的冲击会射出thr
@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;
}