Join FlipAndroid.COM Telegram Group: https://t.me/joinchat/F_aqThGkhwcLzmI49vKAiw


Cómo calcular el pie exacto paso de contar con acelerómetro en android?

Estoy desarrollando alguna aplicación como Runtastic Pedometer usando el algoritmo https://code.google.com/p/pedometer/ pero no estoy consiguiendo ninguna similitud entre los resultados.

Mi código es como sigue:

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; } } } } 

Para registrar sensores:

 mSensorManager = (SensorManager) getSystemService(SENSOR_SERVICE); mSensor = mSensorManager.getDefaultSensor( Sensor.TYPE_ACCELEROMETER); mSensorManager.registerListener(mStepDetector,mSensor,SensorManager.SENSOR_DELAY_NORMAL); 

En el algoritmo tengo diferentes niveles de sensibilidad como 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 } 

En varios niveles de sensibilidad mi resultado es:

 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 

No estoy consiguiendo ningún patrón apropiado para emparejar con el requisito. Según mi análisis esta aplicación está usando Sensor.TYPE_MAGNETIC_FIELD para los pasos de cálculo por favor hágamelo saber algún algoritmo para que pueda cumplir con el requisito

  • Plataformas SDK de Android entre Linux y Windows
  • Realización de una solicitud HTTPS mediante Android Volley
  • Android Studio 2.0 Preview 2 problema con Renderscript
  • Manera de proteger de Lucky Patcher / licencia de juego
  • Archivo binario línea # 8: Error al inflar el fragmento de la clase, Google Maps
  • MPAndroidChart set center vertical line
  • Android: simula mucho tiempo de ejecución
  • Android.os.NetworkOnMainThreadException. ¿Necesidad de utilizar la tarea asincrónica?
  • 5 Solutions collect form web for “Cómo calcular el pie exacto paso de contar con acelerómetro en android?”

    https://github.com/bagilevi/android-pedometer

    Espero que esto pueda ser útil

    Lo primero que debe hacer es decidir sobre un algoritmo. Hasta donde yo sé, hay aproximadamente tres maneras de detectar pasos usando acelerómetros que se describen en la literatura:

    1. Utilice el teorema de Pitágoras para calcular la magnitud del vector de aceleración de cada muestra del acelerómetro. Filtro de paso bajo la señal de magnitud para eliminar el ruido de alta frecuencia y luego buscar los picos y valles en la señal filtrada. Es posible que deba agregar requisitos adicionales para eliminar falsos positivos. Esta es, con mucho, la forma más sencilla de detectar pasos, es también la forma en que la mayoría, si no todos los pedómetros ordinarios del tipo que se puede comprar en una tienda de deportes de trabajo.

    2. Utilice Pythagoras como en (1), luego ejecute la señal a través de una FFT y compare la salida de la FFT con las salidas conocidas de caminar. Esto requiere que usted tenga acceso a una cantidad bastante grande de datos de entrenamiento.

    3. Alimentar los datos del acelerómetro en un algoritmo que utilice alguna técnica de aprendizaje de la máquina adecuada, por ejemplo una red neuronal o una transformada wavelet digital. Por supuesto, puede incluir otros sensores en este enfoque. Esto también requiere que usted tenga acceso a una cantidad bastante grande de datos de entrenamiento.

    Una vez que hayas decidido un algoritmo, probablemente querrás usar algo como Matlab o SciPy para probar tu algoritmo en tu computadora usando grabaciones que has hecho en teléfonos Android. Vaciar los datos del acelerómetro en un archivo cvs de su teléfono, hacer un registro de cuántos pasos representa el archivo, copiar el archivo a su computadora y ejecutar el algoritmo en los datos para ver si obtiene el recuento de pasos correcto. De esta manera puede detectar problemas con el algoritmo y corregirlos.

    Si esto suena difícil, entonces la mejor manera de obtener acceso a una buena detección de pasos es probablemente esperar hasta que más teléfonos vienen con el contador de pasos incorporado que KitKat permite.

    Estoy usando la detección de pasos en mi instrumento para caminar. Consigo los resultados agradables de la detección del paso. Utilizo achartengine para trazar los datos del acelerómetro. Echa un vistazo aquí: https://github.com/MichalDanielDobrzanski/WalkingSynth/blob/master/app/src/main/java/com/dobi/walkingsynth/accelerometer/AccelerometerProcessing.java Qué hago:

    1. Análisis del vector de magnitud para el sensor del acelerómetro.
    2. Establecer un nivel de umbral variable . Cuando la señal del acelerómetro está por encima de ella, lo considero como un paso.
    3. Ajuste del tiempo de estado inactivo (para la detección de pasos) después del primer cruce del umbral.

    El punto 3 se calcula:

    • Ajuste arbitrario del tempo máximo de nuestro caminar (por ejemplo 120bpm)
    • Si 60bpm – 1000msec por paso, entonces 120bpm – 500msec por paso
    • El acelerómetro pasa los datos con determinada frecuencia deseada (SENSOR_DELAY_NORMAL, SENSOR_DELAY_GAME, etc.). Cuando DELAY_GAME: T ~ = 20ms (esto está incluido en la documentación de Android)
    • N – muestras para omitir (después de pasar el umbral)
    • N = 500msec / T
    • N = 500/20 = 25 (muchos de ellos, puede ajustar este valor).
    • Después de eso, el umbral se activa .

    Echa un vistazo a esta foto: Mi aplicación

    Esta es mi realización. Fue escrito hace unos 1,5-2 años. Y realmente no recuerdo todas estas cosas que escribí. Pero funcionó. Y funcionó bien para mis necesidades.

    Sé que esto es realmente gran clase (algunos métodos se eliminan), pero puede ser que será útil. Si no, simplemente eliminaré esta respuesta …

     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; } } } 

    Una diferencia principal que vi entre su implementación y el código en el proyecto grepcode es la forma en que registra al oyente.

    Tu codigo:

     mSensorManager.registerListener(mStepDetector, mSensor, SensorManager.SENSOR_DELAY_NORMAL); 

    Su código:

     mSensorManager.registerListener(mStepDetector, mSensor, SensorManager.SENSOR_DELAY_FASTEST); 

    Esta es una gran diferencia. SENSOR_DELAY_NORMAL está destinado a los cambios de orientación, y por lo tanto no es tan rápido (nunca se dio cuenta de que lleva algún tiempo entre la rotación del dispositivo, y el dispositivo en realidad girar? Eso es porque esta es una funcionalidad que no necesita ser super rápido Probablemente ser bastante molesto incluso.) La tasa en la que se obtiene actualizaciones no es tan alto).

    Por otro lado, SENSOR_DELAY_FASTEST está pensado para cosas como podómetros: desea que los datos del sensor sean tan rápidos y tan frecuentes como sea posible, por lo que sus cálculos de pasos serán lo más precisos posible.

    Intenta cambiar a la velocidad de SENSOR_DELAY_FASTEST y vuelve a probar! Debe hacer una gran diferencia.

    FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.