mirror of
https://github.com/muerwre/orchidmap-front.git
synced 2025-04-24 18:46:40 +07:00
osrm startup helpers added
This commit is contained in:
parent
d9f83425f6
commit
eb091cc1a4
14 changed files with 1928 additions and 0 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -11,5 +11,8 @@
|
|||
yarn-error.log
|
||||
.awcache
|
||||
|
||||
/osrm/pbf
|
||||
/osrm/pbf/*
|
||||
|
||||
# Bundle
|
||||
*.js.map
|
||||
|
|
15
osrm/lib/access.lua
Normal file
15
osrm/lib/access.lua
Normal file
|
@ -0,0 +1,15 @@
|
|||
local ipairs = ipairs
|
||||
|
||||
local Access = {}
|
||||
|
||||
function Access.find_access_tag(source,access_tags_hierarchy)
|
||||
for i,v in ipairs(access_tags_hierarchy) do
|
||||
local tag = source:get_value_by_key(v)
|
||||
if tag then
|
||||
return tag
|
||||
end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
return Access
|
29
osrm/lib/destination.lua
Normal file
29
osrm/lib/destination.lua
Normal file
|
@ -0,0 +1,29 @@
|
|||
local Destination = {}
|
||||
|
||||
function Destination.get_directional_tag(way, is_forward, tag)
|
||||
local v
|
||||
if is_forward then
|
||||
v = way:get_value_by_key(tag .. ':forward') or way:get_value_by_key(tag)
|
||||
else
|
||||
v = way:get_value_by_key(tag .. ':backward') or way:get_value_by_key(tag)
|
||||
end
|
||||
if v then
|
||||
return v.gsub(v, ';', ', ')
|
||||
end
|
||||
end
|
||||
|
||||
-- Assemble destination as: "A59: Düsseldorf, Köln"
|
||||
-- destination:ref ^ ^ destination
|
||||
|
||||
function Destination.get_destination(way, is_forward)
|
||||
ref = Destination.get_directional_tag(way, is_forward, 'destination:ref')
|
||||
dest = Destination.get_directional_tag(way, is_forward, 'destination')
|
||||
street = Destination.get_directional_tag(way, is_forward, 'destination:street')
|
||||
if ref and dest then
|
||||
return ref .. ': ' .. dest
|
||||
else
|
||||
return ref or dest or street or ''
|
||||
end
|
||||
end
|
||||
|
||||
return Destination
|
146
osrm/lib/guidance.lua
Normal file
146
osrm/lib/guidance.lua
Normal file
|
@ -0,0 +1,146 @@
|
|||
local Tags = require('lib/tags')
|
||||
local Set = require('lib/set')
|
||||
|
||||
local Guidance = {}
|
||||
|
||||
-- Guidance: Default Mapping from roads to types/priorities
|
||||
highway_classes = {
|
||||
motorway = road_priority_class.motorway,
|
||||
motorway_link = road_priority_class.link_road,
|
||||
trunk = road_priority_class.trunk,
|
||||
trunk_link = road_priority_class.link_road,
|
||||
primary = road_priority_class.primary,
|
||||
primary_link = road_priority_class.link_road,
|
||||
secondary = road_priority_class.secondary,
|
||||
secondary_link = road_priority_class.link_road,
|
||||
tertiary = road_priority_class.tertiary,
|
||||
tertiary_link = road_priority_class.link_road,
|
||||
unclassified = road_priority_class.side_residential,
|
||||
residential = road_priority_class.side_residential,
|
||||
service = road_priority_class.connectivity,
|
||||
living_street = road_priority_class.main_residential,
|
||||
track = road_priority_class.bike_path,
|
||||
path = road_priority_class.bike_path,
|
||||
footway = road_priority_class.foot_path,
|
||||
pedestrian = road_priority_class.foot_path,
|
||||
steps = road_priority_class.foot_path
|
||||
}
|
||||
|
||||
default_highway_class = road_priority_class.connectivity;
|
||||
|
||||
motorway_types = Set {
|
||||
'motorway',
|
||||
'motorway_link',
|
||||
'trunk',
|
||||
'trunk_link'
|
||||
}
|
||||
|
||||
-- these road types are set with a car in mind. For bicycle/walk we probably need different ones
|
||||
road_types = Set {
|
||||
'motorway',
|
||||
'motorway_link',
|
||||
'trunk',
|
||||
'trunk_link',
|
||||
'primary',
|
||||
'primary_link',
|
||||
'secondary',
|
||||
'secondary_link',
|
||||
'tertiary',
|
||||
'tertiary_link',
|
||||
'unclassified',
|
||||
'residential',
|
||||
'living_street'
|
||||
}
|
||||
|
||||
link_types = Set {
|
||||
'motorway_link',
|
||||
'trunk_link',
|
||||
'primary_link',
|
||||
'secondary_link',
|
||||
'tertiary_link'
|
||||
}
|
||||
|
||||
function Guidance.set_classification (highway, result, input_way)
|
||||
if motorway_types[highway] then
|
||||
result.road_classification.motorway_class = true;
|
||||
end
|
||||
if link_types[highway] then
|
||||
result.road_classification.link_class = true;
|
||||
end
|
||||
if highway_classes[highway] ~= nil then
|
||||
result.road_classification.road_priority_class = highway_classes[highway]
|
||||
else
|
||||
result.road_classification.road_priority_class = default_highway_class
|
||||
end
|
||||
if road_types[highway] then
|
||||
result.road_classification.may_be_ignored = false;
|
||||
else
|
||||
result.road_classification.may_be_ignored = true;
|
||||
end
|
||||
|
||||
local lane_count = input_way:get_value_by_key("lanes")
|
||||
if lane_count then
|
||||
local lc = tonumber(lane_count)
|
||||
if lc ~= nil then
|
||||
result.road_classification.num_lanes = lc
|
||||
end
|
||||
else
|
||||
local total_count = 0
|
||||
local forward_count = input_way:get_value_by_key("lanes:forward")
|
||||
if forward_count then
|
||||
local fc = tonumber(forward_count)
|
||||
if fc ~= nil then
|
||||
total_count = fc
|
||||
end
|
||||
end
|
||||
local backward_count = input_way:get_value_by_key("lanes:backward")
|
||||
if backward_count then
|
||||
local bc = tonumber(backward_count)
|
||||
if bc ~= nil then
|
||||
total_count = total_count + bc
|
||||
end
|
||||
end
|
||||
if total_count ~= 0 then
|
||||
result.road_classification.num_lanes = total_count
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- returns forward,backward psv lane count
|
||||
local function get_psv_counts(way,data)
|
||||
local psv_forward, psv_backward = Tags.get_forward_backward_by_key(way,data,'lanes:psv')
|
||||
if psv_forward then
|
||||
psv_forward = tonumber(psv_forward)
|
||||
end
|
||||
if psv_backward then
|
||||
psv_backward = tonumber(psv_backward)
|
||||
end
|
||||
return psv_forward or 0,
|
||||
psv_backward or 0
|
||||
end
|
||||
|
||||
-- trims lane string with regard to supported lanes
|
||||
local function process_lanes(turn_lanes,vehicle_lanes,first_count,second_count)
|
||||
if turn_lanes then
|
||||
if vehicle_lanes then
|
||||
return applyAccessTokens(turn_lanes,vehicle_lanes)
|
||||
elseif first_count ~= 0 or second_count ~= 0 then
|
||||
return trimLaneString(turn_lanes, first_count, second_count)
|
||||
else
|
||||
return turn_lanes
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- this is broken for left-sided driving. It needs to switch left and right in case of left-sided driving
|
||||
function Guidance.get_turn_lanes(way,data)
|
||||
local psv_fw, psv_bw = get_psv_counts(way,data)
|
||||
local turn_lanes_fw, turn_lanes_bw = Tags.get_forward_backward_by_key(way,data,'turn:lanes')
|
||||
local vehicle_lanes_fw, vehicle_lanes_bw = Tags.get_forward_backward_by_key(way,data,'vehicle:lanes')
|
||||
|
||||
--note: backward lanes swap psv_bw and psv_fw
|
||||
return process_lanes(turn_lanes_fw,vehicle_lanes_fw,psv_bw,psv_fw) or turn_lanes,
|
||||
process_lanes(turn_lanes_bw,vehicle_lanes_bw,psv_fw,psv_bw) or turn_lanes
|
||||
end
|
||||
|
||||
return Guidance
|
521
osrm/lib/handlers.lua
Normal file
521
osrm/lib/handlers.lua
Normal file
|
@ -0,0 +1,521 @@
|
|||
-- Profile handlers dealing with various aspects of tag parsing
|
||||
--
|
||||
-- You can run a selection you find useful in your profile,
|
||||
-- or do you own processing if/when required.
|
||||
|
||||
|
||||
local get_turn_lanes = require("lib/guidance").get_turn_lanes
|
||||
local set_classification = require("lib/guidance").set_classification
|
||||
local get_destination = require("lib/destination").get_destination
|
||||
local Tags = require('lib/tags')
|
||||
|
||||
Handlers = {}
|
||||
|
||||
-- check that way has at least one tag that could imply routability-
|
||||
-- we store the checked tags in data, to avoid fetching again later
|
||||
function Handlers.handle_tag_prefetch(way,result,data,profile)
|
||||
for key,v in pairs(profile.prefetch) do
|
||||
data[key] = way:get_value_by_key( key )
|
||||
end
|
||||
return next(data) ~= nil
|
||||
end
|
||||
|
||||
-- set default mode
|
||||
function Handlers.handle_default_mode(way,result,data,profile)
|
||||
result.forward_mode = profile.default_mode
|
||||
result.backward_mode = profile.default_mode
|
||||
end
|
||||
|
||||
-- handles name, including ref and pronunciation
|
||||
function Handlers.handle_names(way,result,data,profile)
|
||||
-- parse the remaining tags
|
||||
local name = way:get_value_by_key("name")
|
||||
local pronunciation = way:get_value_by_key("name:pronunciation")
|
||||
local ref = way:get_value_by_key("ref")
|
||||
|
||||
-- Set the name that will be used for instructions
|
||||
if name then
|
||||
result.name = name
|
||||
end
|
||||
|
||||
if ref then
|
||||
result.ref = canonicalizeStringList(ref, ";")
|
||||
end
|
||||
|
||||
if pronunciation then
|
||||
result.pronunciation = pronunciation
|
||||
end
|
||||
end
|
||||
|
||||
-- junctions
|
||||
function Handlers.handle_roundabouts(way,result,data,profile)
|
||||
local junction = way:get_value_by_key("junction");
|
||||
|
||||
if junction == "roundabout" then
|
||||
result.roundabout = true
|
||||
end
|
||||
|
||||
-- See Issue 3361: roundabout-shaped not following roundabout rules.
|
||||
-- This will get us "At Strausberger Platz do Maneuver X" instead of multiple quick turns.
|
||||
-- In a new API version we can think of having a separate type passing it through to the user.
|
||||
if junction == "circular" then
|
||||
result.circular = true
|
||||
end
|
||||
end
|
||||
|
||||
-- determine if this way can be used as a start/end point for routing
|
||||
function Handlers.handle_startpoint(way,result,data,profile)
|
||||
-- if profile specifies set of allowed start modes, then check for that
|
||||
-- otherwise require default mode
|
||||
if profile.allowed_start_modes then
|
||||
result.is_startpoint = profile.allowed_start_modes[result.forward_mode] == true or
|
||||
profile.allowed_start_modes[result.backward_mode] == true
|
||||
else
|
||||
result.is_startpoint = result.forward_mode == profile.default_mode or
|
||||
result.backward_mode == profile.default_mode
|
||||
end
|
||||
end
|
||||
|
||||
-- handle turn lanes
|
||||
function Handlers.handle_turn_lanes(way,result,data,profile)
|
||||
local forward, backward = get_turn_lanes(way,data)
|
||||
|
||||
if forward then
|
||||
result.turn_lanes_forward = forward
|
||||
end
|
||||
|
||||
if backward then
|
||||
result.turn_lanes_backward = backward
|
||||
end
|
||||
end
|
||||
|
||||
-- set the road classification based on guidance globals configuration
|
||||
function Handlers.handle_classification(way,result,data,profile)
|
||||
set_classification(data.highway,result,way)
|
||||
end
|
||||
|
||||
-- handle destination tags
|
||||
function Handlers.handle_destinations(way,result,data,profile)
|
||||
if data.is_forward_oneway or data.is_reverse_oneway then
|
||||
local destination = get_destination(way, data.is_forward_oneway)
|
||||
result.destinations = canonicalizeStringList(destination, ",")
|
||||
end
|
||||
end
|
||||
|
||||
-- handling ferries and piers
|
||||
function Handlers.handle_ferries(way,result,data,profile)
|
||||
local route = data.route
|
||||
if route then
|
||||
local route_speed = profile.route_speeds[route]
|
||||
if route_speed and route_speed > 0 then
|
||||
local duration = way:get_value_by_key("duration")
|
||||
if duration and durationIsValid(duration) then
|
||||
result.duration = math.max( parseDuration(duration), 1 )
|
||||
end
|
||||
result.forward_mode = mode.ferry
|
||||
result.backward_mode = mode.ferry
|
||||
result.forward_speed = route_speed
|
||||
result.backward_speed = route_speed
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- handling movable bridges
|
||||
function Handlers.handle_movables(way,result,data,profile)
|
||||
local bridge = data.bridge
|
||||
if bridge then
|
||||
local bridge_speed = profile.bridge_speeds[bridge]
|
||||
if bridge_speed and bridge_speed > 0 then
|
||||
local capacity_car = way:get_value_by_key("capacity:car")
|
||||
if capacity_car ~= 0 then
|
||||
result.forward_mode = profile.default_mode
|
||||
result.backward_mode = profile.default_mode
|
||||
local duration = way:get_value_by_key("duration")
|
||||
if duration and durationIsValid(duration) then
|
||||
result.duration = math.max( parseDuration(duration), 1 )
|
||||
else
|
||||
result.forward_speed = bridge_speed
|
||||
result.backward_speed = bridge_speed
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- service roads
|
||||
function Handlers.handle_service(way,result,data,profile)
|
||||
local service = way:get_value_by_key("service")
|
||||
if service then
|
||||
-- Set don't allow access to certain service roads
|
||||
if profile.service_tag_forbidden[service] then
|
||||
result.forward_mode = mode.inaccessible
|
||||
result.backward_mode = mode.inaccessible
|
||||
return false
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- all lanes restricted to hov vehicles?
|
||||
function Handlers.has_all_designated_hov_lanes(lanes)
|
||||
if not lanes then
|
||||
return false
|
||||
end
|
||||
-- This gmatch call effectively splits the string on | chars.
|
||||
-- we append an extra | to the end so that we can match the final part
|
||||
for lane in (lanes .. '|'):gmatch("([^|]*)|") do
|
||||
if lane and lane ~= "designated" then
|
||||
return false
|
||||
end
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
-- handle high occupancy vehicle tags
|
||||
function Handlers.handle_hov(way,result,data,profile)
|
||||
-- respect user-preference for HOV
|
||||
if not profile.avoid.hov_lanes then
|
||||
return
|
||||
end
|
||||
|
||||
local hov = way:get_value_by_key("hov")
|
||||
if "designated" == hov then
|
||||
result.forward_restricted = true
|
||||
result.backward_restricted = true
|
||||
end
|
||||
|
||||
data.hov_lanes_forward, data.hov_lanes_backward = Tags.get_forward_backward_by_key(way,data,'hov:lanes')
|
||||
local all_hov_forward = Handlers.has_all_designated_hov_lanes(data.hov_lanes_forward)
|
||||
local all_hov_backward = Handlers.has_all_designated_hov_lanes(data.hov_lanes_backward)
|
||||
|
||||
-- in this case we will use turn penalties instead of filtering out
|
||||
if properties.weight_name == 'routability' then
|
||||
if (all_hov_forward) then
|
||||
result.forward_restricted = true
|
||||
end
|
||||
if (all_hov_backward) then
|
||||
result.backward_restricted = true
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
-- filter out ways where all lanes are hov only
|
||||
if all_hov_forward then
|
||||
result.forward_mode = mode.inaccessible
|
||||
end
|
||||
if all_hov_backward then
|
||||
result.backward_mode = mode.inaccessible
|
||||
end
|
||||
end
|
||||
|
||||
-- check accessibility by traversing our access tag hierarchy
|
||||
function Handlers.handle_access(way,result,data,profile)
|
||||
data.forward_access, data.backward_access =
|
||||
Tags.get_forward_backward_by_set(way,data,profile.access_tags_hierarchy)
|
||||
|
||||
if profile.access_tag_blacklist[data.forward_access] then
|
||||
result.forward_mode = mode.inaccessible
|
||||
end
|
||||
|
||||
if profile.access_tag_blacklist[data.backward_access] then
|
||||
result.backward_mode = mode.inaccessible
|
||||
end
|
||||
|
||||
if result.forward_mode == mode.inaccessible and result.backward_mode == mode.inaccessible then
|
||||
return false
|
||||
end
|
||||
|
||||
if profile.restricted_access_tag_list[data.forward_access] then
|
||||
result.forward_restricted = true
|
||||
end
|
||||
|
||||
if profile.restricted_access_tag_list[data.backward_access] then
|
||||
result.backward_restricted = true
|
||||
end
|
||||
end
|
||||
|
||||
-- handle speed (excluding maxspeed)
|
||||
function Handlers.handle_speed(way,result,data,profile)
|
||||
if result.forward_speed ~= -1 then
|
||||
return -- abort if already set, eg. by a route
|
||||
end
|
||||
|
||||
local key,value,speed = Tags.get_constant_by_key_value(way,profile.speeds)
|
||||
|
||||
if speed then
|
||||
-- set speed by way type
|
||||
result.forward_speed = speed
|
||||
result.backward_speed = speed
|
||||
else
|
||||
-- Set the avg speed on ways that are marked accessible
|
||||
if profile.access_tag_whitelist[data.forward_access] then
|
||||
result.forward_speed = profile.default_speed
|
||||
elseif data.forward_access and not profile.access_tag_blacklist[data.forward_access] then
|
||||
result.forward_speed = profile.default_speed -- fallback to the avg speed if access tag is not blacklisted
|
||||
elseif not data.forward_access and data.backward_access then
|
||||
result.forward_mode = mode.inaccessible
|
||||
end
|
||||
|
||||
if profile.access_tag_whitelist[data.backward_access] then
|
||||
result.backward_speed = profile.default_speed
|
||||
elseif data.backward_access and not profile.access_tag_blacklist[data.backward_access] then
|
||||
result.backward_speed = profile.default_speed -- fallback to the avg speed if access tag is not blacklisted
|
||||
elseif not data.backward_access and data.forward_access then
|
||||
result.backward_mode = mode.inaccessible
|
||||
end
|
||||
end
|
||||
|
||||
if result.forward_speed == -1 and result.backward_speed == -1 and result.duration <= 0 then
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
-- reduce speed on bad surfaces
|
||||
function Handlers.handle_surface(way,result,data,profile)
|
||||
local surface = way:get_value_by_key("surface")
|
||||
local tracktype = way:get_value_by_key("tracktype")
|
||||
local smoothness = way:get_value_by_key("smoothness")
|
||||
|
||||
if surface and profile.surface_speeds[surface] then
|
||||
result.forward_speed = math.min(profile.surface_speeds[surface], result.forward_speed)
|
||||
result.backward_speed = math.min(profile.surface_speeds[surface], result.backward_speed)
|
||||
end
|
||||
if tracktype and profile.tracktype_speeds[tracktype] then
|
||||
result.forward_speed = math.min(profile.tracktype_speeds[tracktype], result.forward_speed)
|
||||
result.backward_speed = math.min(profile.tracktype_speeds[tracktype], result.backward_speed)
|
||||
end
|
||||
if smoothness and profile.smoothness_speeds[smoothness] then
|
||||
result.forward_speed = math.min(profile.smoothness_speeds[smoothness], result.forward_speed)
|
||||
result.backward_speed = math.min(profile.smoothness_speeds[smoothness], result.backward_speed)
|
||||
end
|
||||
end
|
||||
|
||||
-- scale speeds to get better average driving times
|
||||
function Handlers.handle_penalties(way,result,data,profile)
|
||||
-- heavily penalize a way tagged with all HOV lanes
|
||||
-- in order to only route over them if there is no other option
|
||||
local service_penalty = 1.0
|
||||
local service = way:get_value_by_key("service")
|
||||
if service and profile.service_penalties[service] then
|
||||
service_penalty = profile.service_penalties[service]
|
||||
end
|
||||
|
||||
local width_penalty = 1.0
|
||||
local width = math.huge
|
||||
local lanes = math.huge
|
||||
local width_string = way:get_value_by_key("width")
|
||||
if width_string and tonumber(width_string:match("%d*")) then
|
||||
width = tonumber(width_string:match("%d*"))
|
||||
end
|
||||
|
||||
local lanes_string = way:get_value_by_key("lanes")
|
||||
if lanes_string and tonumber(lanes_string:match("%d*")) then
|
||||
lanes = tonumber(lanes_string:match("%d*"))
|
||||
end
|
||||
|
||||
local is_bidirectional = result.forward_mode ~= mode.inaccessible and
|
||||
result.backward_mode ~= mode.inaccessible
|
||||
|
||||
if width <= 3 or (lanes <= 1 and is_bidirectional) then
|
||||
width_penalty = 0.5
|
||||
end
|
||||
|
||||
-- Handle high frequency reversible oneways (think traffic signal controlled, changing direction every 15 minutes).
|
||||
-- Scaling speed to take average waiting time into account plus some more for start / stop.
|
||||
local alternating_penalty = 1.0
|
||||
if data.oneway == "alternating" then
|
||||
alternating_penalty = 0.4
|
||||
end
|
||||
|
||||
local sideroad_penalty = 1.0
|
||||
data.sideroad = way:get_value_by_key("side_road")
|
||||
if "yes" == data.sideroad or "rotary" == data.sideroad then
|
||||
sideroad_penalty = profile.side_road_multiplier
|
||||
end
|
||||
|
||||
local forward_penalty = math.min(service_penalty, width_penalty, alternating_penalty, sideroad_penalty)
|
||||
local backward_penalty = math.min(service_penalty, width_penalty, alternating_penalty, sideroad_penalty)
|
||||
|
||||
if properties.weight_name == 'routability' then
|
||||
if result.forward_speed > 0 then
|
||||
result.forward_rate = (result.forward_speed * forward_penalty) / 3.6
|
||||
end
|
||||
if result.backward_speed > 0 then
|
||||
result.backward_rate = (result.backward_speed * backward_penalty) / 3.6
|
||||
end
|
||||
if result.duration > 0 then
|
||||
result.weight = result.duration / forward_penalty
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- maxspeed and advisory maxspeed
|
||||
function Handlers.handle_maxspeed(way,result,data,profile)
|
||||
local keys = Sequence { 'maxspeed:advisory', 'maxspeed' }
|
||||
local forward, backward = Tags.get_forward_backward_by_set(way,data,keys)
|
||||
forward = Handlers.parse_maxspeed(forward,profile)
|
||||
backward = Handlers.parse_maxspeed(backward,profile)
|
||||
|
||||
if forward and forward > 0 then
|
||||
result.forward_speed = forward * profile.speed_reduction
|
||||
end
|
||||
|
||||
if backward and backward > 0 then
|
||||
result.backward_speed = backward * profile.speed_reduction
|
||||
end
|
||||
end
|
||||
|
||||
function Handlers.parse_maxspeed(source,profile)
|
||||
if not source then
|
||||
return 0
|
||||
end
|
||||
local n = tonumber(source:match("%d*"))
|
||||
if n then
|
||||
if string.match(source, "mph") or string.match(source, "mp/h") then
|
||||
n = (n*1609)/1000
|
||||
end
|
||||
else
|
||||
-- parse maxspeed like FR:urban
|
||||
source = string.lower(source)
|
||||
n = profile.maxspeed_table[source]
|
||||
if not n then
|
||||
local highway_type = string.match(source, "%a%a:(%a+)")
|
||||
n = profile.maxspeed_table_default[highway_type]
|
||||
if not n then
|
||||
n = 0
|
||||
end
|
||||
end
|
||||
end
|
||||
return n
|
||||
end
|
||||
|
||||
-- handle oneways tags
|
||||
function Handlers.handle_oneway(way,result,data,profile)
|
||||
if not profile.oneway_handling then
|
||||
return
|
||||
end
|
||||
|
||||
local oneway
|
||||
if profile.oneway_handling == true then
|
||||
oneway = Tags.get_value_by_prefixed_sequence(way,profile.restrictions,'oneway') or way:get_value_by_key("oneway")
|
||||
elseif profile.oneway_handling == 'specific' then
|
||||
oneway = Tags.get_value_by_prefixed_sequence(way,profile.restrictions,'oneway')
|
||||
elseif profile.oneway_handling == 'conditional' then
|
||||
-- Following code assumes that `oneway` and `oneway:conditional` tags have opposite values and takes weakest (always `no`).
|
||||
-- So if we will have:
|
||||
-- oneway=yes, oneway:conditional=no @ (condition1)
|
||||
-- oneway=no, oneway:conditional=yes @ (condition2)
|
||||
-- condition1 will be always true and condition2 will be always false.
|
||||
if way:get_value_by_key("oneway:conditional") then
|
||||
oneway = "no"
|
||||
else
|
||||
oneway = Tags.get_value_by_prefixed_sequence(way,profile.restrictions,'oneway') or way:get_value_by_key("oneway")
|
||||
end
|
||||
end
|
||||
|
||||
data.oneway = oneway
|
||||
|
||||
if oneway == "-1" then
|
||||
data.is_reverse_oneway = true
|
||||
result.forward_mode = mode.inaccessible
|
||||
elseif oneway == "yes" or
|
||||
oneway == "1" or
|
||||
oneway == "true" then
|
||||
data.is_forward_oneway = true
|
||||
result.backward_mode = mode.inaccessible
|
||||
elseif profile.oneway_handling == true then
|
||||
local junction = way:get_value_by_key("junction")
|
||||
if data.highway == "motorway" or
|
||||
junction == "roundabout" or
|
||||
junction == "circular" then
|
||||
if oneway ~= "no" then
|
||||
-- implied oneway
|
||||
data.is_forward_oneway = true
|
||||
result.backward_mode = mode.inaccessible
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function Handlers.handle_weights(way,result,data,profile)
|
||||
if properties.weight_name == 'distance' then
|
||||
result.weight = 0
|
||||
-- set weight rates to 1 for the distance weight, edge weights are distance / rate
|
||||
if (result.forward_mode ~= mode.inaccessible and result.forward_speed > 0) then
|
||||
result.forward_rate = 1
|
||||
end
|
||||
if (result.backward_mode ~= mode.inaccessible and result.backward_speed > 0) then
|
||||
result.backward_rate = 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- handle various that can block access
|
||||
function Handlers.handle_blocked_ways(way,result,data,profile)
|
||||
|
||||
-- areas
|
||||
if profile.avoid.area and way:get_value_by_key("area") == "yes" then
|
||||
return false
|
||||
end
|
||||
|
||||
-- toll roads
|
||||
if profile.avoid.toll and way:get_value_by_key("toll") == "yes" then
|
||||
return false
|
||||
end
|
||||
|
||||
-- don't route over steps
|
||||
if profile.avoid.steps and data.highway == "steps" then
|
||||
return false
|
||||
end
|
||||
|
||||
-- construction
|
||||
-- TODO if highway is valid then we shouldn't check railway, and vica versa
|
||||
if profile.avoid.construction and (data.highway == 'construction' or way:get_value_by_key('railway') == 'construction') then
|
||||
return false
|
||||
end
|
||||
|
||||
-- Reversible oneways change direction with low frequency (think twice a day):
|
||||
-- do not route over these at all at the moment because of time dependence.
|
||||
-- Note: alternating (high frequency) oneways are handled below with penalty.
|
||||
if profile.avoid.reversible and way:get_value_by_key("oneway") == "reversible" then
|
||||
return false
|
||||
end
|
||||
|
||||
-- impassables
|
||||
if profile.avoid.impassable then
|
||||
if way:get_value_by_key("impassable") == "yes" then
|
||||
return false
|
||||
end
|
||||
|
||||
if way:get_value_by_key("status") == "impassable" then
|
||||
return false
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Call a sequence of handlers, aborting in case a handler returns false. Example:
|
||||
--
|
||||
-- handlers = Sequence {
|
||||
-- 'handle_tag_prefetch',
|
||||
-- 'handle_default_mode',
|
||||
-- 'handle_blocked_ways',
|
||||
-- 'handle_access',
|
||||
-- 'handle_speed',
|
||||
-- 'handle_names'
|
||||
-- }
|
||||
--
|
||||
-- Handlers.run(handlers,way,result,data,profile)
|
||||
--
|
||||
-- Each method in the list will be called on the Handlers object.
|
||||
-- All handlers must accept the parameteres (way,result,data,profile) and return false
|
||||
-- if the handler chain should be aborted.
|
||||
-- To ensure the correct order of method calls, use a Sequence of handler names.
|
||||
|
||||
function Handlers.run(handlers,way,result,data,profile)
|
||||
for i,handler in ipairs(handlers) do
|
||||
if Handlers[handler](way,result,data,profile) == false then
|
||||
return false
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return Handlers
|
19
osrm/lib/maxspeed.lua
Normal file
19
osrm/lib/maxspeed.lua
Normal file
|
@ -0,0 +1,19 @@
|
|||
local math = math
|
||||
|
||||
local MaxSpeed = {}
|
||||
|
||||
function MaxSpeed.limit(way,max,maxf,maxb)
|
||||
if maxf and maxf>0 then
|
||||
way.forward_speed = math.min(way.forward_speed, maxf)
|
||||
elseif max and max>0 then
|
||||
way.forward_speed = math.min(way.forward_speed, max)
|
||||
end
|
||||
|
||||
if maxb and maxb>0 then
|
||||
way.backward_speed = math.min(way.backward_speed, maxb)
|
||||
elseif max and max>0 then
|
||||
way.backward_speed = math.min(way.backward_speed, max)
|
||||
end
|
||||
end
|
||||
|
||||
return MaxSpeed
|
457
osrm/lib/pprint.lua
Normal file
457
osrm/lib/pprint.lua
Normal file
|
@ -0,0 +1,457 @@
|
|||
-- Easy way to print data structes
|
||||
-- From https://github.com/jagt/pprint.lua, file is license as pubic domain
|
||||
|
||||
local pprint = { VERSION = '0.1' }
|
||||
|
||||
pprint.defaults = {
|
||||
-- type display trigger, hide not useful datatypes by default
|
||||
-- custom types are treated as table
|
||||
show_nil = true,
|
||||
show_boolean = true,
|
||||
show_number = true,
|
||||
show_string = true,
|
||||
show_table = true,
|
||||
show_function = false,
|
||||
show_thread = false,
|
||||
show_userdata = false,
|
||||
-- additional display trigger
|
||||
show_metatable = false, -- show metatable
|
||||
show_all = false, -- override other show settings and show everything
|
||||
use_tostring = false, -- use __tostring to print table if available
|
||||
filter_function = nil, -- called like callback(value[,key, parent]), return truty value to hide
|
||||
object_cache = 'local', -- cache blob and table to give it a id, 'local' cache per print, 'global' cache
|
||||
-- per process, falsy value to disable (might cause infinite loop)
|
||||
-- format settings
|
||||
indent_size = 2, -- indent for each nested table level
|
||||
level_width = 80, -- max width per indent level
|
||||
wrap_string = true, -- wrap string when it's longer than level_width
|
||||
wrap_array = false, -- wrap every array elements
|
||||
sort_keys = true, -- sort table keys
|
||||
}
|
||||
|
||||
local TYPES = {
|
||||
['nil'] = 1, ['boolean'] = 2, ['number'] = 3, ['string'] = 4,
|
||||
['table'] = 5, ['function'] = 6, ['thread'] = 7, ['userdata'] = 8
|
||||
}
|
||||
|
||||
-- seems this is the only way to escape these, as lua don't know how to map char '\a' to 'a'
|
||||
local ESCAPE_MAP = {
|
||||
['\a'] = '\\a', ['\b'] = '\\b', ['\f'] = '\\f', ['\n'] = '\\n', ['\r'] = '\\r',
|
||||
['\t'] = '\\t', ['\v'] = '\\v', ['\\'] = '\\\\',
|
||||
}
|
||||
|
||||
-- generic utilities
|
||||
local function escape(s)
|
||||
s = s:gsub('([%c\\])', ESCAPE_MAP)
|
||||
local dq = s:find('"')
|
||||
local sq = s:find("'")
|
||||
if dq and sq then
|
||||
return s:gsub('"', '\\"'), '"'
|
||||
elseif sq then
|
||||
return s, '"'
|
||||
else
|
||||
return s, "'"
|
||||
end
|
||||
end
|
||||
|
||||
local function is_plain_key(key)
|
||||
return type(key) == 'string' and key:match('^[%a_][%a%d_]*$')
|
||||
end
|
||||
|
||||
local CACHE_TYPES = {
|
||||
['table'] = true, ['function'] = true, ['thread'] = true, ['userdata'] = true
|
||||
}
|
||||
|
||||
-- cache would be populated to be like:
|
||||
-- {
|
||||
-- function = { `fun1` = 1, _cnt = 1 }, -- object id
|
||||
-- table = { `table1` = 1, `table2` = 2, _cnt = 2 },
|
||||
-- visited_tables = { `table1` = 7, `table2` = 8 }, -- visit count
|
||||
-- }
|
||||
-- use weakrefs to avoid accidentall adding refcount
|
||||
local function cache_apperance(obj, cache, option)
|
||||
if not cache.visited_tables then
|
||||
cache.visited_tables = setmetatable({}, {__mode = 'k'})
|
||||
end
|
||||
local t = type(obj)
|
||||
|
||||
-- TODO can't test filter_function here as we don't have the ix and key,
|
||||
-- might cause different results?
|
||||
-- respect show_xxx and filter_function to be consistent with print results
|
||||
if (not TYPES[t] and not option.show_table)
|
||||
or (TYPES[t] and not option['show_'..t]) then
|
||||
return
|
||||
end
|
||||
|
||||
if CACHE_TYPES[t] or TYPES[t] == nil then
|
||||
if not cache[t] then
|
||||
cache[t] = setmetatable({}, {__mode = 'k'})
|
||||
cache[t]._cnt = 0
|
||||
end
|
||||
if not cache[t][obj] then
|
||||
cache[t]._cnt = cache[t]._cnt + 1
|
||||
cache[t][obj] = cache[t]._cnt
|
||||
end
|
||||
end
|
||||
if t == 'table' or TYPES[t] == nil then
|
||||
if cache.visited_tables[obj] == false then
|
||||
-- already printed, no need to mark this and its children anymore
|
||||
return
|
||||
elseif cache.visited_tables[obj] == nil then
|
||||
cache.visited_tables[obj] = 1
|
||||
else
|
||||
-- visited already, increment and continue
|
||||
cache.visited_tables[obj] = cache.visited_tables[obj] + 1
|
||||
return
|
||||
end
|
||||
for k, v in pairs(obj) do
|
||||
cache_apperance(k, cache, option)
|
||||
cache_apperance(v, cache, option)
|
||||
end
|
||||
local mt = getmetatable(obj)
|
||||
if mt and option.show_metatable then
|
||||
cache_apperance(mt, cache, option)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- makes 'foo2' < 'foo100000'. string.sub makes substring anyway, no need to use index based method
|
||||
local function str_natural_cmp(lhs, rhs)
|
||||
while #lhs > 0 and #rhs > 0 do
|
||||
local lmid, lend = lhs:find('%d+')
|
||||
local rmid, rend = rhs:find('%d+')
|
||||
if not (lmid and rmid) then return lhs < rhs end
|
||||
|
||||
local lsub = lhs:sub(1, lmid-1)
|
||||
local rsub = rhs:sub(1, rmid-1)
|
||||
if lsub ~= rsub then
|
||||
return lsub < rsub
|
||||
end
|
||||
|
||||
local lnum = tonumber(lhs:sub(lmid, lend))
|
||||
local rnum = tonumber(rhs:sub(rmid, rend))
|
||||
if lnum ~= rnum then
|
||||
return lnum < rnum
|
||||
end
|
||||
|
||||
lhs = lhs:sub(lend+1)
|
||||
rhs = rhs:sub(rend+1)
|
||||
end
|
||||
return lhs < rhs
|
||||
end
|
||||
|
||||
local function cmp(lhs, rhs)
|
||||
local tleft = type(lhs)
|
||||
local tright = type(rhs)
|
||||
if tleft == 'number' and tright == 'number' then return lhs < rhs end
|
||||
if tleft == 'string' and tright == 'string' then return str_natural_cmp(lhs, rhs) end
|
||||
if tleft == tright then return str_natural_cmp(tostring(lhs), tostring(rhs)) end
|
||||
|
||||
-- allow custom types
|
||||
local oleft = TYPES[tleft] or 9
|
||||
local oright = TYPES[tright] or 9
|
||||
return oleft < oright
|
||||
end
|
||||
|
||||
-- setup option with default
|
||||
local function make_option(option)
|
||||
if option == nil then
|
||||
option = {}
|
||||
end
|
||||
for k, v in pairs(pprint.defaults) do
|
||||
if option[k] == nil then
|
||||
option[k] = v
|
||||
end
|
||||
if option.show_all then
|
||||
for t, _ in pairs(TYPES) do
|
||||
option['show_'..t] = true
|
||||
end
|
||||
option.show_metatable = true
|
||||
end
|
||||
end
|
||||
return option
|
||||
end
|
||||
|
||||
-- override defaults and take effects for all following calls
|
||||
function pprint.setup(option)
|
||||
pprint.defaults = make_option(option)
|
||||
end
|
||||
|
||||
-- format lua object into a string
|
||||
function pprint.pformat(obj, option, printer)
|
||||
option = make_option(option)
|
||||
local buf = {}
|
||||
local function default_printer(s)
|
||||
table.insert(buf, s)
|
||||
end
|
||||
printer = printer or default_printer
|
||||
|
||||
local cache
|
||||
if option.object_cache == 'global' then
|
||||
-- steal the cache into a local var so it's not visible from _G or anywhere
|
||||
-- still can't avoid user explicitly referentce pprint._cache but it shouldn't happen anyway
|
||||
cache = pprint._cache or {}
|
||||
pprint._cache = nil
|
||||
elseif option.object_cache == 'local' then
|
||||
cache = {}
|
||||
end
|
||||
|
||||
local last = '' -- used for look back and remove trailing comma
|
||||
local status = {
|
||||
indent = '', -- current indent
|
||||
len = 0, -- current line length
|
||||
}
|
||||
|
||||
local wrapped_printer = function(s)
|
||||
printer(last)
|
||||
last = s
|
||||
end
|
||||
|
||||
local function _indent(d)
|
||||
status.indent = string.rep(' ', d + #(status.indent))
|
||||
end
|
||||
|
||||
local function _n(d)
|
||||
wrapped_printer('\n')
|
||||
wrapped_printer(status.indent)
|
||||
if d then
|
||||
_indent(d)
|
||||
end
|
||||
status.len = 0
|
||||
return true -- used to close bracket correctly
|
||||
end
|
||||
|
||||
local function _p(s, nowrap)
|
||||
status.len = status.len + #s
|
||||
if not nowrap and status.len > option.level_width then
|
||||
_n()
|
||||
wrapped_printer(s)
|
||||
status.len = #s
|
||||
else
|
||||
wrapped_printer(s)
|
||||
end
|
||||
end
|
||||
|
||||
local formatter = {}
|
||||
local function format(v)
|
||||
local f = formatter[type(v)]
|
||||
f = f or formatter.table -- allow patched type()
|
||||
if option.filter_function and option.filter_function(v, nil, nil) then
|
||||
return ''
|
||||
else
|
||||
return f(v)
|
||||
end
|
||||
end
|
||||
|
||||
local function tostring_formatter(v)
|
||||
return tostring(v)
|
||||
end
|
||||
|
||||
local function number_formatter(n)
|
||||
return n == math.huge and '[[math.huge]]' or tostring(n)
|
||||
end
|
||||
|
||||
local function nop_formatter(v)
|
||||
return ''
|
||||
end
|
||||
|
||||
local function make_fixed_formatter(t, has_cache)
|
||||
if has_cache then
|
||||
return function (v)
|
||||
return string.format('[[%s %d]]', t, cache[t][v])
|
||||
end
|
||||
else
|
||||
return function (v)
|
||||
return '[['..t..']]'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function string_formatter(s, force_long_quote)
|
||||
local s, quote = escape(s)
|
||||
local quote_len = force_long_quote and 4 or 2
|
||||
if quote_len + #s + status.len > option.level_width then
|
||||
_n()
|
||||
-- only wrap string when is longer than level_width
|
||||
if option.wrap_string and #s + quote_len > option.level_width then
|
||||
-- keep the quotes together
|
||||
_p('[[')
|
||||
while #s + status.len >= option.level_width do
|
||||
local seg = option.level_width - status.len
|
||||
_p(string.sub(s, 1, seg), true)
|
||||
_n()
|
||||
s = string.sub(s, seg+1)
|
||||
end
|
||||
_p(s) -- print the remaining parts
|
||||
return ']]'
|
||||
end
|
||||
end
|
||||
|
||||
return force_long_quote and '[['..s..']]' or quote..s..quote
|
||||
end
|
||||
|
||||
local function table_formatter(t)
|
||||
if option.use_tostring then
|
||||
local mt = getmetatable(t)
|
||||
if mt and mt.__tostring then
|
||||
return string_formatter(tostring(t), true)
|
||||
end
|
||||
end
|
||||
|
||||
local print_header_ix = nil
|
||||
local ttype = type(t)
|
||||
if option.object_cache then
|
||||
local cache_state = cache.visited_tables[t]
|
||||
local tix = cache[ttype][t]
|
||||
-- FIXME should really handle `cache_state == nil`
|
||||
-- as user might add things through filter_function
|
||||
if cache_state == false then
|
||||
-- already printed, just print the the number
|
||||
return string_formatter(string.format('%s %d', ttype, tix), true)
|
||||
elseif cache_state > 1 then
|
||||
-- appeared more than once, print table header with number
|
||||
print_header_ix = tix
|
||||
cache.visited_tables[t] = false
|
||||
else
|
||||
-- appeared exactly once, print like a normal table
|
||||
end
|
||||
end
|
||||
|
||||
local tlen = #t
|
||||
local wrapped = false
|
||||
_p('{')
|
||||
_indent(option.indent_size)
|
||||
_p(string.rep(' ', option.indent_size - 1))
|
||||
if print_header_ix then
|
||||
_p(string.format('--[[%s %d]] ', ttype, print_header_ix))
|
||||
end
|
||||
for ix = 1,tlen do
|
||||
local v = t[ix]
|
||||
if formatter[type(v)] == nop_formatter or
|
||||
(option.filter_function and option.filter_function(v, ix, t)) then
|
||||
-- pass
|
||||
else
|
||||
if option.wrap_array then
|
||||
wrapped = _n()
|
||||
end
|
||||
_p(format(v)..', ')
|
||||
end
|
||||
end
|
||||
|
||||
-- hashmap part of the table, in contrast to array part
|
||||
local function is_hash_key(k)
|
||||
local numkey = tonumber(k)
|
||||
if numkey ~= k or numkey > tlen then
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
local function print_kv(k, v, t)
|
||||
-- can't use option.show_x as obj may contain custom type
|
||||
if formatter[type(v)] == nop_formatter or
|
||||
formatter[type(k)] == nop_formatter or
|
||||
(option.filter_function and option.filter_function(v, k, t)) then
|
||||
return
|
||||
end
|
||||
wrapped = _n()
|
||||
if is_plain_key(k) then
|
||||
_p(k, true)
|
||||
else
|
||||
_p('[')
|
||||
-- [[]] type string in key is illegal, needs to add spaces inbetween
|
||||
local k = format(k)
|
||||
if string.match(k, '%[%[') then
|
||||
_p(' '..k..' ', true)
|
||||
else
|
||||
_p(k, true)
|
||||
end
|
||||
_p(']')
|
||||
end
|
||||
_p(' = ', true)
|
||||
_p(format(v), true)
|
||||
_p(',', true)
|
||||
end
|
||||
|
||||
if option.sort_keys then
|
||||
local keys = {}
|
||||
for k, _ in pairs(t) do
|
||||
if is_hash_key(k) then
|
||||
table.insert(keys, k)
|
||||
end
|
||||
end
|
||||
table.sort(keys, cmp)
|
||||
for _, k in ipairs(keys) do
|
||||
print_kv(k, t[k], t)
|
||||
end
|
||||
else
|
||||
for k, v in pairs(t) do
|
||||
if is_hash_key(k) then
|
||||
print_kv(k, v, t)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if option.show_metatable then
|
||||
local mt = getmetatable(t)
|
||||
if mt then
|
||||
print_kv('__metatable', mt, t)
|
||||
end
|
||||
end
|
||||
|
||||
_indent(-option.indent_size)
|
||||
-- make { } into {}
|
||||
last = string.gsub(last, '^ +$', '')
|
||||
-- peek last to remove trailing comma
|
||||
last = string.gsub(last, ',%s*$', ' ')
|
||||
if wrapped then
|
||||
_n()
|
||||
end
|
||||
_p('}')
|
||||
|
||||
return ''
|
||||
end
|
||||
|
||||
-- set formatters
|
||||
formatter['nil'] = option.show_nil and tostring_formatter or nop_formatter
|
||||
formatter['boolean'] = option.show_boolean and tostring_formatter or nop_formatter
|
||||
formatter['number'] = option.show_number and number_formatter or nop_formatter -- need to handle math.huge
|
||||
formatter['function'] = option.show_function and make_fixed_formatter('function', option.object_cache) or nop_formatter
|
||||
formatter['thread'] = option.show_thread and make_fixed_formatter('thread', option.object_cache) or nop_formatter
|
||||
formatter['userdata'] = option.show_userdata and make_fixed_formatter('userdata', option.object_cache) or nop_formatter
|
||||
formatter['string'] = option.show_string and string_formatter or nop_formatter
|
||||
formatter['table'] = option.show_table and table_formatter or nop_formatter
|
||||
|
||||
if option.object_cache then
|
||||
-- needs to visit the table before start printing
|
||||
cache_apperance(obj, cache, option)
|
||||
end
|
||||
|
||||
_p(format(obj))
|
||||
printer(last) -- close the buffered one
|
||||
|
||||
-- put cache back if global
|
||||
if option.object_cache == 'global' then
|
||||
pprint._cache = cache
|
||||
end
|
||||
|
||||
return table.concat(buf)
|
||||
end
|
||||
|
||||
-- pprint all the arguments
|
||||
function pprint.pprint( ... )
|
||||
local args = {...}
|
||||
-- select will get an accurate count of array len, counting trailing nils
|
||||
local len = select('#', ...)
|
||||
for ix = 1,len do
|
||||
pprint.pformat(args[ix], nil, io.write)
|
||||
io.write('\n')
|
||||
end
|
||||
end
|
||||
|
||||
setmetatable(pprint, {
|
||||
__call = function (_, ...)
|
||||
pprint.pprint(...)
|
||||
end
|
||||
})
|
||||
|
||||
return pprint
|
139
osrm/lib/profile_debugger.lua
Normal file
139
osrm/lib/profile_debugger.lua
Normal file
|
@ -0,0 +1,139 @@
|
|||
-- Enable calling our lua profile code directly from the lua command line,
|
||||
-- which makes it easier to debug.
|
||||
-- We simulate the normal C++ environment by defining the required globals and functions.
|
||||
|
||||
-- See debug_example.lua for an example of how to require and use this file.
|
||||
|
||||
-- for more convenient printing of tables
|
||||
local pprint = require('lib/pprint')
|
||||
|
||||
|
||||
-- globals that are normally set from C++
|
||||
|
||||
-- profiles code modifies this table
|
||||
properties = {}
|
||||
|
||||
-- should match values defined in include/extractor/guidance/road_classification.hpp
|
||||
road_priority_class = {
|
||||
motorway = 0,
|
||||
trunk = 2,
|
||||
primary = 4,
|
||||
secondary = 6,
|
||||
tertiary = 8,
|
||||
main_residential = 10,
|
||||
side_residential = 11,
|
||||
link_road = 14,
|
||||
bike_path = 16,
|
||||
foot_path = 18,
|
||||
connectivity = 31,
|
||||
}
|
||||
|
||||
-- should match values defined in include/extractor/travel_mode.hpp
|
||||
mode = {
|
||||
inaccessible = 0,
|
||||
driving = 1,
|
||||
cycling = 2,
|
||||
walking = 3,
|
||||
ferry = 4,
|
||||
train = 5,
|
||||
pushing_bike = 6,
|
||||
}
|
||||
|
||||
-- Mock C++ helper functions which are called from LUA.
|
||||
-- TODO
|
||||
-- Debugging LUA code that uses these will not work correctly
|
||||
-- unless we reimplement the methods in LUA.
|
||||
|
||||
function durationIsValid(str)
|
||||
return true
|
||||
end
|
||||
|
||||
function parseDuration(str)
|
||||
return 1
|
||||
end
|
||||
|
||||
function canonicalizeStringList(str)
|
||||
return str
|
||||
end
|
||||
|
||||
|
||||
|
||||
-- debug helper
|
||||
local Debug = {}
|
||||
|
||||
-- helpers for sorting associative array
|
||||
function Debug.get_keys_sorted_by_value(tbl, sortFunction)
|
||||
local keys = {}
|
||||
for key in pairs(tbl) do
|
||||
table.insert(keys, key)
|
||||
end
|
||||
|
||||
table.sort(keys, function(a, b)
|
||||
return sortFunction(tbl[a], tbl[b])
|
||||
end)
|
||||
|
||||
return keys
|
||||
end
|
||||
|
||||
-- helper for printing sorted array
|
||||
function Debug.print_sorted(sorted,associative)
|
||||
for _, key in ipairs(sorted) do
|
||||
print(associative[key], key)
|
||||
end
|
||||
end
|
||||
|
||||
function Debug.report_tag_fetches()
|
||||
print("Tag fetches:")
|
||||
sorted_counts = Debug.get_keys_sorted_by_value(Debug.tags.counts, function(a, b) return a > b end)
|
||||
Debug.print_sorted(sorted_counts, Debug.tags.counts)
|
||||
print(Debug.tags.total, 'total')
|
||||
end
|
||||
|
||||
function Debug.load_profile(profile)
|
||||
require(profile)
|
||||
end
|
||||
|
||||
function Debug.reset_tag_fetch_counts()
|
||||
Debug.tags = {
|
||||
total = 0,
|
||||
counts = {}
|
||||
}
|
||||
end
|
||||
|
||||
function Debug.register_tag_fetch(k)
|
||||
if Debug.tags.total then
|
||||
Debug.tags.total = Debug.tags.total + 1
|
||||
else
|
||||
Debug['tags']['total'] = 1
|
||||
end
|
||||
|
||||
if Debug['tags']['counts'][k] then
|
||||
Debug['tags']['counts'][k] = Debug['tags']['counts'][k] + 1
|
||||
else
|
||||
Debug['tags']['counts'][k] = 1
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
function Debug.way_function(way,result)
|
||||
|
||||
-- setup result table
|
||||
result.road_classification = {}
|
||||
result.forward_speed = -1
|
||||
result.backward_speed = -1
|
||||
result.duration = 0
|
||||
|
||||
-- intercept tag function normally provided via C++
|
||||
function way:get_value_by_key(k)
|
||||
Debug.register_tag_fetch(k)
|
||||
return self[k]
|
||||
end
|
||||
|
||||
-- reset tag counts
|
||||
Debug:reset_tag_fetch_counts()
|
||||
|
||||
-- call the global method defined in the profile file
|
||||
way_function(way,result)
|
||||
end
|
||||
|
||||
return Debug
|
10
osrm/lib/sequence.lua
Normal file
10
osrm/lib/sequence.lua
Normal file
|
@ -0,0 +1,10 @@
|
|||
-- Sequence of items
|
||||
-- Ordered, but have to loop through items to check for inclusion.
|
||||
-- Currently the same as a table.
|
||||
|
||||
|
||||
function Sequence(source)
|
||||
return source
|
||||
end
|
||||
|
||||
return Sequence
|
23
osrm/lib/set.lua
Normal file
23
osrm/lib/set.lua
Normal file
|
@ -0,0 +1,23 @@
|
|||
-- Set of items
|
||||
-- Fast check for inclusion, but unordered.
|
||||
--
|
||||
-- Instead of having to do:
|
||||
-- whitelist = { 'apple'=true, 'cherries'=true, 'melons'=true }
|
||||
--
|
||||
-- you can do:
|
||||
-- whitelist = Set { 'apple', 'cherries', 'melons' }
|
||||
--
|
||||
-- and then use it as:
|
||||
-- print( whitelist['cherries'] ) => true
|
||||
|
||||
function Set(source)
|
||||
set = {}
|
||||
if source then
|
||||
for i,v in ipairs(source) do
|
||||
set[v] = true
|
||||
end
|
||||
end
|
||||
return set
|
||||
end
|
||||
|
||||
return Set
|
124
osrm/lib/tags.lua
Normal file
124
osrm/lib/tags.lua
Normal file
|
@ -0,0 +1,124 @@
|
|||
-- Helpers for searching and parsing tags
|
||||
|
||||
local Tags = {}
|
||||
|
||||
-- return [forward,backward] values for a specific tag.
|
||||
-- e.g. for maxspeed search forward:
|
||||
-- maxspeed:forward
|
||||
-- maxspeed
|
||||
-- and backward:
|
||||
-- maxspeed:backward
|
||||
-- maxspeed
|
||||
|
||||
function Tags.get_forward_backward_by_key(way,data,key)
|
||||
local forward = way:get_value_by_key(key .. ':forward')
|
||||
local backward = way:get_value_by_key(key .. ':backward')
|
||||
|
||||
if forward and backward then
|
||||
return forward, backward
|
||||
end
|
||||
|
||||
local common = way:get_value_by_key(key)
|
||||
return forward or common,
|
||||
backward or common
|
||||
end
|
||||
|
||||
-- return [forward,backward] values, searching a
|
||||
-- prioritized sequence of tags
|
||||
-- e.g. for the sequence [maxspeed,advisory] search forward:
|
||||
-- maxspeed:forward
|
||||
-- maxspeed
|
||||
-- advisory:forward
|
||||
-- advisory
|
||||
-- and for backward:
|
||||
-- maxspeed:backward
|
||||
-- maxspeed
|
||||
-- advisory:backward
|
||||
-- advisory
|
||||
|
||||
function Tags.get_forward_backward_by_set(way,data,keys)
|
||||
local forward, backward
|
||||
for i,key in ipairs(keys) do
|
||||
if not forward then
|
||||
forward = way:get_value_by_key(key .. ':forward')
|
||||
end
|
||||
if not backward then
|
||||
backward = way:get_value_by_key(key .. ':backward')
|
||||
end
|
||||
if not forward or not backward then
|
||||
local common = way:get_value_by_key(key)
|
||||
forward = forward or common
|
||||
backward = backward or common
|
||||
end
|
||||
if forward and backward then
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
return forward, backward
|
||||
end
|
||||
|
||||
-- look through a sequence of keys combined with a prefix
|
||||
-- e.g. for the sequence [motorcar,motor_vehicle,vehicle] and the prefix 'oneway' search for:
|
||||
-- oneway:motorcar
|
||||
-- oneway:motor_vehicle
|
||||
-- oneway:vehicle
|
||||
|
||||
function Tags.get_value_by_prefixed_sequence(way,seq,prefix)
|
||||
local v
|
||||
for i,key in ipairs(seq) do
|
||||
v = way:get_value_by_key(prefix .. ':' .. key)
|
||||
if v then
|
||||
return v
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- look through a sequence of keys combined with a postfix
|
||||
-- e.g. for the sequence [motorcar,motor_vehicle,vehicle] and the postfix 'oneway' search for:
|
||||
-- motorcar:oneway
|
||||
-- motor_vehicle:oneway
|
||||
-- vehicle:oneway
|
||||
|
||||
function Tags.get_value_by_postfixed_sequence(way,seq,postfix)
|
||||
local v
|
||||
for i,key in ipairs(seq) do
|
||||
v = way:get_value_by_key(key .. ':' .. postfix)
|
||||
if v then
|
||||
return v
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- check if key-value pairs are set in a way and return a
|
||||
-- corresponding constant if it is. e.g. for this input:
|
||||
--
|
||||
-- local speeds = {
|
||||
-- highway = {
|
||||
-- residential = 20,
|
||||
-- primary = 40
|
||||
-- },
|
||||
-- amenity = {
|
||||
-- parking = 10
|
||||
-- }
|
||||
-- }
|
||||
--
|
||||
-- we would check whether the following key-value combinations
|
||||
-- are set, and return the corresponding constant:
|
||||
--
|
||||
-- highway = residential => 20
|
||||
-- highway = primary => 40
|
||||
-- amenity = parking => 10
|
||||
|
||||
function Tags.get_constant_by_key_value(way,lookup)
|
||||
for key,set in pairs(lookup) do
|
||||
local way_value = way:get_value_by_key(key)
|
||||
for value,t in pairs(set) do
|
||||
if way_value == value then
|
||||
return key,value,t
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return Tags
|
9
osrm/prepare_maps.sh
Executable file
9
osrm/prepare_maps.sh
Executable file
|
@ -0,0 +1,9 @@
|
|||
#!/bin/bash
|
||||
REGION="russia";
|
||||
DISTRICT="siberian-fed-district-latest";
|
||||
|
||||
mkdir pbf
|
||||
wget "https://download.geofabrik.de/$REGION/$DISTRICT.osm.pbf" -O "pbf/$DISTRICT.osm.pbf"
|
||||
|
||||
osrm-extract "./pbf/$DISTRICT.osm.pbf" -p ./rules.lua
|
||||
osrm-contract "./pbf/$DISTRICT.osrm"
|
422
osrm/rules.lua
Normal file
422
osrm/rules.lua
Normal file
|
@ -0,0 +1,422 @@
|
|||
-- Car profile
|
||||
|
||||
api_version = 1
|
||||
|
||||
local find_access_tag = require("lib/access").find_access_tag
|
||||
local Set = require('lib/set')
|
||||
local Sequence = require('lib/sequence')
|
||||
local Handlers = require("lib/handlers")
|
||||
local next = next -- bind to local for speed
|
||||
|
||||
penalty_table = {
|
||||
["service"] = 0.5,
|
||||
}
|
||||
|
||||
-- set profile properties
|
||||
properties.max_speed_for_map_matching = 15 -- 180kmph -> m/s
|
||||
properties.use_turn_restrictions = false
|
||||
properties.continue_straight_at_waypoint = false
|
||||
properties.left_hand_driving = false
|
||||
-- For routing based on duration, but weighted for preferring certain roads
|
||||
properties.weight_name = 'routability'
|
||||
-- For shortest duration without penalties for accessibility
|
||||
--properties.weight_name = 'duration'
|
||||
-- For shortest distance without penalties for accessibility
|
||||
--properties.weight_name = 'distance'
|
||||
|
||||
local profile = {
|
||||
default_mode = mode.driving,
|
||||
default_speed = 10,
|
||||
oneway_handling = true,
|
||||
|
||||
side_road_multiplier = 0.8,
|
||||
turn_penalty = 12,
|
||||
speed_reduction = 0.8,
|
||||
traffic_light_penalty = 2,
|
||||
u_turn_penalty = 20,
|
||||
restricted_penalty = 3000,
|
||||
-- Note^: abstract value but in seconds correlates approximately to 50 min
|
||||
-- meaning that a route through a local access way is > 50 min faster than around
|
||||
|
||||
-- Note: this biases right-side driving.
|
||||
-- Should be inverted for left-driving countries.
|
||||
turn_bias = properties.left_hand_driving and 1/1.075 or 1.075,
|
||||
|
||||
-- a list of suffixes to suppress in name change instructions
|
||||
suffix_list = {
|
||||
'N', 'NE', 'E', 'SE', 'S', 'SW', 'W', 'NW', 'North', 'South', 'West', 'East'
|
||||
},
|
||||
|
||||
barrier_whitelist = Set {
|
||||
'cattle_grid',
|
||||
'border_control',
|
||||
'checkpoint',
|
||||
'toll_booth',
|
||||
'sally_port',
|
||||
'gate',
|
||||
'lift_gate',
|
||||
'no',
|
||||
'entrance'
|
||||
},
|
||||
|
||||
access_tag_whitelist = Set {
|
||||
'yes',
|
||||
'residential',
|
||||
'primary',
|
||||
'secondary',
|
||||
'motorcar',
|
||||
'motor_vehicle',
|
||||
'vehicle',
|
||||
'track',
|
||||
'permissive',
|
||||
'designated',
|
||||
'hov'
|
||||
},
|
||||
|
||||
access_tag_blacklist = Set {
|
||||
-- 'no',
|
||||
-- 'agricultural',
|
||||
-- 'forestry',
|
||||
-- 'emergency',
|
||||
-- 'psv'
|
||||
},
|
||||
|
||||
restricted_access_tag_list = Set {
|
||||
-- 'private',
|
||||
-- 'delivery',
|
||||
-- 'destination'
|
||||
},
|
||||
|
||||
access_tags_hierarchy = Sequence {
|
||||
'motorcar',
|
||||
'motor_vehicle',
|
||||
'vehicle',
|
||||
'residential',
|
||||
'track',
|
||||
'foot',
|
||||
'bicycle',
|
||||
'access'
|
||||
},
|
||||
|
||||
service_tag_forbidden = Set {
|
||||
'emergency_access'
|
||||
},
|
||||
|
||||
restrictions = Sequence {
|
||||
-- 'motorcar',
|
||||
-- 'motor_vehicle',
|
||||
-- 'vehicle'
|
||||
},
|
||||
|
||||
avoid = Set {
|
||||
-- 'area',
|
||||
-- 'toll', -- uncomment this to avoid tolls
|
||||
-- 'reversible',
|
||||
'impassable',
|
||||
-- 'hov_lanes',
|
||||
-- 'steps'
|
||||
},
|
||||
|
||||
speeds = Sequence {
|
||||
highway = {
|
||||
motorway = 80,
|
||||
cycleway = 110,
|
||||
motorway_link = 80,
|
||||
trunk = 80,
|
||||
trunk_link = 100,
|
||||
primary = 100,
|
||||
primary_link = 100,
|
||||
secondary = 90,
|
||||
secondary_link = 90,
|
||||
tertiary = 80,
|
||||
tertiary_link = 80,
|
||||
unclassified = 80,
|
||||
residential = 80,
|
||||
living_street = 75,
|
||||
service = 75,
|
||||
road = 90,
|
||||
track = 95,
|
||||
path = 70,
|
||||
steps = 15,
|
||||
pedestrian = 70,
|
||||
footway = 80,
|
||||
footpath = 100,
|
||||
foot_path = 100,
|
||||
pier = 95,
|
||||
unpaved = 95
|
||||
}
|
||||
},
|
||||
|
||||
service_penalties = {
|
||||
-- alley = 0.5,
|
||||
-- parking = 0.5,
|
||||
-- parking_aisle = 0.5,
|
||||
-- driveway = 0.5,
|
||||
-- ["drive-through"] = 0.5,
|
||||
-- ["drive-thru"] = 0.5
|
||||
},
|
||||
|
||||
route_speeds = {
|
||||
ferry = 5,
|
||||
shuttle_train = 10
|
||||
},
|
||||
|
||||
bridge_speeds = {
|
||||
movable = nil
|
||||
},
|
||||
|
||||
-- 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 = nil,
|
||||
compacted = nil,
|
||||
fine_gravel = nil,
|
||||
|
||||
paving_stones = nil,
|
||||
metal = nil,
|
||||
bricks = nil,
|
||||
|
||||
grass = 50,
|
||||
wood = nil,
|
||||
sett = nil,
|
||||
grass_paver = 80,
|
||||
gravel = 80,
|
||||
unpaved = nil,
|
||||
ground = 80,
|
||||
dirt = 60,
|
||||
pebblestone = nil,
|
||||
tartan = 50,
|
||||
|
||||
cobblestone = 60,
|
||||
clay = 60,
|
||||
|
||||
earth = 60,
|
||||
stone = 60,
|
||||
rocky = 50,
|
||||
sand = 40,
|
||||
|
||||
mud = 40
|
||||
},
|
||||
|
||||
-- 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 = {
|
||||
["ch:rural"] = 80,
|
||||
["ch:trunk"] = 100,
|
||||
["ch:motorway"] = 120,
|
||||
["de:living_street"] = 7,
|
||||
["ru:living_street"] = 20,
|
||||
["ru:urban"] = 60,
|
||||
["ua:urban"] = 60,
|
||||
["at:rural"] = 100,
|
||||
["de:rural"] = 100,
|
||||
["at:trunk"] = 100,
|
||||
["cz:trunk"] = 0,
|
||||
["ro:trunk"] = 100,
|
||||
["cz:motorway"] = 0,
|
||||
["de:motorway"] = 0,
|
||||
["ru:motorway"] = 110,
|
||||
["gb:nsl_single"] = (60*1609)/1000,
|
||||
["gb:nsl_dual"] = (70*1609)/1000,
|
||||
["gb:motorway"] = (70*1609)/1000,
|
||||
["uk:nsl_single"] = (60*1609)/1000,
|
||||
["uk:nsl_dual"] = (70*1609)/1000,
|
||||
["uk:motorway"] = (70*1609)/1000,
|
||||
["nl:rural"] = 80,
|
||||
["nl:trunk"] = 100,
|
||||
["none"] = 140
|
||||
}
|
||||
}
|
||||
|
||||
function get_name_suffix_list(vector)
|
||||
for index,suffix in ipairs(profile.suffix_list) do
|
||||
vector:Add(suffix)
|
||||
end
|
||||
end
|
||||
|
||||
function get_restrictions(vector)
|
||||
for i,v in ipairs(profile.restrictions) do
|
||||
vector:Add(v)
|
||||
end
|
||||
end
|
||||
|
||||
function node_function (node, result)
|
||||
-- parse access and barrier tags
|
||||
local access = find_access_tag(node, profile.access_tags_hierarchy)
|
||||
if access then
|
||||
if profile.access_tag_blacklist[access] then
|
||||
result.barrier = true
|
||||
end
|
||||
else
|
||||
local barrier = node:get_value_by_key("barrier")
|
||||
if barrier then
|
||||
-- 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 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 way_function(way, result)
|
||||
-- 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
|
||||
|
||||
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
|
||||
'handle_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
|
||||
'handle_blocked_ways',
|
||||
|
||||
-- determine access status by checking our hierarchy of
|
||||
-- access tags, e.g: motorcar, motor_vehicle, vehicle
|
||||
'handle_access',
|
||||
|
||||
-- check whether forward/backward directions are routable
|
||||
'handle_oneway',
|
||||
|
||||
-- check whether forward/backward directions are routable
|
||||
'handle_destinations',
|
||||
|
||||
-- check whether we're using a special transport mode
|
||||
'handle_ferries',
|
||||
'handle_movables',
|
||||
|
||||
-- handle service road restrictions
|
||||
'handle_service',
|
||||
|
||||
-- handle hov
|
||||
'handle_hov',
|
||||
|
||||
-- compute speed taking into account way type, maxspeed tags, etc.
|
||||
'handle_speed',
|
||||
'handle_surface',
|
||||
'handle_maxspeed',
|
||||
'handle_penalties',
|
||||
|
||||
-- handle turn lanes and road classification, used for guidance
|
||||
'handle_turn_lanes',
|
||||
'handle_classification',
|
||||
|
||||
-- handle various other flags
|
||||
-- 'handle_roundabouts',
|
||||
'handle_startpoint',
|
||||
|
||||
-- set name, ref and pronunciation
|
||||
'handle_names',
|
||||
|
||||
-- set weight properties of the way
|
||||
'handle_weights'
|
||||
}
|
||||
|
||||
Handlers.run(handlers,way,result,data,profile)
|
||||
end
|
||||
|
||||
function turn_function (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 = profile.turn_bias
|
||||
|
||||
if turn.turn_type ~= turn_type.no_turn then
|
||||
if turn.angle >= 0 then
|
||||
turn.duration = turn_penalty / (1 + math.exp( -((13 / turn_bias) * turn.angle/180 - 6.5*turn_bias)))
|
||||
else
|
||||
turn.duration = turn_penalty / (1 + math.exp( -((13 * turn_bias) * -turn.angle/180 - 6.5/turn_bias)))
|
||||
end
|
||||
|
||||
if turn.direction_modifier == direction_modifier.u_turn then
|
||||
turn.duration = turn.duration + profile.u_turn_penalty
|
||||
end
|
||||
|
||||
if turn.has_traffic_light then
|
||||
turn.duration = turn.duration + profile.traffic_light_penalty
|
||||
end
|
||||
|
||||
-- for distance based routing we don't want to have penalties based on turn angle
|
||||
if properties.weight_name == 'distance' then
|
||||
turn.weight = 0
|
||||
else
|
||||
turn.weight = turn.duration
|
||||
end
|
||||
if 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 = turn.weight + profile.restricted_penalty
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
11
osrm/start_server.sh
Normal file
11
osrm/start_server.sh
Normal file
|
@ -0,0 +1,11 @@
|
|||
#!/bin/bash
|
||||
IP="37.192.131.144"
|
||||
PORT=5000
|
||||
PATH="./pbf/"
|
||||
REGION="siberian-fed-district-latest"
|
||||
|
||||
while :
|
||||
do
|
||||
osrm-routed -i $IP -p $PORT "$PATH/$REGION.osrm"
|
||||
sleep 600
|
||||
done
|
Loading…
Add table
Add a link
Reference in a new issue