Николай Павлов · инженер Инженерный разбор · 2026

Автомобильная навигация · GNSS · Android · полевые испытания

Car GNSS Bridge

Как я связал внешний приёмник GNSS, данные автомобиля, счисление пути и автономную карту, чтобы штатный навигатор не останавливался вместе со спутниковым решением.

Короткая версия. Car GNSS Bridge получает координаты внешнего приёмника и сигналы движения автомобиля, формирует стандартный Android Location и передаёт его штатному навигатору. Внешний приёмник может быть обычным одноантенным: достаточно совместимого потока NMEA. Когда GNSS пропадает, свободное счисление пути (DR) продолжает оценивать перемещение, а RoadLock удерживает позицию на дорожном графе. Если достоверных данных уже недостаточно, система фиксирует последнюю координату в HOLD.
Яндекс Навигатор на штатной мультимедийной системе Geely Monjaro
Интеграция без переделки навигатораШтатное приложение получает стандартный Android Location; изменять его программный код не требуется.
01 · Задача

Когда GNSS в Москве перестал быть надёжным

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

Так появился Car GNSS Bridge. Приложение работает на штатной мультимедийной системе Geely Monjaro под Android 9, принимает GNSS по USB, Bluetooth или TCP и собирает несколько независимых источников в один стандартный Android Location. Сам навигатор при этом менять не нужно.

Главная граница проекта принципиальна: доступ к данным внутренней шины автомобиля выполняется только для чтения через штатные программные интерфейсы. Bridge не управляет электронными блоками и ничего не записывает во внутреннюю шину. Единственный исходящий поток к внешнему приёмнику — стандартные поправки RTCM от NTRIP. Дополнительный модуль LSPosed передаёт скорость и проверяет подтверждение приёма (ACK), но координату не изменяет.

Car GNSS Bridge на штатной мультимедийной системе с панелью калибровки
Car GNSS Bridge на штатной мультимедийной системе. Данные внутренней шины читаются через штатные программные интерфейсы; записи в шину нет.
02 · Архитектура

Сначала состояние сигнала, потом его значение

Одно из главных правил архитектуры: отсутствие измерения нельзя подменять нулём. Поэтому рядом с каждым значением я храню источник, качество, состояние и время последнего обновления. Устаревшая скорость означает «измерения нет», а не «машина остановилась». Неизвестная передача тоже остаётся отдельным состоянием. Даже NMEA с правильной контрольной суммой ещё не становится доверенной координатой автоматически.

Дальше единый рабочий контур проверяет позицию, объединяет скорость и курс и выбирает режим выхода. Пока спутниковое решение достоверно, используется GNSS. После его потери свободное счисление пути (dead reckoning, DR) прогнозирует перемещение, а RoadLock удерживает этот прогноз на дорожном графе. Если нужных входов не хватает, система не делает вид, что всё знает, и переходит в HOLD.

Архитектура Car GNSS Bridge: GNSS, автомобильные сигналы, автономная карта, RoadLock и Android Location
Путь данных от источников до штатного навигатора.
03 · Приём данных

Четыре транспорта, один формат на выходе

Система принимает NMEA от любого совместимого внешнего GNSS-приёмника. Для штатной работы достаточно приёмника с одной антенной: двухантенная конфигурация не требуется. Приёмник может быть подключён через USB Serial, Bluetooth SPP, BLE UART или TCP. Различия этих каналов я спрятал за одним контрактом: выше транспортного слоя всегда приходят полные строки NMEA. Каждый канал сам замечает остановку потока, ограничивает повторные подключения и отбрасывает мусор. USB перебирает подходящие драйверы и скорости порта, TCP не принимает двоичный поток и слишком длинные строки, а BLE ограничивает очередь поправок RTCM.

На уровне NMEA важна уже не доставка, а согласованность измерений. GGA и RMC объединяются только тогда, когда их время расходится не более чем на 1,5 с. Координату, время и качество даёт GNSS. Скорость и путевой угол из RMC я намеренно не использую в объединённом решении: для них есть независимые автомобильные источники. В прототипе я отдельно испытывал двухантенный модуль как возможный независимый источник абсолютного курса: такой приёмник определяет направление по линии между антеннами. Его сообщения THS/HPR и данные второй антенны, как и GSV, оставались в диагностике и не были обязательны для работы системы.

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

04 · Автомобильные данные

Скорость выбирается, а не усредняется

ECARX — это программная платформа штатной мультимедийной системы автомобиля. В разных её версиях скорость доступна через Android Car, AdaptAPI, старый интерфейс ecarx.car или MConfig. Все эти каналы дают доступ к данным внутренней шины автомобиля только для чтения через штатные программные интерфейсы. Я не смешиваю их показания: селектор выбирает один свежий источник по приоритету. По умолчанию значение живёт 700 мс.

