-
Notifications
You must be signed in to change notification settings - Fork 320
NAVAND-1073: fix alternative routes refresh #6848
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
Conversation
ChangelogFeaturesBug fixes and improvements
Known issues
|
suspend fun MapboxNavigation.requestAlternativeRoutesAsync() = suspendCoroutine<Expected<RouteAlternativesError, List<NavigationRoute>>> { continuation -> | ||
requestAlternativeRoutes(object : NavigationRouteAlternativesRequestCallback { | ||
override fun onRouteAlternativeRequestFinished( | ||
routeProgress: RouteProgress, | ||
alternatives: List<NavigationRoute>, | ||
routerOrigin: RouterOrigin | ||
) { | ||
continuation.resume(ExpectedFactory.createValue(alternatives)) | ||
} | ||
|
||
override fun onRouteAlternativesRequestError(error: RouteAlternativesError) { | ||
continuation.resume(ExpectedFactory.createError(error)) | ||
} | ||
}) | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
does somebody use it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, thanks. I was just testing something.
mockWebServerRule.requestHandlers.add( | ||
FailByRequestMockRequestHandler( | ||
MockDirectionsRefreshHandler( | ||
"route_response_alternative_for_multileg", | ||
readRawFileText( | ||
activity, | ||
R.raw.route_response_alternative_for_multileg_refreshed | ||
), | ||
acceptedGeometryIndex = 11 | ||
) | ||
) | ||
) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why do you add the header in the middle of the test? Is that because the last header you add takes over all route refresh requests?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not really. It just doesn't have any effect until we add an alternative. Moved it to the beginning of the test.
18c1b64
to
4170356
Compare
val legGeometryIndex: Int? | ||
val primaryFork = alternativeMetadata.forkIntersectionOfPrimaryRoute | ||
val alternativeFork = alternativeMetadata.forkIntersectionOfAlternativeRoute | ||
if (primaryRouteProgressData.routeGeometryIndex < primaryFork.geometryIndexInRoute) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
do I understand it correctly?
if (primaryRouteProgressData.routeGeometryIndex < primaryFork.geometryIndexInRoute) { | |
val isForkPointAheadOnPrimaryRoute = primaryRouteProgressData.routeGeometryIndex < primaryFork.geometryIndexInRoute | |
if (isForkPointAheadOnPrimaryRoute) { |
it's up to you to apply suggestion or not
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes. I'll introduce a val.
} else { | ||
legIndex = alternativeFork.legIndex | ||
routeGeometryIndex = alternativeFork.geometryIndexInRoute | ||
legGeometryIndex = alternativeFork.geometryIndexInLeg | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
does it mean, that we have passed alternative, but didn't remove it from the tracking routes, we will be refreshing it starting from fork point?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Exactly.
ea36cba
to
b137e7c
Compare
if (isForkPointAheadOnPrimaryRoute) { | ||
val legIndexDiff = primaryFork.legIndex - alternativeFork.legIndex | ||
legIndex = primaryRouteProgressData.legIndex - legIndexDiff | ||
val routeGeometryIndexDiff = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As I know, even if 2 routes follow the same roads, they could have a different points in their geometry. I remember that Directions API inserts additional points if traffic between two points varies. I don't know which range of error in index we should expect and if it's critical. Maybe it is, maybe it's not. Anyway current solution makes things better, so maybe this suggestion is more for a followup PR.
I can propose following alternatives which shouldn't be affected by the difference in geometries:
- Make the NN track current alternative geometry index.
- Track it by ourselves: find nearest point in geometry to the current map matched position. As optimisation we can start search from routeGeometryIndexDiff as it should be very close.
@mapbox/navnative , any suggestions from your side?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Make the NN track current alternative geometry index.
That would be perfect, of course. :)
Track it by ourselves: find nearest point in geometry to the current map matched position. As optimisation we can start search from routeGeometryIndexDiff as it should be very close.
I'm not sure it's a very good idea to implement this platform-side.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As I know, even if 2 routes follow the same roads, they could have a different points in their geometry. I remember that Directions API inserts additional points if traffic between two points varies. I don't know which range of error in index we should expect and if it's critical. Maybe it is, maybe it's not. Anyway current solution makes things better, so maybe this suggestion is more for a followup PR.
Where would the fork be in this case? If the routes follow the same roads but the geometries are different? @mskurydin do you know?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure about routes that have actually different geometry, but there can be routes that have different number of geometry points.
For example, if there's an incident that appeared later on in the trip, the alternative route might have it while the primary route won't. So even though the actual geometry doesn't change, the introduction of an incident will make the alternative route have one more point than the primary route (the point where incident happened). This is a universal risk that we're carrying and a major problem with the refresh feature in itself.
I think that's just the risk will have to bear with for now (and make sure that the code doesn't crash in these situations).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the introduction of an incident will make the alternative route have one more point than the primary route
As far as I remember we Directions API also adds points for traffic when it needs more granularity, doesn't it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I believe so.
internal data class RoutesProgressData( | ||
val primaryRoute: NavigationRoute, | ||
val primaryRouteProgressData: RouteProgressData, | ||
val alternativeRoutesProgressData: List<Pair<NavigationRoute, RouteProgressData?>> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not important suggestion, just a matter of taste
val alternativeRoutesProgressData: List<Pair<NavigationRoute, RouteProgressData?>> | |
val alternativeRoutesProgressData: Map<NavigationRoute, RouteProgressData> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I want to keep the order.
...igation-core/src/main/java/com/mapbox/navigation/core/routerefresh/RouteRefreshController.kt
Outdated
Show resolved
Hide resolved
libnavigation-core/src/test/java/com/mapbox/navigation/core/RoutesProgressDataProviderTest.kt
Outdated
Show resolved
Hide resolved
Codecov Report
@@ Coverage Diff @@
## main #6848 +/- ##
============================================
+ Coverage 72.64% 72.67% +0.02%
- Complexity 5564 5575 +11
============================================
Files 781 783 +2
Lines 30116 30174 +58
Branches 3561 3570 +9
============================================
+ Hits 21878 21929 +51
- Misses 6810 6814 +4
- Partials 1428 1431 +3
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good to me. I don't see any major/blocking problems with this fix.
The only concern I have is how to test it. Current we rely on 1 instrumentation test. Maybe we need to highlight on UI of the test app the part of the route which was refreshed so that testers/early adopters could visually verify if expected part of the route was updated?
e360078
to
4bedcda
Compare
...ts/src/androidTest/java/com/mapbox/navigation/instrumentation_tests/core/RouteRefreshTest.kt
Outdated
Show resolved
Hide resolved
...ts/src/androidTest/java/com/mapbox/navigation/instrumentation_tests/core/RouteRefreshTest.kt
Outdated
Show resolved
Hide resolved
...ts/src/androidTest/java/com/mapbox/navigation/instrumentation_tests/core/RouteRefreshTest.kt
Outdated
Show resolved
Hide resolved
...ts/src/androidTest/java/com/mapbox/navigation/instrumentation_tests/core/RouteRefreshTest.kt
Outdated
Show resolved
Hide resolved
...rc/androidTest/java/com/mapbox/navigation/instrumentation_tests/utils/coroutines/Adapters.kt
Outdated
Show resolved
Hide resolved
.../androidTest/java/com/mapbox/navigation/instrumentation_tests/utils/routes/RoutesProvider.kt
Outdated
Show resolved
Hide resolved
...ts/src/androidTest/java/com/mapbox/navigation/instrumentation_tests/core/RouteRefreshTest.kt
Outdated
Show resolved
Hide resolved
...ts/src/androidTest/java/com/mapbox/navigation/instrumentation_tests/core/RouteRefreshTest.kt
Outdated
Show resolved
Hide resolved
...in/java/com/mapbox/navigation/core/routealternatives/AlternativeRouteProgressDataProvider.kt
Show resolved
Hide resolved
Idk, it looks to me that the logic for highlighting the refreshed part of the route might not be much simpler than the logic introduced here. And I'm not sure if it can be done without the changes on the SDK side (but I might be wrong). |
...in/java/com/mapbox/navigation/core/routealternatives/AlternativeRouteProgressDataProvider.kt
Outdated
Show resolved
Hide resolved
I have a simple idea. Add a button to the test application, which clears annotations that affect visual displaying of congestions. Wait for route refresh and you will be able to see what has been updated by appearing congestions. In this way we will be able to test manually and probably find even more cases similar to this. What do you think? |
1cccc9b
to
2058253
Compare
...in/java/com/mapbox/navigation/core/routealternatives/AlternativeRouteProgressDataProvider.kt
Outdated
Show resolved
Hide resolved
...in/java/com/mapbox/navigation/core/routealternatives/AlternativeRouteProgressDataProvider.kt
Outdated
Show resolved
Hide resolved
a0316e4
to
44a0db8
Compare
b62f509
to
cbf6d04
Compare
69259ab
to
e8c177b
Compare
da7ab52
to
302aa7e
Compare
CP: #6857 |
No description provided.