2017-04-25 4 views
-3

J'ai trois figures: un cube, un octaèdre, un dodécaèdre.Comment déterminer le côté d'un octaèdre et d'un dodécaèdre à l'aide d'un accéléromètre?

A l'intérieur, chaque figurine possède un accéléromètre.

Les côtés des figures numérotés entre 1 et n.

Tâche: déterminer le côté actuel du cube, octaèdre, dodécaèdre.

Pour le cube, I dérivé de la formule:

côté = round ((Ax * 1/988) + (Ay * 2/988) + (Az * 3/988));

« côté » variable donnera des valeurs dans l'intervalle -3 et 3 (sans le 0), ce qui signifie que le côté actuel du cube entre 1 et 6.

Maintenant, je dois faire la même chose pour l'octaèdre et le dodécaèdre. Aide, comment puis-je faire cela? Ai-je besoin de capteurs supplémentaires ou d'un accéléromètre?

+0

Vous avez besoin d'écrire du code. Voilà comment! –

+0

@JarrodRoberson, ici nous n'avons pas besoin d'un code, nous avons besoin d'une formule mathématique –

+5

Ce n'est pas une question sur le sujet. C'est le point que nous ne sommes pas un service de codage. Lisez comment poser une bonne question. Les mathématiques ne sont pas sur le sujet non plus. –

Répondre

4

L'utilisation d'une formule comme celle-là est plutôt astucieuse mais elle a des propriétés indésirables. Premièrement, en se déplaçant d'un côté à l'autre, il se déplace à travers certaines valeurs intermédiaires résultant de la formule qui n'ont pas de signification géométrique. Par exemple, si vous êtes sur le côté -3 et que vous tournez sur le côté -1, il faudra nécessairement passer à -2. Deuxièmement, il peut ne pas être robuste aux données accélérométriques bruyantes, par exemple un vecteur qui est à mi-chemin entre les côtés -3 et -1, mais plus proche de -1 peut donner -2, quand il devrait donner -1.

Une approche alternative consiste à stocker un ensemble de normales de faces pour la figure, puis à prendre le produit scalaire de la lecture de l'accéléromètre avec chacune d'elles. La correspondance la plus proche (celle avec le produit scalaire le plus élevé) est le côté le plus proche.

par exemple:

float cube_sides[6][3] = { 
    {-1, 0, 0}, 
    {0, -1, 0}, 
    {0, 0, -1}, 
    {1, 0, 0}, 
    {0, 1, 0}, 
    {0, 0, 1}, 
}; 

int closest_cube_side(float Ax, float Ay, float Az) 
{ 
    float largest_dot = 0; 
    int closest_side = -1; // will return -1 in case of a zero A vector 
    for(int side = 0; side < 6; side++) 
    { 
     float dot = (cube_sides[side][0] * Ax) + 
      (cube_sides[side][1] * Ay) + 
      (cube_sides[side][2] * Az); 
     if(dot > largest_dot) 
     { 
      largest_dot = dot; 
      closest_side = side; 
     }    
    } 
    return closest_side; 
} 

Vous pouvez étendre cela pour un octaèdre et dodécaèdre en utilisant simplement les Normales de surface pour chacun. Aucun capteur supplémentaire ne devrait être nécessaire.

+0

hmm vient de réaliser que ta réponse est la même que la mienne ... (je supprimerai la mienne comme tu étais plus rapide) mais juste besoin d'ajouter: Dans le cas où la gravité mesurée est trop éloignée de '9.81 [m/s^2]' ne reste pas immobile ni ne tombe en chute libre mais accélère à la place et vous devriez ignorer une telle lecture (en supposant que vous le faites sur la surface de la Terre) – Spektre

+0

@samgak, merci de votre réponse. Je sais peu de choses sur les normales, mais je vais étudier. Petite erreur, vous écrivez 'return closest_side; 'dans la boucle for, il devrait être après pour la boucle :) Pour le cube cela fonctionne très bien. Grand merci! –

+0

@Spektre Je pense que vous devriez restaurer votre réponse car elle contient des informations qui ne sont pas dans la mienne. Peu importe qui est plus rapide – samgak