Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

1

27.03.2020, 10:05

Koppelnavigation und Glättung dieser

(EDIT by David Scherfgen: Original-Thread auf Englisch: Dead reckoning and Smoothing)

Hallo,

ich habe ein Problem mit der Kopelnavigation im 3D-Raum.
Diese wird verwendet, um das System zu entlasten und nur alle paar Sekunden ein Update der Position und Orientierung eines Objektes zu senden.
Da die Koppelnavigation nur extrapoliert, sind die Daten nicht genau, das heißt, das Ergebnis der Koppelnavigation unterscheidet sich von den Updates zu den Positionsdaten vom System.
Dazu gibt es die Glättung. Das Problem ist, dass ich an der Implementierung dieser Glättung scheitere.
Hat Jemand ein Tutorial dafür, oder eine Möglichkeit mir zu helfen?

Jonathan

Community-Fossil

  • Private Nachricht senden

2

27.03.2020, 15:05

Ein Tutorial hab ich nicht zur Hand, aber das Problem hört sich eigentlich lösbar an. Wenn du eine konkrete Frage zu einen bestimmten Schritt hast, könnte man dazu also vielleicht auch so etwas sagen.

Ich nehme an konzeptionell versuchst du aus den alten bekannten Punkten eine vorhersage zu treffen entlang derer du dann das Objekt bewegst bis neue Daten eintreffen. Sobald dies der Fall ist weißt du, wo das Objekt eigentlich sein sollte. Um harte Sprünge zu vermeiden möchtest du dann zwischen der alten extrapolierten Bahn und der neuen (unter Berücksichtigung des neusten Datenpunktes) interpolieren. Ist das so in etwa korrekt? An welcher Stelle scheitert es konkret?
Lieber dumm fragen, als dumm bleiben!

3

27.03.2020, 18:34

Es scheitert an der Korrekten Umsetzung.
Also die Extrapolation geschieht linear, dafür habe ich konkrete Gleichungen implementiert.
Für die Glättung habe ich bisher einen Kalman-Filter benutzt. Der funktionioert für die Position wunderbar, nur die Orientierung stimmt nicht.
Im Prinzip brauche ich also eine Idee/Anregungen/ oder auch Gleichungen wie man die Orientierung möglichst rukelfrei bekommt, ohne zu viel Genauigkeit zu verlieren.

David Scherfgen

Administrator

Beiträge: 10 382

Wohnort: Hildesheim

Beruf: Wissenschaftlicher Mitarbeiter

  • Private Nachricht senden

Jonathan

Community-Fossil

  • Private Nachricht senden

5

27.03.2020, 20:01

Spricht etwas dagegen eine Extrapolation höherer Ordnung zu machen? Wenn man sich ein paar mehr als nur die letzten 2 Punkte anschaut kann man ja recht leicht auch die Beschleunigung und auch höhere Ableitungen bestimmen. Damit könnte man z.b. eine klassische Fallparabel schon exakt extrapolieren. Alles was mit Benutzerinput oder ähnlichen zu tun hat erzeugt natürlich ruckartige Änderungen die man unmöglich vorhersagen kann, aber viele 'natürlich' Prozesse sollten hinreichend glatt sein als das sich das lohnt. Wenn man das Extrapolationproblem genauer löst, hat man später beim Anpassen weniger Arbeit.

Für die Glättung: Wieso eigentlich Glättung und Kalman-Filter? So wie ich das verstehe ist doch beides eher für Situationen in denen dein Signal durch Rauschen gestört wird. Aber du hast ja alle bisherigen Werte schon exakt und ohne Unsicherheit und willst einfach nur einen plausiblen neuen Berechnen.

Letztendlich willst du doch zwischen der alten geschätzten Bahn und der neuen irgendwie interpolieren. Sprich die Korrektur findet innerhalb eines gewissen Zeitfenster statt das nicht zu kurz sein darf weil man sonst die Korrekturruck zu sehr bemerkt. Letztendlich willst du also zu einem bestimmten Punkt in der Zukunft (kurz vor dem nächsten Update) an einem bestimmten Punkt im Raum sein, dort auch einen bestimmten Geschwindigkeitsvektor haben und am besten auch noch die passende Beschleunigung (also möglichst weich in die eigentlich richtige Flugbahn reinblenden). Hört sich für mich eigentlich irgendwie nach Splines an.
Lieber dumm fragen, als dumm bleiben!

6

30.03.2020, 14:15

Ist hier vielleicht was für dich dabei?
https://www.google.com/search?q=kalman+f…chrome&ie=UTF-8


Ich glaube das mit den Quaternions könnte mein Problem direkt lösen. Ich evrstehe sie nur noch nicht ganz.
Als Beispiel, habe ich einen Vektor für die Orientierung (yaw,pitch,roll) = (20,30,40).
Wie würde dieser in das Quaternion System übertragen werden können?
Ich hab soviel verstanden, dass es mit einer Rotation um die Koordinatenachsen geschieht. EIn Quaterion wird als q = (q_0 q_1 q_2 q_3) dargestellt.
Wie werden die Werte q_0-q_3 für den gegebenen Winkel gefüllt?

David Scherfgen

Administrator

Beiträge: 10 382

Wohnort: Hildesheim

Beruf: Wissenschaftlicher Mitarbeiter

  • Private Nachricht senden

7

30.03.2020, 15:23

Schau mal hier: https://en.wikipedia.org/wiki/Conversion…nd_Euler_angles

Da ist auch Code angegeben:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
struct EulerAngles
{
    double roll, pitch, yaw;
};

struct Quaternion
{
    double w, x, y, z;
};

