Powiedzmy, że mam ruchomą okólkę target
zdefiniowaną jako:
Vector2 position;
Vector2 velocity;
float radius;
I obrotowy turret
(zamontowany na jakimś poruszającym się pojeździe) zdefiniowany jako:
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
(Lub coś wzdłuż tych linii. Zauważ, że położenie i prędkość obu są kontrolowane gdzie indziej - załóż, że prędkość jest stała, a zmiany położenia zależą od prędkości.)
Próbuję napisać dwie powiązane funkcje AI, aby określić w danej ramce:
Jakie przyspieszenie kątowe (i w jakim kierunku) zastosować do kąta wieży, aby wieża była skierowana na cel?
Jeśli cel jest obecnie widoczny, czy może on (dowolna część w jego promieniu) być widoczny przez
x
kilka sekund, gdziex
jest ułamek sekundy? (Alternatywnie: czy istnieje inna strategia zapewniająca, że cel jest „zablokowany”, a nie tylko przelatuje przez celowniki?)
I przydałaby mi się pomoc ...
Odpowiedzi:
Najpierw musisz określić różnicę kąta między kierunkiem kierunku wieży a kierunkiem do celu.
Po uzyskaniu tych wielkości można ustawić wyrażenie drugiego stopnia dla kąta wieży. Musisz to obliczyć przy każdej aktualizacji, aby mieć pewność, że zawsze korzystasz z najnowszych danych pozycji i prędkości.
Tutaj pierwszy wyraz (zero stopni) w wyrażeniu przyspieszenia spowoduje, że wieża zacznie się obracać w kierunku celu. Jednak nie zatrzyma się w czasie, a raczej oscyluje wokół niego. Aby się zatrzymać, potrzebujemy drugiego członu tłumienia (pierwszego stopnia), który powoduje, że wysokiej prędkości obrotu przeciwstawia się duże przyspieszenie.
Teraz stałe dodatnie (niekoniecznie stałe programowe) muszą zostać określone i zrównoważone, aby system zachowywał się dobrze.
C0
to główna kontrola prędkości systemu. Wysoka wartość dlaC0
daje dużą prędkość obrotową, a niska wartość daje niską prędkość obrotową. Rzeczywista wartość zależy od wielu czynników, dlatego powinieneś użyć tutaj metody prób i błędów.C1
kontroluje wielkość tłumienia. Wyróżnik równania kwadratowego mówi nam, że jeśliC1*C1 - 4*C0 >= 0
mamy system non-oscylacyjny.Prawdopodobnie powinieneś wybrać
C1
nieco większy niż ten ze względów liczbowych, ale nie za duży, ponieważ może być bardzo nadmiernie tłumiony i wolno reagować. Ponownie musisz dostosować.Należy również pamiętać, że ten kod oblicza tylko przyspieszenie kątowe. Kąt i prędkość kątowa muszą zostać zaktualizowane z tego miejsca gdzieś indziej, przy użyciu i pewnego rodzaju integratora. Z pytania zakładam, że zostało to uwzględnione.
Wreszcie jest coś do powiedzenia na temat opóźnień, ponieważ wieża prawdopodobnie zawsze będzie w tyle, gdy śledzi szybki cel. Prostym sposobem na rozwiązanie tego problemu jest dodanie liniowej prognozy do pozycji celu, tj. Zawsze celowanie lekko do przodu w kierunku do przodu celu.
Co do utrzymywania przez pewien czas wieży w promieniu celu, może to być trudny wymóg nałożenia bezpośrednio na tego rodzaju system. Możesz być pewien, że ten kontroler będzie dążył do tego, aby wieżyczka cały czas była wycelowana w cel (a raczej przewidywaną pozycję). Jeśli wynik okaże się nie być zadowalająca trzeba zmodyfikować parametry
predictionTime
,C0
iC1
(w ramach stabilnych granicach).źródło
k
), a C1 jest współczynnikiem tłumienia (zwykle nazywanym „B” lub „c”). Tak, więc można zminimalizować oscylację, zwiększając tłumienie, ale problem polega na tym, że nie próbuje przewidzieć, gdzie będzie cel , więc jest skazany na opóźnienie w stosunku do pożądanego celu.To, co masz tutaj, to podstawowy problem kontrolny . Wieża to system, przyspieszenie to kontrola, a czujnik mierzy pozycję / prędkość. Istnieje wiele sposobów rozwiązania tych problemów, ponieważ jest to bardzo dobrze zbadany problem w inżynierii.
Kluczem jest stabilny system, tj. System, który nie generuje oscylacji. Zwykle odbywa się to przez dodanie tłumienia. Strona wikipedia powinna zacząć.
źródło
Najpierw obliczyć wektor od wieży do celu. Następnie porównaj to z bieżącym wektorem wieży. Następnie użyj różnicy między nimi, aby obliczyć przyspieszenie kątowe i prędkość kątową wymagane, aby wieżyczka obróciła się w odpowiednim czasie w odpowiednim kierunku.
OK, to wydawało się proste. Jednak naprawdę powinieneś spróbować przewidzieć pozycję celu, ponieważ cel będzie poruszał się przed obróceniem wieży. Aby to zrobić: -
gdzie P to pozycja, a V to prędkość, a indeks dolny to d dla celu (cel) is dla źródła (wieżyczka), co daje wektor kierunku:
gdzie D jest wektorem kierunku, a Dsd 'jest wymaganym kierunkiem w czasie t. Teraz obierz kierunek wieży w oparciu o aktualną pozycję oraz maksymalną prędkość i przyspieszenie dla danego czasu t: -
Ds i Ds 'są kierunkami źródła, a Rs jest prędkością obrotową. Mając to na uwadze, chcesz znaleźć t, kiedy Dsd '== Ds', a zatem Rs, wymagana prędkość obrotowa. Nie zapominaj, że wszystkie P, D i V mają składowe xiy.
Nie wziąłem tutaj pod uwagę przyspieszenia - to dodaje jeszcze więcej do złożoności. Po uzyskaniu Rs i t prawdopodobnie można by zbliżyć paraboliczne Rs (tj. Przyspieszać i zwalniać), aby uzyskać ten sam wynik.
źródło
Prawdopodobnie szukasz tutaj kontrolera PID , podobnego do odpowiedzi przyjętej na to pytanie SO
Początkowo odpowiedziałem na to pytanie „tocząc własne”, ale ta odpowiedź jest znacznie bardziej kompletna i elegancka.
źródło
Pierwszą rzeczą do zrobienia jest obliczenie kąta między strumieniem a śledzonym obiektem.
Następnie sprawdź, czy użycie bieżącej prędkości torrenta i zastosowanie maksymalnego przyspieszenia wstecz (zatrzymanie torrenta) spowoduje, że torrent zatrzyma się przed lub po śledzonym obiekcie.
Jeśli odpowiedź brzmi, że torrent zatrzyma się przed śledzonym obiektem, zastosuj maksymalne przyspieszenie do przodu (zwiększenie prędkości).
Jeśli odpowiedź brzmi, że torrent zatrzyma się za śledzonym obiektem, zastosuj maksymalne przyspieszenie do tyłu (zatrzymując torrent).
W ten sposób torrent będzie zawsze przybywał najszybciej i zatrzyma się we właściwym punkcie (lub ułamek później).
źródło