壁回避ステアリング


8

レイノルズボイドアルゴリズムを使用して小さなステアリングシミュレータを作成しています。次に、壁回避機能を追加します。私の壁は3Dであり、そのような2つの点を使用して定義されています。

   ---------. 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
krolth

1
ありがとうございますが、長方形ではなく円形の障害物を回避する方法について説明しています。
Vodemki

2
エージェントから円の中心までの半径距離を使用します(円の壁の半径を差し引いたもの)。
bobobobo

回答:


14

各壁が速度に影響を与えるようにします。

壁からの逆距離(または逆二乗距離)を使用して各壁が「実行する」力の大きさを決定するようなものを試し、壁の法線が壁が「実行する」力の方向を決定するために使用します。

ここに画像の説明を入力してください

したがって、ここでボイドは4つの壁と相互作用します。赤いベクトル(ボイドから壁の中心へ)の内積は、4つの壁のうち3つで0より大きいため、これらの壁はボイドに力を加えません。

青いベクトル(負の内積)を持つ壁のみが力を持ちます。

力の大きさは、ボイドが壁に近づきすぎると大きくなり、力の方向は壁の黒い矢印の方向になります(壁から直接離れている)。

ここに画像の説明を入力してください

を壁の距離1 / (t+1)であるフォースの大きさに使用する場合t、フォースは0に近づくと本当に強くなりますが、tが高くなるとフェードオフします(図の軸スケールに注意してください。でない tが5 =場合、それは)0.2 0。(t + 1は、無限の力が得られないようにするためです/ボイドがたまたま壁に入った場合に0で除算します)。

を使用する1/(t^2+1)と、力は壁の近くでより鋭くなり、より速く/滑らかに落ちます。

ここに画像の説明を入力してください

それを試して、あなたが好きなものを見てください。


ありがとうございますが、3D壁の扱い方について説明します。たとえば、私の壁には4つのエッジがあるため、必要な力は最大2つ(エージェントの方向が斜めの場合)だと思います。
Vodemki

2Dでは、2ポイントごとが「壁」です。部屋の中央にある四角い柱の場合は、壁が4つあります。ボイドから壁の中心へのベクトルに壁の法線との正の内積がある場合は、(壁を後ろに向けてもプレーヤーが「吸い込まれない」ように)壁を後ろに「カリング」できます。
bobobobo

それで、これでうまくいくと思いますか?Vector2D distance(wallsList [i]-> center()、pos); double dotProduct = distance * wallList [i]-> normal(); if(dotProduct> 0){force + = wallList [i]-> normal()/ distance.length(); }
Vodemki

それは合理的に見えます、それをテストしてください!
bobobobo

このアプローチの欠点は、操縦がエージェントの動きに依存しない反発力としてモデル化されることです。つまり、静電場で薬剤を荷電粒子として扱います。エージェントがその上部(青い)の壁に平行で、その少し上(ページ上)に「飛んでいる」場合を考えてみます。この場合、ステアリングや障害物回避は必要ありません。エージェントは単に通り過ぎるだけなので、壁から押しのけないでください。たとえば、このGDC 99ペーパーの「封じ込め」を参照してください。
クレイグレイノルズ

8

誰かがコードを必要とする場合、ここでは、それを自由に再配布してください。私はそれをより理解しやすいようにコメントしようとしました。boboboboのソリューションに基づいています。

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;
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.