A * эвристика для создания линий Bresenham

Из того, что я понимаю о A * эвристике и как работает алгоритм Брешенема, это может быть невозможно, поскольку только текущее состояние и состояние цели передаются эвристической функции. Но, возможно, у кого-то есть умное решение этой проблемы.

Я использую A * для планирования пути на сетке, и мне нужна эвристика, которая приведет к лучшему пути следования линии Bresenham, когда есть свободные промежутки между текущим состоянием и целью или очередным поворотом препятствие.

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

Манхэттенское расстояние:

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

The shortest path from red to green using the Manhattan distance heuristic

Евклидово расстояние:

Лучше, но все же не идеально. Обратите внимание на прямую линию в конце. Диагональ могла бы так же легко оставаться диагональной, что и я хочу.

The shortest path from red to green using the Euclidian distance heuristic

Что я хочу:

Линии Бресенхама - это розыгрыш следующего хода или цели.

The best path I actually want, which uses Bresenham lines to get to the goal

Я нашел здесь хороший ресурс, http://theory.stanford.edu/~amitp/GameProgramming/Heuristics.html, который касается того, что я ищу, но, похоже, работает только для рисования линий Брешенема от начала до цели. Я хочу, чтобы линии Bresenham рисовали на следующий поворот вокруг препятствия.

Любые идеи для хорошего подхода к этой проблеме?

Ответы

Ответ 1

Можете ли вы изменить функцию стоимости "на лету", чтобы стоимость перехода вперед увеличивалась с накопленной ошибкой?

Идея заключается в том, что в начале алгоритма вычислить DX и DY, как в стандартном Bresenham. (Предположим в остальной части примера, что DX > DY > 0. Измените соответственно для других направлений.)

Затем для каждого посещенного соседа node отследите ошибку Bresnaham:

if (neighbor.X > this.X) 
   neighbor.err=this.err+DY 
else if (neighbor.Y > this.Y) 
   neighbor.err=this.err-DX

Затем измените свою функцию стоимости в пользу увеличения X, но добавьте if (err >= DX/2) then cost=cost+FACTOR. На карте, где все остальные затраты равны, это должно отслеживать правильную линию.

Другая вещь, которая вам может понадобиться, - это специальная обработка, когда путь перемещается по препятствию, иначе вы могли бы получить странные дорожки, похожие на стены, похожие на "кросс-продукт с предметами", например, в вашей связанной статье. Вы могли бы справиться с этой ситуацией, пересчитав DX и DY всякий раз, когда сосед node не находится в направлении + X или + Y. (К сожалению, это, вероятно, требует отслеживания отдельных DX, DY и ошибок для каждого node, что может быть слишком большим объемом служебных данных)

Отказ от ответственности, я не реализовал алгоритм A * или Bresneham за многие годы. Вся эта идея может быть неработоспособной

Ответ 2

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

Ответ 3

Можете ли вы использовать обнаружение столкновения с помощью алгоритма Брешенема, возможно, адаптивного Брешенема, например, с кривой заполнения пространства?

Ответ 4

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