Jump to content

Mein IMU-Brick rotiert


Plenz

Recommended Posts

Die Frage ist ob es möglich ist das ganze in einem nciht gimbal-lock-freien, aber dafür einfachen Koordinatensystem anzugeben. Weil im Endeffekt geben die Quaternionen ja die neue Position des USB (oder welcher Seite auch immer) an, aber eben nur nicht eindeutig. Das heißt es gibt mehrere Varianten die gleiche Lage zu beschreiben, allerdings versteht das keiner (mich eingeschlossen) ^^

 

Ich weiß daher auch nicht, ob es ohne weiteres möglich ist die mehrdeutigen Quaternionen in eindeutige "gimbal-lock" Koords umzurechnen. Wäre okay, wenn es ginge, weil viele das Gimbal-Lock nicht stört.

Link to comment
Share on other sites

  • Replies 51
  • Created
  • Last Reply

Top Posters In This Topic

Top Posters In This Topic

Posted Images

@ThomasKI: Damit stellst du aber nur 2 Achsen dar oder? Also wenn ich den IMU Brick jetzt vor mir halte und um die Y Achse drehe verändert sich die Position des USB Steckers ja nicht!

 

Wenn ich jetzt her gehe und zusätzlich zum Vektor (x,y,z) des USB Steckers auch noch eine Drehung angebe um diesen Vektor, dann habe ich Quaternionen!!!! ;D

 

Edit: Vielleicht sollte ich das mit USB Stecker als Bezungspunkt trotzdem mal durchrechnen und dann so bezeichnen, also Position des USB Steckers in eine Würfel mit Ausmaß 1 und Drehung um diesen Vektor. Dann hab ich immernoch eine Darstellung die ich 1:1 wieder zu dem Quaternion umrechnen kann und zurück, aber vielleicht ists einfacher zu benutzen? Das gucke ich mir morgen mal an, kann eigentlich gar nicht schwer sein, ich tue das im Brick Viewer ja quasi schon.

Link to comment
Share on other sites

kann eigentlich gar nicht schwer sein, ich tue das im Brick Viewer ja quasi schon.

Genau! Diese Quaterdinger interessieren mich nämlich überhaupt nicht, mich interessiert nur die Verdrehung gegenüber der Horizontalen. Und die sieht man im Brick Viewer ganz hervorragend.

 

Anbei ein paar Screenshots:

1.) Der IMU-Brick liegt flach auf dem Tisch

2.) Der IMU-Brick um 45° nach rechts gekippt (links hoch, rechts runter)

3.) Den gekippten IMU-Brick um 90° auf den Tisch nach rechts gedreht

4.) Den gekippten IMU-Brick um weitere 90° auf den Tisch nach rechts gedreht

 

Die grafische Darstellung ist im Grunde genommen immer die selbe: ich sehe den IMU-Brick um 45° nach rechts (um die Achse des USB-Steckers) gekippt. Unabhängig von allen anderen Winkeln! Unabhängig von der Drehrichtung!

 

Alles, was ich brauche, ist eine Formel, die mir diese "45°" ausspuckt, und zwar für alle Screenshots 2.) bis 4.) und natürlich noch eine zweite Formel für das Kippen nach vorn/hinten.

 

Die jetzt in der Doku eingebauten drei Formeln liefern das jedenfalls nicht, ich habe es gerade getestet.

IMUx4.png.f4226a57865f7f5c37928e1356130152.png

Link to comment
Share on other sites

Wenn ich es richtig verstanden habe besteht ein Quaternion im Prinzip aus zwei Elementen einem Richtungsvektor (x,y,z) und einem Winkel (w). Den Richtungsvektor kann man sich nun als einen Pfeil auf der Platine vorstellen z.B. vom Mittelpunkt der Platine zur USB Buchse.

x,y,z  sind jetzt Koordinaten in einem äußeren Koordinatensystem, dessen Ursprung mit dem Mittelpunkt der Platine zusammenfällt.

Um nun zu einer mittels xyzw vorgegebenen Position zu kommen kann ich zwei Wege gehe entweder ich drehe erst die Platine um den winkel w, die Drehachse ist dabei der aufgezeichnete Pfeil und bewege dann die USB Buchse zur mit xyz angegebenen Position ohne dass sich der Mittelpunkt verschiebt,

oder ich bewege erst die USB Buchse und drehe dann um den angegebenen Winkel.

Die Koordinaten beziehen sich aber immer auf ein festes Äußeres koordinatensystem also z.b. x=nord y=süd

 

