1-- Foot profile 2 3api_version = 2 4 5Set = require('lib/set') 6Sequence = require('lib/sequence') 7Handlers = require("lib/way_handlers") 8find_access_tag = require("lib/access").find_access_tag 9 10function setup() 11 local walking_speed = 5 12 return { 13 properties = { 14 weight_name = 'duration', 15 max_speed_for_map_matching = 40/3.6, -- kmph -> m/s 16 call_tagless_node_function = false, 17 traffic_light_penalty = 2, 18 u_turn_penalty = 2, 19 continue_straight_at_waypoint = false, 20 use_turn_restrictions = false, 21 }, 22 23 default_mode = mode.walking, 24 default_speed = walking_speed, 25 oneway_handling = 'specific', -- respect 'oneway:foot' but not 'oneway' 26 27 barrier_blacklist = Set { 28 'yes', 29 'wall', 30 'fence' 31 }, 32 33 access_tag_whitelist = Set { 34 'yes', 35 'foot', 36 'permissive', 37 'designated' 38 }, 39 40 access_tag_blacklist = Set { 41 'no', 42 'agricultural', 43 'forestry', 44 'private', 45 'delivery', 46 }, 47 48 restricted_access_tag_list = Set { }, 49 50 restricted_highway_whitelist = Set { }, 51 52 construction_whitelist = Set {}, 53 54 access_tags_hierarchy = Sequence { 55 'foot', 56 'access' 57 }, 58 59 -- tags disallow access to in combination with highway=service 60 service_access_tag_blacklist = Set { }, 61 62 restrictions = Sequence { 63 'foot' 64 }, 65 66 -- list of suffixes to suppress in name change instructions 67 suffix_list = Set { 68 'N', 'NE', 'E', 'SE', 'S', 'SW', 'W', 'NW', 'North', 'South', 'West', 'East' 69 }, 70 71 avoid = Set { 72 'impassable' 73 }, 74 75 speeds = Sequence { 76 highway = { 77 primary = walking_speed, 78 primary_link = walking_speed, 79 secondary = walking_speed, 80 secondary_link = walking_speed, 81 tertiary = walking_speed, 82 tertiary_link = walking_speed, 83 unclassified = walking_speed, 84 residential = walking_speed, 85 road = walking_speed, 86 living_street = walking_speed, 87 service = walking_speed, 88 track = walking_speed, 89 path = walking_speed, 90 steps = walking_speed, 91 pedestrian = walking_speed, 92 footway = walking_speed, 93 pier = walking_speed, 94 }, 95 96 railway = { 97 platform = walking_speed 98 }, 99 100 amenity = { 101 parking = walking_speed, 102 parking_entrance= walking_speed 103 }, 104 105 man_made = { 106 pier = walking_speed 107 }, 108 109 leisure = { 110 track = walking_speed 111 } 112 }, 113 114 route_speeds = { 115 ferry = 5 116 }, 117 118 bridge_speeds = { 119 }, 120 121 surface_speeds = { 122 fine_gravel = walking_speed*0.75, 123 gravel = walking_speed*0.75, 124 pebblestone = walking_speed*0.75, 125 mud = walking_speed*0.5, 126 sand = walking_speed*0.5 127 }, 128 129 tracktype_speeds = { 130 }, 131 132 smoothness_speeds = { 133 } 134 } 135end 136 137function process_node(profile, node, result) 138 -- parse access and barrier tags 139 local access = find_access_tag(node, profile.access_tags_hierarchy) 140 if access then 141 if profile.access_tag_blacklist[access] then 142 result.barrier = true 143 end 144 else 145 local barrier = node:get_value_by_key("barrier") 146 if barrier then 147 -- make an exception for rising bollard barriers 148 local bollard = node:get_value_by_key("bollard") 149 local rising_bollard = bollard and "rising" == bollard 150 151 if profile.barrier_blacklist[barrier] and not rising_bollard then 152 result.barrier = true 153 end 154 end 155 end 156 157 -- check if node is a traffic light 158 local tag = node:get_value_by_key("highway") 159 if "traffic_signals" == tag then 160 result.traffic_lights = true 161 end 162end 163 164-- main entry point for processsing a way 165function process_way(profile, way, result) 166 -- the intial filtering of ways based on presence of tags 167 -- affects processing times significantly, because all ways 168 -- have to be checked. 169 -- to increase performance, prefetching and intial tag check 170 -- is done in directly instead of via a handler. 171 172 -- in general we should try to abort as soon as 173 -- possible if the way is not routable, to avoid doing 174 -- unnecessary work. this implies we should check things that 175 -- commonly forbids access early, and handle edge cases later. 176 177 -- data table for storing intermediate values during processing 178 local data = { 179 -- prefetch tags 180 highway = way:get_value_by_key('highway'), 181 bridge = way:get_value_by_key('bridge'), 182 route = way:get_value_by_key('route'), 183 leisure = way:get_value_by_key('leisure'), 184 man_made = way:get_value_by_key('man_made'), 185 railway = way:get_value_by_key('railway'), 186 platform = way:get_value_by_key('platform'), 187 amenity = way:get_value_by_key('amenity'), 188 public_transport = way:get_value_by_key('public_transport') 189 } 190 191 -- perform an quick initial check and abort if the way is 192 -- obviously not routable. here we require at least one 193 -- of the prefetched tags to be present, ie. the data table 194 -- cannot be empty 195 if next(data) == nil then -- is the data table empty? 196 return 197 end 198 199 local handlers = Sequence { 200 -- set the default mode for this profile. if can be changed later 201 -- in case it turns we're e.g. on a ferry 202 WayHandlers.default_mode, 203 204 -- check various tags that could indicate that the way is not 205 -- routable. this includes things like status=impassable, 206 -- toll=yes and oneway=reversible 207 WayHandlers.blocked_ways, 208 209 -- determine access status by checking our hierarchy of 210 -- access tags, e.g: motorcar, motor_vehicle, vehicle 211 WayHandlers.access, 212 213 -- check whether forward/backward directons are routable 214 WayHandlers.oneway, 215 216 -- check whether forward/backward directons are routable 217 WayHandlers.destinations, 218 219 -- check whether we're using a special transport mode 220 WayHandlers.ferries, 221 WayHandlers.movables, 222 223 -- compute speed taking into account way type, maxspeed tags, etc. 224 WayHandlers.speed, 225 WayHandlers.surface, 226 227 -- handle turn lanes and road classification, used for guidance 228 WayHandlers.classification, 229 230 -- handle various other flags 231 WayHandlers.roundabouts, 232 WayHandlers.startpoint, 233 234 -- set name, ref and pronunciation 235 WayHandlers.names, 236 237 -- set weight properties of the way 238 WayHandlers.weights 239 } 240 241 WayHandlers.run(profile, way, result, data, handlers) 242end 243 244function process_turn (profile, turn) 245 turn.duration = 0. 246 247 if turn.direction_modifier == direction_modifier.u_turn then 248 turn.duration = turn.duration + profile.properties.u_turn_penalty 249 end 250 251 if turn.has_traffic_light then 252 turn.duration = profile.properties.traffic_light_penalty 253 end 254 if profile.properties.weight_name == 'routability' then 255 -- penalize turns from non-local access only segments onto local access only tags 256 if not turn.source_restricted and turn.target_restricted then 257 turn.weight = turn.weight + 3000 258 end 259 end 260end 261 262return { 263 setup = setup, 264 process_way = process_way, 265 process_node = process_node, 266 process_turn = process_turn 267} 268