Android: detección falsa del acelerómetro
-
06-07-2019 - |
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;
}
}
}
Solución
Aquí hay algunas discrepancias de código ...
-
Puede haber un problema con respecto a la actualización de
last_x
,last_y
ylast_z
. Creo que deberían incluirse dentro la declaraciónif ((curTime - lastUpdate) > 100) {
. En otras palabras, se actualizan cada vez que se llama aonSensorChanged
, 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 solodiffTime
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 pordiffTime
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 paraspeed
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.