-
Notifications
You must be signed in to change notification settings - Fork 319
Route preview state #6107
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
Route preview state #6107
Conversation
20521c0 to
724d720
Compare
| fun setPreviewedRoute() { | ||
| val routes = directionsSession.routes | ||
| if (routes.isNotEmpty()) { | ||
| internalSetNavigationRoutes( |
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.
How is it gonna affect billing? It receives a route in MapboxNavigation#setNavigationRoutes, not in internalSetNavigationRoutes .
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.
thanks, but billing is not supposed to work in this prototype
| initialLegIndex: Int = 0, | ||
| ) { | ||
| //TODO: parse alternatives metadata using NN and set it route alternatives controller | ||
| directionsSession.setRoutes(routes, initialLegIndex, RoutesExtra.ROUTES_UPDATE_REASON_NEW) |
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.
directionsSession notifies RouteObservers. From the docs:
* The route at index 0, if exist, will be treated as the primary route for 'Active Guidance'.
*
* A list of routes can be modified internally and externally at any time with
* [MapboxNavigation.setRoutes], or during automatic reroutes, faster route and route refresh operations.
Wouldn't it be too big a change in the behaviour? Because now it's not only about ActiveGuidance anymore. I'm not sure it would, just wondering.
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.
new state won't break existing behaviour because only new methods can trigger new state
| initialLegIndex: Int = 0, | ||
| ) { | ||
| //TODO: parse alternatives metadata using NN and set it route alternatives controller | ||
| directionsSession.setRoutes(routes, initialLegIndex, RoutesExtra.ROUTES_UPDATE_REASON_NEW) |
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.
Which NavigationSessionState are we gonna be in after this invocation? The prev one, right, nothing changes here?
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.
That's a very good question. I would vote for introducing a new state, but it requires deprecation of old states and introducing a new one.
Codecov Report
@@ Coverage Diff @@
## main #6107 +/- ##
=========================================
Coverage 70.10% 70.10%
- Complexity 4824 4825 +1
=========================================
Files 706 706
Lines 27840 27830 -10
Branches 3276 3272 -4
=========================================
- Hits 19518 19511 -7
+ Misses 7042 7040 -2
+ Partials 1280 1279 -1
|
5c78a48 to
5d4d237
Compare
|
Currently, this PR demonstrates a new API and I want to hear your feedback about the new API. The implementation is quite raw for now: it contains many workarounds and doesn't work well in all cases, so, please focus on the API during review. I will polish the implementation after the feedback about API. @abhishek1508, @kmadsen , can you please check if the preview state solves the problem of sync between Drop-In and car play. @Guardiola31337 , can you please check new session state, does it break something in copilot? @LukasPaczos , @RingerJK , @dzinad , I'm requesting your feedback too 🙂 |
| ) : NavigationSessionState() | ||
| } | ||
|
|
||
| sealed class NavigationSessionStateV2 { |
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.
how to you think, should we replace sealed class by a set of string constants, to be able to add more states in the future?
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 tend to think no. I doubt that we will need more states before v3. And for users it should be more comfortable to use sealed class.
|
Regarding your diagram, I think you should also add a loop from AG to AG via |
|
I see that you now don't allow setting routes from "not active" state directly. It's only set route preview, only then set routes. Do you think it's a good idea? That would break the flow for those who don't use route preview, wouldn't it? Or is it just that the diagram is incomplete? |
|
Is setting route preview during Active Guidance, as mentioned by @RingerJK in another PR, not supported yet? |
Why do you need a primary route in the alternative route object? |
Good catch, thanks. I also missed ability to start route preview from active guidance. I will fix this |
fixed |
it maybe doesn't make sense. As I said, this data structure should be discussed in the future. I mentioned it just to cover the problems this PR doesn't intent to solve and my vision of how those problems should be solved later. |
| threadController.getMainScopeAndRootJob().scope.launch(Dispatchers.Main.immediate) { | ||
| routeUpdateMutex.withLock { | ||
| val alternatives = routes.drop(1) | ||
| val routesData = RouteParser.createRoutesData( |
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.
Didn't you forget to commit RouteParser?
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.
This class comes from NN
| routes.first().nativeRoute(), | ||
| alternatives.map { it.nativeRoute() } | ||
| ) | ||
| routeAlternativesController.processAlternativesMetadata( |
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.
It would clear the cache of metadata that was set previously. But I guess that's OK because in the docs for getAlternativeMetadataFor we have the following:
* If the provided [navigationRoute] is an alternative route in the current session,
* this function will return the associated route metadata.
and setting routes preview means the session's changes, right? BTW, what's "session" here?
| routes, | ||
| routesData.alternativeRoutes() | ||
| ) | ||
| directionsSession.setRoutes(routes, BasicSetRoutesInfo(RoutesExtra.ROUTES_UPDATE_REASON_PREVIEW, initialLegIndex)) |
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.
That would trigger RoutesObserver. Is that expected? The docs for RoutesObserver#onRoutesChanged say:
The route at index 0, if exist, will be treated as the primary route for 'Active Guidance'.
That's not true anymore.
UPD: I think that's expected. But isn't it a breaking change?
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 don't think it's a breaking change. Users don't have to use preview state right after update. But if they start using it, they receive previewed route in the route observer.
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.
OK, makes sense. But at least we should update the docs for RoutesObserver#onRoutesChanged.
BTW, we use MapboxNavigation#internalRoutesObserver to trigger refresh when routes are set. Shouldn't we adopt the logic? I suppose we don't need refresh for preview?
libnavigation-core/src/main/java/com/mapbox/navigation/core/MapboxNavigation.kt
Show resolved
Hide resolved
| hasRoutes: Boolean, | ||
| routePreview: Boolean | ||
| ): NavigationSessionStateV2 = when { | ||
| hasRoutes && routePreview -> { |
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.
What if we're driving here? It should be FreeDrive, shouldn't it?
For V1 it's FreeDrive and I think it makes more sense.
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 you correctly?
mapboxNavigation.startTripSession()
mapboxNavigation.setNavigationRoutesForPreview(routes)
mapboxNavigation.getNavigationSessionStateV2() // Do you expect get FreeDrive state here?
...s/src/androidTest/java/com/mapbox/navigation/instrumentation_tests/core/PreviewRoutesTest.kt
Outdated
Show resolved
Hide resolved
| } | ||
|
|
||
| @Test | ||
| fun preview_route_with_alternative() = sdkTest { |
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.
Maybe get_alternative_metadata_for_previewed_route?
| @Test | ||
| fun preview_route() = sdkTest { | ||
| val routes = RoutesProvider.dc_very_short(activity).toNavigationRoutes() | ||
| mapboxNavigation.startTripSession() |
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'd also add tests:
- where you don't start trip session to check the transition from Idle to RoutePreview.
- Where you are in AG and then stop trip session and set routes preview (to check AG -> RoutePreview transition)
| binding.navigate.visibility = VISIBLE | ||
| binding.navigate.setOnClickListener { | ||
| setRoute() | ||
| binding.navigate.visibility = INVISIBLE |
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 INVISIBLE, not GONE? The same question for xml.
examples/src/main/java/com/mapbox/navigation/examples/core/MapboxNavigationActivity.kt
Outdated
Show resolved
Hide resolved
Discussed with @VysotskiVadim internally. Capturing the highlights for reference and visibility. Copilot is going to be a feature of the Nav SDK so they should go hand by hand i.e. if there are breaking changes in Copilot affecting the SDK, we should adapt the code to support them (as with any other dependency). Worth mentioning that Copilot is going to be an internal feature (we’re not going to expose anything of the guts to external users). The key on this topic from Copilot is |
d8be4f6 to
f948d8c
Compare
f948d8c to
3c323da
Compare
|
Guys, I really want to hear some feedback from you about route preview before I polish the code: @abhishek1508 , does it solve the problem of synchronisation between Drop-In and Android auto? @mapbox/navigation-android , do you see any cases where the feature doesn't work good? |
libnavigation-core/src/main/java/com/mapbox/navigation/core/trip/session/NavigationSession.kt
Show resolved
Hide resolved
Yeah, I don't think Copilot will be impacted as it only cares about the transitions from Free Drive to Active Guidance and viceversa. So yeah, as long as route preview state doesn't interfere with those we should be good. |
|
closed in favour to #6495 |
This PR introduces a preview state in
MapboxNavigation.MapboxNavigationwill be a single source of truth for different clients: mobile app, Drop-In UI, android auto. We wan't charge users for route preview, but if trip session is started, the users will be charged if they are in free drive.The preview state doesn't mean that you can't implement route preview without it. You still can draw a route using route line without
MapboxNavigation. But the route preview state will be the default approach for this as it automatically syncs the state with android auto.States before this PR
New preview state
Is the PR ready for review?
Yes. It's still requires some polishing(documentation, code style, more tests) but it works. If some aspect doesn't work for you, please report it in comments 🙂
I recommend you checking
PreviewRoutesTestandMapboxNavigationActivityto see the preview API in action.route-preview-state.mp4
TODO in followup PRs:
Next steps after "route preview" feature
The introduced route preview state doesn't cover the case when an app developers want to show route preview during active guidance. They can manually draw a route using route line, but
AlternativesMetadataisn't available there. The next logical step I see, is to introduce a data structure which replacesList<NavigationRoute>everywhere(setNavigaitonRoutes,previewNavigationRoutes, etc).This data structure will solve the problems this PR doesn't address:
RoutesDataon set route, which will be carried byNavigationRoutesMapboxNavigation, which will let preview a route even during active navigationThis next step will need to be discussed. I described it ahead because I assume that you ask me about those unsolved problems.