Permalink
Switch branches/tags
Nothing to show
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
874 lines (796 sloc) 35.6 KB
################################################################
# A BRouter profile suited for a streetbike #
################################################################
---context:global
# switch to choose if ferries are considered in routing
assign consider_ferries true
# switch road side we drive on
assign lefthandtraffic false
# switch to assume surfaces are wet
assign iswet false
assign turnInstructionMode 0
assign validForBikes 1
assign pass1coefficient 1
assign pass2coefficient -1
assign considerTurnRestrictions true
assign uphillcost 80
assign uphillcutoff 0.5
assign downhillcost 100
assign downhillcutoff 2.0
assign traffic_tier1 0.1
assign traffic_tier2 0.2
assign traffic_tier3 0.5
assign traffic_tier4 0.8
assign speed_tier1 0.2
assign speed_tier2 0.4
assign speed_tier3 0.6
assign speed_tier4 1.0
---context:way
################################################################
# A bunch of helper-stuff before the actual waycost logic #
################################################################
# Needed for some unknown reason, usualy only used for voice hints
assign priorityclassifier = if highway= then 1 else 0
# Determine if way is part of a cycleroute
assign is_cycleroute
or route_bicycle_rcn=yes
or route_bicycle_lcn=yes
or route_bicycle_icn=yes
or route_bicycle_ncn=yes
or lcn=yes
or rcn=yes
ncn=yes
assign is_cycleroute_other
or route_bicycle_=yes
or route_bicycle_radweit=yes
or route_bicycle_rcn=proposed
or route_bicycle_lcn=proposed
or route_bicycle_icn=proposed
or route_bicycle_ncn=proposed
or lcn=proposed
or rcn=proposed
ncn=proposed
# Determine if we are driving against a oneway
# Missing: cycleway:right/left:oneway=no, we are limited by brouter data here
# Step1: Determine motor traffic flow direction
# -1 means against OSM way direction, 0 means not a oneway, 1 means in OSM way direction, 2 means reversible
assign traffic_direction_global
# roundabouts imply oneway, according to wiki
if junction=roundabout then
if oneway=-1 then -1
else if oneway=reversible then 2
else 1
# motorways imply oneway, according to wiki
else if highway=motorway|motorway_link then
if oneway=-1 then -1
else if oneway=reversible then 2
else 1
else if ( not oneway= ) then
if oneway=yes|1|true then 1
else if oneway=-1 then -1
else if oneway=reversible then 2
else 0
else 0
# Step2: determine bike direction relative to motor traffic
# -1 means against, 0 means both simultaneously, 1 means with
assign bike_direction_relative
# this seems to be a rare tagging problem, actually oneway should always refer to OSM way direction, not traffic direction
if or oneway:bicycle=opposite bicycle=opposite then -1
# we check for simultaneously a bike way opposite and one in traffic direction
else if and ( or cycleway:left=opposite|opposite_lane|opposite_track cycleway:right=opposite|opposite_lane|opposite_track ) ( or ( and ( not cycleway= ) ( not cycleway=no|opposite|opposite_lane|opposite_track|none|proposed ) ) or ( and ( not cycleway:right= ) ( not cycleway:right=opposite_lane|sidepath|no|opposite_track|opposite ) ) ( and ( not cycleway:left= ) ( not cycleway:left=opposite_lane|sidepath|no|opposite_track|opposite ) ) ) then 0
# there is a bike lane that allows us to cycle against oneway traffic
else if ( or cycleway=opposite|opposite_lane|opposite_track or cycleway:left=opposite|opposite_lane|opposite_track cycleway:right=opposite|opposite_lane|opposite_track ) then -1
# no specific information about cycling direction, we have to go with the motor traffic
else 1
# Step3: determine bike direction, relative to the OSM way direction
# -1 means against, 0 means both simultaneously, 1 means with
assign bike_direction_global
# oneway:bicycle refers to the OSM way direction
if oneway:bicycle=no then 0
# not yet implemented in BRouter
# else if ( or cycleway:right:oneway=no cycleway:left:oneway=no ) then 0
else if oneway:bicycle=yes then 1
# we must go with the motor traffic
else if ( equal bike_direction_relative 1 ) then traffic_direction_global
# 1st leftover case: relative bike direction is against the motorcar traffic, we can go in both directions as cyclist
# 2nd leftover case: bikes can go in both directions anyways
else 0
# Step4: use allowed bike directions and BRouter reversedirection to determine if we are going against a oneway
assign badoneway =
# we can go either direction as cyclist, oneway is irrelevant
if ( equal bike_direction_global 0 ) then false
# bike direction is reversible, we are careful and avoid these ways
else if ( equal bike_direction_global 2 ) then true
# rest of the cases, compare bike direction to the brouter reversedirection value and see if we can use the way
else ( xor ( equal bike_direction_global 1 ) ( not reversedirection=yes ) )
# Determine if there is a cycleway
# Missing: cycleway:right/left:oneway=no, we are limited by brouter data here
assign hascycleway
# cycleway in both directions
if and ( not cycleway= ) ( not cycleway=left|right|no|none|opposite|proposed ) then true
else if
and ( and ( not cycleway:left= ) ( not cycleway:left=opposite|opposite_lane|opposite_track|no|sidepath ) ) ( and ( not cycleway:right= ) ( not cycleway:right=opposite|opposite_lane|opposite_track|no|sidepath ) )
then true
# not yet implemented in BRouter
# else if ( or cycleway:right:oneway=no cycleway:left:oneway=no ) then true
# not a cycleway anywhere
else if
and ( or cycleway= cycleway=no|none|proposed ) and ( or cycleway:left= cycleway:left=no|sidepath ) ( or cycleway:right= cycleway:right=no|sidepath )
then false
# oneway street stuff
else if ( and oneway=yes|true|1|-1 reversedirection=yes ) then
if and oneway=yes|true|1 ( or cycleway=opposite_lane|opposite_track or cycleway:left=opposite_lane|opposite_track cycleway:right=opposite_lane|opposite_track ) then true
else if and oneway=-1 ( or ( and ( not cycleway= ) ( not cycleway=left|right|no|none|opposite|proposed ) ) or ( and ( not cycleway:left= ) ( not cycleway:left=opposite|opposite_lane|opposite_track|no|sidepath ) ) ( and ( not cycleway:right= ) ( not cycleway:right=opposite|opposite_lane|opposite_track|no|sidepath ) ) ) then true
else false
else if ( and oneway=yes|true|1|-1 ( not reversedirection=yes ) ) then
if and oneway=yes|true|1 ( or ( and ( not cycleway= ) ( not cycleway=left|right|no|none|opposite|proposed ) ) or ( and ( not cycleway:left= ) ( not cycleway:left=opposite|opposite_lane|opposite_track|no|sidepath ) ) ( and ( not cycleway:right= ) ( not cycleway:right=opposite|opposite_lane|opposite_track|no|sidepath ) ) ) then true
else if and oneway=-1 ( or cycleway=opposite_lane|opposite_track or cycleway:left=opposite_lane|opposite_track cycleway:right=opposite_lane|opposite_track ) then true
else false
# twoway street stuff
else if xor reversedirection=yes lefthandtraffic then
if and ( not cycleway:left= ) ( not cycleway:left=opposite|opposite_lane|opposite_track|no|sidepath ) then true
else if cycleway=left then true
else false
else if xor ( not reversedirection=yes ) lefthandtraffic then
if and ( not cycleway:right= ) ( not cycleway:right=opposite|opposite_lane|opposite_track|no|sidepath ) then true
else if cycleway=right then true
else false
else false
# Determine access properties for vehicles
assign any_motoraccess
if motorcar=yes|destination|designated|permissive then true
else if motor_vehicle=yes|destination|designated|permissive then true
else if motorcycle=yes|destination|designated|permissive then true
else if and vehicle=yes|destination|designated|permissive not motor_vehicle=no|private|agricultural then true
else if hgv=yes|destination|designated|permissive then true
else if and access=yes|destination|designated|permissive not motor_vehicle=no|private|agricultural then true
else if motor_vehicle=no|private|agricultural then false
else if access=no|private|agricultural then false
else if (
or highway=residential|service|unclassified|road|living_street|rest_area|services
or highway=trunk|trunk_link|primary|primary_link|secondary|secondary_link|tertiary|tertiary_link
highway=driveway|mini_roundabout|turning_loop|unsurfaced )
then true
else false
assign bikeaccess
if ( not route=ferry ) then
if bicycle=yes|designated|permissive|destination|mtb then true
else if bicycle=no|dismount|private|use_sidepath then false
else if vehicle=yes|destination|permissive|designated then true
else if vehicle=no|agricultural|private then false
else if and indoor=yes not highway=cycleway then false
else if access=yes|permissive|destination|designated then true
else if access=private|no|agricultural|customers|delivery then false
# no explicit access rules, make assumptions based on waytype
else if
or highway=residential|service|unclassified|road|living_street|rest_area|services
or highway=trunk|trunk_link|primary|primary_link|secondary|secondary_link|tertiary|tertiary_link
or highway=driveway|mini_roundabout|turning_loop
or highway=track|path|cycleway|crossing|byway|unsurfaced
( and highway=footway|pedestrian is_cycleroute )
then true
else false
else false
assign footaccess
if ( not route=ferry ) then
if foot=yes|designated|permissive|destination then true
else if foot=no|private|use_sidepath then false
else if bicycle=dismount then true
else if access=yes|permissive|destination|designated then true
else if access=private|no|agricultural|customers|delivery then false
# no explicit access rules, make assumptions based on waytype
else if
or highway=residential|service|unclassified|road|living_street|rest_area|services
or highway=trunk|trunk_link|primary|primary_link|secondary|secondary_link|tertiary|tertiary_link
or highway=driveway|mini_roundabout|turning_loop
or highway=track|path|crossing|byway|unsurfaced
highway=footway|steps|pedestrian|corridor|platform
then true
else false
else false
assign ferryaccess
if and route=ferry and ( not bicycle=no|private ) consider_ferries then true
else false
# Needed to trigger initialcost, any fantasy value works as long as they differ for waytypes
# Value chances when going from way to way means initialcost is added
assign initialclassifier_waytype
if highway=residential then 10
else if highway=service|rest_area|services|driveway|mini_roundabout|turning_loop then 12
else if highway=track|path|byway|unsurfaced then 13
else if highway=footway|pedestrian then 14
else if highway=road|unclassified then 15
else if highway=tertiary then 8
else if highway=secondary then 6
else if highway=primary then 4
else if highway=cycleway then 1
else if highway=living_street then 11
else if highway=steps then 17
else if highway=trunk then 2
else if highway=trunk_link then 3
else if highway=primary_link then 5
else if highway=secondary_link then 7
else if highway=tertiary_link then 9
else if highway=crossing then 16
else if highway=corridor then 18
else 19
# we want to add initialcost when access on the same waytype changes as well
assign initialclassifier
if bikeaccess then initialclassifier_waytype
else add initialclassifier_waytype 20
################################################################
# Determine which roads can even be considered for routing #
################################################################
assign access_cost
if ferryaccess then 1
else if bikeaccess then 0
else if footaccess then 9
else 10000
################################################################
# Determine road condition #
################################################################
# define a "bracket" that contains all possible penalties based on all the tags indicating road quality
# it has a min penalty, a max penatly, and a expectation value
assign minbrk -0.2
assign maxbrk 10001
assign expcurrent -1
assign expavgnum 0
# smoothness value is the best option to determine road condition
assign new_minbrk
if ( not smoothness= ) then
if smoothness=excellent then -0.2
else if smoothness=very_good then -0.1
else if smoothness=good then 0.0
else if smoothness=intermediate|medium then 0.2
else if smoothness=bad|robust_wheels|poor then 0.6
else if smoothness=very_bad|high_clearance|rough then 1.5
else if smoothness=horrible|off_road_wheels then 6.0
else if smoothness=very_horrible|impassable then 9.0
else -0.2
else -1
assign new_maxbrk
if ( not smoothness= ) then
if smoothness=excellent then -0.1
else if smoothness=very_good then 0.1
else if smoothness=good then 0.3
else if smoothness=intermediate|medium then 0.8
else if smoothness=bad|robust_wheels|poor then 3.0
else if smoothness=very_bad|high_clearance|rough then 8.0
else if smoothness=horrible|off_road_wheels then 9.0
else if smoothness=very_horrible|impassable then 10000
else 10000
else 10001
assign new_exp
if ( not smoothness= ) then
if smoothness=excellent then -0.2
else if smoothness=very_good then -0.1
else if smoothness=good then 0.0
else if and smoothness=intermediate|medium iswet then 0.5
else if smoothness=intermediate|medium then 0.3
else if and smoothness=bad|robust_wheels|poor iswet then 2.0
else if smoothness=bad|robust_wheels|poor then 1.2
else if and smoothness=very_bad|high_clearance|rough iswet then 5.0
else if smoothness=very_bad|high_clearance|rough then 2.0
else if and smoothness=horrible|off_road_wheels iswet then 9.0
else if smoothness=horrible|off_road_wheels then 8.0
else if and smoothness=very_horrible|impassable iswet then 10000
else if smoothness=very_horrible|impassable then 9.0
else 6.0
else -1
# merge the min and max ranges of the existing and new bracket
assign minbrk max minbrk new_minbrk
assign minmax min maxbrk new_maxbrk
assign maxmax max maxbrk new_maxbrk
assign maxbrk if equal minmax minbrk then minmax else if greater minmax minbrk then minmax else maxmax
# merge the expectation values of the existing and new bracket
# workaround because division is missing
assign expavgmulfactor
if equal expavgnum 0 then 1
else if equal expavgnum 1 then 0.5
else if equal expavgnum 2 then 0.3333
else if equal expavgnum 3 then 0.25
else if equal expavgnum 4 then 0.2
else if equal expavgnum 5 then 0.1667
else 0.1429
assign expcopy expcurrent
assign expcurrent
# exp 1 is outside of the bracket
if or ( lesser expcurrent minbrk ) ( greater expcurrent maxbrk )
# exp 2 is outside the bracket, we assume the middle of the bracket
then if or ( lesser new_exp minbrk ) ( greater new_exp maxbrk ) then multiply 0.5 add minbrk maxbrk
# exp 2 is inside the bracket, we use it
else new_exp
# exp 1 is inside the bracket
else
# exp 2 is outside the bracket, we use exp 1
if or ( lesser new_exp minbrk ) ( greater new_exp maxbrk ) then expcurrent
# both exps are inside the bracket, use the middle values of all exps
else multiply ( add ( multiply expcurrent expavgnum ) new_exp ) expavgmulfactor
assign expavgnum
# exp 1 and 2 are inside the bracket
if and ( not or ( lesser expcopy minbrk ) ( greater expcopy maxbrk ) ) ( not or ( lesser new_exp minbrk ) ( greater new_exp maxbrk ) ) then add expavgnum 1
else if equal new_exp -1 then expavgnum
else 1
# tracktype classification allows to determine approximate smoothness too
assign new_minbrk
if ( not tracktype= ) then
if tracktype=grade1 then -0.2
else if tracktype=grade2 then 0.2
else if tracktype=grade3 then 0.4
else if tracktype=grade4 then 0.5
else if tracktype=grade5 then 1.0
else -0.2
else if 4wd_only=yes|recommended then 1.0
else -1
assign new_maxbrk
if ( not tracktype= ) then
if tracktype=grade1 then 0.4
else if tracktype=grade2 then 0.6
else if tracktype=grade3 then 1.0
else if tracktype=grade4 then 2.0
else if tracktype=grade5 then 6.0
else 10000
else if 4wd_only=yes|recommended then 6.0
else 10001
assign new_exp
if ( not tracktype= ) then
if tracktype=grade1 then 0.1
else if and tracktype=grade2 iswet then 0.6
else if tracktype=grade2 then 0.3
else if and tracktype=grade3 iswet then 1.2
else if tracktype=grade3 then 0.5
else if and tracktype=grade4 iswet then 2.0
else if tracktype=grade4 then 1.2
else if and tracktype=grade5 iswet then 6.0
else if tracktype=grade5 then 2.0
else 6.0
else if and 4wd_only=yes|recommended iswet then 6.0
else if 4wd_only=yes|recommended then 2.0
else -1
# merge the min and max ranges of the existing and new bracket
assign minbrk max minbrk new_minbrk
assign minmax min maxbrk new_maxbrk
assign maxmax max maxbrk new_maxbrk
assign maxbrk if equal minmax minbrk then minmax else if greater minmax minbrk then minmax else maxmax
# merge the expectation values of the existing and new bracket
# workaround because division is missing
assign expavgmulfactor
if equal expavgnum 0 then 1
else if equal expavgnum 1 then 0.5
else if equal expavgnum 2 then 0.3333
else if equal expavgnum 3 then 0.25
else if equal expavgnum 4 then 0.2
else if equal expavgnum 5 then 0.1667
else 0.1429
assign expcopy expcurrent
assign expcurrent
# exp 1 is outside of the bracket
if or ( lesser expcurrent minbrk ) ( greater expcurrent maxbrk )
# exp 2 is outside the bracket, we assume the middle of the bracket
then if or ( lesser new_exp minbrk ) ( greater new_exp maxbrk ) then multiply 0.5 add minbrk maxbrk
# exp 2 is inside the bracket, we use it
else new_exp
# exp 1 is inside the bracket
else
# exp 2 is outside the bracket, we use exp 1
if or ( lesser new_exp minbrk ) ( greater new_exp maxbrk ) then expcurrent
# both exps are inside the bracket, use the middle values of all exps
else multiply ( add ( multiply expcurrent expavgnum ) new_exp ) expavgmulfactor
assign expavgnum
# exp 1 and 2 are inside the bracket
if and ( not or ( lesser expcopy minbrk ) ( greater expcopy maxbrk ) ) ( not or ( lesser new_exp minbrk ) ( greater new_exp maxbrk ) ) then add expavgnum 1
else if equal new_exp -1 then expavgnum
else 1
# the surface is great indicator for smoothness
assign new_minbrk
if ( not surface= ) then
if surface=unpaved then 0.4
else if surface=paved then -0.2
else if surface=asphalt then -0.2
else if and surface=concrete ( and not concrete=plates not concrete=lanes ) then -0.2
else if ( or concrete=lanes concrete=plates ) then 0.3
else if surface=paving_stones then 0.1
else if surface=compacted|fine_gravel then 0.2
else if surface=metal then 0.0
else if surface=dirt|earth|ground then 0.8
# gravel is often confused with fine_gravel, assume gravel means fine gravel on cycle/car routes
else if and surface=gravel ( or is_cycleroute or highway=cycleway or bicycle=designated any_motoraccess ) then 0.2
else if surface=gravel then 0.2
else if surface=grass_paver then 0.4
else if surface=pebblestone then 0.4
else if surface=sett|cobblestone then 0.8
else if surface=grass then 0.8
else if surface=wood then 0.8
else if surface=mud|clay|sand then 8.0
else if highway=unsurfaced then 0.4
else -0.2
else -1
assign new_maxbrk
if ( not surface= ) then
if surface=unpaved then 9.0
else if surface=paved then 3.0
else if surface=asphalt then 1.0
else if and surface=concrete ( and not concrete=plates not concrete=lanes ) then 1.0
else if ( or concrete=lanes concrete=plates ) then 1.5
else if surface=paving_stones then 0.6
else if surface=compacted|fine_gravel then 1.0
else if surface=metal then 0.8
else if surface=dirt|earth|ground then 9.0
# gravel is often confused with fine_gravel, assume gravel means fine gravel on cycle/car routes
else if and surface=gravel ( or is_cycleroute or highway=cycleway or bicycle=designated any_motoraccess ) then 1.0
else if surface=gravel then 9.0
else if surface=grass_paver then 0.8
else if surface=pebblestone then 3.0
else if surface=sett|cobblestone then 5.0
else if surface=grass then 3.0
else if surface=wood then 3.0
else if surface=mud|clay|sand then 10000
else 10000
else if highway=unsurfaced then 9.0
else 10001
assign new_exp
if ( not surface= ) then
if and surface=unpaved iswet then 2.0
else if surface=unpaved then 1.0
else if surface=paved then 0.3
else if surface=asphalt then 0.0
else if and surface=concrete ( and not concrete=plates not concrete=lanes ) then 0.1
else if ( or concrete=lanes concrete=plates ) then 0.4
else if surface=paving_stones then 0.2
else if and surface=compacted|fine_gravel iswet then 0.5
else if surface=compacted|fine_gravel then 0.3
else if and surface=metal iswet then 0.8
else if surface=metal then 0.3
else if and surface=dirt|earth|ground iswet then 5.0
else if surface=dirt|earth|ground then 1.0
# gravel is often confused with fine_gravel, assume gravel means fine gravel on cycle/car routes
else if and surface=gravel and ( or is_cycleroute or highway=cycleway or bicycle=designated any_motoraccess ) iswet then 0.5
else if and surface=gravel ( or is_cycleroute or highway=cycleway or bicycle=designated any_motoraccess ) then 0.3
else if surface=gravel then 3.0
else if and surface=grass_paver iswet then 0.6
else if surface=grass_paver then 0.4
else if and surface=pebblestone iswet then 1.5
else if surface=pebblestone then 0.6
else if and surface=sett|cobblestone iswet then 2.0
else if surface=sett|cobblestone then 1.2
else if and surface=grass iswet then 3.0
else if surface=grass then 1.5
else if surface=wood then 1.0
else if and surface=mud|clay|sand iswet then 10000
else if surface=mud|clay|sand then 8.0
else 6.0
else if and highway=unsurfaced iswet then 2.0
else if highway=unsurfaced then 1.0
else -1
# merge the min and max ranges of the existing and new bracket
assign minbrk max minbrk new_minbrk
assign minmax min maxbrk new_maxbrk
assign maxmax max maxbrk new_maxbrk
assign maxbrk if equal minmax minbrk then minmax else if greater minmax minbrk then minmax else maxmax
# merge the expectation values of the existing and new bracket
# workaround because division is missing
assign expavgmulfactor
if equal expavgnum 0 then 1
else if equal expavgnum 1 then 0.5
else if equal expavgnum 2 then 0.3333
else if equal expavgnum 3 then 0.25
else if equal expavgnum 4 then 0.2
else if equal expavgnum 5 then 0.1667
else 0.1429
assign expcopy expcurrent
assign expcurrent
# exp 1 is outside of the bracket
if or ( lesser expcurrent minbrk ) ( greater expcurrent maxbrk )
# exp 2 is outside the bracket, we assume the middle of the bracket
then if or ( lesser new_exp minbrk ) ( greater new_exp maxbrk ) then multiply 0.5 add minbrk maxbrk
# exp 2 is inside the bracket, we use it
else new_exp
# exp 1 is inside the bracket
else
# exp 2 is outside the bracket, we use exp 1
if or ( lesser new_exp minbrk ) ( greater new_exp maxbrk ) then expcurrent
# both exps are inside the bracket, use the middle values of all exps
else multiply ( add ( multiply expcurrent expavgnum ) new_exp ) expavgmulfactor
assign expavgnum
# exp 1 and 2 are inside the bracket
if and ( not or ( lesser expcopy minbrk ) ( greater expcopy maxbrk ) ) ( not or ( lesser new_exp minbrk ) ( greater new_exp maxbrk ) ) then add expavgnum 1
else if equal new_exp -1 then expavgnum
else 1
# fallback to mountainbike scale
assign new_minbrk
if or ( not mtb:scale= ) ( not mtb:scale:uphill= ) then
if or mtb:scale=1 mtb:scale:uphill=1 then 1.0
else if or mtb:scale=0 mtb:scale:uphill=0 then -0.2
else 10000
else -1
assign new_maxbrk
if or ( not mtb:scale= ) ( not mtb:scale:uphill= ) then
if or mtb:scale=1 mtb:scale:uphill=1 then 9.0
else if or mtb:scale=0 mtb:scale:uphill=0 then 2.0
else 10000
else 10001
assign new_exp
if or ( not mtb:scale= ) ( not mtb:scale:uphill= ) then
if and ( or mtb:scale=1 mtb:scale:uphill=1 ) iswet then 9.0
else if or mtb:scale=1 mtb:scale:uphill=1 then 3.0
else if or mtb:scale=0 mtb:scale:uphill=0 then 1.2
else 10000
else -1
# merge the min and max ranges of the existing and new bracket
assign minbrk max minbrk new_minbrk
assign minmax min maxbrk new_maxbrk
assign maxmax max maxbrk new_maxbrk
assign maxbrk if equal minmax minbrk then minmax else if greater minmax minbrk then minmax else maxmax
# merge the expectation values of the existing and new bracket
# workaround because division is missing
assign expavgmulfactor
if equal expavgnum 0 then 1
else if equal expavgnum 1 then 0.5
else if equal expavgnum 2 then 0.3333
else if equal expavgnum 3 then 0.25
else if equal expavgnum 4 then 0.2
else if equal expavgnum 5 then 0.1667
else 0.1429
assign expcopy expcurrent
assign expcurrent
# exp 1 is outside of the bracket
if or ( lesser expcurrent minbrk ) ( greater expcurrent maxbrk )
# exp 2 is outside the bracket, we assume the middle of the bracket
then if or ( lesser new_exp minbrk ) ( greater new_exp maxbrk ) then multiply 0.5 add minbrk maxbrk
# exp 2 is inside the bracket, we use it
else new_exp
# exp 1 is inside the bracket
else
# exp 2 is outside the bracket, we use exp 1
if or ( lesser new_exp minbrk ) ( greater new_exp maxbrk ) then expcurrent
# both exps are inside the bracket, use the middle values of all exps
else multiply ( add ( multiply expcurrent expavgnum ) new_exp ) expavgmulfactor
assign expavgnum
# exp 1 and 2 are inside the bracket
if and ( not or ( lesser expcopy minbrk ) ( greater expcopy maxbrk ) ) ( not or ( lesser new_exp minbrk ) ( greater new_exp maxbrk ) ) then add expavgnum 1
else if equal new_exp -1 then expavgnum
else 1
# fallback to hiking route classification
assign new_minbrk
if ( not sac_scale= ) then
if sac_scale=hiking then 0.0
else 10000
else -1
assign new_maxbrk
if ( not sac_scale= ) then
if sac_scale=hiking then 9.0
else 10000
else 10001
assign new_exp
if ( not sac_scale= ) then
if sac_scale=hiking then 1.5
else 10000
else -1
# merge the min and max ranges of the existing and new bracket
assign minbrk max minbrk new_minbrk
assign minmax min maxbrk new_maxbrk
assign maxmax max maxbrk new_maxbrk
assign maxbrk if equal minmax minbrk then minmax else if greater minmax minbrk then minmax else maxmax
# merge the expectation values of the existing and new bracket
# workaround because division is missing
assign expavgmulfactor
if equal expavgnum 0 then 1
else if equal expavgnum 1 then 0.5
else if equal expavgnum 2 then 0.3333
else if equal expavgnum 3 then 0.25
else if equal expavgnum 4 then 0.2
else if equal expavgnum 5 then 0.1667
else 0.1429
assign expcopy expcurrent
assign expcurrent
# exp 1 is outside of the bracket
if or ( lesser expcurrent minbrk ) ( greater expcurrent maxbrk )
# exp 2 is outside the bracket, we assume the middle of the bracket
then if or ( lesser new_exp minbrk ) ( greater new_exp maxbrk ) then multiply 0.5 add minbrk maxbrk
# exp 2 is inside the bracket, we use it
else new_exp
# exp 1 is inside the bracket
else
# exp 2 is outside the bracket, we use exp 1
if or ( lesser new_exp minbrk ) ( greater new_exp maxbrk ) then expcurrent
# both exps are inside the bracket, use the middle values of all exps
else multiply ( add ( multiply expcurrent expavgnum ) new_exp ) expavgmulfactor
assign expavgnum
# exp 1 and 2 are inside the bracket
if and ( not or ( lesser expcopy minbrk ) ( greater expcurrent maxbrk ) ) ( not or ( lesser new_exp minbrk ) ( greater new_exp maxbrk ) ) then add expavgnum 1
else if equal new_exp -1 then expavgnum
else 1
assign smoothness_cost
if greater expavgnum 0 then expcurrent
# no good indication of smoothness, fallback to make rough assumptions based on waytype
# waytypes that are likely in good condition, but add a little cost for unknown condition
else if and ( not is_cycleroute ) (
or highway=residential
or highway=service
or highway=unclassified
or highway=living_street
or highway=crossing
or highway=road
or highway=rest_area
or highway=services
or highway=driveway
or highway=mini_roundabout
highway=turning_loop )
then 0.1
# waytypes that are almost certainly in good condition
else if and is_cycleroute (
or highway=residential
or highway=service
or highway=unclassified
or highway=living_street
or highway=crossing
or highway=road
or highway=rest_area
or highway=services
or highway=driveway
or highway=mini_roundabout
highway=turning_loop )
then 0.0
else if (
or highway=tertiary|tertiary_link
or highway=secondary|secondary_link
or highway=primary|primary_link
or highway=motorway|motorway_link
or highway=trunk|trunk_link
highway=cycleway )
then 0.0
# footways are expected to be ok
else if highway=footway|pedestrian|platform then 0.1
# probably not too bad smoothness when dedicated for bike
else if bicycle=designated then 0.2
# tracks are usualy slightly compacted, paths often grass or loose ground
else if and highway=track|byway iswet then 3.0
else if highway=track|byway then 1.2
else if and highway=path iswet then 5.0
else if highway=path then 2.0
else 1.5
################################################################
# Traffic Penalty #
################################################################
assign traffic_cost
# many pedestrians but no cars expected
if or and highway=pedestrian ( not segregated=yes )
( highway=platform|corridor )
then traffic_tier1
# anything without motor vehicles is fine
else if not any_motoraccess then 0.0
# 3+ lanes = lots of expected traffic
else if and ( and oneway=yes|true|1|-1 lanes=3|4|5|6|7 ) ( not hascycleway ) then traffic_tier4
else if and lanes=5|6|7 ( not hascycleway ) then traffic_tier4
# a way specifically designed for bikes probably has no traffic
else if ( and bicycle=designated ( not segregated=no ) ) then 0.0
# wild traffic guesses based on roadtype only
else if not hascycleway then
if highway=motorway|motorway_link|trunk|trunk_link|primary|primary_link then traffic_tier4
else if highway=secondary|secondary_link|tertiary|tertiary_link then traffic_tier3
else if highway=residential|mini_roundabout|road|unclassified then traffic_tier2
else 0.0
else if hascycleway then
if highway=motorway|motorway_link|trunk|trunk_link|primary|primary_link|secondary|secondary_link then traffic_tier2
else if highway=tertiary|tertiary_link then traffic_tier1
else 0.0
else 0.0
################################################################
# Maxspeed Penalty #
################################################################
assign maxspeed_cost_raw
if ( not maxspeed= ) then
if maxspeed=70|80 then speed_tier1
else if maxspeed=90|100|rural then speed_tier2
else if maxspeed=110 then speed_tier3
else if maxspeed=130 then speed_tier4
else 0.0
else if ( not highway= ) then
# very rough guess unfortunately
if highway=trunk|trunk_link then speed_tier3
else if highway=primary|primary_link then speed_tier2
else if highway=secondary|secondary_link then speed_tier2
else 0.0
else 0.0
# if the road has a cycleway anything up to speed tier 2 gets no penalty
assign maxspeed_cost if hascycleway then ( max 0.0 ( sub maxspeed_cost_raw speed_tier2 ) ) else maxspeed_cost_raw
################################################################
# onewaycost #
################################################################
assign oneway_cost =
if badoneway then
if greater traffic_cost traffic_tier2 then 20
else 9
else 0
################################################################
# Inital and Turn Cost #
################################################################
assign initialcost_waypreference
# ways with lots of traffic mean we have to be slow when going onto them
if greater traffic_cost traffic_tier2 then 100
else 25
assign initialcost
if ferryaccess then 30000
# getting on and off the bike is a fixed effort for each part of the way we need to walk
else if and ( not bikeaccess ) footaccess then ( add initialcost_waypreference 400 )
else initialcost_waypreference
assign turncost
# unfortunately footways are often drawn in odd shapes in OSM not representing how you really drive
if highway=footway then 0
# we are walking, no cost for turning
else if ( not bikeaccess ) then 0
# we are on a crappy way and slow
else if ( greater smoothness_cost 1.0 ) then 10
else if ( greater smoothness_cost 0.4 ) then 30
# we are on an ok way and probably fast enough that turning is annoying
else 60
################################################################
# Roads that are part of a cycleroute are preferred #
################################################################
# We go 20% extra way, if it means we are on an official cycleroute, or 10% for proposed cycle routes
assign cycleroute_cost
if class:bicycle= then if is_cycleroute then 0.0 else if is_cycleroute_other then 0.10 else 0.20
else if class:bicycle=-3 then 3.0
else if class:bicycle=-2 then 1.0
else if class:bicycle=-1 then 0.4
else if class:bicycle=3 then -0.4
else if class:bicycle=2 then -0.2
else if class:bicycle=1 then 0.0
else 0.0
################################################################
# Final Way Costfactor Calculation #
################################################################
assign costfactor
if ferryaccess then access_cost
else max ( add 1.0 add access_cost add smoothness_cost add traffic_cost add maxspeed_cost add oneway_cost cycleroute_cost ) 1.0
---context:node
################################################################
# A bunch of helper-stuff before the actual nodecost logic #
################################################################
assign bikeaccess
if bicycle=yes|designated|permissive|destination then true
else if bicycle=no|dismount|private then false
else if vehicle=yes|destination|permissive|designated then true
else if vehicle=no|private|agricultural then false
else if access=yes|permissive|destination|designated then true
else if access=private|no|agricultural then false
else if barrier=gate|fence|yes|wall|hedge|obstacle|spikes|door|barrier|debris|ditch|turnstile|stile|swing_gate|hampshire_gate|full-height_turnstile|windfall|footgate|lift_gate|cycle_barrier|toll_booth|border_control|chain|fallen_tree|checkpoint|rope|log|kissing_gate|bump_gate|horse_stile|tree|motorcycle_barrier|guard_rail|bar|jersey_barrier|unknown then false
else if highway=steps then false
else true
assign footaccess
if foot=yes|designated|permissive|destination then true
else if foot=no|private then false
else if bicycle=dismount then true
else if access=yes|permissive|destination|designated then true
else if access=private|no|agricultural then false
else if barrier=gate|fence|yes|wall|hedge|obstacle|spikes|door|barrier|debris|ditch|turnstile|stile|swing_gate|hampshire_gate|full-height_turnstile|windfall|footgate|unknown then false
else true
################################################################
# Determine which points influence us #
################################################################
assign access_cost
if and crossing=no not way:any_motoraccess then 1000
# even if we can pass a barrier, we likely must slow down a bit
else if ( and bikeaccess ( not barrier= ) ) then 25
else if bikeaccess then 0
# getting on and off the bike is a fixed cost
else if footaccess then 400
else 10000
################################################################
# Add costs for assorted things like traffic lights #
################################################################
# Missing: traffic sign direction, we are limited by BRouter data here
assign node_cost =
if highway=traffic_signals then 120
else if crossing=traffic_signals then 120
else if railway=signal then 150
else if railway=level_crossing then 80
else if railway=crossing then 80
else if highway=stop|give_way then 25
else if highway=traffic_calming then 50
else if crossing=zebra then 50
else if ford=yes then 500
else 0
################################################################
# Final Way Costfactor Calculation #
################################################################
assign initialcost add access_cost node_cost