Pull to refresh

Как мы с друзьями собрали сервис для построения маршрутов для походов и велопутешествий ActiveTrip.me

OpenStreetMap *Geoinformation services *Start-up development
Sandbox

Всем привет! Меня зовут Александр, я разрабатываю ActiveTrip.me — cервис для построения маршрутов для пеших, велосипедных, водных походов и путешествий, а также для хранения и группировки интересных мест в виде меток.

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

Что уже можно делать в сервисе:

  1. Строить автоматически маршрут по тропам и дорогам в зависимости от предполагаемого типа передвижения

  2. Строить автоматически маршрут по рекам

  3. Строить маршрут без привязки к дорогам (по прямой между двумя точками)

  4. Строить несколько маршрутов на одной карте

  5. Отмечать важные места на маршруте метками

  6. Изучать местность благодаря разным картам и слоям

  7. Шарить маршруты и скачивать в форматах GPX и KML

Скоро будет добавлена возможность совместного редактирования маршрутов (как в Figma).

Реализация такого картографического сервиса подразумевает решение нескольких базовых задач:

  • Работа с картами и слоями. Получение, хранение и раздача пользователям интересующих их карт и дополнительных слоев

  • Работа с геоданными. Предоставление пользователю инструмента для построения маршрута по точкам с указанием набора дополнительных ограничений, к которым можно отнести:

    • Выбранный способ передвижения: пешком, на велосипеде, на автомобиле, по рекам

    • Тип покрытия поверхности: асфальт, грунт

  • Расчет и предоставление данных о построенном маршруте. В частности о:

    • Протяженности маршрута

    • Типах покрытия поверхности, по которым проходит маршрут: асфальт или грунт. Важно для велосипедистов и внедорожных путешествий

    • Информации о высотах: график профиля высоты маршрута, суммарные набор и сброс высоты, максимальная и минимальная высота на маршруте и т.д. Важно для любого похода в горной местности

  • Прямое и обратное геокодирование. Поиск и перемещение пользователя к нужному участку карты по заданному названию места или адресу, а также автонаименование маршрута по заданным начальной и конечной точкам

  • Реализация пользовательского интерфейса для работы с геоданными: отрисовка подложек и слоев, работа с точками маршрута и метками (POI)

  • Хранение и предоставление пользовательской информации о маршруте: добавление изображений, комментариев

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

  • Возможность поделиться созданным треком через прямую ссылку

  • Импорт GPX и KML-файлов в сервис для последующего редактирования. GPX и KML являются форматами представления трехмерных пространственных геокоординат и основаны на XML-разметке. Большинство навигаторов и навигационных приложений (Garmin, Locus, OsmAnd) используют именно GPX-формат, однако некоторые (Maps.me, Organic Maps) поддерживают только KML-формат

  • Экспорт GPX и KML-файлов. После подготовки маршрута на нашем сервисе его можно загрузить в навигатор или в мобильное приложение и отправиться в путешествие

Существует множество способов реализации каждой из перечисленных выше фич в своем собственном картографическом сервисе. Как правило, можно:

  • Прибегнуть к использованию доступных SDK, open source модулей и библиотек, подняв свой собственный сервер

  • Воспользоваться специализированными сервисами, предоставляющими возможность интеграции через API

Построение маршрута

При попытке решения задачи построения маршрутов, мы обратились к известным open source решениям. Стояла задача справиться с минимальными затратами на вычислительные и финансовые ресурсы (на старте у нас был в наличии скромный VPS сервер с 1 ТБ HDD и 4 GB RAM).

Мы попробовали Valhalla, GraphHopper и BRouter

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

Valhalla

Сборка и запуск Valhalla с использованием собственных ресурсов подробно описаны в документации и состоят из двух шагов:

  1. Необходимо развернуть подготовленный контейнер или собрать его самостоятельно из исходников через CMake. Исходники включают в себя http-сервис, а также набор утилит для препроцессинга геоданных

  2. Далее скачать OSM-данные нужных регионов и скормить утилите препроцессинга

При развертывании процессинг отдельных небольших регионов осуществляется на упомянутом железе за десятки минут (для Швейцарии потребовалось 20 минут). Процессинг стран Европы и Азии отрабатывал несколько суток и, в итоге, завершился с ошибкой.

GraphHopper

Алгоритм запуска инстанса GraphHopper во многом аналогичен.

Процессинг занимает в разы меньшее количество времени (~12 часов на весь мир), но требует значительного количества RAM. В нашем случае это около ~128 ГБ на препроцессинг и ~64 ГБ для дальнейшей работы сервиса (хранит данные в памяти в сжатом виде).

Завышенные нами числа относительно упомянутых в документации появляются из-за необходимости работы не только с автомобильными маршрутами, но и пешими с велосипедными. 

