Проблема и цель проекта
Предприятие осуществляет доставку товаров по городу. Для контроля эксплуатации служебного автомобиля необходимо владеть информацией о том, какую дистанцию должна была проехать машина при доставке по указанным адресам.
Подбор инструментов
Преимущества свободных данных и софта
Для реализации проекта предлагается использовать данные и программное обеспечение, которые распространяются под свободными лицензиями. Преимущества такого подхода перед использованием картографических сервисов от Google или Яндекса следующие:
- Проект подразумевает обработку данных для внутренних целей, а лицензионные договоры Google и Яндекса требуют использования их сервисов только для создания общедоступных публикаций в виде карт. Т.е. использование услуг этих компаний в нужных нам целях будет незаконным. Конечно, вероятность того, что Яндекс обратит внимание на незначительную нагрузку, которую мы генерируем, очень мала. Но с точки зрения развития бизнеса или его продажи в будущем, лучше сразу отказаться от включения в работу предприятия заведомо нелегальных алгоритмов.
- В процессе работы будут постепенно «всплывать» ошибки в используемой базе данных: например, какие-то адреса будут неправильно преобразовываться в координаты. Если мы работаем на основе картографического сервиса Яндекса, то в случае обнаружения ошибок (в нашем опыте такие ошибки у Яндекса были), каждый ошибочный адрес придётся обрабатывать как исключение, поскольку сам Яндекс по нашему запросу исправит эти ошибки только через несколько месяцев. При использовании данных из базы OpenStreetMap, мы можем сами внести исправление в базу, и оно практически сразу станет доступно для нашего приложения.
- При необходимости внести какие-либо изменения в работу алгоритмов по геокодированию или прикладке маршрутов, мы можем отказаться от использования открытого API, а запустить эти сервисы на своём оборудовании, поскольку и база данных дорожной сети, и программное обеспечение доступны на условиях свободных лицензий.
Схема работы
Алгоритм вычисления расстояния между двумя адресами состоит из двух этапов:
- Геокодирование, т.е. преобразование текстовой строки, содержащей адрес, в географические координаты.
- Прокладка маршрута и вычисление его длины.
Геокодирование российских адресов
Международный сайт 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.
Подготовлено для кафе «Моя Италия»
В ответ на запрос в конце статьи возникает ошибка “Not found”. Что делать?
Доброго!
Тоже нужен расчет длины маршрута для приложения, координаты получаю без проблем, а запрос на OSRM заканчивается ответом Not Found
Может какие-то тонкости упустил ?
Спасибо за статью, очень пригодилась!
А касательно OSRM, то у них обновился формат API
Чтобы рассчитать расстояние, необходимо писать строку следующего вида:
http://router.project-osrm.org/route/v1/car/x1,y1;x2,y2
В ответе поле distance.
Спасибо!
Не находит в Воронеже улицы
60 лет влкс
20 лет октября
232 стрелковой девизии
60 армии и т д.
те что начинаются на цифры
А если “Воронеж, 60-й Армии”? В Nominatim находит: https://www.openstreetmap.org/search?query=%D0%92%D0%BE%D1%80%D0%BE%D0%BD%D0%B5%D0%B6%2C%2060-%D0%B9%20%D0%90%D1%80%D0%BC%D0%B8%D0%B8
А есть ли лимиты на использование роутера? Гуглю не могу найти ничего
Эта открытая версия – скорее всего для демонстрационных целей. Если хочется много, надёжно и приватно, то лучше на своём сервере запустить.
Добрый день
пытаюсь посчитать расстоние (маршрут) от Нижнего новгорода до москвы получаю 1465582.9 – как это интерпретировать?
Введите точку старта: Москва
Введите точку завершения: Нижний Новгород
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’)
***
Что я делаю не так? Или в каких единицах я получаю ответ
Здесь документация: http://project-osrm.org/docs/v5.24.0/api/#result-objects. Судя по ней, единицы – это метры.
В онлайн-версии – нормально, 416 км: https://map.project-osrm.org/?z=8¢er=56.099620%2C42.456665&loc=55.758032%2C37.661133&loc=56.301301%2C43.961792&hl=en&alt=0&srv=0
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
Надо поменять координаты местами 🙂
http://router.project-osrm.org/trip/v1/driving/43.9636272489805,56.33679805;37.6174943,55.7504461?overview=false
Большое спасибо. Прошу прощения за невнимательность.
Бывает 🙂 Это вечный вопрос про то, что раньше: долгота или широта.