Quaternion ToQuaternion(double yaw, double pitch, double roll) // yaw (Z), pitch (Y), roll (X)
{
    // Abbreviations for the various angular functions
    double cy = cos(yaw * 0.5);
    double sy = sin(yaw * 0.5);
    double cp = cos(pitch * 0.5);
    double sp = sin(pitch * 0.5);
    double cr = cos(roll * 0.5);
    double sr = sin(roll * 0.5);

    Quaternion q;
    q.w = cy * cp * cr + sy * sp * sr;
    q.x = cy * cp * sr - sy * sp * cr;
    q.y = sy * cp * sr + cy * sp * cr;
    q.z = sy * cp * cr - cy * sp * sr;

    return q;
}

EulerAngles ToEulerAngles(Quaternion q)
{
    EulerAngles angles;

    // roll (x-axis rotation)
    double sinr_cosp = 2 * (q.w * q.x + q.y * q.z);
    double cosr_cosp = 1 - 2 * (q.x * q.x + q.y * q.y);
    angles.roll = std::atan2(sinr_cosp, cosr_cosp);

    // pitch (y-axis rotation)
    double sinp = 2 * (q.w * q.y - q.z * q.x);
    if (std::abs(sinp) >= 1)
        angles.pitch = std::copysign(M_PI / 2, sinp); // use 90 degrees if out of range
    else
        angles.pitch = std::asin(sinp);

    // yaw (z-axis rotation)
    double siny_cosp = 2 * (q.w * q.z + q.x * q.y);
    double cosy_cosp = 1 - 2 * (q.y * q.y + q.z * q.z);
    angles.yaw = std::atan2(siny_cosp, cosy_cosp);

    return angles;
}

(Quelle: Link oben)

8

31.03.2020, 15:55

Vielen Dank, das hilft mir bestimmt erstmal weiter

9

30.04.2020, 11:39

Hallo nochmal und vielen Dank.
Ich stecke immernoch bei den Quaternions fest.
Ich weiß nicht genau wie ich die Rotation hinbekomme.

Ich habe mit dieser Seite die Konvertierungen gemacht: http://www.euclideanspace.com/maths/geom…rnion/index.htm

Dabei sind die Quaternions so berechnet worden:

w = c1 c2 c3 - s1 s2 s3
x = s1 s2 c3 +c1 c2 s3
y = s1 c2 c3 + c1 s2 s3
z = c1 s2 c3 - s1 c2 s3

C ist immer cosinus des halben Winkels und s ist sinus des halben Winkels. Die Zahl ist die Nummer des Winkels, heißt erster Winkel = 1 etc.

Damit geschieht die Konvertierung zurück : http://www.euclideanspace.com/maths/geom…Euler/index.htm

Wenn ich nun einen Winkel konvertiere und zurückkonvertiere erhalte ich den gleichen Winkel.

Nun versuche ich die Rotation hinzubekommen.

In meinem Beispiel habe ich einen Winkelvektor (60,60,60), welcher zu folgendem Quaternion Q1 führt:
(0.5245190528383291, 0.5915063509461096, 0.5915063509461096, 0.15849364905389038 )

Dann will ich um 2 Grad rotieren. Dafür mache ich aus (2,0,0)° ein Quaternion Q2: (0.9998476951563913, 0, 0.01745240643728351, 0)
Dann multipliziere ich das neue Quaternion an das Winkelquaternion von oben: Q2 * Q1 = Q3 (http://www.euclideanspace.com/maths/alge…metic/index.htm)

Das Quaternion Q3 sollte nun meinen Winkel enthalten. Konvertiere ich es zurück ergibt es (62,60,60)°, soweit so gut.
Versuche ich aber die anderen Winkel um 2° zu Rotieren kommt etwas Falsches raus.

Für (0, 2, 0)° ergibt sich (0.9998476951563913, 0, 0, 0.01745240643728351)

Für (0, 0, 2)° ergibt sich (0.9998476951563913, 0.01745240643728351, 0, 0)

Da bekomme ich dann weder (60, 62, 60)° raus noch (60, 60, 62)°.

Das heißt die Multiplikation funktioniert nur für eine Drehrichtung.
Sieht irgendwer meinen Fehler?

Jonathan

Community-Fossil

  • Private Nachricht senden

10

01.05.2020, 08:50

Gibt es einen Grund, weshalb du das per Hand machst?

Ich meine, du wirst doch vermutlich eh schon irgendeine Bibliothek für Vektoren / Matrizen benutzen, oder? Sind da denn keine Quaternionen drin? Ich habe Quaternionen eigentlich immer als Black-Box betrachtet - es gibt Funktionen mit denen man sie erzeugen und kombinieren kann und ich kann damit Vektoren transformieren und das ist alles schon korrekt und effizient implementiert und mehr brauch ich nicht.

Eine fertige Bibliothek zu verwenden (ich z.B. mag glm ganz gerne) find ich auch deshalb sinnvoll, weil dann alle Konventionen konsistent sind. Es kann ja durchaus sein, dass Formeln die man im Netz findet für sich genommen korrekt sind, aber wenn (dummes Beispiel, aber egal) die Formel für Quaternion -> Euler Winkel und die Formel Eueler Winkel -> Quaternion unterschiedliche Definitionen von Euler Winkeln benutzen dann passen sie halt nicht zusammen.

Den Fehler in der Rechnung sehe ich nicht direkt, aber ich würde vielleicht auch nicht Quaternionen oder Euler-Winkel vergleichen, sondern die damit transformierten Vektoren. Weil das Ergebnis auf jeden Fall eindeutig ist, die anderen eben nicht unbedingt.
Lieber dumm fragen, als dumm bleiben!

Werbeanzeige