Wenn ich richtig verstanden habe was Plenz möchte, dann ist ihm das äußere Koordinatensystem relativ egal und er ist nur an den beiden Winkeln zur Z-Achse interessiert, 

Das ist einmal der Winkel USBBuchse-Mittelpunkt-äußereZAchse und einmal StackVerbinder-Mittelpunkt-außereZAchse

 

der erste Winkel ist einfach da es der Winkel zwischen den Vektoren (x,y,z) und (0,0,1)

 

um den zweite Winkel zu berechnen muss man erst den Vektor (a,b,c) ableiten der senkrecht auf dem Richtungsvektor steht und den winkel w erfüllt, dass ist vermutlich etwas mehr Aufwand, da fällt mir spontan auch keine einfache Ableitung ein.

 

Insgesamt wäre es mal interessant zu wissen wie xyzw aussehen wenn man neu kalibriert hat, ist es möglich die Orientierung des Richtungsvektor zur Platine selbst bestimmen oder wird da immer mit dem gleichen gerechnet.

 

EDIT:

In der Docu sind ja beispiele genannt um einen vektor zu transformieren, also um plenz anforderung zu erfüllen muss einmal der Vektor (1,0,0) transformiert werden und einmal der Vektor (0,1,0) bestimmt man nun für jeden der beiden transformierten vektoren den winkel zur zAchse (0,0,1) sollte das Problem eigentlich gelöst sein.

Link to comment
Share on other sites

der winkel w zwischen zwei vektoren (a,b,c) und (x,y,z) lässt sich mit

 

w = acos((a*x+b*y+c*z)/(sqrt(a*a+b*b+c*c)*sqrt(x*x+y*y+z*z)))

 

berechnen

wenn a=b=0 und c=1 ergibt sich

 

w = acos(z/sqrt(x*x+y*y+z*z)))

 

 

was aus der Documentation nicht ganz klar wird, ist in welche Richtung die angegeben Transformation abläuft also vom äußerem Koordinatensytsem (festgelegt bei der Kalibration) zu Koordinaten relativ zur Platine oder anders herum

Link to comment
Share on other sites

Der Winkel hängt natürlich von dem bei der Kalibration gesetzten Richtungsvektor ab, wo der tatsächlich liegt weiß ich nicht, der einfachheithalber habe ich die USBBuchse angenommen.

 

aber das nach oben berechnete w sollte konstant sein wenn du das Brick um die ZAchse drehst, wenn ich dich richtig verstanden habe ist dem so oder?

Link to comment
Share on other sites

Es wäre schön wenn Z nach oben gerichtet wäre, dann würde es nicht immer von +-180 schwanken... eine Schwankung um +-0 ist einfacher zu verarbeiten.

 

Im Moment ist bei mir RPY 0,0,0 der Brick auf dem Kopf liegend mit X-Achse(+) nach Norden. Schöner wäre es 180 grad gedreht also -X Achse nach Süden. Eine Drehung um Z Achse sollte dann eindeutig von 0 bis +-180 laufen oder besser noch von 0 bis zu 360.

 

Wie wäre es mit einer Kompasumrechnung Drehung von Norden weg in nur einer Ebene?

Ansonsten sollte es eine eindeutige Drehungsangabe für die XY Ebene geben.

 

Edit: Die Drehung um Brickmitte finde ich gut.

Link to comment
Share on other sites

aber das nach oben berechnete w sollte konstant sein wenn du das Brick um die ZAchse drehst, wenn ich dich richtig verstanden habe ist dem so oder?

Nein, leider nicht.

 

Ich habe heute noch mal zwei Versuche gemacht:

1.) IMU-Brick waagerecht gelegt und langsam um 360° gedreht

2.) IMU-Brick ca. 45° gekippt und langsam um 360° gedreht

Mit "gekippt" meine ich: USB-Stecker runter, LEDs rauf.

 

Beim Drehen (per Hand) habe ich x,y,z,w mitgeloggt.

Diese Werte habe ich in einer Excel-Tabelle gespeichert und mit den bekannten Formeln ergänzt (die drei aus der Doku und die eine von ThomasKl). Ich hänge die Tabelle hier mal dran.

 

Was ich immer noch suche: eine Formel, die mir bei der ersten Drehung konstant "0" ausgibt und bei der zweiten Drehung konstant "45".

IMU_Test.xls

Link to comment
Share on other sites

So, nächster Versuch :). In dem neuen Beispiel sollte alles untergebracht sein was hier gefragt war: http://www.tinkerforge.com/doc/Hardware/Bricks/IMU_Brick.html#how-to-get-angles-that-are-independent

 

