Как адаптировать алгоритмы поиска пути к ограниченному движению?

10

Представьте себе автомобильное движение, в котором сущности не могут включить ни копейки. Скажем, ради обсуждения, что при скорости они могут разворачиваться на 90 градусов в секунду. Это во многих случаях изменит оптимальный путь и, следовательно, поиск пути. Это может даже сделать «обычные» пути совершенно невозможными для прохождения.

Существуют ли какие-либо алгоритмы поиска пути или алгоритмы планирования движения, которые могут помнить об этом, или есть простые способы адаптации популярных?

Веккар Э.
источник
будет ли поиск пути включать данные о скорости? например, перейти от А к В со скоростью X км / ч (или миль в час), или это будет постоянная скорость? Кроме того, 90 градусов в секунду на медленных скоростях могут оказаться очень замкнутым поворотом, вероятно, даже физически невозможным. (если у вас все 4 колеса не поворачиваются xD)
Брайан Х.
@BrianH. Вот почему я сказал «на скорости». При разумных обстоятельствах будут установлены минимальные и максимальные пороговые значения. Но в идеале я бы искал алгоритм для поиска «идеального» пути, который может включать изменения скорости.
Weckar E.
Я нахожу это очень интересным вопросом, получил +1 от меня, не могу дождаться, чтобы увидеть некоторые аккуратные ответы :)
Брайан Х.
Я бы посчитал это некой невидимой стеной. Кроме того, большинство алгоритмов финансирования пути имеют «вес» для каждого пути (например, хождение по воде медленнее, чем хождение по суше), поэтому вы можете добавить дополнительный вес к пути, который труднее получить. Все это может быть известно только по скорости и направлению движения автомобиля.
the_lotus

Ответы:

10

Добро пожаловать в удивительный мир неголономного планирования движений. Я рекомендую делать это, используя планировщик пути с решетчатой ​​сеткой . Другие альтернативы включают кинодинамический RRT и оптимизацию траектории . К неголономным системам относятся автомобили, лодки, велосипеды или что-то еще, где транспортное средство не может двигаться в любом направлении, в котором оно хочет. Планирование этих систем намного сложнее, чем голономных, и до 2000 года находилось на грани научных исследований. В настоящее время существует множество алгоритмов на выбор, из которых работают достойно.

введите описание изображения здесь

Вот как это работает.

государственный

Конфигурация вашего автомобиля q на самом деле является трехмерным состоянием, содержащим положение x, y автомобиля и его ориентацию t . Узлы в вашем алгоритме A * на самом деле являются трехмерными векторами.

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

действия

Так что с краями?

Это немного сложнее, потому что ваш автомобиль может выбрать бесконечное количество способов поворота колеса. Таким образом, мы можем сделать это доступное для решетки сетки планировщика, ограничивая количество действий , автомобиль может принять для дискретного множества, A . Для простоты предположим, что автомобиль не ускоряется, а может мгновенно менять скорость. В нашем случае 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 - это узлы, Actions - это ребра между узлами, а Start и Goal выражены в терминах GridCells. Эвристика между двумя GridCell - это расстояние в x и y плюс угловое расстояние в тэте.

По пути

Теперь, когда у нас есть путь с точки зрения GridCells и действий между ними, мы можем написать последователь пути для автомобиля. Поскольку ячейки сетки являются дискретными, автомобиль будет прыгать между ячейками. Поэтому нам придется сгладить движение автомобиля по дорожке. Если в вашей игре используется физический движок, это можно сделать, написав контроллер рулевого управления, который пытается удерживать автомобиль как можно ближе к траектории. В противном случае вы можете анимировать путь, используя кривые Безье или просто усредняя ближайшие точки в пути.

mklingen
источник
Отличный пост (и даже короткий! Я делаю что-то похожее для лодок - скользко :-). Ото, там больше места,
Штормград
4

Большинство алгоритмов поиска пути работают на произвольном графе без ограничения геометрии.

Так что вам нужно добавить ориентацию автомобиля к каждому исследуемому узлу и ограничить, какие узлы действительно подключены.

чокнутый урод
источник
Проблема заключается в том, что автомобиль может посещать один и тот же узел, приближающийся с разных направлений, что накладывает различные ограничения на соединения, которые можно перемещать оттуда.
Weckar E.
6
@WeckarE. Но машина не посещает тот же узел. Он посещает 2 узла, которые оказываются в одном и том же месте, но имеют разную ориентацию
freak
3
@WeckarE. Рассматривайте их как два отдельных узла. Физический граф и логический граф не обязательно должны быть одинаковыми.
BlueRaja - Дэнни Пфлюгофт
1

Мои мысли, не проверял их!

  1. Запустите A * от начала до места назначения, верните путь.
  2. Цикл по пути, когда вы обнаруживаете поворот, используйте алгоритм Безье (или любой подобный ему), который использует текущую скорость ищущих, чтобы предсказать узлы, которые создадут плавный поворот. Убедитесь, что он пытается вернуться к ближайшему узлу пути.
  3. Если поворот можно сделать, здорово, если нет, повторите с более медленной скоростью, делая более резкий поворот.
  4. Как только правильный путь будет создан, вернитесь по пути, регулируя скорость искателя, прежде чем сделать поворот, чтобы он замедлился до правильной скорости, прежде чем начать поворот.
  5. Если поворот вообще не может быть выполнен, запустите все заново. Просто убедитесь, что все обработанные узлы поворота, которые не могут быть выполнены, находятся в закрытом списке, поэтому они игнорируются. И вы можете начать с точки, где начинается поворот, чтобы вы могли пропустить успешную часть пути, однако в некоторых случаях это может привести к неоптимальному пути.

Вы также должны быть в состоянии сделать это без необходимости сначала завершать путь, следовательно: обработка поворотов во время A *, что, вероятно, будет намного лучше оптимизировано, но это также может оказаться проблематичным и сбойным, я действительно не знаю и, к сожалению, я нет времени, чтобы проверить это сам.

Найти путь

Деннис
источник
0

Если ваш агент полностью контролирует машину, сделайте это наоборот. Сначала соедините линию от начала до конца, затем выясните, с какой скоростью вы можете перемещаться в каждом повороте, аналогично ответу Денниса.

Не рисуйте кривые Безье из неподвижных точек. Чтобы минимизировать потерю скорости, вам нужно переместить всю линию вокруг, поэтому начните с вставки дополнительных узлов на более или менее равномерном расстоянии, а затем двигайтесь для минимизации энергии или аналогичных стратегий. Для получения более подробной информации вам нужно взглянуть на генерацию искусственной линии в гоночных играх (предпочтительно сим или полусим).

Как только у вас будет запущена система линий AI, запустите поиск A * и для каждого пути продвиньтесь хотя бы на один угол вперед, затем вычислите линию AI, которая даст вам оценку времени. Это будет ваша функция стоимости.

BECD9A66
источник