diff --git a/CHANGELOG.md b/CHANGELOG.md index 5adb658d3..cb02bd9b9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ - FIXED: Properly calculate annotations for speeds, durations and distances when waypoints are used with mapmatching [#4949](https://github.com/Project-OSRM/osrm-backend/pull/4949) - Profile: - CHANGED #4929: Handle oneways in get_forward_backward_by_key [#4929](https://github.com/Project-OSRM/osrm-backend/pull/4929) + - FIXED #4943: Do not route against oneway road if there is a cycleway in the wrong direction; also review bike profile [#4943](https://github.com/Project-OSRM/osrm-backend/issues/4943) - Guidance: - CHANGED #4929: Don't use obviousness for links bifurcations [#4929](https://github.com/Project-OSRM/osrm-backend/pull/4929) - FIXED #4929: Adjust Straight direction modifiers of side roads in driveway handler [#4929](https://github.com/Project-OSRM/osrm-backend/pull/4929) @@ -21,7 +22,6 @@ - Performance - FIXED: Speed up response time when lots of legs exist and geojson is used with `steps=true` [#4936](https://github.com/Project-OSRM/osrm-backend/pull/4936) - # 5.16.0 - Changes from 5.15.2: - Guidance @@ -37,6 +37,7 @@ - ADDED #4775: Exposes more information to the turn function, now being able to set turn weights with highway and access information of the turn as well as other roads at the intersection [#4775](https://github.com/Project-OSRM/osrm-backend/issues/4775) - FIXED #4763: Add support for non-numerical units in car profile for maxheight [#4763](https://github.com/Project-OSRM/osrm-backend/issues/4763) - ADDED #4872: Handling of `barrier=height_restrictor` nodes [#4872](https://github.com/Project-OSRM/osrm-backend/pull/4872) + # 5.15.2 - Changes from 5.15.1: - Features: diff --git a/features/bicycle/cycleway.feature b/features/bicycle/cycleway.feature index f836ef8bf..c04d7aabd 100644 --- a/features/bicycle/cycleway.feature +++ b/features/bicycle/cycleway.feature @@ -46,12 +46,14 @@ Feature: Bike - Cycle tracks/lanes | primary | | | | x | x | | motorway | | | | | | | motorway | track | | | x | | - | motorway | opposite | | | | x | - | motorway | | track | | | x | - | motorway | | opposite | | | x | + | motorway | opposite | | | x | x | + | motorway | | track | | x | | + | motorway | | opposite | | x | x | | motorway | | | track | x | | - | motorway | | | opposite | x | | - | motorway | | track | track | x | x | + | motorway | | | opposite | x | x | + # motorways are implicit oneways and cycleway tracks next to oneways always + # follow the oneway direction (unless tagged as opposite) + | motorway | | track | track | x | | | motorway | | opposite | opposite | x | x | | motorway | | track | opposite | x | x | | motorway | | opposite | track | x | x | @@ -92,6 +94,6 @@ Feature: Bike - Cycle tracks/lanes Then routability should be | highway | cycleway | oneway | forw | backw | | motorway | track | yes | 15 km/h | | - | residential | track | yes | 15 km/h | 6 km/h +-1 | - | cycleway | track | yes | 15 km/h | 6 km/h +-1 | - | footway | track | yes | 15 km/h | 6 km/h +-1 | + | residential | track | yes | 15 km/h | 4 km/h +-1 | + | cycleway | track | yes | 15 km/h | 4 km/h +-1 | + | footway | track | yes | 15 km/h | 4 km/h +-1 | diff --git a/features/bicycle/oneway.feature b/features/bicycle/oneway.feature index 842ac725e..4099a434c 100644 --- a/features/bicycle/oneway.feature +++ b/features/bicycle/oneway.feature @@ -141,5 +141,12 @@ Feature: Bike - Oneway streets | highway | oneway | cycleway:left | cycleway:right | forw | backw | | primary | yes | | | cycling | pushing bike | | primary | yes | | track | cycling | pushing bike | - | primary | yes | track | | cycling | cycling | - | primary | yes | track | track | cycling | cycling | \ No newline at end of file + | primary | yes | track | | cycling | pushing bike | + | primary | yes | track | track | cycling | pushing bike | + + Scenario: Bike - Left/right cycleways on any oneways + Then routability should be + | foot | oneway | cycleway:left | cycleway:right | forw | backw | + | no | yes | track | | cycling | | + | yes | yes | track | | cycling | pushing bike | + | yes | -1 | track | | pushing bike | cycling | \ No newline at end of file diff --git a/features/bicycle/safety.feature b/features/bicycle/safety.feature index b09099c09..bae5ba298 100644 --- a/features/bicycle/safety.feature +++ b/features/bicycle/safety.feature @@ -19,7 +19,7 @@ Feature: Bicycle - Adds penalties to unsafe roads | tertiary_link | | 15 km/h | 15 km/h | 3.3 | 3.3 | | residential | | 15 km/h | 15 km/h | 4.2 | 4.2 | | cycleway | | 15 km/h | 15 km/h | 4.2 | 4.2 | - | footway | | 6 km/h +-1 | 6 km/h +-1 | 1.7 | 1.7 | + | footway | | 4 km/h +-1 | 4 km/h +-1 | 1.1 | 1.1 | Scenario: Bike - Apply no penalties to ways with cycleways Then routability should be @@ -59,8 +59,8 @@ Feature: Bicycle - Adds penalties to unsafe roads | tertiary_link | track | | 15 km/h | 15 km/h | 4.2 | 3.3 | | residential | track | | 15 km/h | 15 km/h | 4.2 | 4.2 | | cycleway | track | | 15 km/h | 15 km/h | 4.2 | 4.2 | - | footway | track | | 15 km/h | 6 km/h +-1 | 4.2 | 1.7 | - | motorway | | track | | 15 km/h | | 4.2 | + | footway | track | | 15 km/h | 4 km/h +-1 | 4.2 | 1.1 | + | motorway | | track | 15 km/h | | 4.2 | | | primary | | track | 15 km/h | 15 km/h | 2.9 | 4.2 | | secondary | | track | 15 km/h | 15 km/h | 3.1 | 4.2 | | tertiary | | track | 15 km/h | 15 km/h | 3.3 | 4.2 | @@ -69,7 +69,7 @@ Feature: Bicycle - Adds penalties to unsafe roads | tertiary_link | | track | 15 km/h | 15 km/h | 3.3 | 4.2 | | residential | | track | 15 km/h | 15 km/h | 4.2 | 4.2 | | cycleway | | track | 15 km/h | 15 km/h | 4.2 | 4.2 | - | footway | | track | 6 km/h +-1 | 15 km/h | 1.7 | 4.2 | + | footway | | track | 4 km/h +-1 | 15 km/h | 1.1 | 4.2 | | motorway | lane | | 15 km/h | | 4.2 | | | primary | lane | | 15 km/h | 15 km/h | 4.2 | 2.9 | | secondary | lane | | 15 km/h | 15 km/h | 4.2 | 3.1 | @@ -79,8 +79,8 @@ Feature: Bicycle - Adds penalties to unsafe roads | tertiary_link | lane | | 15 km/h | 15 km/h | 4.2 | 3.3 | | residential | lane | | 15 km/h +-1 | 15 km/h +-1 | 4.2 | 4.2 | | cycleway | lane | | 15 km/h | 15 km/h | 4.2 | 4.2 | - | footway | lane | | 15 km/h | 6 km/h +-1 | 4.2 | 1.7 | - | motorway | | lane | | 15 km/h | | 4.2 | + | footway | lane | | 15 km/h | 4 km/h +-1 | 4.2 | 1.1 | + | motorway | | lane | 15 km/h | | 4.2 | | | primary | | lane | 15 km/h | 15 km/h | 2.9 | 4.2 | | secondary | | lane | 15 km/h +-1 | 15 km/h +-1 | 3.1 | 4.2 | | tertiary | | lane | 15 km/h | 15 km/h | 3.3 | 4.2 | @@ -89,10 +89,10 @@ Feature: Bicycle - Adds penalties to unsafe roads | tertiary_link | | lane | 15 km/h | 15 km/h | 3.3 | 4.2 | | residential | | lane | 15 km/h | 15 km/h | 4.2 | 4.2 | | cycleway | | lane | 15 km/h | 15 km/h | 4.2 | 4.2 | - | footway | | lane | 6 km/h +-1 | 15 km/h | 1.7 | 4.2 | + | footway | | lane | 4 km/h +-1 | 15 km/h | 1.1 | 4.2 | | motorway | shared_lane | | 15 km/h | | 4.2 | | | primary | shared_lane | | 15 km/h | 15 km/h | 4.2 | 2.9 | - | motorway | | shared_lane | | 15 km/h | | 4.2 | + | motorway | | shared_lane | 15 km/h | | 4.2 | | | primary | | shared_lane | 15 km/h | 15 km/h | 2.9 | 4.2 | @@ -101,4 +101,4 @@ Feature: Bicycle - Adds penalties to unsafe roads | highway | cycleway | forw | backw | forw_rate | backw_rate | | tertiary | shared_lane | 15 km/h | 15 km/h | 4.2 | 4.2 | | tertiary | lane | 15 km/h | 15 km/h | 4.2 | 4.2 | - | tertiary | opposite | 15 km/h | 15 km/h | 3.3 | 4.2 | + | tertiary | opposite | 15 km/h | 15 km/h | 3.3 | 3.3 | diff --git a/features/bicycle/surface.feature b/features/bicycle/surface.feature index 24e172c78..1a4b5763a 100644 --- a/features/bicycle/surface.feature +++ b/features/bicycle/surface.feature @@ -54,6 +54,6 @@ Feature: Bike - Surfaces When I route I should get | from | to | route | modes | speed | | a | b | ab,ab | cycling,cycling | 15 km/h | - | b | a | ab,ab | pushing bike,pushing bike | 6 km/h | - | c | d | cd,cd | pushing bike,pushing bike | 6 km/h | - | d | c | cd,cd | pushing bike,pushing bike | 6 km/h | + | b | a | ab,ab | pushing bike,pushing bike | 4 km/h | + | c | d | cd,cd | pushing bike,pushing bike | 4 km/h | + | d | c | cd,cd | pushing bike,pushing bike | 4 km/h | diff --git a/features/guidance/bicycle-sliproads.feature b/features/guidance/bicycle-sliproads.feature index 0b297155d..347476b45 100644 --- a/features/guidance/bicycle-sliproads.feature +++ b/features/guidance/bicycle-sliproads.feature @@ -22,11 +22,11 @@ Feature: Bike - Mode flag | c | traffic_signals | And the ways - | nodes | highway | name | oneway:bicycle | - | abcd | cycleway | street | | - | eb | path | | yes | - | icef | tertiary | road | | - | geh | secondary | street | | + | nodes | highway | name | oneway:bicycle | maxspeed:forward | + | abcd | cycleway | street | | 4 km/h | + | eb | path | | yes | | + | icef | tertiary | road | | 4 km/h | + | geh | secondary | street | | | When I route I should get | waypoints | route | turns | diff --git a/profiles/bicycle.lua b/profiles/bicycle.lua index 4014b02b0..cb041bdd6 100644 --- a/profiles/bicycle.lua +++ b/profiles/bicycle.lua @@ -1,6 +1,6 @@ -- Bicycle profile -api_version = 2 +api_version = 4 Set = require('lib/set') Sequence = require('lib/sequence') @@ -10,7 +10,7 @@ limit = require("lib/maxspeed").limit function setup() local default_speed = 15 - local walking_speed = 6 + local walking_speed = 4 return { properties = { @@ -21,7 +21,8 @@ function setup() process_call_tagless_node = false, max_speed_for_map_matching = 110/3.6, -- kmph -> m/s use_turn_restrictions = false, - continue_straight_at_waypoint = false + continue_straight_at_waypoint = false, + mode_change_penalty = 30, }, default_mode = mode.cycling, @@ -93,15 +94,18 @@ function setup() cycleway_tags = Set { 'track', 'lane', - 'opposite', - 'opposite_lane', - 'opposite_track', 'share_busway', 'sharrow', 'shared', 'shared_lane' }, + opposite_cycleway_tags = Set { + 'opposite', + 'opposite_lane', + 'opposite_track', + }, + -- reduce the driving speed by 30% for unsafe roads -- only used for cyclability metric unsafe_highway_list = { @@ -367,35 +371,53 @@ function handle_bicycle_tags(profile,way,result,data) end -- cycleway - local has_cycleway_left = false - local has_cycleway_right = false + local has_cycleway_forward = false + local has_cycleway_backward = false + local is_oneway = result.forward_mode ~= mode.inaccessible and result.backward_mode ~= mode.inaccessible and not implied_oneway + + -- cycleways on normal roads + if is_oneway then + if cycleway and profile.cycleway_tags[cycleway] then + has_cycleway_backward = true + has_cycleway_forward = true + end + if (cycleway_right and profile.cycleway_tags[cycleway_right]) or (cycleway_left and profile.opposite_cycleway_tags[cycleway_left]) then + has_cycleway_forward = true + end + if (cycleway_left and profile.cycleway_tags[cycleway_left]) or (cycleway_right and profile.opposite_cycleway_tags[cycleway_right]) then + has_cycleway_backward = true + end + else + local has_twoway_cycleway = (cycleway and profile.opposite_cycleway_tags[cycleway]) or (cycleway_right and profile.opposite_cycleway_tags[cycleway_right]) or (cycleway_left and profile.opposite_cycleway_tags[cycleway_left]) + local has_opposite_cycleway = (cycleway_left and profile.opposite_cycleway_tags[cycleway_left]) or (cycleway_right and profile.opposite_cycleway_tags[cycleway_right]) + local has_oneway_cycleway = (cycleway and profile.cycleway_tags[cycleway]) or (cycleway_right and profile.cycleway_tags[cycleway_right]) or (cycleway_left and profile.cycleway_tags[cycleway_left]) + + -- set cycleway even though it is an one-way if opposite is tagged + if has_twoway_cycleway then + has_cycleway_backward = true + has_cycleway_forward = true + elseif has_opposite_cycleway then + if not reverse then + has_cycleway_backward = true + else + has_cycleway_forward = true + end + elseif has_oneway_cycleway then + if not reverse then + has_cycleway_forward = true + else + has_cycleway_backward = true + end - if cycleway_left and profile.cycleway_tags[cycleway_left] then - has_cycleway_left = true - end - if cycleway_right and profile.cycleway_tags[cycleway_right] then - has_cycleway_right = true - end - if cycleway and string.find(cycleway, "opposite") == 1 then - if reverse then - has_cycleway_right = true - else - has_cycleway_left = true end - elseif cycleway and profile.cycleway_tags[cycleway] then - -- "cycleway" tag without left/right should not affect a direction - -- already forbidden by oneway tags - has_cycleway_left = result.backward_mode ~= mode.inaccessible - has_cycleway_right = result.forward_mode ~= mode.inaccessible end - - if has_cycleway_left then + if has_cycleway_backward then result.backward_mode = mode.cycling result.backward_speed = profile.bicycle_speeds["cycleway"] end - if has_cycleway_right then + if has_cycleway_forward then result.forward_mode = mode.cycling result.forward_speed = profile.bicycle_speeds["cycleway"] end @@ -473,8 +495,8 @@ function handle_bicycle_tags(profile,way,result,data) if profile.properties.weight_name == 'cyclability' then local safety_penalty = profile.unsafe_highway_list[data.highway] or 1. local is_unsafe = safety_penalty < 1 - local forward_is_unsafe = is_unsafe and not has_cycleway_right - local backward_is_unsafe = is_unsafe and not has_cycleway_left + local forward_is_unsafe = is_unsafe and not has_cycleway_forward + local backward_is_unsafe = is_unsafe and not has_cycleway_backward local is_undesireable = data.highway == "service" and profile.service_penalties[service] local forward_penalty = 1. local backward_penalty = 1. @@ -566,7 +588,7 @@ function process_turn(profile, turn) turn.duration = normalized_angle * normalized_angle * profile.turn_penalty * profile.turn_bias end - if turn.direction_modifier == direction_modifier.uturn then + if turn.is_u_turn then turn.duration = turn.duration + profile.properties.u_turn_penalty end @@ -576,6 +598,9 @@ function process_turn(profile, turn) if profile.properties.weight_name == 'cyclability' then turn.weight = turn.duration end + if turn.source_mode == mode.cycling and turn.target_mode ~= mode.cycling then + turn.weight = turn.weight + profile.properties.mode_change_penalty + end end return {