Project-OSRM / osrm-backend

Open Source Routing Machine - C++ backend
http://map.project-osrm.org
BSD 2-Clause "Simplified" License
6.39k stars 3.39k forks source link

'input data is empty' and 'terminate called recursively' errors #1189

Closed bjtaylor1 closed 10 years ago

bjtaylor1 commented 10 years ago

A couple of my luas are not working on the develop branch but they work fine on the master branch. (i could just use master but am conscious to keep ahead of any issues for when develop gets merged into master).

using this lua:

--auk.lua
-- Begin of globals
require("lib/access")
require("lib/whitelist")
require("lib/blacklist")

barrier_whitelist = { ["cattle_grid"] = true, ["border_control"] = true, ["toll_booth"] = true, ["sally_port"] = true, ["gate"] = true, ["no"] = true, ["entrance"] = true}
access_tag_whitelist = { ["yes"] = true, ["motorcar"] = true, ["motor_vehicle"] = true, ["vehicle"] = true, ["permissive"] = true, ["designated"] = true  }
access_tag_blacklist = { ["no"] = true, ["private"] = true, ["agricultural"] = true, ["forestry"] = true, ["emergency"] = true }
access_tag_restricted = { ["destination"] = true, ["delivery"] = true }
access_tags = { "motorcar", "motor_vehicle", "vehicle" }
access_tags_hierachy = { "motorcar", "motor_vehicle", "vehicle", "access" }
service_tag_restricted = { ["parking_aisle"] = true }
ignore_in_grid = { ["ferry"] = true }
restriction_exception_tags = { "motorcar", "motor_vehicle", "vehicle" }
default_speed = 17
speed_trunk = default_speed 
speed_primary = default_speed
speed_secondary = default_speed
speed_tertiary = default_speed
speed_unclassified = default_speed 
speed_residential = default_speed 
speed_service = default_speed

myspeed_profile = {
  ["trunk"] = speed_trunk,
  ["trunk_link"] = speed_trunk,
  ["primary"] = speed_primary,
  ["primary_link"] = speed_primary,
  ["secondary"] = speed_secondary,
  ["secondary_link"] = speed_secondary,
  ["tertiary"] = speed_tertiary,
  ["tertiary_link"] = speed_tertiary,
  ["unclassified"] = speed_unclassified,
  ["residential"] = speed_residential,
  ["living_street"] = speed_residential,
  ["service"] = speed_service,
--  ["track"] = 5,
  ["ferry"] = 5,
  ["shuttle_train"] = 10,
  ["default"] = default_speed
}

take_minimum_of_speeds  = false
obey_oneway                   = true
obey_bollards           =  false
use_restrictions            = true
ignore_areas                  = true -- future feature
traffic_signal_penalty  = 0 
u_turn_penalty              = 20

-- End of globals

function get_exceptions(vector)
    for i,v in ipairs(restriction_exception_tags) do
        vector:Add(v)
    end
end

local function parse_maxspeed(source)
    if source == nil then
        return 0
    end
    local n = tonumber(source:match("%d*"))
    if n == nil then
        n = 0
    end
    if string.match(source, "mph") or string.match(source, "mp/h") then
        n = (n*1609)/1000;
    end
    return math.abs(n)
end

function node_function (node)
  local barrier = node.tags:Find("barrier")
  local access = Access.find_access_tag(node, access_tags_hierachy)
  local traffic_signal = node.tags:Find("highway")

  --flag node if it carries a traffic light

  if traffic_signal == "traffic_signals" then
    node.traffic_light = true;
  end

    -- parse access and barrier tags
    if access  and access ~= "" then
        if access_tag_blacklist[access] then
            node.bollard = true
        end
    elseif barrier and barrier ~= "" then
        if barrier_whitelist[barrier] then
            return
        else
            node.bollard = true
        end
    end
end

function way_function (way)
  local thespeed = -1

