Press "Enter" to skip to content

Как определить длину пути между адресами

Проблема и цель проекта

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

Подбор инструментов

Преимущества свободных данных и софта

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

  • Проект подразумевает обработку данных для внутренних целей, а лицензионные договоры Google и Яндекса требуют использования их сервисов только для создания общедоступных публикаций в виде карт. Т.е. использование услуг этих компаний в нужных нам целях будет незаконным. Конечно, вероятность того, что Яндекс обратит внимание на незначительную нагрузку, которую мы генерируем, очень мала. Но с точки зрения развития бизнеса или его продажи в будущем, лучше сразу отказаться от включения в работу предприятия заведомо нелегальных алгоритмов.
  • В процессе работы будут постепенно «всплывать» ошибки в используемой базе данных: например, какие-то адреса будут неправильно преобразовываться в координаты. Если мы работаем на основе картографического сервиса Яндекса, то в случае обнаружения ошибок (в нашем опыте такие ошибки у Яндекса были), каждый ошибочный адрес придётся обрабатывать как исключение, поскольку сам Яндекс по нашему запросу исправит эти ошибки только через несколько месяцев. При использовании данных из базы OpenStreetMap, мы можем сами внести исправление в базу, и оно практически сразу станет доступно для нашего приложения.
  • При необходимости внести какие-либо изменения в работу алгоритмов по геокодированию или прикладке маршрутов, мы можем отказаться от использования открытого API, а запустить эти сервисы на своём оборудовании, поскольку и база данных дорожной сети, и программное обеспечение доступны на условиях свободных лицензий.

Схема работы

Алгоритм вычисления расстояния между двумя адресами состоит из двух этапов:

  1. Геокодирование, т.е. преобразование текстовой строки, содержащей адрес, в географические координаты.
  2. Прокладка маршрута и вычисление его длины.
Open Source Routing Machine
Open Source Routing Machine

Геокодирование российских адресов

Международный сайт OpenStreetMap.org для геокодирования использует программу Nominatim. У нас есть опыт работы с API Nominatim через статистический пакет R. Исходные коды R-скриптов доступны в репозитории на github.

Для национального проекта OpenStreetMap.ru разработано собственное приложение для поиска адресов и точек интереса. Приложение «заточено» под специфику адресов в России, »понимает« нумерацию домов в духе »14 К2 С1« и может искать дома с двойным адресом. У поисковика доступно API, документация опубликована в форуме. Например, для определения координат дома по адресу «Псков, Маркса, 23» следует отправить запрос вида http://openstreetmap.ru/api/search?q=Псков, Маркса, 23. Ответ вернётся в формате JSON, координаты хранятся в полях lat и lon.

Для снижения количества ошибок геокодирования и уменьшения объёма лишней информации в ответе в строку запроса рекомендуется добавить параметры точки начала поиска (координаты центра города; аргументы запроса lat и lon), поиск только по адресам (stype=addr), количество ответов установить равным 1 (cnt=1).

Прокладка маршрута

Корифей OpenStreetMap и ведущий новостного блога ШТОСМ Илья Зверев порекомендовал использовать для маршрутизации Open Source Routing Machine. У разработчиков запущен демо-сервер с доступным API (Илья просил не более 20 запросов в минуту, также существует ряд требований).

Предположим, мы хотим узнать длину маршрута между адресами Маркса, 23 и Рижский, 69 в городе Пскове. Через API OpenStreetMap.ru мы узнаём координаты:

Маркса, 23
57.818023681640625, 28.342592239379883
Рижский, 69
57.812679290771484, 28.28318214416504

Полученные координаты мы отправляем на API Open Source Routing Machine в виде запроса http://router.project-osrm.org/viaroute?loc=57.818023681640625,28.342592239379883&loc=57.812679290771484,28.28318214416504. Ответ приходит в формате JSON, в поле total_time содержится предполагаемое время на дорогу (в нашем случае 467 секунд), в поле total_distance — длина маршрута (4582 метра).

OSRM позволяет прокладывать маршрут сразу между последовательностью точек, но не более 25.

Подготовлено для кафе «Моя Италия»

15 Comments

  1. Evgeny
    Evgeny 2019-04-26

    В ответ на запрос в конце статьи возникает ошибка “Not found”. Что делать?

  2. Валерий
    Валерий 2019-10-03

    Доброго!
    Тоже нужен расчет длины маршрута для приложения, координаты получаю без проблем, а запрос на OSRM заканчивается ответом Not Found
    Может какие-то тонкости упустил ?

  3. Дмитрий
    Дмитрий 2020-08-19

    Спасибо за статью, очень пригодилась!
    А касательно OSRM, то у них обновился формат API
    Чтобы рассчитать расстояние, необходимо писать строку следующего вида:
    http://router.project-osrm.org/route/v1/car/x1,y1;x2,y2
    В ответе поле distance.

    • Alexander Matrunich
      Alexander Matrunich 2020-10-14

      Спасибо!

  4. Сергей
    Сергей 2020-10-13

    Не находит в Воронеже улицы
    60 лет влкс
    20 лет октября
    232 стрелковой девизии
    60 армии и т д.
    те что начинаются на цифры

  5. diakon
    diakon 2021-11-15

    А есть ли лимиты на использование роутера? Гуглю не могу найти ничего

    • Alexander Matrunich
      Alexander Matrunich 2021-11-15

      Эта открытая версия – скорее всего для демонстрационных целей. Если хочется много, надёжно и приватно, то лучше на своём сервере запустить.

  6. Дмитрий
    Дмитрий 2021-12-20

    Добрый день
    пытаюсь посчитать расстоние (маршрут) от Нижнего новгорода до москвы получаю 1465582.9 – как это интерпретировать?

  7. Дмитрий
    Дмитрий 2021-12-20

    Введите точку старта: Москва
    Введите точку завершения: Нижний Новгород
    55.7504461
    37.6174943
    56.33679805
    43.9636272489805
    ————————————————————
    http://router.project-osrm.org/route/v1/car/55.7504461,37.6174943;56.33679805,43.9636272489805
    итог 1464283.3
    ****
    json_body_request = JSON.parse(request.body)
    json_body_request.fetch(‘routes’).fetch(0).fetch(‘distance’)
    ***
    Что я делаю не так? Или в каких единицах я получаю ответ

  8. Дмитрий
    Дмитрий 2021-12-20

    code “Ok”
    waypoints
    0
    waypoint_index 0
    trips_index 0
    hint “ueUAgI2-IoIFDgAADw0AAHdsAQAuIwEAweZ5RKGyaESq_MpGYvShRgUOAAAPDQAAd2wBAC4jAQAm6AAAP51bA0iPoAKeoVsD69SeAhUAnwUjGCj5”
    distance 12583.156552
    location
    0 56.335679
    1 44.076872
    name “”
    1
    waypoint_index 1
    trips_index 0
    hint “UGf5hFVn-YQJAAAATAAAAAALAABNCQAAHFXYQMJ6UUIlFvRE-aLORAkAAABMAAAAAAsAAE0JAAAm6AAAjalSA6b9PQIur1IDVv89AlEAPxUjGCj5”
    distance 135.947123
    location
    0 55.749005
    1 37.617062
    name “”
    trips
    0
    legs
    0
    steps []
    weight 95934.9
    distance 1445763.4
    summary “”
    duration 95934.9
    1
    steps []
    weight 96769.4
    distance 1464283.3
    summary “”
    duration 96769.4
    weight_name “routability”
    weight 192704.3
    distance 2910046.7
    duration 192704.3

    Все еще две тысячи километров между москвой и нижним новгродом. Не соображу как это можно интерпритировать. Точки всего две. GET запрос переписал по новому http://router.project-osrm.org/trip/v1/driving/56.33679805,43.9636272489805;55.7504461,37.6174943?overview=false

  9. Дмитрий
    Дмитрий 2021-12-21

    Большое спасибо. Прошу прощения за невнимательность.

    • Alexander Matrunich
      Alexander Matrunich 2021-12-21

      Бывает 🙂 Это вечный вопрос про то, что раньше: долгота или широта.

Leave a Reply

Your email address will not be published. Required fields are marked *

Защита от спама *