Seite 1 von 2
Yaw-Pitch-Roll-Rotations Berechnung einer Einheitsmatrix
Verfasst: 14.12.2010 15:35
von mpz
WICHTIG habe den Text des Themas geändert, da der neue Text wesendlich sinnvoller ist und das Thema besser beschreibt
Hallo Leute,
ich kämpfe gerade mit einem mathematischen Problem und komme nicht weiter. Gegeben sind zwei Punkte als Vectoren point (x,y,z) im 3D Raum. Der erste Punkt hat die Koordinaten (0,0,0) der andere (x,y,z) als Variable. Jetzt möchte ich die 3 Winkel der x/y/z Achse der Geraden erhalten, möglichst in Grad oder Radiant.
P.S: Es handelt sich quasi dabei um eine Lookat Berechnung die ich derzeit über eine Matrix Berechnung hinbekomme, kann aber dummerweise aus dieser Matrix nicht die drei Winkel ableiten, daher dachte ich ich berechne die Winkel anders herum. Das Problem ist das sich das Objekt nach der Lookat Routine nicht vernüftig drehen kann da die enstandenen Winkel unbekannt sind
Gruß Michael
Re: 3 Winkel einer Linie im 3D Raum
Verfasst: 14.12.2010 17:46
von DarkDragon
Die Winkel bekommst ganz leicht durch eine orthogonale Projektion auf die Basis-Ebenen durch das Skalarprodukt:
Code: Alles auswählen
cos alpha = (vektor1 * vektor2) / (|vektor1| * |vektor2|)
alpha = acos((vektor1 * vektor2) / (|vektor1| * |vektor2|))
Am Beispiel z-Winkel mit Projektion auf xy-Ebene mit dem Vektor v = (5, 4, 3):
v auf Ebene xy Projeziert: w = (5, 4, 0)
Winkel zwischen (0, 1, 0) und w nach obiger Formel:
Code: Alles auswählen
Debug ACos((5 * 0 + 4 * 1 + 0 * 0) / (Sqr(Pow(5, 2) + Pow(4, 2) + Pow(0, 2)) * 1)) * 180.0 / #PI
51.34
Allerdings würde ich es bei einer Engine bevorzugen wenn man selbst mit Matrizen arbeiten darf.
[EDIT]
Die Gerade musst du natürlich als einen Richtungsvektor darstellen