--special ways override everything else and we can go max (unclassified) speed on them
  if(Whitelist.whitelist_ways_by_id[way.id]) then
    way.special = true
    way.specialtext = "whitelist"
    way.speed = speed_unclassified
    way.type = 1
    return
  end

  if(Blacklist.blacklist_ways_by_id[way.id]) then
    way.special = true
    way.specialtext = "blacklist"
    return
  end

  -- we dont route over areas
  local area = way.tags:Find("area")
  if ignore_areas and ("yes" == area) then
    return
  end

  -- check if oneway tag is unsupported
  local oneway = way.tags:Find("oneway")
  if "reversible" == oneway then
    return
  end

  local impassable = way.tags:Find("impassable")
  if "yes" == impassable then
    return
  end

  local status = way.tags:Find("status")
  if "impassable" == status then
    return
  end

  -- Check if we are allowed to access the way
  local access = Access.find_access_tag(way, access_tags_hierachy)
  if access_tag_blacklist[access] then
    return
  end

  -- Second, parse the way according to these properties
  local highway = way.tags:Find("highway")

  if "motorway" == highway then
    return
  end

  if "motorway_junction" == highway then
    return
  end
  local name = way.tags:Find("name")
  local ref = way.tags:Find("ref")
  local junction = way.tags:Find("junction")
  local route = way.tags:Find("route")
  local maxspeed = math.max(parse_maxspeed(way.tags:Find ( "maxspeed") ), default_speed)
  local maxspeed_forward = math.max(parse_maxspeed(way.tags:Find( "maxspeed:forward")), default_speed)
  local maxspeed_backward = parse_maxspeed(way.tags:Find( "maxspeed:backward"))
  local barrier = way.tags:Find("barrier")
  local cycleway = way.tags:Find("cycleway")
  local duration  = way.tags:Find("duration")
  local service  = way.tags:Find("service")

  if maxspeed >= 112 and "roundabout" ~= junction then --112 = 70 mph
    return
  end

  -- Set the name that will be used for instructions
    if "" ~= ref then
      way.name = ref
    elseif "" ~= name then
      way.name = name
--  else
--      way.name = highway      -- if no name exists, use way type
    end

    if "roundabout" == junction then
      way.roundabout = true;
    end

  -- Handling ferries and piers
  if (myspeed_profile[route] ~= nil and myspeed_profile[route] > 0) then
    if durationIsValid(duration) then
      way.duration = math.max( parseDuration(duration), 1 );
    end
    way.direction = Way.bidirectional
    if myspeed_profile[route] ~= nil then
      highway = route;
    end
    if tonumber(way.duration) < 0 then
      thespeed = myspeed_profile[highway]
    end
  end

  -- Set the avg speed on the way if it is accessible by road class
  if (myspeed_profile[highway] ~= nil and thespeed == -1 ) then
      thespeed = myspeed_profile[highway]
  end

  -- Set the avg speed on ways that are marked accessible
  if "" ~= highway and access_tag_whitelist[access] and thespeed == -1 then
    if 0 == maxspeed then
      maxspeed = math.huge
    end
    thespeed = math.min(myspeed_profile["default"], maxspeed)
  end

  -- Set access restriction flag if access is allowed under certain restrictions only
  if access ~= "" and access_tag_restricted[access] then
    way.is_access_restricted = true
  end

  -- Set access restriction flag if service is allowed under certain restrictions only
  if service ~= "" and service_tag_restricted[service] then
      way.is_access_restricted = true
  end

  -- Set direction according to tags on way
  way.direction = Way.bidirectional
  if obey_oneway  then
      if oneway == "-1" then
        way.direction = Way.opposite
    elseif oneway == "yes" or
      oneway == "1" or
      oneway == "true" or
      junction == "roundabout" or
      (highway == "motorway_link" and oneway ~="no") or
      (highway == "motorway" and oneway ~= "no")
      then
         way.direction = Way.oneway
    end
  end

  -- Override speed settings if explicit forward/backward maxspeeds are given
  if thespeed > 0 and maxspeed_forward ~= nil and maxspeed_forward > 0 then
    if Way.bidirectional == way.direction then
      way.backward_speed = thespeed
    end
    thespeed = math.max(maxspeed_forward, default_speed)
  end
  if maxspeed_backward ~= nil and maxspeed_backward > 0 then
    way.backward_speed = math.max(maxspeed_backward, default_speed)
  end

  -- Override general direction settings of there is a specific one for our mode of travel
  if ignore_in_grid[highway] ~= nil and ignore_in_grid[highway] then
        way.ignore_in_grid = true
    end
    way.type = 1
  way.speed = thespeed
  return
end

-- These are wrappers to parse vectors of nodes and ways and thus to speed up any tracing JIT

function node_vector_function(vector)
 for v in vector.nodes do
  node_function(v)
 end
end

function turn_function (angle)
  return 5
end

then osrm-extract returns:

