การติดตามเป้าหมาย: เมื่อใดที่จะเร่งและลดความเร็วของป้อมปืนหมุน?


24

ว่าฉันมีวงกลมเคลื่อนที่ที่targetกำหนด:

Vector2 position;
Vector2 velocity;
float radius;

และการหมุนturret(ติดตั้งบนยานพาหนะที่กำลังเคลื่อนที่บางชนิด) กำหนดเป็น:

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

(หรือบางสิ่งบางอย่างตามเส้นเหล่านั้นโปรดทราบว่าตำแหน่งและความเร็วของทั้งสองถูกควบคุมที่อื่น - สมมติว่าความเร็วคงที่และเปลี่ยนตำแหน่งตามความเร็ว)

ฉันพยายามเขียนฟังก์ชัน AI ที่เกี่ยวข้องสองรายการเพื่อกำหนดในกรอบที่กำหนด:

  • การเร่งความเร็วเชิงมุม (และทิศทางใด) ที่ใช้กับมุมของป้อมปืนเพื่อให้ป้อมปืนชี้ไปที่เป้าหมาย

  • หากเป้าหมายอยู่ในระยะมองเห็นจะสามารถเก็บส่วนใดส่วนหนึ่งไว้ในรัศมีเป็นระยะxเวลาไม่กี่วินาทีxเศษเสี้ยววินาที (ทางเลือก: มีกลยุทธ์อื่นที่จะทำให้แน่ใจว่าเป้าหมาย "ล็อคอยู่" จริง ๆ แล้วไม่ใช่แค่บินข้ามจุดชมวิวหรือไม่?)

และฉันสามารถใช้ความช่วยเหลือ ...


1
คุณอาจมีค่าที่แตกต่างกันสำหรับการเร่งความเร็วและการลดความเร็วในการหมุน - ในโลกแห่งความเป็นจริงอาจเป็นมอเตอร์และเบรคอีกอัน
e100

คำตอบ:


19

ก่อนอื่นคุณต้องพิจารณาความแตกต่างของมุมระหว่างป้อมปืนหันหน้าเข้าหาทิศทางและทิศทางไปยังเป้าหมาย

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;

เมื่อคุณมีปริมาณเหล่านี้คุณสามารถตั้งค่านิพจน์ระดับที่สองสำหรับมุมป้อมปืน คุณต้องคำนวณสิ่งนี้ในการอัพเดทแต่ละครั้งเพื่อให้แน่ใจว่าคุณใช้ข้อมูลตำแหน่งและความเร็วล่าสุดเสมอ

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

ที่นี่เทอมแรก (ศูนย์องศา) ในการแสดงความเร่งจะทำให้ป้อมปืนเริ่มหันเข้าหาเป้าหมาย อย่างไรก็ตามมันจะไม่หยุดในเวลา แต่ค่อนข้างจะแกว่งไปมา ในการทำให้หยุดเราต้องใช้เทอมที่สอง (ระดับแรก) ซึ่งทำให้ความเร็วในการเลี้ยวสูงถูกต่อต้านโดยการเร่งความเร็วสูง

ตอนนี้ค่าคงที่บวก (ไม่จำเป็นต้องเป็นค่าคงที่ของโปรแกรม) จำเป็นต้องได้รับการพิจารณาและสมดุลเพื่อให้ระบบทำงานได้ดี C0เป็นตัวควบคุมหลักสำหรับความเร็วของระบบ ค่าที่สูงสำหรับC0จะให้ความเร็วในการเปลี่ยนที่รวดเร็วและค่าต่ำจะให้ความเร็วในการกลึงต่ำ ค่าจริงขึ้นอยู่กับหลายปัจจัยดังนั้นคุณควรใช้การทดลองและข้อผิดพลาดที่นี่ C1ควบคุมขนาดการทำให้หมาด ๆ การเลือกปฏิบัติของสมการกำลังสองบอกเราว่าถ้าC1*C1 - 4*C0 >= 0เรามีระบบที่ไม่สั่น

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

คุณควรเลือกC1ใหญ่กว่านี้เล็กน้อยด้วยเหตุผลเชิงตัวเลข แต่ไม่ใหญ่เกินไปเพราะอาจทำให้ชื้นมากและตอบสนองช้า อีกครั้งคุณต้องปรับแต่ง

นอกจากนี้โปรดทราบว่ารหัสนี้คำนวณการเร่งความเร็วเชิงมุมเท่านั้น ความเร็วและมุมเชิงมุมต้องได้รับการอัปเดตจากที่อื่นโดยใช้และผู้รวมระบบในบางประเภท จากคำถามที่ฉันคิดว่าสิ่งนี้ได้รับการคุ้มครอง

