Zielverfolgung: Wann soll ein rotierender Turm beschleunigt und abgebremst werden?

24

Angenommen, ich habe ein sich bewegendes Rundschreiben targetdefiniert als:

Vector2 position;
Vector2 velocity;
float radius;

Und eine drehende turret(an einem fahrenden Fahrzeug angebrachte) definiert als:

Vector2 position;
Vector2 velocity;
float angle; // radians
float angularVelocity; // radians per second
const float maxAngularVelocity; // radians per second
const float maxAngularAcceleration; // radians per second per second

(Oder so ähnlich. Beachten Sie, dass Position und Geschwindigkeit von beiden an anderer Stelle gesteuert werden - nehmen Sie an, dass die Geschwindigkeit konstant ist und sich die Position basierend auf der Geschwindigkeit ändert.)

Ich versuche, zwei verwandte KI-Funktionen zu schreiben, um für einen bestimmten Frame Folgendes zu bestimmen:

  • Welche Winkelbeschleunigung (und in welche Richtung) muss auf den Revolverwinkel angewendet werden, damit der Revolver auf das Ziel zeigt?

  • Wenn das Ziel gerade in Sichtweite ist, kann es (irgendein Teil innerhalb seines Radius) für xSekunden in Sichtweite gehalten werden , wo xist ein Bruchteil einer Sekunde? (Alternativ: Gibt es eine andere Strategie, um sicherzustellen, dass das Ziel tatsächlich "fest" ist und nicht nur über die Sehenswürdigkeiten fliegt?)

Und ich könnte Hilfe gebrauchen ...

Andrew Russell
quelle
1
Möglicherweise haben Sie unterschiedliche Werte für die Drehbeschleunigung und -verzögerung - in der Realität ist einer wahrscheinlich ein Motor und der andere eine Bremse.
e100

Antworten:

19

Zuerst müssen Sie die Winkeldifferenz zwischen der Richtung des Turms und der Richtung zum Ziel bestimmen.

Vector2 turretToTarget = target.position - turret.position;
float desiredAngle = atan2(turretToTarget.y, turretToTarget.x);
float angleDiff = desiredAngle - turret.angle;

// Normalize angle to [-PI,PI] range. This ensures that the turret
// turns the shortest way.
while (angleDiff < -PI) angleDiff += 2*PI;
while (angleDiff >= PI) angleDiff -= 2*PI;

Sobald Sie diese Größen haben, können Sie einen Ausdruck zweiten Grades für den Revolverwinkel einrichten. Sie müssen dies bei jeder Aktualisierung berechnen, um sicherzustellen, dass Sie immer die neuesten Positions- und Geschwindigkeitsdaten verwenden.

// Compute angular acceleration.
const float C0 = // Must be determined.
const float C1 = // Must be determined.
float angularAcc = C0 * angleDiff - C1 * turret.angularVelocity;

Hier bewirkt der erste Term (null Grad) im Beschleunigungsausdruck, dass sich der Turm in Richtung des Ziels dreht. Es wird jedoch nicht rechtzeitig aufhören, sondern darüber hin- und herschwingen. Damit es stoppt, benötigen wir den zweiten Dämpfungsterm (erster Grad), der bewirkt, dass einer hohen Drehgeschwindigkeit eine hohe Beschleunigung gegenübersteht.

Nun müssen die positiven Konstanten (nicht unbedingt Programmkonstanten) bestimmt und ausgeglichen werden, damit sich das System gut verhält. C0ist die Hauptsteuerung für die Geschwindigkeit des Systems. Ein hoher Wert für C0ergibt eine schnelle Drehgeschwindigkeit und ein niedriger Wert ergibt eine niedrige Drehgeschwindigkeit. Der tatsächliche Wert hängt von vielen Faktoren ab, daher sollten Sie hier "trial and error" verwenden. C1regelt die Stärke der Dämpfung. Die Diskriminante der quadratischen Gleichung sagt uns, dass C1*C1 - 4*C0 >= 0wir ein nicht oszillierendes System haben.

// New definition.
const float C1 = 2*sqrt(C0); // Stabilizes the system.

Sie sollten wahrscheinlich C1aus numerischen Gründen ein wenig größer wählen , aber nicht zu groß, da es stattdessen sehr überlastet und langsam reagieren kann. Auch hier müssen Sie optimieren.

Es ist auch wichtig zu beachten, dass dieser Code nur die Winkelbeschleunigung berechnet. Der Winkel und die Winkelgeschwindigkeit müssen unter Verwendung einer Art Integrator von dieser Stelle aus aktualisiert werden. Aus der Frage gehe ich davon aus, dass dies abgedeckt wurde.

Zum Schluss gibt es noch einiges zum Thema Verzögerung zu sagen, da der Turm bei der Verfolgung eines schnellen Ziels wahrscheinlich immer zurückbleibt. Eine einfache Möglichkeit, dies zu beheben, besteht darin, der Position des Ziels eine lineare Vorhersage hinzuzufügen, dh immer leicht nach vorne in die Vorwärtsrichtung des Ziels zu zielen.

// Improvement of the first lines above.
const float predictionTime = 1; // One second prediction, you need to experiment.
Vector2 turretToTarget = target.position + predictionTime * target.velocity - turret.position;
/// ...

Um den Turm für einige Zeit im Radius des Ziels zu halten, kann dies eine schwierige Anforderung sein, die direkt an ein solches System gestellt werden muss. Sie können sicher sein, dass dieser Controller stets bestrebt ist, den Turm auf das Ziel (bzw. die vorhergesagte Position) auszurichten. Wenn das Ergebnis nicht zufriedenstellend erweist , müssen Sie die Parameter ändern predictionTime, C0und C1(innerhalb stabiler Grenzen).

Staffan E
quelle
Ich bin nicht qualifiziert zu sagen, ob dies richtig ist oder nicht, aber es klingt wie ein paar clevere Sachen! Ich habe diese Art von Problemen in der Vergangenheit gelöst, indem ich die Wirkung der Beschleunigung vorausgesagt habe, um herauszufinden, wann zu beschleunigen und wann "die Pausen" anzuwenden sind. Heißt das, ich habe es falsch gemacht?
Iain
Das atan2 macht es schwierig, diese Methode an ein Vorhersagesystem anzupassen, da die x- und y-Parameter von atan2 von t abhängig werden.
Skizz 30.07.10
Dies ist genau die Lösung, auf die ich in meiner Antwort unten hingewiesen habe. Hervorragendes Detail und Präsentation!
drxzcl
@Iain: Nein, hier gibt es kein Richtig und Falsch. Obwohl Ihre Methode vermutlich zwei diskrete Zustände haben würde: Beschleunigen / Verlangsamen, ist diese Methode von einem Regler aus der Steuerungstheorie inspiriert, der die Beschleunigung skaliert, um eine schnelle Reaktion zu erzielen und gleichzeitig Überschwingen und Oszillationen zu reduzieren.
Staffan E
1
Wie bei den anderen Kommentaren funktioniert dies für ein stationäres Ziel, ist jedoch für sich bewegende Ziele wahrscheinlich nicht akzeptabel. Die Ausdrücke C0 und C1 sind herkömmliche gedämpfte Federbeläge, wobei C0 die Federkraft kdarstellt (üblicherweise als "B" oder "c" bezeichnet ) und C1 den Dämpfungsfaktor darstellt (üblicherweise als "B" oder "c" bezeichnet). Also ja, können Sie Schwingung minimieren , indem die Dämpfung kurbelt aber das Problem ist , dass dies nicht zu antizipieren nicht versuchen , wo das Ziel wird sein, so zum Scheitern verurteilt ist das gewünschte Ziel zu hinken.
Dash-Tom-Bang
3

Was Sie hier haben, ist ein grundlegendes Steuerungsproblem . Der Turm ist das System, die Beschleunigung ist die Steuerung und der Sensor misst Position / Geschwindigkeit. Es gibt viele Möglichkeiten, diese Probleme anzugehen, da es sich um ein sehr gut untersuchtes Problem im Ingenieurwesen handelt.

Der Schlüssel liegt in einem stabilen System, dh einem System, das keine Schwingungen erzeugt. Dies geschieht normalerweise durch Hinzufügen von Dämpfung. Die Wikipedia-Seite sollte Ihnen den Einstieg erleichtern.

