| |
| Gut zu wissen: Hilfreiche Tipps und Tricks aus der Praxis prägnant, und auf den Punkt gebracht für SOLIDWORKS |
| |
| Schulung iMachining, ein Seminar am 14.10.2024
|
Autor
|
Thema: von Rotationsmatrix Drehwinkel berechnen lassen (9737 mal gelesen)
|
zool Mitglied
Beiträge: 7 Registriert: 24.05.2006
|
erstellt am: 27. Mai. 2006 18:54 <-- editieren / zitieren --> Unities abgeben:
|
PaulSchuepbach Mitglied Programmierer
Beiträge: 1005 Registriert: 01.10.2003
|
erstellt am: 28. Mai. 2006 21:08 <-- editieren / zitieren --> Unities abgeben: Nur für zool
Hallo Zool, mit einem SWX-Beispiel kann ich nicht dienen - aber mit einem aus Inventor: Sub GetAngles() Dim oDoc As AssemblyDocument Set oDoc = ThisApplication.ActiveDocument Dim oOcc As ComponentOccurrence Set oOcc = oDoc.ComponentDefinition.Occurrences(2) Dim oMat As Matrix Set oMat = oOcc.Transformation Dim aRotAngles(2) As Double Call CalculateRotationAngles(oMat, aRotAngles) End Sub Private Sub CalculateRotationAngles(ByVal oMatrix As Inventor.Matrix, ByRef aRotAngles() As Double) Const PI = 3.14159265358979 Const TODEGREES As Double = 180 / PI Dim dB As Double Dim dC As Double Dim dNumer As Double Dim dDenom As Double Dim dAcosValue As Double Dim oRotate As Inventor.Matrix Dim oAxis As Inventor.Vector Dim oCenter As Inventor.Point Set oRotate = ThisApplication.TransientGeometry.CreateMatrix Set oAxis = ThisApplication.TransientGeometry.CreateVector Set oCenter = ThisApplication.TransientGeometry.CreatePoint oCenter.X = 0 oCenter.Y = 0 oCenter.Z = 0 ' Choose aRotAngles[0] about x which transforms axes[2] onto the x-z plane dB = oMatrix.Cell(2, 3) dC = oMatrix.Cell(3, 3) dNumer = dC dDenom = Sqr(dB * dB + dC * dC) ' Make sure we can do the division. If not, then axes[2] is already in the x-z plane If (Abs(dDenom) <= 0.000001) Then aRotAngles(0) = 0# Else If (dNumer / dDenom >= 1#) Then dAcosValue = 0# Else If (dNumer / dDenom <= -1#) Then dAcosValue = PI Else dAcosValue = Acos(dNumer / dDenom) End If End If aRotAngles(0) = Sgn(dB) * dAcosValue oAxis.X = 1 oAxis.Y = 0 oAxis.Z = 0 Call oRotate.SetToRotation(aRotAngles(0), oAxis, oCenter) Call oMatrix.PreMultiplyBy(oRotate) End If ' Choose aRotAngles[1] about y which transforms axes[3] onto the z axis If (oMatrix.Cell(3, 3) >= 1#) Then dAcosValue = 0# Else If (oMatrix.Cell(3, 3) <= -1#) Then dAcosValue = PI Else dAcosValue = Acos(oMatrix.Cell(3, 3)) End If End If aRotAngles(1) = Math.Sgn(-oMatrix.Cell(1, 3)) * dAcosValue oAxis.X = 0 oAxis.Y = 1 oAxis.Z = 0 Call oRotate.SetToRotation(aRotAngles(1), oAxis, oCenter) Call oMatrix.PreMultiplyBy(oRotate) ' Choose aRotAngles[2] about z which transforms axes[0] onto the x axis If (oMatrix.Cell(1, 1) >= 1#) Then dAcosValue = 0# Else If (oMatrix.Cell(1, 1) <= -1#) Then dAcosValue = PI Else dAcosValue = Acos(oMatrix.Cell(1, 1)) End If End If aRotAngles(2) = Math.Sgn(-oMatrix.Cell(2, 1)) * dAcosValue 'if you want to get the result in degrees aRotAngles(0) = aRotAngles(0) * TODEGREES aRotAngles(1) = aRotAngles(1) * TODEGREES aRotAngles(2) = aRotAngles(2) * TODEGREES End Sub Public Function Acos(value) As Double Acos = Math.Atn(-value / Math.Sqr(-value * value + 1)) + 2 * Math.Atn(1) End Function
In diesem Beispiel werden die 3 Drehwinkel der 2. Instanz (s. Set oOcc = oDoc.ComponentDefinition.Occurrences(2)) berechnet. Den Rest solltest Du aus dem Code ableiten können.
Falls Du was nicht verstehst, melde Dich einfach. Grüsse, Paul
www.morecam.ch www.thinkcad.de (...jetzt auch für SWX...) [Diese Nachricht wurde von PaulSchuepbach am 29. Mai. 2006 editiert.] Eine Antwort auf diesen Beitrag verfassen (mit Zitat/Zitat des Beitrags) IP |
zool Mitglied
Beiträge: 7 Registriert: 24.05.2006
|
erstellt am: 31. Mai. 2006 12:42 <-- editieren / zitieren --> Unities abgeben:
Hallo PaulSchuepbach, sorry für die späte Meldung und danke erstmal für deine Funktion. Ich verstehe zwar was da passiert und habe es in SolidWorks zum laufen gebracht, nur die einzelnen math. Berechnungen sind mir nicht ganz klar. Zum Beispiel ist mir folgende Berechnung ' Choose aRotAngles[0] about x which transforms axes[2] onto the x-z plane dB = oMatrix.Cell(2, 3) dC = oMatrix.Cell(3, 3) dNumer = dC dDenom = Sqr(dB * dB + dC * dC) nicht ganz klar. Warum wird da aus der Zeile y und Zeile z der Matrix die Werte genommen und multipliziert und anschließend die Wurzel gezogen? Ist bei Inventor die Matrix identisch mit SW? Die 1. Zeile ist die x-Achse, 2.Zeile die y-Achse und 3.Zeile die Z-Achse. Zusätzlich sind dann noch die Translationswerte und der Scalierungsfaktor im Array enthalten die aber hierfür nicht von Bedeutung sind. Die Ergebnisse machen mich etwas stutzig da sie nicht mit dem übereinstimmen was ich raus haben müsste. Meist kommt 0, 90, -180 oder -90 Grad raus. Die Rotationsmatrix ist sie als Gesamtmatrix zu betrachten oder ist das ne einzelne Matrix? Also es gibt ja 3 Rotationsmatrizen. Für jede Achse eine. Und die kann man ja zusammen multiplizieren und man bekommt die Gesamtmatrix aus der man die 3 Drehwinkel berechnen kann. Wenn es sich bei der Rotationsmatrix allerdings nicht um die Gesamtmatrix handelt, dann weis ich noch immer keinen Weg um die Winkel zu berechnen. Habe zwar was gefunden um aus zwei Vektoren einen Winkel zu berechnen aber auch da komme ich nicht auf richtige Ergebniss. Eine Antwort auf diesen Beitrag verfassen (mit Zitat/Zitat des Beitrags) IP |
jens_oliver Mitglied Softwareentwickler
Beiträge: 114 Registriert: 28.06.2005
|
erstellt am: 31. Mai. 2006 13:54 <-- editieren / zitieren --> Unities abgeben: Nur für zool
|
zool Mitglied
Beiträge: 7 Registriert: 24.05.2006
|
erstellt am: 01. Jun. 2006 08:33 <-- editieren / zitieren --> Unities abgeben:
Hallo jens_oliver, danke erstmal für Deine Hilfe. Mir ist das mit den Euler Winkeln bekannt. Leider gibt es aber auch noch Cardan-Winkel und nirgens steht ob Solid Works eine Gesamt-Matrix nach dem Prinzip R = R ω* R ϕ* Rκ oder nach Euler Z*X*Z hat. Bei beiden Möglichkeiten spielt die Reihenfolge eine Rolle und dadurch entstehen x Möglichkeiten die man durchtesten müsste. Ich muss halt die richtigen Winkel mehrerer Bauteile aus SolidWorks auslesen um in einem anderen System (wo nur 3 Funktionen zur Rotation und eine zur Translation zur Verfügung stehen) diese Bauteile wieder zusammensetzen zu können. Wenn ich die Translation zuerst mache und dann ein bissl probiere mit den Winkeln dann passen die Bauteile auch wieder zusammen im anderen System, nur leider bräuchte ich die Winkel ausgelesen/berechnet um ein Automatismus zu programmieren. Momentan habe ich die Reihenfolge x,y,z und z,y,x erfolglos probiert mit mehreren Varianten der Gesamtmatrix (also x*y*z und z*y*x). Allerdings habe ich z*x*z noch nicht getestet. Dadurch das die drei Funktionen aus dem anderen System hintereinander ausgeführt werden, könnte das mit den EulerWinkel schon sein. Wenn ich das richtig verstanden habe müsste also erst eine z-Drehung, dann eine x`-Drehung und dann wieder eine z``-Drehung erfolgen. Weis jemand wie die Rotationsmatrix von Solid Works zusammengesetzt ist? In der API-Help steht halt nur drin, das 1.Zeile x, 2.Zeile y und 3.Zeile z ist. Muss die Translation eigentlich vor den Rotationen erfolgen oder spielt das keine Rolle? Eine Antwort auf diesen Beitrag verfassen (mit Zitat/Zitat des Beitrags) IP |
jens_oliver Mitglied Softwareentwickler
Beiträge: 114 Registriert: 28.06.2005
|
erstellt am: 01. Jun. 2006 09:39 <-- editieren / zitieren --> Unities abgeben: Nur für zool
Hallo, man kann sich die Transformationsmatrix als eine Art Anweisungsvorschrift vorstellen, also Drehung um bestimmte Achsen und eine Verschiebung. Ich stelle sie mir aber meistens als Koordinatensystem vor, welches durch die drei Achsen in seiner Orientierung definiert ist und der Ursprung die Verschiebung ist. Dann musst du nämlich nicht wissen um welche Achsen SW dreht sondern nur wissen wie Dein neues System dreht. Wenn das neue System Eulerwinkel benutzt berechne diese, wenn Kardanwinkel dann berechne Dir die Kardanwinkel aus der Transformationsmatrix. SW liefert dir ja nur das Ergebnis und nicht die Winkel. Befindet sich dein Bauteil vor der Transformation im neuen System nicht im Ursprung, dann verschiebt sich dein Bauteil durch die Drehungen. Um das Bauteil nun an die richtige Position zu bekommen musst du Dir die neue Position (nach den Drehungen) berechnen und diese von der Verschiebung der Transformationsmatrix abziehen. Um diesen Vektor verschiebst du dann das Bauteil noch. Gruß Oliver Knepper
------------------ Software nach Maß für Ihr CAD-System www.ib-knepper.de Eine Antwort auf diesen Beitrag verfassen (mit Zitat/Zitat des Beitrags) IP |
zool Mitglied
Beiträge: 7 Registriert: 24.05.2006
|
erstellt am: 01. Jun. 2006 10:14 <-- editieren / zitieren --> Unities abgeben:
Hallo, um die EulerWinkel oder CardanWinkel zu berechnen muss man aber die Definition der Rotationsmatrix kennen von SW (also ob es sich um eine Gesamtmatrix handelt die in der Reihenfolge x*y*z berechnet wurde oder z*y*x oder wie auch immer). Woher weis ich sonst aus welcher Zeile und Spalte ich z.B. den Winkel x rausbekomme? Unter [URL=http://www.fh-bochum.de/fb5/photo/scripte/pdfs/normalfach/2005-10-21%20Vorlesung%20Photogrammetrie%20I.pdf][/URL] ist z.B. beschrieben, das sin x = a13 ist. Ich habe auch noch im Netz was gefunden, dass man aus zwei Vektoren einen Winkel berechnen kann. Weis aber nicht ob der geht. Dann habe ich noch eine Formel zu Drehwinkel gefunden die lautet: 2cos phi + 1 = Spur A (Spur A = a11 + a22 + a33 : also die Diagonale) bzw. phi = acos((a11+a22+a33)-1/2) Frag mich wie man dann noch die anderen zwei Winkel rausbekommt... In der Hilfe des neuen Systems habe ich übrigens folgendes gefunden: "Rotationen und Verschiebungen werden immer vom Koordinatenurprung aus berechnet. Es ist durchaus von Bedeutung, ob zuerst eine Rotation und dann eine Verschiebung ausgeführt werden soll oder umgekehrt."
Eine Antwort auf diesen Beitrag verfassen (mit Zitat/Zitat des Beitrags) IP |
jens_oliver Mitglied Softwareentwickler
Beiträge: 114 Registriert: 28.06.2005
|
erstellt am: 01. Jun. 2006 11:54 <-- editieren / zitieren --> Unities abgeben: Nur für zool
Hi, ich bin kein Mathematiker, aber ich glaube nicht das das Ergebnis (Rotationsmatrix) abhängig ist von dem Weg den man benutzt. Meiner Meinung nach gilt: R=R(euler1,z)*R(euler2,x)*R(euler3,z) = R(x)*R(y)*R(z)=… „Eine Rotation und Verschiebung wird immer vom Koordinatenursprung aus berechnet.“ Das bedeutet dass du die Formeln (sin x = a13, Vorlesungsscript) so nicht benutzen kannst, da die Gesamtdrehung um mitgedrehte Achsen durchgeführt wird. Da dein neues System nur um die Ursprungsachsen dreht benötigst du andere Winkel (habe leider keine Formel gefunden). Gruß Oliver Knepper
------------------ Software nach Maß für Ihr CAD-System www.ib-knepper.de Eine Antwort auf diesen Beitrag verfassen (mit Zitat/Zitat des Beitrags) IP |
zool Mitglied
Beiträge: 7 Registriert: 24.05.2006
|
erstellt am: 02. Jun. 2006 08:11 <-- editieren / zitieren --> Unities abgeben:
Hi, ich bin auch kein Mathematiker aber ne Lösung brauche ich dennoch... Die für ein Bauteil erhaltene Rotationsmatrix von SolidWorks sieht z.B. so aus: 1,22460635382235e-16 1 -6,99745080729426e-15 -1 1,22460635382235e-16 -1,44840850751452e-17 -1,44840850751444e-17 6,99745080729426e-15 1 Daraus bräuchte ich halt die Winkel berechnet. Die obige Funktion bringt zwar Ergebnisse aber die können irgendwie nicht stimmen.
Die Ausgabe der Matrix erhält man über:
Code:
Dim swApp As Object Dim activeDocument As ObjectDim selEntity As Object Dim selType As Long Dim SelMgr As Object Dim owningComponent As Object Dim componentName As String Const swDocPART = 1 Const swDocASSEMBLY = 2 Const swSelEDGES = 1 Const swSelFACES = 2 Const swSelCOMPONENTS = 20 Const swSelVERTICES = 3 Sub main() Set swApp = CreateObject("SldWorks.Application") Set activeDocument = swApp.ActiveDoc ' Make sure this is assembly If (activeDocument.GetType <> swDocASSEMBLY) Then Exit Sub End If ' Get the SelectionMgr interface Set SelMgr = activeDocument.SelectionManager ' Check the selected object type selType = SelMgr.GetSelectedObjectType2(1) ' If item is face, edge or vertex If ((selType = swSelFACES) Or _ (selType = swSelEDGES) Or _ (selType = swSelVERTICES)) Then ' Obtain the selected Entity object Set selEntity = SelMgr.GetSelectedObject3(1) ' Get the owning Component object Set owningComponent = selEntity.GetComponent Else If (selType = swSelCOMPONENTS) Then Set owningComponent = SelMgr.GetSelectedObject3(1) Else Exit Sub End If End If 'Get the Component Name componentName = owningComponent.Name Transform = owningComponent.GetXform
Vielleicht hat ja jemand noch ne Idee für mich.
Eine Antwort auf diesen Beitrag verfassen (mit Zitat/Zitat des Beitrags) IP |
jens_oliver Mitglied Softwareentwickler
Beiträge: 114 Registriert: 28.06.2005
|
erstellt am: 02. Jun. 2006 14:20 <-- editieren / zitieren --> Unities abgeben: Nur für zool
Hi, ich habe noch ein wenig gegoogelt. Ich glaube du brauchst die yaw, pitch und roll Winkel, da diese sich ja auf die Hauptachsen beziehen. Leider ist das Ergebnis (Rotationsmatrix->Winkel) nicht eindeutig und es sind einige Fallunterscheidungen zu machen. Hier eine Berechnung der Winkel die ich gefunden habe, die aber wohl nicht immer gültig ist. c[3,3]=Rotationsmatrix Winkel x=arctan(c32/c33) Winkel y=arctan(-c31/sqrt(c32*c32+c33*c33)) Winkel z=arctan(c21/c11) Komischerweise lieferte die Formel beim testen nur die richtigen Ergebnisse wenn man zuerst um Z dann um Y und dann um X dreht. Ich hatte erwartet dass die Reihenfolge genau umgekehrt ist. Gruß Oliver Knepper
------------------ Software nach Maß für Ihr CAD-System www.ib-knepper.de Eine Antwort auf diesen Beitrag verfassen (mit Zitat/Zitat des Beitrags) IP |
zool Mitglied
Beiträge: 7 Registriert: 24.05.2006
|
erstellt am: 02. Jun. 2006 15:36 <-- editieren / zitieren --> Unities abgeben:
Hi Oliver, also erstmal nochmal vielen Dank für Deine Bemühungen!!! Ich habe nun rausgefunden, wie die SolidWorks Matrix berechnet wird und das bestätigt Deine Verwunderung mit Zitat: zuerst um Z dann um Y und dann um X
. Also die Matrix wird tatsächlich mit einer Gesamtmatrix ZYX berechnet. Durch Matrizenmultiplikation von M=Mz*My*Mx kommt man auf die Gesamtmatrix. Irgendwo habe ich gelesen, das die Rotation rückwärts gerechnet werden muss und deshalb handelt es sich trotzdem um eine x->y->z-> Rotation. Diese sieht so aus: cos(q)cos(k) cos(q)-sin(k) sin(q) (sin(k)cos(w))+(-sin(w)-sin(q)cos(k)) (cos(k)cos(w))+(-sin(w)-sin(q)-sin(k)) cos(q)-sin(w) (sin(k)sin(w))+(cos(w)-sin(q)cos(k)) (sin(w)cos(k))+(-sin(q)-sin(k)cos(w)) cos(q)cos(w) w steht für den x-Winkel q steht für den y-Winkel k steht für den z-Winkel
Allerdings kann man nur die Matrize nachfolziehen wenn ein Bauteil im Koordinatenursprung ist (0,0,0) und man dann einfach mal eine Drehung des Bauteils macht. Ich habe dabei festgestellt, wenn mann erst für x 1 Grad und für y 1 Grad eingibt und dann nochmal 1 Grad für z, so kommt was anderes heraus als wenn ich gleich jeweils um 1 Grad rotieren lasse.
Also müsste SW immer vom letzten Ursprung ausgehen... Wenn ich jetzt Deine gefundenen Winkelberechnungen mir anschaue: -sin(w)cos(q) ------------- = arctan(-c32/c33) ; sollte stimmen für Winkel x, nur eventuell mit - davor ??? cos(w)cos(q) Beim Winkel y würde ich sagen stimmt es nicht. Da müsste eigentlich laut der Gesamtmatrix hin c13=sin(q). Und beim Winkel z müsste eigentlich hin: -sin(k)cos(q) -------------- = arctan(-c12/c11) cos(k)cos(q) Könnte das sein? Habs noch nicht getestet... Eine Antwort auf diesen Beitrag verfassen (mit Zitat/Zitat des Beitrags) IP |
zool Mitglied
Beiträge: 7 Registriert: 24.05.2006
|
erstellt am: 14. Jun. 2006 10:35 <-- editieren / zitieren --> Unities abgeben:
Zur Ergänzung: Die Matrix stimmt und die Winkel auch. Aber leider nur im Bereich -90° <= a <= 90° für asin und -90 < a < 90° für die zwei berechneten atan Winkel. Das Problem mit dem atan lässt sich über die atan2 Funktion lösen, die die Vorzeichen von cosinus und sinus beachtet.
Funktion lautet so: Public Function atan2mod(ByVal y As Double, ByVal x As Double) As Double Dim PI As Double PI = Atn(1) * 4 'PI If x > 0 Then atan2mod = Atn(y / x) ElseIf x < 0 And y >= 0 Then atan2mod = PI + Atn(y / x) ElseIf x < 0 And y < 0 Then atan2mod = -PI + Atn(y / x) ElseIf x = 0 Or y = 0 Then atan2mod = 0 End If End Function Das Problem mit den Quadranten für den Winkel q (=y) konnte ich leider noch nicht lösen. Ich bräuchte den cosinus eigentlich dafür zwecks Vorzeichen. Nur aus der Matrix bekommt man den nicht wirklich raus
Eine Antwort auf diesen Beitrag verfassen (mit Zitat/Zitat des Beitrags) IP |