Несколько месяцев назад, сразу после Burning Man, я заказал запятую EON Devkit с серой Пандой и Жирафом (теперь они объединяют их в одну автомобильную сбрую и берут еще 140 долларов (199 + 60 - ›399 долларов)).

Установив его на свою машину (Honda Civic 2016 Touring), я был рад запустить его с openpilot 0.6.4 (после прочтения документов, разбросанных по сети).

Как исследователь и инженер CV&DL в течение многих лет, я тестировал алгоритмы в openpilot в различных сценариях и обнаружил, что поведение алгоритма определения полосы движения является интересным:

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

Я заглянул в исходный код openpilot, обнаружил, что все три модели глубокого обучения в openpilot находятся в формате Контейнер глубокого обучения Qualcomm (DLC), и легко нашел место, где вызывается модель обнаружения полосы движения:

Очевидно, что коды в «TEMPORAL» указывают на то, что реализована некоторая рекуррентная структура.

Погрузитесь в функцию addRecurrent:

Из кода кажется, что субвектор из выходного вектора сети связан с входным тензором в сети. Этот вектор имеет размер 1x512 (TEMPORAL_SIZE).

Помимо подсказки в исходном коде, я также нашел недавний твит от comma.ai, указывающий, что они фактически реализуют Gated Recurrent Units (GRU) в своей модели вождения:

Но то, как ГРУ реализованы в модели, остается для меня вопросом. Это реализовано с помощью convGRU (например, convLSTM) или структурой CNN + RNN? Как определены и организованы выходы сети?

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

Я думал, что информация в файле DLC, скорее всего, зашифрована (что оказалось неверным), поэтому я начал с исходного кода.

Анализ исходного кода

Углубившись в код driving.cc, можно легко увидеть из кодов и комментариев, что модель выводит вероятности и стандартные отклонения пути движения, левой полосы и правой полосы, а также различной информации от ведущего автомобиля :

Все эти коды находятся в функции model_eval_frame, и эта функция вызывается в selfdrive / visiond / visiond.cc:

Из кодов в visiond.cc видно, что выходные данные модели вождения публикуются в ZMQ через порт 8009.

Я провожу поиск по запросу «8009» в коде и нахожу всех подписчиков:

Первый подписчик находится в ui.c, который в основном используется для отображения результатов обнаружения в EON Devkit.

Второй подписчик определен в service_list.yaml, поэтому мне нужно найти базовые функции, которые вызывают этот файл. К счастью, с помощью нескольких раундов перекрестного поиска (благодаря VS Code) я нахожу всех подписчиков на вывод driving_model:

Все эти подписчики представляют собой модули, написанные на Python в папке controls. Модуль радара получает информацию о ведущей машине от модели вождения и объединяет ее с данными радара для более точного обнаружения свинца. Модуль планирования получает информацию о пути движения и реализует прогнозирующее управление модели (MPC) для скорости движения. Модуль lane_planner получает информацию о возможном пути, левой и правой полосах движения и выводит ее в модуль path_planner.

Кроме того, я обнаружил, что service_list.yaml включает в себя все публикации / подписки ZMQ и связь между ними:

Объединив всю эту информацию, я рисую черновую диаграмму, чтобы показать общие интерфейсы модели вождения:

Визуализация

Однако анализ кода не дает мне много полезной информации, чтобы сделать вывод об архитектуре глубокой нейронной сети. Поэтому я планировал проанализировать driving_model.dlc, создав изолированную среду тестирования с использованием Qualcomm Snapdragon Neural Processing Engine (SNPE) SDK.

По совпадению, когда я изучал справочное руководство SNPE SDK, я обнаружил, что на самом деле существует инструмент визуализации для файла DLC: snpe-dlc-viewer.

Все инструменты в SNPE SDK работают только в среде Ubuntu. Поэтому я быстро запустил докер для Ubuntu на своем Macbook Pro, установил необходимые библиотеки python и установил PYTHON_PATH, а затем набрал команду snpe-dlc-viewer, чтобы преобразовать driving_model.dlc в html (я был так взволнован, когда настал этот момент). HTML предоставляет фантастический интерфейс для визуализации модели:

Из визуализации можно легко заметить, что CNN извлечения признаков имеет структуру, подобную ResNet, состоящую из 4 слоев (от conv2 до conv5):

После CNN элемент 8x16x4 преобразуется в вектор 1x512, и вектор передается в структуру, подобную RNN:

Эта структура, очевидно, является модифицированной версией ГРУ:

После этапа RNN выход 1x512 разделен на 5 каналов. Первые 4 канала подключены к 4-слойным MLP и, наконец, выводят информацию о пути (1x384) , левой полосе (1x385) , правой полосе (1x385) и отведение (1x58):

Пятый канал напрямую связан с выходом и снова подключается к входу GRU (rnn_state: 0) в коде. Для получения дополнительных сведений о модели вы можете визуализировать модель с помощью snpe-dlc-viewer или просто загрузить HTML-файл ниже и открыть его в браузере:



Еще одна вещь, заслуживающая внимания: начиная с openpilot 0.6.5, comma.ai изменил этап между CNN и GRU с простой структуры свертки 1x1 на структуру, подобную начальной:

Я считаю, что это изменение является ключом к улучшению прогнозирования пути и обнаружения потенциальных клиентов, упомянутых в RELEASES.md.

Обсуждение

Пока что я объяснил интерфейс и структуру модели вождения. Однако остается еще один вопрос:

Из визуализации модели видно, что вектор DESIRE 1x8 объединяется с выходными данными CNN и растворяется в GRU:

Из кода мы видим, что вектор DISIRE инициализируется всеми нулями и не используется во время вывода:

Следовательно, мы можем сделать вывод, что ввод DESIRE не используется сейчас, и я считаю, что этот ввод зарезервирован для использования в будущем.

Но что может быть в будущем? Я поискал ключевое слово «desire» в исходном коде openpilot и нашел перечисление с 7 определенными статусами:

Не уверен, связано ли это «Желание» с «Желанием» в driving.cc. Если это так, будет очень интересно увидеть обратную связь вектора управления с моделью вождения и напрямую повлиять на результаты восприятия.

В этой статье рассказывается о моем пути к расшифровке модели вождения в openpilot. Я хотел бы поблагодарить comma ai за открытый исходный код их кода и моделей.

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

Пожалуйста, дайте мне знать, если есть какие-либо вопросы или что-то неправильное / неточное в этой статье.