Изменения

Перейти к: навигация, поиск

Visibility graph и motion planning

17 455 байт добавлено, 19:39, 4 сентября 2022
м
rollbackEdits.php mass rollback
<div style== Нахождение любого пути между точками с препятствиями =={|align="backgroundright"|-colorvalign="top"|[[Файл: #ABCDEF; font-sizetrap.png|200px|thumb|right|Путь с препятствиями через трапецоидную карту]]|[[Файл: 16px; font-weight: bold; color: #000000; text-align: center; padding: 4px; border-style: solid; border-width: 1px;">Эта статья находится в разработке!</div>notShort.png|300px|thumb|right|Такой путь не самый короткий]]|}<includeonly>Для начала рассмотрим движение материальной точки. Случай, когда размером и формой движимого объекта пренебречь нельзя, будет рассмотрен [[Категория: В разработкеVisibility graph и motion planning#Motion planning|позднее]]</includeonly>.
== Visibility graph ==Эту задачу можно решить с помощью [[Трапецоидная карта | трапецоидной карты]]. По ней строится граф, ребра которого соединяют центры трапедоидов, а также начальную и конечную вершины с серединами вертикальных сторон трапецоидов. В таком графе ищется путь между начальной и конечной вершинами.
Если точки лежат внутри одного трапецоида {{---}} ответ найден. Иначе идём из стартовой точки в центр её трапецоида, далее по построенным рёбрам ищем трапецоид содержащий финальную точку. Для этого можно использовать поиск в ширину или другой алгоритм нахождения кратчайшего пути в графе. В общемконечном итоге, когда мы ищем соединяем середину последнего трапецоида с конечной вершиной. Данный алгоритм работает за <tex> O(n \log n) </tex> и за линейное количество памяти и хорошо подходит для нахождения какого-нибудь пути между парой данных вершин. Но если нужно найти кратчайший путь от точки , этот алгоритм не подходит, хоть и работает быстро. Однако, решения нахождения кратчайшего пути в лучшем случае работают за <tex> S O(n^2) </tex> до времени и памяти (здесь и далее <tex> T n </tex> {{---}} количество всех вершин). == Нахождение кратчайшего пути между точками с препятствиями===== Visibility graph ===Рассмотрим точное решение нахождения кратчайшего пути на плоскости между двумя точками с полигональными препятствиями с помощью построения графа видимости. После его построения, можно построить как и в случае с трапецоидной картой, кратчайший путь ищется любым стандартным алгоритмом поиска (например, алгоритмом [[Алгоритм Дейкстры|Дейкстры]] или [[Трапецоидная карта Алгоритм A*| трапецоидную картуA*]]). Для простоты рассуждений начальную и конечную вершины будем считать вершинами полигонов. {{Лемма|about=О кратчайшем пути|statement=Любой кратчайший путь между двумя вершинами с полигональными препятствиями представляет собой ломаную, соединить ребрами середины вертикальных сторон с центрами трапецоидов и в этом графе вершины которой {{---}} вершины полигонов.|proof=[[Алгоритм Дейкстры Файл:short.png|150px|thumb|right| ДейкстройShort cut]] найти Пусть кратчайший путь от {{---}} не ломаная. В таком случае, на пути существует такая точка <tex> S p </tex> до , которая не принадлежит ни одному прямому отрезку. Это означает, что существует <tex> T \epsilon</tex>-окрестность точки <tex> p </tex>, в которую не попадает ни одно препятствие (случай, когда точка попала на ребро рассматривается аналогично). В таком случае, подпуть, который находится внутри <tex>\epsilon</tex>-окрестности, по неравенству треугольника может быть сокращён по хорде, соединяющий точки пересечения границы <tex>\epsilon</tex>-окрестности с путем. Но этот Раз часть пути может быть уменьшена, значит и весь путь может быть уменьшен, а значит исходное предположение некорректно.}}{{Определение|definition =Говорят, что вершина <tex> u </tex> ''видна'' (англ. mutually visible) из <tex> v </tex>, если отрезок <tex> uv </tex> не будет кратчайшимпересекает ни одного препятствия.}}{{Определение|definition =''Граф видимости'' (кэпангл. visibility graph){{---}} граф, вершины которого {{---}} вершины полигонов. Между вершинами <tex> u </tex> и <tex> v </tex> существует ребро, если из <tex> u </tex> видна <tex> v </tex>.}} В худшем случае в таком графе может быть <tex> O(n^2) </tex> ребер. Однако по некоторым ребрам кратчайший путь точно не пройдет, и такие ребра из графа можно удалить.
{{Лемма
|about=О неиспользуемых вершинах
|statement=
Любой кратчайший путь от [[Файл:edgeToDelete.png|150px|thumb|right|Удаляем <tex> S BD </tex> до ]]# Если существуют вершины <tex> A, B, C </tex> одного препятствия и вершина <tex> D </tex> такая, что поворот <tex> T DBA </tex> не совпадает с полигональными препятствиями представляет собой ломануюповоротом <tex> DBC </tex>, то ребро <tex> DB </tex> не принадлежит кратчайшему пути и его можно удалить из графа. (См. поясняющую картинку справа)# Все внутренние вершины которой {{---}} вершины полигонов, кроме вырожденного случая, (начальная/конечная точка лежит внутри выпуклой оболочки фигуры) можно игнорировать.
|proof=
Пусть путь проходит(в смысле вершины) [[Файл:edgeNotToDelete.png|200px|thumb|right|Не удаляем <tex> BS </tex>]]# Путь проходящий через ребро <tex> BD </tex> будет длиннее, чем через какую-то другую точку. Рассмотрим окрестность этой соседей точки. По <tex> B </tex>, так как по неравенству треугольника мы сможем немножко<tex> AB + BD > AD </tex># Если случай не вырожденный, да срезать. Значит этот значит заход внутрь фигуры только увеличит суммарный путь не кратчайший. Противоречие, значит лемма доказано и все офигеннотак как по неравенству треугольника расстояние между соседними выпуклыми вершинами всегда меньше суммы расстояний с учётом внутренней.
}}
 
По доказанным леммам любое ребро кратчайшего пути содержится в графе. Таким образом, для нахождения кратчайшего пути осталось найти кратчайший путь в этом графе от начальной до конечной вершины.
 
=== Построение visibility графа ===
==== Наивный алгоритм. <tex> O(n ^ 3) </tex> ====
Для каждой пары вершин проверяем, можно ли добавить ребро между ними, то есть нет ли пересечений с полигонами. <tex> O(n^2) </tex> пар вершин и <tex> O(n) </tex> ребер, то есть <tex> O(n^3) </tex>.
 
==== Lee’s Algorithm. <tex> O(n ^ 2 \log n) </tex> ====
{|
|
[[Файл:Zam.png|300px|thumb|left|Заметание плоскости вращающимся лучом]]
Однако можно это сделать за <tex> O(n ^ 2 \log n) </tex>. Идея алгоритма проста: для каждой вершины найдем видимые из нее вершины. Если научиться делать это за <tex> O(n \log n) </tex>, задача решена, так как всего точек <tex> n </tex>.
 
Для каждой вершины будем рассматривать только правую половину плоскости, так как ребра, которые должны идти в левую половину, будут исходить из вершин, для которых текущая вершина будет справа.
 
Переформулируем задачу. Дано: точка <tex> v </tex> и множество отрезков {{---}} ребер препятствий.
Найти: множество концов отрезков, видимых из <tex> v </tex>.
 
Для решения этой задачи будем использовать заметающий луч с началом в точке <tex> v </tex>. Его статусом будут отрезки, которые его пересекают, упорядоченные по возрастанию расстояния от точки <tex> v </tex> до точки пересечения. Точками событий будут концы отрезков.
 
Пустим луч из рассматриваемой вершины <tex> v </tex> вертикально вверх и добавим в статус все отрезки, которые он пересекает, по увеличению расстояния до них. Теперь будем рассматривать точки <tex> w \in V </tex> в порядке сортировки по углу между <tex> v </tex> и вертикальной полуосью <tex> l </tex>. При таком обходе для проверки видимости вершины достаточно проверить пересечение с ближайшим к <tex> v </tex> отрезком, то есть первым в статусе(так как отрезки отсортированы по расстоянию до них). Действительно, если вершина <tex> w </tex> не видна, то отрезок <tex> vw </tex> пересекает несколько отрезков, лежащих перед <tex> w </tex>, а значит и ближайший. В противном случае все пересекаемые лучом отрезки лежат за вершиной <tex> w </tex> и пересечения отрезка <tex> vw </tex> с ближайшим отрезком не будет. Вне зависимости от видимости вершины, необходимо изменить статус заметающего луча. Для этого необходимо удалить из статуса все отрезки, которые заканчиваются вершине <tex> w </tex> (лежат слева от прямой <tex> vw </tex>) и добавить все отрезки, которые в ней начинаются (лежат справа от прямой <tex> vw </tex>).
 
===== Псевдокод =====
graph buildVisibilityGraph(Set<Segment> segments)
vertices = getVertices(segments) <tex> \cup\ \{s,\ t\} </tex>
graph = visibilityGraph(vertices)
'''for''' Vertex <tex>v</tex> '''in''' vertices
'''for''' Vertex <tex>w</tex> '''in''' getVisibleVertices(<tex>v</tex>, segments)
visibilityGraph.addEdge(<tex>v</tex>, <tex>w</tex>)
'''return''' visibilityGraph
Здесь функция getVisibleVertices(<tex> v </tex>) возвращает все видимые из <tex> v </tex> вершины и выглядит так:
Set<Vertex> getVisibleVertices(Vertex <tex>v</tex>, Set<Segment> segments)
Set<Vertex> answer
'''for''' Segment <tex>s</tex> '''in''' segments
'''if''' intersect(<tex> s </tex>, <tex> l </tex>)
status.add(<tex>s</tex>)
'''for''' Point <tex>w</tex> '''in''' segments
'''if''' <tex>v.x \leqslant w.x</tex>
currentVertices.add(<tex>w</tex>)
sort(currentVertices) by angle
'''for''' Point <tex>w</tex> '''in''' currentVertices
'''if''' '''not''' intersect(<tex>vw</tex>, status.closest)
answer.add(<tex>w</tex>)
'''for''' Segment <tex>s</tex> ending in <tex>w</tex>
status.delete(<tex>s</tex>)
'''for''' Segment <tex>s</tex> beginning in <tex>w</tex>
status.add(<tex>s</tex>)
'''return''' answer
В качестве статуса нужно использовать структуру данных, позволяющую добавлять и удалять из нее отрезки за <tex> O(\log n) </tex> и извлекать минимум за <tex> O(1) </tex> или <tex> O(\log n) </tex>. В этом случае достигается асимптотика <tex> O(n^2 \log n) </tex>, так как для каждой из <tex> n </tex> точек выполняется сортировка за <tex> O(n \log n) </tex>, обновление статуса (суммарно <tex> O(n \log n) </tex>, так как каждый отрезок добавляется и удаляется из статуса не более одного раза) и запросы ближайшего отрезка (<tex> O(\log n) </tex> или <tex> O(1) </tex> на точку, то есть <tex> O(n \log n) </tex> или <tex> O(n) </tex>).
|
[[Файл:Zamrefr1.png|250px|thumb|right|Обновление статуса заметающего луча: добавляем ребра <tex> w_1 w_5 </tex> и <tex> w_1 w_2 </tex> в статус]]
[[Файл:Zamrefr2.png|250px|thumb|right|Добавляем ребра <tex> w_3 w_2 </tex> и <tex> w_3 w_4 </tex> в статус]]
[[Файл:Zamrefr3.png|250px|thumb|right|Удаляем ребра <tex> w_3 w_2 </tex> и <tex> w_1 w_2 </tex> из статуса]]
|}
== Motion planning ==
[[Файл:mink.png|200px|thumb|left|Изменяем препятствия]]
[[Файл:mink2.png|400px|thumb|right|Ищем путь для точки]]
Рассмотрим задачу нахождения кратчайшего пути, когда движимый объект {{---}} это выпуклый полигон. Например, робот, которого надо доставить из начальной в конечную точку.
Здесь могла быть Ваша рекламаЕсли полигон вращать нельзя, задачу сводится к движению точки так: выбирается точка на полигоне, которая принимается за начало координат. Но скоро будет конспектВ такой системе координат для каждого препятствия считается [[Сумма Минковского (определение, вычисление)|сумма Минковского]] с полигоном. Получаются бОльшие препятствия, но теперь достаточно двигать выбранную точку, что было описано выше.
== Источники ==* Mark de BergЕсли полигон можно вращать, Otfried Cheongзадача нахождения ''кратчайшего'' пути становится достаточно ресурсоёмка, Marc van Kreveld, Mark Overmars (2008), Computational Geometry: Algorithms and Applications (3rd edition), Springer-Verlag, ISBN 978-3-540-77973-5 Chapter 15 page 324поэтому обычно рассматривают задачу нахождения какого-331нибудь пути между конечными точками.
Первый шаг решения этой задачи совпадает с предыдущим случаем: выберем точку и построим [[Сумма Минковского (определение, вычисление)|сумму Минковского]] препятствий с полигоном. Рассмотрим малый угол <tex> \epsilon </tex>. Представим, что поворот полигона на этот угол {{---}} это движение вверх-вниз между слоями, на каждом из которых посчитана сумма Минковского с полигоном, повернутым на этот угол.
 
На каждом слое построим трапецоидную карту и граф, как описано в [[Visibility graph и motion planning#Нахождение пути между точками с препятствиями|начале]]. Если [[Пересечение многоугольников (PSLG overlaying)|пересечь]] соседние слои и добавить между их графами ребра, получится один большой граф, в котором ищется кратчайший путь.
 
При таком подходе может возникнуть ошибка при пересечении слоев: на каждом слое состояния будут допустимые, а осуществить поворот физически будет невозможно. Обычно, эту проблему решают двумя способами: измельчением угла поворота и изначальным сглаживанием углов полигона. Первый способ повышает не только точность решения, но и вычислительную сложность задачи. Второй подход практически исключает возможность нахождения пути, когда его нет, но повышает вероятность "ненахождения" пути, когда он есть.
 
== Источники информации ==
* Mark de Berg, Otfried Cheong, Marc van Kreveld, Mark Overmars, Computational Geometry: Algorithms and Applications {{---}} Third edition {{---}} Springer, 2008. {{---}} Chapter 15. {{---}} ISBN 978-3-540-77973-5
* [http://www.academia.edu/2845047/3D_Visibility_Graph Academia.edu] {{---}} 3D Visibility Graph
* [http://habrahabr.ru/post/199256/ Хабрахабр] {{---}} Motion planning: граф видимости, дорожные карты
* [http://igitur-archive.library.uu.nl/math/2006-1214-201604/overmars_88_new_methods.pdf igitur-archive.library.uu.nl] {{---}} Visibility graph при помощи rotation tree за <tex>O(n^2)</tex>.
[[Категория: Вычислительная геометрия]]
 
== Ссылки ==
* [https://github.com/Igorjan94/cg/blob/master/include/cg/algorithms/visibilityGraph.h Github] {{---}} Реализация алгоритма за <tex> O(n^2 \log n) </tex>
1632
правки

Навигация