Question

J'ai un extrait de code pour détecter les mouvements de l'accéléromètre. Cela fonctionne parfois en détectant correctement les mouvements légers, mais parfois en détectant les mouvements lorsque je laisse mon appareil inactif. Existe-t-il des problèmes de détection d'accéléromètre intégré sur Android?

J'utilise un appareil HTC G-1. Mon extrait de code est ci-dessous. Comment puis-je résoudre le problème pour pouvoir détecter les petits mouvements de l'appareil mais ne rien détecter lorsque l'appareil est inactif?

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

    }

}
Était-ce utile?

La solution

Voici quelques divergences de code ...

  • Il peut y avoir un problème concernant la mise à jour de last_x , last_y et last_z . Je crois qu'ils devraient être inclus à l'intérieur du instruction if ((curTime - lastUpdate) & 100) {. En d'autres termes, ils sont mis à jour à chaque appel de onSensorChanged et non toutes les 100 millisecondes. Vous devriez probablement déplacer la mise à jour de ces trois variables dans l'accolade au-dessus d'eux.

  • Sur la ligne où vous calculez la vitesse , la formule se termine par ... / diffTime * 10000; Voulez-vous multiplier simplement diffTime sur 10000, ou le résultat entier? Étant donné que / et * ont généralement la même priorité de l'opérateur dans la plupart des langues que je connais (telles que Java ), votre équation sera évaluée de gauche à droite, en divisant d’abord par diffTime puis par en multipliant ce résultat par 10000.

    Je suppose que vous voulez simplement multiplier diffTime par 10 000, ce qui divise le résultat final par ce montant. C'est la différence entre diviser par 10 000 ou multiplier par 10 000, ce qui signifie que vous obtenez probablement des valeurs de vitesse supérieures de 10 ^ 8 à ce que vous devriez, déclenchant ainsi votre seuil même lorsque l'appareil est inactif. Vous devez placer des parenthèses autour de la multiplication, comme ... / (diffTime * 10000); , pour vous assurer que cela est exécuté avant que la division ait lieu.

    En outre, si vous souhaitez mettre à l'échelle diffTime de quelques millisecondes à quelques secondes, votre facteur d'échelle doit être égal à 1000.

Autres conseils

Personnellement, dans ma bibliothèque de réalité augmentée, j'utilise une moyenne glissante pour les mises à jour:

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

Cela a tendance à lisser les données et vous pouvez modifier le facteur de filtrage pour obtenir la réactivité souhaitée.

rawZValue est la valeur brute provenant de l'accéléromètre.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top