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

    }

}
Foi útil?

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 e last_z. Eu acredito que eles devem ser incluídos dentro a declaração if ((curTime - lastUpdate) > 100) {. Em outras palavras, eles estão sendo atualizados a cada vez onSensorChanged é 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 apenas diffTime 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 por diffTime 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 para speed 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.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top