对于我的Android应用,我需要或多或少准确地计算步数。我说"或多或少"因为我需要做的是知道在2秒内采取的步骤是否比以前的步骤更多或更少。 我尝试了以下两种算法,但没有一种算法有效。此外,我已经测试过请求Google Fit的步数,但它有时会返回215,然后是155,所以我不能依赖它。
我的解决方案如下:
private SensorEventListener sensorEventListener = new SensorEventListener() {
//Listens for change in acceleration, displays and computes the steps
@Override
public void onSensorChanged(SensorEvent event) {
//Gather the values from accelerometer
float x = event.values[0];
float y = event.values[1];
float z = event.values[2];
//Fetch the current y
currentY = y;
//Measure if a step was taken
if(Math.abs(currentY - previousY) > threshold) {
numSteps++;
textViewSteps.setText(String.valueOf(numSteps));
//Vibramos
Vibrator vibrator = (Vibrator) getSystemService(VIBRATOR_SERVICE);
vibrator.vibrate(200);
}
//Display the values
//textViewX.setText(String.valueOf(x));
//textViewY.setText(String.valueOf(y));
//textViewZ.setText(String.valueOf(z));
//Store the previous y
previousY = y;
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
};
private SensorEventListener sensorEventListener = new SensorEventListener()
{
private final static String TAG = "StepDetector";
private float mLimit = 10;
private float mLastValues[] = new float[3*2];
private float mScale[] = new float[2];
private float mYOffset;
private float mLastDirections[] = new float[3*2];
private float mLastExtremes[][] = { new float[3*2], new float[3*2] };
private float mLastDiff[] = new float[3*2];
private int mLastMatch = -1;
//Como no podemos crear un constructor en una clase anónima, uso un inicializador de instancia (instance initializer)
{
int h = 480;
mYOffset = h * 0.5f;
mScale[0] = - (h * 0.5f * (1.0f / (SensorManager.STANDARD_GRAVITY * 2)));
mScale[1] = - (h * 0.5f * (1.0f / (SensorManager.MAGNETIC_FIELD_EARTH_MAX)));
}
public void setSensitivity(float sensitivity) {
mLimit = sensitivity; // 1.97 2.96 4.44 6.66 10.00 15.00 22.50 33.75 50.62
}
//public void onSensorChanged(int sensor, float[] values) {
public void onSensorChanged(SensorEvent event) {
if(calculateKmhtime == 0)
calculateKmhtime = System.currentTimeMillis();
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;
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) {
Log.i(TAG, "step");
//Hemos detectado un paso. Aumentamos el número de pasos
numSteps++;
textViewSteps.setText(String.valueOf(numSteps));
mLastMatch = extType;
long currentTime = System.currentTimeMillis();
//Vibramos
Vibrator vibrator = (Vibrator) getSystemService(VIBRATOR_SERVICE);
vibrator.vibrate(200);
if(currentTime - calculateKmhtime >= CALCULATE_KMH_DELAY) {
calculateKmh(stepsInSpecifiedSeconds, (currentTime - calculateKmhtime) / 1000);
calculateKmhtime = System.currentTimeMillis();
stepsInSpecifiedSeconds = 0;
}else{
stepsInSpecifiedSeconds++;
}
}
else {
mLastMatch = -1;
}
}
mLastDiff[k] = diff;
}
mLastDirections[k] = direction;
mLastValues[k] = v;
}
}
}
}
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
};
如何改进? 谢谢