Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Profile: Access highway= key in segment function #6145

Closed
bda1986 opened this issue Oct 12, 2021 · 6 comments
Closed

Profile: Access highway= key in segment function #6145

bda1986 opened this issue Oct 12, 2021 · 6 comments
Labels

Comments

@bda1986
Copy link

bda1986 commented Oct 12, 2021

Within the process_way() function in a profile, it is possible to obtain relevant keys using, e.g., way:get_value_by_key('highway').
Is there a similar possibility to do so for the segment function?

I have used a modified version of the rasterbot.lua profile to include third-party raster elevation data and would like the slope of a segment to affect duration conditional on the surface or road type.
For example, the same slope should assign a higher penalty on ways with highway=track than on highway=primary.

However, keys/tags such as highway=primary are not listed among the available attributes in the process_segment() function, as described in profiles.md.
As far as I understand, the segments are subsets or parts of the ways, so the information specific to each way should be available for the segment somehow?

@mjjbell
Copy link
Member

mjjbell commented Oct 29, 2021

As the extraction is currently constructed this will be difficult, the OSM tag context has been discarded by the time the extraction reaches process_segment.

Just to understand correctly, you want to disproportionately apply a slope to the speed of a segment depending on the highway type?
E.g. Given a 5mph track and a 70mph motorway with identical uphill slope, you might want to scale the track to 3mph but motorways are scaled down less, so becomes 65mph?

@bda1986
Copy link
Author

bda1986 commented Nov 1, 2021

Just to understand correctly, you want to disproportionately apply a slope to the speed of a segment depending on the highway type? E.g. Given a 5mph track and a 70mph motorway with identical uphill slope, you might want to scale the track to 3mph but motorways are scaled down less, so becomes 65mph?

Exactly, this is what I was trying to achieve.

As the extraction is currently constructed this will be difficult, as the OSM tag context has been discarded by the time the extraction reaches process_segment.

So any information related to the way, for example, the way_id is no longer available in the process_segment function?
Do the segments themselves have some sort of identifier (other than the coordinates) that would make it possible to join external data?

@mjjbell
Copy link
Member

mjjbell commented Nov 1, 2021

Had a deeper look.

process_segment is called from ProcessSegment in the C++ extraction code.

ExtractionSegment segment(source_coord, target_coord, distance, weight, duration);
scripting_environment.ProcessSegment(segment);

At this point, it's iterating over a list of InternalExtractorEdge values. In addition to edge coordinates, it also has an embedded NodeBasedEdgeWithOSM value.

These internal edges are actually created when processing the output of process_way

util::for_each_pair(
nodes.cbegin(),
nodes.cend(),
[&](const osmium::NodeRef &first_node, const osmium::NodeRef &last_node) {
NodeBasedEdgeWithOSM edge = {
OSMNodeID{static_cast<std::uint64_t>(first_node.ref())},
OSMNodeID{static_cast<std::uint64_t>(last_node.ref())},
0, // weight
0, // duration
0, // distance
{}, // geometry id
static_cast<AnnotationID>(annotation_data_id),
{true,
in_backward_direction && !split_edge,
split_edge,
parsed_way.roundabout,
parsed_way.circular,
parsed_way.is_startpoint,
parsed_way.forward_restricted,
road_classification,
parsed_way.highway_turn_classification,
parsed_way.access_turn_classification}};
external_memory.all_edges_list.push_back(InternalExtractorEdge(
std::move(edge), forward_weight_data, forward_duration_data, {}));
});

So it looks like the edge already has access to the OSM segment nodes, and a guidance classification that is almost a complete list of OSM highway types.

-- Guidance: Default Mapping from roads to types/priorities
highway_classes = {
motorway = road_priority_class.motorway,
motorway_link = road_priority_class.motorway_link,
trunk = road_priority_class.trunk,
trunk_link = road_priority_class.trunk_link,
primary = road_priority_class.primary,
primary_link = road_priority_class.primary_link,
secondary = road_priority_class.secondary,
secondary_link = road_priority_class.secondary_link,
tertiary = road_priority_class.tertiary,
tertiary_link = road_priority_class.tertiary_link,
unclassified = road_priority_class.unclassified,
residential = road_priority_class.main_residential,
service = road_priority_class.alley,
living_street = road_priority_class.side_residential,
track = road_priority_class.bike_path,
path = road_priority_class.bike_path,
footway = road_priority_class.foot_path,
pedestrian = road_priority_class.foot_path,
steps = road_priority_class.foot_path
}

Could this list be sufficient for your calculations?

We could also add the OSM way ID to the internal edge representation and pass that through instead.
This was already being proposed in #5325 to enable way annotations, so perhaps that's not a bad option.

Either way, there's a bit of additional plumbing required to pass these values through to process_segment, but it's still not keeping the full list of OSM tags available for inspection. I would expect doing that will be a lot of additional memory bloat for most use-cases.

@bda1986
Copy link
Author

bda1986 commented Nov 4, 2021

Thank you for pointing out these code snippets.
This definitely makes it clearer to me how the information are passed through internally.

Could this list be sufficient for your calculations?

For my case, it would be ideal to pass the highway and surface key to the segment function.
However, the list of OSM highway types you've mentioned would already be very helpful, as the surface tag seems to have a lot of missing values anyway. So definitely yes, it would be sufficient.

We could also add the OSM way ID to the internal edge representation and pass that through instead. This was already being proposed in #5325 to enable way annotations, so perhaps that's not a bad option.

Either way, there's a bit of additional plumbing required to pass these values through to process_segment, but it's still not keeping the full list of OSM tags available for inspection. I would expect doing that will be a lot of additional memory bloat for most use-cases.

I do understand that this would cause quite some memory bloat, especially for users who do not use this feature - which is probably the vast majority.
Could using the way ID instead be a less memory-intensive alternative? I could then join the relevant data externally, as suggested in #5325.

@mjjbell
Copy link
Member

mjjbell commented Nov 5, 2021

Could using the way ID instead be a less memory-intensive alternative? I could then join the relevant data externally, as suggested in #5325.

Yes, I think we can add the way ID to NodeBasedEdgeWithOSM and expose the values it contains to process_segment.

Copy link

github-actions bot commented Jul 8, 2024

This issue seems to be stale. It will be closed in 30 days if no further activity occurs.

@github-actions github-actions bot added the Stale label Jul 8, 2024
@github-actions github-actions bot closed this as not planned Won't fix, can't repro, duplicate, stale Aug 8, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants