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