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

Route alternatives (aka FasterRoute v2) #4375

Merged
merged 1 commit into from
May 19, 2021
Merged

Conversation

kmadsen
Copy link
Contributor

@kmadsen kmadsen commented May 10, 2021

Description

Addressing feedback on Faster Route and making a more flexible interface and feature called Route Alternatives. Resolves #4233.

Surfaces the ability to continuously monitor route alternatives, migrates the options interface to be consistent with other features, and showcases an integration test. More details in this comment

  • Migrate to the route alternatives interface
  • Migrate to the options pattern
  • Surface native function to compare routes
  • Build an integration test
  • Comments and cleanup

Changelog

<changelog>Add ability to periodically observe route alternatives. Deleted `FasterRouteObserver` in favor of `RouteAlternativesObserver` and `RouteAlternativesOptions`.</changelog>

Screenshots or Gifs

Pictures of the routes on the instrumentation test. The test is initialized with the slower route, the faster alternative will periodically refresh.

Original Alternative
Screen Shot 2021-05-11 at 6 31 22 PM Screen Shot 2021-05-11 at 6 31 27 PM
rendering-alternatives.mp4

@kmadsen kmadsen force-pushed the km-alternative-routes-v2 branch 5 times, most recently from 0289296 to d158609 Compare May 12, 2021 15:52
@kmadsen kmadsen marked this pull request as ready for review May 12, 2021 15:52
@kmadsen kmadsen force-pushed the km-alternative-routes-v2 branch 2 times, most recently from 22502bf to 7702f7f Compare May 12, 2021 16:51
@kmadsen
Copy link
Contributor Author

kmadsen commented May 12, 2021

What's in review

  • RouteAlternativeOptions allow you to update a simple interval that the alternatives are requested - this could be done before but there has been confusion of how to do so.
  • The route alternatives are surfaced through the RouteAlternativeObserver with the current route filtered
  • Expose a isDifferentRoute function that allows you to compare cached routes or create "rejected lists" NOPE: Route alternatives (aka FasterRoute v2) #4375 (comment)
  • Created an instrumentation test to showcase how you can test faster route with ci systems

Should we add it now? - explicit call to request alternatives

Right now there is a set interval to request alternatives periodically. But we could expose a function to force it to trigger "out of interval". The function is already available in the RouteAlternativesController, we could surface it through MapboxNavigation. One side effect of this trigger, would be that the current intervaled request would be canceled - causing potentially wasted requests and more frequent cancels.

Out of scope - road aware alternative requests

Similar to explicitly requesting explicitly. Considering how we could use the road information to determine when to request route alternatives (approaching intersections, enter highway, exit highway, ...). This sounds good but considering it out of scope because I'd like to scope it with nav native.

Also we want to consider that, once the road tiles have been downloaded for things like EHorizon, the directions api request is not even needed. The onboard router is able to fulfill the request for alternatives - meaning a simple fast interval is also worth considering under these conditions.

Out of scope - alternative route progress

Similar to how the current route has progress. A driver will be making progress on an alternative route. This will impact how a alternative route lines are shown on the map while driving. This is considered out of scope of the current change, because it will not impact the current interface being designed. Continuously showing alternative routes will be addressed after integrating this interface.

@kmadsen kmadsen force-pushed the km-alternative-routes-v2 branch 3 times, most recently from 2faa0ad to 59f7477 Compare May 12, 2021 23:00
@LukasPaczos LukasPaczos requested a review from a team May 13, 2021 11:00
@LukasPaczos LukasPaczos added Core Work related to core navigation and integrations. feature New feature request. backwards incompatible Requires a SEMVER major version change. labels May 13, 2021
Copy link
Member

@LukasPaczos LukasPaczos left a comment

Choose a reason for hiding this comment

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

Looking good so far!

Should we add it now? - explicit call to request alternatives

I'm on the fence. Sounds like a great tool to give developers more flexibility and control when the request is triggered to build a UX around it. If we do that, we should add an option to disable the automatic alternative routes requests (RouteAlternativesOptions#enabled) so that developers can fully own this. However, if we do that, we still need to have some kind of a throttling mechanism so that we do not allow for flooding our APIs too easily. cc @jyrigo @AhmerKhan1 for visibility.

Expose a isDifferentRoute function that allows you to compare cached routes or create "rejected lists"

Could you give an example of how to build that rejected list? What would be the criteria? There is one feature that I think we might be missing for this to be possible, like Navigator#isDifferentRoute(route1, route2).

}

