Laden...

Matrix3D - Affine Transformation

Erstellt von PhilHol vor 12 Jahren Letzter Beitrag vor 12 Jahren 5.755 Views
P
PhilHol Themenstarter:in
82 Beiträge seit 2007
vor 12 Jahren
Matrix3D - Affine Transformation

Hallo MyCSharp Team,

Zur Zeit arbeite ich mit der Matrix3D und Vector3D Klasse der PresentationCore Library.

Mein Ziel ist eine "echte" Affine Transformation, in der ich auf Basis von relativen Vektoren absolute Koordinaten berechne, indem ich eben die Koordinaten transformiere.

Jetzt ist es aber so, daß ich einfach nicht auf die gleichen Werte wie meine Excel Berechnungen komme. Als Validierung verwende ich AutoCAD. Wenn ich im AutoCAD eine Drehung ausführe, und sie mithilfe der "Rotate" Funktion von Matrix3D nachmache, ist der resultierte Vektor nicht identisch.

Verwende ich die Matrix3D Klasse falsch oder was für Tipps habt ihr für den Umgang damit?

[Edit] Als Beispiel:
Im AutoCAD einen Block, mit
1 / 1 / 1
gezeichnet und ihn nach X um 10° und nach Z um 10° gedreht ergibt:
0,8112 / 1,3145 / 0,78636

In C# hab ich adäquat folgendes versucht:

            Matrix3D testMatrix = new Matrix3D();
            testMatrix.Rotate(new Quaternion(new Vector3D(1, 0, 0), 10));
            testMatrix.Rotate(new Quaternion(new Vector3D(0, 0, 1), 10));

            Point3D inputPoint = new Point3D(1, 1, 1);
            Point3D outputPoint = new Point3D();

            MatrixTransform3D outputTest = new MatrixTransform3D();
            outputTest.Matrix = testMatrix;

            outputTest.TryTransform(inputPoint, out outputPoint);

Das Ergebnis ist:
0,84395 / 0,97248 / 1,158455
[/Edit]

Vielen Dank

[Edit2]
Oder weiß vllt jemand eine bessere Lösung. Meine grundlegende Aufgabe:
Gegeben ist ein relativer Vektor eines Stereokamerasystems und dieser Vektor muss zum Fixpunkt des Wagens gebracht werden und dann in das Weltkoordinatensystem. Klingt einfach, ist aber aufgrund der verschiedenen Verdrehungen (roll / pitch / heading) nicht so einfach ..
[/Edit2]

lg
Phil

5.657 Beiträge seit 2006
vor 12 Jahren

Hallo, ehrlich gesagt, finde ich das Ganze ziemlich wirr. Du schreibst, daß du in AutoCad einen "Block" drehst, erklärst aber, wie du einen Normalenvektor drehst. Wie dreht man etwas "nach" X bzw. Y, man dreht doch im Normalfall um eine Achse.
Und überhaupt: Ist eine affine Transformation wirklich geeignet, um die Prokjektion einer Stereokamera zu berechnen? Dabei geschieht ja eine perspektivische Verzerrung, deshalb reicht eine affine Transformation schon nicht mehr aus (siehe auch Photogrammetrie).
Im Code-Beispiel solltest du bei deiner Berechnung zumindest mit einer Identitätsmatrix anfangen, nicht mit einer leeren Matrix (Matrix3D.Identity Property ). Ein extra Transformations-Objekt brauchst du übrigens nicht, man kann Vektoren und Matrizen einfach miteinander multiplizieren.

Weeks of programming can save you hours of planning

P
PhilHol Themenstarter:in
82 Beiträge seit 2007
vor 12 Jahren

OK, sry .. ich versuch's noch mal weniger wirr zu schreiben ^^

Also gegeben ist ein Stereokamerasystem.. Die Parameter besitze ich alle um erfolgreich transformieren zu können (also die Verdrehungen und Transformationen). Und aus dem System messe ich einen relativen Vektor zu einem Objekt.

Achja und ich meine nicht den Algorithmus zur Bestimmung des relativen Vektors aus dem Bild heraus, sondern dieser Vektor ist schon vorhanden, er muß "lediglich" in absolute Weltkoordinaen gebracht werden.

Und die Aufgabe meines Systems wäre die transformation des relativen Vektors zu einer absoluten Koordinate. Wie gesagt die Angaben hab ich alle dafür.

Um zu verdeutlichen, was ich meinte, hab ich im AutoCAD einen Block gezeichnet mit den Maßen 1 / 1 / 1, was einem Vektor 1 / 1 / 1 entspricht. Diesen Block hab ich um die X und dann um die Z Achse um je 10° gedreht und erhalte die oben genannten Werte für die Diagonale des Blocks (also quasi als ob ich den Vektor gedreht hätte) --> 0,8112 / 1,3145 / 0,78636

Das wollte ich 1:1 mittels Matrix3D abbilden, aber irgendwie komm ich nicht auf das gleiche Ergebnis. Ich hab mir schon gedacht, dass es vllt an einem Quadrantenproblem liegt und hab alle Möglichkeiten probiert. Also von 90, 180 und 270 jeweils die 10° dazu oder abgezogen. Das "beste" Ergebnis ist immer noch wenn ich 180 - 10° verwende, nur dann ist x und z gespiegelt negativ --> -0,78636 / 1,3145 / -0,8112

Gibt es für Matrix3D vllt irgendeine genauere Beschreibung außer der MSDN ?

Vielen Dank auf jeden fall schon mal für die Identity Matrix und dem Tipp für die Matrixmultiplikation. Manchmal denk ich einfach zu kompliziert ..

lg

[EDIT]
Wenn ich eine Translation in der Matrix ausführe und nacher den Vektor mit der Matrize multipliziere, wird die Translation nicht berücksichtigt 😦 .. Darum hab ich diesen MatrixTransform3D verwendet .. Warum verwendet der *-operator keine Translation ? Hab per reflector nachgeguckt, er leitet es quasi an die Transform Methode der Matrix3D weiter und die macht einfach keine Translation

5.657 Beiträge seit 2006
vor 12 Jahren

Also auf gut Deutsch, du möchtest einen Normalenvektor um 2 verschiedene Achsen drehen?
Das hat meiner Meinung nach überhaupt nichts mit der Stereokamera zu tun, und könnte sich genauso auf eine normale (Mono-) Kamera beziehen, oder?
Gegeben hast du:

  • Die Ausgangsposition (Kamerastandort)
  • Die Richtung des Vektors in die Szene (durch die Rotation der Kamera)
  • Die Länge des Vektors

Also mußt du nur die Rotationen berechnen, so wie in deinem Code-Beispiel. Wenn du zusätzlich noch weitere Transformationen (z.B. Translation) verwenden möchtest, mußt du es in der richtigen Reihenfolge tun. Also z.B. erst um den Nullpunkt drehen, dann verschieben. Bzw. erst zum Koordinatenursprung verschieben, dann drehen, dann wieder "zurückschieben".

Weitere Infos gibs z.B. hier oder bei Google.

Weeks of programming can save you hours of planning

P
PhilHol Themenstarter:in
82 Beiträge seit 2007
vor 12 Jahren

Hmm .. Im Prinzip ja, sry dass ich dich damit verwirrt habe, ich dachte nur ich erzähl von dem Einsatzzweck damit klar ist, was ich machen will..

Wenn man's genau nimmt ist es aber so, dass die absolute Koordinate in der IMU, also im Fahrzeuginneren gespeichert ist. D.h. ich muss den Vektor vom Kamerastandort aus in die IMU transformieren und dort dann mit der absoluten Koordinate verknüpfen.

Mein Grundlegendes Problem ist aber immer noch, dass egal in welchem Quadranten ich die Rotation durchführe, ich nie zum gleichen Ergebnis komme wie mit AutoCAD.

Gibt es für die Matrix3D Klasse eine vernünftige Anleitung, was genau bei der Rotation passiert? Klar ich kann im dissasembler nachschauen welche Zellen multipliziert werden, aber ich bin, wie man sicher schon gemerkt hat 😉, kein Mathematiker und kann mir das Modell visuell zwar herleiten, aber sollte es mit einer vernünftigen Matrix abbilden

Vielen Dank für deine Hilfe soweit 😃

lg

5.657 Beiträge seit 2006
vor 12 Jahren

Man kann ja AutoCad nicht ohne weiteres mit WPF gleichsetzen. Das geht nur, wenn das gleiche Koordinatensystem verwendet wird (links- bzw. rechtshändig?, welche Achse zeigt nach oben?). Der Vergleich hilft also erstmal nichts. Was dein Code verkehrt macht, weiß ich nicht, denn den behältst du ja für dich. Wie eine Matrix-Transformation (und im Speziellen: die Rotation) funktioniert, ist 1. völlig egal (weil bereits implementiert), und 2. im Internet / im Reflector nachzulesen.

Weeks of programming can save you hours of planning

P
PhilHol Themenstarter:in
82 Beiträge seit 2007
vor 12 Jahren

Mhmm .. OK so wie du klingst schein ich einen völlig falschen Ansatz zu verfolgen kopfkratz

Ich meinte nicht die Rotation an sich als quellcode, sondern wie man sich das vorstellen kann, in welche Richtung es dreht etc.

Anders gefragt... Was würdest du für so eine Transformation verwenden ? Scheinbar nicht die PresentationBase vom WPF ..

Es ist im Moment so, daß wir diese Transformation über eine lange Funktion mit diversen mathematischen Operationen realisiert haben. So jetzt ist da nur irgendwo ein kleiner Fehler drinnen und wie so oft typisch, gibt es den Typen nicht mehr, der diesen Code geschrieben hat. So und meine Aufgabe wäre jetzt, das ganze nachzuvollziehen (ok das geht noch) und einfacher zu programmieren, damit es leichter verwaltbar wird.

Ich dachte mir an sowas z.b.:


// Relativer Vektor von der Kamera zum Objekt
Point3D point = new Point3D(1.257, -0.875, -11.379);
Point3D output;

Matrix3D resFromDll = Matrix3D.Identity;  

// Verdrehung der Kamerawinkel zur IMU einrechnen
resFromDll.Rotate(new Quaternion(new Vector3D(1, 0, 0), 90 - (11 + 0.502)));
resFromDll.Rotate(new Quaternion(new Vector3D(0, 0, 1), -10));

// Kameraoffsets zur IMU
resFromDll.Translate(new Vector3D(-1.236, 0.121, 2.406));

// Verdrehungen nach pitch/nick
resFromDll.Rotate(new Quaternion(new Vector3D(0, 1, 0), -2.133));
resFromDll.Rotate(new Quaternion(new Vector3D(1, 0, 0), -0.502));

// Verdrehung heading
resFromDll.Rotate(new Quaternion(new Vector3D(0, 0, 1), 180 + 95.323));

// Absolute Koordinaten einbeziehen
resFromDll.Translate(new Vector3D(7180.147, 347923.101, 161.904));

output = point*resFromDll;

Das wär der aktuelle Quellcode, der aber nicht genau (paar meter daneben) zum gewünschten Ergebnis kommt (ok das will ich jetzt auch net erfragen, aber wollte eben wissen ob solche Beispiele mit der PresentationCore überhaupt sinnvoll sind ..) ..

5.657 Beiträge seit 2006
vor 12 Jahren

Anders gefragt... Was würdest du für so eine Transformation verwenden ? Scheinbar nicht die PresentationBase vom WPF ..

Im Prinzip würde ich auch mit Matrizen und Vektoren arbeiten. Welche Implementierung man verwendet, ist aber jedem selbst überlassen, und auch nicht wichtig.

So jetzt ist da nur irgendwo ein kleiner Fehler drinnen und wie so oft typisch, gibt es den Typen nicht mehr, der diesen Code geschrieben hat.

Welcher Fehler? Das geht jetzt schon in Richtung [Hinweis] Wie poste ich richtig?, deswegen an dieser Stelle gleich mal ein Hinweis darauf.

Im Prinzip kannst du doch jeden einzelnen Berechnungsschritt auskommentieren, und dann schauen was (nicht) passiert bzw. per Einzelschrittdebugging herausfinden, welche Werte verkehrt sind. Dann solltest du sehr schnell die Fehlerursache eingegrenz haben.

Weeks of programming can save you hours of planning

