diff --git a/features/car/access.feature b/features/car/access.feature index bcc33c96a..2e989c8de 100644 --- a/features/car/access.feature +++ b/features/car/access.feature @@ -181,32 +181,42 @@ Feature: Car - Restricted access @hov Scenario: Car - designated HOV ways are rated low Then routability should be - | highway | hov | bothw | forw_rate | - | primary | designated | x | 2 | - | primary | yes | x | 18 | - | primary | no | x | 18 | + | highway | hov | bothw | forw_rate | backw_rate | + | primary | designated | x | 2 | 2 | + | primary | yes | x | 18 | 18 | + | primary | no | x | 18 | 18 | + + # Models: + # https://www.openstreetmap.org/way/124891268 + # https://www.openstreetmap.org/way/237173472 + @hov + Scenario: Car - I-66 use HOV-only roads with heavy penalty + Then routability should be + | highway | hov | hov:lanes | lanes | access | oneway | forw | backw | forw_rate | + | motorway | designated | designated\|designated\|designated | 3 | hov | yes | x | | 3 | + | motorway | lane | | 3 | designated | yes | x | | 25 | @hov - Scenario: Car - a way with all lanes HOV-designated is inaccessible by default (similar to hov=designated) + Scenario: Car - a way with all lanes HOV-designated is highly penalized by default (similar to hov=designated) Then routability should be - | highway | hov:lanes:forward | hov:lanes:backward | hov:lanes | oneway | forw | backw | - | primary | designated | designated | | | | | - | primary | | designated | | | x | | - | primary | designated | | | | | x | - | primary | designated\|designated | designated\|designated | | | | | - | primary | designated\|no | designated\|no | | | x | x | - | primary | yes\|no | yes\|no | | | x | x | - | primary | | | | | x | x | - | primary | designated | | | -1 | | x | - | primary | | designated | | -1 | | | - | primary | | | designated | yes | | | - | primary | | | designated | -1 | | | - | primary | | | designated\| | yes | x | | - | primary | | | designated\| | -1 | | x | - | primary | | | designated\|designated | yes | | | - | primary | | | designated\|designated | -1 | | | - | primary | | | designated\|yes | yes | x | | - | primary | | | designated\|no | -1 | | x | + | highway | hov:lanes:forward | hov:lanes:backward | hov:lanes | oneway | forw | backw | forw_rate | backw_rate | + | primary | designated | designated | | | x | x | 2 | 2 | + | primary | | designated | | | x | x | 18 | 2 | + | primary | designated | | | | x | x | 2 | 18 | + | primary | designated\|designated | designated\|designated | | | x | x | 2 | 2 | + | primary | designated\|no | designated\|no | | | x | x | 18 | 18 | + | primary | yes\|no | yes\|no | | | x | x | 18 | 18 | + | primary | | | | | x | x | 18 | 18 | + | primary | designated | | | -1 | | x | | 18 | + | primary | | designated | | -1 | | x | | 2 | + | primary | | | designated | yes | x | | 2 | | + | primary | | | designated | -1 | | x | | 2 | + | primary | | | designated\| | yes | x | | 18 | | + | primary | | | designated\| | -1 | | x | | 18 | + | primary | | | designated\|designated | yes | x | | 2 | | + | primary | | | designated\|designated | -1 | | x | | 2 | + | primary | | | designated\|yes | yes | x | | 18 | | + | primary | | | designated\|no | -1 | | x | | 18 | Scenario: Car - these toll roads always work Then routability should be diff --git a/profiles/car.lua b/profiles/car.lua index 113a5158e..74ec0964d 100644 --- a/profiles/car.lua +++ b/profiles/car.lua @@ -63,7 +63,8 @@ local profile = { 'vehicle', 'permissive', 'designated', - 'destination' + 'destination', + 'hov' -- we might filter hov out later depending on the avoid settings or add penalties }, access_tag_blacklist = Set { diff --git a/profiles/lib/handlers.lua b/profiles/lib/handlers.lua index 7af7e1685..e206723a1 100644 --- a/profiles/lib/handlers.lua +++ b/profiles/lib/handlers.lua @@ -173,7 +173,12 @@ 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 or properties.weight_name ~= 'routability' then + if not profile.avoid.hov_lanes then + return + end + + -- in this case we will use penalties instead of filtering out + if properties.weight_name == 'routability' then return end @@ -268,19 +273,28 @@ end 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 hov_penalty = 1.0 + local forward_hov_penalty = 1.0 + local backward_hov_penalty = 1.0 if profile.avoid.hov_lanes then local hov = way:get_value_by_key("hov") - local all_lanes_designated = Handlers.has_all_designated_hov_lanes(data.hov_lanes_forward) - if "designated" == hov or all_lanes_designated then - hov_penalty = 0.1 + if "designated" == hov then + forward_hov_penalty = 0.1 + backward_hov_penalty = 0.1 + else + data.hov_lanes_forward, data.hov_lanes_backward = Tags.get_forward_backward_by_key(way,data,'hov:lanes') + if Handlers.has_all_designated_hov_lanes(data.hov_lanes_forward) then + forward_hov_penalty = 0.1 + end + if Handlers.has_all_designated_hov_lanes(data.hov_lanes_backward) then + backward_hov_penalty = 0.1 + end end end 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] + service_penalty = profile.service_penalties[service] end local width_penalty = 1.0 @@ -316,17 +330,18 @@ function Handlers.handle_penalties(way,result,data,profile) sideroad_penalty = side_road_multiplier; end - local penalty = math.min(service_penalty, width_penalty, alternating_penalty, sideroad_penalty, hov_penalty) + local forward_penalty = math.min(service_penalty, width_penalty, alternating_penalty, sideroad_penalty, forward_hov_penalty) + local backward_penalty = math.min(service_penalty, width_penalty, alternating_penalty, sideroad_penalty, backward_hov_penalty) if properties.weight_name == 'routability' then if result.forward_speed > 0 then - result.forward_rate = (result.forward_speed * penalty) / 3.6 + result.forward_rate = (result.forward_speed * forward_penalty) / 3.6 end if result.backward_speed > 0 then - result.backward_rate = (result.backward_speed * penalty) / 3.6 + result.backward_rate = (result.backward_speed * backward_penalty) / 3.6 end if result.duration > 0 then - result.weight = result.duration / penalty + result.weight = result.duration / forward_penalty end end end