Pregunta

Tengo un fragmento de código para detectar movimientos del acelerómetro. Funciona algunas veces al detectar correctamente movimientos leves, pero a veces detecta movimientos cuando mantengo mi dispositivo inactivo también. ¿Hay algún problema con la detección del acelerómetro incorporado en Android?

Yo uso un dispositivo HTC G-1. Mi fragmento de código está debajo. ¿Cómo lo resuelvo para poder detectar pequeños movimientos del dispositivo pero no detectar nada cuando el dispositivo está inactivo?

private static final int SHAKE_THRESHOLD = 50;

public void onSensorChanged(int sensor, float[] values) {

    if (sensor == SensorManager.SENSOR_ACCELEROMETER) {
        long curTime = System.currentTimeMillis();
        // only allow one update every 100ms.
        if ((curTime - lastUpdate) > 100) {
            long diffTime = (curTime - lastUpdate);
            lastUpdate = curTime;

            x = values[SensorManager.DATA_X];
            y = values[SensorManager.DATA_Y];
            z = values[SensorManager.DATA_Z];

            float speed = Math.abs(x+y+z - last_x - last_y - last_z) / diffTime * 10000;

            if (speed > SHAKE_THRESHOLD) { 
                long curTime = System.currentTimeMillis();
                long diff = (curTime - shakeTime);              
                shakeTime = curTime;

                if (myFlagIgnoreShakeDetection==true)  //Caused unneccessary accelerometer   
                                                       //notification looping when device is idle
                   return;

                // Doing something...
            }
         last_x = x;
         last_y = y;
         last_z = z;
        }

    }

}
¿Fue útil?

Solución

Aquí hay algunas discrepancias de código ...

  • Puede haber un problema con respecto a la actualización de last_x , last_y y last_z . Creo que deberían incluirse dentro la declaración if ((curTime - lastUpdate) > 100) {. En otras palabras, se actualizan cada vez que se llama a onSensorChanged , no cada 100 milisegundos. Probablemente deberías mover la actualización de esas tres variables a la llave encima de ellas.

  • En la línea donde calcula la velocidad , la fórmula termina con ... / diffTime * 10000; ¿Desea multiplicar solo diffTime por 10000, o el resultado completo? Dado que / y * suelen tener la misma prioridad del operador en la mayoría de los idiomas que conozco (como Java ), su ecuación se evaluará de izquierda a derecha, dividiéndose primero por diffTime y luego multiplicando ese resultado por 10000.

    Supongo que te refieres a multiplicar solo diffTime por 10000, por lo tanto dividiendo el resultado final por esa cantidad. Esta es la diferencia entre dividir por 10000 o multiplicar por 10000, lo que significa que probablemente esté obteniendo valores para speed que son 10 ^ 8 mayores de lo que debería, disparando así su umbral incluso cuando el dispositivo está inactivo. Debe poner paréntesis alrededor de la multiplicación, como ... / (diffTime * 10000); , para asegurarse de que se realiza antes de que se realice la división.

    Además, si tiene la intención de escalar diffTime de milisegundos a segundos, su factor de escala debería ser 1000.

Otros consejos

Personalmente, en mi biblioteca de realidad aumentada, utilizo un promedio móvil para las actualizaciones:

float kFilteringFactor = (float)0.05;    
rollingZ = (float) ((rawZValue * kFilteringFactor) + (rollingZ * (1.0 - kFilteringFactor)));

Esto tiende a suavizar los datos bastante bien, y puede ajustar el factor de filtrado para obtener la capacidad de respuesta que desee.

rawZValue es el valor bruto que viene del acelerómetro.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top