P
PhilHol Themenstarter:in
82 Beiträge seit 2007
vor 12 Jahren

Na gut, ich schein glaub ich zu viel um den heißen Brei rumzureden.

Ich such seit Tage schon nach einer ausführlichen Beschreibung der Vector3D und Matrix3D Klassen, uzw. nicht nur "M12 is first row, second column" sondern auch deren Bedeutungen usw. Ich dachte, daß ich das hier mal frage und wollte mit dem Beispiel gleich erklären warum ich das suche. Einfach weil beim AutoCAD und beim WPF nicht die gleichen Ergebenise rauskommen. Das Koordinatensystem ist bei beiden gleich, was ich bisher feststellen konnte.

Den Auszug mit dem "Fehler" war jetzt nicht gemeint, daß es darum geht, sondern galt als Hintergrund warum ich überhaupt das Ganze mache. (Quasi als Einleitung des restlichen Codes, den ich zuletzt gepostet habe)

Einzelschrittdebugging verwende ich schon. Ich hänge halt, wie gesagt, schon bei der ersten Rotation, die mir nicht das gleiche auswirft. Bzw. ich nicht weiß, ob die Matrix Rotation z.b. das Quadrantenproblem schon ausmerzt oder in welche Richtung ich drehe wenn ich positiv drehe. Bei der Methode steht "Appends a rotation transform to the current Matrix3D. " und das war's .. Kein Beispiel, keine Zeichnung wie man sich das vorstellen kann oder so. Klar normalerweise braucht man so etwas auch nicht, weil's ja, wie du richtig festgestellt hast, es schon implementiert ist und man es einfach nur verwenden muss. .. Aber gerade bei solchen Funktionen wäre es wichtig zu wissen, was für mathematische Operationen da im Hintergrund ablaufen, um den Input anzupassen

mhmm .. und was ich letztendlich suche ist z.b. ein Beispiel oder eine Referenz, das mir eine saubere Transformationsimplementierung beschreibt anhand der ich debuggen kann. (Aber nicht in 2D, da gibt's genug, das stimmt 😃 )

lg
Phil

5.657 Beiträge seit 2006
vor 12 Jahren

Ich such seit Tage schon nach einer ausführlichen Beschreibung der Vector3D und Matrix3D Klassen, uzw. nicht nur "M12 is first row, second column" sondern auch deren Bedeutungen usw.

Mehr kann man dazu ja auch nicht sagen, denn was in den einzelnen Spalten und Zeilen der Matrix steht, hängt ja schließlich davon ab, welche Berechnung du durchführen möchtest. Matrizen können ja nicht nur für eine Rotation verwendet werden.
Die allgemeinen Infos findest du in dem verlinkten Wikipedia-Artikel, und wie es implementiert ist, mußt du letzendlich gar nicht wissen.

Bzw. ich nicht weiß, ob die Matrix Rotation z.b. das Quadrantenproblem schon ausmerzt oder in welche Richtung ich drehe wenn ich positiv drehe.

Quaternions drehen meiner Meinung nach immer im Uhrzeigersinn (clockwise)! Aber:

Aber gerade bei solchen Funktionen wäre es wichtig zu wissen, was für mathematische Operationen da im Hintergrund ablaufen, um den Input anzupassen

Das hat alles nichts mehr mit Matrizen und Vektoren zu tun, sondern ist ein eher allgemeines Problem. Du könntest dich z.B. mal mit Unit Tests bzw. Test-Driven Development (TDD) auseinandersetzen, das wäre dir sicher eine große Hilfe.

Es würde dann darauf hinauslaufen, daß du einige "Low-Level"-Methoden schreibst, um beispielsweise den Kamera-Vektor zu drehen oder zu verschieben. Dann schreibst du dir Tests für diese Methoden, und wenn nicht der von dir erwartete Wert zurückgegeben wird, beendet der Test mit einem Fehler. Dann hast du entweder einen Denkfehler oder einen Programmierfehler eingebaut. Wenn alle Tests durchlaufen, weißt du auch genau, was in welcher Methode gemacht wird, und hast auch den entsprechenden Überblick, um die übergeordneten Methoden zu schreiben.

Weeks of programming can save you hours of planning