Всем привет, я Максим, последнее время работаю на MAPS.ME, а конкретно в части ядра С++, обработки и подготовки данных. Хотелось бы поделиться своими наработками и похвастаться тем как приложение становится чуточку лучше.
Сокращения использованные мной:
ОСМ — OpenStreetMap.org,
ОТ — общественный транспорт,
Автобус — на самом деле так называю любой тип ОТ, просто слова не нашел более подходящего по простоте.
Исходные данные об общественном транспорте мы берем с ОСМ, равно как и всю остальную базовую картографическую информацию. Рассказывать про представление данных на ОСМ я сильно не буду, для этого у них есть прекрасные статьи на их вики. Но все‑таки в качестве базы хотелось бы упомянуть что на ОСМ есть 3 типа объектов: точка, линия, объединение (в оригинальном именовании это Node, Way, Relation). Применительно к описанию общественного транспорта, каждый маршрут в каждую сторону — это объединение следующих объектов: сегментов дорог, точек остановки и платформ (это тоже термин из ОСМ, если по‑русски, то платформа — это как раз зачастую то, что мы называем остановкой в русском языке — место где люди ждут автобус).
Давайте сначала проследим за потоком преобразования данных который происходит у нас каждый раз при формировании карт. МАПС — приложение оффлайн, соответственно все базовые данные мы упаковываем в карты которые разбивают весь мир на 1200 регионов, они скачиваются в приложении пользователем для дальнейшего оффлайн использования. Объем упакованных бинарных данных с ОСМ на весь мир сейчас приблизительно 80ГБ. Это не какие‑то сырые бинарные данные, они ужаты всеми правдами и неправдами до сингулярности. Не скажу что прям big‑data, но для его разбора пришлось применять некоторые типовые ухищрения чтобы по памяти поместиться.
Первым делом был написан свой велосипед для вычленения необходимых данных, разбиения по регионам, преобразования в читаемый глазами формат (для верификации и дальнейшего разбора на питоне). Берем все линии ОТ, для них берем все сегменты дорог, остановки, далее для всех них собираем точки, сохраняем для каждого региона в отдельный файл.
Далее для каждого региона запускаем обработчик данных. Оказалось что данные зачастую имеют ряд проблем, их надо исправлять. Вот некоторые из них.
Сегменты дорог перечислены не в том порядке. Мы пытаемся восстановить их последовательность. Для нас это не проблема, идем дальше.
Между сегментами могут быть пропуски. Мы игнорируем небольшие разрывы. Если разрыв большой, то считаем маршрут не восстанавливаемым и обрываем его.
Есть много маршрутов на ОСМ где отсутствуют точки остановки ОТ, только платформы. Эти точки по сути выступают только лишь в качестве проекции платформы на траекторию движения, мы не используем точки остановки, тем более что они тоже могут быть перепутаны относительно траектории и платформ. Более того, точки остановки не несут хоть сколько‑нибудь значимой информации, вся информация хранится либо в маршруте либо в платформе.
Платформы могут быть перечислены не по порядку следования по траектории, мы пытаемся восстановить их последовательность. Это оказалось не самой логически простой задачей в общем случае. Ведь надо учитывать что маршруты могут проходить по одному и тому же сегменту в двух направлениях, проекции на полилинию траектории может не быть вовсе. Для сегмента проходимого в двух направлениях остановка в одну сторону должна подходить, а в другую сторону логично что нет. Из‑за задачи восстановления последовательности мы выкидываем остановки если они находятся не с правильной стороны по ходу прохождения траектории (да, учитываем лево‑/право‑ стороннее движение в регионе).
Круговые перекрестки могут быть не разбиты на сегменты, поэтому вход и выход с них зачастую получаются с разрывами.
Это совсем не все проблемы.
Почти тотально отсутствует информация о расписании, времени в пути, режиме работы. К примеру портят складывающуюся картину так называемые «ночные» автобусы, их надо если и предоставлять пользователям то под правильным соусом. Отсутствие расписания заставляет делать очень грубые допущения на данный момент, все автобусы становятся эквивалентны, что на самом деле абсолютно неприемлемо но мы пока что осознанно пошли на такое по простой причине: «лучше показать пользователю хоть какую‑то возможность чем не иметь никакой». В первом случае мы можем дальше развиваться и прийти к идеалу, второй вариант тупиковый.
Портят картину автобусы которые не разбиты на прямой и обратный маршрут.
Не решены проблемы когда в качестве платформы записана не точка а целый площадной объект‑платформа (не ясно что выбирать в качестве точки привязки. Мы же смело отказались от точек остановки:)) или вообще вообще объект‑релэйшн.
Сначала из‑за отсутствия хоть какой‑нибудь информации о движении мы выставляли на всех участках скорость взятую у сферического коня в вакууме. Она даже была настолько хороша что результаты получались аналогичными тем, что давали передовые навигационные приложения. Но была оговорка: это только в пределах города, без существенных пробок, за пределами города мы безбожно врали. Поэтому внедрена модель физического ускорения для расчета длительности, чутка картина выправилась. Отсутствие расписания также ставит перед фактом отсутствия понимания времени ожидания автобуса. Мы также пока что возлагаем выбор на пользователя но стараемся максимально помочь: предлагаются к примеру все эквивалентные способы добраться на ОТ. Эквивалентные в нашей терминологии — это идущие по той же траектории, не путайте с альтернативными.
Обработанные данные о линиях, остановках и траектории сохраняются в промежуточном формате для дальнейшей их записи в файл карты. Здесь никаких ноу‑хау, спасибо всем замечательным разработчикам приложения которые обкатали процесс загрузки информации о метро для дальнейшей маршрутизации и отрисовки. С точки зрения маршрутизации мы на данном этапе ничего не придумали нового, алгоритм на графе остался прежний (а‑стар), схема простая: в существующий граф дорог добавляются ребра от ОТ и связываются они ребрами‑проекциями на остановках.
Пред‑подготовка данных ОТ на данный момент выявила множество проблем с данными на ОСМ, мы подготовили отчет с ошибками, который будем обновлять при сборке новых карт (получается раз в несколько месяцев). Работа по улучшению диагностик еще впереди. Надеемся на взаимодействие с ОСМ коммьюнити с целью взаимовыгодного улучшения качества данных.
На данный момент даже не все возможности использования данных ОТ реализованы в приложении, мы в процессе. Что уже есть по ОТ:
данные по всему миру по метро, автобусам, троллейбусам, трамваям, маршрутным такси
навигация с выбором предпочтительных типов ОТ. это включает в себя отображение эквивалентных линий ОТ, выбор типов ОТ, отображение маршрута на карте, отображение деталей о маршруте, следование по маршруту.
Уже на подходе функционал:
поиск маршрута ОТ по названию и детальное отображение выбранного
просмотр и выбор среди маршрутов проходящих по выбранной дороге или через выбранную остановку
отображение сети ОТ для интересующих видов транспорта
Если статья окажется интересной, то продолжу цикл публикаций о развитии в мапс ми. Команде есть чем поделиться с миром. К примеру, мне нравится объединение функционала подсветки скачанных и нескачанных регионов с возможностью отображения предмаршрута при поиске маршрута через несколько регионов.
Комментарии (21)
mentin
19.08.2024 21:08А результат довольно странный получается. У меня маршрут автобуса выглядит так:
Надо приехать с юга в точку А. Вместо того чтобы просто вылезти в точке А, maps.me предлагает доехать до Б (по пути, на вертикальном участке, по его мнению, остановок нет), потом перейти на противоположную сторону и поехать на том же маршруте обратно (что невозможно, там кусок где автобус едет только в одном направлении) и только там уже выйти в А.
maxbushlya Автор
19.08.2024 21:08Давайте разбираться. Говорите точки, мы исправимся если действительно есть проблема
GT21
19.08.2024 21:08Если находите "битый" маршрут, то сразу хоть помечайте его fixme=*, пусть люди потом починят (когда-нибудь)
freeExec
19.08.2024 21:08С таким же успехом можно на дома без адреса вешать fixme=добавьте адрес, пользы будет примерно одинаково.
GT21
19.08.2024 21:08Ну ты сравнил, пара десятков сломанных маршрутов и тысячи домов без адреса. Причем проблема маршрута не всегда может быть очевидна и ты даже не узнаешь что она есть. А тут разработчики сразу указали бы, что не так
freeExec
19.08.2024 21:08Маршрутов тоже тысячи. И починить их с дивана в подобающем большинстве нельзя.
Если браться за починки, то валидаторы гадяться куда лучше, чем богом забытый fixme.GT21
19.08.2024 21:08Я говорил про один город. Если брать все города, где сломанных маршрутов будет тысячи, то количество домов без адресации пойдет на сотни тысяч, если не на миллионы
GT21
19.08.2024 21:08+1"автобусы которые не разбиты на прямой и обратный маршрут."
А они и не всегда должны быть разбиты, они могут двигаться без остановки
maxbushlya Автор
19.08.2024 21:08Может я не очень точно сформулировал. Да, сам по себе маршрут туда-обратно для нас не является проблемой. Правильно перечислите сегменты, остановки - и мы его разберем. Тут я писал про историю что есть маршруты где люди накидывают сегментов "в одну сторону" и остановки на оба направления. Мы даже обрабатываем корректно одно направление если оно может быть восстановлено. Но обратного автобуса не получится восстановить:)
maxbushlya Автор
19.08.2024 21:08а еще до кучи накидают сегментов в обратную сторону только которые отличаются по траектории от уже перечисленных, вдобавок перепутают порядок - траектории закольцуются или будут уходить не туда... есть такие вот шутники
GT21
19.08.2024 21:08Вообще осм нуждается в глобальной переработке, он застыл на уровне 2010 года. И надо бы уже глобально переходить на "PTv3"
Ещё:
1) насколько механизм ОТ открыт, можно ли его использовать в органик мапс?
2) официально в России маршруток нет, есть автобусы малого класса. Предлагаю добавить поддержку тега bus_class:length=*, где "малый" и "очень малый" приравнивать к маогруткам
maxbushlya Автор
19.08.2024 21:08Не вижу проблем сделать это в Органик, это же открытые данные с ОСМ.
GT21
19.08.2024 21:08Речь не про данные, а про скрипт/модуль навигации/алгоритм/библиотеку или что там у вас используется
maxbushlya Автор
19.08.2024 21:08Нет, это не открытый код. Реализовать не сложно особенно с учетом того что я написал. Не рокет-сайнс:)
maxbushlya Автор
19.08.2024 21:08По узости своего кругозора считаю что не надо никаких PTv3, это только еще больше сбивать с толку будет, все эти поколения, сбои парсеров из-за несовместимости. Меня лично пока устраивают данные, мы их научились правильно обрабатывать в большинстве случаев. Пока что нас вполне устроит исправление проблем качества данных. И да, как я уже писал, качество функционала в приложении в конечном счете сильнее зависит от наличия расписания нежели от схемы данных
y2k
Весьма смело, учитывая что маршруты могут только их и включать. Ну и вы лишились возможности найти ближайшую точку на полигоне (или линии) платформы. Хотя, это уже излишества. Можно просто взять центроид.
В вашем отчёте с ошибками сплошные ошибки :) Из 5 проверенных маршрутов с dropped platforms ни в одном нет ошибок. "Trajectory ... is not continuous after ", возникает на маршрутах, которые дважды проходят по одной линии. Видимо, вы не предусмотрели такой сценарий при их сортировке.
maxbushlya Автор
Да, ошибок действительно много. Есть несколько "источников": наши ошибки в логике обработки, ошибки ОСМ. Надо конкретно обсуждать какой из автобусов и почему вы считаете что мы обработали неверно.
Насчет того, что мы неправильно обрабатываем сегмент где туда-обратно проходит автобус: глазами на ОСМ этого не видно, все кажется слитным, но чтобы сегмент в двух направлениях был пройден надо чтобы он соответственно два раза был перечислен в релэйшене. Это логично что сегменты должны быть все перечислены по пути прохождения, иначе получается разрыв. На ОСМ сегменты рисуются линией и не видно сколько раз они перечислены. Так что не считаю это багом с нашей стороны. Не думайте что мы эти кейсы не рассматривали, тем более что я явно про них писал в статье:)
y2k
relation 969924 dropped platforms: {'1097813609'} - разрывов в маршруте нет, <10 метров, справа по ходу
Trajectory of relation 14359750 is not continuous after way 1099616904 node 10066531054 - но ок, может действительно стоит разрезать кольцо
maxbushlya Автор
Спасибо, буду разбираться. Если честно, то я сам уже нашел косяков после публикации отчета об ошибках)) буду исправлять