Рулевое управление


8

Я сделал небольшой симулятор рулевого управления, используя алгоритм Рейнольдса Бойда. Теперь я хочу добавить функцию предотвращения стен. Мои стены в 3D и определены с использованием двух таких точек:

   ---------. P2
   |        |
P1 .---------

У моих агентов есть скорость, позиция и т. Д.

Не могли бы вы рассказать мне, как избежать моих агентов?

Vector2D ReynoldsSteeringModel::repulsionFromWalls()
{
    Vector2D force;
    vector<Wall *> wallsList = walls();
    Point2D pos = self()->position();
    Vector2D velocity = self()->velocity();

    for (unsigned i=0; i<wallsList.size(); i++)
    {
        //TODO
    }

    return force;
}

Затем я использую все силы, возвращаемые функциями boid, и применяю их к своему агенту.

Мне просто нужно знать, как это сделать со своими стенами.

Спасибо за вашу помощь.


2
Вы смотрели на оригинальную статью Рейнольда? Если я правильно помню, у него есть информация о том, как избежать препятствий и избегать стен. Я думаю, что это документ: red3d.com/cwr/steer/gdc99
— Кролт

1
Спасибо, но это объясняет, как избежать кругового препятствия, а не прямоугольного.
— Водемки

2
Используйте радиальное расстояние от агента до центра круга ( минус радиус стенки круга ).
— Бобобобо

Ответы:


14

Пусть каждая стена оказывает влияние на скорость.

Попробуйте что-то вроде использования обратного расстояния (или обратного квадрата расстояния) от стены, чтобы определить величину силы, которую "оказывает" каждая стена, и нормали стены, чтобы определить направление силы, которую "оказывает" стена.

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

Так что здесь бойд взаимодействует с 4 стенами. Поскольку скалярное произведение красных векторов (boid-to-wall-center) больше 0 для 3 из 4 стенок, эти стенки не будут оказывать силы на boid.

Только стена с синим вектором (произведение отрицательных точек) будет иметь силу.

Величина силы должна быть большой, так как штанга оказывается слишком близко к стене, а направление силы должно быть в направлении черной стрелки на стене (указывающей прямо от стены).

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

Если вы используете 1 / (t+1)для величины силы, где tрасстояние от стены, то сила будет очень сильной, когда приближается к 0, но исчезает ни к чему, когда t становится выше (обратите внимание на масштаб оси на диаграмме, это это не 0 при Т = 5, то 0,2). (Т + 1 такова, что вы не получите бесконечное усилие / деление на 0, если случится, что бид попадет в стену).

Если вы используете 1/(t^2+1), то сила у стены намного острее и падает быстрее / плавнее.

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

Поэкспериментируйте с этим и посмотрите, что вам нравится.


Спасибо, но как бороться с 3D стеной. Например, моя стена имеет 4 ребра, поэтому я считаю, что мне нужно максимум 2 силы (если направление агента по диагонали).
— Водемки

В 2D каждые 2 точки являются «стеной». Если это квадратный столб в центре комнаты, то у вас есть 4 стены. Вы можете "отбраковать" стены с обратной обшивкой (чтобы стены с обратной обшивкой не "сосали" игрока), если вектор от boid к центру стены имеет положительное произведение точек с нормалью стены.
— Бобобобо

Итак, вы думаете, это сделает работу? Расстояние Vector2D (wallList [i] -> center (), pos); double dotProduct = расстояние * wallList [i] -> normal (); if (dotProduct> 0) {force + = wallList [i] -> normal () / distance.length (); }
— Водемки

Это выглядит разумно, проверьте это!
— Бобобобо

Недостатком этого подхода является то, что рулевое управление моделируется как сила отталкивания, которая не зависит от движения агента. То есть он рассматривает агент как заряженную частицу в электростатическом поле. Рассмотрим случай, когда агент «летит» параллельно этой верхней (синей) стене и немного над ней (на странице). В этом случае рулевое управление или обход препятствий не требуются. Агент просто проходит мимо, и его не следует отталкивать от стены. См., Например, «сдерживание» в этом документе GDC 99 .
— Крейг Рейнольдс

8

Если кому-то нужен код, вот он, не стесняйтесь распространять его. Я попытался прокомментировать это, чтобы быть более понятным. Основано на решении бобобо .

Vector2D ReynoldsSteeringModel::repulsionFromWalls(vector<Vector2D *> walls)
{
    Vector2D force; // My force will be stored here
    Point2D pos = self()->position(); // Position of the agent

    // For each wall
    for (unsigned j=0; j<walls->size(); j++)
    {
        // Get the center point of the wall
        Real coordX = (walls[j]->p1().x() + walls[j]->p1().y()) / 2.0;
        Real coordY = (walls[j]->p2().x() + walls[j]->p2().y()) / 2.0;
        Point2D center(coordX, coordY);

        // Create a new vector between my agent and the center of the current wall
        Vector2D distance(center, pos);

        // If the wall is visible, calculate the force to apply
        double dotProduct = distance * partsList[j]->normal();
        if (dotProduct < 0)
        {
            force +=  partsList[j]->normal() / (distance.length() * distance.length() + 1);
        }
    }

    // Returned the calculated force
    return force;
}
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.