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

Fixed order of generated edges and guidance turns #4706

Merged
merged 15 commits into from
Jan 5, 2018
Merged

Conversation

oxidase
Copy link
Contributor

@oxidase oxidase commented Nov 27, 2017

Issue

This step is required before implementation of #4674

The order of edges is fixed by the order of node-based graph nodes and adjacent intersection edges incoming_edges and outgoing_edges and the implicit intersection connectivity matrix that is specified by a free function isTurnAllowed.

Tasklist

  • Re-enable via-way restrictions
  • Check changes of generated turns for BER
  • Check changes of generated turns for CA
  • Check changes of generated turns for DE
  • Cleanup the PR
  • Squash commits of the PR
  • add regression / cucumber cases (see docs/testing.md)
  • Add CHANGELOG entry
  • review
  • adjust for comments

Requirements / Relations

Blocks #4674

@oxidase
Copy link
Contributor Author

oxidase commented Nov 29, 2017

For Berlin extract instructions changed at locations ( - instruction generated by master, and not by the branch, + instruction is generated by the branch and not by master):

+(lon:13.362239, lat:52.499917), (noturn), slight left
+(lon:13.389962, lat:52.509648), (noturn), straight
-(lon:13.416905, lat:52.547719), continue, left
+(lon:13.429998, lat:52.608707), (suppressed), straight
-(lon:13.533043, lat:52.489697), (noturn), slight right
-(lon:13.533043, lat:52.489697), (noturn), slight left
+(lon:13.533043, lat:52.489697), (noturn), straight
+(lon:13.579658, lat:52.459044), (suppressed), slight left

Still has to check missing continue, left instruction at https://www.openstreetmap.org/node/60103176, but that could related to a bug with spurious U-turns
screenshot from 2017-11-29 15-56-32

@oxidase oxidase force-pushed the refactor/guidance branch 3 times, most recently from 3c51d08 to e509a7c Compare November 30, 2017 13:19
@oxidase
Copy link
Contributor Author

oxidase commented Nov 30, 2017

Compared generated turn instruction with respect to master (modifications are additions or deletions only):

  • BER 8 modifications in 401144 generated instructions

  • CA 186 modifications for 12151513 generated instructions

  • DE 583 modifications for
    30656676 generated instructions

The number of modified instructions is vanishingly small ~0.002% and almost all locations are either suppressed or invalid turns.

There are some manually selected locations that show edge cases in bearings merging and must be fixed later:

}

return intersection;
}

private:
mutable std::mutex lock;
mutable std::unordered_map<TurnType::Enum, std::uint64_t> type_hist;
mutable std::unordered_map<DirectionModifier::Enum, std::uint64_t> modifier_hist;
mutable std::map<TurnType::Enum, std::uint64_t> type_hist;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a particular reason we need to preserve the insertion order here? Just curious.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, map preserves order, so it is easier to do line-by-line comparison with diff

}

// Enforce ordering of outgoing edges
std::sort(result.begin(), result.end());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This sequence should be sorted by construction.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it depends on GetAdjacentEdgeRange implementation, but can add std::is_sorted assertion in both places

@oxidase oxidase force-pushed the refactor/guidance branch 2 times, most recently from 2f00908 to 18b058d Compare December 1, 2017 21:39
@danpat
Copy link
Member

danpat commented Dec 4, 2017

@oxidase minor - can you add a CHANGELOG entry for this? It'll help when reviewing changes for the next release.

@oxidase oxidase force-pushed the refactor/guidance branch 3 times, most recently from b3c8a5d to 2f47634 Compare December 5, 2017 11:39
Copy link
Member

@TheMarex TheMarex left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a few smaller clarifications needed, otherwise looks good. Thanks for this refactor! 👍


type_hist[type] += 1;
modifier_hist[modifier] += 1;
if (road.entry_allowed)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch!

@@ -111,8 +113,7 @@ transformTurnLaneMapIntoArrays(const LaneDescriptionMap &turn_lane_map)
//
// turn lane offsets points into the locations of the turn_lane_masks array. We use a standard
// adjacency array like structure to store the turn lane masks.
std::vector<std::uint32_t> turn_lane_offsets(turn_lane_map.data.size() +
2); // empty ID + sentinel
std::vector<std::uint32_t> turn_lane_offsets(turn_lane_map.data.size() + 1); // + sentinel
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you know why it was + 2 before?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

probably it is for empty ID but an empty entry is already included into turn_lane_map.data

