detecção de falsos Acelerômetro: Android
-
06-07-2019 - |
Pergunta
Eu tenho um trecho de código para detectar acelerômetro movimentos. Ele funciona algumas vezes, detectando corretamente movimentos leves, mas às vezes ele detecta movimentos quando eu mantive minha ocioso dispositivo também. Há algum problema com built-in de detecção de acelerômetro no Android?
Eu uso um dispositivo HTC G-1. Meu trecho de código está abaixo. Como posso resolver isso para que eu possa detectar pequenos movimentos do dispositivo, mas não detectar nada quando o dispositivo está ocioso?
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;
}
}
}
Solução
Aqui estão as discrepâncias alguns código ...
-
Pode haver um problema em relação à actualização de
last_x
,last_y
elast_z
. Eu acredito que eles devem ser incluídos dentro a declaraçãoif ((curTime - lastUpdate) > 100) {
. Em outras palavras, eles estão sendo atualizados a cada vezonSensorChanged
é chamado, e não a cada 100 milissegundos. Você provavelmente deve mover a actualização desses três variáveis ??para a chaveta acima deles. -
Na linha onde você calcular o
speed
, as extremidades fórmula com... / diffTime * 10000;
Você está querendo multiplicar apenasdiffTime
por 10000, ou de todo o resultado? Desde/
e*
normalmente têm o mesmo operador precedência na maioria dos idiomas que eu conheço (como < a href = "http://www.cs.uwf.edu/~eelsheik/cop2253/resources/op_precedence.html" rel = "nofollow noreferrer"> Java ), sua equação será avaliada da esquerda para a direita , dividindo pela primeira vez pordiffTime
então multiplicando esse resultado por 10000.Eu estou supondo que você quer dizer para multiplicar apenas
diffTime
por 10000, portanto, divisória o resultado final por esse montante. Esta é a diferença entre dividindo por 10000 ou multiplicando por 10000, o que significa que você provavelmente está recebendo valores paraspeed
que são 10 ^ 8 maior do que deveria, tropeçando, assim, o seu limite, mesmo quando o dispositivo está ocioso. Você precisa colocar parênteses em torno da multiplicação, como... / (diffTime * 10000);
, para ter certeza que é realizada antes a divisão ocorre.Além disso, se você está pretendendo
diffTime
escala de milissegundos para segundos, o fator de escala deve ser 1000.
Outras dicas
Eu, pessoalmente, na minha biblioteca de realidade aumentada, use uma média móvel para as atualizações:
float kFilteringFactor = (float)0.05;
rollingZ = (float) ((rawZValue * kFilteringFactor) + (rollingZ * (1.0 - kFilteringFactor)));
Isso tende a suavizar os dados muito bem, e você pode ajustar o fator de filtragem para obter a resposta que você quer.
rawZValue é o valor bruto vindo do acelerômetro.