Calcul angle entre 2 vecteurs 3f : problème taille variable

Bonjour à tous,

Bon, je poste sur un problème que plusieurs d'autres vous ont déjà dû avoir, qui concerne les tailles de variables.

Je m'explique : je souhaite "tout simplement" mesurer l'angle entre deux vecteurs, dont la formule est la suivante :

angle =degrees(acos(((ax * ax0 + ay * ay0 + az * az0) / sqrt(((ax * ax + ay * ay + az * az) * (ax0 * ax0 + ay0 * ay0 + az0 * az0))))));

Mon problème : dans mon moniteur série ma valeur de angle est toujours égal à 0.

Je récupère les doonées d'un MPU6050 dont les valeurs de ax0, ay0 et az0 sont :

ax0 : 924 ay0 : -252 az0 : -17252

Les valeurs de ax, ay, az sont similaires car pour le moment je ne fais pas bouger mon montage.

Le câblage est fait ainsi, mais je ne pense pas qu'il y ai un lien de cause à effet car je me suis déjà servi plusieurs fois de cet accéléro pour d'autres choses et je récupère parfaitement les valeurs.

Pour comprendre, j'ai donc décomposé cette formule de "angle" en plusieurs sous-formules, et je me suis rendu compte que le problème arrivait là :

sqrt(((ax * ax + ay * ay + az * az) * (ax0 * ax0 + ay0 * ay0 + az0 * az0)))

La valeur retournée est à chaque fois un chiffre incohérent. J'ai essayé de décomposer cette formule, mais d'une part ça ne marche toujours pas, et surtout ça ne résout pas mon problème de fond : j'ai un problème de taille de variable.

De fait, j'ai deux questions :

  • Comment feriez-vous pour gérer ce problème de taille de variable?
  • Si pas de solution au 1., connaissez vous une autre méthode de calcul d'angle entre deux vecteurs 3d? J'ai cherché mais rien trouvé de simple

Pour finir, le code complet :

#include "Wire.h"  // Arduino Wire library
#include "I2Cdev.h"  //bibliothèque I2Cdev à installer
#include "MPU6050.h" //bibliothèque MPU6050 à installer
#include "math.h"

MPU6050 accelgyro;

int16_t ax, ay, az, gx, gy, gz;
int ax0, ay0, az0;

unsigned long angle = 0;

void setup()
{
  Wire.begin();  // bus I2C

  Serial.begin(9600); // liaison série

  accelgyro.initialize();

  accelgyro.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);

  //On défini le vecteur de référence
  ax0 = ax ;
  ay0 = ay ;
  az0 = az;

  Serial.println("|");
  Serial.println("|");
  Serial.println("|");
  Serial.println("|");
  Serial.print("ax0 : ");
  Serial.print(ax0);
  Serial.print("    ay0 : ");
  Serial.print(ay0);
  Serial.print("    az0 : ");
  Serial.println(az0);
  Serial.println("");
  Serial.println("");
}

void loop() {

  accelgyro.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);

  angle = degrees(acos(((ax * ax0 + ay * ay0 + az * az0) / sqrt(((ax * ax + ay * ay + az * az) * (ax0 * ax0 + ay0 * ay0 + az0 * az0))))));

  // Affichage accel/gyro x/y/z
  Serial.print("\tax/ay/az : ");
  Serial.print(ax);
  Serial.print("\t");
  Serial.print(ay);
  Serial.print("\t");
  Serial.print(az);
  Serial.print("\t angle : ");
  Serial.println(angle);

}

Si vous avez une astuce, je suis preneur!

D'avance merci.

Bonjour,

Comme tu fais les multiplications avec des entiers et que les entiers sont sur 16 bits, il y a toutes les chances que ces multiplications provoquent un débordement -> faire les calculs en flottant.

Bonjour,
Merci pour la réponse, mais en float c'est pareil... :frowning:

Comment tu fais ton calcul en float?

Je déclare juste ma variable en float....c’est pas suffisant?

La valeur retournée est à chaque fois un chiffre incohérent.

Les angles sont bien exprimés en radians ?

catsur:
Je déclare juste ma variable en float....c’est pas suffisant?

Si tu parles de la variable de réception, ce n'est pas suffisant.
En C/C++ la type de calcul d'une expression ne dépend pas de la variable de réception, mais uniquement du type des opérandes de l'expression.
Par exemple il faut mettre

sqrt(((float)ax * (float)ax + (float)ay * (float)ay + (float)az * (float)az) * ((float)ax0 * (float)ax0 + (float)ay0 * (float)ay0 + (float)az0 * (float)az0))

En fait (sauf erreur de ma part) je pense qu'il suffit de mettre

sqrt(((float)ax * ax + ay * ay + az * az) * ((float)ay * ax0 + ay0 * ay0 + az0 * az0))

Car si dans une sous expression un opérande est float alors tout le calcul se fait en float