diff --git a/profiles/bicycle.lua b/profiles/bicycle.lua index ad041b1c0..774e7d840 100644 --- a/profiles/bicycle.lua +++ b/profiles/bicycle.lua @@ -1,97 +1,12 @@ api_version = 1 -- Bicycle profile - local find_access_tag = require("lib/access").find_access_tag +local Set = require('lib/set') +local Sequence = require('lib/sequence') local limit = require("lib/maxspeed").limit local set_classification = require("lib/guidance").set_classification --- Begin of globals -barrier_whitelist = { [""] = true, ["cycle_barrier"] = true, ["bollard"] = true, ["entrance"] = true, ["cattle_grid"] = true, ["border_control"] = true, ["toll_booth"] = true, ["sally_port"] = true, ["gate"] = true, ["no"] = true, ["block"] = true } -access_tag_whitelist = { ["yes"] = true, ["permissive"] = true, ["designated"] = true } -access_tag_blacklist = { ["no"] = true, ["private"] = true, ["agricultural"] = true, ["forestry"] = true, ["delivery"] = true } -access_tags_hierarchy = { "bicycle", "vehicle", "access" } -cycleway_tags = {["track"]=true,["lane"]=true,["opposite"]=true,["opposite_lane"]=true,["opposite_track"]=true,["share_busway"]=true,["sharrow"]=true,["shared"]=true } -restrictions = { "bicycle" } -unsafe_highway_list = { ["primary"] = true, ["secondary"] = true, ["tertiary"] = true, ["primary_link"] = true, ["secondary_link"] = true, ["tertiary_link"] = true} - -local default_speed = 15 -local walking_speed = 6 - -bicycle_speeds = { - ["cycleway"] = default_speed, - ["primary"] = default_speed, - ["primary_link"] = default_speed, - ["secondary"] = default_speed, - ["secondary_link"] = default_speed, - ["tertiary"] = default_speed, - ["tertiary_link"] = default_speed, - ["residential"] = default_speed, - ["unclassified"] = default_speed, - ["living_street"] = default_speed, - ["road"] = default_speed, - ["service"] = default_speed, - ["track"] = 12, - ["path"] = 12 - --["footway"] = 12, - --["pedestrian"] = 12, -} - -pedestrian_speeds = { - ["footway"] = walking_speed, - ["pedestrian"] = walking_speed, - ["steps"] = 2 -} - -railway_speeds = { - ["train"] = 10, - ["railway"] = 10, - ["subway"] = 10, - ["light_rail"] = 10, - ["monorail"] = 10, - ["tram"] = 10 -} - -platform_speeds = { - ["platform"] = walking_speed -} - -amenity_speeds = { - ["parking"] = 10, - ["parking_entrance"] = 10 -} - -man_made_speeds = { - ["pier"] = walking_speed -} - -route_speeds = { - ["ferry"] = 5 -} - -bridge_speeds = { - ["movable"] = 5 -} - -surface_speeds = { - ["asphalt"] = default_speed, - ["cobblestone:flattened"] = 10, - ["paving_stones"] = 10, - ["compacted"] = 10, - ["cobblestone"] = 6, - ["unpaved"] = 6, - ["fine_gravel"] = 6, - ["gravel"] = 6, - ["pebblestone"] = 6, - ["ground"] = 6, - ["dirt"] = 6, - ["earth"] = 6, - ["grass"] = 6, - ["mud"] = 3, - ["sand"] = 3, - ["sett"] = 10 -} - -- these need to be global because they are accesed externaly properties.max_speed_for_map_matching = 110/3.6 -- kmph -> m/s properties.use_turn_restrictions = false @@ -99,16 +14,157 @@ properties.continue_straight_at_waypoint = false properties.weight_name = 'duration' --properties.weight_name = 'cyclability' -local obey_oneway = true -local ignore_areas = true -local traffic_light_penalty = 2 -local u_turn_penalty = 20 -local turn_penalty = 6 -local turn_bias = 1.4 --- reduce the driving speed by 30% for unsafe roads --- local safety_penalty = 0.7 -local safety_penalty = 1.0 -local use_public_transport = true + +local default_speed = 15 +local walking_speed = 6 + +local profile = { + default_mode = mode.cycling, + default_speed = 15, + oneway_handling = true, + + traffic_light_penalty = 2, + u_turn_penalty = 20, + turn_penalty = 6, + turn_bias = 1.4, + + -- reduce the driving speed by 30% for unsafe roads + -- local safety_penalty = 0.7, + safety_penalty = 1.0, + use_public_transport = true, + + barrier_whitelist = Set { + 'cycle_barrier', + 'bollard', + 'entrance', + 'cattle_grid', + 'border_control', + 'toll_booth', + 'sally_port', + 'gate', + 'no', + 'block' + }, + + access_tag_whitelist = Set { + 'yes', + 'permissive', + 'designated' + }, + + access_tag_blacklist = Set { + 'no', + 'private', + 'agricultural', + 'forestry', + 'delivery' + }, + + access_tags_hierarchy = Sequence { + 'bicycle', + 'vehicle', + 'access' + }, + + restrictions = Set { + 'bicycle' + }, + + cycleway_tags = Set { + 'track', + 'lane', + 'opposite', + 'opposite_lane', + 'opposite_track', + 'share_busway', + 'sharrow', + 'shared' + }, + + unsafe_highway_list = Set { + 'primary', + 'secondary', + 'tertiary', + 'primary_link', + 'secondary_link', + 'tertiary_link' + }, + + bicycle_speeds = { + cycleway = default_speed, + primary = default_speed, + primary_link = default_speed, + secondary = default_speed, + secondary_link = default_speed, + tertiary = default_speed, + tertiary_link = default_speed, + residential = default_speed, + unclassified = default_speed, + living_street = default_speed, + road = default_speed, + service = default_speed, + track = 12, + path = 12 + --footway = 12, + --pedestrian = 12, + }, + + pedestrian_speeds = { + footway = walking_speed, + pedestrian = walking_speed, + steps = 2 + }, + + railway_speeds = { + train = 10, + railway = 10, + subway = 10, + light_rail = 10, + monorail = 10, + tram = 10 + }, + + platform_speeds = { + platform = walking_speed + }, + + amenity_speeds = { + parking = 10, + parking_entrance = 10 + }, + + man_made_speeds = { + pier = walking_speed + }, + + route_speeds = { + ferry = 5 + }, + + bridge_speeds = { + movable = 5 + }, + + surface_speeds = { + asphalt = default_speed, + ["cobblestone:flattened"] = 10, + paving_stones = 10, + compacted = 10, + cobblestone = 6, + unpaved = 6, + fine_gravel = 6, + gravel = 6, + pebblestone = 6, + ground = 6, + dirt = 6, + earth = 6, + grass = 6, + mud = 3, + sand = 3, + sett = 10 + } +} + local function parse_maxspeed(source) if not source then @@ -125,7 +181,7 @@ local function parse_maxspeed(source) end function get_restrictions(vector) - for i,v in ipairs(restrictions) do + for i,v in ipairs(profile.restrictions) do vector:Add(v) end end @@ -135,17 +191,17 @@ function node_function (node, result) local highway = node:get_value_by_key("highway") local is_crossing = highway and highway == "crossing" - local access = find_access_tag(node, access_tags_hierarchy) + local access = find_access_tag(node, profile.access_tags_hierarchy) if access and access ~= "" then -- access restrictions on crossing nodes are not relevant for -- the traffic on the road - if access_tag_blacklist[access] and not is_crossing then + if profile.access_tag_blacklist[access] and not is_crossing then result.barrier = true end else local barrier = node:get_value_by_key("barrier") if barrier and "" ~= barrier then - if not barrier_whitelist[barrier] then + if not profile.barrier_whitelist[barrier] then result.barrier = true end end @@ -169,7 +225,7 @@ function way_function (way, result) local bridge = way:get_value_by_key("bridge") if (not highway or highway == '') and (not route or route == '') and - (not use_public_transport or not railway or railway=='') and + (not profile.use_public_transport or not railway or railway=='') and (not amenity or amenity=='') and (not man_made or man_made=='') and (not public_transport or public_transport=='') and @@ -184,8 +240,8 @@ function way_function (way, result) end -- access - local access = find_access_tag(way, access_tags_hierarchy) - if access and access_tag_blacklist[access] then + local access = find_access_tag(way, profile.access_tags_hierarchy) + if access and profile.access_tag_blacklist[access] then return end @@ -232,7 +288,7 @@ function way_function (way, result) end -- speed - local bridge_speed = bridge_speeds[bridge] + local bridge_speed = profile.bridge_speeds[bridge] if (bridge_speed and bridge_speed > 0) then highway = bridge if duration and durationIsValid(duration) then @@ -240,42 +296,42 @@ function way_function (way, result) end result.forward_speed = bridge_speed result.backward_speed = bridge_speed - elseif route_speeds[route] then + elseif profile.route_speeds[route] then -- ferries (doesn't cover routes tagged using relations) result.forward_mode = mode.ferry result.backward_mode = mode.ferry if duration and durationIsValid(duration) then result.duration = math.max( 1, parseDuration(duration) ) else - result.forward_speed = route_speeds[route] - result.backward_speed = route_speeds[route] + result.forward_speed = profile.route_speeds[route] + result.backward_speed = profile.route_speeds[route] end -- public transport - elseif use_public_transport and railway and platform_speeds[railway] then + elseif profile.use_public_transport and railway and profile.platform_speeds[railway] then -- railway platforms (old tagging scheme) - result.forward_speed = platform_speeds[railway] - result.backward_speed = platform_speeds[railway] - elseif use_public_transport and platform_speeds[public_transport] then + result.forward_speed = profile.platform_speeds[railway] + result.backward_speed = profile.platform_speeds[railway] + elseif profile.use_public_transport and profile.platform_speeds[public_transport] then -- public_transport platforms (new tagging platform) - result.forward_speed = platform_speeds[public_transport] - result.backward_speed = platform_speeds[public_transport] - elseif use_public_transport and railway and railway_speeds[railway] then + result.forward_speed = profile.platform_speeds[public_transport] + result.backward_speed = profile.platform_speeds[public_transport] + elseif profile.use_public_transport and railway and profile.railway_speeds[railway] then result.forward_mode = mode.train result.backward_mode = mode.train -- railways - if (not access and highway) or access_tag_whitelist[access] then - result.forward_speed = railway_speeds[railway] - result.backward_speed = railway_speeds[railway] + if (not access and highway) or profile.access_tag_whitelist[access] then + result.forward_speed = profile.railway_speeds[railway] + result.backward_speed = profile.railway_speeds[railway] end - elseif amenity and amenity_speeds[amenity] then + elseif amenity and profile.amenity_speeds[amenity] then -- parking areas - result.forward_speed = amenity_speeds[amenity] - result.backward_speed = amenity_speeds[amenity] - elseif bicycle_speeds[highway] then + result.forward_speed = profile.amenity_speeds[amenity] + result.backward_speed = profile.amenity_speeds[amenity] + elseif profile.bicycle_speeds[highway] then -- regular ways - result.forward_speed = bicycle_speeds[highway] - result.backward_speed = bicycle_speeds[highway] - elseif access and access_tag_whitelist[access] then + result.forward_speed = profile.bicycle_speeds[highway] + result.backward_speed = profile.bicycle_speeds[highway] + elseif access and profile.access_tag_whitelist[access] then -- unknown way, but valid access tag result.forward_speed = default_speed result.backward_speed = default_speed @@ -283,16 +339,16 @@ function way_function (way, result) -- biking not allowed, maybe we can push our bike? -- essentially requires pedestrian profiling, for example foot=no mean we can't push a bike if foot ~= 'no' and (junction ~= "roundabout" and junction ~= "circular") then - if pedestrian_speeds[highway] then + if profile.pedestrian_speeds[highway] then -- pedestrian-only ways and areas - result.forward_speed = pedestrian_speeds[highway] - result.backward_speed = pedestrian_speeds[highway] + result.forward_speed = profile.pedestrian_speeds[highway] + result.backward_speed = profile.pedestrian_speeds[highway] result.forward_mode = mode.pushing_bike result.backward_mode = mode.pushing_bike - elseif man_made and man_made_speeds[man_made] then + elseif man_made and profile.man_made_speeds[man_made] then -- man made structures - result.forward_speed = man_made_speeds[man_made] - result.backward_speed = man_made_speeds[man_made] + result.forward_speed = profile.man_made_speeds[man_made] + result.backward_speed = profile.man_made_speeds[man_made] result.forward_mode = mode.pushing_bike result.backward_mode = mode.pushing_bike elseif foot == 'yes' then @@ -330,20 +386,20 @@ function way_function (way, result) if impliedOneway then result.forward_mode = mode.inaccessible result.backward_mode = mode.cycling - result.backward_speed = bicycle_speeds["cycleway"] + result.backward_speed = profile.bicycle_speeds["cycleway"] end - elseif cycleway_left and cycleway_tags[cycleway_left] and cycleway_right and cycleway_tags[cycleway_right] then + elseif cycleway_left and profile.cycleway_tags[cycleway_left] and cycleway_right and profile.cycleway_tags[cycleway_right] then -- prevent implied - elseif cycleway_left and cycleway_tags[cycleway_left] then + elseif cycleway_left and profile.cycleway_tags[cycleway_left] then if impliedOneway then result.forward_mode = mode.inaccessible result.backward_mode = mode.cycling - result.backward_speed = bicycle_speeds["cycleway"] + result.backward_speed = profile.bicycle_speeds["cycleway"] end - elseif cycleway_right and cycleway_tags[cycleway_right] then + elseif cycleway_right and profile.cycleway_tags[cycleway_right] then if impliedOneway then result.forward_mode = mode.cycling - result.backward_speed = bicycle_speeds["cycleway"] + result.backward_speed = profile.bicycle_speeds["cycleway"] result.backward_mode = mode.inaccessible end elseif oneway == "-1" then @@ -353,7 +409,7 @@ function way_function (way, result) end -- pushing bikes - if bicycle_speeds[highway] or pedestrian_speeds[highway] then + if profile.bicycle_speeds[highway] or profile.pedestrian_speeds[highway] then if foot ~= "no" and junction ~= "roundabout" and junction ~= "circular" then if result.backward_mode == mode.inaccessible then result.backward_speed = walking_speed @@ -366,15 +422,15 @@ function way_function (way, result) end -- cycleways - if cycleway and cycleway_tags[cycleway] then - result.forward_speed = bicycle_speeds["cycleway"] - result.backward_speed = bicycle_speeds["cycleway"] - elseif cycleway_left and cycleway_tags[cycleway_left] then - result.forward_speed = bicycle_speeds["cycleway"] - result.backward_speed = bicycle_speeds["cycleway"] - elseif cycleway_right and cycleway_tags[cycleway_right] then - result.forward_speed = bicycle_speeds["cycleway"] - result.backward_speed = bicycle_speeds["cycleway"] + if cycleway and profile.cycleway_tags[cycleway] then + result.forward_speed = profile.bicycle_speeds["cycleway"] + result.backward_speed = profile.bicycle_speeds["cycleway"] + elseif cycleway_left and profile.cycleway_tags[cycleway_left] then + result.forward_speed = profile.bicycle_speeds["cycleway"] + result.backward_speed = profile.bicycle_speeds["cycleway"] + elseif cycleway_right and profile.cycleway_tags[cycleway_right] then + result.forward_speed = profile.bicycle_speeds["cycleway"] + result.backward_speed = profile.bicycle_speeds["cycleway"] end -- dismount @@ -388,9 +444,9 @@ function way_function (way, result) -- reduce speed on bad surfaces local surface = way:get_value_by_key("surface") - if surface and surface_speeds[surface] then - result.forward_speed = math.min(surface_speeds[surface], result.forward_speed) - result.backward_speed = math.min(surface_speeds[surface], result.backward_speed) + 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 -- set the road classification based on guidance globals configuration @@ -400,25 +456,25 @@ function way_function (way, result) limit( result, maxspeed, maxspeed_forward, maxspeed_backward ) -- convert duration into cyclability - local is_unsafe = safety_penalty < 1 and unsafe_highway_list[highway] + local is_unsafe = profile.safety_penalty < 1 and profile.unsafe_highway_list[highway] if result.forward_speed > 0 then -- convert from km/h to m/s result.forward_rate = result.forward_speed / 3.6; if is_unsafe then - result.forward_rate = result.forward_rate * safety_penalty + result.forward_rate = result.forward_rate * profile.safety_penalty end end if result.backward_speed > 0 then -- convert from km/h to m/s result.backward_rate = result.backward_speed / 3.6; if is_unsafe then - result.backward_rate = result.backward_rate * safety_penalty + result.backward_rate = result.backward_rate * profile.safety_penalty end end if result.duration > 0 then result.weight = result.duration; if is_unsafe then - result.weight = result.weight * (1+safety_penalty) + result.weight = result.weight * (1+profile.safety_penalty) end end end @@ -427,16 +483,16 @@ function turn_function(turn) -- compute turn penalty as angle^2, with a left/right bias local normalized_angle = turn.angle / 90.0 if normalized_angle >= 0.0 then - turn.duration = normalized_angle * normalized_angle * turn_penalty / turn_bias + turn.duration = normalized_angle * normalized_angle * profile.turn_penalty / profile.turn_bias else - turn.duration = normalized_angle * normalized_angle * turn_penalty * turn_bias + turn.duration = normalized_angle * normalized_angle * profile.turn_penalty * profile.turn_bias end if turn.direction_modifier == direction_modifier.uturn then - turn.duration = turn.duration + u_turn_penalty + turn.duration = turn.duration + profile.u_turn_penalty end if turn.has_traffic_light then - turn.duration = turn.duration + traffic_light_penalty + turn.duration = turn.duration + profile.traffic_light_penalty end end diff --git a/profiles/lib/profile_debugger.lua b/profiles/lib/profile_debugger.lua index eb85fa1f3..1f5b150dd 100644 --- a/profiles/lib/profile_debugger.lua +++ b/profiles/lib/profile_debugger.lua @@ -121,6 +121,7 @@ function Debug.way_function(way,result) 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)