Compare commits

...

7 Commits

Author SHA1 Message Date
Daniel Patterson
078624a54c
Bump versions preparing for merge. 2017-09-19 14:12:24 -07:00
Daniel Patterson
bb5530646a
Update changelog. 2017-09-19 14:12:13 -07:00
Denis Koronchik
4d3e35982b
Some improvements in code 2017-09-19 14:09:30 -07:00
Denis Koronchik
6227242c85
Add test for route relation process in car.lua. Some fixes 2017-09-19 14:09:30 -07:00
Denis Koronchik
b3e6b59528
Fix bug with simple refs support (not lists) 2017-09-19 14:09:30 -07:00
Denis Koronchik
40398a1856
Add route relation support for multi ref's 2017-09-19 14:09:29 -07:00
Denis Koronchik
7078ebd2cb
Implement route relation parse in car.lua 2017-09-19 14:09:29 -07:00
7 changed files with 282 additions and 5 deletions

View File

@ -1,6 +1,7 @@
# UNRELEASED
- Profile:
- 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
- Infrastructure:
- Lua 5.1 support is removed due to lack of support in sol2 https://github.com/ThePhD/sol2/issues/302

View File

@ -60,7 +60,7 @@ if (POLICY CMP0048)
endif()
project(OSRM C CXX)
set(OSRM_VERSION_MAJOR 5)
set(OSRM_VERSION_MINOR 12)
set(OSRM_VERSION_MINOR 13)
set(OSRM_VERSION_PATCH 0)
set(OSRM_VERSION "${OSRM_VERSION_MAJOR}.${OSRM_VERSION_MINOR}.${OSRM_VERSION_PATCH}")

View 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 |

View File

@ -1,6 +1,6 @@
{
"name": "osrm",
"version": "5.12.0-roundaboutexits.1",
"version": "5.13.0-cardinal.1",
"private": false,
"description": "The Open Source Routing Machine is a high performance routing engine written in C++14 designed to run on OpenStreetMap data.",
"dependencies": {

View File

@ -1,12 +1,14 @@
-- Car profile
api_version = 2
api_version = 3
Set = require('lib/set')
Sequence = require('lib/sequence')
Handlers = require("lib/way_handlers")
Relations = require("lib/relations")
find_access_tag = require("lib/access").find_access_tag
limit = require("lib/maxspeed").limit
Utils = require("lib/utils")
function setup()
local use_left_hand_driving = false
@ -279,7 +281,7 @@ function setup()
}
end
function process_node(profile, node, result)
function process_node(profile, node, result, relations)
-- parse access and barrier tags
local access = find_access_tag(node, profile.access_tags_hierarchy)
if access then
@ -306,7 +308,7 @@ function process_node(profile, node, result)
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
-- affects processing times significantly, because all ways
-- have to be checked.
@ -390,6 +392,74 @@ function process_way(profile, way, result)
}
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
function process_turn(profile, turn)
@ -434,5 +504,6 @@ return {
setup = setup,
process_way = process_way,
process_node = process_node,
process_relation = process_relation,
process_turn = process_turn
}

View 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
View 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