drxzcl
quelle
2

Berechnen Sie zunächst den Vektor vom Turm zum Ziel. Vergleichen Sie dies dann mit dem aktuellen Vektor des Turms. Verwenden Sie dann die Differenz zwischen beiden, um die Winkelbeschleunigung und die Winkelgeschwindigkeit zu ermitteln, die erforderlich sind, damit sich der Turm innerhalb einer bestimmten Zeit in die richtige Richtung dreht.

OK, das schien einfach zu sein. Sie sollten jedoch wirklich versuchen, die Position des Ziels vorherzusehen, da sich das Ziel bis zu dem Zeitpunkt bewegen wird, an dem Sie den Turm gedreht haben. Um dies zu tun:-

Pd' = Pd + t.Vd
Ps' = Ps + t.Vs

wobei P die Position und V die Geschwindigkeit ist und der Index d für das Ziel (Ziel) und s für die Quelle (Turm) ist, was einen Richtungsvektor ergibt:

Dsd' = Pd' - Ps' = Pd + t.Vd - (Ps + t.Vs) = Pd - Ps + (Vd - Vs).t

wobei D ein Richtungsvektor ist und Dsd 'die erforderliche Richtung zum Zeitpunkt t ist. Berechnen Sie nun die Richtung des Revolvers basierend auf der aktuellen Position und der maximalen Geschwindigkeit und Beschleunigung für eine bestimmte Zeit t:

Ds' = t.Ds.Rs -> this is a vector rotation

Ds und Ds 'sind die Quellrichtungen und Rs ist die Rotationsgeschwindigkeit. Bei alledem wollen Sie t finden, wenn Dsd '== Ds' und damit Rs die erforderliche Rotationsgeschwindigkeit ist. Vergiss nicht, dass alle Ps, Ds und Vs x- und y-Komponenten haben.

Ich habe die Beschleunigung hier nicht berücksichtigt - das erhöht die Komplexität erheblich. Sobald Sie Rs und t haben, können Sie sich wahrscheinlich einem parabolischen Rs annähern (dh beschleunigen und verlangsamen), um das gleiche Ergebnis zu erzielen.

Skizz
quelle
Dies sieht nach einer guten Antwort für die Abfangberechnung aus, aber leider gibt es eine große Lücke zwischen Leuten, die diese Art von mathematischer Notation lesen und in Programmcode umwandeln können, und den meisten Leuten, die Spiele machen, auf die die Antwort noch nicht bekannt ist die Frage. Mit anderen Worten, ich denke, die Spieleentwickler, die diese mathematische Notation lesen können, können wahrscheinlich bereits herausfinden, wie die Brennlösung zu programmieren ist. Es würde mir helfen, Ihre Formeln zu verstehen, wenn Sie erklären würden, was Ihre Begriffe bedeuten.
Dronz,
2

Was Sie hier wahrscheinlich suchen, ist ein PID-Regler , ähnlich der Antwort, die auf diese SO-Frage akzeptiert wurde

Ich hatte diese Frage zunächst mit "Rolling My Own" beantwortet, aber diese Antwort ist deutlich vollständiger und eleganter.

nicolaskruchten
quelle
0

Zunächst müssen Sie den Winkel zwischen dem aktuellen und dem verfolgten Objekt berechnen.
Als nächstes prüfen Sie, ob der Strom vor oder nach dem verfolgten Objekt stoppt, wenn Sie die aktuelle Geschwindigkeit des Stroms verwenden und die maximale Beschleunigung rückwärts anwenden (den Strom stoppen).
Wenn die Antwort lautet, dass der Strom vor dem verfolgten Objekt anhält, wenden Sie die maximale Beschleunigung vorwärts an (zunehmende Geschwindigkeit).
Wenn die Antwort lautet, dass der Strom nach dem verfolgten Objekt anhält, wenden Sie die maximale Beschleunigung rückwärts an (Anhalten des Stroms).
Auf diese Weise kommt der Strom immer am schnellsten an und stoppt am richtigen Punkt (oder einen Bruchteil später).

Dani
quelle