グリッド上でA *を使用して自然に見えるパスを作成する方法は?


13

私はこれを読んでいます:http : //theory.stanford.edu/~amitp/GameProgramming/Heuristics.html

しかし、私が理解していないこともいくつかあります。たとえば、この記事では、対角線の動きを伴う経路探索に次のようなものを使用するように記述されています。

function heuristic(node) =
    dx = abs(node.x - goal.x)
    dy = abs(node.y - goal.y)
    return D * max(dx, dy)

記事のようにDを設定して自然なパスを取得する方法がわからない、それを言ったようにDを隣接するスクエア間の最低コストに設定し、ヒューリスティックなものに関する意味がわからない4 * Dであり、何も変わらないようです。

これは私のヒューリスティック関数および移動関数です。

def heuristic(self, node, goal):
    D = 5
    dx = abs(node.x - goal.x)
    dy = abs(node.y - goal.y)
    return D * max(dx, dy)

def move_cost(self, current, node):
   cross = abs(current.x - node.x) == 1 and abs(current.y - node.y) == 1
   return 7 if cross else 5

結果:

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

実現したいスムーズな航行経路:

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

私のコードの残り:http : //pastebin.com/TL2cEkeX


更新

これは私がこれまでに見つけた最良の解決策です。

def heuristic(node, start, goal):
    dx1 = node.x - goal.x
    dy1 = node.y - goal.y
    dx2 = start.x - goal.x
    dy2 = start.y - goal.y
    cross = abs(dx1*dy2 - dx2*dy1)

    dx3 = abs(dx1)
    dy3 = abs(dy1)

    return 5 + (cross*0.01) * (dx3+dy3) + (sqrt(2)-2) * min(dx3, dy3)

def move_cost(current, node):
    cross = abs(current.x - node.x) == 1 and abs(current.y - node.y) == 1
    return 7 if cross else 5

2番目の写真から目的のパスを生成しますが、障害物をうまく処理できず(壁をcraう傾向があります)、長距離で最適なパスを生成できません。

それを改善するために適用できるいくつかの調整と最適化は何ですか?


2
ヒューリスティックとしてデカルト距離を使用するとどうなりますか?
ジミー

2
これは単なるアイデアです。エージェントが同じ方向に移動するたびに、あるタイルから別のタイルに移動するコストを増やします。
Ali1S232

@Jimmy私はsqrt(pow(goal.x-node.x、2)+ pow(goal.y-node.y、2))を試しましたが、私の小さな例のパスでは実際に私の質問の画像とまったく同じを返します。
匿名エンティティ

回答:


10

A *は、グラフの最短経路を示します。グリッドをグラフとして使用する場合、多くの場合、複数の最短パスがあります。最初の図で、これ最短経路の1つです。すべての軸方向の動きを最初に配置し、その後すべての斜めの動きを配置します。しかし、これは、すべての対角線を最初に置いた場合、または軸方向と斜め方向の動きを混在させた場合と同じ長さのパスです。これらはすべて同等に短く、どのA *が選択されるかは、コードの記述方法とグラフの表現方法によって異なります。

あなたが望んでいるのは次のいずれかだと思います:

  1. グリッド上を移動する必要がありますが、見た目が良くなるように軸方向と斜めのステップを混ぜたいと思います。1つのアプローチは、他の等しく短いパスの1つを選択することです。「ネクタイブレーク」を見つけるために、そのヒューリスティックページを読み続けてください。別のアプローチは、隣人を評価するとき、最初に評価するものをランダムに選択して、常に隣同士を選択しないようにすることです。グリッド上を移動する場合、ユークリッド/デカルト距離の使用お勧めしませ。A *の実行が遅くなるのは不一致です。
  2. グリッド上を移動する必要はなく、直線で移動する必要があります。1つのアプローチは、「ストリングプル」を使用してパスをまっすぐにすることです。パスが曲がる場所を探し、それらのポイントの間に直線を描きます。別のアプローチは、基になるグラフ自体にこれを適用することです。グリッド上のパス検索の代わりに、マップ上のキーポイント上のパス検索を行い、それらのキーポイント間の直線に沿って移動します。ここに例を見ることができます。さらに別のアプローチはTheta *アルゴリズムです。

いい答えです。私はいくつかの新しい情報で私の質問を更新しました、あなたの答えを少し指定できることを望みます。
匿名エンティティ

障害についてのビットが期待されると思います。ヒューリスティックのページには、「障害物の少ないきれいな」というタイトルの図があります。タイブレークアプローチは、障害を回避するのにあまり役立ちません。他のアプローチの1つ(Theta *など)が必要な場合があります。
-amitp

2

A *アルゴリズムを使用すると、パスエッジに異なるコストを割り当てることができます。状況に応じてコストを割り当てることもできます。これは、A *パスを、見た目通りに形作るためのメインツールです。

長い対角線を思いとどまらせたい場合は、ペナルティを科すことができます。パスが同じ方向に進むたびにわずかなコストを追加します。これを行うと、アルゴリズムはパス全体で可能な限り均等に斜めのステップを自動的に分散しようとします。この追加コストがエッジを追加するコスト以上にならないようにしてください。そうしないと、アルゴリズムは直線を避けるために完全に不要な迂回を開始します。

適切な式は次のとおりです。

cost = normal_cost * (1.1 - 0.1 / num_of_steps_in_the_same_direction

これには、パスコストが整数としてではなく、浮動小数点値として追跡される必要があることに注意してください。


1

適応A *

フィリップが言ったように、方向が長期間変わらない場合はコストを追加する必要があります。しかし、Philippの機能は、追加のコストの合計にすぐにつながる可能性があります。これは、追加のタイルを移動するためのコストよりも高くなります。しかし、彼の重要なアイデアは正しいです!

A *を適応させて(すべての)最適パス(最短の長さ)を計算し、別のヒューリスティックによってそれらの1つを選択するのは簡単に思えます。しかし問題がある。長いパスがある場合、最適な長さのソリューションがたくさんあるかもしれません。これにより、A *アルゴリズムはこれらの他のすべてのソリューションの計算にもはるかに時間がかかります。これは、グリッドが原因です。90度ではなく80度歩くことはできません。これにより、1つの最適なソリューションではなく、複数の準最適なソリューションが得られます。想像のために、障害物のない地図を想像してください。x距離は2、y距離は3です。これは、すべての最短経路に2つの斜めの動きと1つの直線の動きがあることを意味します。この単純なパスには、SDD、DSD、DDS(D =対角線、S =直線)の3つの有効な組み合わせがあります。本当の「楽しみ」は、たとえば次のようなパスがあるときにすでに始まります 3回の直線移動と2回の斜め移動:SSSDD、SSDSD、SSDDS、SDSSD、SDSDS、SDDSS、DSSSD、DSSDS、DSDSS、DDSSS(見逃していない場合、最短経路の10のバリエーション)。あなたはアイデアを持っているべきだったと思う...

そのため、より少ないソリューション(または1つのソリューションのみ)が「最適」になるようにコスト関数を調整することにより、これを修正する必要があります。

コスト関数の適応

Philippが式の例で提案しているように適応を行うと、はるかに良い結果が得られますが、まだいくつかの問題があります。パスに沿って短い/長い「パーツ」を均等に分散することはありません。つまり、方向の変更はパスの開始時に頻繁に行われ、逆もまた同様です。

さらに、「ターン」するアクターが際限なく存在するパスは、人間に観察されると次善のようです。(ターンアニメーションを表示するには)時間を要するため、遅くする必要があります。

ただし、コストにフロートを使用する代わりに、「2次コスト」または2次ソート基準を実装できます。一次コストが同じ場合、二次コストを使用して、どのソリューションが優先されるかを推定します。これにより、誤って一次コスト(グリッドメジャーのルート長)が増加することはありません。

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