Erst wird eine Bezugsposition festgelegt, diese Position legt fest wo 0 Grad für alle Winkel sind. Danach sollten die Winkel für x, y und z berechnet werden. Gimbal Locks sind bei +90 und -90° bei allen Achsen, in etwa einem 15° Radius um den Gimbal Lock fangen die Werte an ungenau zu werden und beim Überspringen können Achsen um 180° springen (das ist korrektes verhalten).

 

Wenn das nicht ausreicht oder das zu ungenau ist für eure Anwendung müssen entweder Rotationsmatrizen oder direkt die Quaternionen benutzt werden, da geht kein weg dran vorbei. Hab heute den halben Tag rumprobiert, eine bessere Darstellung kriege ich mit Eulerwinkel nicht hin ;D!

Link to comment
Share on other sites

(Wir könnten einen Selbsthilfe Mathe Thread aufmachen...)

Überlegung:

 

Ich habe einen Vektor Norden diesen rotiere ich um die Achsen bzw ich Multipliziere mit der Rotationsmatrix. Danach setze ich das Ergebnis in Z = 0 und erhalte den Vektor in der XY Ebene. Nach dem Normieren bestimme ich den Winkel vom Nordvektor zum Positionsvektor und habe die globale Drehung des IMU in der Ebene oder?

Ich muss mal meine Mathe Vorlesungsunterlagen zusammen suchen ^^ Habe ich irgendwas übersehen an meiner Überlegung?

 

Link to comment
Share on other sites

was mir bei den Erklärungen fehlt ist irgendwie die Information von welchem Bezugssystem ausgegangen wird.

In meiner Vorstellung gibt es zwei Koordinatensysteme das des Bricks mit den x,y,z Achsen so wie sie auf dem brick aufgedruckt sind und das Äußere also die Welt mit Nord-Süd (NS), Ost-West (OW) und dem gefühlten Unten-Oben (UO).

Jetzt braucht man die Transformation für Weltkoordinaten (NS,OW,UO) in Brickkoordinaten (x,y,z) und für die Transformation von Brick zu Welt koordinaten.

 

Um das Problem von Plenz zu lösen müsste man einmal den Punkt (1,0,0) von Brick zu Welt transformieren und dann den Winkel zur UO-Achse bestimmen.

Und dann das gleiche nochmal mit dem Punkt (0,1,0).

 

wenn ich das richtig verstanden habe dann Transformiert die in der Api angegebene Matrix Brickkoordinaten in Weltkoordinaten.

 

EDIT:

Das was plenz möchte müsste  eigentlich auch einfach anhand der Gyroskopdaten möglich sein.

Link to comment
Share on other sites

In meiner Vorstellung gibt es zwei Koordinatensysteme das des Bricks mit den x,y,z Achsen so wie sie auf dem brick aufgedruckt sind und das Äußere also die Welt mit Nord-Süd (NS), Ost-West (OW) und dem gefühlten Unten-Oben (UO).

 

Also du hast einmal das Koordinatensystem was die Quaternionen standardmäßig ausgeben. Die "Nullstellung" kannst du einfach suchen indem du dir die Quaternionen ausgeben lässt und guckst wo 0, 0, 0 rauskommt. Das IMU Brick "aufm Kopf" halten und USB Stecker 45° von Norden nach rechts, so ungefähr. Dieses Koordinatensystem ist aber nicht wichtig, da muss man nicht drin rechnen.

 

Das "Weltkoordinatensystem" hab ich jetzt in dem Beispiel "base system" genannt. Dazu speicherst du einfach die Quaternionen an der Stelle wo du die 0, 0, 0 Position haben willst und multiplizierst die dann immer mit dem konjugierten der Quaternionen die du bekommst. Wo für dich unten/oben ist und auch wo die Himmelsrichtungen sind ist ja abhängig davon wie du die IMU einbaust! Aber wie gesagt, die Umrechnung dafür ist nur eine Quaternionen Multiplikation.

 

Wie man dann zu unabhängigen Winkeln kommt ist auch in dem Beispiel drin.

 

Echte Eulerwinkel (die man nacheinander Anwenden kann um zurück zum Nullpunkt zu kommen) gibt es mit der getOrientation Funktion.

 

IMO sollten damit jetzt schon die meiste notwendige Mathematik abgedeckt sein :).

 

Edit: Eins noch: Wie man von Quaternionen zu Rotationsmatrizen kommt (z.B. zur Darstellung in Opengl/DirectX oder zur Berechnung von Gimbal Lock freien Winkel ohne Quaternionen) ist in der API Dokumentation zu den jeweiligen Sprachen beschrieben!

