New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[transit] GTFS converter. #12946
[transit] GTFS converter. #12946
Conversation
@maksimandrianov интересует твой апрув дескрипшена реквеста - нет ли какой лажи в формате json'ов для генератора. Исходники реквеста пока не надо) |
{ | ||
TransitId m_routeId = 0; | ||
std::vector<TransitId> m_stopsIds; | ||
TransitId m_shapeId = 0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
То есть в случае метро, скажем, для сокольнической линии, у нас будет продублирована одна и та же полилиния для направления туда и обратно, только точки в ней будут храниться в обратном порядке? Так же для московского метро были отдельные линии не только для направления туда-обратно, но и укороченные версии, когда поезд не доезжает до конечной станции, а уходит раньше в депо. Для таких случаев полилинии тоже будут отдельные?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Да, получается, что для метро это будут пары - вектор точек и инвертированный вектор. Относительно общего количества полилиний - автобусов, поездов и тд, это очень небольшой процент, поэтому мне показалось избыточным оптимизировать этот кейс.
А можно поподробнее про укороченные версии с депо? Кажется, мы это сейчас не используем. Какие могут быть кейсы отображения пользователю линии метро:
на общей карте (и там показываются самые длинные полилинии),
как участки построенного им пути (и там депо тоже не нужно).
Или есть что-то еще?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
А можно поподробнее про укороченные версии с депо?
Действительно в Москве в метро часто делают укороченные ветки, в час пик. Чтоб больше поездов проходило через центр. Я жил на фиолетовой ветки и на зеленой, на северозападе. Тут такие станции Октябрьское поле и Сокол. Т.е. имеет
line 1: Планерная - Котельники
line 2: Котельники - Планерная
line 3: Октябрьское поле - Котельники
line 4 Котельники - Октябрьское поле
и еще 2 с какой-то станции на стороне Котельников. Выхино или Кузьминки, не помню.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Понятно. Тогда предлагаю в lines добавить "ссылку" на shape, такую же, как в edges.json:
EdgeShapeLink - "ссылка" на кусок полилинии. Состоит из: shape id, start index, end index. По shape id определяется shape, и внутри ее вектора точек находится отрезок от start idex до end index включительно.
Это оптимизирует хранение линий, являющихся "под-линиями" других линий.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@darina @bykoianko Такой вариант подойдет?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Реализовано через ссылку на shape, содержащую id полилинии и индексы начала и конца на полилинии.
{ | ||
std::set<TransitId> m_linesIds; | ||
m2::PointD m_point; | ||
std::string m_title; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Будет ли это это полной заменой имени, которое мы сейчас достаем из фичи? Если да, то потребуются имена для разных локалей.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Имя нужно для GTFS сущностей, дополнительные данные для которых нельзя достать из ОСМ. Как вариант, для остановок метро можно оставить поле osm id, которое для GTFS будет в не валидном состоянии (max val или 0). Что думаешь?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Как вариант, для остановок метро можно оставить поле osm id, которое для GTFS будет в не валидном состоянии (max val или 0). Что думаешь?
Кажется, что если у нас есть строчное поле, то в него можно запихнуть название остановки и не держать ни какого osm id. Но возникает вопрос с переводами. Думаю, что почти всегда у нас не будет более чем 2-3 языков с названием остановки. Т.е. остановки метро в Москве - это 2 языка. В остановки автобуса МО - один. Если в стране 2 гос языка, то они + английский максимум. Кажется где-то на этапе генерации можно было бы их сформировать и дальше использовать.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
То есть заменить std::string m_title
на мапу "айди языка" - текст названия?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Из осмовых фич мы сейчас достаем локализованное имя остановки и иконку для gate. Если переводы имени можно упаковать в json, то как быть с иконками? В mwm для gate будет доступен FeatureType с теми же типами, только c FeatureId в интервале FakeFeatureIds? И тогда согласно стилю для такого FeatureType можно будет достать его иконку?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Для сущностей метро, которые приехали из ОСМ, предлагаю в поле id не генерить айди, а использовать айди осма. В рантайме проверять, что !FakeFeatureIds::IsTransitFeature(), и тогда для нее делать все то, что ты описала.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Мне ок такой вариант.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
То есть заменить
std::string m_title
на мапу "айди языка" - текст названия?
Отличный вариант. Только надо так сделать, чтоб id языка было такое же, как у нас в программе везде.
Для сущностей метро, которые приехали из ОСМ, предлагаю в поле id не генерить айди, а использовать айди осма. В рантайме проверять, что !FakeFeatureIds::IsTransitFeature(), и тогда для нее делать все то, что ты описала.
По мне хороший вариант.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Готово.
В lines.json хранятся stop ids для каждой линии и в stops.json хранятся line ids линий для данной остановки. Верно? А нам нужно это дублирование на уровне json? Я не сколько о размере думаю, сколько о том, что потребуется согласованность серьезная между ними. Т.е. нужно после парсинга проверять, что если для остановки номер 123 есть линии, 5, 7 и 9, то в этих линия есть остановка 123. Как вариант, могу предложить получать линии, которые проходят через данную остановку из lines.json |
Вес дуги графа? Верно? А как ты планируешь (и планируешь ли) этот вес увязывать с расписанием? |
веса? |
Т.е. мы не планируем поддержать расписание, типа: 3 автобуса в 9:00, в 10:00 и в 20:00 по будням и один в 9:30 по выходным? |
Когда линий много, как в больших метро люди начинают путаться? Может нам как-то заложить на не только цвет, но и разные начертания линии? Ну пунктиром там, не знаю. Глянь, где как обозначаются. |
Я оставила эту логику, потому что она действует сейчас для метро. Я бы тоже убрала дублирование на уровне json, и пополняла список линий для каждой остановки на этапе генератора. @maksimandrianov Что скажешь? |
Да, это вес дуги графа. Для увязки с расписанием в транзитном роутинге нужна работа с полем "osmoh::RuleSequence расписание", привязанном к line. Что-то типа access:conditional, только про расписание) С какого часа по какой работает, в какие дни месяца/недели, есть ли перерывы. И от этого отталкиваться. |
Вес, 1 штука. Сейчас для метро так сделано. |
Кажется что линии могут называться на разных языках. |
А это правильно. Кажется, что часто бывают ситуации когда вход один, а остановок несколько. И требуется разное время, чтоб добраться до каждой их них. |
Ну, это поле нужно, чтобы получить информацию про то, когда и как этот маршрут работает. А чтобы знать расписание конкретных остановок, к остановке можно привязать мапу line id - osmoh::RuleSequence. И в ней для твоего примера получится что-то типа Что думаешь? |
Если уж мы взялись переделывать json и transit, то кажется в нем стоит учесть недоделки которые у нас были раньше. По возможности, конечно. Но по любому, мы не часто будем его переделывать. |
Возможно, будет полезен паттерн пунктира, цвет линии и цвет ее обводки. |
Сейчас у нас в transit_colors.txt лежит около 36 цветов. Даша объяснила, что эти цвета составляли дизайнеры с учетом стиля нашей карты. Кажется, пока хватает. А маршруты наземного транспорта мы не будем показывать по несколько за раз. Обозначение не только цветом, но и толщиной или типом линии я встречала на картах, где нужно отобразить ВСЕ маршруты общественного транспорта. Это не наш случай. |
У нас уже не хватает просто цвета, например, в Москве после добавления линий аэроэкспрессов и мцд стало сложно понять, где метро, а где нет. В планах стоит задача рисовать такие линии по-разному. |
я за, давай уберем |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
пингани, пожалуйста, в сл или в этом реквесте, когда интеграционные тесты будут
Договорились. |
JTALL |
1 similar comment
JTALL |
JTLINUX |
6 similar comments
JTLINUX |
JTLINUX |
JTLINUX |
JTLINUX |
JTLINUX |
JTLINUX |
JTLINUXGCC |
У линии есть список остановок. Есть ли какие-то гарантии на порядок этих остановок в списке? Они идут в порядке следования? |
world_feed | ||
gflags | ||
) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Лишняя?
Да, есть гарантия, что этот порядок - и есть порядок остановок на линии. |
Может напишем про это где-нибудь в коде? Или написано уже? |
А результирующий json куда пойдет дальше? Где будет обработан? |
Надо бы по результатам работа с общ транспортом написать статью в confluence. |
Добавила комментарий над этим полем (m_stopIds) в LineData. |
В generator_tool. Это есть в комментариях. |
Да, когда замержим реквест, перенесу его дескрипшен в новую статью в confluence. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
896f070
to
4e881aa
Compare
JTALL |
@bykoianko @darina @maksimandrianov PTAL
Описание утилиты для генерации json с необходимыми данными из GTFS-фидов
Исполняемый файл gtfs_converter. Параметры:
FakeFeatureIds::IsTransitFeature()
. Файл нужен, чтобы при перегенерации json'ов id не менялись, и у пользователя с разными версиями карт ничего бы не сломалось.Пример запуска для обработки всех фидов в 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, в котором поставлялось метро:
FakeFeatureIds::IsTransitFeature()
, и тогда он обозначает сущность из GTFS или метро, либо лежит в интервале обычных OSM id, и тогда обозначает те сущности метро, которые ссылаются на объекты OSM (выходы из метро и тд).Разбивка по сущностям, отличная от старой. Поля тоже отличаются. Ниже приведена схема, описания файлов и их полей и примеры строк.
**networks.json** - операторы - id - название оператора. Здесь и далее поля названия представляют собой мапу айди языка - текст. Если в GTFS feed_info.txt отсутствует информаци о языке, то по умолчанию ставится английский.
routes.json - маршруты. Один маршрут может состоять из нескольких lines
lines.json - линии маршрута. У двух линий одного и того же маршрута могут не совпадать: полилиния; список остановок; даты работы и дни-исключения в графике работы; расписание работы. То есть линией может быть не только "маршрут от одной конечной до другой" и "в обратную сторону", но и один и тот же отрезок пути, но с совершенно разными расписаниями. Или один и тот же отрезок пути, но с разным списком остановок и разными интервалами.
shape id - полилиния для данного lineDELETEDshapes.json - полилинии
stops.json - остановки
lines ids - список линий маршрутов, относящихся к этой остановкеDELETEDedges.json - ребра дорожного графа по линиям
Состоит из: shape id, start idex, end index. По shape id определяется shape, и внутри ее вектора точек находится отрезок от start idex до end index включительно.
edges_transfer.json - ребра дорожного графа по пересадкам
transfers.json - пересадочные узлы
gates.json - входы/выходы
Особенности реализации
В 99% фидов отсутствуют подсказки о матчинге последовательности остановок на полилинию маршрута. Поэтому в методе
WorldFeed::ModifyShapes()
реализован алгоритм, который по полилинии маршрута, последовательности остановок и их координатам проецирует остановки на ближайший участок маршрута. При необходимости добавляет точку-проекцию в полилинию маршрута и обновляет соответствующие ссылки на данную полилинию (edges, lines).В фидах присутствуют полилинии, которые целиком включены в другие, более длинные полилинии. Чтобы не дублировать данные, метод
WorldFeed::ModifyLinesAndShapes()
удаляет такие shape, и обновляет ссылки из элементов line на shape.В нашей 3party реализации opening hours отсутствует возможность задавать тип Event вместо интервала (то есть единственное время или единственную дату вместо пары начало-конец). Поэтому в расписании прибытия транспорта на остановку всегда присутствует начало-конец, даже если они совпадают.
Почти во всех фидах отсутствует прямое указание языка фида (оно должно быть в feed_info.txt). В методе
WorldFeed::SetFeedLanguage()
за язык по умолчанию считается "default", который есть в languages.txt и означающий язык, используемый в данной местности. Если в фиде указан язык, он ищется в нашем списке поддерживаемых языков. Если его там нет, язык фида сбрасывается в "default".