Android: fausse détection d'accéléromètre
-
06-07-2019 - |
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;
}
}
}
La solution
Voici quelques divergences de code ...
-
Il peut y avoir un problème concernant la mise à jour de
last_x
,last_y
etlast_z
. Je crois qu'ils devraient être inclus à l'intérieur duinstruction if ((curTime - lastUpdate) & 100) {
. En d'autres termes, ils sont mis à jour à chaque appel deonSensorChanged
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 simplementdiffTime
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 pardiffTime
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 devitesse
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.