@bykoianko @darina @maksimandrianov PTAL
Описание утилиты для генерации json с необходимыми данными из GTFS-фидов
Исполняемый файл gtfs_converter. Параметры:
- path_mapping - путь к мапингу сущностей GTFS на константные, не меняющиеся при перезапуске id из интервала
FakeFeatureIds::IsTransitFeature()
. Файл нужен, чтобы при перегенерации json'ов id не менялись, и у пользователя с разными версиями карт ничего бы не сломалось.
- path_gtfs_feeds - путь к директории с поддиректориями, содержащими фиды.
- path_directory_json - путь к директории для сохранения json'ов.
- path_resources_dir - путь к omim/data. Нужен для работы color picker'а, притягивающего цвет route к ближайшему цвету из data/transit_colors.txt.
- start_feed - опциональный параметр. С какого фида продолжить работу. Указывается название директории с фидом. Все фиды до данного пропускаются.
- stop_feed - опциональный параметр. на каком фиде остановить работу. Все фиды после данного не обрабатываются.
Пример запуска для обработки всех фидов в path_gtfs_feeds:
./gtfs_converter --path_gtfs_feeds=feeds --path_json=jsons_for_generator --path_mapping=mapping.txt --path_resources=omim/data
Пример запуска для обработки только двух фидов - директорий с названиями "10" и "11":
./gtfs_converter --path_gtfs_feeds=feeds --path_json=jsons_for_generator --path_mapping=mapping.txt --path_resources=omim/data --start_feed="10" --stop_feed="11"
В случае запуска с какого-то фида (указан start_feed), происходит дозапись в файлы из path_json. Если же этот параметр не указан, вместо дозаписи файлы полностью перезаписываются.
Новый формат данных для работы с общественным транспортом
Этот реквест реализует пайплайн преобразования директорий с GTFS-фидами (каждый из которых состоит из csv-файлов) в набор line-by-line json'ов.
Путь к директории с результирующими json должен быть прописан для генератора в map_generator.ini вместо SUBWAY_URL. Генератор на основе json подготовит соответствующие mwm-секции для работы с общественным транспортом в приложении.
Планируется переписать для работы с новым форматом общественного транспорта часть генератора, движка отрисовки и транзит роутинга.
Отличия новых json-файлов от старого формата json, в котором поставлялось метро:
- Несколько файлов вместо единого.
- Line-by-line json вместо обычного.
- Замена osm id и внутреннего id на единый TransitId, который сохраняется между перегенерациями карт разных версий. TransitId либо находится в интервале
FakeFeatureIds::IsTransitFeature()
, и тогда он обозначает сущность из GTFS или метро, либо лежит в интервале обычных OSM id, и тогда обозначает те сущности метро, которые ссылаются на объекты OSM (выходы из метро и тд).
Разбивка по сущностям, отличная от старой. Поля тоже отличаются. Ниже приведена схема, описания файлов и их полей и примеры строк.
**networks.json** - операторы
- id
- название оператора. Здесь и далее поля названия представляют собой мапу айди языка - текст. Если в GTFS feed_info.txt отсутствует информаци о языке, то по умолчанию ставится английский.
{"id":4048948901,"title":[{"lang":"en","text":"LA Go Bus"}]}
routes.json - маршруты. Один маршрут может состоять из нескольких lines
- id
- id оператора, к которому привязан маршрут
- цвет линии
- тип общественного транспорта
- название маршрута
{"id":4048915470,"network_id":4048915465,"color":"blue","type":"rail","title":[{"lang":"en","text":"Special Event Extra Service"}]}
lines.json - линии маршрута. У двух линий одного и того же маршрута могут не совпадать: полилиния; список остановок; даты работы и дни-исключения в графике работы; расписание работы. То есть линией может быть не только "маршрут от одной конечной до другой" и "в обратную сторону", но и один и тот же отрезок пути, но с совершенно разными расписаниями. Или один и тот же отрезок пути, но с разным списком остановок и разными интервалами.
- id
- route id - маршут, к которому относится линия
- ~~shape id - полилиния для данного line~~ DELETED
- ShapeLink - "ссылка" на кусок shape, относящейся к этой линии. Состоит из: shape id, start idex, end index. ADDED
- stop ids - список остановок. Остановки перечислены в порядке следования транспорта по данной линии.
- название линии
- интервалы циркуляции транспорта по этой линии. Могут быть не заполнены. Интервал - это пара значений: промежуток в секундах и отрезок дня, для которого он действителен. Отрезок дня - в формате osm opening hours. Таким образом интервал зависит от времени: интервал движения автобуса с 10:00 до 12:00 каждые 15 минут, c 12:01 до 18:00 каждые 10, а c 18:01 до 22:00 каждые 20 минут. UPDATE
- osmoh::OpeningHours дни работы - в формате osm opening hours хранится информация, по каким дням недели начиная с какого числа и заканчивая каким числом эта линия активна или не активна, учитываются и исключения в расписании.
{"id":4047400409,"route_id":4048911702,"shape":{"id":4048914922,"start_index":0,"end_index":205},"title":[{"lang":"en","text":""}],"stops_ids":[4048915038,4047400615,4047400616,4048915039,4047400617,4047400618,4048915040,4047400620,4048915041,4047400621,4047400622,4048915042,4047400624,4047400625,4047400626,4047400627,4047400628,4047400629,4048915043,4047400631,4047400632,4048915044,4047400634,4047400635,4047400636,4047400637,4047400638,4047400639,4047400640,4047400641,4047400642,4048915045,4047400644,4047400645,4048915046,4048915047,4047400647,4048915048,4047400648,4047400649,4048915049,4047400651,4047400652,4026542873,4048915050,4047400654,4047400655,4048915051,4047400657,4036441623,4048915052,4047400658,4047400659,4048915053,4047400661,4047400662,4047400663],"service_days":"2020 Apr 18-2020 May 29 Sa-Sa; 2020 Apr 18-2020 May 29 Su-Su closed","intervals":[]}
shapes.json - полилинии
- id
- вектор m2::PointD точек - полилиния
{"id":4048914807,"points":[{"x":-122.42373600000001,"y":40.775536922248669},{"x":-122.422065,"y":40.774955435607225},{"x":-122.421807,"y":40.774866948826073},{"x":-122.42111981639971,"y":40.774521158122255},{"x":-122.421081,"y":40.774501625714656},{"x":-122.41952658685517,"y":40.77395581671977},{"x":-122.394953,"y":40.873905644937466},{"x":-122.394987,"y":40.87402079957468}]}
stops.json - остановки
- id
- ~~lines ids - список линий маршрутов, относящихся к этой остановке~~ DELETED
- m2::PointD - координата остановки.
- название остановки - нужно, потому что больше его взять попросту неоткуда. В метро этого поля не было, потому что название подтягивалось из ОСМ.
- расписание. NEW пары line id - osmoh:: OpeningHours. Для каждой линии, проходящей через остановку, список времен прибытие-отбытие.
{"id":4047401815,"point":{"x":-122.469273,"y":40.765036587936251},"title":[{"lang":"en","text":"Daly City Bart Station"}],"timetable":[{"line_id":4047391414,"arrivals":"05:20-05:20 open"},{"line_id":4047391416,"arrivals":"04:05-04:05 open"}]}
edges.json - ребра дорожного графа по линиям
- id from_stop
- id to_stop
- line id
- вес - сколько секунд потребуется, чтобы по линии line id добраться от from_stop до to_stop.
- ShapeLink - "ссылка" на кусок полилинии, описывающий это ребро.
Состоит из: shape id, start idex, end index. По shape id определяется shape, и внутри ее вектора точек находится отрезок от start idex до end index включительно.
{"line_id":4047391343,"stop_id_from":4048915463,"stop_id_to":4048915464,"weight":59,"shape":{"id":4047391340,"start_index":541,"end_index":545}}
edges_transfer.json - ребра дорожного графа по пересадкам
- id from_stop
- id to_stop
- вес - сколько секунд потребуется, чтобы сделать переход с from_stop к to_stop.
{"stop_id_from":4046917465,"stop_id_to":4046917441,"weight":180}
transfers.json - пересадочные узлы
- id
- m2::PointD - координата пересадки.
- stops ids - список остановок, относящихся к этому пересадочному узлу.
{"id":4046920600,"point":{"x":-117.15321790199999,"y":34.641982917905516},"stops_ids":[4046919060,4048936712]}
gates.json - входы/выходы
- id
- is exit
- is entrance
- пары id остановки - вес UPDATED- сколько секунд потребуется, чтобы пройти расстояние от gate до остановки. Список остановок и их весов.
{"id":4048918257,"weights":[{"stop_id":4048918228,"time_to_stop":198},{"stop_id":4048918218,"time_to_stop":198},{"stop_id":4048918215,"time_to_stop":198},{"stop_id":4048918210,"time_to_stop":198}],"exit":true,"entrance":true,"point":{"x":-74.061300000000003,"y":44.671850577887199}}
Особенности реализации
-
В 99% фидов отсутствуют подсказки о матчинге последовательности остановок на полилинию маршрута. Поэтому в методе WorldFeed::ModifyShapes()
реализован алгоритм, который по полилинии маршрута, последовательности остановок и их координатам проецирует остановки на ближайший участок маршрута. При необходимости добавляет точку-проекцию в полилинию маршрута и обновляет соответствующие ссылки на данную полилинию (edges, lines).
-
В фидах присутствуют полилинии, которые целиком включены в другие, более длинные полилинии. Чтобы не дублировать данные, метод WorldFeed::ModifyLinesAndShapes()
удаляет такие shape, и обновляет ссылки из элементов line на shape.
-
В нашей 3party реализации opening hours отсутствует возможность задавать тип Event вместо интервала (то есть единственное время или единственную дату вместо пары начало-конец). Поэтому в расписании прибытия транспорта на остановку всегда присутствует начало-конец, даже если они совпадают.
-
Почти во всех фидах отсутствует прямое указание языка фида (оно должно быть в feed_info.txt). В методе WorldFeed::SetFeedLanguage()
за язык по умолчанию считается "default", который есть в languages.txt и означающий язык, используемый в данной местности. Если в фиде указан язык, он ищется в нашем списке поддерживаемых языков. Если его там нет, язык фида сбрасывается в "default".