Dynamisches Triebwerkauswuchten des Raumschiffs


14

Die Raumschiffe in meinem Spiel sind dafür gedacht, von Spielern gebaut zu werden, mit einer willkürlichen Anzahl von Triebwerken, die bei jeder Drehung irgendwo angebracht sind. Ich habe momentan einen schmutzigen Code, um das Schiff in einen bestimmten Winkel zu drehen (Beschleunigen und Verzögern).

Hier ist ein Beispiel für ein symmetrisches Schiff, dessen Ausrichtung auf die rote Linie zeigt und das angewiesen wird, sich nach links zu drehen.

Schiff

Wie Sie sich vorstellen können, wirken sich jedoch manchmal unerwünschte lineare Kräfte auf das Schiff aus, je nachdem, wo der Spieler die Triebwerke aufgestellt hat. In diesem Fall bewegt sich das Schiff vorwärts.

Ich überlege, ob es möglich ist, den maximalen Schub zu finden, den ein Triebwerk ausüben kann, um keine lineare Geschwindigkeit zu verursachen. (Im obigen Fall wäre dies keine, da nichts den Kräften der hinteren Triebwerke entgegenwirkt und die vorderen sich gegenseitig töten.)

Bisher habe ich mir eine Formel ausgedacht, mit der die "Drehungseffizienz" bestimmt werden kann, z. B. wie viel Drehung in Bezug auf die lineare Bewegung verursacht wird.

a - Positionsvektor zum Triebwerk a b - Positionsvektor zum Triebwerk b v1 - Kraft vom Triebwerk a v2 - Kraft vom Triebwerk b

efficiencyDelta = a.cross (v1) / | v1 | - (a.cross (v1) + b.cross (v2)) / | v1 + v2 |

im Grunde genommen "a.cross (v1 * t) / | v1 |" soll die Wendungseffizienz sein. Und dann subtrahieren wir es von der Effizienz der kombinierten Triebwerke, um zu sehen, ob sich das Abfeuern des neuen Triebwerks lohnt.

Das Problem entsteht, wenn ich merke, dass Triebwerke nicht nur ein- oder ausgeschaltet sein sollen, sondern ihren Schub von 0 bis 1 variieren können. Und wie man vorgeht, wenn der Spieler möchte, dass das Schiff vorwärts fährt. Natürlich müsste es ein Gleichgewicht geben, wie viel gedreht / bewegt werden muss.

Ich bin kein Raketenwissenschaftler und hoffe, es gibt jemanden, der mir sagen kann, ob es überhaupt möglich ist, die Drosselung jedes einzelnen Triebwerks auf diese Weise zu berechnen und mir einen Schub in die richtige Richtung zu geben.

Danke dass du dir die Zeit nimmst! / Kim


3
Ich habe auf demselben Pfad begonnen, aber bei vielen Konfigurationen ist es unmöglich, sowohl zu drehen als auch nicht zu übersetzen. Nehmen Sie also Rotation weg? Oder erlauben Sie eine Übersetzung? Letztendlich liegt es an dem Benutzer, der das Schiff entwirft. Für meine Demo habe ich es gefälscht. Related: gamedev.stackexchange.com/questions/58216/… , gamedev.stackexchange.com/questions/40615/…
MichaelHouse

Ich bin einen ähnlichen Weg gegangen und habe schließlich eine Demo auf dieser Seite geschrieben . Wenn Sie die Triebwerke bewegen (ziehen Sie sie auf dem Schiff, um Position und Leistung einzustellen), werden drei Formen gezeichnet. Die Intuition ist, dass Sie sich alle möglichen Bewegungen als einen Punkt im 3D-Raum vorstellen können (x, y, Drehung), und auf 0-1 begrenzt zu sein, ist eine Einschränkung in diesem Raum. So erhalten Sie eine 3D-Form, die alle möglichen Bewegungen enthält. Wenn Sie keine lineare Geschwindigkeit wollen, schauen Sie auf die Linie (x = 0, y = 0) in diesem Raum (Q, W, E, S alle 0 in meiner Demo)
amitp

Antworten:


7

Ich gehe davon aus, dass Sie eine physikalisch korrekte Bewegung für Ihr Schiff haben, da diese Analyse sonst nicht gültig ist. Sie benötigen etwas Stärkeres als Effizienz, um dieses Problem richtig zu lösen.

Jedes Triebwerk hat zwei Auswirkungen auf die Schiffsbewegung: linear und winklig. Diese können unabhängig voneinander betrachtet werden. Wenn das Triebwerk eine Kraft fin einer Richtung erzeugt dirund vom Massenmittelpunkt um einen Vektor versetzt ist r(nicht um den geometrischen Mittelpunkt oder den Mittelpunkt des Sprites!), Hat dies folgende Auswirkungen auf die lineare Komponente:

t = f * dir // f is a scalar, dir is unit length

Die Auswirkung auf die Winkelgeschwindigkeit ergibt sich aus dem Drehmoment:

tau = f * <dir.x, dir.y, 0> CROSS <r.x, r.y, 0> // cross product

tist ein Kraftvektor (dh der lineare Schub). tauist ein vorzeichenbehafteter Skalar, der, geteilt durch das Massenträgheitsmoment, die Winkelbeschleunigung ergibt. Es ist wichtig, dass dirund rsich beide im selben Koordinatenraum befinden, dh beide in lokalen Koordinaten oder beide in Weltkoordinaten.

Die Gesamtlinearbeschleunigung des Schiffes ergibt sich aus der Summe der ts für jedes Triebwerk geteilt durch die Schiffsmasse. In ähnlicher Weise ist die Winkelbeschleunigung nur die Summe der Drehmomente geteilt durch das Massenträgheitsmoment (das ein anderer Skalar ist). Das Schiff dreht sich nicht, wenn das Gesamtdrehmoment Null ist. Ebenso bewegt es sich nicht, wenn der Gesamtschub Null ist. Das Rückrufdrehmoment ist ein Skalar, aber der Schub (die Summe der t) ist ein 2D-Vektor.

Der Punkt dieser Darstellung ist, dass wir jetzt unser Problem als lineares Programm schreiben können . Sagen Sie zuerst, wir möchten, dass sich unser Schiff dreht, ohne sich zu bewegen . Wir haben eine Variable für jedes Triebwerk: $ x_1, x_2, ... $. Dies ist die Menge an Schub, die das Triebwerk liefert. Eine Reihe von Einschränkungen ist:

0 <= x_i < fmax_i  //for each i

wo fmaxist die maximale Kraft für dieses Triebwerk (dies lässt uns stärkere oder schwächere haben). Als nächstes sagen wir, dass beide Gleichungen:

0 = Sum_i  x_i * dir_i.x
0 = Sum_i  x_i * dir_i.y

Dies kodiert die Einschränkung, dass wir keine lineare Beschleunigung anwenden, indem wir sagen, dass der Gesamtschub Null ist (Schub ist ein Vektor, also sagen wir einfach, dass jeder Teil Null ist).

Jetzt wollen wir, dass sich unser Schiff dreht. Vermutlich wollen wir das so schnell wie möglich tun, also wollen wir:

max (Sum_i  x_i * c_i)
where c_i = <dir_i.x, dir_i.y, 0> CROSS <r_i.x, r_i.y, 0>

Das Lösen nach dem x_i, während die obigen Ungleichungen und Gleichungen erfüllt werden, während die obige Summe maximiert wird, gibt uns den gewünschten Schub. Die meisten Programmiersprachen verfügen über eine LP-Bibliothek. Fügen Sie einfach das obige Problem ein und es wird Ihre Antwort hervorbringen.

Ein ähnliches Problem wird uns bewegen lassen, ohne uns umzudrehen. Nehmen wir an, wir schreiben unser Problem in ein Koordinatensystem, in dem wir uns in die positive x-Richtung bewegen wollen. Dann sind die Einschränkungen:

0 <= x_i < fmax_i  //for each i
max Sum_i  x_i * dir_i.x
0 = Sum_i  x_i * dir_i.y
0 = (Sum_i  x_i * c_i)
where c_i = <dir_i.x, dir_i.y, 0> CROSS <r_i.x, r_i.y, 0> // as before

Mit der Einschränkung, dass die Triebwerke nur Schub in einer einzigen Richtung erzeugen können, sind der Art der Rotationen und linearen Geschwindigkeiten, die Sie erreichen können, Grenzen gesetzt. Dies wird sich als die Lösung manifestieren 0 = x_1 = x_2 = ... = x_n, was bedeutet, dass Sie niemals irgendwo hinkommen werden. Um dies zu mildern, schlage ich vor, ein Paar kleiner, schwacher (etwa 5% oder 10%) Triebwerke für jeden Spieler hinzuzufügen, der das Triebwerk auf beiden Seiten in einem Winkel von 45 Grad platziert. Dies gibt der Lösung mehr Flexibilität, da diese verwendet werden können, um schwachen Sekundäreffekten der Hauptantriebe entgegenzuwirken.

Für bis zu 100 Thruster ist die Lösung für die LP schnell genug, um pro Frame durchgeführt zu werden. Da die Lösung jedoch nicht vom Standort oder dem aktuellen Status abhängt, können Sie die Lösung für jede sinnvolle Controller-Eingabekombination vorberechnen, wenn sich die Form ändert (dies schließt das Hinzufügen von Nicht-Triebwerken ein, die das Trägheitsmoment oder die Masse des Schiffes ändern). denn dann befinden sich die Triebwerke relativ zum Massenmittelpunkt an einer anderen Stelle!). Dies sind 24 Möglichkeiten (dh 8 Richtungen mal (Linkslauf, keine Drehung, Rechtslauf)).


Sehr gut erklärt!
Kim

1
Was Sum_iheißt in diesem Zusammenhang?
S. Tarık Çetin

1

Mein erster Gedanke war eine rein empirische Lösung, die das Rigg in einer Sandbox-Umgebung für unterschiedliche Schubgrade simuliert, um das Verhalten zu bestimmen. Anstatt auf der Suche nach einer deterministischen Lösung eine Menge komplexer Mathematik zu balancieren, können Sie diese numerisch erreichen, beispielsweise mit der Newton-Methode. Beispiel:

Der Schubbereich liegt zwischen 0 und 1000, wobei 1000 VIEL ist.

Schritt 1

Mit Vertrauen simulieren (0 + 1000) / 2 = 500. Ergebnis: zu viel Vertrauen

Schritt 2

Der Bereich liegt jetzt zwischen 0 und 500. Mit Vertrauen simulieren (0 + 500) / 2 = 250. Ergebnis: zu viel Vertrauen

Schritt 3

Der Bereich liegt jetzt zwischen 0 und 250. Mit Vertrauen simulieren (0 + 250) / 2 = 125. Ergebnis: Zu wenig Vertrauen

Schritt 4

Der Bereich liegt jetzt zwischen 125 und 250. Mit Vertrauen simulieren (125 + 250) /2=187.5 Das Ergebnis ist zu viel Vertrauen

Schritt # 5 Der Bereich liegt jetzt zwischen 125 und 187,5. Mit Vertrauen simulieren (125 + 187,5) /2=156,25. Das Ergebnis ist zu wenig Vertrauen

Schritt # 6 Der Bereich liegt jetzt zwischen 156,25 und 187,5. Der Bereich liegt unter dem Schwellenwert von 35, was bedeutet, dass es sich um eine ausreichend gute Schätzung handelt

Endergebnis = (187,5 + 156,25) / 2 = 171,875

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.