2009-05-11 8 views
1

Je leur demande à 50Hz/50 fois par seconde pour les données. Lorsque je tourne soudainement l'appareil sur l'axe des x de 90 degrés alors que l'appareil est à plat sur une table avec l'affichage vers le haut avant, les valeurs se déplacent assez lentement à la valeur "cible" pour cette position.Pourquoi mes accéléromètres réagissent-ils si lentement?

Maintenant, la chose étrange est la suivante: si j'augmente le taux de mesure, la valeur se déplace plus rapidement à cette nouvelle valeur lors de retournement soudain le dispositif de 90 degrés. Mais si je demande juste une fois par seconde pour la nouvelle valeur, il faut très longtemps jusqu'à ce que la valeur atteigne la cible. Quelle peut en être la raison? Je ne fais aucune sorte d'agrégation de données, et ne rien accumuler. Je fais juste un filtrage simple pour me débarrasser du bruit. Ma méthode ressemble à ceci:

- (void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration { 
    // Use a basic low-pass filter to only keep the gravity in the accelerometer values for the X and Y axes 
    // accelerationX is an instance variable 
    accelerationX = acceleration.x * 0.05 + accelerationX * (1.0 - 0.05); 

    // round 
    int i = accelerationX * 100; 
    float clippedAccelerationValue = i; 
    clippedAccelerationValue /= 100; 

    [self moveViews:clippedAccelerationValue]; 
} 

plus tard, dans mes -moveViews: méthode, je fais ceci:

-(IBAction)moveSceneForPseudo3D:(float)accelerationValue { 
    if(fabs(lastAccelerationValue - accelerationValue) > 0.02) { // some little treshold to prevent flickering when it lays on a table 
     float viewAccelerationOffset = accelerationValue * 19 * -1; 

     newXPos = initialViewOrigin + viewAccelerationOffset; 
     myView.frame = CGRectMake(newXPos, myView.frame.origin.y, myView.frame.size.width, myView.frame.size.height); 

     lastAccelerationValue = accelerationValue; 
    } 
} 

En conséquence, le dispositif se tourna à 90 degrés sur le x-achsis ou 180 degrés, la vue se déplace assez lentement vers sa position cible. Je ne sais pas si c'est à cause de la physique des accéléromètres, ou si c'est un bug dans mon code de filtrage. Je sais seulement qu'il y a des jeux au rythme rapide où les accéléromètres sont utilisés pour la direction, donc je ne peux presque pas imaginer que c'est un problème matériel.

Répondre

8

Cette ligne:

accelerationX = acceleration.x * 0.05 + accelerationX * (1.0 - 0.05); 

est un filtre passe-bas, qui fonctionne en calculant une moyenne mobile de l'accélération de x. En d'autres termes, chaque fois que le rappel est appelé, vous ne faites que déplacer le accelerationX de 5% vers la nouvelle valeur de l'accéléromètre. C'est pourquoi il faut plusieurs itérations avant que accelerationX reflète la nouvelle orientation.

Ce que vous devez faire est d'augmenter la valeur 0.05, soit 0.2. Je ferais un #define global et jouerais avec différentes valeurs avec différents taux de régénération.

+0

Merci! C'était exactement la solution au problème. – Thanks

+0

Il convient d'ajouter que le déphasage créé par un filtre RC LowPass (que ce code implémente) est significatif. D'autres implémentations d'un filtre passe-bas (tel que celui mis en œuvre en utilisant FFT) sont un peu mieux et à cet égard. Ils sont beaucoup plus difficiles à mettre en œuvre cependant. –

Questions connexes