Compare commits
7 Commits
master
...
v5.13.0-ca
Author | SHA1 | Date | |
---|---|---|---|
|
078624a54c | ||
|
bb5530646a | ||
|
4d3e35982b | ||
|
6227242c85 | ||
|
b3e6b59528 | ||
|
40398a1856 | ||
|
7078ebd2cb |
@ -1,6 +1,7 @@
|
|||||||
# UNRELEASED
|
# UNRELEASED
|
||||||
- Profile:
|
- Profile:
|
||||||
- New function to support relations: `process_relation`. Read more in profiles documentation.
|
- New function to support relations: `process_relation`. Read more in profiles documentation.
|
||||||
|
- Append cardinal directions from route relations to ref fields to improve instructions
|
||||||
- Support of `distance` weight in foot and bicycle profiles
|
- Support of `distance` weight in foot and bicycle profiles
|
||||||
- Infrastructure:
|
- Infrastructure:
|
||||||
- Lua 5.1 support is removed due to lack of support in sol2 https://github.com/ThePhD/sol2/issues/302
|
- Lua 5.1 support is removed due to lack of support in sol2 https://github.com/ThePhD/sol2/issues/302
|
||||||
|
@ -60,7 +60,7 @@ if (POLICY CMP0048)
|
|||||||
endif()
|
endif()
|
||||||
project(OSRM C CXX)
|
project(OSRM C CXX)
|
||||||
set(OSRM_VERSION_MAJOR 5)
|
set(OSRM_VERSION_MAJOR 5)
|
||||||
set(OSRM_VERSION_MINOR 12)
|
set(OSRM_VERSION_MINOR 13)
|
||||||
set(OSRM_VERSION_PATCH 0)
|
set(OSRM_VERSION_PATCH 0)
|
||||||
set(OSRM_VERSION "${OSRM_VERSION_MAJOR}.${OSRM_VERSION_MINOR}.${OSRM_VERSION_PATCH}")
|
set(OSRM_VERSION "${OSRM_VERSION_MAJOR}.${OSRM_VERSION_MINOR}.${OSRM_VERSION_PATCH}")
|
||||||
|
|
||||||
|
68
features/car/route_relations.feature
Normal file
68
features/car/route_relations.feature
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
@routing @car @relations
|
||||||
|
Feature: Car - route relations
|
||||||
|
Background:
|
||||||
|
Given the profile "car"
|
||||||
|
|
||||||
|
@sliproads
|
||||||
|
Scenario: Cardinal direction assignment to refs
|
||||||
|
Given the node map
|
||||||
|
"""
|
||||||
|
a b
|
||||||
|
| |
|
||||||
|
c------+--+------d
|
||||||
|
e------+--+------f
|
||||||
|
| |
|
||||||
|
g h
|
||||||
|
|
||||||
|
i----------------j
|
||||||
|
k----------------l
|
||||||
|
|
||||||
|
x----------------y
|
||||||
|
z----------------w
|
||||||
|
"""
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes | name | highway | ref |
|
||||||
|
| ag | southbound | motorway | I 80 |
|
||||||
|
| hb | northbound | motorway | I 80 |
|
||||||
|
| dc | westbound | motorway | I 85;CO 93 |
|
||||||
|
| ef | eastbound | motorway | I 85;US 12 |
|
||||||
|
| ij | westbound-2 | motorway | I 99 |
|
||||||
|
| ji | eastbound-2 | motorway | I 99 |
|
||||||
|
| kl | eastbound-2 | motorway | I 99 |
|
||||||
|
| lk | eastbound-2 | motorway | I 99 |
|
||||||
|
| xy | watermill | motorway | I 45M; US 3 |
|
||||||
|
|
||||||
|
And the relations
|
||||||
|
| type | way:south | route | ref |
|
||||||
|
| route | ag | road | 80 |
|
||||||
|
| route | ef | road | 12 |
|
||||||
|
|
||||||
|
And the relations
|
||||||
|
| type | way:north | route | ref |
|
||||||
|
| route | hb | road | 80 |
|
||||||
|
| route | cd | road | 93 |
|
||||||
|
|
||||||
|
And the relations
|
||||||
|
| type | way:west | route | ref |
|
||||||
|
| route | dc | road | 85 |
|
||||||
|
| route | ij | road | 99 |
|
||||||
|
| route | xy | road | I 45 |
|
||||||
|
|
||||||
|
And the relations
|
||||||
|
| type | way:east | route | ref |
|
||||||
|
| route | lk | road | I 99 |
|
||||||
|
|
||||||
|
And the relations
|
||||||
|
| type | way:east | route | ref |
|
||||||
|
| route | xy | road | US 3 |
|
||||||
|
|
||||||
|
When I route I should get
|
||||||
|
| waypoints | route | ref |
|
||||||
|
| a,g | southbound,southbound | I 80 $south,I 80 $south |
|
||||||
|
| h,b | northbound,northbound | I 80 $north,I 80 $north |
|
||||||
|
| d,c | westbound,westbound | I 85 $west; CO 93 $north,I 85 $west; CO 93 $north |
|
||||||
|
| e,f | eastbound,eastbound | I 85; US 12 $south,I 85; US 12 $south |
|
||||||
|
| i,j | westbound-2,westbound-2 | I 99 $west,I 99 $west |
|
||||||
|
| l,k | eastbound-2,eastbound-2 | I 99 $east,I 99 $east |
|
||||||
|
| x,y | watermill,watermill | I 45M $west; US 3 $east,I 45M $west; US 3 $east |
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "osrm",
|
"name": "osrm",
|
||||||
"version": "5.12.0-roundaboutexits.1",
|
"version": "5.13.0-cardinal.1",
|
||||||
"private": false,
|
"private": false,
|
||||||
"description": "The Open Source Routing Machine is a high performance routing engine written in C++14 designed to run on OpenStreetMap data.",
|
"description": "The Open Source Routing Machine is a high performance routing engine written in C++14 designed to run on OpenStreetMap data.",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
@ -1,12 +1,14 @@
|
|||||||
-- Car profile
|
-- Car profile
|
||||||
|
|
||||||
api_version = 2
|
api_version = 3
|
||||||
|
|
||||||
Set = require('lib/set')
|
Set = require('lib/set')
|
||||||
Sequence = require('lib/sequence')
|
Sequence = require('lib/sequence')
|
||||||
Handlers = require("lib/way_handlers")
|
Handlers = require("lib/way_handlers")
|
||||||
|
Relations = require("lib/relations")
|
||||||
find_access_tag = require("lib/access").find_access_tag
|
find_access_tag = require("lib/access").find_access_tag
|
||||||
limit = require("lib/maxspeed").limit
|
limit = require("lib/maxspeed").limit
|
||||||
|
Utils = require("lib/utils")
|
||||||
|
|
||||||
function setup()
|
function setup()
|
||||||
local use_left_hand_driving = false
|
local use_left_hand_driving = false
|
||||||
@ -279,7 +281,7 @@ function setup()
|
|||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
function process_node(profile, node, result)
|
function process_node(profile, node, result, relations)
|
||||||
-- parse access and barrier tags
|
-- parse access and barrier tags
|
||||||
local access = find_access_tag(node, profile.access_tags_hierarchy)
|
local access = find_access_tag(node, profile.access_tags_hierarchy)
|
||||||
if access then
|
if access then
|
||||||
@ -306,7 +308,7 @@ function process_node(profile, node, result)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function process_way(profile, way, result)
|
function process_way(profile, way, result, relations)
|
||||||
-- the intial filtering of ways based on presence of tags
|
-- the intial filtering of ways based on presence of tags
|
||||||
-- affects processing times significantly, because all ways
|
-- affects processing times significantly, because all ways
|
||||||
-- have to be checked.
|
-- have to be checked.
|
||||||
@ -390,6 +392,74 @@ function process_way(profile, way, result)
|
|||||||
}
|
}
|
||||||
|
|
||||||
WayHandlers.run(profile,way,result,data,handlers)
|
WayHandlers.run(profile,way,result,data,handlers)
|
||||||
|
|
||||||
|
-- now process relations data
|
||||||
|
local matched_refs = nil;
|
||||||
|
if result.ref then
|
||||||
|
local match_res = Relations.match_to_ref(relations, result.ref)
|
||||||
|
|
||||||
|
local ref = ''
|
||||||
|
for _, m in pairs(match_res) do
|
||||||
|
if ref ~= '' then
|
||||||
|
ref = ref .. '; '
|
||||||
|
end
|
||||||
|
|
||||||
|
if m.dir then
|
||||||
|
ref = ref .. m.ref .. ' $' .. m.dir
|
||||||
|
else
|
||||||
|
ref = ref .. m.ref
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
result.ref = ref
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
function process_relation(profile, relation, result)
|
||||||
|
local t = relation:get_value_by_key("type")
|
||||||
|
|
||||||
|
function add_extra_data(m)
|
||||||
|
local name = relation:get_value_by_key("name")
|
||||||
|
if name then
|
||||||
|
result[m]['route_name'] = name
|
||||||
|
end
|
||||||
|
|
||||||
|
local ref = relation:get_value_by_key("ref")
|
||||||
|
if ref then
|
||||||
|
result[m]['route_ref'] = ref
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if t == 'route' then
|
||||||
|
local route = relation:get_value_by_key("route")
|
||||||
|
if route == 'road' then
|
||||||
|
for _, m in ipairs(relation:members()) do
|
||||||
|
-- process case, where directions set as role
|
||||||
|
local role = string.lower(m:role())
|
||||||
|
if role == 'north' or role == 'south' or role == 'west' or role == 'east' then
|
||||||
|
result[m]['route_direction'] = role
|
||||||
|
add_extra_data(m)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local direction = relation:get_value_by_key('direction')
|
||||||
|
if direction then
|
||||||
|
direction = string.lower(direction)
|
||||||
|
if direction == 'north' or direction == 'south' or direction == 'west' or direction == 'east' then
|
||||||
|
for _, m in ipairs(relation:members()) do
|
||||||
|
if m:role() == 'forward' then
|
||||||
|
result[m]['route_direction'] = direction
|
||||||
|
add_extra_data(m)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function process_turn(profile, turn)
|
function process_turn(profile, turn)
|
||||||
@ -434,5 +504,6 @@ return {
|
|||||||
setup = setup,
|
setup = setup,
|
||||||
process_way = process_way,
|
process_way = process_way,
|
||||||
process_node = process_node,
|
process_node = process_node,
|
||||||
|
process_relation = process_relation,
|
||||||
process_turn = process_turn
|
process_turn = process_turn
|
||||||
}
|
}
|
||||||
|
94
profiles/lib/relations.lua
Normal file
94
profiles/lib/relations.lua
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
-- Profile functions dealing with various aspects of relation parsing
|
||||||
|
--
|
||||||
|
-- You can run a selection you find useful in your profile,
|
||||||
|
-- or do you own processing if/when required.
|
||||||
|
|
||||||
|
Utils = require('lib/utils')
|
||||||
|
|
||||||
|
Relations = {}
|
||||||
|
|
||||||
|
-- match ref values to relations data
|
||||||
|
function Relations.match_to_ref(relations, ref)
|
||||||
|
|
||||||
|
function calculate_scores(refs, tag_value)
|
||||||
|
local tag_tokens = Set(Utils.tokenize_common(tag_value))
|
||||||
|
local result = {}
|
||||||
|
for i, r in ipairs(refs) do
|
||||||
|
local ref_tokens = Utils.tokenize_common(r)
|
||||||
|
local score = 0
|
||||||
|
|
||||||
|
for _, t in ipairs(ref_tokens) do
|
||||||
|
if tag_tokens[t] then
|
||||||
|
if Utils.is_number(t) then
|
||||||
|
score = score + 2
|
||||||
|
else
|
||||||
|
score = score + 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
result[r] = score
|
||||||
|
end
|
||||||
|
|
||||||
|
return result
|
||||||
|
end
|
||||||
|
|
||||||
|
local references = Utils.string_list_tokens(ref)
|
||||||
|
local result_match = {}
|
||||||
|
local order = {}
|
||||||
|
for i, r in ipairs(references) do
|
||||||
|
result_match[r] = false
|
||||||
|
order[i] = r
|
||||||
|
end
|
||||||
|
|
||||||
|
for i, rel in ipairs(relations) do
|
||||||
|
local name_scores = nil
|
||||||
|
local name_tokens = {}
|
||||||
|
local route_name = rel["route_name"]
|
||||||
|
if route_name then
|
||||||
|
name_scores = calculate_scores(references, route_name)
|
||||||
|
end
|
||||||
|
|
||||||
|
local ref_scores = nil
|
||||||
|
local ref_tokens = {}
|
||||||
|
local route_ref = rel["route_ref"]
|
||||||
|
if route_ref then
|
||||||
|
ref_scores = calculate_scores(references, route_ref)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- merge scores
|
||||||
|
local direction = rel["route_direction"]
|
||||||
|
if direction then
|
||||||
|
local best_score = -1
|
||||||
|
local best_ref = nil
|
||||||
|
|
||||||
|
function find_best(scores)
|
||||||
|
if scores then
|
||||||
|
for k ,v in pairs(scores) do
|
||||||
|
if v > best_score then
|
||||||
|
best_ref = k
|
||||||
|
best_score = v
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
find_best(name_scores)
|
||||||
|
find_best(ref_scores)
|
||||||
|
|
||||||
|
if best_ref then
|
||||||
|
result_match[best_ref] = direction
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
local result = {}
|
||||||
|
for i, r in ipairs(order) do
|
||||||
|
result[i] = { ref = r, dir = result_match[r] };
|
||||||
|
end
|
||||||
|
|
||||||
|
return result
|
||||||
|
end
|
||||||
|
|
||||||
|
return Relations
|
43
profiles/lib/utils.lua
Normal file
43
profiles/lib/utils.lua
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
-- Profile functions to implement common algorithms of data processing
|
||||||
|
--
|
||||||
|
-- You can run a selection you find useful in your profile,
|
||||||
|
-- or do you own processing if/when required.
|
||||||
|
|
||||||
|
Utils = {}
|
||||||
|
|
||||||
|
-- split string 'a; b; c' to table with values ['a', 'b', 'c']
|
||||||
|
-- so it use just one separator ';'
|
||||||
|
function Utils.string_list_tokens(str)
|
||||||
|
result = {}
|
||||||
|
local idx = 0
|
||||||
|
for s in str.gmatch(str, "([^;]*)") do
|
||||||
|
if s ~= nil and s ~= '' then
|
||||||
|
idx = idx + 1
|
||||||
|
result[idx] = s:gsub("^%s*(.-)%s*$", "%1")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return result
|
||||||
|
end
|
||||||
|
|
||||||
|
-- same as Utils.StringListTokens, but with many possible separators:
|
||||||
|
-- ',' | ';' | ' '| '(' | ')'
|
||||||
|
function Utils.tokenize_common(str)
|
||||||
|
result = {}
|
||||||
|
local idx = 0
|
||||||
|
for s in str.gmatch(str, "%S+") do
|
||||||
|
if s ~= nil and s ~= '' then
|
||||||
|
idx = idx + 1
|
||||||
|
result[idx] = s:gsub("^%s*(.-)%s*$", "%1")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return result
|
||||||
|
end
|
||||||
|
|
||||||
|
-- returns true, if string contains a number
|
||||||
|
function Utils.is_number(str)
|
||||||
|
return (tonumber(str) ~= nil)
|
||||||
|
end
|
||||||
|
|
||||||
|
return Utils
|
Loading…
Reference in New Issue
Block a user