private companion object {
private val MINIMUM_REFRESH_INTERVAL = TimeUnit.SECONDS.toMillis(10)
Copy link
Member

Choose a reason for hiding this comment

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

Isn't that too often? I'm worried about the overhead that developers could even unintentionally cause.

Copy link
Contributor

Choose a reason for hiding this comment

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

I agree. What about battery power consumption?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Our default value is 5 minutes. The minimum allowed is 10 seconds. Customer feedback is typically, asking for lower lower thresholds.

For what it's worth, Lyft requested directions from Google once every 5 seconds in their driver app. Battery was not a concern because drivers are always plugged in.

Copy link
Member

Choose a reason for hiding this comment

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

I'm thinking more in terms of not flooding Directions API.

@kshehadeh @danpat we're reworking here a feature that periodically requests alternative routes (by making a new route request). What would be your recommendation for a minimal interval between those requests?

Copy link

Choose a reason for hiding this comment

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

@LukasPaczos Rather than hard-coding a refresh interval, I would do the following:

  • Examine the Cache-Control header and look at the max-age value. Set the refresh timer to trigger when max-age runs out.
  • If max-age is not set, look for an Expires header - if set, set the fresh timer to trigger when Expires occurs.
  • If neither header is set, use 60 seconds.

We do set Cache-Control on all API responses currently, and intend to do so indefinitely. Using these headers will allow us to optimize the experience for all customers without triggering excessive refresh requests at a resolution greater than our traffic/incident data is updating.

Copy link
Contributor Author

@kmadsen kmadsen May 17, 2021

Choose a reason for hiding this comment

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

@danpat just to clarify, because it's not about a route expiring. It's considering active guidance. This is different from a refresh interval. This is, examining the alternatives while in-route. So the origin location is changing.

For example, I just used Google's version of this. I was driving and there was a truck blocking the street. I looked at my phone and saw I had an alternative with a similar ETA by turning right a few meters ahead. Keeping track of these alternatives, is not about the age of the route - they expire when your location changes.

@abhishek1508
Copy link
Contributor

Continuously showing alternative routes when you are driving to a destination will be addressed after integrating this interface.

I think we should cut a ticket for this feature so that we don't forget.

cc @kmadsen

@abhishek1508
Copy link
Contributor

Looking at the code in a first glance, there are 2 questions that come to my mind:

  • Route Alternatives: is it same as alternative routes that you receive when you request the route for first time by setting RouteOptions.Builder().alternatives(true).build()
  • RouteAlternativeObserver: As a user do I need to register this observer to receive alternative routes the first time when I request a route with the above RouteOptions
  • RouteRefresh vs RouteAlternative: Reading the description of RouteAlternative it seems like these are routes that are faster and alternate to the current route you are driving on. If the understanding is correct, what does RouteRefresh do?

I guess my point is that we need to choose the nomenclature carefully as I think this is gonna lead to confusion and misinterpretation not only between customers but internally b/w support teams and TAM's as well.

cc @kmadsen @LukasPaczos

@kmadsen
Copy link
Contributor Author

kmadsen commented May 13, 2021

Responding to: #4375 (comment) cc: @abhishek1508

Route Alternatives: is it same as alternative routes that you receive when you request the route for first time by setting RouteOptions.Builder().alternatives(true).build()

Good question and not exactly. For example, alternatives(true) causes more than 1 route to be returned. If you have alternatives(false), then the RouteAlternativesObserver.onRouteAlternatives will never respond with more than 1 alternative route.

RouteAlternativeObserver: As a user do I need to register this observer to receive alternative routes the first time when I request a route with the above RouteOptions

Hmm good thought here. If you call MapboxNavigation.requestRoutes(.. alternatives(true) ).. It will not cause the RouteAlternativeObserver to trigger. The RoutesObserver is also capable of returning alternative routes. We could remove RouteAlternativeObserver in favor of only surfacing alternatives through RoutesObserver 🤔 - this is in fact, how we surface route refresh (but developers have asked about separating the callbacks).

RouteRefresh vs RouteAlternative: Reading the description of RouteAlternative it seems like these are routes that are faster and alternate to the current route you are driving on. If the understanding is correct, what does RouteRefresh do?

RouteRefresh only updates the current route's LegAnnotations (aka traffic). RouteAlternatives (FasterRoute) is essentially a MapboxNaivation.requestRoute poller. Which includes more information than traffic. The added logic, is that it accounts for the route progress.

@kmadsen
Copy link
Contributor Author

kmadsen commented May 13, 2021

Responding to #4375 (review) cc: @LukasPaczos

Should we add it now? - explicit call to request alternatives

I'm on the fence. Sounds like a great tool to give developers more flexibility and control when the request is triggered to build a UX around it. If we do that, we should add an option to disable the automatic alternative routes requests (RouteAlternativesOptions#enabled) so that developers can fully own this. However, if we do that, we still need to have some kind of a throttling mechanism so that we do not allow for flooding our APIs too easily. cc @jyrigo @AhmerKhan1 for visibility.

Good comments and questions. My opinion is that it is not needed for this change. Adding new options and functions will not be a breaking change - so we can continue to discuss and possibly add it in the future. Even as part of a minor version.

Expose a isDifferentRoute function that allows you to compare cached routes or create "rejected lists"

Could you give an example of how to build that rejected list? What would be the criteria? There is one feature that I think we might be missing for this to be possible, like Navigator#isDifferentRoute(route1, route2).

Thanks for the callout here. isDifferentRoute will not help identify previously rejected routes. The code we have to support "rejected lists" could be achieved by revising the RouteComparator.. but here we are deleting it. Worth requesting this from native cc: @SiarheiFedartsou

@kmadsen
Copy link
Contributor Author

kmadsen commented May 13, 2021

Continuously showing alternative routes when you are driving to a destination will be addressed after integrating this interface.

I think we should cut a ticket for this feature so that we don't forget.

@abhishek1508 https://github.com/mapbox/navigation-sdks/issues/985

@kmadsen
Copy link
Contributor Author

kmadsen commented May 14, 2021

@LukasPaczos @abhishek1508 An update after the feedback - so this is ready for another round.

  • Built a prototype to see how the api could change when adding more functionality from the navigator Prototype route alternatives rendering #4397
  • Conclusions: isDifferentRoute doesn't solve external problems so I removed it from this change
  • Conclusions: We can consider surfacing alternative route progress through the RouteObserver, but we should think about it more

The changes requested from the native team have a few different approaches. I think this change is still in the direction we want to go in, and we'll be able to follow up with improvements without breaking apis.

What do you think?

@LukasPaczos
Copy link
Member

We can consider surfacing alternative route progress through the RouteObserver, but we should think about it more

I'm thinking that we shouldn't. We advertise the RoutesObserver as the source of truth, so developers could receive the RouteAlternativesObserver call and then decide whether they want to accept those alternatives to be displayed, or dismiss them.

When they want to dismiss, they just do nothing.

When they want to display the alternatives, they call MapboxNavigation#setRoutes and swap indices 1 and 2 (if present) for new alternatives. In an ideal setup this change triggers RoutesObserver from which they redraw the route lines using the RouteLineApi.

@kmadsen kmadsen force-pushed the km-alternative-routes-v2 branch 2 times, most recently from 7e02a0d to 3bfcd32 Compare May 18, 2021 00:14
@kmadsen kmadsen force-pushed the km-alternative-routes-v2 branch 2 times, most recently from 4c6a874 to df2fb24 Compare May 18, 2021 02:01
@kmadsen kmadsen force-pushed the km-alternative-routes-v2 branch 3 times, most recently from 3a697ff to 1e487e5 Compare May 18, 2021 15:17
@kmadsen kmadsen force-pushed the km-alternative-routes-v2 branch 3 times, most recently from 5caa544 to 6c13e15 Compare May 18, 2021 17:12
@stevenm69
Copy link

stevenm69 commented May 18, 2021 via email

@kmadsen kmadsen force-pushed the km-alternative-routes-v2 branch 2 times, most recently from dfc3c6a to c98ab03 Compare May 19, 2021 16:37
Copy link
Member

@LukasPaczos LukasPaczos left a comment

Choose a reason for hiding this comment

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

:shipit:

@kmadsen kmadsen force-pushed the km-alternative-routes-v2 branch 2 times, most recently from 8b52a6f to 00f3156 Compare May 19, 2021 17:31
@kmadsen kmadsen merged commit 4c91e80 into main May 19, 2021
@kmadsen kmadsen deleted the km-alternative-routes-v2 branch May 19, 2021 18:46
@yunikkk
Copy link

yunikkk commented May 20, 2021

Thanks for the callout here. isDifferentRoute will not help identify previously rejected routes.

Our usecase required it specifically to filter current route/routeProgress from the overall list of routes. With new implementation isDifferentRoute seems not necessary with filtered alternatives returned.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backwards incompatible Requires a SEMVER major version change. Core Work related to core navigation and integrations. feature New feature request.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Confusing onFasterRoute API
6 participants