@@ -419,22 +421,43 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(

TurnDataExternalContainer turn_data_container;

// TODO: add a MergableRoadDetector instance, to be deleted later
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't fully understand this TODO, there is an instance of this class a few lines below.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it is better to keep MergableRoadDetector for now, but it also influences intersections connectivity via edges merging and creating U-turns

const auto &incoming_edges = intersection::getIncomingEdges(
m_node_based_graph, node_at_center_of_intersection);
const auto &outgoing_edges = intersection::getOutgoingEdges(
m_node_based_graph, node_at_center_of_intersection);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

node_at_center_of_intersection maybe we can use intersection_node or something less verbose?

const auto &outgoing_edges = intersection::getOutgoingEdges(
m_node_based_graph, node_at_center_of_intersection);
const auto &edge_geometries_and_merged_edges =
intersection::getIntersectionGeometries(m_node_based_graph,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe this would be more concise using std::tie()?

@@ -165,8 +170,9 @@ bool MergableRoadDetector::EdgeDataSupportsMerge(
bool MergableRoadDetector::IsTrafficLoop(const NodeID intersection_node,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this still needed? I thought we compress traffic lights now.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.


for (const auto outgoing_edge : graph.GetAdjacentEdgeRange(intersection_node))
{
// TODO: to use TurnAnalysis all outgoing edges are required, to be uncommented later
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't quite understand yet how we could skip reversed edges in the future. How will this be possible?

return true;

// Allow U-turn if the incoming edge has a U-turn lane
const auto &incoming_edge_annotation_id = graph.GetEdgeData(from.edge).annotation_data;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should probably discuss if using the presence of a uturn lane is a good idea here, or if we should base this on country specific settings. Making the accessibility depend on turn lanes is just quite ugly.

In general, we should investigate how often this code path is even triggered - I have a feeling that most streets with a u-turn lane also have segregated ways for both directions (so it is not a "simple" uturn).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added a TODO line here, but i would keep it as it is now

using InputEdge = util::NodeBasedDynamicGraph::InputEdge;
using Graph = util::NodeBasedDynamicGraph;

BOOST_AUTO_TEST_CASE(simple_intersection_connectivity)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice! Good to see some unit tests for this code.

Copy link
Contributor

@karenzshea karenzshea left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🙌

const guidance::TurnLanesIndexedArray &turn_lanes_data,
const IntersectionEdge &incoming_edge);

IntersectionEdge skipDegreeTwoNodes(const util::NodeBasedDynamicGraph &graph,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we keep the explanatory comments from

// Graph Compression cannot compress every setting. For example any barrier/traffic light cannot
// be compressed. As a result, a simple road of the form `a ----- b` might end up as having an
// intermediate intersection, if there is a traffic light in between. If we want to look farther
// down a road, finding the next actual decision requires the look at multiple intersections.
// Here we follow the road until we either reach a dead end or find the next intersection with
// more than a single next road. This function skips over degree two nodes to find coorect input
// for GetConnectedRoads.
OSRM_ATTR_WARN_UNUSED
IntersectionGenerationParameters SkipDegreeTwoNodes(const NodeID starting_node,
? I think they're still applicable, and useful to have.

road.edge = graph.GetTarget(next_edge) == road.node ? next_edge + 1 : next_edge;
road.node = next_node;
next_node = graph.GetTarget(road.edge);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like we lost a CanBeCompressed() check from

if (!CanBeCompressed(node_based_graph.GetEdgeData(query_edge),

Do we not need this check anymore?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This check always returns true because of an assignment query_edge = next_edge; one line above and it was a comparison of two identical data structures.

@oxidase
Copy link
Contributor Author

oxidase commented Dec 7, 2017

Checked modified instruction in SF https://gist.github.com/oxidase/f0492bd6ffff80a7f24a91a2f07a4602
There are 45 modified instructions in 11 unique places and most changes are new U-turn instructions due to 701ac2c that also fixes #4704.

Also ce17c78 changes distance_to_extract from 150 to 120 meters. This makes are_parallel check less dependent on roads divergence, like South Van Ness Avenue at https://www.openstreetmap.org/node/65299217

@TheMarex
Copy link
Member

@oxidase heads up I rebased this on master for a pre-release.

@oxidase oxidase force-pushed the refactor/guidance branch 4 times, most recently from 52c0293 to 97f29d7 Compare January 2, 2018 21:05
@oxidase
Copy link
Contributor Author

oxidase commented Jan 3, 2018

@TheMarex @daniel-j-h 5.14.3 release fixes assertions

@oxidase oxidase added this to the 5.15.0 milestone Jan 3, 2018
@oxidase oxidase force-pushed the refactor/guidance branch 2 times, most recently from a2140c2 to 154ceb1 Compare January 3, 2018 18:09
@oxidase
Copy link
Contributor Author

oxidase commented Jan 3, 2018

The commit 154ceb1 changes turn instructions at places on the diff map http://geojson.io/#id=gist:oxidase/221b0b27779fbb5ca662a35d699708bc&map=12/37.8198/-122.3956

@oxidase oxidase merged commit 6d801e7 into master Jan 5, 2018
@oxidase oxidase deleted the refactor/guidance branch January 5, 2018 16:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants