Das ist ein Problem, das ich bei der Implementierung eines Spiels mit der LÖVE -Maschine, die box2d mit Lua-Skripten.
Das Ziel ist einfach: Ein revolverartiges Objekt (von oben gesehen, in einer 2D-Umgebung) muss sich so orientieren, dass es auf ein Ziel zeigt.
Der Revolver befindet sich auf den Koordinaten x, y und das Ziel befindet sich auf tx, ty. Wir können annehmen, dass x, y fest sind, aber tx, ty neigen dazu, von einem Moment zum anderen zu variieren (d. H. Sie wären der Mauszeiger).
Der Revolverkopf hat einen Rotor, der eine Drehkraft (Drehmoment) zu jedem Zeitpunkt im oder gegen den Uhrzeigersinn aufbringen kann. Die Größe dieser Kraft hat eine obere Grenze namens maxTorque.
Der Revolver hat auch eine gewisse Rotationsträgheit, die für eine Winkelbewegung auf die gleiche Weise wirkt wie die Masse für eine lineare Bewegung. Es gibt keinerlei Reibung, deshalb dreht sich der Turm weiter, wenn er eine Winkelgeschwindigkeit hat.
Der Revolver verfügt über eine kleine AI-Funktion, die seine Ausrichtung neu auswertet, um zu überprüfen, ob er in die richtige Richtung zeigt, und aktiviert den Rotator. Dies geschieht jedes dt (~ 60 mal pro Sekunde). So sieht es jetzt aus:
%Vor%... es scheitert. Lassen Sie mich das mit zwei illustrativen Situationen erklären:
Ich denke, dass mein Revolver anfangen sollte, Drehmomente in der "entgegengesetzten Richtung des kürzesten Weges" anzulegen, bevor er den Zielwinkel erreicht (wie ein Auto, das vor dem Anhalten bremst).
Intuitiv denke ich, dass der Revolver "Drehmomente in der entgegengesetzten Richtung des kürzesten Weges beginnen sollte, wenn er etwa auf halbem Weg zum Zielobjekt ist". Meine Intuition sagt mir, dass es etwas mit der Winkelgeschwindigkeit zu tun hat. Und dann ist da noch die Tatsache, dass das Ziel mobil ist - ich weiß nicht, ob ich das irgendwie berücksichtigen oder einfach ignorieren sollte.
Wie berechne ich, wann der Turm "anfangen muss zu bremsen"?
Ok ich glaube, ich habe die Lösung.
Dies basiert auf der Idee von Beta, aber mit einigen notwendigen Verbesserungen. Hier geht es:
%Vor% Das Konzept dahinter ist einfach: Ich muss berechnen, wie viel "Raum" (Winkel) der Turm braucht, um vollständig zu stoppen. Das hängt davon ab, wie schnell sich der Turm bewegt und wie viel Drehmoment er auf sich selbst anwenden kann. Kurz gesagt, das berechne ich mit brakingAngle
.
Meine Formel zur Berechnung dieses Winkels unterscheidet sich geringfügig von der Beta. Ein Freund von mir half mir mit der Physik, und nun, sie scheinen zu arbeiten. Das Hinzufügen von w war meine Idee.
Ich musste eine "normalizing" Funktion implementieren, die jeden Winkel zurück in die 0-2Pi Zone bringt.
Anfangs war das ein verschränktes Wenn-sonst-wenn-sonst. Da die Bedingungen sehr repetitiv waren, verwendete ich eine boolesche Logik , um den Algorithmus zu vereinfachen. Der Nachteil ist, dass, selbst wenn es in Ordnung ist und es nicht kompliziert ist, es sich nicht zeigt, warum es funktioniert.
Sobald der Code ein wenig sauberer ist, werde ich hier einen Link zu einer Demo veröffentlichen.
Vielen Dank.
EDIT: Working LÖVE Beispiel ist jetzt verfügbar hier . Die wichtigen Sachen sind in actors / AI.lua (die .love-Datei kann mit einem Zip-Komprimierer geöffnet werden)
Denken Sie rückwärts. Der Turm muss "anfangen zu bremsen", wenn er gerade genug Raum hat, um von seiner momentanen Winkelgeschwindigkeit zu einem toten Stopp abzubremsen, der der gleiche ist wie der Raum, den er von einem toten Stopp zu seiner gegenwärtigen Winkelgeschwindigkeit beschleunigen müsste, die Sie können auch Probleme mit kleinen Oszillationen um das Ziel herum haben, wenn Ihre Schrittzeit zu groß ist; Das erfordert ein wenig mehr Finesse, du musst etwas früher und sanfter bremsen. Mach dir keine Sorgen, bis du es siehst. Das sollte jetzt gut genug sein, aber es gibt noch einen weiteren Haken, der Sie später stolpern könnte: zu entscheiden, welchen Weg Sie gehen sollen. Manchmal ist es viel schneller, wenn man schon so weit ist. In diesem Fall müssen Sie entscheiden, welcher Weg weniger Zeit in Anspruch nimmt, was nicht schwierig ist, aber Sie müssen diese Brücke überqueren, wenn Sie dazu kommen. BEARBEITEN: Versuchen Sie Folgendes:
Meine Gleichung war falsch, es sollte Inertia / 2 * maxTorque sein, nicht 2 * maxTorque / Inertia (das ist, was ich bekomme, wenn ich versuche, Algebra an der Tastatur zu machen). Ich habe es behoben.
Dies scheint ein Problem zu sein, das mit einem PID-Controller gelöst werden kann. Ich benutze sie in meiner Arbeit, um eine Heizleistung zu steuern, um eine Temperatur einzustellen.
Für die Komponente 'P' wenden Sie ein Drehmoment an, das proportional zur Differenz zwischen dem Turmwinkel und dem Zielwinkel ist, d. h.
P = P0 * differenceAngle
Wenn dies immer noch zu viel oszilliert (es wird ein bisschen), dann fügen Sie eine 'I' Komponente hinzu,
%Vor%Wenn dies zu stark überschwingt, fügen Sie einen 'D'-Ausdruck hinzu
%Vor% P0
, I0
und D0
sind Konstanten, die Sie einstellen können, um das gewünschte Verhalten zu erhalten (d. h. wie schnell die Geschütze reagieren usw.)
Nur als Tipp, normalerweise P0
& gt; I0
& gt; D0
Verwenden Sie diese Begriffe, um zu bestimmen, wie viel Drehmoment angewendet wird, d. h.
%Vor%BEARBEITEN:
Hier ist eine Anwendung geschrieben mit Verarbeitung , die PID verwendet. Es funktioniert eigentlich ohne I oder D. Sehen Sie es funktioniert hier
%Vor%Sie können eine Gleichung für die Winkelgeschwindigkeit vs. den Winkelabstand für den Rotor finden, wenn das beschleunigende Drehmoment angewendet wird, und die gleiche Gleichung für das Anlegen des Bremsmoments finden.
Ändern Sie dann die Bruchgleichung so, dass sie die Winkelabstandsachse im gewünschten Winkel inte- griert. Mit diesen zwei Gleichungen können Sie den Winkelabstand berechnen, bei dem sie sich schneiden, was Ihnen den Bruchpunkt geben würde.
Könnte aber total falsch sein, so lange nicht mehr. Wahrscheinlich eine einfachere Lösung. Ich gehe davon aus, dass die Beschleunigung nicht linear ist.
Eine vereinfachte Version dieses Problems ist ziemlich einfach zu lösen. Angenommen, der Motor hat ein unendliches Drehmoment, dh er kann die Geschwindigkeit sofort ändern. Dies ist offensichtlich nicht physikalisch korrekt, aber macht das Problem viel einfacher zu lösen und am Ende ist kein Problem.
Fokussiere auf eine Zielwinkelgeschwindigkeit, nicht auf einen Zielwinkel.
%Vor%Der Grund dafür ist, dass der Turm automatisch versucht, sich langsamer zu bewegen, wenn er seinen Zielwinkel erreicht.
Das unendliche Drehmoment wird durch die Tatsache maskiert, dass der Revolver nicht versucht, die Entfernung augenblicklich zu schließen. Stattdessen versucht es, die Entfernung in einem Zeitschritt zu schließen. Auch da der Bereich von -pi bis pi ziemlich klein ist, zeigen sich die möglicherweise wahnwitzigen Beschleunigungen nie. Die maximale Winkelgeschwindigkeit hält die Rotationen des Turms realistisch.
Ich habe noch nie die reale Gleichung für die Lösung mit Drehmoment anstelle der Winkelgeschwindigkeit ausgearbeitet, aber ich kann mir vorstellen, dass sie den PID-Gleichungen sehr ähnlich sieht.