ในที่สุดก็มีบางสิ่งที่จะพูดเกี่ยวกับการล้าหลังเพราะป้อมอาจจะอยู่ข้างหลังเสมอเมื่อติดตามเป้าหมายที่รวดเร็ว วิธีง่ายๆในการแก้ไขปัญหานี้คือการเพิ่มการทำนายเชิงเส้นให้กับตำแหน่งของเป้าหมายนั่นคือเล็งไปข้างหน้าเล็กน้อยในทิศทางไปข้างหน้าของเป้าหมาย

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

สำหรับการรักษาป้อมปืนเล็งไว้ในรัศมีของเป้าหมายในบางครั้งนี่อาจเป็นข้อกำหนดที่ยากมากที่จะกำหนดโดยตรงกับระบบประเภทนี้ คุณสามารถมั่นใจได้ว่าคอนโทรลเลอร์นี้จะพยายามรักษาป้อมปืนไว้ที่เป้าหมาย (หรือมากกว่าตำแหน่งที่คาดการณ์ไว้) ตลอดเวลา หากผลที่เปิดออกไม่ได้เป็นที่น่าพอใจมีการปรับเปลี่ยนพารามิเตอร์predictionTime, C0และC1(ภายในขอบเขตที่มีเสถียรภาพ)


ฉันไม่มีคุณสมบัติที่จะพูดว่าสิ่งนี้ถูกต้องหรือไม่ แต่ดูเหมือนว่าจะเป็นสิ่งที่ฉลาด! ฉันได้แก้ไขปัญหาประเภทนี้ในอดีตโดยการคาดการณ์ล่วงหน้าถึงผลของการเร่งความเร็วที่จะออกกำลังเมื่อต้องเร่งความเร็วและเมื่อใดที่ "ใช้การหยุดพัก" นั่นหมายความว่าฉันทำผิดหรือเปล่า?
Iain

atan2 ทำให้วิธีนี้ยากที่จะปรับให้เข้ากับระบบการทำนายเนื่องจากพารามิเตอร์ x และ y เป็น atan2 ขึ้นอยู่กับ t
Skizz

นี่เป็นคำตอบที่ฉันได้รับคำแนะนำด้านล่าง รายละเอียดและการนำเสนอที่ยอดเยี่ยม!
drxzcl

@Iain: ไม่มีไม่มีถูกและผิดที่นี่ ในขณะที่ฉันคิดว่าวิธีการของคุณจะมีสองสถานะที่ไม่ต่อเนื่อง: เร่ง / ชะลอตัววิธีนี้เป็นแรงบันดาลใจจากผู้ควบคุมจากทฤษฎีการควบคุมการปรับอัตราเร่งเพื่อให้ตอบสนองอย่างรวดเร็วในขณะที่ลดการโอเวอร์โหลดและแกว่ง
Staffan E

1
เช่นเดียวกับความคิดเห็นอื่น ๆ สิ่งนี้จะใช้ได้กับเป้าหมายที่อยู่กับที่ แต่จะไม่สามารถยอมรับได้สำหรับเป้าหมายที่เคลื่อนที่ใด ๆ คำศัพท์ C0 และ C1 เป็นแบบสปริงแบบดั้งเดิมซึ่ง C0 หมายถึงความแข็งแรงของสปริง (ปกติเรียกว่าk) และ C1 เป็นปัจจัยการทำให้หมาด ๆ (ปกติเรียกว่า 'B' หรือ 'c') ใช่คุณสามารถลดการสั่นได้โดยการทำให้หมาด ๆ แต่ปัญหาก็คือว่านี่ไม่ได้พยายามคาดการณ์ว่าเป้าหมายจะอยู่ที่ใดดังนั้นจะถึงเป้าหมายที่ต้องการ
dash-tom-bang

3

สิ่งที่คุณมีที่นี่เป็นพื้นฐานปัญหาการควบคุม ป้อมปืนเป็นระบบการเร่งความเร็วเป็นส่วนควบคุมและเซ็นเซอร์จะวัดตำแหน่ง / ความเร็ว มีหลายวิธีในการแก้ปัญหาเหล่านี้เนื่องจากเป็นปัญหาที่ได้รับการศึกษาเป็นอย่างดีในด้านวิศวกรรม

