Velocity-Verlet

Übersicht BlitzMax, BlitzMax NG Beginners-Corner

Neue Antwort erstellen

Blitzcraft

Betreff: Velocity-Verlet

BeitragDi, Aug 21, 2012 19:34
Antworten mit Zitat
Benutzer-Profile anzeigen
Ich versuche derzeit ein Velocity-Verlet Algoritzmus zu schreiben und bin dabei auf ein ähnliches Problem wie in diesem alten Thread gestoßen.
Jetzt habe ich aber keinen Plan wie ich einen Constraint-Solver mit Geschwindigkeit und Beschleunigung machen soll. Confused
Könnte mir jemand da jemand weiterhelfen?
Screenshot aus meinem ersten Projekt

Propellator

BeitragDi, Aug 21, 2012 21:05
Antworten mit Zitat
Benutzer-Profile anzeigen
Hi,

ich weiss zwar nicht genau was für eine Art von Verlet-Implementation das ist, aber ich kann dir sagen dass ich die Wikipedia-Artikel nicht wirklich hilfreich fand für eine praktische Implementierung von Verlet-Physik.
Durch etwas googlen stiess ich auf diesen Artikel, welcher mir sehr half und prinzipiell zeigte wie einfach das ganze ohne grossem Schnickschnack wie Kollision ist.

Wenn es spezifische Fragen zu Problemen gibt, stelle diese doch bitte, dann kann man dir auch besser helfen. Smile

Bye.
Propellator - Alles andere ist irrelephant.
Elefanten sind die Könige der Antarktis.

Tornado11

BeitragDi, Aug 21, 2012 22:07
Antworten mit Zitat
Benutzer-Profile anzeigen
Also dein Artikel der behandelt Position verlet, nicht velocity verlet.
Im ersteren ist die Geschwindigkeit implizit angegeben durch die momentane und die letzte position des z.B. Massenpunktes.
Wieso möchsten du umbedingt velocity verlet verwenden bzw. was ist dein Ziel? Mit diesen Informationen könnte man dir vielleicht besser helfen.

Was für ein "Constraint" brauchst du den? Es gibt da verschiedene. z.B. zwei Punkte auf eine gewisse Distanz halten (Distance constraint), nur bestimmte Drehungen zulassen (Angular Constraint) oder Reibung (Friction constraint) etc...

Blitzcraft

BeitragMi, Aug 22, 2012 9:29
Antworten mit Zitat
Benutzer-Profile anzeigen
Also ich fande velocity-verlet besser da dort dir Geschwindigkeit direkt in einer variable gespeichert ist und man diese nicht ständig aus der neuen und der alten Position berechnen muss, oder hab ich da was falsch verstanden?

Ich meinte übrigens den distance constraint.
Und um Trägheit zu erzielen, müsste ich im constraint-solver mit Geschwindigkeit arbeiten, nur wie? Meine versuche die distance mit Geschwindigkeit auszugleichen haben nicht so ganz funktioniert.
Screenshot aus meinem ersten Projekt

Tornado11

BeitragMi, Aug 22, 2012 12:50
Antworten mit Zitat
Benutzer-Profile anzeigen
ehm das Thema ist ziemlich kompliziert und wenn man position verlet nimmt, dann vereinfacht sich halt einfach vieles.

Zitat:
Also ich fande velocity-verlet besser da dort dir Geschwindigkeit direkt in einer variable gespeichert ist und man diese nicht ständig aus der neuen und der alten Position berechnen muss, oder hab ich da was falsch verstanden?

Das Handling der Geschwindigkeit ist erfahrungsgemäss eigentlich kein Problem (mit position verlet). Was für welche stellst du dir den vor?

Du willst ja eine Distance Constraint, dass kann man sich bildlich als eine "Stange" vorstellen, die z.B. zwei Partikel x1 und x2 (Vektoren) auf eine festgelegte Distanz d hält. In einer Gleichung festgehalten ist das
Code: [AUSKLAPPEN]
|x1-x2| - d = 0 ; Die Distanz zwischen den Punkten minus der gewünschten distanz muss immer 0 sein


Tja um diese Gleichung zu "lösen" gibt es viele Ansätze.
Es gibt da sogenannte globale Lösungsansätze, die Versuchen alle Constraints gleichzeit zu lösen. Die sind aber unheimlich kompliziert und auch langsam (sog. LCP solver). Oder man kann die Constraints iterativ lösen, d.h. man "löst" jedes Constraint nacheinander immer wieder und hofft das das gesammte System sich der realen Lösung nähert (konvergiert). Die Grundidee ist, dass man Partikeln, die auseinander gedriftet sind einen "Schubs" gibt damit sie wieder am gleichen Platz landen (entweder einen Impuls ausüben oder eine Kraft). Aus der Physik kennst du vielleicht F = -D *s (Federgleichung) wobei D die Federkonstante ist. Ein Versuch wäre z.B. die Distance Constraint als Feder zu modelieren aber erfahrungsgemäss funktioniert das nicht so gut (D müsste unendlich sein für eine unendlich starre Feder).

Anderer Möglichkeit:
Ein sehr einfacher iterativer Solver ergibt sich wenn man den position verlet verwendet der im Pseudocode so aussieht
Code: [AUSKLAPPEN]
delta = x2-x1                      ;momentane Distanz zwischen zwei punkten
deltalength = sqrt(delta*delta)    ;Pythagoras
diff = (deltalength-d)/deltalength ;korrigiere ein kleines Stück (Gauss seidel verfahren)
x1 += delta * 0.5 * diff                 ; Korrigiere jeweil um die Hälfte
x2 -= delta * 0.5 * diff                  ; ACHTUNG! die Geschwindigkeit wird implizit verändert durch das Repositionieren der Punkte. Darum funktionierts auch!


Wie man das bei Velocity verlet richtig macht weiss ich eigentlich nicht. Ich habe aber mal eine "hacky" Lösung gesehen wo einfach die Geschwindigkeit angepasst wurde à la position verlet aber dann könnte man ja genauso gut letzteres nehmen...

Falls du English kannst und durch kompliziertes Zeug wühlen willst kannst du ja mal das http://www.matthiasmueller.inf...sedDyn.pdf Anschauen. Das erklärt die ganzen Herleitungen (wie lineare und angulares moment konserviert werden und blabla)

Blitzcraft

BeitragMi, Aug 22, 2012 14:26
Antworten mit Zitat
Benutzer-Profile anzeigen
Einen Position-Verlet Solver habe ich ja schon und wollte diesen in einen Velocity-Verlet Solver umbauen, aber wenn das so kompliziert ist und es keine einfachere Lösung gibt die gut funktioniert, dann werde ich wohl Position-Verlet nehmen müssen. Laughing
Ich wusste nicht das Velocity-Verlet so kompliziert ist. Sad
Screenshot aus meinem ersten Projekt

Tornado11

BeitragMi, Aug 22, 2012 16:49
Antworten mit Zitat
Benutzer-Profile anzeigen
Ich habe eine semi-schwierige Lösung parat, aber ich habe die noch nicht ausgiebig in der Praxis getestet. Sie korrigiert die Positionen der beiden Partikeln mit kurzen Impulsen (damit sie an der richtigen Stelle bleiben/hinkommen).

Weil das physikalische Geblubber vielleicht nicht so interessant ist mach ich es kurz.
Code: [AUSKLAPPEN]

Partikel x1, x2 (vektoren) mit massen m1, m2 und Geschwindigkeiten v1,v2
distanz = x2-x1
normal = distanz / |distanz|
vrelativ = (v2-v1) * normal                                //Skalarprodukt
distanz_relativ = distanz - gewünschteDistanz
temp =  vrelativ + (distanz_relativ / dt )           //dt ist das Zeitinterval über das du die Partikel integrierst
korrektur_impuls = temp *(m1 + m2)               //p = m* v, normalerweise arbeitet man mit inversen Massen...
v1 += korrektur_impuls * (1/m1)
v2 -=  korrektur_impuls * (1/m2)


Von der Idee her: Es wird die relative Geschwindigkeit gemessen und die Distanz zum Ort wo die Partikel sein müssten. Dazu wird ein passender Impuls berechnet, der die Partikel wieder an den richtigen Ort schiebt.

Das wäre ein Iterationsschritt ähnlich dem bei Position-Verlet.

Eigentlich siehst du wo das hinführt. Position-Verlet ist wirklich sehr einfach darum auch ziemlich beliebt. Wenn man aber halt andere Integrationsmethoden (Physik-Engine Sinne) verwenden möchte dann wirds halt beliebig kompliziert.

Blitzcraft

BeitragDo, Aug 23, 2012 12:25
Antworten mit Zitat
Benutzer-Profile anzeigen
Ich bin jetzt schon auf Position-Verlet umgestiegen, aber trotzdem danke!
Kompliziertere und längere Rechnungen für ein am Ende fast gleiches Ergebnis sind eigentlich unnötig.

Beim umchreiben bin ich aber auf ein anderes Problem gestoßen was ich mir nicht so ganz erklären kann:
Code: [AUSKLAPPEN]
Method Update()
   Local Temp_Pos:Float[Dimensions]
   Local d:Int
      
   For d = 0 Until Dimensions
      Temp_Pos[d] = Pos[d]

      DebugLog Old_Pos[d]

      Pos[d] :+ (Pos[d] - Old_Pos[d]) + Acc[d] * Delta_Time^2

      DebugLog Old_Pos[d]
      DebugLog "---"

      Old_Pos[d] = Temp_Pos[d]
   Next
End Method

Hier habe ich die Methode wo die einzelnen Nodes geupdatet werden.
Das Problem liegt zwischen den beiden DebugLogs:
In der Rechnung wird Old_Pos geändert, obwohl dort nur Pos geändert werden sollte Question

Debug Log hat Folgendes geschrieben:
DebugLog:100.000000 <-- Old_Pos davor
DebugLog:100.000000 <-- Old_Pos danach
DebugLog:---
DebugLog:100.000000
DebugLog:125.000000
DebugLog:---
DebugLog:100.000000
DebugLog:100.000000
DebugLog:---
DebugLog:150.000000
DebugLog:175.000000
DebugLog:---

Was habe ich falsch gemacht?
Screenshot aus meinem ersten Projekt

Tornado11

BeitragDo, Aug 23, 2012 15:43
Antworten mit Zitat
Benutzer-Profile anzeigen
Also die Update Methode ist richtig, ich verstehe deine Frage nicht ganz?
Zitat:
In der Rechnung wird Old_Pos geändert, obwohl dort nur Pos geändert werden sollte Question


du machst ja das, was auch richtig ist:
Code: [AUSKLAPPEN]
Old_Pos[d] = Temp_Pos[d]


Und die Debug-ausgabe würde Sinn machen, wenn Dimensions = 1 wäre, also du nur ein Node überwachen würdest

Blitzcraft

BeitragDo, Aug 23, 2012 16:07
Antworten mit Zitat
Benutzer-Profile anzeigen
Tornado11 hat Folgendes geschrieben:
Und die Debug-ausgabe würde Sinn machen, wenn Dimensions = 1 wäre, also du nur ein Node überwachen würdest

Dimensions ist eine Konstante mit dem Wert 2 und bedeutet dass das ganze 2D ist, also es eine x und eine y Koordinate gibt.
Aber der DebugLog hat weniger mit den Dimensions zu tun sondern mit der Logik
In der Rechnung in der Mitte...
Code: [AUSKLAPPEN]
Pos[d] :+ (Pos[d] - Old_Pos[d]) + Acc[d] * Delta_Time^2

wird ja nur Pos geändert, aber wieso ändert sich dann Old_Pos, wenn zwischen den beiden DebugLogs nur diese eine Rechung steht:
Zitat:
DebugLog:100.000000 <-- DebugLog vor der Rechnung (y-Koordinate)
DebugLog:125.000000 <-- DebugLog nach der Rechnung (y-Koordinate)
Screenshot aus meinem ersten Projekt

Noobody

BeitragDo, Aug 23, 2012 18:51
Antworten mit Zitat
Benutzer-Profile anzeigen
Bist du denn sicher, dass Pos und Old_Pos zwei verschiedene Arrays sind? Die einzige Erklärung, die ich habe, wäre dass beide Variablen das gleiche Array referenzieren und darum das Update in Pos auch in Old_Pos sichtbar ist.
Man is the best computer we can put aboard a spacecraft ... and the only one that can be mass produced with unskilled labor. -- Wernher von Braun

Blitzcraft

BeitragDo, Aug 23, 2012 20:11
Antworten mit Zitat
Benutzer-Profile anzeigen
Danke für den Tipp Very Happy
Ich hatte in der Create-Funktion beiden Variablen den gleichen Spawn-Positions-Array zugewiesen.
Funktioniert jetzt!
Screenshot aus meinem ersten Projekt

Neue Antwort erstellen


Übersicht BlitzMax, BlitzMax NG Beginners-Corner

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group