Làm thế nào để thích ứng các thuật toán tìm đường với chuyển động bị hạn chế?


10

Hãy tưởng tượng chuyển động giống như xe hơi nơi các thực thể không thể bật xu. Nói, để thảo luận, khi ở tốc độ, chúng có thể quay 90 độ mỗi giây. Điều này trong nhiều trường hợp sẽ thay đổi đường dẫn tối ưu và do đó tìm đường dẫn. Nó thậm chí có thể làm cho các đường dẫn 'thông thường' hoàn toàn không thể đi qua.

Có bất kỳ thuật toán tìm đường hoặc thuật toán lập kế hoạch di chuyển nào có thể ghi nhớ điều này, hoặc có những cách đơn giản để điều chỉnh những thuật toán phổ biến không?


đường dẫn cũng sẽ bao gồm dữ liệu tốc độ? như, đi từ A đến B với tốc độ X km / h (hoặc mph), hoặc nó sẽ là một tốc độ không đổi? Ngoài ra, 90 độ mỗi giây ở tốc độ chậm có thể là một lượt rất kín, thậm chí có thể là không thể. (trừ khi bạn có tất cả 4 bánh quay xD)
Brian H.

@BrianH. Đó là lý do tại sao tôi nói 'ở tốc độ'. Trong trường hợp hợp lý sẽ có ngưỡng tối thiểu và tối đa tại chỗ. Nhưng lý tưởng là tôi có một thuật toán tìm đường dẫn 'lý tưởng', có thể bao gồm các biến thể tốc độ.
Weckar E.

Tôi thấy đây là một câu hỏi rất thú vị, nhận được +1 từ tôi, không thể chờ đợi để xem một số câu trả lời gọn gàng :)
Brian H.


Tôi sẽ coi đây là một loại tường vô hình. Ngoài ra, hầu hết các thuật toán cấp vốn đường dẫn có "trọng số" cho mỗi đường dẫn (ví dụ: đi bộ trong nước chậm hơn so với đi bộ trên đất liền) để bạn có thể thêm trọng lượng bổ sung cho đường dẫn khó đi hơn. Tất cả điều này chỉ có thể được biết với tốc độ và hướng xe.
the_lotus

Câu trả lời:


10

Chào mừng bạn đến với thế giới tuyệt vời của kế hoạch chuyển động phi tổng thể. Tôi khuyên bạn nên làm điều này bằng cách sử dụng một kế hoạch đường dẫn lưới mắt cáo . Các lựa chọn thay thế khác bao gồm RRT động lực họctối ưu hóa quỹ đạo . Các hệ thống phi tổng thể bao gồm ô tô, thuyền, xe đạp hoặc bất kỳ thứ gì mà phương tiện không thể đi theo bất kỳ hướng nào nó muốn. Lập kế hoạch cho các hệ thống này khó hơn nhiều so với các hệ thống tổng thể và cho đến năm 2000 là trên cơ sở nghiên cứu học thuật. Ngày nay có rất nhiều thuật toán để lựa chọn trong đó hoạt động tốt.

nhập mô tả hình ảnh ở đây

Đây là cách nó hoạt động.

Tiểu bang

Cấu hình của chiếc xe của bạn q thực sự là một trạng thái 3D chứa x của xe, vị trí y định hướng của nó t . Các nút trong thuật toán A * của bạn thực sự là các vectơ 3D.

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

Hành động

Vậy còn các cạnh thì sao?

Điều đó hơi khó hơn, bởi vì chiếc xe của bạn thực sự có thể chọn số cách để xoay bánh xe. Vì vậy, chúng ta có thể làm cho điều này thể truy cập đến một kế hoạch lưới điện lưới bằng cách hạn chế số lượng các hành động của xe có thể mất đến một tập rời rạc, Một . Vì mục đích đơn giản, giả sử rằng chiếc xe không tăng tốc mà thay vào đó có thể thay đổi vận tốc tức thời. Trong trường hợp của chúng tôi, A có thể như sau:

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;
}

Bây giờ, chúng ta có thể tạo ra một bộ hành động riêng biệt mà chiếc xe có thể thực hiện bất cứ lúc nào. Ví dụ, một quyền cứng trong khi nhấn ga đầy đủ trong 0,5 giây sẽ trông như thế này:

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

Đặt xe ngược lại và lùi xe sẽ như thế này:

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

Và danh sách hành động của bạn sẽ như thế này:

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

Bạn cũng cần một cách xác định cách thức một hành động được thực hiện tại một nút dẫn đến một nút mới. Đây được gọi là động lực chuyển tiếp của hệ thống.

// 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);
}

Các ô lưới rời rạc

Bây giờ, để xây dựng lưới mắt cáo, tất cả những gì chúng ta cần làm là băm các trạng thái của xe vào các ô lưới rời rạc. Điều này biến chúng thành các nút riêng biệt có thể được theo sau bởi A *. Điều này là cực kỳ quan trọng bởi vì nếu không thì A * sẽ không có cách nào để biết liệu hai trạng thái xe có thực sự giống nhau để so sánh chúng hay không. Bằng cách băm đến các giá trị ô lưới số nguyên, điều này trở nên tầm thường.

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; 
}