รหัสลงท้ายด้วยระบบที่เสถียรเช่นระบบที่ไม่สร้างความผันผวน ซึ่งมักจะทำโดยการเพิ่มการทำให้หมาด ๆ หน้าวิกิพีเดียควรเริ่มต้นให้คุณ


2

ก่อนอื่นให้คำนวณเวกเตอร์จากป้อมปืนไปยังเป้าหมาย จากนั้นเปรียบเทียบสิ่งนี้กับเวกเตอร์ปัจจุบันของป้อมปืน จากนั้นใช้ความแตกต่างระหว่างทั้งสองเพื่อหาค่าความเร่งเชิงมุมและความเร็วเชิงมุมที่ต้องใช้เพื่อให้ป้อมปืนหันไปชี้ในทิศทางที่ถูกต้องภายในเวลาที่กำหนด

ตกลงที่ดูเหมือนง่าย อย่างไรก็ตามคุณควรพยายามคาดการณ์ตำแหน่งของเป้าหมายจริงๆเพราะเป้าหมายจะเคลื่อนที่ตามเวลาที่คุณเปิดป้อมปืน เพื่อทำสิ่งนี้:-

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

โดยที่ P คือตำแหน่งและ V คือความเร็วและตัวห้อยคือ d สำหรับปลายทาง (เป้าหมาย) และ s สำหรับแหล่งที่มา (ป้อมปืน) ซึ่งให้เวกเตอร์ทิศทาง: -

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

โดยที่ D คือเวกเตอร์ทิศทางและ Dsd 'เป็นทิศทางที่ต้องการ ณ เวลา t ทีนี้หาทิศทางของป้อมปืนตามตำแหน่งปัจจุบันและความเร็วสูงสุดและความเร่งตามเวลาที่กำหนด t: -

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

Ds และ Ds 'คือทิศทางของแหล่งกำเนิดและ Rs คือความเร็วในการหมุน จากทั้งหมดที่คุณต้องการหาเมื่อ Dsd '== Ds' และทำให้ Rs คือความเร็วในการหมุนที่ต้องการ อย่าลืมว่า P's, D's และ V ทั้งหมดมีส่วนประกอบ x และ y

ฉันไม่ได้คำนึงถึงความเร่งที่นี่ซึ่งเพิ่มความซับซ้อนให้มากขึ้น เมื่อคุณได้รับอาร์เอสแล้วคุณอาจจะประมาณพาราโบลาอาร์เอส (เช่นเร่งความเร็วและลดความเร็ว) เพื่อให้ได้ผลลัพธ์เดียวกัน


นี่ดูเหมือนคำตอบที่ดีสำหรับการคำนวณการสกัดกั้น แต่น่าเสียดายที่มีช่องว่างขนาดใหญ่ระหว่างผู้ที่สามารถอ่านสัญกรณ์คณิตศาสตร์ประเภทนั้นและเปลี่ยนเป็นรหัสโปรแกรมและคนส่วนใหญ่ที่ทำเกมที่ไม่ทราบคำตอบ คำถาม. ในคำอื่น ๆ ฉันคิดว่าเกม devs ที่สามารถอ่านสัญกรณ์คณิตศาสตร์ที่อาจจะสามารถหาวิธีการเขียนโปรแกรมการแก้ปัญหาการยิง มันจะช่วยให้ฉันเข้าใจสูตรของคุณถ้าคุณอธิบายว่าคำของคุณหมายถึงอะไร
Dronz


0

สิ่งแรกที่ต้องทำคือการคำนวณมุมระหว่างวัตถุที่เกิดขึ้นกับวัตถุที่ถูกติดตาม
สิ่งต่อไปคือการตรวจสอบว่าใช้ความเร็วฝนตกหนักในปัจจุบันและใช้การเร่งความเร็วสูงสุดย้อนหลัง (หยุดฝนตกหนัก) ฝนตกหนักจะหยุดก่อนหรือหลังวัตถุที่ถูกติดตาม
หากคำตอบคือฝนตกหนักจะหยุดก่อนวัตถุที่ติดตามให้ใช้การเร่งความเร็วสูงสุดไปข้างหน้า (เพิ่มความเร็ว)
หากคำตอบคือฝนตกหนักจะหยุดหลังจากวัตถุที่ติดตามให้ใช้การเร่งความเร็วสูงสุดย้อนกลับ (หยุดฝนตกหนัก)
วิธีนี้ฝนตกหนักจะมาถึงเร็วที่สุดและจะหยุดที่จุดที่ถูกต้อง (หรือเสี้ยวหลัง)

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.