Funcionalitats algorisme PM2.5 i PM10
This commit is contained in:
parent
3f51181e79
commit
8c03e490a0
@ -1,48 +1,66 @@
|
|||||||
-- Bicycle profile
|
|
||||||
|
|
||||||
api_version = 4
|
-- Foot profile
|
||||||
|
local http = require("socket.http") -- LuaSocket for HTTP requests
|
||||||
|
local json = require("cjson")
|
||||||
|
|
||||||
|
api_version = 2
|
||||||
|
|
||||||
Set = require('lib/set')
|
Set = require('lib/set')
|
||||||
Sequence = require('lib/sequence')
|
Sequence = require('lib/sequence')
|
||||||
Handlers = require("lib/way_handlers")
|
Handlers = require("lib/way_handlers")
|
||||||
TrafficSignal = require("lib/traffic_signal")
|
|
||||||
find_access_tag = require("lib/access").find_access_tag
|
find_access_tag = require("lib/access").find_access_tag
|
||||||
limit = require("lib/maxspeed").limit
|
stations_data = nil
|
||||||
Measure = require("lib/measure")
|
|
||||||
|
|
||||||
|
function fetch_pollution_data()
|
||||||
|
local url = "http://128.199.51.173:8000/routes/api/pollution/PM10"
|
||||||
|
local response, status = http.request(url)
|
||||||
|
|
||||||
|
if status == 200 and response then
|
||||||
|
print("Raw response:", response)
|
||||||
|
local success, data = pcall(json.decode, response) -- Manejar errores de JSON
|
||||||
|
if success and data and data.stations then
|
||||||
|
print("Pollution data fetched successfully.")
|
||||||
|
print("Number of stations:", #data.stations)
|
||||||
|
return data
|
||||||
|
else
|
||||||
|
print("Failed to decode JSON or missing 'stations' key.")
|
||||||
|
end
|
||||||
|
else
|
||||||
|
print("HTTP request failed. Status:", status)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Fallback a datos vacíos si hay un error
|
||||||
|
return { stations = {} }
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function setup()
|
function setup()
|
||||||
local default_speed = 15
|
local walking_speed = 5
|
||||||
local walking_speed = 4
|
stations_data = fetch_pollution_data()
|
||||||
|
|
||||||
|
-- Check if data was successfully retrieved
|
||||||
|
if not stations_data or not stations_data.stations then
|
||||||
|
print("Warning: Pollution data could not be loaded. Defaulting to no pollution.")
|
||||||
|
stations_data = { stations = {} } -- Fallback to empty station data
|
||||||
|
else
|
||||||
|
print("Pollution data loaded successfully.")
|
||||||
|
end
|
||||||
return {
|
return {
|
||||||
properties = {
|
properties = {
|
||||||
u_turn_penalty = 20,
|
|
||||||
traffic_light_penalty = 2,
|
|
||||||
--weight_name = 'cyclability',
|
|
||||||
weight_name = 'duration',
|
weight_name = 'duration',
|
||||||
process_call_tagless_node = false,
|
max_speed_for_map_matching = 40/3.6, -- kmph -> m/s
|
||||||
max_speed_for_map_matching = 110/3.6, -- kmph -> m/s
|
call_tagless_node_function = false,
|
||||||
use_turn_restrictions = false,
|
traffic_light_penalty = 2,
|
||||||
|
u_turn_penalty = 2,
|
||||||
continue_straight_at_waypoint = false,
|
continue_straight_at_waypoint = false,
|
||||||
mode_change_penalty = 30,
|
use_turn_restrictions = false,
|
||||||
},
|
},
|
||||||
|
|
||||||
default_mode = mode.cycling,
|
default_mode = mode.walking,
|
||||||
default_speed = default_speed,
|
default_speed = walking_speed,
|
||||||
walking_speed = walking_speed,
|
oneway_handling = 'specific', -- respect 'oneway:foot' but not 'oneway'
|
||||||
oneway_handling = true,
|
|
||||||
turn_penalty = 6,
|
|
||||||
turn_bias = 1.4,
|
|
||||||
use_public_transport = true,
|
|
||||||
|
|
||||||
-- Exclude narrow ways, in particular to route with cargo bike
|
|
||||||
width = nil, -- Cargo bike could 0.5 width, in meters
|
|
||||||
exclude_cargo_bike = false,
|
|
||||||
|
|
||||||
allowed_start_modes = Set {
|
|
||||||
mode.cycling,
|
|
||||||
mode.pushing_bike
|
|
||||||
},
|
|
||||||
|
|
||||||
barrier_blacklist = Set {
|
barrier_blacklist = Set {
|
||||||
'yes',
|
'yes',
|
||||||
@ -52,120 +70,85 @@ function setup()
|
|||||||
|
|
||||||
access_tag_whitelist = Set {
|
access_tag_whitelist = Set {
|
||||||
'yes',
|
'yes',
|
||||||
|
'foot',
|
||||||
'permissive',
|
'permissive',
|
||||||
'designated'
|
'designated'
|
||||||
},
|
},
|
||||||
|
|
||||||
access_tag_blacklist = Set {
|
access_tag_blacklist = Set {
|
||||||
'no',
|
'no',
|
||||||
'private',
|
|
||||||
'agricultural',
|
'agricultural',
|
||||||
'forestry',
|
'forestry',
|
||||||
|
'private',
|
||||||
'delivery',
|
'delivery',
|
||||||
-- When a way is tagged with `use_sidepath` a parallel way suitable for
|
|
||||||
-- cyclists is mapped and must be used instead (by law). This tag is
|
|
||||||
-- used on ways that normally may be used by cyclists, but not when
|
|
||||||
-- a signposted parallel cycleway is available. For purposes of routing
|
|
||||||
-- cyclists, this value should be treated as 'no access for bicycles'.
|
|
||||||
'use_sidepath'
|
|
||||||
},
|
},
|
||||||
|
|
||||||
restricted_access_tag_list = Set { },
|
restricted_access_tag_list = Set { },
|
||||||
|
|
||||||
restricted_highway_whitelist = Set { },
|
restricted_highway_whitelist = Set { },
|
||||||
|
|
||||||
-- tags disallow access to in combination with highway=service
|
construction_whitelist = Set {},
|
||||||
service_access_tag_blacklist = Set { },
|
|
||||||
|
|
||||||
construction_whitelist = Set {
|
|
||||||
'no',
|
|
||||||
'widening',
|
|
||||||
'minor',
|
|
||||||
},
|
|
||||||
|
|
||||||
access_tags_hierarchy = Sequence {
|
access_tags_hierarchy = Sequence {
|
||||||
'bicycle',
|
'foot',
|
||||||
'vehicle',
|
|
||||||
'access'
|
'access'
|
||||||
},
|
},
|
||||||
|
|
||||||
restrictions = Set {
|
-- tags disallow access to in combination with highway=service
|
||||||
'bicycle'
|
service_access_tag_blacklist = Set { },
|
||||||
|
|
||||||
|
restrictions = Sequence {
|
||||||
|
'foot'
|
||||||
},
|
},
|
||||||
|
|
||||||
cycleway_tags = Set {
|
-- list of suffixes to suppress in name change instructions
|
||||||
'track',
|
suffix_list = Set {
|
||||||
'lane',
|
'N', 'NE', 'E', 'SE', 'S', 'SW', 'W', 'NW', 'North', 'South', 'West', 'East'
|
||||||
'share_busway',
|
|
||||||
'sharrow',
|
|
||||||
'shared',
|
|
||||||
'shared_lane'
|
|
||||||
},
|
},
|
||||||
|
|
||||||
opposite_cycleway_tags = Set {
|
avoid = Set {
|
||||||
'opposite',
|
'impassable',
|
||||||
'opposite_lane',
|
'proposed'
|
||||||
'opposite_track',
|
|
||||||
},
|
},
|
||||||
|
|
||||||
-- reduce the driving speed by 30% for unsafe roads
|
speeds = Sequence {
|
||||||
-- only used for cyclability metric
|
highway = {
|
||||||
unsafe_highway_list = {
|
primary = walking_speed,
|
||||||
primary = 0.5,
|
primary_link = walking_speed,
|
||||||
secondary = 0.65,
|
secondary = walking_speed,
|
||||||
tertiary = 0.8,
|
secondary_link = walking_speed,
|
||||||
primary_link = 0.5,
|
tertiary = walking_speed,
|
||||||
secondary_link = 0.65,
|
tertiary_link = walking_speed,
|
||||||
tertiary_link = 0.8,
|
unclassified = walking_speed,
|
||||||
},
|
residential = walking_speed,
|
||||||
|
road = walking_speed,
|
||||||
|
living_street = walking_speed,
|
||||||
|
service = walking_speed,
|
||||||
|
track = walking_speed,
|
||||||
|
path = walking_speed,
|
||||||
|
steps = walking_speed,
|
||||||
|
pedestrian = walking_speed,
|
||||||
|
platform = walking_speed,
|
||||||
|
footway = walking_speed,
|
||||||
|
pier = walking_speed,
|
||||||
|
},
|
||||||
|
|
||||||
service_penalties = {
|
railway = {
|
||||||
alley = 0.5,
|
platform = walking_speed
|
||||||
},
|
},
|
||||||
|
|
||||||
bicycle_speeds = {
|
amenity = {
|
||||||
cycleway = default_speed,
|
parking = walking_speed,
|
||||||
primary = default_speed,
|
parking_entrance= walking_speed
|
||||||
primary_link = default_speed,
|
},
|
||||||
secondary = default_speed,
|
|
||||||
secondary_link = default_speed,
|
|
||||||
tertiary = default_speed,
|
|
||||||
tertiary_link = default_speed,
|
|
||||||
residential = default_speed,
|
|
||||||
unclassified = default_speed,
|
|
||||||
living_street = default_speed,
|
|
||||||
road = default_speed,
|
|
||||||
service = default_speed,
|
|
||||||
track = 12,
|
|
||||||
path = 13
|
|
||||||
},
|
|
||||||
|
|
||||||
pedestrian_speeds = {
|
man_made = {
|
||||||
footway = walking_speed,
|
pier = walking_speed
|
||||||
pedestrian = walking_speed,
|
},
|
||||||
steps = 2
|
|
||||||
},
|
|
||||||
|
|
||||||
railway_speeds = {
|
leisure = {
|
||||||
train = 10,
|
track = walking_speed
|
||||||
railway = 10,
|
}
|
||||||
subway = 10,
|
|
||||||
light_rail = 10,
|
|
||||||
monorail = 10,
|
|
||||||
tram = 10
|
|
||||||
},
|
|
||||||
|
|
||||||
platform_speeds = {
|
|
||||||
platform = walking_speed
|
|
||||||
},
|
|
||||||
|
|
||||||
amenity_speeds = {
|
|
||||||
parking = 10,
|
|
||||||
parking_entrance = 10
|
|
||||||
},
|
|
||||||
|
|
||||||
man_made_speeds = {
|
|
||||||
pier = walking_speed
|
|
||||||
},
|
},
|
||||||
|
|
||||||
route_speeds = {
|
route_speeds = {
|
||||||
@ -173,487 +156,119 @@ function setup()
|
|||||||
},
|
},
|
||||||
|
|
||||||
bridge_speeds = {
|
bridge_speeds = {
|
||||||
movable = 5
|
|
||||||
},
|
},
|
||||||
|
|
||||||
surface_speeds = {
|
surface_speeds = {
|
||||||
asphalt = default_speed,
|
fine_gravel = walking_speed*0.75,
|
||||||
chipseal = default_speed,
|
gravel = walking_speed*0.75,
|
||||||
concrete = default_speed,
|
pebblestone = walking_speed*0.75,
|
||||||
concrete_lanes = default_speed,
|
mud = walking_speed*0.5,
|
||||||
wood = 10,
|
sand = walking_speed*0.5
|
||||||
metal = 10,
|
|
||||||
["cobblestone:flattened"] = 10,
|
|
||||||
paving_stones = 10,
|
|
||||||
compacted = 10,
|
|
||||||
cobblestone = 7,
|
|
||||||
unpaved = 6,
|
|
||||||
fine_gravel = 10,
|
|
||||||
gravel = 6,
|
|
||||||
pebblestone = 6,
|
|
||||||
grass_paver = 6,
|
|
||||||
ground = 10,
|
|
||||||
dirt = 8,
|
|
||||||
earth = 6,
|
|
||||||
grass = 6,
|
|
||||||
mud = 3,
|
|
||||||
sand = 3,
|
|
||||||
woodchips = 3,
|
|
||||||
sett = 9
|
|
||||||
},
|
|
||||||
|
|
||||||
classes = Sequence {
|
|
||||||
'ferry', 'tunnel'
|
|
||||||
},
|
|
||||||
|
|
||||||
-- Which classes should be excludable
|
|
||||||
-- This increases memory usage so its disabled by default.
|
|
||||||
excludable = Sequence {
|
|
||||||
-- Set {'ferry'}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
tracktype_speeds = {
|
tracktype_speeds = {
|
||||||
},
|
},
|
||||||
|
|
||||||
smoothness_speeds = {
|
smoothness_speeds = {
|
||||||
},
|
|
||||||
|
|
||||||
avoid = Set {
|
|
||||||
'impassable',
|
|
||||||
'construction',
|
|
||||||
'proposed'
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
function process_node(profile, node, result)
|
function calculate_pollution(lat, lon)
|
||||||
-- parse access and barrier tags
|
-- Calcular contaminación
|
||||||
local highway = node:get_value_by_key("highway")
|
local pollution_value = 0
|
||||||
local is_crossing = highway and highway == "crossing"
|
local total_weight = 0
|
||||||
|
local weight = 0
|
||||||
|
local p = 1.8
|
||||||
|
local max_distance = 3
|
||||||
|
if stations_data and stations_data.stations then
|
||||||
|
for _, station in ipairs(stations_data.stations) do
|
||||||
|
local station_lat = tonumber(station.lat)
|
||||||
|
local station_lon = tonumber(station.lon)
|
||||||
|
local latest_reading = tonumber(station.pollution)
|
||||||
|
|
||||||
|
if station_lat and station_lon and latest_reading then
|
||||||
|
-- Fórmula de distancia usando Haversine
|
||||||
|
local R = 6371 -- Radio de la Tierra en km
|
||||||
|
local dlat = math.rad(station_lat - lat)
|
||||||
|
local dlon = math.rad(station_lon - lon)
|
||||||
|
local a = math.sin(dlat / 2)^2 +
|
||||||
|
math.cos(math.rad(lat)) * math.cos(math.rad(station_lat)) * math.sin(dlon / 2)^2
|
||||||
|
local c = 2 * math.atan2(math.sqrt(a), math.sqrt(1 - a))
|
||||||
|
local distance = R * c
|
||||||
|
|
||||||
|
-- Ponderación ajustada
|
||||||
|
weight = 1 / ((distance + 1))
|
||||||
|
weight = tonumber(string.format("%.6f", weight))
|
||||||
|
pollution_value = pollution_value + (latest_reading * weight)
|
||||||
|
--total_weight = total_weight + weight
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
||||||
|
--print(pollution_value)
|
||||||
|
return pollution_value
|
||||||
|
else
|
||||||
|
print("No station data available.")
|
||||||
|
return 0
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function process_node(profile, node, result)
|
||||||
|
-- Parse access and barrier tags
|
||||||
local access = find_access_tag(node, profile.access_tags_hierarchy)
|
local access = find_access_tag(node, profile.access_tags_hierarchy)
|
||||||
if access and access ~= "" then
|
if access then
|
||||||
-- access restrictions on crossing nodes are not relevant for
|
if profile.access_tag_blacklist[access] then
|
||||||
-- the traffic on the road
|
|
||||||
if profile.access_tag_blacklist[access] and not is_crossing then
|
|
||||||
result.barrier = true
|
result.barrier = true
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
local barrier = node:get_value_by_key("barrier")
|
local barrier = node:get_value_by_key("barrier")
|
||||||
if barrier and "" ~= barrier then
|
if barrier then
|
||||||
if profile.barrier_blacklist[barrier] then
|
-- Make an exception for rising bollard barriers
|
||||||
|
local bollard = node:get_value_by_key("bollard")
|
||||||
|
local rising_bollard = bollard and "rising" == bollard
|
||||||
|
|
||||||
|
if profile.barrier_blacklist[barrier] and not rising_bollard then
|
||||||
result.barrier = true
|
result.barrier = true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if profile.exclude_cargo_bike then
|
|
||||||
local cargo_bike = node:get_value_by_key("cargo_bike")
|
|
||||||
if cargo_bike and cargo_bike == "no" then
|
|
||||||
result.barrier = true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- width
|
|
||||||
if profile.width then
|
|
||||||
-- From barrier=cycle_barrier or other barriers
|
|
||||||
local maxwidth_physical = node:get_value_by_key("maxwidth:physical")
|
|
||||||
local maxwidth_physical_meter = maxwidth_physical and Measure.parse_value_meters(maxwidth_physical) or 99
|
|
||||||
local opening = node:get_value_by_key("opening")
|
|
||||||
local opening_meter = opening and Measure.parse_value_meters(opening) or 99
|
|
||||||
local width_meter = math.min(maxwidth_physical_meter, opening_meter)
|
|
||||||
|
|
||||||
if width_meter and width_meter < profile.width then
|
|
||||||
result.barrier = true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- check if node is a traffic light
|
|
||||||
result.traffic_lights = TrafficSignal.get_value(node)
|
|
||||||
end
|
|
||||||
|
|
||||||
function handle_bicycle_tags(profile,way,result,data)
|
|
||||||
-- initial routability check, filters out buildings, boundaries, etc
|
|
||||||
data.route = way:get_value_by_key("route")
|
|
||||||
data.man_made = way:get_value_by_key("man_made")
|
|
||||||
data.railway = way:get_value_by_key("railway")
|
|
||||||
data.amenity = way:get_value_by_key("amenity")
|
|
||||||
data.public_transport = way:get_value_by_key("public_transport")
|
|
||||||
data.bridge = way:get_value_by_key("bridge")
|
|
||||||
|
|
||||||
if (not data.highway or data.highway == '') and
|
|
||||||
(not data.route or data.route == '') and
|
|
||||||
(not profile.use_public_transport or not data.railway or data.railway=='') and
|
|
||||||
(not data.amenity or data.amenity=='') and
|
|
||||||
(not data.man_made or data.man_made=='') and
|
|
||||||
(not data.public_transport or data.public_transport=='') and
|
|
||||||
(not data.bridge or data.bridge=='')
|
|
||||||
then
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
|
|
||||||
-- access
|
|
||||||
data.access = find_access_tag(way, profile.access_tags_hierarchy)
|
|
||||||
if data.access and profile.access_tag_blacklist[data.access] then
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
|
|
||||||
-- other tags
|
|
||||||
data.junction = way:get_value_by_key("junction")
|
|
||||||
data.maxspeed = Measure.get_max_speed(way:get_value_by_key ("maxspeed")) or 0
|
|
||||||
data.maxspeed_forward = Measure.get_max_speed(way:get_value_by_key("maxspeed:forward")) or 0
|
|
||||||
data.maxspeed_backward = Measure.get_max_speed(way:get_value_by_key("maxspeed:backward")) or 0
|
|
||||||
data.barrier = way:get_value_by_key("barrier")
|
|
||||||
data.oneway = way:get_value_by_key("oneway")
|
|
||||||
data.oneway_bicycle = way:get_value_by_key("oneway:bicycle")
|
|
||||||
data.cycleway = way:get_value_by_key("cycleway")
|
|
||||||
data.cycleway_left = way:get_value_by_key("cycleway:left")
|
|
||||||
data.cycleway_right = way:get_value_by_key("cycleway:right")
|
|
||||||
data.duration = way:get_value_by_key("duration")
|
|
||||||
data.service = way:get_value_by_key("service")
|
|
||||||
data.foot = way:get_value_by_key("foot")
|
|
||||||
data.foot_forward = way:get_value_by_key("foot:forward")
|
|
||||||
data.foot_backward = way:get_value_by_key("foot:backward")
|
|
||||||
data.bicycle = way:get_value_by_key("bicycle")
|
|
||||||
|
|
||||||
speed_handler(profile,way,result,data)
|
|
||||||
|
|
||||||
oneway_handler(profile,way,result,data)
|
|
||||||
|
|
||||||
cycleway_handler(profile,way,result,data)
|
|
||||||
|
|
||||||
bike_push_handler(profile,way,result,data)
|
|
||||||
|
|
||||||
-- width should be after bike_push
|
|
||||||
width_handler(profile,way,result,data)
|
|
||||||
|
|
||||||
-- maxspeed
|
|
||||||
limit( result, data.maxspeed, data.maxspeed_forward, data.maxspeed_backward )
|
|
||||||
|
|
||||||
-- not routable if no speed assigned
|
|
||||||
-- this avoid assertions in debug builds
|
|
||||||
if result.forward_speed <= 0 and result.duration <= 0 then
|
|
||||||
result.forward_mode = mode.inaccessible
|
|
||||||
end
|
|
||||||
if result.backward_speed <= 0 and result.duration <= 0 then
|
|
||||||
result.backward_mode = mode.inaccessible
|
|
||||||
end
|
|
||||||
|
|
||||||
safety_handler(profile,way,result,data)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
-- main entry point for processsing a way
|
||||||
function speed_handler(profile,way,result,data)
|
|
||||||
|
|
||||||
data.way_type_allows_pushing = false
|
|
||||||
|
|
||||||
-- speed
|
|
||||||
local bridge_speed = profile.bridge_speeds[data.bridge]
|
|
||||||
if (bridge_speed and bridge_speed > 0) then
|
|
||||||
data.highway = data.bridge
|
|
||||||
if data.duration and durationIsValid(data.duration) then
|
|
||||||
result.duration = math.max( parseDuration(data.duration), 1 )
|
|
||||||
end
|
|
||||||
result.forward_speed = bridge_speed
|
|
||||||
result.backward_speed = bridge_speed
|
|
||||||
data.way_type_allows_pushing = true
|
|
||||||
elseif profile.route_speeds[data.route] then
|
|
||||||
-- ferries (doesn't cover routes tagged using relations)
|
|
||||||
result.forward_mode = mode.ferry
|
|
||||||
result.backward_mode = mode.ferry
|
|
||||||
if data.duration and durationIsValid(data.duration) then
|
|
||||||
result.duration = math.max( 1, parseDuration(data.duration) )
|
|
||||||
else
|
|
||||||
result.forward_speed = profile.route_speeds[data.route]
|
|
||||||
result.backward_speed = profile.route_speeds[data.route]
|
|
||||||
end
|
|
||||||
-- railway platforms (old tagging scheme)
|
|
||||||
elseif data.railway and profile.platform_speeds[data.railway] then
|
|
||||||
result.forward_speed = profile.platform_speeds[data.railway]
|
|
||||||
result.backward_speed = profile.platform_speeds[data.railway]
|
|
||||||
data.way_type_allows_pushing = true
|
|
||||||
-- public_transport platforms (new tagging platform)
|
|
||||||
elseif data.public_transport and profile.platform_speeds[data.public_transport] then
|
|
||||||
result.forward_speed = profile.platform_speeds[data.public_transport]
|
|
||||||
result.backward_speed = profile.platform_speeds[data.public_transport]
|
|
||||||
data.way_type_allows_pushing = true
|
|
||||||
-- railways
|
|
||||||
elseif profile.use_public_transport and data.railway and profile.railway_speeds[data.railway] and profile.access_tag_whitelist[data.access] then
|
|
||||||
result.forward_mode = mode.train
|
|
||||||
result.backward_mode = mode.train
|
|
||||||
result.forward_speed = profile.railway_speeds[data.railway]
|
|
||||||
result.backward_speed = profile.railway_speeds[data.railway]
|
|
||||||
elseif data.amenity and profile.amenity_speeds[data.amenity] then
|
|
||||||
-- parking areas
|
|
||||||
result.forward_speed = profile.amenity_speeds[data.amenity]
|
|
||||||
result.backward_speed = profile.amenity_speeds[data.amenity]
|
|
||||||
data.way_type_allows_pushing = true
|
|
||||||
elseif profile.bicycle_speeds[data.highway] then
|
|
||||||
-- regular ways
|
|
||||||
result.forward_speed = profile.bicycle_speeds[data.highway]
|
|
||||||
result.backward_speed = profile.bicycle_speeds[data.highway]
|
|
||||||
data.way_type_allows_pushing = true
|
|
||||||
elseif data.access and profile.access_tag_whitelist[data.access] then
|
|
||||||
-- unknown way, but valid access tag
|
|
||||||
result.forward_speed = profile.default_speed
|
|
||||||
result.backward_speed = profile.default_speed
|
|
||||||
data.way_type_allows_pushing = true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function oneway_handler(profile,way,result,data)
|
|
||||||
-- oneway
|
|
||||||
data.implied_oneway = data.junction == "roundabout" or data.junction == "circular" or data.highway == "motorway"
|
|
||||||
data.reverse = false
|
|
||||||
|
|
||||||
if data.oneway_bicycle == "yes" or data.oneway_bicycle == "1" or data.oneway_bicycle == "true" then
|
|
||||||
result.backward_mode = mode.inaccessible
|
|
||||||
elseif data.oneway_bicycle == "no" or data.oneway_bicycle == "0" or data.oneway_bicycle == "false" then
|
|
||||||
-- prevent other cases
|
|
||||||
elseif data.oneway_bicycle == "-1" then
|
|
||||||
result.forward_mode = mode.inaccessible
|
|
||||||
data.reverse = true
|
|
||||||
elseif data.oneway == "yes" or data.oneway == "1" or data.oneway == "true" then
|
|
||||||
result.backward_mode = mode.inaccessible
|
|
||||||
elseif data.oneway == "no" or data.oneway == "0" or data.oneway == "false" then
|
|
||||||
-- prevent other cases
|
|
||||||
elseif data.oneway == "-1" then
|
|
||||||
result.forward_mode = mode.inaccessible
|
|
||||||
data.reverse = true
|
|
||||||
elseif data.implied_oneway then
|
|
||||||
result.backward_mode = mode.inaccessible
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function cycleway_handler(profile,way,result,data)
|
|
||||||
-- cycleway
|
|
||||||
data.has_cycleway_forward = false
|
|
||||||
data.has_cycleway_backward = false
|
|
||||||
data.is_twoway = result.forward_mode ~= mode.inaccessible and result.backward_mode ~= mode.inaccessible and not data.implied_oneway
|
|
||||||
|
|
||||||
-- cycleways on normal roads
|
|
||||||
if data.is_twoway then
|
|
||||||
if data.cycleway and profile.cycleway_tags[data.cycleway] then
|
|
||||||
data.has_cycleway_backward = true
|
|
||||||
data.has_cycleway_forward = true
|
|
||||||
end
|
|
||||||
if (data.cycleway_right and profile.cycleway_tags[data.cycleway_right]) or (data.cycleway_left and profile.opposite_cycleway_tags[data.cycleway_left]) then
|
|
||||||
data.has_cycleway_forward = true
|
|
||||||
end
|
|
||||||
if (data.cycleway_left and profile.cycleway_tags[data.cycleway_left]) or (data.cycleway_right and profile.opposite_cycleway_tags[data.cycleway_right]) then
|
|
||||||
data.has_cycleway_backward = true
|
|
||||||
end
|
|
||||||
else
|
|
||||||
local has_twoway_cycleway = (data.cycleway and profile.opposite_cycleway_tags[data.cycleway]) or (data.cycleway_right and profile.opposite_cycleway_tags[data.cycleway_right]) or (data.cycleway_left and profile.opposite_cycleway_tags[data.cycleway_left])
|
|
||||||
local has_opposite_cycleway = (data.cycleway_left and profile.opposite_cycleway_tags[data.cycleway_left]) or (data.cycleway_right and profile.opposite_cycleway_tags[data.cycleway_right])
|
|
||||||
local has_oneway_cycleway = (data.cycleway and profile.cycleway_tags[data.cycleway]) or (data.cycleway_right and profile.cycleway_tags[data.cycleway_right]) or (data.cycleway_left and profile.cycleway_tags[data.cycleway_left])
|
|
||||||
|
|
||||||
-- set cycleway even though it is an one-way if opposite is tagged
|
|
||||||
if has_twoway_cycleway then
|
|
||||||
data.has_cycleway_backward = true
|
|
||||||
data.has_cycleway_forward = true
|
|
||||||
elseif has_opposite_cycleway then
|
|
||||||
if not data.reverse then
|
|
||||||
data.has_cycleway_backward = true
|
|
||||||
else
|
|
||||||
data.has_cycleway_forward = true
|
|
||||||
end
|
|
||||||
elseif has_oneway_cycleway then
|
|
||||||
if not data.reverse then
|
|
||||||
data.has_cycleway_forward = true
|
|
||||||
else
|
|
||||||
data.has_cycleway_backward = true
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
if data.has_cycleway_backward then
|
|
||||||
result.backward_mode = mode.cycling
|
|
||||||
result.backward_speed = profile.bicycle_speeds["cycleway"]
|
|
||||||
end
|
|
||||||
|
|
||||||
if data.has_cycleway_forward then
|
|
||||||
result.forward_mode = mode.cycling
|
|
||||||
result.forward_speed = profile.bicycle_speeds["cycleway"]
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function width_handler(profile,way,result,data)
|
|
||||||
if profile.exclude_cargo_bike then
|
|
||||||
local cargo_bike = way:get_value_by_key("cargo_bike")
|
|
||||||
if cargo_bike and cargo_bike == "no" then
|
|
||||||
result.forward_mode = mode.inaccessible
|
|
||||||
result.backward_mode = mode.inaccessible
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
if profile.width then
|
|
||||||
local width = way:get_value_by_key("width")
|
|
||||||
if width then
|
|
||||||
local width_meter = Measure.parse_value_meters(width)
|
|
||||||
if width_meter and width_meter < profile.width then
|
|
||||||
result.forward_mode = mode.inaccessible
|
|
||||||
result.backward_mode = mode.inaccessible
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function bike_push_handler(profile,way,result,data)
|
|
||||||
-- pushing bikes - if no other mode found
|
|
||||||
if result.forward_mode == mode.inaccessible or result.backward_mode == mode.inaccessible or
|
|
||||||
result.forward_speed == -1 or result.backward_speed == -1 then
|
|
||||||
if data.foot ~= 'no' then
|
|
||||||
local push_forward_speed = nil
|
|
||||||
local push_backward_speed = nil
|
|
||||||
|
|
||||||
if profile.pedestrian_speeds[data.highway] then
|
|
||||||
push_forward_speed = profile.pedestrian_speeds[data.highway]
|
|
||||||
push_backward_speed = profile.pedestrian_speeds[data.highway]
|
|
||||||
elseif data.man_made and profile.man_made_speeds[data.man_made] then
|
|
||||||
push_forward_speed = profile.man_made_speeds[data.man_made]
|
|
||||||
push_backward_speed = profile.man_made_speeds[data.man_made]
|
|
||||||
else
|
|
||||||
if data.foot == 'yes' then
|
|
||||||
push_forward_speed = profile.walking_speed
|
|
||||||
if not data.implied_oneway then
|
|
||||||
push_backward_speed = profile.walking_speed
|
|
||||||
end
|
|
||||||
elseif data.foot_forward == 'yes' then
|
|
||||||
push_forward_speed = profile.walking_speed
|
|
||||||
elseif data.foot_backward == 'yes' then
|
|
||||||
push_backward_speed = profile.walking_speed
|
|
||||||
elseif data.way_type_allows_pushing then
|
|
||||||
push_forward_speed = profile.walking_speed
|
|
||||||
if not data.implied_oneway then
|
|
||||||
push_backward_speed = profile.walking_speed
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
if push_forward_speed and (result.forward_mode == mode.inaccessible or result.forward_speed == -1) then
|
|
||||||
result.forward_mode = mode.pushing_bike
|
|
||||||
result.forward_speed = push_forward_speed
|
|
||||||
end
|
|
||||||
if push_backward_speed and (result.backward_mode == mode.inaccessible or result.backward_speed == -1)then
|
|
||||||
result.backward_mode = mode.pushing_bike
|
|
||||||
result.backward_speed = push_backward_speed
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
-- dismount
|
|
||||||
if data.bicycle == "dismount" then
|
|
||||||
result.forward_mode = mode.pushing_bike
|
|
||||||
result.backward_mode = mode.pushing_bike
|
|
||||||
result.forward_speed = profile.walking_speed
|
|
||||||
result.backward_speed = profile.walking_speed
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function safety_handler(profile,way,result,data)
|
|
||||||
-- convert duration into cyclability
|
|
||||||
if profile.properties.weight_name == 'cyclability' then
|
|
||||||
local safety_penalty = profile.unsafe_highway_list[data.highway] or 1.
|
|
||||||
local is_unsafe = safety_penalty < 1
|
|
||||||
|
|
||||||
-- primaries that are one ways are probably huge primaries where the lanes need to be separated
|
|
||||||
if is_unsafe and data.highway == 'primary' and not data.is_twoway then
|
|
||||||
safety_penalty = safety_penalty * 0.5
|
|
||||||
end
|
|
||||||
if is_unsafe and data.highway == 'secondary' and not data.is_twoway then
|
|
||||||
safety_penalty = safety_penalty * 0.6
|
|
||||||
end
|
|
||||||
|
|
||||||
local forward_is_unsafe = is_unsafe and not data.has_cycleway_forward
|
|
||||||
local backward_is_unsafe = is_unsafe and not data.has_cycleway_backward
|
|
||||||
local is_undesireable = data.highway == "service" and profile.service_penalties[data.service]
|
|
||||||
local forward_penalty = 1.
|
|
||||||
local backward_penalty = 1.
|
|
||||||
if forward_is_unsafe then
|
|
||||||
forward_penalty = math.min(forward_penalty, safety_penalty)
|
|
||||||
end
|
|
||||||
if backward_is_unsafe then
|
|
||||||
backward_penalty = math.min(backward_penalty, safety_penalty)
|
|
||||||
end
|
|
||||||
|
|
||||||
if is_undesireable then
|
|
||||||
forward_penalty = math.min(forward_penalty, profile.service_penalties[data.service])
|
|
||||||
backward_penalty = math.min(backward_penalty, profile.service_penalties[data.service])
|
|
||||||
end
|
|
||||||
|
|
||||||
if result.forward_speed > 0 then
|
|
||||||
-- convert from km/h to m/s
|
|
||||||
result.forward_rate = result.forward_speed / 3.6 * forward_penalty
|
|
||||||
end
|
|
||||||
if result.backward_speed > 0 then
|
|
||||||
-- convert from km/h to m/s
|
|
||||||
result.backward_rate = result.backward_speed / 3.6 * backward_penalty
|
|
||||||
end
|
|
||||||
if result.duration > 0 then
|
|
||||||
result.weight = result.duration / forward_penalty
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function process_way(profile, way, result)
|
function process_way(profile, way, result)
|
||||||
-- the initial filtering of ways based on presence of tags
|
-- the intial filtering of ways based on presence of tags
|
||||||
-- affects processing times significantly, because all ways
|
-- affects processing times significantly, because all ways
|
||||||
-- have to be checked.
|
-- have to be checked.
|
||||||
-- to increase performance, prefetching and initial tag check
|
-- to increase performance, prefetching and intial tag check
|
||||||
-- is done directly instead of via a handler.
|
-- is done in directly instead of via a handler.
|
||||||
|
|
||||||
-- in general we should try to abort as soon as
|
-- in general we should try to abort as soon as
|
||||||
-- possible if the way is not routable, to avoid doing
|
-- possible if the way is not routable, to avoid doing
|
||||||
-- unnecessary work. this implies we should check things that
|
-- unnecessary work. this implies we should check things that
|
||||||
-- commonly forbids access early, and handle edge cases later.
|
-- commonly forbids access early, and handle edge cases later.
|
||||||
|
|
||||||
-- data table for storing intermediate values during processing
|
-- data table for storing intermediate values during processing
|
||||||
|
|
||||||
local data = {
|
local data = {
|
||||||
-- prefetch tags
|
-- prefetch tags
|
||||||
highway = way:get_value_by_key('highway'),
|
highway = way:get_value_by_key("highway"),
|
||||||
|
|
||||||
route = nil,
|
|
||||||
man_made = nil,
|
|
||||||
railway = nil,
|
|
||||||
amenity = nil,
|
|
||||||
public_transport = nil,
|
|
||||||
bridge = nil,
|
|
||||||
|
|
||||||
access = nil,
|
|
||||||
|
|
||||||
junction = nil,
|
|
||||||
maxspeed = nil,
|
|
||||||
maxspeed_forward = nil,
|
|
||||||
maxspeed_backward = nil,
|
|
||||||
barrier = nil,
|
|
||||||
oneway = nil,
|
|
||||||
oneway_bicycle = nil,
|
|
||||||
cycleway = nil,
|
|
||||||
cycleway_left = nil,
|
|
||||||
cycleway_right = nil,
|
|
||||||
duration = nil,
|
|
||||||
service = nil,
|
|
||||||
foot = nil,
|
|
||||||
foot_forward = nil,
|
|
||||||
foot_backward = nil,
|
|
||||||
bicycle = nil,
|
|
||||||
|
|
||||||
way_type_allows_pushing = false,
|
|
||||||
has_cycleway_forward = false,
|
|
||||||
has_cycleway_backward = false,
|
|
||||||
is_twoway = true,
|
|
||||||
reverse = false,
|
|
||||||
implied_oneway = false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
-- Verificar si el objeto `way` está definido
|
||||||
|
if not way then
|
||||||
|
print("Error: way is nil.")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
-- perform an quick initial check and abort if the way is
|
||||||
|
-- obviously not routable. here we require at least one
|
||||||
|
-- of the prefetched tags to be present, ie. the data table
|
||||||
|
-- cannot be empty
|
||||||
|
if next(data) == nil then -- is the data table empty?
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
local handlers = Sequence {
|
local handlers = Sequence {
|
||||||
-- set the default mode for this profile. if can be changed later
|
-- set the default mode for this profile. if can be changed later
|
||||||
-- in case it turns we're e.g. on a ferry
|
-- in case it turns we're e.g. on a ferry
|
||||||
@ -664,61 +279,82 @@ function process_way(profile, way, result)
|
|||||||
-- toll=yes and oneway=reversible
|
-- toll=yes and oneway=reversible
|
||||||
WayHandlers.blocked_ways,
|
WayHandlers.blocked_ways,
|
||||||
|
|
||||||
-- our main handler
|
-- determine access status by checking our hierarchy of
|
||||||
handle_bicycle_tags,
|
-- access tags, e.g: motorcar, motor_vehicle, vehicle
|
||||||
|
WayHandlers.access,
|
||||||
|
|
||||||
|
-- check whether forward/backward directons are routable
|
||||||
|
WayHandlers.oneway,
|
||||||
|
|
||||||
|
-- check whether forward/backward directons are routable
|
||||||
|
WayHandlers.destinations,
|
||||||
|
|
||||||
|
-- check whether we're using a special transport mode
|
||||||
|
WayHandlers.ferries,
|
||||||
|
WayHandlers.movables,
|
||||||
|
|
||||||
-- compute speed taking into account way type, maxspeed tags, etc.
|
-- compute speed taking into account way type, maxspeed tags, etc.
|
||||||
|
WayHandlers.speed,
|
||||||
WayHandlers.surface,
|
WayHandlers.surface,
|
||||||
|
|
||||||
-- handle turn lanes and road classification, used for guidance
|
-- handle turn lanes and road classification, used for guidance
|
||||||
WayHandlers.classification,
|
WayHandlers.classification,
|
||||||
|
|
||||||
-- handle allowed start/end modes
|
-- handle various other flags
|
||||||
WayHandlers.startpoint,
|
|
||||||
|
|
||||||
-- handle roundabouts
|
|
||||||
WayHandlers.roundabouts,
|
WayHandlers.roundabouts,
|
||||||
|
WayHandlers.startpoint,
|
||||||
|
|
||||||
-- set name, ref and pronunciation
|
-- set name, ref and pronunciation
|
||||||
WayHandlers.names,
|
WayHandlers.names,
|
||||||
|
|
||||||
-- set classes
|
|
||||||
WayHandlers.classes,
|
|
||||||
|
|
||||||
-- set weight properties of the way
|
-- set weight properties of the way
|
||||||
WayHandlers.weights
|
WayHandlers.weights,
|
||||||
}
|
}
|
||||||
|
|
||||||
WayHandlers.run(profile, way, result, data, handlers)
|
WayHandlers.run(profile, way, result, data, handlers)
|
||||||
end
|
end
|
||||||
|
|
||||||
function process_turn(profile, turn)
|
function process_turn (profile, turn)
|
||||||
-- compute turn penalty as angle^2, with a left/right bias
|
turn.duration = 0.
|
||||||
local normalized_angle = turn.angle / 90.0
|
|
||||||
if normalized_angle >= 0.0 then
|
|
||||||
turn.duration = normalized_angle * normalized_angle * profile.turn_penalty / profile.turn_bias
|
|
||||||
else
|
|
||||||
turn.duration = normalized_angle * normalized_angle * profile.turn_penalty * profile.turn_bias
|
|
||||||
end
|
|
||||||
|
|
||||||
if turn.is_u_turn then
|
if turn.direction_modifier == direction_modifier.u_turn then
|
||||||
turn.duration = turn.duration + profile.properties.u_turn_penalty
|
turn.duration = turn.duration + profile.properties.u_turn_penalty
|
||||||
end
|
end
|
||||||
|
|
||||||
if turn.has_traffic_light then
|
if turn.has_traffic_light then
|
||||||
turn.duration = turn.duration + profile.properties.traffic_light_penalty
|
turn.duration = profile.properties.traffic_light_penalty
|
||||||
end
|
end
|
||||||
if profile.properties.weight_name == 'cyclability' then
|
if profile.properties.weight_name == 'routability' then
|
||||||
turn.weight = turn.duration
|
-- penalize turns from non-local access only segments onto local access only tags
|
||||||
end
|
if not turn.source_restricted and turn.target_restricted then
|
||||||
if turn.source_mode == mode.cycling and turn.target_mode ~= mode.cycling then
|
turn.weight = turn.weight + 3000
|
||||||
turn.weight = turn.weight + profile.properties.mode_change_penalty
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function process_segment(profile, segment)
|
||||||
|
-- Extract coordinates of the start and end points
|
||||||
|
local source_lat, source_lon = segment.source.lat, segment.source.lon
|
||||||
|
local target_lat, target_lon = segment.target.lat, segment.target.lon
|
||||||
|
|
||||||
|
-- Calculate pollution impact at source and target
|
||||||
|
local pollution_source = calculate_pollution(source_lat, source_lon)
|
||||||
|
local pollution_target = calculate_pollution(target_lat, target_lon)
|
||||||
|
|
||||||
|
|
||||||
|
-- Average pollution for the segment
|
||||||
|
local avg_pollution = (pollution_source + pollution_target) / 2
|
||||||
|
--print(avg_pollution)
|
||||||
|
|
||||||
|
-- Adjust weight and duration based on pollution level
|
||||||
|
segment.weight = segment.weight + (avg_pollution^1.4)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
setup = setup,
|
setup = setup,
|
||||||
process_way = process_way,
|
process_way = process_way,
|
||||||
process_node = process_node,
|
process_node = process_node,
|
||||||
process_turn = process_turn
|
process_turn = process_turn,
|
||||||
|
process_segment = process_segment
|
||||||
}
|
}
|
||||||
|
559
profiles/car.lua
559
profiles/car.lua
@ -1,376 +1,242 @@
|
|||||||
-- Car profile
|
|
||||||
|
|
||||||
api_version = 4
|
-- Foot profile
|
||||||
|
local http = require("socket.http") -- LuaSocket for HTTP requests
|
||||||
|
local json = require("cjson")
|
||||||
|
|
||||||
|
api_version = 2
|
||||||
|
|
||||||
Set = require('lib/set')
|
Set = require('lib/set')
|
||||||
Sequence = require('lib/sequence')
|
Sequence = require('lib/sequence')
|
||||||
Handlers = require("lib/way_handlers")
|
Handlers = require("lib/way_handlers")
|
||||||
Relations = require("lib/relations")
|
|
||||||
TrafficSignal = require("lib/traffic_signal")
|
|
||||||
find_access_tag = require("lib/access").find_access_tag
|
find_access_tag = require("lib/access").find_access_tag
|
||||||
limit = require("lib/maxspeed").limit
|
stations_data = nil
|
||||||
Utils = require("lib/utils")
|
|
||||||
Measure = require("lib/measure")
|
|
||||||
|
function fetch_pollution_data()
|
||||||
|
local url = "http://128.199.51.173:8000/routes/api/pollution/PM2.5/"
|
||||||
|
local response, status = http.request(url)
|
||||||
|
|
||||||
|
if status == 200 and response then
|
||||||
|
print("Raw response:", response)
|
||||||
|
local success, data = pcall(json.decode, response) -- Manejar errores de JSON
|
||||||
|
if success and data and data.stations then
|
||||||
|
print("Pollution data fetched successfully.")
|
||||||
|
print("Number of stations:", #data.stations)
|
||||||
|
return data
|
||||||
|
else
|
||||||
|
print("Failed to decode JSON or missing 'stations' key.")
|
||||||
|
end
|
||||||
|
else
|
||||||
|
print("HTTP request failed. Status:", status)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Fallback a datos vacíos si hay un error
|
||||||
|
return { stations = {} }
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function setup()
|
function setup()
|
||||||
|
local walking_speed = 5
|
||||||
|
stations_data = fetch_pollution_data()
|
||||||
|
|
||||||
|
-- Check if data was successfully retrieved
|
||||||
|
if not stations_data or not stations_data.stations then
|
||||||
|
print("Warning: Pollution data could not be loaded. Defaulting to no pollution.")
|
||||||
|
stations_data = { stations = {} } -- Fallback to empty station data
|
||||||
|
else
|
||||||
|
print("Pollution data loaded successfully.")
|
||||||
|
end
|
||||||
return {
|
return {
|
||||||
properties = {
|
properties = {
|
||||||
max_speed_for_map_matching = 180/3.6, -- 180kmph -> m/s
|
weight_name = 'duration',
|
||||||
-- For routing based on duration, but weighted for preferring certain roads
|
max_speed_for_map_matching = 40/3.6, -- kmph -> m/s
|
||||||
weight_name = 'routability',
|
call_tagless_node_function = false,
|
||||||
-- For shortest duration without penalties for accessibility
|
traffic_light_penalty = 2,
|
||||||
-- weight_name = 'duration',
|
u_turn_penalty = 2,
|
||||||
-- For shortest distance without penalties for accessibility
|
continue_straight_at_waypoint = false,
|
||||||
-- weight_name = 'distance',
|
use_turn_restrictions = false,
|
||||||
process_call_tagless_node = false,
|
|
||||||
u_turn_penalty = 20,
|
|
||||||
continue_straight_at_waypoint = true,
|
|
||||||
use_turn_restrictions = true,
|
|
||||||
left_hand_driving = false,
|
|
||||||
traffic_light_penalty = 2,
|
|
||||||
},
|
},
|
||||||
|
|
||||||
default_mode = mode.driving,
|
default_mode = mode.walking,
|
||||||
default_speed = 10,
|
default_speed = walking_speed,
|
||||||
oneway_handling = true,
|
oneway_handling = 'specific', -- respect 'oneway:foot' but not 'oneway'
|
||||||
side_road_multiplier = 0.8,
|
|
||||||
turn_penalty = 7.5,
|
|
||||||
speed_reduction = 0.8,
|
|
||||||
turn_bias = 1.075,
|
|
||||||
cardinal_directions = false,
|
|
||||||
|
|
||||||
-- Size of the vehicle, to be limited by physical restriction of the way
|
barrier_blacklist = Set {
|
||||||
vehicle_height = 2.0, -- in meters, 2.0m is the height slightly above biggest SUVs
|
'yes',
|
||||||
vehicle_width = 1.9, -- in meters, ways with narrow tag are considered narrower than 2.2m
|
'wall',
|
||||||
|
'fence'
|
||||||
-- Size of the vehicle, to be limited mostly by legal restriction of the way
|
|
||||||
vehicle_length = 4.8, -- in meters, 4.8m is the length of large or family car
|
|
||||||
vehicle_weight = 2000, -- in kilograms
|
|
||||||
|
|
||||||
-- a list of suffixes to suppress in name change instructions. The suffixes also include common substrings of each other
|
|
||||||
suffix_list = {
|
|
||||||
'N', 'NE', 'E', 'SE', 'S', 'SW', 'W', 'NW', 'North', 'South', 'West', 'East', 'Nor', 'Sou', 'We', 'Ea'
|
|
||||||
},
|
|
||||||
|
|
||||||
barrier_whitelist = Set {
|
|
||||||
'cattle_grid',
|
|
||||||
'border_control',
|
|
||||||
'toll_booth',
|
|
||||||
'sally_port',
|
|
||||||
'gate',
|
|
||||||
'lift_gate',
|
|
||||||
'no',
|
|
||||||
'entrance',
|
|
||||||
'height_restrictor',
|
|
||||||
'arch'
|
|
||||||
},
|
},
|
||||||
|
|
||||||
access_tag_whitelist = Set {
|
access_tag_whitelist = Set {
|
||||||
'yes',
|
'yes',
|
||||||
'motorcar',
|
'foot',
|
||||||
'motor_vehicle',
|
|
||||||
'vehicle',
|
|
||||||
'permissive',
|
'permissive',
|
||||||
'designated',
|
'designated'
|
||||||
'hov'
|
|
||||||
},
|
},
|
||||||
|
|
||||||
access_tag_blacklist = Set {
|
access_tag_blacklist = Set {
|
||||||
'no',
|
'no',
|
||||||
'agricultural',
|
'agricultural',
|
||||||
'forestry',
|
'forestry',
|
||||||
'emergency',
|
|
||||||
'psv',
|
|
||||||
'customers',
|
|
||||||
'private',
|
'private',
|
||||||
'delivery',
|
'delivery',
|
||||||
'destination'
|
|
||||||
},
|
},
|
||||||
|
|
||||||
-- tags disallow access to in combination with highway=service
|
restricted_access_tag_list = Set { },
|
||||||
service_access_tag_blacklist = Set {
|
|
||||||
'private'
|
|
||||||
},
|
|
||||||
|
|
||||||
restricted_access_tag_list = Set {
|
restricted_highway_whitelist = Set { },
|
||||||
'private',
|
|
||||||
'delivery',
|
construction_whitelist = Set {},
|
||||||
'destination',
|
|
||||||
'customers',
|
|
||||||
},
|
|
||||||
|
|
||||||
access_tags_hierarchy = Sequence {
|
access_tags_hierarchy = Sequence {
|
||||||
'motorcar',
|
'foot',
|
||||||
'motor_vehicle',
|
|
||||||
'vehicle',
|
|
||||||
'access'
|
'access'
|
||||||
},
|
},
|
||||||
|
|
||||||
service_tag_forbidden = Set {
|
-- tags disallow access to in combination with highway=service
|
||||||
'emergency_access'
|
service_access_tag_blacklist = Set { },
|
||||||
},
|
|
||||||
|
|
||||||
restrictions = Sequence {
|
restrictions = Sequence {
|
||||||
'motorcar',
|
'foot'
|
||||||
'motor_vehicle',
|
|
||||||
'vehicle'
|
|
||||||
},
|
},
|
||||||
|
|
||||||
classes = Sequence {
|
-- list of suffixes to suppress in name change instructions
|
||||||
'toll', 'motorway', 'ferry', 'restricted', 'tunnel'
|
suffix_list = Set {
|
||||||
},
|
'N', 'NE', 'E', 'SE', 'S', 'SW', 'W', 'NW', 'North', 'South', 'West', 'East'
|
||||||
|
|
||||||
-- classes to support for exclude flags
|
|
||||||
excludable = Sequence {
|
|
||||||
Set {'toll'},
|
|
||||||
Set {'motorway'},
|
|
||||||
Set {'ferry'}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
avoid = Set {
|
avoid = Set {
|
||||||
'area',
|
|
||||||
-- 'toll', -- uncomment this to avoid tolls
|
|
||||||
'reversible',
|
|
||||||
'impassable',
|
'impassable',
|
||||||
'hov_lanes',
|
|
||||||
'steps',
|
|
||||||
'construction',
|
|
||||||
'proposed'
|
'proposed'
|
||||||
},
|
},
|
||||||
|
|
||||||
speeds = Sequence {
|
speeds = Sequence {
|
||||||
highway = {
|
highway = {
|
||||||
motorway = 90,
|
primary = walking_speed,
|
||||||
motorway_link = 45,
|
primary_link = walking_speed,
|
||||||
trunk = 85,
|
secondary = walking_speed,
|
||||||
trunk_link = 40,
|
secondary_link = walking_speed,
|
||||||
primary = 65,
|
tertiary = walking_speed,
|
||||||
primary_link = 30,
|
tertiary_link = walking_speed,
|
||||||
secondary = 55,
|
unclassified = walking_speed,
|
||||||
secondary_link = 25,
|
residential = walking_speed,
|
||||||
tertiary = 40,
|
road = walking_speed,
|
||||||
tertiary_link = 20,
|
living_street = walking_speed,
|
||||||
unclassified = 25,
|
service = walking_speed,
|
||||||
residential = 25,
|
track = walking_speed,
|
||||||
living_street = 10,
|
path = walking_speed,
|
||||||
service = 15
|
steps = walking_speed,
|
||||||
|
pedestrian = walking_speed,
|
||||||
|
platform = walking_speed,
|
||||||
|
footway = walking_speed,
|
||||||
|
pier = walking_speed,
|
||||||
|
},
|
||||||
|
|
||||||
|
railway = {
|
||||||
|
platform = walking_speed
|
||||||
|
},
|
||||||
|
|
||||||
|
amenity = {
|
||||||
|
parking = walking_speed,
|
||||||
|
parking_entrance= walking_speed
|
||||||
|
},
|
||||||
|
|
||||||
|
man_made = {
|
||||||
|
pier = walking_speed
|
||||||
|
},
|
||||||
|
|
||||||
|
leisure = {
|
||||||
|
track = walking_speed
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
service_penalties = {
|
|
||||||
alley = 0.5,
|
|
||||||
parking = 0.5,
|
|
||||||
parking_aisle = 0.5,
|
|
||||||
driveway = 0.5,
|
|
||||||
["drive-through"] = 0.5,
|
|
||||||
["drive-thru"] = 0.5
|
|
||||||
},
|
|
||||||
|
|
||||||
restricted_highway_whitelist = Set {
|
|
||||||
'motorway',
|
|
||||||
'motorway_link',
|
|
||||||
'trunk',
|
|
||||||
'trunk_link',
|
|
||||||
'primary',
|
|
||||||
'primary_link',
|
|
||||||
'secondary',
|
|
||||||
'secondary_link',
|
|
||||||
'tertiary',
|
|
||||||
'tertiary_link',
|
|
||||||
'residential',
|
|
||||||
'living_street',
|
|
||||||
'unclassified',
|
|
||||||
'service'
|
|
||||||
},
|
|
||||||
|
|
||||||
construction_whitelist = Set {
|
|
||||||
'no',
|
|
||||||
'widening',
|
|
||||||
'minor',
|
|
||||||
},
|
|
||||||
|
|
||||||
route_speeds = {
|
route_speeds = {
|
||||||
ferry = 5,
|
ferry = 5
|
||||||
shuttle_train = 10
|
|
||||||
},
|
},
|
||||||
|
|
||||||
bridge_speeds = {
|
bridge_speeds = {
|
||||||
movable = 5
|
|
||||||
},
|
},
|
||||||
|
|
||||||
-- surface/trackype/smoothness
|
|
||||||
-- values were estimated from looking at the photos at the relevant wiki pages
|
|
||||||
|
|
||||||
-- max speed for surfaces
|
|
||||||
surface_speeds = {
|
surface_speeds = {
|
||||||
asphalt = nil, -- nil mean no limit. removing the line has the same effect
|
fine_gravel = walking_speed*0.75,
|
||||||
concrete = nil,
|
gravel = walking_speed*0.75,
|
||||||
["concrete:plates"] = nil,
|
pebblestone = walking_speed*0.75,
|
||||||
["concrete:lanes"] = nil,
|
mud = walking_speed*0.5,
|
||||||
paved = nil,
|
sand = walking_speed*0.5
|
||||||
|
|
||||||
cement = 80,
|
|
||||||
compacted = 80,
|
|
||||||
fine_gravel = 80,
|
|
||||||
|
|
||||||
paving_stones = 60,
|
|
||||||
metal = 60,
|
|
||||||
bricks = 60,
|
|
||||||
|
|
||||||
grass = 40,
|
|
||||||
wood = 40,
|
|
||||||
sett = 40,
|
|
||||||
grass_paver = 40,
|
|
||||||
gravel = 40,
|
|
||||||
unpaved = 40,
|
|
||||||
ground = 40,
|
|
||||||
dirt = 40,
|
|
||||||
pebblestone = 40,
|
|
||||||
tartan = 40,
|
|
||||||
|
|
||||||
cobblestone = 30,
|
|
||||||
clay = 30,
|
|
||||||
|
|
||||||
earth = 20,
|
|
||||||
stone = 20,
|
|
||||||
rocky = 20,
|
|
||||||
sand = 20,
|
|
||||||
|
|
||||||
mud = 10
|
|
||||||
},
|
},
|
||||||
|
|
||||||
-- max speed for tracktypes
|
|
||||||
tracktype_speeds = {
|
tracktype_speeds = {
|
||||||
grade1 = 60,
|
|
||||||
grade2 = 40,
|
|
||||||
grade3 = 30,
|
|
||||||
grade4 = 25,
|
|
||||||
grade5 = 20
|
|
||||||
},
|
},
|
||||||
|
|
||||||
-- max speed for smoothnesses
|
|
||||||
smoothness_speeds = {
|
smoothness_speeds = {
|
||||||
intermediate = 80,
|
|
||||||
bad = 40,
|
|
||||||
very_bad = 20,
|
|
||||||
horrible = 10,
|
|
||||||
very_horrible = 5,
|
|
||||||
impassable = 0
|
|
||||||
},
|
|
||||||
|
|
||||||
-- http://wiki.openstreetmap.org/wiki/Speed_limits
|
|
||||||
maxspeed_table_default = {
|
|
||||||
urban = 50,
|
|
||||||
rural = 90,
|
|
||||||
trunk = 110,
|
|
||||||
motorway = 130
|
|
||||||
},
|
|
||||||
|
|
||||||
-- List only exceptions
|
|
||||||
maxspeed_table = {
|
|
||||||
["at:rural"] = 100,
|
|
||||||
["at:trunk"] = 100,
|
|
||||||
["be:motorway"] = 120,
|
|
||||||
["be-bru:rural"] = 70,
|
|
||||||
["be-bru:urban"] = 30,
|
|
||||||
["be-vlg:rural"] = 70,
|
|
||||||
["bg:motorway"] = 140,
|
|
||||||
["by:urban"] = 60,
|
|
||||||
["by:motorway"] = 110,
|
|
||||||
["ca-on:rural"] = 80,
|
|
||||||
["ch:rural"] = 80,
|
|
||||||
["ch:trunk"] = 100,
|
|
||||||
["ch:motorway"] = 120,
|
|
||||||
["cz:trunk"] = 0,
|
|
||||||
["cz:motorway"] = 0,
|
|
||||||
["de:living_street"] = 7,
|
|
||||||
["de:rural"] = 100,
|
|
||||||
["de:motorway"] = 0,
|
|
||||||
["dk:rural"] = 80,
|
|
||||||
["es:trunk"] = 90,
|
|
||||||
["fr:rural"] = 80,
|
|
||||||
["gb:nsl_single"] = (60*1609)/1000,
|
|
||||||
["gb:nsl_dual"] = (70*1609)/1000,
|
|
||||||
["gb:motorway"] = (70*1609)/1000,
|
|
||||||
["nl:rural"] = 80,
|
|
||||||
["nl:trunk"] = 100,
|
|
||||||
['no:rural'] = 80,
|
|
||||||
['no:motorway'] = 110,
|
|
||||||
['ph:urban'] = 40,
|
|
||||||
['ph:rural'] = 80,
|
|
||||||
['ph:motorway'] = 100,
|
|
||||||
['pl:rural'] = 100,
|
|
||||||
['pl:trunk'] = 120,
|
|
||||||
['pl:motorway'] = 140,
|
|
||||||
["ro:trunk"] = 100,
|
|
||||||
["ru:living_street"] = 20,
|
|
||||||
["ru:urban"] = 60,
|
|
||||||
["ru:motorway"] = 110,
|
|
||||||
["uk:nsl_single"] = (60*1609)/1000,
|
|
||||||
["uk:nsl_dual"] = (70*1609)/1000,
|
|
||||||
["uk:motorway"] = (70*1609)/1000,
|
|
||||||
['za:urban'] = 60,
|
|
||||||
['za:rural'] = 100,
|
|
||||||
["none"] = 140
|
|
||||||
},
|
|
||||||
|
|
||||||
relation_types = Sequence {
|
|
||||||
"route"
|
|
||||||
},
|
|
||||||
|
|
||||||
-- classify highway tags when necessary for turn weights
|
|
||||||
highway_turn_classification = {
|
|
||||||
},
|
|
||||||
|
|
||||||
-- classify access tags when necessary for turn weights
|
|
||||||
access_turn_classification = {
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
function process_node(profile, node, result, relations)
|
function calculate_pollution(lat, lon)
|
||||||
-- parse access and barrier tags
|
-- Calcular contaminación
|
||||||
|
local pollution_value = 0
|
||||||
|
local total_weight = 0
|
||||||
|
local weight = 0
|
||||||
|
local p = 1.8
|
||||||
|
local max_distance = 3
|
||||||
|
if stations_data and stations_data.stations then
|
||||||
|
for _, station in ipairs(stations_data.stations) do
|
||||||
|
local station_lat = tonumber(station.lat)
|
||||||
|
local station_lon = tonumber(station.lon)
|
||||||
|
local latest_reading = tonumber(station.pollution)
|
||||||
|
|
||||||
|
if station_lat and station_lon and latest_reading then
|
||||||
|
-- Fórmula de distancia usando Haversine
|
||||||
|
local R = 6371 -- Radio de la Tierra en km
|
||||||
|
local dlat = math.rad(station_lat - lat)
|
||||||
|
local dlon = math.rad(station_lon - lon)
|
||||||
|
local a = math.sin(dlat / 2)^2 +
|
||||||
|
math.cos(math.rad(lat)) * math.cos(math.rad(station_lat)) * math.sin(dlon / 2)^2
|
||||||
|
local c = 2 * math.atan2(math.sqrt(a), math.sqrt(1 - a))
|
||||||
|
local distance = R * c
|
||||||
|
|
||||||
|
-- Ponderación ajustada
|
||||||
|
weight = 1 / ((distance + 1))
|
||||||
|
weight = tonumber(string.format("%.6f", weight))
|
||||||
|
pollution_value = pollution_value + (latest_reading * weight)
|
||||||
|
--total_weight = total_weight + weight
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
||||||
|
--print(pollution_value)
|
||||||
|
return pollution_value
|
||||||
|
else
|
||||||
|
print("No station data available.")
|
||||||
|
return 0
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function process_node(profile, node, result)
|
||||||
|
-- Parse access and barrier tags
|
||||||
local access = find_access_tag(node, profile.access_tags_hierarchy)
|
local access = find_access_tag(node, profile.access_tags_hierarchy)
|
||||||
if access then
|
if access then
|
||||||
if profile.access_tag_blacklist[access] and not profile.restricted_access_tag_list[access] then
|
if profile.access_tag_blacklist[access] then
|
||||||
result.barrier = true
|
result.barrier = true
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
local barrier = node:get_value_by_key("barrier")
|
local barrier = node:get_value_by_key("barrier")
|
||||||
if barrier then
|
if barrier then
|
||||||
-- check height restriction barriers
|
-- Make an exception for rising bollard barriers
|
||||||
local restricted_by_height = false
|
|
||||||
if barrier == 'height_restrictor' then
|
|
||||||
local maxheight = Measure.get_max_height(node:get_value_by_key("maxheight"), node)
|
|
||||||
restricted_by_height = maxheight and maxheight < profile.vehicle_height
|
|
||||||
end
|
|
||||||
|
|
||||||
-- make an exception for rising bollard barriers
|
|
||||||
local bollard = node:get_value_by_key("bollard")
|
local bollard = node:get_value_by_key("bollard")
|
||||||
local rising_bollard = bollard and "rising" == bollard
|
local rising_bollard = bollard and "rising" == bollard
|
||||||
|
|
||||||
-- make an exception for lowered/flat barrier=kerb
|
if profile.barrier_blacklist[barrier] and not rising_bollard then
|
||||||
-- and incorrect tagging of highway crossing kerb as highway barrier
|
|
||||||
local kerb = node:get_value_by_key("kerb")
|
|
||||||
local highway = node:get_value_by_key("highway")
|
|
||||||
local flat_kerb = kerb and ("lowered" == kerb or "flush" == kerb)
|
|
||||||
local highway_crossing_kerb = barrier == "kerb" and highway and highway == "crossing"
|
|
||||||
|
|
||||||
if not profile.barrier_whitelist[barrier]
|
|
||||||
and not rising_bollard
|
|
||||||
and not flat_kerb
|
|
||||||
and not highway_crossing_kerb
|
|
||||||
or restricted_by_height then
|
|
||||||
result.barrier = true
|
result.barrier = true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- check if node is a traffic light
|
|
||||||
result.traffic_lights = TrafficSignal.get_value(node)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function process_way(profile, way, result, relations)
|
|
||||||
|
-- main entry point for processsing a way
|
||||||
|
function process_way(profile, way, result)
|
||||||
-- the intial filtering of ways based on presence of tags
|
-- the intial filtering of ways based on presence of tags
|
||||||
-- affects processing times significantly, because all ways
|
-- affects processing times significantly, because all ways
|
||||||
-- have to be checked.
|
-- have to be checked.
|
||||||
@ -385,21 +251,25 @@ function process_way(profile, way, result, relations)
|
|||||||
-- data table for storing intermediate values during processing
|
-- data table for storing intermediate values during processing
|
||||||
local data = {
|
local data = {
|
||||||
-- prefetch tags
|
-- prefetch tags
|
||||||
highway = way:get_value_by_key('highway'),
|
highway = way:get_value_by_key("highway"),
|
||||||
bridge = way:get_value_by_key('bridge'),
|
|
||||||
route = way:get_value_by_key('route')
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
-- Verificar si el objeto `way` está definido
|
||||||
|
if not way then
|
||||||
|
print("Error: way is nil.")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
-- perform an quick initial check and abort if the way is
|
-- perform an quick initial check and abort if the way is
|
||||||
-- obviously not routable.
|
-- obviously not routable. here we require at least one
|
||||||
-- highway or route tags must be in data table, bridge is optional
|
-- of the prefetched tags to be present, ie. the data table
|
||||||
if (not data.highway or data.highway == '') and
|
-- cannot be empty
|
||||||
(not data.route or data.route == '')
|
if next(data) == nil then -- is the data table empty?
|
||||||
then
|
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
handlers = Sequence {
|
local handlers = Sequence {
|
||||||
-- set the default mode for this profile. if can be changed later
|
-- set the default mode for this profile. if can be changed later
|
||||||
-- in case it turns we're e.g. on a ferry
|
-- in case it turns we're e.g. on a ferry
|
||||||
WayHandlers.default_mode,
|
WayHandlers.default_mode,
|
||||||
@ -408,108 +278,83 @@ function process_way(profile, way, result, relations)
|
|||||||
-- routable. this includes things like status=impassable,
|
-- routable. this includes things like status=impassable,
|
||||||
-- toll=yes and oneway=reversible
|
-- toll=yes and oneway=reversible
|
||||||
WayHandlers.blocked_ways,
|
WayHandlers.blocked_ways,
|
||||||
WayHandlers.avoid_ways,
|
|
||||||
WayHandlers.handle_height,
|
|
||||||
WayHandlers.handle_width,
|
|
||||||
WayHandlers.handle_length,
|
|
||||||
WayHandlers.handle_weight,
|
|
||||||
|
|
||||||
-- determine access status by checking our hierarchy of
|
-- determine access status by checking our hierarchy of
|
||||||
-- access tags, e.g: motorcar, motor_vehicle, vehicle
|
-- access tags, e.g: motorcar, motor_vehicle, vehicle
|
||||||
WayHandlers.access,
|
WayHandlers.access,
|
||||||
|
|
||||||
-- check whether forward/backward directions are routable
|
-- check whether forward/backward directons are routable
|
||||||
WayHandlers.oneway,
|
WayHandlers.oneway,
|
||||||
|
|
||||||
-- check a road's destination
|
-- check whether forward/backward directons are routable
|
||||||
WayHandlers.destinations,
|
WayHandlers.destinations,
|
||||||
|
|
||||||
-- check whether we're using a special transport mode
|
-- check whether we're using a special transport mode
|
||||||
WayHandlers.ferries,
|
WayHandlers.ferries,
|
||||||
WayHandlers.movables,
|
WayHandlers.movables,
|
||||||
|
|
||||||
-- handle service road restrictions
|
|
||||||
WayHandlers.service,
|
|
||||||
|
|
||||||
-- handle hov
|
|
||||||
WayHandlers.hov,
|
|
||||||
|
|
||||||
-- compute speed taking into account way type, maxspeed tags, etc.
|
-- compute speed taking into account way type, maxspeed tags, etc.
|
||||||
WayHandlers.speed,
|
WayHandlers.speed,
|
||||||
WayHandlers.maxspeed,
|
|
||||||
WayHandlers.surface,
|
WayHandlers.surface,
|
||||||
WayHandlers.penalties,
|
|
||||||
|
|
||||||
-- compute class labels
|
|
||||||
WayHandlers.classes,
|
|
||||||
|
|
||||||
-- handle turn lanes and road classification, used for guidance
|
-- handle turn lanes and road classification, used for guidance
|
||||||
WayHandlers.turn_lanes,
|
|
||||||
WayHandlers.classification,
|
WayHandlers.classification,
|
||||||
|
|
||||||
-- handle various other flags
|
-- handle various other flags
|
||||||
WayHandlers.roundabouts,
|
WayHandlers.roundabouts,
|
||||||
WayHandlers.startpoint,
|
WayHandlers.startpoint,
|
||||||
WayHandlers.driving_side,
|
|
||||||
|
|
||||||
-- set name, ref and pronunciation
|
-- set name, ref and pronunciation
|
||||||
WayHandlers.names,
|
WayHandlers.names,
|
||||||
|
|
||||||
-- set weight properties of the way
|
-- set weight properties of the way
|
||||||
WayHandlers.weights,
|
WayHandlers.weights,
|
||||||
|
|
||||||
-- set classification of ways relevant for turns
|
|
||||||
WayHandlers.way_classification_for_turn
|
|
||||||
}
|
}
|
||||||
|
|
||||||
WayHandlers.run(profile, way, result, data, handlers, relations)
|
WayHandlers.run(profile, way, result, data, handlers)
|
||||||
|
|
||||||
if profile.cardinal_directions then
|
|
||||||
Relations.process_way_refs(way, relations, result)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function process_turn(profile, turn)
|
function process_turn (profile, turn)
|
||||||
-- Use a sigmoid function to return a penalty that maxes out at turn_penalty
|
turn.duration = 0.
|
||||||
-- over the space of 0-180 degrees. Values here were chosen by fitting
|
|
||||||
-- the function to some turn penalty samples from real driving.
|
if turn.direction_modifier == direction_modifier.u_turn then
|
||||||
local turn_penalty = profile.turn_penalty
|
turn.duration = turn.duration + profile.properties.u_turn_penalty
|
||||||
local turn_bias = turn.is_left_hand_driving and 1. / profile.turn_bias or profile.turn_bias
|
end
|
||||||
|
|
||||||
if turn.has_traffic_light then
|
if turn.has_traffic_light then
|
||||||
turn.duration = profile.properties.traffic_light_penalty
|
turn.duration = profile.properties.traffic_light_penalty
|
||||||
end
|
end
|
||||||
|
|
||||||
if turn.number_of_roads > 2 or turn.source_mode ~= turn.target_mode or turn.is_u_turn then
|
|
||||||
if turn.angle >= 0 then
|
|
||||||
turn.duration = turn.duration + turn_penalty / (1 + math.exp( -((13 / turn_bias) * turn.angle/180 - 6.5*turn_bias)))
|
|
||||||
else
|
|
||||||
turn.duration = turn.duration + turn_penalty / (1 + math.exp( -((13 * turn_bias) * -turn.angle/180 - 6.5/turn_bias)))
|
|
||||||
end
|
|
||||||
|
|
||||||
if turn.is_u_turn then
|
|
||||||
turn.duration = turn.duration + profile.properties.u_turn_penalty
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- for distance based routing we don't want to have penalties based on turn angle
|
|
||||||
if profile.properties.weight_name == 'distance' then
|
|
||||||
turn.weight = 0
|
|
||||||
else
|
|
||||||
turn.weight = turn.duration
|
|
||||||
end
|
|
||||||
|
|
||||||
if profile.properties.weight_name == 'routability' then
|
if profile.properties.weight_name == 'routability' then
|
||||||
-- penalize turns from non-local access only segments onto local access only tags
|
-- penalize turns from non-local access only segments onto local access only tags
|
||||||
if not turn.source_restricted and turn.target_restricted then
|
if not turn.source_restricted and turn.target_restricted then
|
||||||
turn.weight = constants.max_turn_weight
|
turn.weight = turn.weight + 3000
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function process_segment(profile, segment)
|
||||||
|
-- Extract coordinates of the start and end points
|
||||||
|
local source_lat, source_lon = segment.source.lat, segment.source.lon
|
||||||
|
local target_lat, target_lon = segment.target.lat, segment.target.lon
|
||||||
|
|
||||||
|
-- Calculate pollution impact at source and target
|
||||||
|
local pollution_source = calculate_pollution(source_lat, source_lon)
|
||||||
|
local pollution_target = calculate_pollution(target_lat, target_lon)
|
||||||
|
|
||||||
|
|
||||||
|
-- Average pollution for the segment
|
||||||
|
local avg_pollution = (pollution_source + pollution_target) / 2
|
||||||
|
--print(avg_pollution)
|
||||||
|
|
||||||
|
-- Adjust weight and duration based on pollution level
|
||||||
|
segment.weight = segment.weight + (avg_pollution^1.4)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
setup = setup,
|
setup = setup,
|
||||||
process_way = process_way,
|
process_way = process_way,
|
||||||
process_node = process_node,
|
process_node = process_node,
|
||||||
process_turn = process_turn
|
process_turn = process_turn,
|
||||||
|
process_segment = process_segment
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
|
||||||
-- Foot profile
|
-- Foot profile
|
||||||
local http = require("socket.http") -- LuaSocket for HTTP requests
|
local http = require("socket.http") -- LuaSocket for HTTP requests
|
||||||
local json = require("cjson")
|
local json = require("cjson")
|
||||||
@ -8,43 +9,44 @@ Set = require('lib/set')
|
|||||||
Sequence = require('lib/sequence')
|
Sequence = require('lib/sequence')
|
||||||
Handlers = require("lib/way_handlers")
|
Handlers = require("lib/way_handlers")
|
||||||
find_access_tag = require("lib/access").find_access_tag
|
find_access_tag = require("lib/access").find_access_tag
|
||||||
|
stations_data = nil
|
||||||
|
|
||||||
function fetch_pollution_data(location)
|
|
||||||
-- Convert location userdata to a string
|
|
||||||
local location_str = tostring(location)
|
|
||||||
|
|
||||||
-- Check if the location is "(undefined,undefined)"
|
function fetch_pollution_data()
|
||||||
if location_str == "(undefined,undefined)" then
|
local url = "http://128.199.51.173:8000/routes/api/pollution/NO2"
|
||||||
print("Location is undefined. Skipping pollution data fetch.")
|
|
||||||
return 0 -- Return 0 for undefined locations
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Extract lat and lon from the location string
|
|
||||||
local lat, lon = location_str:match("%(([^,]+),([^%)]+)%)")
|
|
||||||
if lat and lon then
|
|
||||||
lat = tonumber(lat)
|
|
||||||
lon = tonumber(lon)
|
|
||||||
else
|
|
||||||
print("Invalid location format: " .. location_str)
|
|
||||||
return 0 -- Return 0 if the format is invalid
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Fetch pollution data
|
|
||||||
local url = string.format("http://localhost:8008/routes/api/pollution?lat=%f&lon=%f", lat, lon)
|
|
||||||
local response, status = http.request(url)
|
local response, status = http.request(url)
|
||||||
|
|
||||||
if status == 200 then
|
if status == 200 and response then
|
||||||
local data = json.decode(response)
|
print("Raw response:", response)
|
||||||
return data.pollution -- Return the pollution weight from the backend
|
local success, data = pcall(json.decode, response) -- Manejar errores de JSON
|
||||||
|
if success and data and data.stations then
|
||||||
|
print("Pollution data fetched successfully.")
|
||||||
|
print("Number of stations:", #data.stations)
|
||||||
|
return data
|
||||||
|
else
|
||||||
|
print("Failed to decode JSON or missing 'stations' key.")
|
||||||
|
end
|
||||||
else
|
else
|
||||||
print("Failed to fetch pollution data. HTTP status: " .. tostring(status))
|
print("HTTP request failed. Status:", status)
|
||||||
return 0 -- Return 0 if the request fails
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Fallback a datos vacíos si hay un error
|
||||||
|
return { stations = {} }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function setup()
|
function setup()
|
||||||
local walking_speed = 5
|
local walking_speed = 5
|
||||||
|
stations_data = fetch_pollution_data()
|
||||||
|
|
||||||
|
-- Check if data was successfully retrieved
|
||||||
|
if not stations_data or not stations_data.stations then
|
||||||
|
print("Warning: Pollution data could not be loaded. Defaulting to no pollution.")
|
||||||
|
stations_data = { stations = {} } -- Fallback to empty station data
|
||||||
|
else
|
||||||
|
print("Pollution data loaded successfully.")
|
||||||
|
end
|
||||||
return {
|
return {
|
||||||
properties = {
|
properties = {
|
||||||
weight_name = 'duration',
|
weight_name = 'duration',
|
||||||
@ -172,8 +174,47 @@ function setup()
|
|||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function calculate_pollution(lat, lon)
|
||||||
|
-- Calcular contaminación
|
||||||
|
local pollution_value = 0
|
||||||
|
local total_weight = 0
|
||||||
|
local weight = 0
|
||||||
|
local p = 1.8
|
||||||
|
local max_distance = 3
|
||||||
|
if stations_data and stations_data.stations then
|
||||||
|
for _, station in ipairs(stations_data.stations) do
|
||||||
|
local station_lat = tonumber(station.lat)
|
||||||
|
local station_lon = tonumber(station.lon)
|
||||||
|
local latest_reading = tonumber(station.pollution)
|
||||||
|
|
||||||
|
if station_lat and station_lon and latest_reading then
|
||||||
|
-- Fórmula de distancia usando Haversine
|
||||||
|
local R = 6371 -- Radio de la Tierra en km
|
||||||
|
local dlat = math.rad(station_lat - lat)
|
||||||
|
local dlon = math.rad(station_lon - lon)
|
||||||
|
local a = math.sin(dlat / 2)^2 +
|
||||||
|
math.cos(math.rad(lat)) * math.cos(math.rad(station_lat)) * math.sin(dlon / 2)^2
|
||||||
|
local c = 2 * math.atan2(math.sqrt(a), math.sqrt(1 - a))
|
||||||
|
local distance = R * c
|
||||||
|
|
||||||
|
-- Ponderación ajustada
|
||||||
|
weight = 1 / ((distance + 1))
|
||||||
|
weight = tonumber(string.format("%.6f", weight))
|
||||||
|
pollution_value = pollution_value + (latest_reading * weight)
|
||||||
|
--total_weight = total_weight + weight
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
||||||
|
--print(pollution_value)
|
||||||
|
return pollution_value
|
||||||
|
else
|
||||||
|
print("No station data available.")
|
||||||
|
return 0
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
function process_node(profile, node, result)
|
function process_node(profile, node, result)
|
||||||
-- parse access and barrier tags
|
-- Parse access and barrier tags
|
||||||
local access = find_access_tag(node, profile.access_tags_hierarchy)
|
local access = find_access_tag(node, profile.access_tags_hierarchy)
|
||||||
if access then
|
if access then
|
||||||
if profile.access_tag_blacklist[access] then
|
if profile.access_tag_blacklist[access] then
|
||||||
@ -182,7 +223,7 @@ function process_node(profile, node, result)
|
|||||||
else
|
else
|
||||||
local barrier = node:get_value_by_key("barrier")
|
local barrier = node:get_value_by_key("barrier")
|
||||||
if barrier then
|
if barrier then
|
||||||
-- make an exception for rising bollard barriers
|
-- Make an exception for rising bollard barriers
|
||||||
local bollard = node:get_value_by_key("bollard")
|
local bollard = node:get_value_by_key("bollard")
|
||||||
local rising_bollard = bollard and "rising" == bollard
|
local rising_bollard = bollard and "rising" == bollard
|
||||||
|
|
||||||
@ -191,20 +232,9 @@ function process_node(profile, node, result)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
local location = node:location()
|
|
||||||
local pollution = fetch_pollution_data(location)
|
|
||||||
print(pollution)
|
|
||||||
--result.weight = result.weight + pollution
|
|
||||||
|
|
||||||
|
|
||||||
-- check if node is a traffic light
|
|
||||||
local tag = node:get_value_by_key("highway")
|
|
||||||
if "traffic_signals" == tag then
|
|
||||||
-- Direction should only apply to vehicles
|
|
||||||
result.traffic_lights = true
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
-- main entry point for processsing a way
|
-- main entry point for processsing a way
|
||||||
function process_way(profile, way, result)
|
function process_way(profile, way, result)
|
||||||
-- the intial filtering of ways based on presence of tags
|
-- the intial filtering of ways based on presence of tags
|
||||||
@ -302,9 +332,29 @@ function process_turn (profile, turn)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function process_segment(profile, segment)
|
||||||
|
-- Extract coordinates of the start and end points
|
||||||
|
local source_lat, source_lon = segment.source.lat, segment.source.lon
|
||||||
|
local target_lat, target_lon = segment.target.lat, segment.target.lon
|
||||||
|
|
||||||
|
-- Calculate pollution impact at source and target
|
||||||
|
local pollution_source = calculate_pollution(source_lat, source_lon)
|
||||||
|
local pollution_target = calculate_pollution(target_lat, target_lon)
|
||||||
|
|
||||||
|
|
||||||
|
-- Average pollution for the segment
|
||||||
|
local avg_pollution = (pollution_source + pollution_target) / 2
|
||||||
|
--print(avg_pollution)
|
||||||
|
|
||||||
|
-- Adjust weight and duration based on pollution level
|
||||||
|
segment.weight = segment.weight + (avg_pollution^1.4)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
setup = setup,
|
setup = setup,
|
||||||
process_way = process_way,
|
process_way = process_way,
|
||||||
process_node = process_node,
|
process_node = process_node,
|
||||||
process_turn = process_turn
|
process_turn = process_turn,
|
||||||
|
process_segment = process_segment
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user