Прежде всего. Является ли радиоуправляемая машина «радиоуправляемой», если она едет сама? Наверное, нет, но, по крайней мере, это была машинка на радиоуправлении. Эта тема о том, как он стал автономным транспортным средством, используя Raspberry Pi, Python и круглые печенья на полу.

Это, пожалуй, один из самых простых автономных транспортных средств. Он наблюдает только за направлением, в котором должен двигаться дальше, используя камеру и некоторые простые алгоритмы компьютерного зрения. 2D-симулятор вождения использовался для обучения «агента-водителя», которого было достаточно, чтобы ввести загадочный ИИ в уравнение. Но сначала давайте посмотрим на компоненты.

Аппаратное обеспечение

  • Дорожный радиоуправляемый автомобиль Kyosho Electric
  • Малина Пи модель 4
  • Пи камера
  • Ардуино Нано
  • Поворотный энкодер
  • Контроллер Xbox360 и USB-донгл

Автомобиль с радиоуправлением изначально был полноприводным, но после удаления карданного вала он стал заднеприводным. Это позволило разместить энкодер в переднем креплении вала. RasPi 4 — это немного более мощная версия Pi3, поэтому я думаю, что они могут быть взаимозаменяемы. Однако все вычисления выполняются в Pi, поэтому у нас не может быть слишком большой вычислительной мощности. Arduino измеряет скорость и напряжение автомобильного аккумулятора. Контроллер Xbox — это просто бонус, который дает возможность управлять экипировкой человека. для целей сбора данных.

Программное обеспечение

  • Компьютерное зрение для извлечения признаков из изображений с камеры
  • Управление приводом (RasPi PWM для управления двигателем и сервоприводом)
  • Выбор агента водителя
  • Код Arduino для определения скорости и измерения напряжения батареи
  • Ведение журнала базы данных MySql для сбора данных
  • Веб-сервер и пользовательский интерфейс приборной панели (поток камеры в реальном времени, построение показателей, управление параметрами)
  • Нейронная сеть для расчетов выходных данных в реальном времени
  • Обученный симулятором агент нейронной сети

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

Моделирование. Обучение агента вождению автомобиля в среде 2D-симуляции было первым шагом к автономному вождению. Сам симулятор представлял собой симулятор OpenAI Car Racing. По умолчанию симулятор не имеет каких-либо функций, которые впоследствии можно было бы легко извлечь из реального мира. Кроме того, тренер должен быть построен. Этот репозиторий имеет некоторые простые функции состояния агента, такие как направление движения, которое в нашем случае используется для радиоуправляемой машины. Также есть трейнер Evolution Strategy, который представляет собой немного брутальный способ найти оптимальные параметры для нейронной сети. Однако задача и сеть достаточно просты

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

Обработка изображений. Теперь, когда у нас есть агент, который знает, как управлять симуляцией, нам нужно сгенерировать те же функции из реального мира. Первым делом нужно было решить, как идентифицировать дорогу. Возможно, наиболее распространенным способом является использование камеры и обнаружения полосы движения. Но для этого проекта мы использовали круглые объекты, «куки». Бросать печенье на пол — это простой способ построить дорожку, которую легко изменить при необходимости. Симметричные круглые формы также не так распространены в природе, что снижает количество ложных срабатываний при использовании компьютерного зрения.

Вероятно, есть сотни различных способов найти круги на изображении, но мы ищем легкое решение. OpenCV предоставляет нам широкий спектр алгоритмов компьютерного зрения, и мы выбрали Hough Circles. Это дает расположение всех кругов, найденных на изображении, в пределах заданных параметров. Однако в нашей установке есть фундаментальная ошибка; Круги на полу видны только как круги с точки зрения вида сверху.

Камера в машине снимает с высоты 25 см над полом под углом 30°. Механически изменить перспективу на вид сверху может быть сложно, но, к счастью, OpenCV дает нам виртуальное преобразование перспективы с использованием точек калибровки. Рисование прямоугольника на полу и использование его известных размеров для деформации изображения с камеры дает нам перспективу вида сверху.

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

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

Управление диском. Модуль управления приводом сопоставляет инструкции по вождению с оборудованием и позволяет нам выбирать, кто будет за рулем. Замена пульта дистанционного управления на управление Pi GPIO была простой, поскольку MCU автомобиля и сервопривод работали с PWM. Аппаратный ШИМ PiGPIO-библиотеки оказался самым надежным для управления.

Модуль позволяет создавать новые классы водителей, которые можно использовать для вождения. Например, в этом проекте было четыре драйвера: Idleдля простоя во время отладки, GamePadдля сбора данных и тестирования оборудования, DumDumдля справки. производительность и ИИ для агента, прошедшего обучение на симуляторе. В каждом классе есть метод set_actions, который устанавливает значения для газа и рулевого управления. Таким образом, может быть несколько разных ИИ и других драйверов, которые имеют свой особый способ расчета следующих действий. Единственное, что меняется в основном модуле, это то, какой класс водителя установлен для водительского места.

Веб-сервер и панель управления. Отладку и управление можно выполнять через SSH, но, поскольку для этого уже требуется подключение к Интернету, почему бы не использовать локальный веб-сервер? Сервер Flask берет ресурсы у Pi, но судя по тестированию производительности, ничего примечательного. Веб-сервер работает как пользовательский интерфейс, позволяющий изменять параметры, отслеживать показатели производительности и времени выполнения, а также просматривать прямую трансляцию с камеры. Панель инструментов представляет собой простой HTML-шаблон, а отображение выполняется на стороне клиента с помощью JS.

Регистратор. Для будущего использования и улучшения может быть полезен сбор данных из тестовых случаев. Сохранение состояния среды во времени позволяет воссоздавать тестовые случаи и анализировать производительность и даже обучать на ее основе новые ИИ. Данные сохраняются в базе данных MySql, также работающей на Pi.

Оно живое!

Прежде чем перейти к результатам, давайте посмотрим, с кем конкурирует ИИ. Ранее уже упоминался класс драйвера под названием DumDum, и это название связано с тем, что он пытается быть наименее интеллектуальным из возможных драйверов. Он имеет предопределенный постоянный выход дроссельной заслонки, а рулевое управление просто: Угол направления = угол поворота. Также у ИИ есть некоторые «гиперпараметры», которые настраиваются вручную. Поскольку симулятор не совсем точно отображает реальный мир, существуют такие параметры, как коррекция скорости для соответствия введенной скорости, коррекция дроссельной заслонки для соответствия ускорению и рулевое управление. коррекция в соответствии с маневрированием. Все это корректируется методом проб и ошибок. А теперь вот как они выступили (ИИ в верхнем ряду, Манекен внизу):

Итак, вполне очевидная победа манекена. Причин тому может быть много, но в целом логично, что простое решение простой задачи работает лучше. Однако одним заметным отличием в поведении ИИ является редкое использование газа. Это стало еще более очевидным при увеличении коррекции дроссельной заслонки, когда в некоторых ситуациях автомобиль двигался назад. Это, вероятно, связано с определением скорости и крутизны кривой, поскольку агент научился тормозить (= отрицательный дроссель) для крутых поворотов на симуляторе. Также стоит отметить, что манекен использовал только постоянные 2% от общей мощности дроссельной заслонки. Это оставляет очень низкое разрешение для ИИ для управления «оптимальным» дросселем (при условии, что 2% — это максимальное значение, с которым может справиться эта установка).

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

Как сделать лучше

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

Разрешение уже было уменьшено до 320x280 для ускорения обработки изображения. Лучшая оптика в камере, вероятно, помогла бы без увеличения разрешения. Однако более высокое разрешение также может помочь, а это требует большей вычислительной мощности. В настоящее время FPS составляет ~27, а ограничивающим фактором является обработка изображения. Тем не менее, камера снимает только 30 кадров в секунду, так что тут нечего улучшать. Вероятно, из кода обработки изображений можно было бы выжать больше производительности, но без более мощного компьютера/контроллера она останется очень ограниченной. Переключение обработки на облако или отдельный сервер легко дало бы гораздо больше вычислительной мощности, но создало проблему с задержкой в ​​сети.

30 кадров в секунду, вероятно, будут иметь большое значение, если сторона компьютерного зрения надежна. Однако увеличение FPS помогло бы быстрее. Для этого потребуется более быстрая камера (60 кадров в секунду) и, конечно же, большая вычислительная мощность, как упоминалось ранее. Более высокие скорости и поверхности с меньшим трением потребуют более быстрого времени реакции, тогда как FPS камеры действительно становится решающим фактором.

Как насчет SLAM? Метод одновременной локализации и картирования широко используется в робототехнике для лучшего понимания агентом окружающей среды. В нашем случае это будет означать, что после того, как автомобиль завершит один полный круг, он будет знать, что будет на следующем круге, и оптимизировать свое вождение на основе этого. И не только это, построение карты и расположение на ней могло бы помочь избежать ложных срабатываний и оставаться на трассе даже на первом круге.

Мы оставим реализацию SLAM для части 2, но давайте посмотрим, что у нас уже есть для этого. Есть только один энкодер, который измеряет скорость вращения дифференциала передних колес. Это дает нам расстояние, на которое продвинулось транспортное средство. Мы не знаем реального угла поворота колес, но знаем, в каком положении мы хотели их повернуть. Вот пример восстановления маршрута из одного из тестовых случаев:

Как и ожидалось, существует высокая неопределенность в локализации с использованием энкодера и угла поворота рулевого колеса. Таким образом, алгоритмы SLAM предпочитают использовать несколько разных источников локализации, таких как кодировщики, CV и LIDAR вместе взятые.

Это где мы получили до сих пор. Я надеюсь, что это даст вам новые идеи для ваших проектов, и оставьте комментарий, если это так!

Вот репозиторий кода:

https://github.com/Miikkasna/acar