Pelacakan Target: Kapan mempercepat dan memperlambat menara putar?


24

Katakanlah saya memiliki lingkaran bergerak yang targetdidefinisikan sebagai:

Vector2 position;
Vector2 velocity;
float radius;

Dan yang berputar turret(dipasang pada jenis kendaraan yang bergerak) didefinisikan sebagai:

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

(Atau sesuatu di sepanjang garis itu. Perhatikan bahwa posisi dan kecepatan keduanya dikendalikan di tempat lain - anggap kecepatan konstan dan perubahan posisi berdasarkan kecepatan.)

Saya mencoba untuk menulis dua fungsi AI terkait untuk menentukan, pada bingkai yang diberikan:

  • Apa percepatan sudut (dan ke arah mana) yang diterapkan pada sudut turret untuk menjaga turret tetap mengarah ke target?

  • Jika target saat ini sudah di depan mata, dapatkah itu (bagian mana pun dalam radius) dapat dilihat selama beberapa xdetik, di mana xsebagian kecil dari yang kedua? (Alternatifnya: apakah ada strategi lain untuk memastikan target benar-benar "terkunci" dan tidak hanya terbang melintasi pemandangan?)

Dan saya bisa menggunakan bantuan ...


1
Anda mungkin memiliki nilai yang berbeda untuk akselerasi dan perlambatan rotasi - di dunia nyata, yang satu mungkin motor dan yang lain rem.
e100

Jawaban:


19

Pertama, Anda perlu menentukan perbedaan sudut antara arah turret menghadap dan arah ke target.

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;

Setelah Anda memiliki jumlah ini, Anda dapat mengatur ekspresi derajat kedua untuk sudut turret. Anda perlu menghitung ini pada setiap pembaruan untuk memastikan Anda selalu menggunakan data terbaru dari posisi dan kecepatan.

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

Di sini, suku pertama (nol derajat) dalam ekspresi akselerasi akan menyebabkan turet mulai berbalik ke arah target. Namun itu tidak akan berhenti tepat waktu tetapi berosilasi bolak-balik di atasnya. Untuk menghentikannya kita membutuhkan peredam istilah kedua (derajat pertama) yang menyebabkan kecepatan belok tinggi ditentang oleh akselerasi tinggi.

Sekarang konstanta positif (tidak harus konstanta program) perlu ditentukan dan seimbang untuk membuat sistem berperilaku baik. C0adalah kontrol utama untuk kecepatan sistem. Nilai yang tinggi untuk C0akan memberikan kecepatan belokan cepat dan nilai yang rendah akan memberikan kecepatan belokan yang rendah. Nilai aktual tergantung pada banyak faktor sehingga Anda harus menggunakan coba-coba di sini. C1mengontrol besarnya redaman. The diskriminan dari persamaan kuadrat memberitahu kita bahwa jika C1*C1 - 4*C0 >= 0kita memiliki sistem non-berosilasi.

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

Anda mungkin harus memilih C1yang sedikit lebih besar dari ini karena alasan numerik, tetapi tidak terlalu besar karena mungkin akan menjadi terlalu lembab dan lambat untuk merespons. Sekali lagi, Anda perlu mengubah.

Juga penting untuk dicatat bahwa kode ini hanya menghitung percepatan sudut. Sudut dan kecepatan sudut perlu diperbarui dari tempat lain ini, menggunakan dan integrator dari beberapa jenis. Dari pertanyaan saya berasumsi bahwa ini telah dibahas.

Akhirnya ada sesuatu untuk dikatakan tentang lagging, karena turret mungkin akan selalu tertinggal ketika melacak target yang cepat. Cara sederhana untuk mengatasi ini adalah dengan menambahkan prediksi linier ke posisi target, yaitu selalu mengarah sedikit ke depan dalam arah maju target.

// 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;
/// ...

Adapun untuk menjaga turet diarahkan dalam radius target untuk beberapa waktu, ini mungkin merupakan persyaratan yang sulit untuk memaksakan langsung pada sistem semacam ini. Anda dapat yakin bahwa pengontrol ini akan berusaha untuk menjaga turet diarahkan pada target (atau lebih tepatnya posisi yang diprediksi) setiap saat. Jika hasilnya ternyata tidak memuaskan Anda harus memodifikasi parameter predictionTime, C0dan C1(dalam batas stabil).


Saya tidak memenuhi syarat untuk mengatakan apakah ini benar atau tidak, tetapi kedengarannya seperti hal yang cerdas! Saya telah memecahkan jenis-jenis masalah ini di masa lalu dengan memperkirakan efek percepatan untuk mengetahui kapan harus berakselerasi dan kapan harus "menerapkan jeda". Apakah itu berarti saya telah melakukan kesalahan?
Iain

Atan2 membuat metode ini sulit untuk beradaptasi dengan sistem prediksi karena parameter x dan y untuk atan2 menjadi tergantung pada t.
Mendesing

Ini persis solusi yang saya mengisyaratkan pada jawaban saya di bawah ini. Detail dan presentasi yang luar biasa!
drxzcl

@Ain: Tidak ada yang benar dan salah di sini. Meskipun saya kira metode Anda akan memiliki dua status diskrit: akselerasi / perlambat, metode ini terinspirasi oleh regulator dari teori kontrol, penskalaan akselerasi untuk membuat respons cepat sekaligus mengurangi overshoot dan osilasi.
Staffan E

1
Seperti dengan komentar lain, ini akan bekerja untuk target stasioner tetapi kemungkinan tidak dapat diterima untuk target bergerak. Istilah C0 dan C1 adalah bahan pegas teredam tradisional, di mana C0 mewakili kekuatan pegas (biasanya disebut k) dan C1 adalah faktor redaman (biasanya disebut 'B' atau 'c'). Jadi ya, Anda dapat meminimalkan osilasi dengan memiringkan redaman tetapi masalahnya adalah ini tidak mencoba mengantisipasi di mana target akan berada, jadi pasti akan ketinggalan tujuan yang diinginkan.
dash-tom-bang

3

Apa yang Anda miliki di sini adalah masalah kontrol dasar . Menara adalah sistem, akselerasi adalah kontrol dan sensor mengukur posisi / kecepatan. Ada banyak cara untuk mengatasi masalah ini, karena ini merupakan masalah yang dipelajari dengan sangat baik di bidang teknik.

Kunci diakhiri dengan sistem stabil, yaitu sistem yang tidak menghasilkan osilasi. Ini biasanya dilakukan dengan menambahkan redaman. Halaman wikipedia harus membantu Anda memulai.


2

Pertama, hitung vektor dari turret ke target. Kemudian bandingkan dengan vektor turret saat ini. Kemudian gunakan perbedaan antara keduanya untuk menghitung akselerasi sudut dan kecepatan sudut yang diperlukan untuk membuat turet berputar ke titik di arah yang benar dalam waktu tertentu.

Oke, itu tampak sederhana. Namun, Anda harus benar-benar mencoba mengantisipasi posisi target karena target akan bergerak pada saat Anda memutar menara. Untuk melakukan ini:-

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

di mana P adalah posisi dan V adalah kecepatan dan subskrip adalah d untuk tujuan (target) dan s untuk sumber (turet), yang memberikan vektor arah: -

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

di mana D adalah vektor arah dan Dsd 'adalah arah yang diperlukan pada waktu t. Sekarang, cari tahu arah turret berdasarkan posisi saat ini dan kecepatan maksimum dan akselerasi untuk waktu tertentu t: -

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

Ds dan Ds 'adalah arah sumber dan Rs adalah kecepatan rotasi. Dengan semua itu, Anda ingin mencari t ketika Dsd '== Ds' dan dengan demikian Rs, kecepatan rotasi yang diperlukan. Jangan lupa bahwa semua komponen P, D, dan V memiliki komponen x dan y.

Saya belum memperhitungkan akselerasi di sini - yang menambah lebih banyak kompleksitas. Setelah Anda mendapatkan Rs dan t, Anda mungkin bisa memperkirakan Rs parabola (yaitu mempercepat dan mengurangi kecepatan) untuk mendapatkan hasil yang sama.


Ini sepertinya jawaban yang bagus untuk perhitungan intersepsi, tapi sayangnya ada celah besar antara orang yang bisa membaca notasi matematika semacam itu dan mengubahnya menjadi kode program, dan sebagian besar orang membuat game yang belum tahu jawabannya. pertanyaan. Dengan kata lain, saya pikir para pengembang game yang dapat membaca notasi matematika itu, mungkin sudah dapat mengetahui cara memprogram solusi menembak. Itu akan membantu saya memahami formula Anda jika Anda menjelaskan apa arti istilah Anda.
Dronz

2

Apa yang mungkin Anda cari di sini adalah Kontroler PID , mirip dengan jawaban yang diterima pada pertanyaan SO ini

Saya awalnya menjawab pertanyaan itu dengan "menggulirkan milik saya" tetapi jawaban ini secara signifikan lebih lengkap dan elegan.


0

Hal pertama yang harus dilakukan adalah menghitung sudut antara turrent dan objek yang dilacak.
Hal berikutnya adalah memeriksa apakah menggunakan kecepatan torrent saat ini dan menerapkan akselerasi maksimum mundur (menghentikan torrent) akankah torrent berhenti sebelum atau setelah objek yang dilacak.
Jika jawabannya adalah bahwa torrent akan berhenti sebelum objek yang dilacak, terapkan akselerasi maksimum ke depan (meningkatkan kecepatan).
Jika jawabannya adalah bahwa torrent akan berhenti setelah objek yang dilacak, terapkan akselerasi maksimum mundur (menghentikan torrent).
Dengan cara ini torrent akan selalu tiba paling cepat dan akan berhenti di titik yang tepat (atau sebagian kecil setelah).

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.