私はアプリケーションを作成しています。私の目的は、ユーザーが歩いていることを検出することです。私は次のようなカルマンフィルターを使用しています:
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で初期化されます。
ユーザーが歩いているかどうかは(加速度ベクトルの大きさの値を見て)検出できますが、問題は、ユーザーが歩いていないときに電話を動かすと、歩いているように見えることです。
適切なフィルターを使用していますか?
ベクトルの大きさだけを見るのは正しいですか、それとも単一の値を見る必要がありますか?
Googleは、DetectedActivity
を使用して取得できるActivityRecognitionApi
と呼ばれるこのAPIを提供しています。これらのドキュメントには、 ここ および ここ にアクセスできます。
DetectedActivity
にはユーザーの現在のアクティビティを取得するためのメソッドpublic int getType()
と、0〜100の値を返すpublic int getConfidence()
があります。getConfidence()
の場合、APIは、ユーザーが返されたアクティビティを実行していることをより確実にします。
getType()
によって返されるものの一定の要約は次のとおりです。
私の最初の直感は、センサーの履歴に対してFFT分析を実行し、歩行時にどの周波数の大きさが大きいかを確認することです。
これは基本的に、歩行が「どのように聞こえる」かを確認し、加速度センサーの入力をマイクのように扱い、歩行時に大きな周波数(つまり、発生する最大の加速度はどの周波数であるか)を確認することです。
私はあなたがいくつかの低周波数(足音率のような)または多分何か他のもので高いマグニチュードを探していると思います。データを見るのは面白いでしょう。
私の推測では、FFTを実行して、ある周波数での大きさが特定のしきい値よりも大きいか、2つの周波数の大きさの差がある程度以上であるかを探します。繰り返しますが、実際のデータによって、それを検出する方法が決まります。
歩行検出には、加速度計からの平滑化された信号に適用される導関数を使用します。導関数がしきい値よりも大きい場合、それはステップであったと示唆できます。しかし、それはベストプラクティスではないと思います。さらに、電話がズボンのポケットに入れられている場合にのみ機能します。
このアプリでは次のコードが使用されました 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つの振動が理にかなった範囲内で並んでいる限り、これも当てはまる限り、歩行が発生していると結論付けます。-
水平加速度を測定し、それを使用して速度値を更新します。速度は時間とともにドリフトしますが、ステップの時間にわたって速度の移動平均を滑らかに保つ必要があります。3回の振動あたりの歩行速度の半分を超えてドリフトしない限り、歩行しますが、それが最初は短時間、つまり0.5秒または2回の振動で歩行速度に上昇しました。
それはすべてそれをカバーするはずです。もちろん、これらすべてをNNへの入力と見なすと、少しaiを使用すると、物事が単純または同じように複雑になりますが、驚くほど正確になります。つまり、前処理。
編集:通常歩いているときの平均加速度は0に近いので、十分に正確ではないと思います。加速度を測定するためにできることのほとんどは、誰かが歩き始めたときまたは停止したときを検出することです(しかし、あなたが言ったように、それをフィルタリングするのは難しいですある場所に立っている人がデバイスを動かした)
だから...私が以前に書いたことは、おそらくとにかく機能しないでしょう:
ユーザーが移動していないときに破棄することで、ユーザーが移動しているかどうかを「予測」できます(明らか)。最初の2つのオプションは次のとおりです。
近接センサーと光センサー(オプション)を使用して、電話が「非表示」になっているかどうかを確認します。この方法は精度は低くなりますが、簡単です。
動きの連続性を制御します。電話が10秒以上動いていて、動きが卑劣でない場合は、彼が歩いていると見なします。私もパフォーマンスではないことを知っていますが、ところで、どんな種類のポジショニングを使用しないかは難しいです...なぜあなたはLocationManager
?を使用しませんか?