Привет, Хабр! Я работаю в небольшом стартапе в Берлине, занимающимся разработкой автопилотов для автомобилей. Мы заканчиваем проект для сервисных станций одного крупного немецкого автопроизводителя и я бы хотел рассказать о нём: как мы его делали, с какими трудностями столкнулись и что нового открыли для себя. В этой части я расскажу про perception модуль и немного про архитектуру решения в целом. Про остальные модули, возможно, расскажем в следующих частях. Буду очень рад обратной связи и взгляду со стороны на наш подход.

Пресс-релиз проекта со стороны заказчика можно найти тут.

Для начала скажу, зачем автопроизводитель обратился к нам, а не сделал проект своими силами. Крупным немецким концернам сложно менять процессы, а формат разработки автомобилей редко подходит для программного обеспечения — итерации долгие и требуют хорошего планирования. Мне кажется, немецкие автопроизводители это понимают, и поэтому можно встретить стартапы, которые основаны ими, но работают как независимая фирма (например, AID от Audi и Zenuity от Volvo). Другие автопроизводители организуют мероприятия вроде Startup Autobahn, где они ищут возможных подрядчиков для задач и новые идеи. Они могут заказать продукт или прототип и через короткий промежуток времени получить готовый результат. Это может оказаться быстрее, чем пробовать делать то же самое самим, и по затратам выходит не дороже собственной разработки. Сложность изменения процессов хорошо демонстрирует количество разрешений, необходимое для того, чтобы начать тестирование машины с автопилотом у заказчиков: согласие на видеосъемку людей (даже если мы не сохраняем данные, а потоковое видео используем только в анонимном виде без идентификации конкретных людей), согласие на видеосъемку территории, согласие профсоюза и рабочего консула на тестирование данных технологий, согласие службы безопасности, согласие службы IT — это ещё не весь список.

Задача


В текущем проекте заказчик хочет понять, возможно ли управлять автомобилями в сервисных центрах при помощи “AI”. Пользовательский сценарий при этом такой:

  1. Техник хочет начать работу с машиной, которая стоит где-то на парковке снаружи тестовой зоны.
  2. Он выбирает на планшете машину, выбирает сервисный бокс и нажимает “Заехать”.
  3. Машина заезжает внутрь и останавливается в конечной точке (лифт, рампа, или что-то ещё).
  4. Когда техник заканчивает работу над машиной, он нажимает на кнопку на планшете, машина выезжает и паркуется на какое-то свободное место снаружи.

Особенности: не на всех машинах есть камеры. На тех машинах, на которых они есть, мы не имеем к ним доступа. Единственные данные на машине, к которым у нас есть доступ — сонары и одометрия

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

Таким образом, управление автомобилем должно происходить по внешним сенсорам, установленным в сервисной зоне.

Решение


Архитектура конечного продукта выглядит следующим образом:

  • В сервисной зоне мы устанавливаем внешние камеры, лидаров и прочего нет (привет Тесла).
  • Данные с камер поступают на Jetson TX2 (по три камеры на каждый), которые занимаются задачей поиска машины и предобработкой изображений с камер.
  • Далее данные камеры приходят на центральный сервер, который носит гордое название Control Tower и на котором они попадают в модули perception, tracking и path-planning. В результате анализа принимается решение о дальнейшем направлении движения автомобиля и оно отправляется в машину.
  • На данном этапе проекта в машину ставится ещё один Jetson TX2, который при помощи нашего драйвера подключается к Vector, который производит дешифровку данных автомобиля и отправку команд. TX2 получает команды на управление с центрального сервера и транслирует их автомобилю.

Для уровня инфраструктуры используется ROS.

Вот что происходит после того, как техник выбрал машину и нажал “заехать”:

  1. Система ищет машину: мы посылаем команду автомобилю мигать аварийными сигналами, после чего мы можем определить, какая из машин на парковке выбрана техником. На начальном этапе разработки мы рассматривали также вариант определения машины по планке номера, но на некоторых участках у запаркованной машины номер может быть не виден. Кроме того, если бы мы сделали определение машины по регистрационном номеру, то разрешение фотографий пришлось бы сильно увеличить, что отрицательно повлияло бы на производительность, а так мы используем одно и то же изображение для поиска и управления автомобилем. Данный этап происходит один раз и повторяется только в случае, если по какой-то причине мы потеряли автомобиль в трекинге.
  2. Как только машина найдена, мы закидываем картинки с камер, на которые попадает автомобиль, в модуль perception, который производит сегментацию пространства и отдает координаты всех объектов, их ориентацию и размеры. Этот процесс постоянный, выполняется со скоростью примерно 30 кадров в секунду. Последующие процессы также постоянные и выполняются до тех пор, пока машина не приедет в конечную точку.
  3. Модуль трекинга получает на вход данные от perception, сонаров и одометрии, держит в памяти все найденные объекты, объединяет их, уточняет местоположение, предсказывает положение и скорость объектов.
  4. Далее path planner, который делится на две части: global path planner для глобального маршрута и local path planner для локального (отвечает за обход препятствий), строит путь и принимает решение, куда ехать нашей машине, отправляет команду.
  5. Jetson на машине принимает команду и транслирует её автомобилю.

Выезд наружу происходит так же, как и заезд.

Perception


Одним из основных и, по моему мнению, самым интересным модулем является perception. Этот модуль описывает данные с сенсоров в таком виде, чтобы можно было точно принять решение о движении. В нашем проекте он выдает координаты, ориентацию и размеры всех объектов, попадающих на камеры. При проектировании этого модуля мы решили начать с алгоритмов, которые позволили бы производить анализ изображения за один проход. Мы попробовали:

  1. Disentangled VAE. Небольшая модификация, внесенная в ?-VAE, позволила нам тренировать сеть так, что латентные векторы хранили информацию об изображении в схематическом виде сверху вниз.
  2. Conditional GAN (самая известная реализация — pix2pix). Данную сеть можно использовать для построения карт. Мы также использовали её для построения схематического вида сверху, вкладывая в неё данные с одной или всех камер одновременно и ожидая схематический вид сверху на выходе.

Одна из итераций Conditional GAN для одной камеры, слева направо: входное изображение, предсказание сети, ожидаемый результат



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

  • За отведенное время мы не смогли научиться использовать данные из латентных векторов для описания изображения. Результатом работы сети всегда была картинка — вид сверху со схематическим расположением объектов. Это менее точно и мы опасались, что такой точности будет недостаточно для управления автомобилем.
  • Решение получается не масштабируемым: для всех последующих установок и для случаев, когда нужно изменить направление некоторых камер, требуется переконфигурация симулятора и повторная полная тренировка.

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

После этого мы подошли к задаче с другой стороны, через обычный поиск объектов + сеть для определения пространственного положения найденных объектов (например такая или такая). Этот вариант нам показался наиболее точным. Единственный минус — он медленнее предложенных до этого подходов, но укладывается в наши возможные рамки задержки, так как скорость движения автомобиля по сервисной зоне не более 5 км/час. Самой интересной работой в области предсказания 3D-положения объекта нам показалась вот эта, которая показывает довольно неплохие результаты на KITTI. Мы построили аналогичную сеть с некоторыми изменениями и написали наш собственный алгоритм определения surrounding box, а если быть более точным, алгоритм оценки координат центра проекции объекта на землю — для принятия решений о направлении движения нам не нужны данные о высоте объектов. На вход сети подается изображение объекта и его тип (машина, пешеход,..), на выходе — его размеры и ориентация в пространстве. Далее модуль оценивает центр проекции и отдает данные по всем объектам: координаты центра, ориентацию и размеры (ширину и длину).

В конечном продукте каждая картинка сначала прогоняется через сеть для поиска объектов, затем все объекты отправляются в 3D-сеть для предсказания ориентации и размеров, после чего мы оцениваем центр проекции каждого и отправляем его и данные об ориентации и размере дальше. Особенностью данного метода является то, что он очень сильно завязан на точность границы boundary box из сети поиска объектов. По этой причине сети типа YOLO нам не подошли. Оптимальный баланс производительности и точности boundary box нам показался на сети RetinaNet.

Стоит заметить одну вещь, с которой нам повезло на данном проекте: земля плоская. Ну, то есть, не такая плоская, как у известного сообщества, но на нашей территории изгибов не наблюдается. Это позволяет использовать зафиксированные монокулярные камеры для проекции объектов в координаты плоскости земли без информации о расстоянии до объекта. В дальнейших планах стоит внедрение monocular depth prediction. Работ на эту тему много, вот, например, одна из последних и очень интересных, которую мы сейчас пробуем для будущих проектов. Depth prediction позволит работать не только на плоской земле, он потенциально должен увеличить точность определения препятствий, упростить процесс конфигурации новых камер и позволит отказаться от необходимости лейблировать каждый объект — нам не важно что именно это за объект, если это какое-то препятствие.

На этом всё, спасибо, что прочитали, и с удовольствием отвечу на вопросы. В качестве бонуса хочу рассказать про неожиданный негативный эффект: автопилот не заботится об ориентации автомобиля, для него не важно как ехать — передом или задом. Главное — ехать оптимально и ни в кого не врезаться. Поэтому есть большая вероятность, что автомобиль часть пути будет проезжать задним ходом, особенно на небольших площадках, где требуется высокая маневренность. Однако люди привыкли, что автомобиль в основном двигается передом, и часто ожидают такого же поведения от автопилота. Если человек бизнеса видит машину, которая вместо того, чтобы ехать передом, едет задом, то он может посчитать, что продукт не готов и содержит ошибки.

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

Комментарии (30)


  1. vassabi
    25.06.2019 10:19
    +1

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

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

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


    1. AlexGechis Автор
      25.06.2019 10:40

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


  1. Veliant
    25.06.2019 10:26
    +1

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


    1. AlexGechis Автор
      25.06.2019 10:36

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


      1. vassabi
        25.06.2019 10:50

        а не смотрели в сторону устройств а-ля «радиометка с сигнализацией» (например)?
        Чтобы находить и уточнять положение машины по нему (+ чтобы оно напоминало о себе при попытке уноса за территорию).


        1. AlexGechis Автор
          25.06.2019 10:52

          Нет, не смотрели. Заказчику интересно именно решение с machine learning


          1. vassabi
            25.06.2019 13:58

            так ведь не для замещения ML, а для помощи.

            PS: В том числе — помощи людям (если он на магните на крыше или хотя бы на дворниках прикреплен, и издает звуки\мигает при движении красным\синим — он даже более заметен ИМХО чем аварийка)


  1. alexbuyval
    25.06.2019 10:45
    +1

    Спасибо за интересный материал!

    Самой интересной работой в области предсказания 3D-положения объекта нам показалась вот эта, которая показывает довольно неплохие результаты на KITTI.

    Мы тоже для своего автопилота в университете Иннополис делали сетку по похожему принципу :)
    Интересно на сколько большой датасет вам понадобился, чтобы получить достаточно точные значения ориентации и размеров?
    К слову сказать, мы использовали КИТТИ + свой датасет с ~3000 изображений и все равно точность детекции ориентации и размеров нас не всегда устраивает.

    В конечном продукте каждая картинка сначала прогоняется через сеть для поиска объектов, затем все объекты отправляются в 3D-сеть для предсказания ориентации и размеров, после чего мы оцениваем центр проекции каждого и отправляем его и данные об ориентации и размере дальше.

    Я правильно понимаю, что у Вас не отдельная 3D сеть, а просто дополнительные слои для регрессии размеров и ориентации?


    1. AlexGechis Автор
      25.06.2019 11:02

      К сожалению, KITTI запрещает коммерческое использование. У нас в датасете около 10тыс аннотированных изображений, половина из них из симулятора. Увеличение размера датасета с определенного момента практически не влияет на улучшение работы сети, наибольший эффект оказывает работа c самой сетью: loss function и тп. Кстати, если тренировать сеть только на данных из симулятора, то результат тоже получается неплохой.

      Я правильно понимаю, что у Вас не отдельная 3D сеть, а просто дополнительные слои для регрессии размеров и ориентации?

      У нас две сети: одна для 2D, вторая для 3D, в которой регрессия размеров и ориентации — отдельные слои.


      1. alexbuyval
        25.06.2019 11:06

        Спасибо!

        У нас две сети: одна для 2D, вторая для 3D, в которой регрессия размеров и ориентации — отдельные слои.

        А какое преимущество это дает? Ведь в этом случае тело сети придется считать 2 раза.


        1. AlexGechis Автор
          25.06.2019 11:14

          Их архитектура в корне разная, плюс результаты работы 2D используются в 3D: сначала мы определяем границы объектов и их тип в 2D сети, потом каждый объект отправляем в 3D, которая уже определяет ориентацию и размеры объекта.


  1. alexbuyval
    25.06.2019 11:15

    А как вы поступаете в случае если машина видна с нескольких камер?
    Фьюзити как-то данные о ее положении или просто выбираете ту, с которой лучше видно?


    1. AlexGechis Автор
      25.06.2019 11:18

      Берем изображение со всех камер, на которых она видна и мы можем гарантировать хорошее качество (не сильно далеко от камеры), далее data fusion в модуле трекинга.


  1. alexbuyval
    25.06.2019 11:24

    Скорее всего на таких скоростях для вас это некритично, но все же спрошу.
    Упирались ли вы в производительность ROS? Например, то что сообщения не всегда гарантированно приходят или прыгает период между сообщениями.
    Думали ли в сторону ROS 2.0 или какого-то другого фреймворка?


    1. r0mans
      25.06.2019 23:41

      Да, ROS2 в pipeline. Сейчас начали тестировать Crystal Clemmys (для другого проекта). С нашей нагрузкой ROS1 более менее справляется, надо учесть, что это ранний прототип и без real-time требований. Но в общем тяжелые данные (картинки с камер, occupancy grids и тд) даже для прототипа лучше передавать в обход ROS топиков (например, gstreamer или nodelets). Также мы используем свой проприетарный bus для общения с актуаторами и сенсорами машины, что дает возможность вывести safety модули в более легкое, высокопроизводительное окружение. С другой стороны нельзя недооценивать возможность очень быстрого прототипирования и огромный выбор модулей для ROS1.


      1. alexbuyval
        26.06.2019 09:55

        Спасибо за развернутый ответ!


  1. alexbuyval
    25.06.2019 11:36

    На данном этапе проекта в машину ставится ещё один Jetson TX2, который при помощи нашего драйвера подключается к Vector, который производит дешифровку данных автомобиля и отправку команд. TX2 получает команды на управление с центрального сервера и транслирует их автомобилю.

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


    1. AlexGechis Автор
      25.06.2019 11:55

      данные вопросы я не могу комментировать, на предыдущий вопрос про ROS уточняю у коллег и скоро напишу.


  1. alexbuyval
    26.06.2019 09:56

    Кстати, а как вы отличаете каким автомобилем вы управляете когда в кадре 2 и более машин одинаковых моделей и цветов?


    1. kisaa
      26.06.2019 10:23

      А также в случае, когда клиент просто решит помигать аварийкой, а ваша система начнет искать (совсем другую) машину?


      1. AlexGechis Автор
        26.06.2019 21:23

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


  1. slovak
    26.06.2019 20:55

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

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

    Просто 5.
    Вопрос с заказчиком разве не обсуждался?


    1. AlexGechis Автор
      26.06.2019 21:13

      Я думаю, если бы заказчик знал ответы на такие детали, то ему бы не понадобилось обращаться во внешнюю фирму за разработкой


      1. slovak
        27.06.2019 10:18

        Масштабируемость и переиспользование — это не деталь, а высокоуровневое требование, которое заказчику вполне по зубам.


        1. AlexGechis Автор
          27.06.2019 10:34

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


  1. anisimovih
    26.06.2019 21:12

    Я правильно понимаю, что если на парковке 100 машин, то вам нужно иметь 100 Jetson? Дороговато выходит.


    1. AlexGechis Автор
      26.06.2019 21:17

      Немного больше: ещё по одному на три камеры. На данном этапе прототипа это так, но в будущем возможен другой формат.


  1. slovak
    27.06.2019 12:04

    автопилот не заботится об ориентации автомобиля, для него не важно как ехать — передом или задом. Главное — ехать оптимально и ни в кого не врезаться.

    Подскажите, ведь критерий оптимальности задается разрботчиком? Если cost функция считается для спланированной траектории, то ничего не мешает задать компонент, который будет штрафовать за каждый метр пройденый задним ходом.
    Какие критерии оптимальности преследовались в Вашем случае?


    1. AlexGechis Автор
      28.06.2019 02:20

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


      1. slovak
        28.06.2019 12:18

        А что Вы ожидали публикуя статью? Одни только восторженные возгласы? )))
        Может быть это и не проблема, поэтому я и интересуюсь. Вы ведь так и не ответили на мой вопрос по поводу критериев оптимальности.