- PVSM.RU - https://www.pvsm.ru -
Всем привет. Продолжаем собирать автомобильный автопилот на компьютерном зрении из гитхаба и палок (начало здесь [1]). Сегодня подключаем к делу датчики движения смартфона (акселерометр, гироскоп и GPS приемник) на Android, осваиваем несложный sensor fusion и окончательно закрываем с кодом для сбора обучающей выборки. Бонусы — Android приложение [2] для записи всех сенсоров синхронзированных с видео и больше часа размеченных данных [3] в рамках импортозамещения иностранных конкурсов [4]. Весь код по-прежнему на github [5].
Это трехосные MEMS [6] акселерометр и гироскоп, они будут нам крайне полезны.
В двух словах напомню (за деталями добро пожаловать в предыдущий пост [1], что конечная цель — обучить систему, которая по кадрам видео с лобового стекла сможет выдавать управляющие воздействия для автомобиля (угол поворота руля и желаемую скорость или ускорение). Для этого нужна обучающая выборка — видео с заездов, где машиной управляет человек, и синхронизированная по времени информация об угле поворота и скорости. В современных автомобилях эти данные можно считывать через CAN шину [7], но надо во-первых покупать и подключать специальный CAN адаптер, а во-вторых разбираться с расшифровкой протокола и формата данных, которые у разных производителей разные. Вместо всей этой возни мы вычисляем управляющие воздействия косвенно — из сырых данных с обычного смартфона, ни к чему дополнительно не подключенного.
В прошлой серии мы научились определять угловую скорость поворота автомобиля в горизонтальной плоскости на основе только видео кадров с помощью библиотеки [8] видео-SLAM [9]. К сожалению, на практике эта библиотека очень неточно вычисляет поступательную скорость устройства. А не зная поступательную скорость, мы не можем обучить даже компонент поворота руля для автопилота по отдельности, так как угловая скорость зависит от комбинации степени поворота руля (эквивалентно, радиуса поворота ) и поступательной скорости автомобиля .
Чтобы получить поступательную скорость, сегодня переключаемся с обработки видео на датчики движения, которые есть почти в любом смартфоне: GPS приемник, акселерометр и гироскоп. Посмотрим на плюсы и минусы каждого, объединим информацию и получим мгновенную скорость для каждого кадра видео. Более того, информацию о вращениях тоже возьмём с гироскопа, что позволит отказаться от более капризного оптического SLAM и нужной ему калибровки камеры смартфона. В итоге новый процесс сбора данных усох до трех "нажатий кнопки": ставим приложение [2] на телефон — записываем трек на заезде — обрабатываем одной командой [10] на компьютере.
В итоге получаем покадровую аннотацию с поступательной скоростью и скоростью поворотов:
Работать будем с андроидом. Безотносительно платформы — для знающих английский интересное видео [11] о том, как информация с разных сенсоров может дополнять улучшать калибровку и уменьшать ошибки. Нас интересуют сенсоры движения [12] (акселерометр и гироскоп) и местоположения [13] (GPS).
С точки зрения API всё просто — запрашиваем у пользователя разрешения, подписываемся на обновления, и получаем поток событий с показанием сенсора и временем измерения. Детали можно посмотреть в исходниках [14].
Рассмотрим плюсы и минусы сенсоров.
GPS — это, как выяснилось, 90% успеха в определении поступательной скорости, по крайней мере на относительно открытых пространствах. От GPS приходят в формате Location [15]:
Огромный плюс GPS данных — погрешности измерений независимы, то есть не накапливаются со временем: на новое измерение не влияет то, сколько измерений было до этого и скакими погрешностями. Это очень важное свойство, на которое опирается весь остальной подход.
Недостаток же в том, что измерения проводятся редко, примерно 1 раз в секунду, и заметно чаще их проводить просто нет смысла — перемещение устройства всё равно было бы сопоставимо с ошибкой измерения. Как результат, во-первых, GPS данные с запозданием реагируют на изменение скорости, а во-вторых с них сложнее убирать шумы — для этого нужно смотреть на соседние по времени измерения, что ещё больше усугубляет нечеткость данных по времени. Вот пример графика скорости с GPS:
Здесь подозрение вызывают первые 25 секунд (постоянное ускорение и вероятное запаздывание GPS измерений) и шум между 30 и 40 секундой. Для затравки, тот же график после обработки данных с акселерометра и гироскопа:
Как видно, есть улучшения по обоим показателям: на ускорения реагируем раньше, и выброс на 35 секунде заглажен.
Инерциальные датчики замеряют ускорения, линейные (акселерометр) и центростремительные (гироскоп). Результат их измерений — оценка изменения движения устройства по отношению к предыдущему моменту времени. Математически это выражается в использовании системы координат [17] привязанной к устройству:
Акселерометр [18] выдает линейные ускорения вдоль трех осей устройства, гироскоп [19] — угловые скорости вокруг тех же трех осей.
Плюс инерциальных датчиков — возможность очень частых измерений, в 400 Гц и выше, что на порядок перекрывает частоту видеокадров в ~30 Гц. Главный минус — отсутствие связи с неподвижной системой координат. Датчики сопособны измерить только изменение относительно предыдущего положения, поэтому для расчета результатов в неподвижной системе координат их показания нужно интегрировать по времени, а при этом ошибки измерений накапливаются — чем дольше период измерения, тем больше итоговая ошибка в следующий момент времени.
Как видно, GPS и инерциальные датчики имеют зеркально противоположные достоинства и недостатки, а значит нужно объединить сильные стороны обоих источников, к чему и приступаем.
Имея запись данных от GPS и инерциальных датчиков, требуется оценить:
Горизонтальное вращение мы уже вычисляли в прошлом посте [1], но, как выяснилось, старый способ (через анализ видео) сложнее и капризнее, чем работа напрямую с гироскопом, поэтому лучше поменять подход.
Казалось бы, чего уж проще. Из школьной физики мы знаем по определению
Но нам нужна скорость в неподвижной системе координат, а система координат акселерометра вращается вместе с устройством. Обозначим R
матрицу вращения из системы координат устройства в неподвижную, тогда
где — ускорение по осям координат утсройства. В свою очередь матрицу поворота получаем просто проинтегрировав вращения, измеренные гироскопом ( — производная матрицы вращения, её можно рассчитать, зная угловые скорости вокруг трех осей):
И всё? Не тут-то было, это только для сферического акселерометра в вакууме работает. Посмотрим на реальные данные со смартфона, неподвижно лежащего на столе:
Наблюдения:
Второй эксперимент — запишем суммарное ускорение с телефона лежащего на столе экраном вверх, а потом — экраном вниз, и сравним:
Наблюдения:
n
измерений составит .Итак, чтобы получить настоящее ускорение в неподвижное системе координат, необходимы поправки к "сырым" измерениям акселерометра. Применим простую модель:
где
Матрицу вращения получим интеграцией угловых скоростей с гироскопа, а вот остальные параметры неизвестны (включая , т.к. неизвестна начальная ориентация смартфона). Найти калибровочные параметры помогут данные с GPS. Вспомним, что измерения GPS довольно точны. А значит скорость, рассчитанная по инерциальным датчикам должна быть близка к скорости по данным GPS. Формализуем эту интуицию как задачу оптимизации. Для каждого интервала между соседними GPS измерениями (порядка 1 секунды) посчитаем дистанцию, пройденную по данным инерциальных данных, и по данным GPS, и целевой функцией назначим метрику L2 по всему времени записи:
где
i
и i+1
.Также обозначим и , и подставляя поправки к сырым замерам акселерометра, получаем окончательный вид целевой функции:
Выглядит страшновато, но на самом деле это простая квадратичная функция, несложно взять производные аналитически и оптимизировать любым численным методом, например L-BFGS [22].
Для начала проверим на коротком отрезке в полминуты:
Здесь "на глаз" не очень понятно, какой график более правильный, но можно объявить успех хотя бы в том смысле, что калибровкой удалось подобрать параметры поправок, с которыми оценки скорости с двух разных источников очень близки. Теперь попробуем тот же подход на более продолжительной записи, порядка 10 минут:
Тут конечно полный провал. Получается, модель простых поправок недостаточна на долгих временных интервалах, то есть остались важные источники искажений, которые она не учитывает. Это могут быть
Бороться с проблемами простой модели поправок для инерциальных датчиков можно по-разному. Возможные варианты:
Мы схитрим. Ведь в конечном итоге нам интересна не сама по себе калибровочная модель, а итоговые значения скорости. А раз на коротких отрезках калибровка справляется, можно применить стандартный прием со скользящим окном:
Конечный результат:
Объявляем успех с поступательной скоростью, возвращаемся к угловой скорости поворотов.
Угловая скорость поворота нужна, чтобы вычислить радиус поворота (и соответственно угол поворота руля): . Гироскоп замеряет угловую скорость напрямую, но в трехмерном пространстве: кроме вращения вокруг вертикальной оси (yaw — собственно поворотов), в данных отражаются еще и вращения вокруг попреречной (pitch — изменение уклона дороги, проезд лежачих полицейских) и продольной (roll — заезд одной стороной в колею или яму):
Нам нужно выделить из трехмерных вращений только компоненту вокруг вертикальной оси (в системе координат автомобиля). Соответственно, нужно получить направление этой оси. Для этого воспользуемся наблюдением, что величина вращения вокруг вертикальной оси гораздо больше, чем вокруг продольной и поперечной (повороты по 90 градусов — норма, а вот смена уклона и колея — к счастью, нет). А значит можно просто принять ту ось, вокруг которой общее вращение было максимальным, за вертикальную.
Математически выделить доминантную ось вращения удобно, представив каждое элементарное вращение (т.е. измерение гироскопа) в виде кватерниона. Вращение вокруг единичной оси (x,y,z)
на угол представляется кватернионом
Удобство в том, что первые три компонента кватерниона характеризуют одновременно и направление оси вращения, и величину вращения. Поэтому хороший результат дает метод главных компонент [23], примененный просто к первым трем компонентам кватерниона. После выделения доминантной оси, получается такая картина:
Видно, что заметно большая доля вращений проходит вокруг выделенной доминантной оси, чем вокруг остальных двух перпендикулярных ей.
Кстати, в предыдущем посте [1] тоже применялся метод главных компонент, но тогда я не сообразил применить его к вращениям напрямую, а выделял горизонтальную плоскость по трехмерной траектории (т.е. основываясь на смещениях вместо вращений). Новый способ лучше не только тем, что полностью не нуждается в информации о смещениях, но и тем, что вертикальная ось выделяется в системе координат устройства. То есть с новым подходом вертикальная ось — перпендикуляр к локальной плоскости дороги, вместо средней плоскости всей траектории в старом подходе. Например, теперь вертикальная ось поворачевается (вместе с автомобиле при переезде от дороги в гору к дороге под гору). В результате выделение горизонтального поворота из общего вращения стало точнее.
Бонусом к коду [5] хочу поделиться уже обработанными данными [24] для тех, кому интересно поиграться с обучением своих моделей. В торренте больше часа сырых данных, записанных на подмосковных дорогах, плюс (в директориях postprocessed
) результаты вычисления поступательной скорости и угловой скорости поворотов. Если воспользуетесь — будет интересно узнать о результатах!
На этом всё, в следующей серии — учимся предсказывать управляющие воздействия по видео.
Автор: waiwnf
Источник [25]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/obrabotka-izobrazhenij/256203
Ссылки в тексте:
[1] начало здесь: https://habrahabr.ru/post/325704/
[2] Android приложение: https://play.google.com/store/apps/details?id=ru.pilotguru.recorder
[3] размеченных данных: #processed-data-torrent
[4] иностранных конкурсов: https://medium.com/udacity/challenge-2-using-deep-learning-to-predict-steering-angles-f42004a36ff3
[5] на github: https://github.com/waiwnf/pilotguru
[6] MEMS: https://ru.wikipedia.org/wiki/%D0%9C%D0%B8%D0%BA%D1%80%D0%BE%D1%8D%D0%BB%D0%B5%D0%BA%D1%82%D1%80%D0%BE%D0%BC%D0%B5%D1%85%D0%B0%D0%BD%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%B8%D0%B5_%D1%81%D0%B8%D1%81%D1%82%D0%B5%D0%BC%D1%8B
[7] CAN шину: https://ru.wikipedia.org/wiki/Controller_Area_Network
[8] библиотеки: https://github.com/raulmur/ORB_SLAM2
[9] видео-SLAM: https://en.wikipedia.org/wiki/Simultaneous_localization_and_mapping
[10] одной командой: https://github.com/waiwnf/pilotguru#velocity-from-imu
[11] интересное видео: https://www.youtube.com/watch?v=C7JQ7Rpwn2k
[12] сенсоры движения: https://developer.android.com/guide/topics/sensors/sensors_motion.html
[13] местоположения: https://developer.android.com/guide/topics/location/strategies.html
[14] в исходниках: https://github.com/waiwnf/pilotguru/blob/master/mobile/android/app/src/main/java/ru/pilotguru/recorder/MainActivity.java
[15] Location: https://developer.android.com/reference/android/location/Location.html
[16] точности координат: https://developer.android.com/reference/android/location/Location.html#getAccuracy()
[17] системы координат: https://developer.android.com/guide/topics/sensors/sensors_overview.html#sensors-coords
[18] Акселерометр: https://developer.android.com/guide/topics/sensors/sensors_motion.html#sensors-motion-accel
[19] гироскоп: https://developer.android.com/guide/topics/sensors/sensors_motion.html#sensors-motion-gyro
[20] на уровне ОС: https://developer.android.com/guide/topics/sensors/sensors_motion.html#sensors-motion-linear
[21] центральной предельной теореме: https://ru.wikipedia.org/wiki/%D0%A6%D0%B5%D0%BD%D1%82%D1%80%D0%B0%D0%BB%D1%8C%D0%BD%D0%B0%D1%8F_%D0%BF%D1%80%D0%B5%D0%B4%D0%B5%D0%BB%D1%8C%D0%BD%D0%B0%D1%8F_%D1%82%D0%B5%D0%BE%D1%80%D0%B5%D0%BC%D0%B0
[22] L-BFGS: https://en.wikipedia.org/wiki/Limited-memory_BFGS
[23] метод главных компонент: http://www.chemometrics.ru/materials/textbooks/pca.htm
[24] уже обработанными данными: https://github.com/waiwnf/pilotguru/raw/master/data/open/torrents/pilotguru-data-20170523.torrent
[25] Источник: https://habrahabr.ru/post/329484/
Нажмите здесь для печати.