![]() |
![]() |
![]() |
|||||
![]() |
Алгоритмы построения пути для беспилотного автомобиля. Лекция Яндекса |
||||||
МЕНЮ Искусственный интеллект Поиск Регистрация на сайте Помощь проекту ТЕМЫ Новости ИИ Искусственный интеллект Разработка ИИГолосовой помощник Городские сумасшедшие ИИ в медицине ИИ проекты Искусственные нейросети Слежка за людьми Угроза ИИ ИИ теория Внедрение ИИКомпьютерные науки Машинное обуч. (Ошибки) Машинное обучение Машинный перевод Реализация ИИ Реализация нейросетей Создание беспилотных авто Трезво про ИИ Философия ИИ Big data Работа разума и сознаниеМодель мозгаРобототехника, БПЛАТрансгуманизмОбработка текстаТеория эволюцииДополненная реальностьЖелезоКиберугрозыНаучный мирИТ индустрияРазработка ПОТеория информацииМатематикаЦифровая экономика
Генетические алгоритмы Капсульные нейросети Основы нейронных сетей Распознавание лиц Распознавание образов Распознавание речи Техническое зрение Чат-боты Авторизация |
2017-10-22 15:36 Яндекс уже некоторое время ведет разработку беспилотного автомобиля. Перед вами одна из первых технических лекций на эту тему. В направлении беспилотных автомобилей работают сотрудники Яндекса в разных городах, включая и Минск. Автор лекции Роман Удовиченко как раз из Минска — он руководит группой обработки дорожной ситуации. На сентябрьском Я.Субботнике Роман рассказал об одной из больших задач, стоящих перед его группой.
Мы просто берем текущее положение машины, смотрим на путь, по которому мы хотели бы ехать, и плавно сворачиваем на этот путь, выруливаем на него. Получается достаточно просто. Но перемещение в городе связано с тем, что нужно соблюдать правила дорожного движения. — Меня зовут Рома Удовиченко, я работаю в Яндексе в Минске руководителем группы обработки дорожной ситуации в направлении беспилотных автомобилей. Сегодня расскажу про очень небольшую, но важную часть нашей работы — алгоритмах построения пути для беспилотного автомобиля. Сначала хочется понять, что нужно сделать, чтобы научить машину ездить самостоятельно — при условии, что мы обвешали ее датчиками, навесили на нее камер, радаров и чего угодно. Мы можем делать всё, осталось написать код предположений. ![]() А можем применить модную нынче технологию нейросетей и сказать, что в явном виде мы программировать ничего не будем. Давайте просто картинку с камер подавать в нейросеть, предварительно ее обучив на каких-нибудь человеческих перемещениях. Обучим, в каких ситуациях куда нужно крутить руль, тормозить, газовать, возьмем много-много данных, сделаем большую нейросеть, и по задумке она должна хорошо себя вести после этого. В этом направлении ведутся большие работы, но на практике кажется, что нужно все-таки слишком много данных, нужна слишком большая нейросеть, чтобы за человеком все успешно повторять в различных ситуациях. Поэтому сегодня мы поговорим о классическом подходе, в частности — о планировании пути, построении траектории, по которой мы будем ехать. Почему планирование пути — сложная задача, которую нельзя сделать за неделю и дальше пойти делать что-то интересное? Автомобиль вообще обладает рядом довольно существенных ограничений. Это не шар в пространстве, который может катиться в любую сторону и условно мгновенно останавливаться и замедляться. У автомобиля есть текущее направление, угол поворота колес, и он не может просто оказаться на два метра левее от текущего местоположения, это очень сложно. Он может ехать примерно вперед, поворачивая на какой-то угол, но тем не менее, перемещение очень сильно ограничено. И траектория, которую мы строим, подвержена ограничениям, которые следуют из кинематики. Например, мы не можем мгновенно разогнаться и даже мгновенно увеличить свое ускорение. ![]() Первое, с чего начнем, это алгоритмы на графах. Первый вопрос, на который нам необходимо ответить, чтобы понять, какие алгоритмы можно применить, это как вообще построить граф? Вот стоит машина, мы можем понять, где она стоит, но в реальности графа никакого нет, вершин ребер на дороге не нарисовано. Нам этот граф нужно как-то придумать самим. Первое, что можем сделать: разобьем все пространство на клетки, рассмотрим маленькие клеточки и скажем, что есть вся наша поверхность земли, разбитая на клетки 25 на 25 или 50 на 50 см. Потом соединим соседние клетки ребрами и будем искать на них путь. Это будет довольно далеко от того пути, который машина может проехать, но какое-то приближение это даст. И у нас будут такие вершины в двумерном пространстве. Мы можем усложнять наше пространство, добавляя туда текущий угол поворота машины. У нас уже будут клетки не просто x и y, но и текущая ориентация машины в направлениях север, юг, запад и восток, тоже как-то дискретизированных. Кроме направления мы можем много всего учитывать: текущую скорость машины, текущее ускорение, текущее тангенциальное ускорение, нормальное. Все это важно учитывать. Но чем больше мы усложняем наше пространство, тем более сложным становится наш граф. ![]() Предположим, мы рассмотрим не столь хорошо стыкующиеся друг с другом примитивы — например, скажем, что поворот налево происходит под углом 89 градусов, а поворот направо под углом 90 градусов. Тогда у нас уже такое же количество вершин, как на предыдущей картинке, будет занимать существенно меньшую площадь пространства, поскольку они плохо друг с другом стыкуются и плотность точек будет очень высокая, а покрыть пространство далеко мы не сможем. Можем объединить эти два подхода и сказать, что мы рассматриваем примитивы движения под любыми углами, проехать вперед, проехать вперед и повернуть на 10 градусов, 15 градусов, что угодно. При этом все равно разобьем пространство на клеточки и скажем, что в одной клетке не может быть больше 1, 2, …, k вершин. Когда мы рассматриваем очередную вершину в графе в процессе использования какого-то алгоритма, мы говорим, что тут в клетке новая вершина, обрабатываем ее соответствующим образом. Если потом оказывается, что мы в указанную клетку хотим попасть уже в другой вершине, то мы ее рассматривать не будем. Это нас лишает возможности построить какой-то более оптимальный маршрут, чем если бы мы использовали все-все вершины. Зато это позволяет существенно повысить скорость работы и эффективность. У нас есть граф, мы хотим на нем применить какой-то алгоритм. Есть алгоритм А*. ![]() Чтобы производить поиск более эффективно, мы будем рассматривать вершины не только по увеличению расстояния от старта, а еще и прибавим к этому расстоянию некоторую эвристическую оценку того, сколько нам осталось ехать до конца. Логика очень понятна: мы не просто говорим, что мы сейчас стоим в какой-то вершине и поэтому рассматриваем следующую по очереди вершину на каком-то удалении от старта. Мы еще к этому параметру добавляем какую-то функцию, позволяющую нам оценить более перспективные вершины, от которых, скорее всего, до финиша ехать недалеко. Мы не знаем, сколько на самом деле ехать от каждой вершины до финиша, потому что если бы мы знали, нам и путь не надо было бы искать. Но мы можем это как-то оценить и получить картинку на нижнем рисунке. Мы будем оценивать вершины, которые как-то идут в сторону нашей цели, и рассмотрим существенно меньшее количество вершин, чем в алгоритме Дейкстры. Про это можно много рассказывать, но в целом идея в том, что для корректной работы алгоритма необходимо, чтобы наша эвристика, функция оценки расстояния до конечной вершины, никогда не превышала настоящего расстояния, которое нам осталось проехать. Только в этом случае гарантируется правильная работа алгоритма. ![]() Самое простое, что мы можем сделать, это рассмотреть расстояние до цели напрямик. Очевидно, мы не можем приехать к конечной точке быстрее, чем если мы просто как танк поедем к ней напрямик. Более сложная и более эффективная эвристика — расстояние с учетом наших кинематических ограничений, но без учета препятствий. Предположим, в мире ничего нет, только мы и цель, но машина не может мгновенно перемещаться влево или вправо, ездит по своим законам, по имеющейся физической модели машины. Поскольку никаких препятствий нет, мы можем заранее просчитать расстояние до цели из различных мест, в которых мы можем находиться, и использовать это в качестве эвристической функции. Можем поступить наоборот: сказать, что препятствие есть, но, допустим, машина умеет двигаться вперед, назад, влево, вправо, как угодно, быстро разгоняться и быстро тормозить. Построим наше расстояние с учетом препятствий, которые мы видим. Снова получится оценка, находящаяся ниже, чем реальное расстояние, которое нам осталось проехать. И наконец, из всех эвристик мы можем рассмотреть максимум. Поскольку каждая из них не превышает нашего действительного расстояния, максимум из них тоже не будет превышать действительного расстояния и алгоритм будет работать неплохо. ![]() Второй вариант — оптимизационные методы, основанные не на дискретном, а на более непрерывном подходе. ![]() ![]() ![]() Можем рассмотреть третью производную, которая является рывком, то есть мы не хотим, чтобы ускорение тоже менялось достаточно резко. Кстати, именно от резкого изменения ускорения людей укачивает в процессе езды. Если ускорение фиксированное и машина просто все время разгоняется, то, как показывают исследования, людей не укачивает. Вестибулярный аппарат человека улавливает и не всегда хорошо реагирует, если она то разгоняется, то тормозит. Мы можем не хотеть делать крутые повороты, ограничиваем наш угол. И есть дополнительные ограничения, которые говорят, что машина физически не может разгоняться быстрее какого-то ускорения. Если все мы это учтем каким-то образом, то сможем решить задачу с помощью абстрактного алгоритма минимизации функции и получим некий результат. Отдельно хочется поговорить про вычисления расстояний, потому что в большинстве методов оптимизации очень любят работать с плавными функциями, которые хорошо дифференцируемые, гладенькие. Тогда там все работает хорошо. А наша машина — объект довольно сложной формы, и препятствия, которые мы объезжаем, это тоже объекты хитрых форм. Поэтому тут нужно производить какое-то упрощение. Например, мы можем сказать, что машина — не что-то сложное, а просто пять окружностей, которые ездят туда-сюда. ![]() Что нужно, чтобы плавно изменялось расстояние? Наше эвклидово расстояние до невыпуклых многоугольников не обладает необходимыми нам свойствами и плохо дифференцируемо в местах, где эта невыпуклость возникает. Поэтому мы можем построить такое псевдорасстояние по градиентному полю до нашей ломаной, она здесь обозначена красным и представляет собой препятствие. Мы можем довольно несложно ввести поле расстояний от каждой точки до этой ломаной, которая направлена в сторону ломаной и обладает необходимыми свойствами дифференцируемости — пусть и не являясь строго кратчайшей. Если мы все это сделаем — сможем построить гладкую, красивую и аккуратную траекторию. ![]() Однако выход есть. Мы можем применить алгоритмы, которые работают некоторым случайным образом, но зато позволяют нам построить какой-то приближенный маршрут достаточно быстро и удобно. Например, мы будем строить наш граф, являющийся деревом, итеративным образом. Вначале ничего делить на клеточки не будем, никаких примитивов строить не будем. Мы просто возьмем симулятор нашей машины, который в целом умеет симулировать движение, максимально похожее на то, как машина едет по-настоящему. И возьмем стартовую точку. После этого итеративно выберем случайную точку в пространстве. И — найдем в текущем построенном дереве ближайший к ней узел. Построим ребро в сторону этой точки с помощью симуляции проезда в эту сторону. Получается, мы каждый раз едем от нашего построенного дерева в случайную сторону и можем вершины в этом дереве делать в пространстве любой размерности, то есть в каждой вершине учитывать текущее направление машины, текущую скорость, ускорение, все углы, которые нам важны. А потом, когда мы возьмем новую точку, то возьмем и ближайшую к этой точке вершину. Проедем с помощью какой-то симуляции, например, 5 метров в сторону этой точки. Затем возьмем другую точку и проедем в ее сторону. Что нам это дает? Мы каждый раз исследуем пространство, но очень агрессивно. Мы не ищем оптимальные способы объехать препятствие. Мы просто ездим в разные стороны, но каждый раз делаем это из наиболее исследуемого участка нашего пространства к той, неизведанной стороне. ![]() ![]() ![]() Специализированные методы. Когда машина ездит в городе, у нас нет абстрактных точек А и Б и неструктурированного окружения со случайными препятствиями. У нас в городе все более-менее понятно: есть конкретные полосы и движение нашей машины почти всегда заключается в том, что мы едем примерно по центру полосы, иногда смещаемся левее или правее, чтобы объехать препятствие, иногда перестраиваемся, чтобы по правилам дорожного движения повернуть туда, куда нужно. На перекрестках из одной полосы в другую перестраиваемся. ![]() ![]() ![]() И с тем, чтобы распознавать все это на ходу, есть некоторая проблема. Беспилотный автомобиль довольно легко поместить в ловушку. ![]() ![]() В целом в процессе решения возникает очень много задач построения пути — во всех смежных областях, которые были сначала. Если вы хотите помочь нам разбираться с этими сложностями и реализовывать всё в алгоритмах — обязательно приходите к нам наносить добро. Мы будем рады вас видеть в минской группе разработки. Построение различных путей, учет правил дорожного движения — как раз одна из наших тем. Большое спасибо. Источник: habrahabr.ru ![]() Комментарии: |
||||||