Гонщики ненавидят его за этот простой трюк

Есть соревнование по автономному вождению под названием F1десятая, которое имеет как физическую версию (в которой вам нужен физический автомобиль, масштаб 1/10), так и виртуальную, где любой может соревноваться. В этом сообщении блога мы сосредоточимся на виртуальной гонке, которая поставляется с gym-подобной средой под названием f1tenth_gym, которая выглядит следующим образом:

Да, я знаю — вы почти чувствуете запах горящей резины :)
Но на самом деле, простота этой среды (и большинства gym сред, я полагаю) является ее самой сильной стороной. Вы можете быстро создавать прототипы и тестировать больше идей. Именно по этой причине я перешел на эту среду с симулятора CARLA, который, хотя и красивее, иногда слишком громоздкий.

Контроллер, который управляет автомобилем в коротком клипе выше, называется Pure Pursuit, и лучшее время круга, которое я получил, составило 52,47 с после тестирования более 1000 различных комбинаций параметров. Тема этой записи в блоге: как мне удалось сократить время круга до 44,35 с, используя те же данные, которые я собрал при поиске оптимальных параметров контроллера.

Введение

У автомобиля два исполнительных механизма: угол поворота и нужная скорость (а не ускорение, как можно было бы ожидать от «обычного» автомобиля).

Я использовал контроллер Pure Pursuit, который, по сути, направляет угол поворота руля в какую-то точку, лежащую дальше по дороге на заранее заданном пути, что дает довольно простой, но достаточно надежный способ выбора первого привода. (Кстати, если вы хотите узнать больше о контроллере Pure Pursuit, не смотрите дальше этой лекции.) Это расстояние часто называют расстоянием упреждения, и я должен отметить, что обычно это расстояние зависит от скорости контроллера. транспортное средство, но в моей реализации оно фактически заморожено на протяжении всей гонки, просто чтобы сделать его еще проще.

Нужно еще придумать второй актуатор, скорость. Самый простой подход: придерживайтесь заранее определенной скорости, если только центробежная сила не превышает пороговое значение усилия на шину, и если это произойдет, уменьшите скорость до значения, которое находится прямо под этой точкой. Очевидно, что это упрощение обречено на неудачу, потому что: динамика автомобиля намного сложнее, а также потому, что, хотя мы просим конкретную скорость, машина не может просто мгновенно «сделать ее такой». Например: предположим, что мы идем со скоростью 10 м/с, и наша процедура определяет, что на самом деле скорость должна быть максимум 5 м/с. Запрашивать конкретную скорость — это не то же самое, что волшебным образом устанавливать скорость транспортного средства на это значение, для достижения этого требуется время.

Таким образом, мы получаем довольно упрощенный контроллер, поведение которого (и общая производительность) зависят от трех параметров:
• расстояние просмотра вперед | 4,24 м
• уставка скорости | 10,62 м/с
• Максимальное усилие на шину | 13.42N
, где приведены значения, для которых я получил лучшее время круга, просто чтобы дать вам представление об их величинах.

Мотивация

Проблема с этим контроллером заключается в том, что вы можете найти параметры, которые дают вам удовлетворительные результаты для одного набора условий (скажем, определенного поворота), но не для всей гоночной трассы. В частности, в интересующем меня треке много прямых:

Наш простой контроллер может либо хорошо проходить повороты, либо быстро двигаться по прямым, но не то и другое одновременно. Нужно будет оптимизировать путь, чтобы иметь возможность быстрее проходить повороты, или добавить оператор «if» в код, чтобы быстро двигаться по прямой и медленно проходить повороты, или любой другой трюк, чтобы сделать его более шикарным. Это увеличило бы общее количество параметров и, честно говоря, выглядело бы немного неуклюже. Но также я имел в виду более широкую картину, а именно: я хотел иметь процедуру, которую можно было бы обобщить для гонок против противников. (Однако в следующем посте в блоге.)

Идея заключалась в том, чтобы обучить модель, которая имитирует поведение нашего слабого контроллера для заданного набора параметров, а затем использовать эту модель для непрерывного определения наилучших параметров. Для этого необходимы две вещи: 1) метод подсчета параметров, который позволит нам определить, какие из них являются «лучшими», и 2) процедура определения лучших параметров в данной ситуации без оценки всех возможных комбинаций значений параметров в реальном времени. , во время гонки.

Методы

Модель

Входными данными для модели являются три вектора: состояние транспортного средства, путь, по которому мы должны следовать, и параметры контроллера. И есть два выходных вектора: будущая траектория и будущие приводы, необходимые для того, чтобы эта траектория сбылась.

ВВОДЫ:
состояние транспортного средствасодержит 5 чисел: продольная и поперечная скорости, угловая скорость (координата Z) и текущие приводы (угол поворота и скорость). Обратите внимание, что нет ни положения, ни рыскания. Это связано с тем, что мы уже работаем в системе координат, центрированной на автомобиле (его положение всегда (0, 0)), с осью X, направленной вперед в направлении, в котором указывает автомобиль (поэтому рыскание всегда 0).

Цент обозначает осевую линию, то есть путь, по которому мы идем. Как следует из названия, это путь, который лежит ровно посередине между границами гоночной трассы. (Очевидно, что этот путь не самый быстрый, но об этом мы поговорим подробнее в следующем посте.)

И, наконец, params — это параметры контроллера (упреждающее расстояние, заданное значение скорости и максимальное усилие на шине), которые были установлены во время записи данных. Идея состоит в том, чтобы искать лучшие параметры во время вождения с помощью онлайн-процедуры градиентного подъема, чтобы мы постоянно адаптировались к меняющимся условиям.
_________

ВЫВОДЫ:
траектория – это 150 двухмерных точек, представляющих будущие положения автомобиля, а действие  – это вектор, содержащий будущие исполнительные механизмы: 9 углов поворота и 9 скорости.

Нам нужна траектория, чтобы вычислить счет позже, в то время как приводы нужны, чтобы управлять транспортным средством. Хотя я должен сказать: не все из них, я беру только первый угол поворота и скорость и отбрасываю остальные (как вы обычно делаете в контроллере, таком как Model Predictive Control, который я использовал в предыдущем сообщении в блоге ).
_________

Цветные прямоугольники на графике изображают модули, содержащие один или несколько полносвязных слоев, ничего особенного.

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

Счет

Первоначально я использовал термин «возврат», но потом понял, что это может сбить с толку читателей, подкованных в обучении с подкреплением, поэтому я остановился на «оценке». Помните, мы хотели бы иметь возможность сказать, насколько хороши текущие параметры (те, которые используются в качестве входных данных для нейронной сети), то есть мы хотим присвоить оценку параметрам контроллера. Я использовал следующую формулу для подсчета баллов:

где прогресс — это функция траектории и центральной линии и просто общее расстояние, пройденное вдоль центральной линии, тогда как штраф — это функция всех расстояний между точками в траектория и все точки на ближайших границах гоночной трассы. Подробности смотрите в коде.

Во время вывода, управляя транспортным средством, я оцениваю градиент оценки по отношению к параметрам контроллера, и я делаю это, подавая на модель пакет размером 25, в котором все состояния и центральные входные данные одинаковы, но параметры контроллера различаются, и это: текущие значения параметров + 24 соседних значения, необходимые для оценки градиента.

Я постоянно обновляю параметры контроллера, как вы обычно делаете в цикле градиентного подъема:

Эта онлайн-оптимизация, вероятно, никогда не достигает оптимума, отчасти потому, что ландшафт очков постоянно меняется, а отчасти потому, что это довольно грубый подход, но надежда была, что он, по крайней мере, достаточно быстро адаптируется к новым условиям.

Полученные результаты

Это графическое представление, которое я использовал, чтобы определить, едет ли модель так, как задумано (см. полное видео здесь):

В верхнем ряду показаны прогнозы модели (слева направо): будущая траектория (150 шагов в будущее), 9 будущих углов поворота и 9 будущих скоростей. Красные линии и точки представляют лучший прогноз в партии размером 25, синие — результаты для текущих параметров контроллера. Все эти серые линии соответствуют неоптимальным входным параметрам.

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

Данные

Я хотел бы проверить этот подход на реальном автомобиле (масштаб 1/10, не нужно паниковать), поэтому мне нужно было учитывать две вещи: безопасность и количество необходимых данных.

Безопасность обеспечивается до тех пор, пока любые стены находятся далеко от пути следования автомобиля и алгоритм локализации работает корректно. Если оба варианта верны, я могу выбрать значения параметров контроллера из довольно широкого диапазона и запустить сбор данных без дополнительного контроля.

Лучшее время круга, которое я получил (44,35 с), было, когда я обучил модель на данных из 1000 гонок, каждая гонка длилась 110 с времени моделирования (может быть, 7 с в реальном времени), так что 1000 x 110 с = 30,6 часа, слишком долго. Но я также провел эксперименты, в которых было проведено всего 32 гонки (что составляет примерно 1 час времени моделирования), а лучшее время круга тогда было 45,49 с, что «достаточно хорошо». Наш реальный мир немного сложнее, так что 1 час времени симуляции может означать что угодно, но, по крайней мере, это дает мне некоторую надежду, что это достижимо.

Время вывода

Вывод на моей рабочей станции (GTX 1080Ti) вместе с вычислением прогресса и штрафов (которые также выполняются на графическом процессоре) занимает ~1,5 мс. Это для партии размером 25, но я также проверил, сколько времени требуется для партии размером 512, и это составило ~ 3,1 мс. Я пока не знаю, насколько быстро это будет на Jetson, но, опять же, это выглядит многообещающе, даже без каких-либо дополнительных ускорений (я думаю о TensorRT, это то, что я знаю лучше всего).

Обсуждение и будущая работа

Я не упускаю из виду, что сокращение времени круга не было бы таким значительным, если бы я использовал более сложный контроллер. В частности, MPC, оптимизирующий пройденное расстояние вдоль центральной линии, вероятно, приведет к тому, что модель не будет иметь такого значительного сокращения времени прохождения круга (если, например, что-то не так с динамической моделью, используемой для контроллера). Ускорение контроллера Pure Pursuit здесь не имело особого значения, я просто хотел знать, в правильном ли направлении я двигаюсь, нет ли в моем коде критических ошибок.

Тот факт, что время круга сократилось, является хорошим признаком, и теперь я могу перейти к следующему шагу — оптимизации ввода «центов», используемого моделью. В настоящее время это невозможно, потому что эта функция имеет размер 600 (300 2D путевых точек), но ее можно существенно сократить. Как только это будет сделано, и как только я выясню, как эффективно выбирать пространство возможных путевых точек, я не только смогу следовать более быстрым путем, но и надеюсь избежать столкновений с препятствиями.

Следующим шагом после этого является избегание столкновений с противниками. Для этого мне нужно было бы хотя бы примерно спрогнозировать их будущие позиции. Но подождите секунду... текущая модель может сделать именно это, все, что мне нужно сделать, это немного увеличить партию, она все равно будет невероятно быстрой. (Предполагая, что я знаю состояние своих противников, но это «выполнимо».) Затем я могу рассчитать штраф, используя не только границы, но и предсказанную траекторию противников, и оптимизировать счет, как я делаю сейчас.

Это то, где я сейчас нахожусь и куда я хотел бы добраться отсюда. Проект разделен на три репозитория:
* форк проекта f1tenth_gym
* этот репозиторий для обучения модели
* и этот всеобъемлющий репозиторий (пакет Python) содержащий код, используемый в обоих вышеуказанных проектах.

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