Accéléromètre 3D calculer l’orientation

J’ai des valeurs d’accéléromètre pour les 3 axes (généralement lorsqu’il n’y a que la gravité contient des données entre -1.0 et 1.0):

float Rx; float Ry; float Rz; 

Je fais des calculs soma, puis je reçois les angles pour chaque axe.

  float R = sqrt(pow(Rx,2)+pow(Ry,2)+pow(Rz,2)); float Arx = acos(Rx/R)*180/M_PI; float Ary = acos(Ry/R)*180/M_PI; float Arz = acos(Rz/R)*180/M_PI; 

Ensuite, je règle les valeurs des angles de la boîte en opengl

 rquad = Arx; yquad = Ary; 

Qui tourne ma boîte:

 glRotatef(yquad,1.0f,0.0f,0.0f); glRotatef(rquad,0.0f,1.0f,0.0f); 

Cela fonctionne sur l’hémisphère. J’aimerais utiliser la totalité de la sphère et je sais que je dois utiliser la valeur Arz pour que cela fonctionne, mais je ne sais pas comment puis-je l’utiliser pour cette rotation. Pourriez-vous m’aider?

Mise à jour: La réponse finale est dans mon cas:

  rquad = -atan2(Rx/R, Rz/R)*180/M_PI; yquad = -atan2(Ry/R, Rz/R)*180/M_PI; 

La bonne réponse est:

 Roll = atan2(Y, Z) * 180/M_PI; Pitch = atan2(-X, sqrt(Y*Y + Z*Z)) * 180/M_PI; 

Source: http://www.freescale.com/files/sensors/doc/app_note/AN3461.pdf (page 10, équations 25 et 26)

La réponse de Uesp est fausse. Cela semble être une approximation acceptable jusqu’à ce que le tangage et le roulis dépassent les 45 degrés.

J’assume peut-être une convention d’orientation différente, mais même si vous permutez les axes et inversez les valeurs de manière cohérente, les calculs de uesp ne seront jamais équivalents.

Bien que la réponse de matteo soit correcte, elle ne fournit pas la solution complète et complète: Les formules sont correctes:

 Roll = atan2(Y, Z) * 180/M_PI; Pitch = atan2(-X, sqrt(Y*Y + Z*Z)) * 180/M_PI; 

Cependant, lorsque la hauteur tonale est de + 90 / -90 degrés et que l’axe des X est vertical pointant vers le haut / le bas, la sortie normalisée idéale de l’accéléromètre devrait être:

 accX = -1 / accX = 1 accY = 0 accZ = 0 

Ce qui signifie un roll angle of 0 degrees ; correct. Mais en pratique, la sortie de l’accéléromètre est bruyante et vous rapprocheriez de quelque chose comme:

 accX = -1 / accX = 1 accY = 0.003 accZ = 0.004 

Cela peut sembler faible, mais l’angle de roulis sera d’environ 30 degrés, ce qui n’est pas correct.

L’instinct évident serait de filtrer les derniers chiffres, mais cela affecterait la précision, ce qui n’est pas toujours acceptable.

Le compromis, qui est très bien expliqué dans la note d’application de référence, consiste à inclure un très faible pourcentage de la lecture de l’axe X de l’accéléromètre dans la formule pour le rouleau:

 Roll = atan2( Y, sign* sqrt(Z*Z+ miu*X*X)); sign = 1 if accZ>0, -1 otherwise miu = 0.001 

L’erreur introduite de cette manière est considérablement plus petite que dans le cas précédent: 2 à 3 degrés lors de la mesure d’un rouleau dans les mêmes conditions que celles décrites ci-dessus.

J’ai essayé la solution recommandée (matteo) et, même si au début cela semblait bien fonctionner, j’ai remarqué que lorsque le diapason approche les 90 degrés (à partir d’environ 70 degrés, mais pas nécessairement de manière constante sur différents téléphones), le roulement augmente soudainement. Quand le pitch est à 90, le résultat qui devrait être autour de 0 est maintenant à plus de 100 et continue d’augmenter jusqu’à 180. J’essaie de trouver un moyen mathématiquement d’empêcher cela, si je limite le résultat à + 90 / -90, se comporte normalement mais je n’obtiens pas la plage que je veux (+ 180 / -180): Math.atan2 (y, Math.sqrt ((x x) + (z z))) * (180 / Math.PI)

Pour roll , j’ai trouvé que vous pouvez utiliser arctan(y/sqrt(X*X)+(z*z)) ce qui donnera un roll -90/90 qui correspond au standard de l’aviation sans donner le problème de la hauteur.

J’utilise les calculs suivants pour convertir les lectures de notre accéléromètre en valeurs de roulis et de tangage:

 Roll = atan2( sqrt(Y*Y + X*X), Z) * 180/M_PI; Pitch = atan2( sqrt(X*X + Z*Z), Y) * 180/M_PI; 

Vous devrez peut-être échanger les valeurs X / Y / Z ou traduire le roulis / la hauteur en fonction de la définition de vos accéléromètres. Pour les utiliser dans l’affichage, il suffit simplement de:

 glRotatef (Pitch, 0.0f, 0.0f, 1.0f); glRotatef (Roll, 1.0f, 0.0f, 0.0f);