วิธีปรับอัลกอริธึม pathfinding ให้สอดคล้องกับการเคลื่อนไหวที่ จำกัด ?


10

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

มีอัลกอริทึมการค้นพบเส้นทางหรืออัลกอริทึมการวางแผนการเคลื่อนไหวที่สามารถจำได้หรือไม่หรือมีวิธีง่ายๆในการปรับตัวที่เป็นที่นิยม?


การค้นหาเส้นทางจะรวมข้อมูลความเร็วไว้ด้วยหรือไม่ เช่นไปจาก A ถึง B ที่ X km / h (หรือ mph) หรือความเร็วคงที่หรือไม่? เช่นกัน 90 องศาต่อวินาทีด้วยความเร็วที่ช้าอาจกลายเป็นการปิดตัวเองอย่างมาก (เว้นแต่คุณจะเปลี่ยนล้อทั้ง 4 ล้อ xD)
Brian H.

@BrianH นั่นเป็นเหตุผลที่ฉันพูดว่า 'at-speed' ในสถานการณ์ที่เหมาะสมจะต้องมีเกณฑ์ขั้นต่ำและสูงสุด แต่ความนึกคิดฉันมีอัลกอริทึมที่ค้นหาเส้นทาง 'อุดมคติ' ซึ่งอาจรวมถึงการเปลี่ยนแปลงความเร็ว
Weckar E.

ฉันพบนี้เป็นคำถามที่น่าสนใจมากได้ +1 จากฉันลาดเทรอเพื่อดูคำตอบบางอย่าง :)
ไบรอันเอช


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

คำตอบ:


10

ยินดีต้อนรับสู่โลกมหัศจรรย์ของการวางแผนการเคลื่อนไหวที่ไม่ใช่แบบองค์รวม ผมขอแนะนำให้ทำเช่นนี้โดยใช้การวางแผนเส้นทางตารางตาข่าย ทางเลือกอื่น ๆ รวมถึงRRT kinodynamicและการเพิ่มประสิทธิภาพของวิถี ระบบที่ไม่ใช่แบบองค์รวมประกอบด้วยรถยนต์เรือ unicycles หรืออะไรก็ตามที่ยานพาหนะไม่สามารถเดินทางไปในทิศทางใดก็ได้ตามที่ต้องการ การวางแผนสำหรับระบบเหล่านี้นั้นยากกว่าระบบแบบฮอโลโลคัลมากและจนถึง ~ 2000 อยู่บนขอบของการวิจัยทางวิชาการ ทุกวันนี้มีอัลกอริทึมมากมายให้เลือกใช้ซึ่งทำงานได้อย่างเหมาะสม

ป้อนคำอธิบายรูปภาพที่นี่

นี่คือวิธีการทำงาน

สถานะ

รถของคุณกำหนดค่าQเป็นจริงรัฐ 3D ที่มี x รถตำแหน่ง Y และปฐมนิเทศที โหนดในอัลกอริทึม A * ของคุณนั้นเป็นเวกเตอร์ 3 มิติ

class Node
{
    // The position and orientation of the car.
    float x, y, theta;
}

การปฏิบัติ

แล้วขอบล่ะ

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

class Action
{
    // The direction of the steering wheel.
    float wheelDirection;

    // The speed to go at in m/s.
    float speed;

    // The time that it takes to complete an action in seconds.
    float dt;
}

ตอนนี้เราสามารถสร้างชุดการกระทำที่ไม่ต่อเนื่องที่รถสามารถทำได้ตลอดเวลา ตัวอย่างเช่นสิทธิ์ที่ยากขณะกดแก๊สเต็ม 0.5 วินาทีจะมีลักษณะดังนี้:

Action turnRight;
turnRight.speed = 1;
turnRight.wheelDirection = 1;
turnRight.dt = 0.5;

การนำรถกลับด้านและสำรองจะมีลักษณะเช่นนี้:

Action reverse;
reverse.speed = -1;
reverse.wheelDirection = 0;
reverse.dt = 0.5;

และรายการการกระทำของคุณจะเป็นดังนี้:

List<Action> actions = { turnRight, turnLeft, goStraight, reverse ...}

คุณต้องมีวิธีการกำหนดวิธีการดำเนินการที่โหนดส่งผลให้โหนดใหม่ สิ่งนี้เรียกว่าพลวัตไปข้างหน้าของระบบ

// These forward dynamics are for a dubin's car that can change its
// course instantaneously.
Node forwardIntegrate(Node start, Action action) 
{
    // the speed of the car in theta, x and y.
    float thetaDot = action.wheelDirection * TURNING_RADIUS;

    // the discrete timestep in seconds that we integrate at.
    float timestep = 0.001;

    float x = start.x;
    float y = start.y;
    float theta = start.theta;

    // Discrete Euler integration over the length of the action.
    for (float t = 0; t < action.dt; t += timestep)
    {
       theta += timestep * thetaDot;
       float xDot = action.speed * cos(theta);
       float yDot = action.speed * sin(theta);
       x += timestep * xDot;
       y += timestep * yDot;
    }

    return Node(x, y, theta);
}

เซลล์กริดแบบแยก

ตอนนี้ที่จะสร้างตารางตาข่ายทั้งหมดที่เราต้องทำคือกัญชารัฐของรถที่เข้าสู่เซลล์ตารางต่อเนื่อง สิ่งนี้จะเปลี่ยนเป็นโหนดแบบไม่ต่อเนื่องที่สามารถตามด้วย A * สิ่งนี้สำคัญมากเพราะมิเช่นนั้น A * จะไม่มีทางรู้ว่ารถสองคันนั้นเหมือนกันจริง ๆ หรือเปล่าเพื่อเปรียบเทียบกับพวกเขา ด้วยการแปลงค่าเซลล์กริดเป็นจำนวนเต็มสิ่งนี้จะกลายเป็นเรื่องเล็กน้อย

