algorithm を使用してRuntastic Pedometerなどのアプリケーションを開発していますが、結果に類似性はありません。
私のコードは次のとおりです:
public void onSensorChanged(SensorEvent event)
{
Sensor sensor = event.sensor;
synchronized (this)
{
if (sensor.getType() == Sensor.TYPE_ORIENTATION) {}
else {
int j = (sensor.getType() == Sensor.TYPE_ACCELEROMETER) ? 1 : 0;
if (j == 1) {
float vSum = 0;
for (int i=0 ; i<3 ; i++) {
final float v = mYOffset + event.values[i] * mScale[j];
vSum += v;
}
int k = 0;
float v = vSum / 3;
//Log.e("data", "data"+v);
float direction = (v > mLastValues[k] ? 1 : (v < mLastValues[k] ? -1 : 0));
if (direction == - mLastDirections[k]) {
// Direction changed
int extType = (direction > 0 ? 0 : 1); // minumum or maximum?
mLastExtremes[extType][k] = mLastValues[k];
float diff = Math.abs(mLastExtremes[extType][k] - mLastExtremes[1 - extType][k]);
if (diff > mLimit) {
boolean isAlmostAsLargeAsPrevious = diff > (mLastDiff[k]*2/3);
boolean isPreviousLargeEnough = mLastDiff[k] > (diff/3);
boolean isNotContra = (mLastMatch != 1 - extType);
if (isAlmostAsLargeAsPrevious && isPreviousLargeEnough && isNotContra) {
for (StepListener stepListener : mStepListeners) {
stepListener.onStep();
}
mLastMatch = extType;
}
else {
Log.i(TAG, "no step");
mLastMatch = -1;
}
}
mLastDiff[k] = diff;
}
mLastDirections[k] = direction;
mLastValues[k] = v;
}
}
}
}
センサーの登録:
mSensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
mSensor = mSensorManager.getDefaultSensor(
Sensor.TYPE_ACCELEROMETER);
mSensorManager.registerListener(mStepDetector,mSensor,SensorManager.SENSOR_DELAY_NORMAL);
アルゴリズムでは、パブリックボイドとして感度のレベルが異なります
setSensitivity(float sensitivity) {
mLimit = sensitivity; // 1.97 2.96 4.44 6.66 10.00 15.00 22.50 33.75 50.62
}
さまざまな感度レベルでの私の結果は:
sensitivity rantastic pedometer my app
10.00 3870 5500
11.00 3000 4000
11.15 3765 4576
13.00 2000 890
11.30 754 986
要件に一致する適切なパターンを取得できません。私の分析によると、このアプリケーションはSensor.TYPE_MAGNETIC_FIELD
ステップ計算については、要件を満たすためにアルゴリズムを教えてください。
最初に行う必要があるのは、アルゴリズムの決定です。私が知る限り、文献に記載されている加速度計を使用してステップを検出するには、おおまかに言って3つの方法があります。
ピタゴラスの定理を使用して、加速度計からの各サンプルの加速度ベクトルの大きさを計算します。振幅信号をローパスフィルター処理して高周波ノイズを除去し、フィルター処理された信号のピークと谷を探します。誤検知を削除するには、要件を追加する必要がある場合があります。これは歩数を検出する最も簡単な方法であり、スポーツ店で購入できる種類の通常の歩数計ではないにしても、ほとんどすべての方法で動作します。
(1)のようにピタゴラスを使用し、FFTを介して信号を実行し、FFTからの出力を歩行の既知の出力と比較します。そのためには、かなり大量のトレーニングデータにアクセスする必要があります。
加速度計のデータを、ニューラルネットワークやデジタルウェーブレット変換などの適切な機械学習手法を使用するアルゴリズムに送ります。もちろん、このアプローチに他のセンサーを含めることができます。これには、かなり大量のトレーニングデータにアクセスする必要もあります。
アルゴリズムを決定したら、MatlabやSciPyのようなものを使用して、Android電話。加速度計データをCVSにダンプします。ファイルを携帯電話に保存し、そのファイルが表すステップ数を記録し、ファイルをコンピューターにコピーし、データに対してアルゴリズムを実行して、ステップ数が正しいかどうかを確認します。それら。
これが難しいように思える場合、適切なステップ検出にアクセスするための最善の方法は、おそらくキットカットが有効にする組み込みのステップカウンターを備えた電話機がさらに来るまで待つことです。
https://github.com/bagilevi/Android-pedometer
これが役に立つことを願っています
歩行器具でステップ検出を使用しています。 ステップ検出のいい結果が得られます。achartengineを使用して加速度計データをプロットします。 こちら をご覧ください。私がやること:
ポイント3.は計算されます:
この写真を見てください:
これが私の実現です。約1.5〜2年前に書かれました。そして、私が書いたこれらすべてのことを本当に覚えていません。しかし、うまくいきました。そして、それは私のニーズに合っていました。
私はこれが本当に大きなクラスであることを知っています(一部のメソッドは削除されます)が、役に立つかもしれません。そうでない場合は、この回答を削除します...
public class StepDetector implements SensorEventListener
{
public static final int MAX_BUFFER_SIZE = 5;
private static final int Y_DATA_COUNT = 4;
private static final double MIN_GRAVITY = 2;
private static final double MAX_GRAVITY = 1200;
public void onSensorChanged(final SensorEvent sensorEvent)
{
final float[] values = sensorEvent.values;
final Sensor sensor = sensorEvent.sensor;
if (sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD)
{
magneticDetector(values, sensorEvent.timestamp / (500 * 10 ^ 6l));
}
if (sensor.getType() == Sensor.TYPE_ACCELEROMETER)
{
accelDetector(values, sensorEvent.timestamp / (500 * 10 ^ 6l));
}
}
private ArrayList<float[]> mAccelDataBuffer = new ArrayList<float[]>();
private ArrayList<Long> mMagneticFireData = new ArrayList<Long>();
private Long mLastStepTime = null;
private ArrayList<Pair> mAccelFireData = new ArrayList<Pair>();
private void accelDetector(float[] detectedValues, long timeStamp)
{
float[] currentValues = new float[3];
for (int i = 0; i < currentValues.length; ++i)
{
currentValues[i] = detectedValues[i];
}
mAccelDataBuffer.add(currentValues);
if (mAccelDataBuffer.size() > StepDetector.MAX_BUFFER_SIZE)
{
double avgGravity = 0;
for (float[] values : mAccelDataBuffer)
{
avgGravity += Math.abs(Math.sqrt(
values[0] * values[0] + values[1] * values[1] + values[2] * values[2]) - SensorManager.STANDARD_GRAVITY);
}
avgGravity /= mAccelDataBuffer.size();
if (avgGravity >= MIN_GRAVITY && avgGravity < MAX_GRAVITY)
{
mAccelFireData.add(new Pair(timeStamp, true));
}
else
{
mAccelFireData.add(new Pair(timeStamp, false));
}
if (mAccelFireData.size() >= Y_DATA_COUNT)
{
checkData(mAccelFireData, timeStamp);
mAccelFireData.remove(0);
}
mAccelDataBuffer.clear();
}
}
private void checkData(ArrayList<Pair> accelFireData, long timeStamp)
{
boolean stepAlreadyDetected = false;
Iterator<Pair> iterator = accelFireData.iterator();
while (iterator.hasNext() && !stepAlreadyDetected)
{
stepAlreadyDetected = iterator.next().first.equals(mLastStepTime);
}
if (!stepAlreadyDetected)
{
int firstPosition = Collections.binarySearch(mMagneticFireData, accelFireData.get(0).first);
int secondPosition = Collections
.binarySearch(mMagneticFireData, accelFireData.get(accelFireData.size() - 1).first - 1);
if (firstPosition > 0 || secondPosition > 0 || firstPosition != secondPosition)
{
if (firstPosition < 0)
{
firstPosition = -firstPosition - 1;
}
if (firstPosition < mMagneticFireData.size() && firstPosition > 0)
{
mMagneticFireData = new ArrayList<Long>(
mMagneticFireData.subList(firstPosition - 1, mMagneticFireData.size()));
}
iterator = accelFireData.iterator();
while (iterator.hasNext())
{
if (iterator.next().second)
{
mLastStepTime = timeStamp;
accelFireData.remove(accelFireData.size() - 1);
accelFireData.add(new Pair(timeStamp, false));
onStep();
break;
}
}
}
}
}
private float mLastDirections;
private float mLastValues;
private float mLastExtremes[] = new float[2];
private Integer mLastType;
private ArrayList<Float> mMagneticDataBuffer = new ArrayList<Float>();
private void magneticDetector(float[] values, long timeStamp)
{
mMagneticDataBuffer.add(values[2]);
if (mMagneticDataBuffer.size() > StepDetector.MAX_BUFFER_SIZE)
{
float avg = 0;
for (int i = 0; i < mMagneticDataBuffer.size(); ++i)
{
avg += mMagneticDataBuffer.get(i);
}
avg /= mMagneticDataBuffer.size();
float direction = (avg > mLastValues ? 1 : (avg < mLastValues ? -1 : 0));
if (direction == -mLastDirections)
{
// Direction changed
int extType = (direction > 0 ? 0 : 1); // minumum or maximum?
mLastExtremes[extType] = mLastValues;
float diff = Math.abs(mLastExtremes[extType] - mLastExtremes[1 - extType]);
if (diff > 8 && (null == mLastType || mLastType != extType))
{
mLastType = extType;
mMagneticFireData.add(timeStamp);
}
}
mLastDirections = direction;
mLastValues = avg;
mMagneticDataBuffer.clear();
}
}
public static class Pair implements Serializable
{
Long first;
boolean second;
public Pair(long first, boolean second)
{
this.first = first;
this.second = second;
}
@Override
public boolean equals(Object o)
{
if (o instanceof Pair)
{
return first.equals(((Pair) o).first);
}
return false;
}
}
}
実装とgrepcodeプロジェクトのコードの間に見た主な違いの1つは、リスナーを登録する方法です。
あなたのコード:
mSensorManager.registerListener(mStepDetector,
mSensor,
SensorManager.SENSOR_DELAY_NORMAL);
彼らのコード:
mSensorManager.registerListener(mStepDetector,
mSensor,
SensorManager.SENSOR_DELAY_FASTEST);
これは大きな違いです。 SENSOR_DELAY_NORMAL
は方向の変更を目的としているため、それほど高速ではありません(デバイスを回転させてから実際にデバイスを回転させるまでに時間がかかることに気づいたことはありませんか?速い(おそらくかなり面倒です。)更新を取得する割合はそれほど高くありません)。
一方、SENSOR_DELAY_FASTEST
は歩数計のようなものを対象としています。センサーデータをできるだけ速く頻繁に取得する必要があるため、ステップの計算は可能な限り正確になります。
SENSOR_DELAY_FASTEST
レートに切り替えて、もう一度テストしてください!それは大きな違いを生むはずです。