it-swarm.com.de

3D-Beschleunigungsmesser berechnen die Ausrichtung

Ich habe Beschleunigungsmesser-Werte für die 3-Achse (normalerweise, wenn nur die Schwerkraft Daten zwischen -1,0 und 1,0 enthält):

  float Rx;
  float Ry;
  float Rz;

Ich mache Soma-Berechnungen, dann bekomme ich die Winkel für jede Achse.

  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;

Dann stelle ich die Werte für die Kastenwinkel in opengl ein

rquad = Arx;
yquad = Ary;

Was dreht meine Box:

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

Es funktioniert auf der Hemisphäre. Ich würde gerne die volle Sphäre verwenden und weiß, dass ich den Arz-Wert verwenden muss, damit es funktioniert, aber ich weiß nicht, wie ich das für diese Rotation verwenden kann. Kannst du mir helfen?

Update: Die endgültige Antwort lautet in meinem Fall:

  rquad = -atan2(Rx/R, Rz/R)*180/M_PI;
  yquad = -atan2(Ry/R, Rz/R)*180/M_PI;
26
Roland Soós

Die richtige Antwort ist:

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

Quelle: http://www.freescale.com/files/sensors/doc/app_note/AN3461.pdf (Seite 10, Gl. 25 und 26)

die Antwort von uesp ist falsch. Es sieht nach einer akzeptablen Annäherung aus, bis die Neigung und der Rollwinkel beide über 45 Grad gehen.

Ich gehe vielleicht von einer anderen Orientierungskonvention aus, aber selbst wenn Sie Achsen austauschen und Werte auf eine konsistente Art und Weise invertieren, werden die Berechnungen von uesp niemals gleichwertig sein.

40
matteo

Die Antwort von matteo ist zwar korrekt, bietet jedoch nicht die vollständige, vollständige Lösung: Die Formeln sind richtig:

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

Wenn jedoch die Neigung + 90/-90 Grad beträgt und die X-Achse vertikal nach oben/unten zeigt, sollte der normalisierte Ausgang des Beschleunigungsmessers Folgendes sein:

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

Was bedeutet ein roll angle of 0 degrees; richtig . In der Praxis ist der Ausgang des Beschleunigungsmessers jedoch sehr laut und Sie würden etwas näher kommen:

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

Dies mag klein erscheinen, führt aber dazu, dass der Rollwinkel ~ 30 Grad beträgt, was nicht korrekt ist.

Der offensichtliche Instinkt wäre, die letzten Ziffern herauszufiltern, was jedoch die Genauigkeit beeinträchtigen würde, was nicht immer akzeptabel ist.

Der Kompromiss, der in der Referenz-App-Anmerkung sehr gut erklärt wird, besteht darin, einen sehr kleinen Prozentsatz des X-Achsenwerts des Beschleunigungsmessers in die Formel für die Rolle aufzunehmen:

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

Der auf diese Weise eingeführte Fehler ist erheblich kleiner als im vorigen Fall: 2-3 Grad beim Messen der Rolle unter den gleichen Bedingungen, die oben erläutert wurden.

18
Pandrei

Ich habe die empfohlene Lösung (matteo's) ausprobiert, und obwohl sie anfangs gut zu funktionieren schien, fiel mir auf, dass der Roll plötzlich ansteigt, wenn sich die Tonhöhe um 90 Grad nähert (beginnend bei etwa 70 Grad, aber nicht unbedingt auf verschiedenen Handys konstant). Wenn die Tonhöhe bei 90 liegt, ist der Wurfwert, der um 0 liegen sollte, jetzt über 100 und steigt weiter auf 180. Ich versuche, einen Weg zu finden, um dies mathematisch zu verhindern, wenn ich den Wurf auf + 90/-90 beschränke verhält sich normalerweise, aber ich bekomme nicht den gewünschten Bereich (+ 180/-180): Math.atan2 (y, Math.sqrt ((xx) + (z z))) * (180 /Math.PI))

3
FaithNoMan

Ich verwende die folgenden Berechnungen, um unsere Beschleunigungsmesser-Messwerte in Roll- und Nickwerte umzuwandeln:

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

Möglicherweise müssen Sie die X/Y/Z-Werte tauschen oder die Roll/Pitch-Werte verschieben, je nachdem, wie Ihre Beschleunigungsmesser definiert sind. Um sie in der Anzeige zu verwenden, ist es ganz einfach:

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

Für roll habe ich festgestellt, dass Sie arctan(y/sqrt(X*X)+(z*z)) verwenden können. Dadurch wird roll -90/90 ausgegeben

0
Ian Bloomfield