Bây giờ, chúng ta có thể thực hiện kế hoạch A * trong đó GridCells là các nút, Hành động là các cạnh giữa các nút và Bắt đầu và Mục tiêu được thể hiện dưới dạng GridCells. Heuristic giữa hai GridCells là khoảng cách tính bằng x và y cộng với khoảng cách góc trong theta.

Theo con đường

Bây giờ chúng ta có một đường dẫn về GridCells và Hành động giữa chúng, chúng ta có thể viết một người theo dõi đường dẫn cho chiếc xe. Vì các ô lưới là rời rạc, chiếc xe sẽ nhảy vào giữa các ô. Vì vậy, chúng ta sẽ phải làm dịu chuyển động của chiếc xe dọc theo con đường. Nếu trò chơi của bạn đang sử dụng một động cơ vật lý, điều này có thể được thực hiện bằng cách viết một bộ điều khiển lái cố gắng giữ chiếc xe càng gần càng tốt với đường dẫn. Mặt khác, bạn có thể làm động đường dẫn bằng cách sử dụng các đường cong bezier hoặc đơn giản bằng cách lấy trung bình một vài điểm gần nhất trong đường dẫn.


Bài đăng tuyệt vời (và thậm chí ngắn! Tôi làm một cái gì đó tương tự cho thuyền - trơn :-). Otoh, có nhiều không gian hơn,
Stormwind

4

Hầu hết các thuật toán tìm đường dẫn hoạt động trên một biểu đồ tùy ý mà không hạn chế hình học.

Vì vậy, những gì bạn cần làm là thêm định hướng của chiếc xe vào từng nút được khám phá và hạn chế những nút nào thực sự được kết nối.


Vấn đề là chiếc xe có thể truy cập vào cùng một nút tiếp cận từ các hướng khác nhau, trong đó đặt ra các hạn chế khác nhau đối với các kết nối có thể bị chặn từ đó.
Weckar E.

6
@WeckarE. Nhưng chiếc xe không ghé thăm cùng một nút. Nó truy cập vào 2 nút xảy ra có cùng một vị trí nhưng định hướng khác nhau
ratchet freak

3
@WeckarE. Coi đó là hai nút riêng biệt Biểu đồ vật lý và biểu đồ logic không cần phải giống hệt nhau.
BlueRaja - Daniel Pflughoeft

1

Suy nghĩ của tôi, chưa thử nghiệm chúng!

  1. Chạy A * từ đầu đến đích, trả về đường dẫn.
  2. Lặp lại đường dẫn, khi bạn phát hiện một ngã rẽ, hãy sử dụng thuật toán bezier (hoặc bất kỳ thứ gì tương tự), sử dụng tốc độ hiện tại của người tìm kiếm để dự đoán các nút sẽ tạo ra một ngã rẽ trơn tru. Hãy chắc chắn rằng nó cố gắng quay trở lại nút đường dẫn gần nhất.
  3. Nếu lần lượt có thể được thực hiện, tuyệt vời, nếu không, lặp lại với tốc độ chậm hơn, làm cho lần lượt sắc nét hơn.
  4. Khi đường dẫn chính xác được tạo, quay lại đường dẫn điều chỉnh tốc độ của người tìm trước khi rẽ được thực hiện để nó chậm lại với tốc độ chính xác trước khi bắt đầu rẽ.
  5. Nếu lần lượt không thể thực hiện được, hãy chạy lại toàn bộ. Chỉ cần đảm bảo tất cả các nút được xử lý của lượt không thể thực hiện được trong danh sách đã đóng, vì vậy chúng bị bỏ qua. Và bạn có thể bắt đầu với điểm bắt đầu rẽ để bạn có thể bỏ qua phần thành công của đường dẫn, tuy nhiên, trong một số trường hợp, điều này có thể dẫn đến đường dẫn tối ưu hơn.

Bạn cũng có thể làm điều này mà không cần phải hoàn thành đường dẫn trước, ergo: xử lý các lượt trong A *, có thể sẽ được tối ưu hóa tốt hơn nhiều, nhưng nó cũng có thể chứng minh là có vấn đề và rối mắt, tôi thực sự không biết và không may là tôi không có thời gian để tự kiểm tra nó

Tìm đường


0

Nếu đại lý của bạn có toàn quyền kiểm soát chiếc xe, hãy làm theo cách khác. Kết nối một dòng từ đầu đến cuối trước, sau đó tìm ra tốc độ bạn có thể điều hướng mỗi lượt, tương tự như câu trả lời của Dennis.

Đừng vẽ đường cong Bezier từ các điểm cố định. Để giảm thiểu mất tốc độ, bạn cần di chuyển toàn bộ dòng xung quanh, vì vậy hãy bắt đầu bằng cách chèn thêm các nút ở khoảng cách thậm chí ít hơn và sau đó di chuyển để giảm thiểu năng lượng hoặc các chiến lược tương tự. Để biết chi tiết, bạn cần xem xét việc tạo dòng AI trong các trò chơi đua xe (tốt nhất là sim hoặc bán sim).

Khi bạn có hệ thống dòng AI đang chạy, hãy chạy tìm kiếm A * của bạn và cho mỗi đường dẫn đi ít nhất một góc về phía trước, sau đó tính toán dòng AI cung cấp cho bạn ước tính thời gian. Đây sẽ là chức năng chi phí của bạn.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.