Автомобильная скорость записывается в каждый публикуемый Location, даже в HOLD. Это важно: если поле оставить пустым, навигатор может сам вычислить скорость по разности координат. Тогда небольшой скачок позиции будет выглядеть как резкое ложное ускорение.

Со временем похожая история. Location.time получает системные часы Android, эпоха GNSS хранится отдельно в gnss_time_ms, а порядок событий задаёт монотонный elapsedRealtimeNanos. В результате часы приёмника и мультимедийной системы больше не могут переставлять кадры местами.

Экран состояния Car GNSS Bridge со скоростью, курсом и источниками
На экране видны не только значения, но и их источники, возраст измерений и текущий режим формирования координаты.
05 · Курс автомобиля

Как определить направление без магнитометра

У курса нет одного безусловно надёжного источника, поэтому каждому датчику отведена своя роль. Абсолютное направление относительно севера я получаю по хорде — линии между двумя принятыми координатами GNSS. База должна быть не меньше 8 м, качество обеих точек проверяется отдельно, а при движении задним ходом азимут разворачивается на 180°. Магнитометр мультимедийной системы, Android IMU и путевой угол из RMC для этой роли оказались недостаточно надёжными.

Прогноз по углу руляω = v · tan(δ) / (L + K·v²)
Оценка по задним колёсамω = (vR − vL) / track

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

Схема комплексирования угла руля, угловой скорости по колёсам, хорд GNSS и направления дороги
Откуда система получает направление движения.

Что показал опыт с двухантенным модулем. Это был отдельный эксперимент, а не требование к системе. В журнале модуля было 3 215 записей курса: 692 — с плавающим решением float; фиксированного решения fixed не было ни разу. Медианная неопределённость решений float составила 46,8°. В этих испытаниях модуль не подошёл на роль основного источника абсолютного курса, поэтому его данные остались диагностическими.

06 · Режим выхода

Что происходит после потери GNSS

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

При потере GNSS поставщик координат Android продолжает работать. Пока свежи скорость, курс и направление, свободный DR оценивает перемещение, а RoadLock сопоставляет его с дорожным графом и удерживает машину на выбранной дороге. На остановке или при нехватке данных координата переходит в HOLD. У свободного DR есть и жёсткая граница: без внешней поправки он работает не более десяти минут движения, после чего включается защитный HOLD-CAP.

Машина состояний GNSS, DR, рабочего RoadLock и безопасного HOLD
Переключение между GNSS, DR, RoadLock и HOLD.
07 · Автономная карта

Карта корректирует курс и поддерживает RoadLock

Для работы без сети я собрал дорожный граф OpenStreetMap в собственный бинарный формат .cgbr. Внутри — заголовок с CRC, тайлы 0,02° × 0,04°, метровое квантование и компактные приращения zigzag-varint. Файл лежит в APK без сжатия, проверяется при открытии и читается через отображение в память (mmap). Весь ресурс занимает 33 613 210 байт.

Конвейер OpenStreetMap к roads.cgbr и memory-mapped чтению
Автономная карта: от OpenStreetMap до ближайших дорог.

Раз в две секунды первый картографический этап ищет коридор в радиусе 100 м, проверяет качество и непрерывность совпадения и оценивает направление дороги. Здесь карта поправляет только общий сдвиг курса. Координату удерживает уже отдельный RoadLock после потери GNSS. Важно, что оба алгоритма получают свободный DR, а не собственный предыдущий результат: иначе карта начала бы подтверждать сама себя.

08 · RoadLock

Удержание позиции на дорожном графе

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

После подтверждённой потери GNSS RoadLock публикует в Android Location координату, согласованную с дорожным коридором. Но привязка не выполняется любой ценой. Если уверенного лидера нет, выбор откладывается или сопровождение прекращается, а система возвращается к предусмотренному безопасному режиму. При отказе от гипотезы накопленное смещение гасится плавно.

Рабочий процесс RoadLock: кандидаты дороги, оценка гипотез и публикация координаты CORRIDOR
Как RoadLock продолжает движение по дорожному графу.
Выбор ветки по изменению курса, величине невязки и запасу до второго кандидата
Выбор дороги по фактическому повороту.
09 · Полевые испытания

Что показали реальные поездки

Одну из ранних серий RoadLock я провёл в безопасном режиме: рассчитанный дорожный коридор записывался в журнал, но не попадал в навигатор. Цель была простой — найти слабые места до включения рабочего выхода. Числа из раннего эскизного описания, для которых не оказалось экспериментальных данных, я из статьи убрал.

344 м / 1 440 мошибка свободного DR в первом контролируемом отключении GNSS — 23,9%
365 м / 1 548 мошибка во втором эпизоде: 23,6%
1,007медианный масштаб одометрии; 10–90-й процентили = 0,964–1,059
0,146–0,176°/сдрейф угловой скорости — основное ограничение свободного DR

Журнал показал проблему, которую трудно заметить по экрану: при позднем захвате RoadLock начинал искать дорогу вокруг точки, уже смещённой примерно на 1,4 км. Расхождение тестового коридора и рабочей координаты доходило до 79,9 м. Раздельные контуры не дали этой ошибке попасть в навигацию и одновременно проявили поздний захват, неустойчивый выбор развилки, сброс накопленного подтверждения и слабое место прежнего ограничения автономного счисления.

Эти числа относятся к ранней проверочной серии. По текущему опыту эксплуатации я могу подтвердить: после доработок система стала заметно точнее и при потере GNSS поддерживает навигационную позицию в городском движении не менее 10 минут. Речь идёт только о расчёте и передаче координаты навигатору: автомобилем система не управляет.

Цикл полевого испытания, параллельного расчёта, регистрации и автономного воспроизведения данных
Поездка превращается в воспроизводимый тест.

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

10 · Достоверность и восстановление

Проверка не должна мешать системе восстановиться

Слишком строгий «судья» легко запирает систему в собственном недоверии. Я столкнулся с этим, когда проверка относительно устаревшей опорной точки начала отвергать все честные координаты и не оставила пути назад. Поэтому модуль обнаружения подмены по умолчанию работает как наблюдатель в режиме MONITOR: подозрительный fix остаётся в потоке, а решение проверки записывается в телеметрию. Реальная блокировка включается отдельно.

Проверка опирается на независимые признаки: одометрию, передачу, монотонное время и расхождение с прогнозом DR. Если ненадёжен сам прогноз, уменьшается доверие к нему, а не к GNSS. После разрыва потока система ждёт последовательность согласованных координат в течение заданного времени и лишь затем принимает новую опорную точку.

Калибровка с контрольной выборкой

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

Нет сигналаЭто отдельное состояние, а не ноль и не автоматическое предположение о движении вперёд.
Независимая проверкаКарта не проверяет координату, которую перед этим сформировала сама.
Путь к восстановлениюУстаревшее внутреннее состояние не должно бесконечно отклонять новые данные.
Целостное применениеКоэффициенты меняются только после контрольной выборки и подтверждённой остановки.
11 · Проверка алгоритмов

Поездка должна воспроизводиться без автомобиля

Скриншота с неправильной точкой недостаточно, чтобы понять причину. Поэтому регистратор сохраняет исходные NMEA, автомобильные сигналы, решения алгоритмов, опубликованные Location и переходы состояний в NDJSON примерно с частотой 4 Гц. Размер сегментов и очередей ограничен, важные события записываются устойчиво. Загрузка на закрытый HTTPS-сервер продолжается после обрыва, а повторная отправка не создаёт дубликатов.

Цепочка «вход → решение → выход» позволяет заново проиграть работу GNSS, DR и RoadLock на одной временной шкале. В журнале видна не только конечная координата, но и причина каждого перехода. Именно так поле превращается в воспроизводимый тест.

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

Основные алгоритмы я вынес в обычный Java-слой без зависимостей от Android. На момент аудита проект содержал 99 файлов *Test.java и 877 аннотаций @Test. Они охватывают NMEA, транспорты, свежесть данных, объединение измерений, повторный захват, калибровку, DR/HOLD, карту, RoadLock, запись и загрузку журналов. Это статический подсчёт исходников, а не отчёт о последнем запуске CI.

12 · Итоги

Рабочая система и её границы

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

На штатной мультимедийной системе Car GNSS Bridge передаёт навигатору согласованные координаты GNSS и скорость автомобиля. Когда спутниковое решение исчезает, свободный DR продолжает оценивать перемещение, а рабочий RoadLock удерживает позицию на дорожном графе. В текущей эксплуатации эта версия заметно точнее ранней и поддерживает навигационную позицию в городском движении без GNSS не менее 10 минут. Если данных уже недостаточно, система честно переходит в HOLD.

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

Java · фоновая служба Android · NMEA · последовательный интерфейс USB · Bluetooth SPP/BLE · TCP · NTRIP/RTCM · системное программное обеспечение штатной мультимедийной системы (ECARX) · Android Car · счисление пути · OpenStreetMap · отображение файлов в память (mmap) · NDJSON · модульные тесты JVM