Альтернатива — использование уже развернутой версии GraphHopper Direction API. Бесплатная версия ограничена 500 запросами в день, что даже для реализации прототипа оказалось недостаточно.

Mapbox

Mapbox - широко известный поставщик пользовательских онлайн-карт, сервисов навигации и геопоиска для веб-сайтов и приложений.

Также Mapbox хостит и предоставляет возможность использования Valhalla в рамках Navigation API. В бесплатном варианте использования доступно до 100000 запросов в месяц.

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

BRouter

BRouter - открытый движок для построения маршрутов. Представлен в виде исходного кода движка, сервера для развертывания на собственном железе и мобильного приложения.

Отличается гораздо более низкими требованиями с точки зрения ресурсов. Данные после препроцессинга занимают кратно меньше места, чем в случае с GraphHopper и Valhalla.

Возможно обновление данных на регулярной основе (на текущий момент BRouter поставляет свежие данные раз в неделю).

Из недостатков — строит маршрут медленнее, чем решения, построенные на базе Valhalla.

Из ключевых преимуществ — возможность построения маршрутов по воде.

Что мы в итоге используем для построения маршрута?

Для реализации прототипа мы решили ограничиться использованием Valhalla API, предоставляемое Mapbox, для построения маршрутов по земле, для воды использовали развернутый на собственном железе сервер Brouter.

Для оптимизации количества запросов к Mapbox (с учетом ограничения бесплатного использования) мы внедрили следующее:

  1. Построенный пользователем маршрут мы сжимаем с использованием Polyline Encoding алгоритма и кешируем на своей стороне. При повторном обращении к созданному треку мы избегаем лишних вызовов к API и отрисовываем трек на основе сохраненных данных

  2. При внесении модификаций в построенный маршрут мы перестраиваем лишь необходимый участок. Помимо оптимизации количества вызовов мы улучшаем пользовательский опыт, поскольку операция обновления маршрута в общем случае не идемпотентна: у нас нет гарантии, что для одинакового набора точек мы всегда будем получать маршруты идентичного вида

Расчет высоты

Поход к расчету высоты мы посмотрели у создателя проекта Nakarte.me:

  1. Берем открытые данные о высотах из http://viewfinderpanoramas.org

  2. Осуществляем препроцессинг данных о высотах с использованием утилиты и складываем их в БД

  3. Поднимаем сервер, работающий с подготовленными данными. Сервер по переданной на вход нитке маршрута осуществляет интерполяцию высот на основе подготовленных данных и отдает результат

  4. Данные скачиваются с данного сайта, препроцессятся с помощью утилиты и складываются в SQLite на собственном сервере

  5. После этого с помощью программ из того же репозитория создается микросервис, который интерполирует высоты, используя полученные после препроцессинга данные

Геокодирование

Геокодирование используется для повышения удобства использования сервиса.

Прямое геокодирование — получение по заданному адресу координат географической точки. Обратное геокодирование, соответственно, решает обратную задачу: получение адреса или названия, расположенного в точке объекта, по указанным координатам.

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

  1. Для прямого геокодирования мы используем API от MapyCZ компании Seznam (в статье выше его не упоминают)

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

Для сервиса возможности обратного геокодирования полезны в двух сценариях:

  1. Автогенерация названия маршрута по стартовой точке

  2. Индексация построенных пользователями маршрутов для дальнейшего формирования каталога. Может быть полезно для реализации функциональности вида «найти все построенные треки пользователей, проходящие через село X». При этом относительно дешево решается проблема локализации — API принимает на вход набор необходимых языков

Импорт и экспорт треков

Загрузку и скачивание пользовательских треков мы поддерживаем в виде GPX и KML-файлов. Эти файлы можно использовать в мобильных приложениях и портативных навигаторах. Кроме этого, можно расшарить свой трек через публичную ссылку

Отрисовка маршрутов на карте

На данный момент отрисовка полностью основана на использовании библиотеки Leaflet. Из коробки поддерживается отображение слоёв карт в формате Tiled web map, отображение геометрических объектов, линий и маркеров.

Из возникших и еще не решенных проблем — Leaflet не справляется с одновременной отрисовкой большого числа маркеров (> 100 шт.). Пока обходим это через динамическое отображение в зависимости от масштаба, но такой подход уместен не во всех случаях.

Заключение

Сейчас мы с командой активно развиваем ActiveTrip.me и регулярно выпускаем обновления. Буду благодарен, если найдете время для тестирования и дадите обратную связь.

Также у проекта есть активное русскоязычное сообщество в Telegram. А новости о проекте мы публикуем в Telegram и VK.

Tags:
Hubs:
Total votes 33: ↑33 and ↓0 +33
Views 11K
Comments 55
Comments Comments 55