. Die Position der Geraden ist ja irrelevant.
Re: 3 Winkel einer Linie im 3D Raum
Verfasst: 14.12.2010 19:30
von STARGÅTE
Eigentlich reichen 2 Winkel um einen Punkt im Raum zu lokalisieren (Stichwort: Kugelkoordinaten)
Der Anstand, welcher ja der Radius bei Kugelkoordinaten ist, ist für ein LookAt egal ...
Den 3. Winkel brauchst du ja nur, um das Ergebnis noch mal um die Sichtachse zu drehen.
Da dieser Winkel aber aus den Angaben von nur einem Punkten nicht eindeutig bestimmt ist, kannst du ihn auch nicht berechnen.
Schließlich kann ich die Kamera ja auch x,y,z richten und dabei dann frei um die z-Achse drehen, ohne das sich das Ergebnis (nach x,y,z gucken) ändert.
Re: 3 Winkel einer Linie im 3D Raum
Verfasst: 16.12.2010 14:11
von D.J.Peters
Tip:
Dreh doch mal einen Punkt/Vector z.B. 0,0,1 1.57 RAD um die X-Achse und schau Dir mal die Werte dieser Matrix an.
Nimm ruhig noch andere Vectoren die die Länge 1 haben
Dann fällt der Groschen bestimmt äh heute heißt das ja "Cent"
Die drei gesuchten Winkel stehen ja in der Matrix:
Code: Alles auswählen
heading = ATan2(-m.m20,m.m00)
bank = ATan2(-m.m12,m.m11)
attitude = ASin(m.m10)
Ich gehe einfach davon aus das Du weiss wie eine Matrix aufgebaut ist bzw. welches Feld der Matrix z.B. mit
m20 gemeint ist.
Im Falle einer singularen Matrix:
Code: Alles auswählen
if (m.m10 > 0.998)
heading = Atan2(m.m02,m.m22)
attitude = PI/2
bank = 0
elseif (m.m10 < -0.998)
heading = Atan2(m.m02,m.m22)
attitude = -PI/2
bank = 0
endif
Grüsse Joshy
Re: 3 Winkel einer Linie im 3D Raum
Verfasst: 16.12.2010 17:31
von mpz
Hi D.J.Peters,
ich glaube das wäre ein Ansatz. Bisher habe ich keine RotationsMatrix to Angle Funktion gefunden die die Funktion D3DXMatrixRotationYawPitchRoll(matrix, yaw, pitch, roll ) reverse zurück rollte bzw wie man auf yaw, pitch, roll kommen kann. Alle Formeln und Ansätze sind an der Wirklichkeit ( bei zwei funktionen von yaw, pitch, roll funktionierts, bei drei nicht mehr) gescheitert. Ich werd mal experimientieren und falls ich zu einem Ergebnis komme veröffentlichen...
Gruß Michael
Re: 3 Winkel einer Linie im 3D Raum
Verfasst: 17.12.2010 15:13
von mpz
Hi Leute,
ich fürchte ich benötige noch nen "Groschen". Hier mal meine bisherige Routine. Sobald yaw als Wert dazu kommt geht alles den Bach runter, bzw. werden die Winkel falsch angeben. Daher die Frage wie bekomme ich den Winkel mit Vectoren hin, vermutlich drei Vectoren berechnen. Hat noch jemans eine Idee die hilft ?!?!
Yaw.f = 0
Pitch.f = 20
Roll.f = 30
Ergebnis super
Yaw.f = 60
Pitch.f = 20
Roll.f = 30
Ergebnis Murx
Code: Alles auswählen
;- Beispiele funktioniert nur unter Windows
Structure D3DXMATRIX
_11.f
_12.f
_13.f
_14.f
_21.f
_22.f
_23.f
_24.f
_31.f
_32.f
_33.f
_34.f
_41.f
_42.f
_43.f
_44.f
EndStructure
Structure D3DXVector3
x.f
y.f
z.f
EndStructure
Macro D3DXToDegree(radian) ; radiant in Grad
(radian * 57.29578)
; (radian * 57.295779513082323)
EndMacro
Macro D3DXToRadian(Degree)
(Degree * 0.017453)
; (Degree * 0.017453292519943295)
EndMacro
Import "d3dx9.lib"
D3DXMatrixRotationYawPitchRoll (*pOut.D3DXMATRIX, Yaw.f, Pitch.f, Roll.f)
D3DXVec3TransformNormal (*pOut.D3DXVector3, *pV.D3DXVector3, *pM.D3DXMATRIX)
EndImport
Matrix.D3DXMATRIX
Matrix\_11 = 1
Matrix\_22 = 1
Matrix\_33 = 1
Matrix\_44 = 1
Yaw.f = 0
Pitch.f = 20
Roll.f = 30
D3DXMatrixRotationYawPitchRoll (Matrix.D3DXMATRIX, D3DXToRadian(Yaw.f), D3DXToRadian(Pitch.f), D3DXToRadian(Roll.f))
;- Berechnung 1
alpha.f = ATan2 (Sqr(Pow(Matrix\_11,2) + Pow (Matrix\_21,2)),Matrix\_31);
float1.f = D3DXToDegree(alpha)
float2.f = D3DXToDegree(-ATan2(Matrix\_33/Cos(alpha),Matrix\_32/Cos(alpha)))
float3.f = D3DXToDegree(-ATan2(Matrix\_11/Cos(alpha),Matrix\_21/Cos(alpha)))
;- Berechnung 2
If Matrix\_11 > = 0
float4.f = D3DXToDegree(ASin(Matrix\_31))
float5.f = D3DXToDegree(-ATan2(Matrix\_33,Matrix\_32))
float6.f = D3DXToDegree(-ATan2(Matrix\_11,Matrix\_21 ))
Else
float4 = D3DXToDegree(ACos(Matrix\_31))+90
float5 = D3DXToDegree(ATan2(-Matrix\_33,-Matrix\_32))
float6 = D3DXToDegree(ATan2(-Matrix\_11,-Matrix\_21 ))
EndIf
Debug "Winkel mit Matrix Routine"
Debug float1
Debug float2
Debug float3
Debug float4
Debug float5
Debug float6
pV.D3DXVector3
pV\x = 1
pV\y = 0
pV\z = 0
D3DXVec3TransformNormal (pOut.D3DXVector3, pV.D3DXVector3, @Matrix)
Debug "Vector x = 1"
Debug pV\x
Debug pV\y
Debug pV\z
Debug pOut\x
Debug pOut\y
Debug pOut\z
; What nu sprach Zeus
Re: 3 Winkel einer Linie im 3D Raum
Verfasst: 17.12.2010 15:56
von DarkDragon
mpz hat geschrieben:Hi Leute,
ich fürchte ich benötige noch nen "Groschen". Hier mal meine bisherige Routine. Sobald yaw als Wert dazu kommt geht alles den Bach runter, bzw. werden die Winkel falsch angeben. Daher die Frage wie bekomme ich den Winkel mit Vectoren hin, vermutlich drei Vectoren berechnen. Hat noch jemans eine Idee die hilft ?!?!
Naja, das geht eben nicht, bzw. nicht wenn nicht mehr Informationen gegeben sind wie z.B. ein Up Vektor. Außerdem kannst du das vergessen, sobald du z.B. Skalierungen mit rein bringst oder andere (vielleicht auch völlig abstruse) Verzerrungen:
Code: Alles auswählen
D3DXMatrixRotationYawPitchRoll (Matrix.D3DXMATRIX, D3DXToRadian(Yaw.f), D3DXToRadian(Pitch.f), D3DXToRadian(Roll.f))
D3DXMatrixScaling(MatrixScaling.D3DXMatrix, 1.0, 3.0, 1.0)
D3DXMatrixMultiply(Matrix, Matrix, MatrixScaling)
dann kommt für
nämlich
raus.
[EDIT]
Du müsstest aber ja einen Up-Vektor haben wenn ich das richtig sehe. Aber dann hast du eigentlich alles was du brauchst, und ich verstehe den Umweg über die Matrizen nicht, wenn du eh nur die 3 Winkel haben willst und keine Transformationsmatrix für das LookAt.
Du musst praktisch rausfinden bei welchen 3 Winkeln der rotierte Rightvektor (1, 0, 0), der Upvektor (0, 1, 0) und der Viewvektor (0, 0, 1) ergibt.
Re: 3 Winkel einer Linie im 3D Raum
Verfasst: 02.01.2011 20:20
von mpz
Hi,
grossen Dank an Gnasen der mit mir diese Matrix-Lösung in Kleinarbeit hinbekommen hat. Hier gibt es aber verschiedene "Winkelmöglichkeiten" die die selbe Matrix erzeugt. Daher kommt nicht der "gleiche" Winkel raus sondern eine YawPitchRoll Mischung die die gleiche Matrix erzeugen. In der Praxis funktioniert das super. Da ich im Netz keine vergleichbare Lösung gefunden haben kommt hier die Lösung.
"Allerdings würde ich halt darauf hinweisen, dass der Code für linkshändig orientierte Koordinatensysteme ist. Nur zur Sicherheit bevor noch andere verzweifeln."
An DarkDragon
auch mitMatrixScaling funktioniert die Formel, allerdings ist es bei DX9 wichtig die Matrixen in der richtigen Reihenfolge zu multiplizieren
Richtig -> D3DXMatrixMultiply(Matrix, MatrixScaling, Matrix)
Code: Alles auswählen
;- Beispiele funktioniert nur unter Windows
Structure D3DXMATRIX
_11.f
_12.f
_13.f
_14.f
_21.f
_22.f
_23.f
_24.f
_31.f
_32.f
_33.f
_34.f
_41.f
_42.f
_43.f
_44.f
EndStructure
Structure D3DXVector3
x.f
y.f
z.f
EndStructure
Macro D3DXToDegree(radian) ; radiant in Grad
(radian * 57.29578)
; (radian * 57.295779513082323)
EndMacro
Macro D3DXToRadian(Degree)
(Degree * 0.017453)
; (Degree * 0.017453292519943295)
EndMacro
Import "d3dx9.lib"
D3DXMatrixRotationYawPitchRoll (*pOut.D3DXMATRIX, Yaw.f, Pitch.f, Roll.f)
D3DXVec3TransformNormal (*pOut.D3DXVector3, *pV.D3DXVector3, *pM.D3DXMATRIX)
EndImport
Matrix.D3DXMATRIX
Matrix\_11 = 1
Matrix\_22 = 1
Matrix\_33 = 1
Matrix\_44 = 1
Yaw.f = 320
Pitch.f = -120
Roll.f = -42
D3DXMatrixRotationYawPitchRoll(Matrix.D3DXMATRIX, D3DXToRadian(Yaw), D3DXToRadian(Pitch), D3DXToRadian(Roll))
Debug "-----RESULT AFTER ROTATION-----"
Debug Matrix\_11
Debug Matrix\_12
Debug Matrix\_13
Debug Matrix\_21
Debug Matrix\_22
Debug Matrix\_23
Debug Matrix\_31
Debug Matrix\_32
Debug Matrix\_33
;- Berechnung
theta.f = ATan2(Matrix\_33,Matrix\_31)+#PI
phi.f = ATan2(Sin(theta)*Matrix\_31+Cos(theta)*Matrix\_33, -Matrix\_32)
ksi.f = ATan2(Cos(theta)*Matrix\_11-Sin(theta)*Matrix\_13,-Cos(theta)*Matrix\_21+Sin(theta)*Matrix\_23)
Debug ""
Debug "yaw " + StrF(D3DXToDegree(theta))
Debug "pitch " + StrF(D3DXToDegree(phi))
Debug "roll " + StrF(D3DXToDegree(ksi))
Debug ""
Yaw.f = D3DXToDegree(theta)
Pitch.f = D3DXToDegree(phi)
Roll.f = D3DXToDegree(ksi)
Matrix2.D3DXMATRIX
Matrix2\_11 = 1
Matrix2\_22 = 1
Matrix2\_33 = 1
Matrix2\_44 = 1
D3DXMatrixRotationYawPitchRoll(Matrix2.D3DXMATRIX, D3DXToRadian(Yaw), D3DXToRadian(Pitch), D3DXToRadian(Roll))
Debug "-----RESULT AFTER ROTATION (invers berechnete Transformationswinkel)-----"
Debug Matrix2\_11
Debug Matrix2\_12
Debug Matrix2\_13
Debug Matrix2\_21
Debug Matrix2\_22
Debug Matrix2\_23
Debug Matrix2\_31
Debug Matrix2\_32
Debug Matrix2\_33
CallDebugger
Re: 3 Winkel einer Linie im 3D Raum
Verfasst: 02.01.2011 20:34
von DarkDragon
Hallo,
mpz hat geschrieben:An DarkDragon
auch mitMatrixScaling funktioniert die Formel, allerdings ist es bei DX9 wichtig die Matrixen in der richtigen Reihenfolge zu multiplizieren
Gut möglich. Die Reihenfolge ist aber ja garnicht interessant. Ich wollte damit ja nur klarstellen, dass wenn du weitere Transformationen hast (es muss ja nichtmal Scaling sein, sondern kann auch eine Projektion auf eine Ebene sein o.ä.), ob nun davor oder danach kannst du alles weitere wieder vergessen, die Winkel werden nichtmehr stimmen. Auch mit deiner Reihenfolge funktioniert es nicht, denn es kommt
yaw 319.9946289063
pitch -119.9979858398
roll -69.6847839355
statt
Yaw.f = 320
Pitch.f = -120
Roll.f = -42
raus.
Code: Alles auswählen
;- Beispiele funktioniert nur unter Windows
Structure D3DXMATRIX
_11.f
_12.f
_13.f
_14.f
_21.f
_22.f
_23.f
_24.f
_31.f
_32.f
_33.f
_34.f
_41.f
_42.f
_43.f
_44.f
EndStructure
Structure D3DXVector3
x.f
y.f
z.f
EndStructure
Macro D3DXToDegree(radian) ; radiant in Grad
(radian * 57.29578)
; (radian * 57.295779513082323)
EndMacro
Macro D3DXToRadian(Degree)
(Degree * 0.017453)
; (Degree * 0.017453292519943295)
EndMacro
Import "d3dx9.lib"
D3DXMatrixRotationYawPitchRoll (*pOut.D3DXMATRIX, Yaw.f, Pitch.f, Roll.f)
D3DXVec3TransformNormal (*pOut.D3DXVector3, *pV.D3DXVector3, *pM.D3DXMATRIX)
D3DXMatrixScaling(*Matrix.D3DXMatrix, X.f, Y.f, Z.f)
D3DXMatrixMultiply(*Matrix, *MatrixA, *MatrixB)
EndImport
Matrix.D3DXMATRIX
Matrix\_11 = 1
Matrix\_22 = 1
Matrix\_33 = 1
Matrix\_44 = 1
Yaw.f = 320
Pitch.f = -120
Roll.f = -42
D3DXMatrixRotationYawPitchRoll(Matrix.D3DXMATRIX, D3DXToRadian(Yaw), D3DXToRadian(Pitch), D3DXToRadian(Roll))
D3DXMatrixScaling(MatrixScaling.D3DXMatrix, 1.0, 3.0, 1.0)
D3DXMatrixMultiply(Matrix, MatrixScaling, Matrix)
Debug "-----RESULT AFTER ROTATION-----"
Debug Matrix\_11
Debug Matrix\_12
Debug Matrix\_13
Debug Matrix\_21
Debug Matrix\_22
Debug Matrix\_23
Debug Matrix\_31
Debug Matrix\_32
Debug Matrix\_33
;- Berechnung
theta.f = ATan2(Matrix\_33,Matrix\_31)+#PI
phi.f = ATan2(Sin(theta)*Matrix\_31+Cos(theta)*Matrix\_33, -Matrix\_32)
ksi.f = ATan2(Cos(theta)*Matrix\_11-Sin(theta)*Matrix\_13,-Cos(theta)*Matrix\_21+Sin(theta)*Matrix\_23)
Debug ""
Debug "yaw " + StrF(D3DXToDegree(theta))
Debug "pitch " + StrF(D3DXToDegree(phi))
Debug "roll " + StrF(D3DXToDegree(ksi))
Debug ""
Yaw.f = D3DXToDegree(theta)
Pitch.f = D3DXToDegree(phi)
Roll.f = D3DXToDegree(ksi)
Matrix2.D3DXMATRIX
Matrix2\_11 = 1
Matrix2\_22 = 1
Matrix2\_33 = 1
Matrix2\_44 = 1
D3DXMatrixRotationYawPitchRoll(Matrix2.D3DXMATRIX, D3DXToRadian(Yaw), D3DXToRadian(Pitch), D3DXToRadian(Roll))
Debug "-----RESULT AFTER ROTATION (invers berechnete Transformationswinkel)-----"
Debug Matrix2\_11
Debug Matrix2\_12
Debug Matrix2\_13
Debug Matrix2\_21
Debug Matrix2\_22
Debug Matrix2\_23
Debug Matrix2\_31
Debug Matrix2\_32
Debug Matrix2\_33
CallDebugger
Außerdem kannst du die Gerade ja an ihrer eigenen Achse drehen, wesshalb du nie alle 3 Winkel nur anhand der Geraden und der Matrix errechnen könntest, sondern du bräuchstes noch einen Vektor wie du selbst erkannt hast:
mpz hat geschrieben:grossen Dank an Gnasen der mit mir diese Matrix-Lösung in Kleinarbeit hinbekommen hat. Hier gibt es aber verschiedene "Winkelmöglichkeiten" die die selbe Matrix erzeugt. Daher kommt nicht der "gleiche" Winkel raus sondern eine YawPitchRoll Mischung die die gleiche Matrix erzeugen. In der Praxis funktioniert das super.
Doch ob das in der Praxis so immer funktionieren wird bezweifel ich stark. Angenommen du willst dass eine menschliche Figur nach vorne schaut, dann kann der Kopf oben, links, rechts, unten, einfach überall sein und das wählst du mit dieser Methode praktisch willkürlich aus.
Re: 3 Winkel einer Linie im 3D Raum
Verfasst: 02.01.2011 20:52
von mpz
Hi Darkdragon,
im Detail muss ich mich geschlagen geben. Ich habe "Dein Scaling" in einem Praktischen Beispiel eingeben und da hat es auch gut funktioniert. Das Obejekt sah zwar verzerrt aus wurde aber trotzdem korrekt gezeichnet. Für meine Funktion ist die Formel absolut aussreichend und ich werde bei Lookat eh nichts verzerren
Gruß Michael