GridCell hashNode(Node node)
{
    GridCell cell;
    cell.x = round(node.x / X_RESOLUTION);
    cell.y = round(node.y / Y_RESOLUTION);
    cell.theta = round(node.theta / THETA_RESOLUTION);
    return cell; 
}

ตอนนี้เราสามารถทำแผน A * โดยที่ GridCells เป็นโหนดการดำเนินการเป็นขอบระหว่างโหนดและการเริ่มต้นและเป้าหมายจะแสดงในแง่ของ GridCells Heuristic ระหว่างสอง GridCells คือระยะห่างใน x และ y บวกระยะทางเชิงมุมใน theta

ติดตามเส้นทาง

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


โพสต์ที่ยอดเยี่ยม (และแม้สั้น! ฉันทำสิ่งที่คล้ายกันสำหรับเรือ - ลื่น :-) โอโตะมีพื้นที่มากขึ้น
Stormwind

4

อัลกอริธึมการค้นหาเส้นทางส่วนใหญ่ทำงานบนกราฟโดยไม่มีข้อ จำกัด ของรูปทรงเรขาคณิต

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


ปัญหาคือรถสามารถไปที่โหนดเดียวกันซึ่งมาจากทิศทางที่แตกต่างกันซึ่งวางข้อ จำกัด ที่แตกต่างกันในการเชื่อมต่อที่สามารถข้ามจากที่นั่นได้
Weckar E.

6
@WeckarE แต่รถไม่ได้ไปที่โหนดเดียวกัน มันเข้าชม 2 โหนดที่มีตำแหน่งเดียวกัน แต่มีทิศทางที่แตกต่างกัน
ratchet freak

3
@WeckarE ถือว่าเป็นสองโหนดแยกกัน กราฟทางกายภาพและกราฟตรรกะไม่จำเป็นต้องเหมือนกันทุกประการ
BlueRaja - Danny Pflughoeft

1

ความคิดของฉันไม่ได้ทดสอบพวกเขา!

  1. เรียกใช้A *ตั้งแต่ต้นถึงปลายทางส่งคืนพา ธ
  2. วนลูปผ่านเส้นทางเมื่อคุณตรวจพบเทิร์นให้ใช้อัลกอริธึมbezier (หรืออะไรทำนองนั้น) ซึ่งใช้ความเร็วปัจจุบันของผู้ค้นหาเพื่อทำนายโหนดที่จะสร้างการหมุนอย่างราบรื่น ตรวจสอบให้แน่ใจว่าได้พยายามกลับไปที่พา ธ - โหนดที่ใกล้ที่สุด
  3. หากเลี้ยวได้ดีเยี่ยมไม่เช่นนั้นให้ทำซ้ำด้วยความเร็วที่ช้าลงทำให้เลี้ยวได้คมชัดยิ่งขึ้น
  4. เมื่อสร้างเส้นทางที่ถูกต้องแล้วให้ย้อนกลับไปตามเส้นทางที่ปรับความเร็วของผู้ค้นหาก่อนที่จะทำการเลี้ยวเพื่อให้ช้าลงถึงความเร็วที่ถูกต้องก่อนที่จะเริ่มการเลี้ยว
  5. หากไม่สามารถเลี้ยวได้ให้ดำเนินการทั้งหมดอีกครั้ง เพียงให้แน่ใจว่าโหนดที่จัดการทั้งหมดของเทิร์นที่ไม่สามารถทำได้อยู่ในรายการปิดดังนั้นจึงถูกละเว้น และคุณสามารถเริ่มต้นด้วยจุดที่มีการเปิดเพื่อให้คุณสามารถข้ามส่วนที่ประสบความสำเร็จของเส้นทางอย่างไรก็ตามในบางกรณีสิ่งนี้อาจส่งผลให้เส้นทางที่ดีที่สุดน้อยกว่า

คุณควรจะสามารถทำสิ่งนี้ได้โดยไม่ต้องทำให้เสร็จก่อนเส้นทาง ergo: การเลี้ยวในช่วง A * ซึ่งน่าจะเหมาะที่สุด แต่ก็อาจพิสูจน์ได้ว่าเป็นปัญหาและมีปัญหาฉันไม่อยากรู้และโชคร้ายจริงๆ ไม่มีเวลาที่จะทดสอบด้วยตัวเอง

pathfinding


0

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

อย่าวาดเส้นโค้ง Bezier จากจุดคงที่ เพื่อลดการสูญเสียความเร็วให้น้อยที่สุดคุณจำเป็นต้องย้ายทั้งเส้นรอบ ๆ ดังนั้นเริ่มต้นด้วยการแทรกโหนดพิเศษที่ระยะทางมากขึ้นหรือน้อยลงและจากนั้นย้ายจากนั้นสำหรับการลดพลังงานหรือกลยุทธ์ที่คล้ายกัน สำหรับรายละเอียดที่คุณต้องพิจารณาในการสร้างสาย AI ในเกมแข่งรถ (โดยเฉพาะซิมหรือกึ่งซิม)

เมื่อคุณเปิดใช้งานระบบสาย AI ให้เรียกใช้การค้นหา A * และสำหรับแต่ละเส้นทางเดินอย่างน้อยหนึ่งมุมไปข้างหน้าจากนั้นคำนวณบรรทัด AI ที่ให้การประมาณเวลา นี่จะเป็นฟังก์ชั่นค่าใช้จ่ายของคุณ

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