Skip to content

Commit

Permalink
Add OSM node barrier=height_restrictor handling
Browse files Browse the repository at this point in the history
  • Loading branch information
oxidase committed Feb 12, 2018
1 parent 0da2029 commit 8e728a9
Show file tree
Hide file tree
Showing 5 changed files with 61 additions and 31 deletions.
8 changes: 8 additions & 0 deletions features/car/barrier.feature
Original file line number Diff line number Diff line change
Expand Up @@ -45,3 +45,11 @@ Feature: Car - Barriers
| bollard | | |
| bollard | rising | x |
| bollard | removable | |

Scenario: Car - Height restrictions
Then routability should be
| node/barrier | node/maxheight | bothw |
| height_restrictor | | x |
| height_restrictor | 1 | |
| height_restrictor | 3 | x |
| height_restrictor | default | x |
9 changes: 7 additions & 2 deletions features/options/extract/lua.feature
Original file line number Diff line number Diff line change
Expand Up @@ -129,8 +129,12 @@ Feature: osrm-extract lua ways:get_nodes()
"""
functions = require('testbot')
functions.process_node = function(profile, node, result, relations)
print ('node ' .. tostring(node:get_location_tag('answer')))
end
functions.process_way = function(profile, way, result, relations)
print ('answer ' .. tostring(way:get_location_tag('answer')))
print ('way ' .. tostring(way:get_location_tag('answer')))
result.forward_mode = mode.driving
result.forward_speed = 1
end
Expand All @@ -148,4 +152,5 @@ Feature: osrm-extract lua ways:get_nodes()

When I run "osrm-extract --profile {profile_file} {osm_file} --location-dependent-data test/data/regions/null-island.geojson"
Then it should exit successfully
And stdout should contain "answer 42"
And stdout should contain "node 42"
And stdout should contain "way 42"
13 changes: 11 additions & 2 deletions profiles/car.lua
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ Relations = require("lib/relations")
find_access_tag = require("lib/access").find_access_tag
limit = require("lib/maxspeed").limit
Utils = require("lib/utils")
Measure = require("lib/measure")

function setup()
return {
Expand Down Expand Up @@ -54,7 +55,8 @@ function setup()
'gate',
'lift_gate',
'no',
'entrance'
'entrance',
'height_restrictor'
},

access_tag_whitelist = Set {
Expand Down Expand Up @@ -320,11 +322,18 @@ function process_node(profile, node, result, relations)
else
local barrier = node:get_value_by_key("barrier")
if barrier then
-- check height restriction 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 rising_bollard = bollard and "rising" == bollard

if not profile.barrier_whitelist[barrier] and not rising_bollard then
if not profile.barrier_whitelist[barrier] and not rising_bollard or restricted_by_height then
result.barrier = true
end
end
Expand Down
6 changes: 3 additions & 3 deletions profiles/lib/measure.lua
Original file line number Diff line number Diff line change
Expand Up @@ -62,11 +62,11 @@ local height_non_numerical_values = Set { "default", "none", "no-sign", "unsigne

--- Get maxheight of specified way in meters. If there are no
--- max height, then return nil
function Measure.get_max_height(raw_value,way)
function Measure.get_max_height(raw_value, element)
if raw_value then
if height_non_numerical_values[raw_value] then
if way then
return way:get_location_tag('maxheight') or default_maxheight
if element then
return element:get_location_tag('maxheight') or default_maxheight
else
return default_maxheight
end
Expand Down
56 changes: 32 additions & 24 deletions src/extractor/scripting_environment_lua.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,22 @@ void Sol2ScriptingEnvironment::InitContext(LuaScriptingContext &context)
"valid",
&osmium::Location::valid);

auto get_location_tag = [](auto &context, const auto &location, const char *key) {
if (context.location_dependent_data.empty())
return sol::object(sol::nil);

const LocationDependentData::point_t point{location.lon(), location.lat()};
if (!boost::geometry::equals(context.last_location_point, point))
{
context.last_location_point = point;
context.last_location_indexes =
context.location_dependent_data.GetPropertyIndexes(point);
}

auto value = context.location_dependent_data.FindByKey(context.last_location_indexes, key);
return boost::apply_visitor(to_lua_object(context.state), value);
};

context.state.new_usertype<osmium::Way>(
"Way",
"get_value_by_key",
Expand All @@ -229,37 +245,29 @@ void Sol2ScriptingEnvironment::InitContext(LuaScriptingContext &context)
"get_nodes",
[](const osmium::Way &way) { return sol::as_table(way.nodes()); },
"get_location_tag",
[&context](const osmium::Way &way, const char *key) {
if (context.location_dependent_data.empty())
return sol::object(sol::nil);
[&context, &get_location_tag](const osmium::Way &way, const char *key) {
// HEURISTIC: use a single node (last) of the way to localize the way
// For more complicated scenarios a proper merging of multiple tags
// at one or many locations must be provided
const auto &nodes = way.nodes();
const auto &location = nodes.back().location();
const LocationDependentData::point_t point{location.lon(), location.lat()};

if (!boost::geometry::equals(context.last_location_point, point))
{
context.last_location_point = point;
context.last_location_indexes =
context.location_dependent_data.GetPropertyIndexes(point);
}

auto value =
context.location_dependent_data.FindByKey(context.last_location_indexes, key);
return boost::apply_visitor(to_lua_object(context.state), value);
return get_location_tag(context, location, key);
});

context.state.new_usertype<osmium::Node>("Node",
"location",
&osmium::Node::location,
"get_value_by_key",
&get_value_by_key<osmium::Node>,
"id",
&osmium::Node::id,
"version",
&osmium::Node::version);
context.state.new_usertype<osmium::Node>(
"Node",
"location",
&osmium::Node::location,
"get_value_by_key",
&get_value_by_key<osmium::Node>,
"id",
&osmium::Node::id,
"version",
&osmium::Node::version,
"get_location_tag",
[&context, &get_location_tag](const osmium::Node &node, const char *key) {
return get_location_tag(context, node.location(), key);
});

context.state.new_usertype<ExtractionNode>("ResultNode",
"traffic_lights",
Expand Down

0 comments on commit 8e728a9

Please sign in to comment.