Quaternion zu EulerWinkel umrechnen

Dieses Herstellerbeispiel besteht lediglich aus einer exe Datei, usb-zu-serial treibern für das ARM-Evaluations Board, einer Firmware für dieses im .bin format und zwei PDFs mit einer Benutzeranleitung,wie man diese Demo bedient. Also kein Quellcode, header-dateien oder ähnliches was uns weiterhilft.

Vielen vielen Dank Razor

Zuerst einmal bin ich seit ein paar Stunden dabei das Ganze zu verstehen.
Um dich nicht zu enttäuschen wollte ich ein Beispiel mit deinem Code zum Laufen bringen.
Nun, momentan scheitere ich scheinbar schon an der Programmstruktur.
In den diversen Sketche die ich bis jetzt Programmiert habe, habe ich solche Wertübergabe wie du im ersten Satz noch nicht gebraucht, da ich das so nicht kenne.
Dein Code:

void quaternion2euler(float* q0,float* q1,float* q2, float* q3,float* phi,float* theta,float* psi)

Sieht so aus als man da gleichzeitig die Quaternion Werte übergibt (q0, q1, q2, q3) aber gleichzeitig die Winkel phi, theta, psi ausliesst.

Ich habe ein kleines Beispiel geschrieben was ich bis jetzt kenne um Werte zu übergeben und zurück lesen:

//  Test Werte an einem Funktionsblock zu übergeben
//  Test Werte an einem Funktionsblock zu übergeben und danach zurück geben zu lassen

float wert;

void setup()
{
Serial.begin(38400);
}

void loop()
{
 quaternion2euler(-10.23, 55.11, 88.88, 99.99);  // 4 Werte an Funktionsblock "quaternion2euler" übergeben
 wert = rueckgeben(4.5);                         // Wert an Funktionsblock "rückgeben" senden (4.5) und dannach zurück lesen
 Serial.print ("      rueckgegebener Wert  ");   
 Serial.println (wert);                          // Wert von Block "rückgeben" ausdrucken
}

void quaternion2euler(float q0, float q1, float q2, float q3){ // Funktionsblock "quaternion2euler"
 Serial.print ("      Q0  ");                                  // Werte Q0,Q1,Q2,Q3 ausdrucken
  Serial.print (q0);
  Serial.print ("      Q1  ");
  Serial.print (q1);
  Serial.print ("      Q2  ");
  Serial.print (q2);
  Serial.print ("      Q3  ");
  Serial.print (q3);
  
  
  }
  
  float rueckgeben (float x){            // Funktionsblock "rückgeben"
    float ergebnis = x*2;
    return ergebnis;
  }

Was ist mein Denkfehler, wie geht das bei deiner Zeile mit dem übergeben und auslesen?

Das mit dem Pointer und umrechnen bin ich erst noch dabei zu verstehen, ich brauche Zeit, bin aber dabei.

@Udo klein

Diverse Leute wie ich sind dabei bei Invensense die nötigen Infos zu entlocken, momentan ist da nichts zu machen.
Schau mal Hier (leider muss man sich da anmelden):

http://www.invensense.com/developers/forum/viewforum.php?f=3&sid=ccea78fb9f6bf8bf8482e04ea307f815

oder hier:
http://www.varesano.net/blog/fabio/initial-tests-freeimu-v04-and-mpu6050

Die zwei Spezialisten die die beiden Bibliotheken geschrieben haben wissen zur Zeit nicht wie es geht!

Gruss Kay

Deklariere einfach 4 Variablen q0, q1,q2,q3. Weis ihnen die Werte zu. Und übergib sie dann der Prozedur mit &q0, &q1 usw. Dasselbe für die Winkel. Ich hab mich hier für Pointer entschieden,da die Übergabe dann schneller von Statten geht.
Pointer sind Speicheradressen. Für genauere Infos siehe hier.

http://www.peacesoftware.de/ckurs12.html

Das ist mein Code von der Zeitmessung:

const float pi = 3.14159;
unsigned long ms;

void quaternion2euler(float* q0,float* q1,float* q2, float* q3,float* phi,float* theta,float* psi){ //quaternion2euler(&q0,&q1,&q2,&q3,&phi,&theta,&psi);
 *phi = atan2(2*(*q0 * *q1+*q2 * *q3),1-2*(*q1 * *q1+*q2 * *q2));                          //So sieht der Prozeduraufruf aus
 *theta=asin(2*(*q0 * *q2-*q3 * *q1));                                                       //Einfach die Formeln nachgebildet
 *psi = atan2(2*(*q0 * *q3+*q1 * *q2),1-2*(*q2 * *q2+*q3 * *q3));                          
}

void setup(){
  Serial.begin(9600);
}

void loop(){
 float q0,q1,q2,q3;
 float phi,theta,psi;
 
 q0=0.5;
 q1=0.5;
 q2=0.5;
 q3=0.5;
 ms=millis();
 for(int i=0;i<2000;i++){
 quaternion2euler(&q0,&q1,&q2,&q3,&phi,&theta,&psi);
 }
 Serial.println(millis()-ms);
 Serial.println(phi);
 Serial.println(theta);
 Serial.println(psi);
 delay(10000);
}

Danke für dein Zeitmessungscode, habe es nun (glaub ich) gerafft wie das mit den Werten übergeben geht.

Habe nun versucht das im Beispielsketch das Quaternion ausgibt zu implementieren.
Hier der Code als *txt (ist zu gross für das "code" hier im Forum)

Hier

Sehr komisch ist, das die Ausgabe scheinbar nicht das ist was ich bei Print geschrieben habe, selbst das "Hallo" das ich testhalber im ersten Print geschrieben habe erscheint nicht, stattdessen erscheint im Serial Fenster dies:

"ection to 0...1.54ion to 0...0.78ion to 0...0.11"

Die Werte ändern sich auch wenn ich den MPU6050 schwenke.

Was läuft da falsch?

Da hier keiner eine Glaskugel hat wäre es gut wenn Du Deinen vollständigen Code postest.

Das ist der vollständige Code, einfach ein MPU6050 Breadboard an den Arduino anschliessen, die Bibliothek ist in meinem Post 1 , und nun kannst du das Serial Fenster aufmachen und die Daten anschauen.

Man sieht aber auch ohne MPU6050 wie ich Razor's Code Implementiert habe, ob nun richtig oder falsch.
Das komische Ausgeben des Print hat nichts mit dem Code von Razor zu tun, nur weiss ich nicht wieso die Funktion Print etwas anderes ausgibt.

Du musst nur im Code schauen das ich als *txt verlinkt habe, falls es dich den wirklich Interessiert.

Die Werte stimmen, denn sie sind im Bogenmaß. Allerdings würde ich die Berechnung nach der Ermittlung der Quaternionen machen, damit es kein undefiniertes Verhalten im ersten Durchlauf gibt. Dieses komische sind Teile aus der Initialisierung, ich würde am Ende vom setup() noch ein delay(1000) oder so setzen, damit sich der DMP erst einmal setzen kann und werte Produzieren. im nächsten Schritt alle DEBUG_PRINT und DEBUG_PRINTLN aus der Setup werfen, da diese dir nur dazu dienen zu verfolgen, wie der DMP initialisiert wird. Das scheint ja zu funktionieren, da du ja scheinbar Werte erhälst.

hierfür entferne das #define DEBUG relativ weit oben.

am Ende vom loop() noch ein delay(100), damit du die serielle Schnittstelle nicht überlastest.

So, habe mal nach deinen Vorschlägen grob aufgeräumt.

Es Funktioniert. :slight_smile:

Hier

Wobei ich am Ende von Setup die delay(1000) wieder wegnehmen musste, denn damit stockte die ganze Serial Ausgabe, wieso weiss ich nicht.

Vielen Dank Razor, auf diesem Beispiel kann ich nun aufbauen.
Fehlt nur noch die Umrechnung von Bogenmass auf Winkelmass!

Wo kann ich hier ein ein kühles Blondes rüberschieben?

Gruss Kay

Im winkelmass findest du es im ersten von mir geposteten Code.

Also mein Kopf ist nun durch, sehe nur noch Sterne.
Muss das Morgen weitermachen.

Razor, du hast wirklich sehr geholfen, vielen Dank dafür.

Gruss Kay

Der von Dir verlinkte Code enthält sehr viele Print Statements. Ich würde darauf tippen, dass dadurch zuviel Speicher verbraucht wird und das merkwürdige Verhalten daher kommt, dass bereits einige Speicherbereiche überschrieben werden.

An Deiner Stelle würde ich die Strings für die Debugausgabe nicht im Ram sondern nur im Flash ablegen. Google nach PROGMEM.

So, nun in Winkel (wird natürlich noch weiter aufgeräumt):

Hier

Jetzt kann ich das Ganze mit einem Komplementärfilter vergleichen.

Noch als Info, scheinbar bekommen nur grosse OEM Partner von Invensense die Kompletten Infos bezüglich DMP.
Eigentlich finde ich die Werbung ist somit Bull....!!

Gruss Kay