Provide all intersections with additional information along a route via PathDetails#2590
Conversation
core/src/main/java/com/graphhopper/util/details/AverageSpeedDetails.java
Show resolved
Hide resolved
|
Interesting feature, thank you! I can imagine that this can be useful for other (analyzing) use cases too. Do you have an example JSON output of the path detail? And would it make sense to list all roads of the junction with some path details like road_class? (or even return all specified path details? And then in+out average_speed? Do we need the location in this path detail or better also use the index into the |
|
Thanks for your feedback. Here is a sample from the intersection json: "intersection": [
[
0,
1,
{
"entry": [
true
],
"bearings": [
109
],
"location": [
8.947839452785571,
48.533868607925086
],
"out": 0
}
],
[
1,
2,
{
"entry": [
true,
true,
false
],
"bearings": [
21,
184,
289
],
"in": 2,
"location": [
8.9480157,
48.5338281
],
"out": 0
}
],
[
2,
3,
{
"entry": [
true,
true,
false
],
"bearings": [
33,
89,
201
],
"in": 2,
"location": [
8.9480786,
48.5339366
],
"out": 0
}
],
[
3,
4,
{
"entry": [
true,
false
],
"bearings": [
49,
213
],
"in": 1,
"location": [
8.948174,
48.534033
],
"out": 0
}
]
]
At least for the navigation rerouting case, I am not sure if this makes sense. For data analysis, this could make sense.
We could do this, but this will become really tricky I think. I think the simplification happens after the calculation of the PathDetails, so at this point we don't know the intervals yet and we would have to calculate them similarly to how we do it for the instructions. So this would be quite complicated to do? |
Thanks! The path details in general include the interval for which they exist ( Is the bearing relative to the "current" edge and the And can you describe the Why is
Why should we include the location at all? Due to the path detail interval, which should work with the simplification, we already have the location (?)
Why is detaching the edge state necessary here?
This special case should be better done in the navigate converter (?) |
You mean to have PathDetails with from=to, only at the intersection? Sure this can be done, then we would probably need to add empty PathDetails in between the intersections?
It is absolute. 0 => north.
Yes, this is a trick I use to sort the entries by bearing. I created a small inner class that implements Comparable. This is translated to "Json" here. I explained the format in the class header, do you think more is necessary? https://github.com/graphhopper/graphhopper/pull/2590/files#diff-cddef4461eced91b655f853965fa82475b82e6b566ce6359c54b30d8cebd57daR36
Entry is an int, the index in the bearings array. So we have bearings of all edges, but only one of them are the entry.
I built it with the conversion for the NavigateResponse in mind and there it is easier to have the location :). It is not really an argument for the PathDetail, so I can change this if you like?
Ah, I think you are right, we could simply read the values from the Iterator. I think I had to use detach in an earlier version and haven't reverted that 👍
Yes 👍 |
The API would allow us to omit this which would make slightly more sense, but path simplification might not work and in general it is probably a good idea to always cover the entire path and include an "empty" path detail.
Sorry I don't understand what you mean here. If there are multiple edges that we can use as entry (your above examples shows e.g.
Also the name for
Yes would be better without location.
Why not? |
Ah sorry, you are right, I mixed entry with in and out :). For the naming I did follow the schema that is already consumable by the Maplibre Nav client, which is based on the Mapbox Directions API. So I followed the naming, we can choose completely different names and do the whole conversion in the navigation converter?
I think the idea is that for rerouting it wouldn't be a common turn? We can change that if you want?? |
# Conflicts: # core/src/main/java/com/graphhopper/util/details/PathDetailsBuilderFactory.java
I was wrong here, we can't do that with PathDetails, as a PathDetail has at least the lenght of one edge. And every edge change creates a new PathDetail. But we can omit the location 👍.
I think the reason for detaching was that it wasn't possible to compare edgeIds otherwise. The problem is that we can have VirtualEdgeIteratorStates and we have the method: Here we have a check for VirtualEdgeIteratorState, this does not work for I updated the PR. I removed the location from the PathDetails and renamed entry to entries on the GraphHopper side. The navigation endpoint still has to use entry, so it is a bit inconsistent now :( . |
Thanks 👍 ... and is it possible to move this special case to the /navigate endpoint?
As the format is otherwise also completely different I wouldn't call it inconsistent :)
Oh, ugly indeed. You could call "detach" only if it is a VirtualEdgeIterator :D Edit: can you also have a look if a response with this path detail is parsable by our Java client? e.g. serialized back into a map? I think atm we can only handle primitives. |
Ah sorry, I forgot about that one :). I deleted it for now, I think this should still work for the navigation client, if we see issues, we can always introduce special handling :).
I actually thought about this as well.
That is actually a really good point. It did not work. I added special handling for Map values and it should work now. |
karussell
left a comment
There was a problem hiding this comment.
Thanks for the changes. See my minor comments and can you also adapt to master?
core/src/main/java/com/graphhopper/util/details/IntersectionDetails.java
Outdated
Show resolved
Hide resolved
core/src/main/java/com/graphhopper/util/details/IntersectionDetails.java
Show resolved
Hide resolved
core/src/main/java/com/graphhopper/util/details/IntersectionDetails.java
Outdated
Show resolved
Hide resolved
|
@boldtrn can you review my comments? It seems close to merging :) |
|
Sorry I think your reply got lost in my emails somehow, I will update the PR so we can merge this :). |
|
I updated the PR. Sorry again for the delay. Let me know if this works for you, or if you need anything else. |
web-api/src/main/java/com/graphhopper/jackson/ResponsePathDeserializer.java
Outdated
Show resolved
Hide resolved
|
Thanks! |
Fixes #1415. This PR adds the ability to calculate the intersections for a route. This feature can be especially helpful for navigation clients to improve recognising off route cases. Navigation clients could do this because they know where an intersection is and at what angles users can turn onto a different road. This means that if a user is not close to an intersection, being away from the route is probably due to poor GPS or inaccurate road data. When leaving the route at an intersection with the provided bearing, the navigation client could recognise this case and calculate a new route.
We calculate the bearings similarly to how we do it for the instructions. The calculation requires to use the
atanfunction which is rather performance intensive, so there is a slowdown when you use this feature with CH. Since we calculate bearings for every edge change, the performance impact is larger than the performance impact of instructions. As this feature is optional there should be no influence for the regular routing, but it is forced for the NavigateResource. We have to force it for the NavigateResource as the Maplibre Navigation client can't change the request parameters easily, so that the client could opt in to get this information.In order to calculate the the bearings we need an EdgeExplorer and NodeAccess so I added the Graph to the
PathDetailsBuilderFactory.The format of the IntersectionDetails follows the format that we need in the NavigateResource.