ubuntu@ip-172-31-38-27:~/Project-OSRM$ ./osrm-extract -p auk.lua monaco-latest.osm.pbf
[info] Input file: monaco-latest.osm.pbf
[info] Profile: auk.lua
[info] Threads: 4
[info] Using script auk.lua
[STXXL-MSG] STXXL v1.3.1 (release)
[STXXL-ERRMSG] Warning: no config file found.
[STXXL-ERRMSG] Using default disk configuration.
[STXXL-MSG] 1 disks are allocated, total space: 1000 MiB
[info] Using turn restrictions
[info] Found 3 exceptions to turn restrictions:
[info]   motorcar
[info]   motor_vehicle
[info]   vehicle
[info] Parsing in progress..
[info] Parsing finished after 0.118 seconds
[warn] The input data is empty, exiting.
[STXXL-ERRMSG] Removing disk file created from default configuration: /var/tmp/stxxl

and with this lua

--tourist.lua
-- Begin of globals
require("lib/access")
require("lib/whitelist")
require("lib/blacklist")

barrier_whitelist = { ["cattle_grid"] = true, ["border_control"] = true, ["toll_booth"] = true, ["sally_port"] = true, ["gate"] = true, ["no"] = true, ["entrance"] = true, ["cycle_barrier"] = true, ["motorcycle_barrier"] = true, ["swing_gate"] = true, ["gate"] = true, ["kissing_gate"] = true, ["stile"] = true, ["bollard"] = true}
access_tag_whitelist = { ["yes"] = true, ["motorcar"] = true, ["motor_vehicle"] = true, ["vehicle"] = true, ["permissive"] = true, ["designated"] = true  }
access_tag_blacklist = { ["no"] = true, ["private"] = true, ["agricultural"] = true, ["forestry"] = true, ["emergency"] = true }
access_tag_restricted = { ["destination"] = true, ["delivery"] = true }
access_tags = { "motorcar", "motor_vehicle", "vehicle" }
access_tags_hierachy = { "motorcar", "motor_vehicle", "vehicle", "access" }
service_tag_restricted = { ["parking_aisle"] = true }
ignore_in_grid = { ["ferry"] = true }
restriction_exception_tags = { "motorcar", "motor_vehicle", "vehicle" }

tourist_temp_whitelist = {
 [23467175] = true, --st ives busway link set asphalt 2/1/14
 [44436696] = true, --cambridge
 [4678992] = true,
 [160092236] = true, --millennium coastal path
 [29575839] = true,
 [166430441] = true,
 [33425596] = true,
 [158732038] = true,
 [37873042] = true
}

take_minimum_of_speeds  = false
obey_oneway                   = true
obey_bollards           =  false
use_restrictions            = true
ignore_areas                  = true -- future feature
traffic_signal_penalty  = 15
u_turn_penalty              = 20

-- End of globals

function get_exceptions(vector)
    for i,v in ipairs(restriction_exception_tags) do
        vector:Add(v)
    end
end

local function parse_maxspeed(source)
    if source == nil then
        return 0
    end
    local n = tonumber(source:match("%d*"))
    if n == nil then
        n = 0
    end
    if string.match(source, "mph") or string.match(source, "mp/h") then
        n = (n*1609)/1000;
    end
    return math.abs(n)
end

function node_function (node)
  local barrier = node.tags:Find("barrier")
  local access = Access.find_access_tag(node, access_tags_hierachy)
  local traffic_signal = node.tags:Find("highway")

  --flag node if it carries a traffic light

  if traffic_signal == "traffic_signals" then
    node.traffic_light = true;
  end

    -- parse access and barrier tags
    if access  and access ~= "" then
        if access_tag_blacklist[access] then
            node.bollard = true
        end
    elseif barrier and barrier ~= "" then
        if barrier_whitelist[barrier] then
            return
        else
            node.bollard = true
        end
    end
end

function way_function (way)
  local default_speed = 15
  local speed_trunk = 5
  local speed_primary = 15
  local speed_secondary = 20 
  local speed_tertiary = 27
  local speed_unclassified = 40
  local speed_cyclepath = 43
  local speed_residential = 15 
  local speed_service = default_speed
  local myspeed_profile = {
    ["trunk"] = speed_trunk,
    ["trunk_link"] = speed_trunk,
    ["primary"] = speed_primary,
    ["primary_link"] = speed_primary,
    ["secondary"] = speed_secondary,
    ["secondary_link"] = speed_secondary,
    ["tertiary"] = speed_tertiary,
    ["tertiary_link"] = speed_tertiary,
    ["unclassified"] = speed_unclassified,
    ["residential"] = speed_residential,
    ["living_street"] = speed_residential,
    ["service"] = speed_service,
  --  ["track"] = 5,
    ["ferry"] = 5,
    ["shuttle_train"] = 10,
    ["default"] = default_speed
  }

  way.type = 0
  local thespeed = -1

  --special ways override everything else and we can go max (unclassified) speed on them
  if(Whitelist.whitelist_ways_by_id[way.id] or tourist_temp_whitelist[way.id]) then
    way.special = true
    way.specialtext = "whitelist"
    way.speed = speed_cyclepath
    return
  end

  if(Blacklist.blacklist_ways_by_id[way.id]) then
    way.special = true
    way.specialtext = "blacklist"
    return
  end

  local surface = way.tags:Find("surface")
  local bicycle = way.tags:Find("bicycle")
  local bikesallowed = ("yes" == bicycle or "permissive" == bicycle or "designated" == bicycle or "destination" == bicycle)
  local name = way.tags:Find("name")
  local highway = way.tags:Find("highway")
  local descriptor = highway.." "..surface.." "..bicycle.." "..name
  if ("asphalt" == surface or "paved" == surface) and 
    ("cycleway" == highway or
        ("track" == highway and bikesallowed) or
        ("bridleway" == highway and bikesallowed) or 
        ("footway" == highway and bikesallowed) or
        ("path" == highway and bikesallowed)
        ) then
      way.special = true
      way.specialtext = "cyclepath "..descriptor
          way.speed = speed_cyclepath
        return
  end

  -- we dont route over areas
  local area = way.tags:Find("area")
  if ignore_areas and ("yes" == area) then
    return
  end

  -- check if oneway tag is unsupported
  local oneway = way.tags:Find("oneway")
  if "reversible" == oneway then
    return
  end

  local impassable = way.tags:Find("impassable")
  if "yes" == impassable then
    return
  end

  local status = way.tags:Find("status")
  if "impassable" == status then
    return
  end

  -- Check if we are allowed to access the way
  local access = Access.find_access_tag(way, access_tags_hierachy)
  if access_tag_blacklist[access] then
    return
  end

  -- Second, parse the way according to these properties

  if "motorway" == highway then
    return
  end

  if "motorway_junction" == highway then
    return
  end

  local ref = way.tags:Find("ref")
  local junction = way.tags:Find("junction")
  local route = way.tags:Find("route")
  local actualmaxspeed = parse_maxspeed(way.tags:Find ( "maxspeed") )
  local maxspeed = math.max(actualmaxspeed, default_speed)
  local maxspeed_forward = math.max(parse_maxspeed(way.tags:Find( "maxspeed:forward")), default_speed)
  local maxspeed_backward = parse_maxspeed(way.tags:Find( "maxspeed:backward"))
  local barrier = way.tags:Find("barrier")
  local cycleway = way.tags:Find("cycleway")
  local duration  = way.tags:Find("duration")
  local service  = way.tags:Find("service")

  if maxspeed >= 112 and "roundabout" ~= junction then --112 = 70 mph
    return
  end

  -- Set the name that will be used for instructions
    if "" ~= ref then
      way.name = ref
    elseif "" ~= name then
      way.name = name
--  else
--      way.name = highway      -- if no name exists, use way type
    end

    if "roundabout" == junction then
      way.roundabout = true;
    end

  -- Handling ferries and piers
  if (myspeed_profile[route] ~= nil and myspeed_profile[route] > 0) then
    if durationIsValid(duration) then
      way.duration = math.max( parseDuration(duration), 1 );
    end
    way.direction = Way.bidirectional
    if myspeed_profile[route] ~= nil then
      highway = route;
    end
    if tonumber(way.duration) < 0 then
      thespeed = myspeed_profile[highway]
    end
    return
  end

  -- Set the avg speed on the way if it is accessible by road class
  if (myspeed_profile[highway] ~= nil and way.speed == -1 ) then
    thespeed = myspeed_profile[highway]
  end

  -- Set the avg speed on ways that are marked accessible
  if "" ~= highway and access_tag_whitelist[access] and way.speed == -1 then
    if 0 == maxspeed then
      maxspeed = math.huge
    end
    thespeed = math.min(myspeed_profile["default"], maxspeed)
  end

  -- Set access restriction flag if access is allowed under certain restrictions only
  if access ~= "" and access_tag_restricted[access] then
    way.is_access_restricted = true
  end

  -- Set access restriction flag if service is allowed under certain restrictions only
  if service ~= "" and service_tag_restricted[service] then
      way.is_access_restricted = true
  end

  -- Set direction according to tags on way
  way.direction = Way.bidirectional
  if obey_oneway  then
      if oneway == "-1" then
        way.direction = Way.opposite
    elseif oneway == "yes" or
      oneway == "1" or
      oneway == "true" or
      junction == "roundabout" or
      (highway == "motorway_link" and oneway ~="no") or
      (highway == "motorway" and oneway ~= "no")
      then
         way.direction = Way.oneway
    end
  end

  -- Override speed settings if explicit forward/backward maxspeeds are given
  if way.speed > 0 and maxspeed_forward ~= nil and maxspeed_forward > 0 then
    if Way.bidirectional == way.direction then
      way.backward_speed = way.speed
    end
    way.speed = math.max(maxspeed_forward, default_speed)
  end
  if maxspeed_backward ~= nil and maxspeed_backward > 0 then
    way.backward_speed = math.max(maxspeed_backward, default_speed)
  end

  -- Override general direction settings of there is a specific one for our mode of travel
  if ignore_in_grid[highway] ~= nil and ignore_in_grid[highway] then
        way.ignore_in_grid = true
    end

--30mph roads are no worse than tertiary:
  if thespeed ~= nil and thespeed > 0 and actualmaxspeed > 0 then
    if thespeed < speed_tertiary and actualmaxspeed <= 49 then
      thespeed = speed_tertiary
    end
--40mph roads are no worse than secondary:
    if thespeed < speed_secondary and actualmaxspeed <= 65 then 
      thespeed = speed_secondary
    end
  end

  way.speed = thespeed  
return
end

-- These are wrappers to parse vectors of nodes and ways and thus to speed up any tracing JIT

function node_vector_function(vector)
 for v in vector.nodes do
  node_function(v)
 end
end

function turn_function (angle)
  return 30 
end

I get:

ubuntu@ip-172-31-38-27:~/Project-OSRM$ ./osrm-extract -p tourist.lua monaco-latest.osm.pbf
[info] Input file: monaco-latest.osm.pbf
[info] Profile: tourist.lua
[info] Threads: 4
[info] Using script tourist.lua
[STXXL-MSG] STXXL v1.3.1 (release)
[STXXL-ERRMSG] Warning: no config file found.
[STXXL-ERRMSG] Using default disk configuration.
[STXXL-MSG] 1 disks are allocated, total space: 1000 MiB
[info] Using turn restrictions
[info] Found 3 exceptions to turn restrictions:
[info]   motorcar
[info]   motor_vehicle
[info]   vehicle
[info] Parsing in progress..
terminate called recursively
terminate called recursively
Aborted (core dumped)

lib is present and contains access.lua, whitelist.lua which is:

module "Whitelist"

whitelist_ways_by_id = {
[13008676] = true,
[13008702] = true,
[13008703] = true
--etc etc, just loads of ids explicitly listed
}

and blacklist.lua which is:

module "Blacklist"

blacklist_ways_by_id = {
 [203935360] = true,
 [3996812] = true,
 [117699757] = true
--etc etc, just another list of IDs
}

the develop branch works fine with car.lua and the above profiles work fine with the master branch, so it appears to be something that has changed in the develop branch that isn't in master yet that the above luas have failed to keep pace with so I'm just wondering if you can suggest what it could be?

bjtaylor1 commented 10 years ago

aa - it's because it seemingly now has to set "way.forward_speed" and "way.backward_speed" as well as just (or instead of) "way.speed".

What is way.backward_speed used for? Should it always be the same as way.forward_speed? Is way.speed still needed?

Is it possible to get notifications of things that might break an existing lua script?

TheMarex commented 10 years ago

AFAIK backward_speed is used for ways that can be traveled in both directions, but has different speed limits for each direction. See for example the specification on maxspeed in the OSM wiki "maxspeed:forward" vs. "maxspeed:backward"

As far as notifications go, please remember develop is the development branch. Seriously, it is a very bad idea to use it if you have any serious concerns of stability and backward compatibility. If the profile API changes, that will be probably mentioned in the release notes of the new version.

bjtaylor1 commented 10 years ago

yep, sure - cheers.