Link to comment
Share on other sites

Habs gerade nochmal getestet, bei mir funktionierts. D.h. der Callback kommt genau einmal? Funktionieren Callbacks denn im Allgemeinen bei dir? Wenn du das Beispiel mal soweit verkleinerst das nur noch die Callbackperiode und der Callback gesetzt wird, gehts dann?

 

Geht das Beispiel aus der Doku:  http://www.tinkerforge.com/doc/Software/Bricks/IMU_Brick_Python.html#imu-brick-python-examples?

Link to comment
Share on other sites

Sorry, ich hab jetzt keine Lust auf Debuggen. Bisher ging jedenfalls alles. Mein Programm, das ich von dem Callback-Beispielprogramm abgeleitet habe, funktioniert nach wie vor.

 

Jedenfalls habe ich jetzt noch mal mit meinem Programm zwei Tests gemacht, wieder einmal waagerecht und einmal um 45° gekippt, und dabei jeweils langsam um 360° rotiert. Etwa alle 5° habe ich x, y, z, w abgespeichert, in Excel übertragen und dort die Formeln eingesetzt. Hier angefügt die Ergebnisse, schön mit Diagrammen dargestellt. Man sieht: keine der Formeln rechnet irgend etwas heraus. Wenn der IMU-Brick gekippt ist, ändern sich bei einer einfachen Drehung sämtliche Winkel.

 

Deshalb noch mal zurück nach oben zu meinem Eintrag mit den Screenshots vom Brick Viewer. Ich habe das dumpfe Gefühl, das in der grafischen Darstellung des IMU-Bricks meine gesuchten Formeln stecken, denn egal wie man den IMU-Brick auf dem Tisch rotiert, das Bild stellt immer "IMU-Brick ist 45° zur Seite gekippt" dar. Also muss es doch irgend eine Formel geben, die ich in meine Excel-Tabelle einfügen kann und die mir in jeder Zeile diese 45° errechnet.

IMU_Test.xls

Link to comment
Share on other sites

Also, nachdem ich nun wieder mal Zeit gefunden habe, mit der IMU zu "spielen"

komme ich nun "scheinbar" zu einem "ersten" brauchbaren Ergebnis.

 

Zielsetzung war: Erkennen von Roll, Pitch und Yaw (in einem Flugzeug) - getestet habe ich bisher nur am Schreibtisch mit Drehen, usw.... Der

Kurs, errechnet aus dem Magnetfeld, ist noch nicht "Tilt-Compensated", was

aber zwingend notwendig ist:

 

Init der IMU

imu.set_convergence_speed 250
  sleep 5
  imu.set_convergence_speed 5
  
  q = []
  q = imu.get_quaternion

  base_x = q[0]
  base_y = q[1]
  base_z = q[2]
  base_w = q[3]

 

Konjugation

x = -x
y = -y
z = -z

 

Und die Winkel:

 

  x_angle = Math.atan2(2*y*z - 2*x*w, w*w + z*z - x*x - y*y)*180/Math::PI + 180
  y_angle = Math.atan2(2*w*y + 2*x*z, w*w + z*z  -x*x - y*y)*180/Math::PI + 180
  z_angle = Math.atan2(-w*y + x*y + y*x - w*w, w*w + y*y - z*y -  
                        x*x)*180/Math::PI + 180

 

Diese Formeln stammen aus dem Forum, nicht von mir.... Ich werde am WE oder

Anfang der Woche mal einen Flug machen und es testen.

 

Das Brick liegt mit LED's nach oben auf einem MasterBrick gesteckt. Das IMU

Brick hängt sich des öfteren auf, wenn ich dort ein lCD Prickelt einstöpsle...

 

Code ist Ruby - wenn das nun klappt, werde ich mal nach IOS wechseln...

 

 

Gruss, Dirk

Link to comment
Share on other sites

@ROSEDOLA: Oh, das sehe ich ja jetzt erst, dein Ruby Code tut ja schon genau das gleiche ;D. Aber deine Formeln für x,y,z angle entsprechen irgendwie nicht denen die ich hab:

x_angle = int(math.atan2(2.0*(y*z - w*x), 1.0 - 2.0*(x*x + y*y))*180/math.pi)
y_angle = int(math.atan2(2.0*(x*z + w*y), 1.0 - 2.0*(x*x + y*y))*180/math.pi)
z_angle = int(math.atan2(2.0*(x*y + w*z), 1.0 - 2.0*(x*x + z*z))*180/math.pi)

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


×
×
  • Create New...