Created
November 21, 2018 08:30
-
-
Save ZsoltMedgyesi-Itineris/a50efd2a65456a6ec5ae72fd0a35d76d to your computer and use it in GitHub Desktop.
OSRM profile which gives wayIDs back as road names.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-- Car profile | |
api_version = 4 | |
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") | |
Measure = require("lib/measure") | |
function setup() | |
return { | |
properties = { | |
max_speed_for_map_matching = 180/3.6, -- 180kmph -> m/s | |
-- For routing based on duration, but weighted for preferring certain roads | |
weight_name = 'routability', | |
-- For shortest duration without penalties for accessibility | |
-- weight_name = 'duration', | |
-- For shortest distance without penalties for accessibility | |
-- weight_name = 'distance', | |
process_call_tagless_node = false, | |
u_turn_penalty = 20, | |
continue_straight_at_waypoint = true, | |
use_turn_restrictions = true, | |
left_hand_driving = false, | |
traffic_light_penalty = 2, | |
}, | |
default_mode = mode.driving, | |
default_speed = 10, | |
oneway_handling = true, | |
side_road_multiplier = 0.8, | |
turn_penalty = 7.5, | |
speed_reduction = 0.8, | |
turn_bias = 1.075, | |
cardinal_directions = false, | |
-- Size of the vehicle, to be limited by physical restriction of the way | |
vehicle_height = 2.5, -- in meters, 2.5m is the height of van | |
vehicle_width = 1.9, -- in meters, ways with narrow tag are considered narrower than 2.2m | |
-- a list of suffixes to suppress in name change instructions. The suffixes also include common substrings of each other | |
suffix_list = { | |
'N', 'NE', 'E', 'SE', 'S', 'SW', 'W', 'NW', 'North', 'South', 'West', 'East', 'Nor', 'Sou', 'We', 'Ea' | |
}, | |
barrier_whitelist = Set { | |
'cattle_grid', | |
'border_control', | |
'toll_booth', | |
'sally_port', | |
'gate', | |
'lift_gate', | |
'no', | |
'entrance', | |
'height_restrictor' | |
}, | |
access_tag_whitelist = Set { | |
'yes', | |
'motorcar', | |
'motor_vehicle', | |
'vehicle', | |
'permissive', | |
'designated', | |
'hov' | |
}, | |
access_tag_blacklist = Set { | |
'no', | |
'agricultural', | |
'forestry', | |
'emergency', | |
'psv', | |
'customers', | |
'private', | |
'delivery', | |
'destination' | |
}, | |
-- tags disallow access to in combination with highway=service | |
service_access_tag_blacklist = Set { | |
'private' | |
}, | |
restricted_access_tag_list = Set { | |
'private', | |
'delivery', | |
'destination', | |
'customers', | |
}, | |
access_tags_hierarchy = Sequence { | |
'motorcar', | |
'motor_vehicle', | |
'vehicle', | |
'access' | |
}, | |
service_tag_forbidden = Set { | |
'emergency_access' | |
}, | |
restrictions = Sequence { | |
'motorcar', | |
'motor_vehicle', | |
'vehicle' | |
}, | |
classes = Sequence { | |
'toll', 'motorway', 'ferry', 'restricted', 'tunnel' | |
}, | |
-- classes to support for exclude flags | |
excludable = Sequence { | |
Set {'toll'}, | |
Set {'motorway'}, | |
Set {'ferry'} | |
}, | |
avoid = Set { | |
'area', | |
-- 'toll', -- uncomment this to avoid tolls | |
'reversible', | |
'impassable', | |
'hov_lanes', | |
'steps', | |
'construction', | |
'proposed' | |
}, | |
speeds = Sequence { | |
highway = { | |
motorway = 90, | |
motorway_link = 45, | |
trunk = 85, | |
trunk_link = 40, | |
primary = 65, | |
primary_link = 30, | |
secondary = 55, | |
secondary_link = 25, | |
tertiary = 40, | |
tertiary_link = 20, | |
unclassified = 25, | |
residential = 25, | |
living_street = 10, | |
service = 15 | |
} | |
}, | |
service_penalties = { | |
alley = 0.5, | |
parking = 0.5, | |
parking_aisle = 0.5, | |
driveway = 0.5, | |
["drive-through"] = 0.5, | |
["drive-thru"] = 0.5 | |
}, | |
restricted_highway_whitelist = Set { | |
'motorway', | |
'motorway_link', | |
'trunk', | |
'trunk_link', | |
'primary', | |
'primary_link', | |
'secondary', | |
'secondary_link', | |
'tertiary', | |
'tertiary_link', | |
'residential', | |
'living_street', | |
'unclassified', | |
'service' | |
}, | |
construction_whitelist = Set { | |
'no', | |
'widening', | |
'minor', | |
}, | |
route_speeds = { | |
ferry = 5, | |
shuttle_train = 10 | |
}, | |
bridge_speeds = { | |
movable = 5 | |
}, | |
-- surface/trackype/smoothness | |
-- values were estimated from looking at the photos at the relevant wiki pages | |
-- max speed for surfaces | |
surface_speeds = { | |
asphalt = nil, -- nil mean no limit. removing the line has the same effect | |
concrete = nil, | |
["concrete:plates"] = nil, | |
["concrete:lanes"] = nil, | |
paved = nil, | |
cement = 80, | |
compacted = 80, | |
fine_gravel = 80, | |
paving_stones = 60, | |
metal = 60, | |
bricks = 60, | |
grass = 40, | |
wood = 40, | |
sett = 40, | |
grass_paver = 40, | |
gravel = 40, | |
unpaved = 40, | |
ground = 40, | |
dirt = 40, | |
pebblestone = 40, | |
tartan = 40, | |
cobblestone = 30, | |
clay = 30, | |
earth = 20, | |
stone = 20, | |
rocky = 20, | |
sand = 20, | |
mud = 10 | |
}, | |
-- max speed for tracktypes | |
tracktype_speeds = { | |
grade1 = 60, | |
grade2 = 40, | |
grade3 = 30, | |
grade4 = 25, | |
grade5 = 20 | |
}, | |
-- max speed for smoothnesses | |
smoothness_speeds = { | |
intermediate = 80, | |
bad = 40, | |
very_bad = 20, | |
horrible = 10, | |
very_horrible = 5, | |
impassable = 0 | |
}, | |
-- http://wiki.openstreetmap.org/wiki/Speed_limits | |
maxspeed_table_default = { | |
urban = 50, | |
rural = 90, | |
trunk = 110, | |
motorway = 130 | |
}, | |
-- List only exceptions | |
maxspeed_table = { | |
["at:rural"] = 100, | |
["at:trunk"] = 100, | |
["be:motorway"] = 120, | |
["by:urban"] = 60, | |
["by:motorway"] = 110, | |
["ch:rural"] = 80, | |
["ch:trunk"] = 100, | |
["ch:motorway"] = 120, | |
["cz:trunk"] = 0, | |
["cz:motorway"] = 0, | |
["de:living_street"] = 7, | |
["de:rural"] = 100, | |
["de:motorway"] = 0, | |
["dk:rural"] = 80, | |
["gb:nsl_single"] = (60*1609)/1000, | |
["gb:nsl_dual"] = (70*1609)/1000, | |
["gb:motorway"] = (70*1609)/1000, | |
["nl:rural"] = 80, | |
["nl:trunk"] = 100, | |
['no:rural'] = 80, | |
['no:motorway'] = 110, | |
['pl:rural'] = 100, | |
['pl:trunk'] = 120, | |
['pl:motorway'] = 140, | |
["ro:trunk"] = 100, | |
["ru:living_street"] = 20, | |
["ru:urban"] = 60, | |
["ru:motorway"] = 110, | |
["uk:nsl_single"] = (60*1609)/1000, | |
["uk:nsl_dual"] = (70*1609)/1000, | |
["uk:motorway"] = (70*1609)/1000, | |
['za:urban'] = 60, | |
['za:rural'] = 100, | |
["none"] = 140 | |
}, | |
relation_types = Sequence { | |
"route" | |
}, | |
-- classify highway tags when necessary for turn weights | |
highway_turn_classification = { | |
}, | |
-- classify access tags when necessary for turn weights | |
access_turn_classification = { | |
} | |
} | |
end | |
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 | |
if profile.access_tag_blacklist[access] and not profile.restricted_access_tag_list[access] then | |
result.barrier = true | |
end | |
else | |
local barrier = node:get_value_by_key("barrier") | |
if barrier then | |
-- check height restriction barriers | |
local restricted_by_height = false | |
if barrier == 'height_restrictor' then | |
local maxheight = Measure.get_max_height(node:get_value_by_key("maxheight"), node) | |
restricted_by_height = maxheight and maxheight < profile.vehicle_height | |
end | |
-- make an exception for rising bollard barriers | |
local bollard = node:get_value_by_key("bollard") | |
local rising_bollard = bollard and "rising" == bollard | |
if not profile.barrier_whitelist[barrier] and not rising_bollard or restricted_by_height then | |
result.barrier = true | |
end | |
end | |
end | |
-- check if node is a traffic light | |
local tag = node:get_value_by_key("highway") | |
if "traffic_signals" == tag then | |
result.traffic_lights = true | |
end | |
end | |
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. | |
-- to increase performance, prefetching and intial tag check | |
-- is done in directly instead of via a handler. | |
-- in general we should try to abort as soon as | |
-- possible if the way is not routable, to avoid doing | |
-- unnecessary work. this implies we should check things that | |
-- commonly forbids access early, and handle edge cases later. | |
-- data table for storing intermediate values during processing | |
local data = { | |
-- prefetch tags | |
highway = way:get_value_by_key('highway'), | |
bridge = way:get_value_by_key('bridge'), | |
route = way:get_value_by_key('route') | |
} | |
-- perform an quick initial check and abort if the way is | |
-- obviously not routable. | |
-- highway or route tags must be in data table, bridge is optional | |
if (not data.highway or data.highway == '') and | |
(not data.route or data.route == '') | |
then | |
return | |
end | |
result.name = way:id() | |
handlers = Sequence { | |
-- set the default mode for this profile. if can be changed later | |
-- in case it turns we're e.g. on a ferry | |
WayHandlers.default_mode, | |
-- check various tags that could indicate that the way is not | |
-- routable. this includes things like status=impassable, | |
-- toll=yes and oneway=reversible | |
WayHandlers.blocked_ways, | |
WayHandlers.avoid_ways, | |
WayHandlers.handle_height, | |
WayHandlers.handle_width, | |
-- determine access status by checking our hierarchy of | |
-- access tags, e.g: motorcar, motor_vehicle, vehicle | |
WayHandlers.access, | |
-- check whether forward/backward directions are routable | |
WayHandlers.oneway, | |
-- check a road's destination | |
WayHandlers.destinations, | |
-- check whether we're using a special transport mode | |
WayHandlers.ferries, | |
WayHandlers.movables, | |
-- handle service road restrictions | |
WayHandlers.service, | |
-- handle hov | |
WayHandlers.hov, | |
-- compute speed taking into account way type, maxspeed tags, etc. | |
WayHandlers.speed, | |
WayHandlers.surface, | |
WayHandlers.maxspeed, | |
WayHandlers.penalties, | |
-- compute class labels | |
WayHandlers.classes, | |
-- handle turn lanes and road classification, used for guidance | |
WayHandlers.turn_lanes, | |
WayHandlers.classification, | |
-- handle various other flags | |
WayHandlers.roundabouts, | |
WayHandlers.startpoint, | |
WayHandlers.driving_side, | |
-- set name, ref and pronunciation | |
--WayHandlers.names, | |
-- set weight properties of the way | |
WayHandlers.weights, | |
-- set classification of ways relevant for turns | |
WayHandlers.way_classification_for_turn | |
} | |
WayHandlers.run(profile, way, result, data, handlers, relations) | |
if profile.cardinal_directions then | |
Relations.process_way_refs(way, relations, result) | |
end | |
end | |
function process_turn(profile, turn) | |
-- Use a sigmoid function to return a penalty that maxes out at turn_penalty | |
-- over the space of 0-180 degrees. Values here were chosen by fitting | |
-- the function to some turn penalty samples from real driving. | |
local turn_penalty = profile.turn_penalty | |
local turn_bias = turn.is_left_hand_driving and 1. / profile.turn_bias or profile.turn_bias | |
if turn.has_traffic_light then | |
turn.duration = profile.properties.traffic_light_penalty | |
end | |
if turn.number_of_roads > 2 or turn.source_mode ~= turn.target_mode or turn.is_u_turn then | |
if turn.angle >= 0 then | |
turn.duration = turn.duration + turn_penalty / (1 + math.exp( -((13 / turn_bias) * turn.angle/180 - 6.5*turn_bias))) | |
else | |
turn.duration = turn.duration + turn_penalty / (1 + math.exp( -((13 * turn_bias) * -turn.angle/180 - 6.5/turn_bias))) | |
end | |
if turn.is_u_turn then | |
turn.duration = turn.duration + profile.properties.u_turn_penalty | |
end | |
end | |
-- for distance based routing we don't want to have penalties based on turn angle | |
if profile.properties.weight_name == 'distance' then | |
turn.weight = 0 | |
else | |
turn.weight = turn.duration | |
end | |
if profile.properties.weight_name == 'routability' then | |
-- penalize turns from non-local access only segments onto local access only tags | |
if not turn.source_restricted and turn.target_restricted then | |
turn.weight = constants.max_turn_weight | |
end | |
end | |
end | |
return { | |
setup = setup, | |
process_way = process_way, | |
process_node = process_node, | |
process_turn = process_turn | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment