Roundtrips
The Routing API offers the ability to generate a random route, starting at a given waypoint and back to that same point.
The main differences between roundtrip generation and normal routing are:
- A normal route needs to have at least two input waypoints. Roundtrip generation needs only one; if multiple waypoints are given, the additional ones are ignored. The generated roundtrip will consist of multiple output waypoints however; the additional ones are created by the algorithm.
- Normal routing is deterministic: as long as all relevant inputs (map data, live traffic information, etc) remain unchanged, you can expect the same route to be generated for a given sequence of waypoints. The roundtrip generation algorithm, on the other hand, is random by design: every time you call
calculateRoutea new roundtrip will be generated. It is however possible to explicitly specify a "seed value", in which case for a given seed value the generated roundtrip will be the same each time, as long as all other relevant data isn't changed.
Apart from that, all the normal routing preferences, such as the vehicle profile and the user's fitness factor, are taken into account.
Relevant data types
The ERangeType enumeration is used to specify the meaning of the units used for the range parameter. At the time of this writing, this enumeration is only used for the roundtrips feature.
| ERangeType value | Numeric value | Description |
|---|---|---|
| Default | 0 | Equivalent to DistanceBased when route type is RT_Shortest; equivalent to TimeBased for all other route types. |
| DistanceBased | 1 | Range is a distance, measured in meters. |
| TimeBased | 2 | Range is a duration, measured in seconds. |
| (EnergyBased) | (3) | Not currently supported. |
For example, a value of 10,000 would mean 10km for a distance-based request but 10,000 seconds, or about three hours, for a time-based request. To avoid confusion is is recommended to avoid the Default value and specify DistanceBased or TimeBased explicitly. The Default value is supported for consistency with the Ranges (aka Isochrones) feature.
Relevant parameters
| Parameter | Type | Description |
|---|---|---|
| range | uint32 | Desired length or duration of the roundtrip. The algorithm will attempt to approximate this target but is not guaranteed to match it exactly. |
| rangeType | ERangeType | Units in which the range are specified, as described above. |
| randomSeed | uint32 | Value 0 will randomly generate a different roundtrip each time. For any other value, roundtrip generation is deterministic, as long as all relevant other data and parameters stay the same too. |
Relevant API calls
On the RoutePreferences class in GEM_RoutingPreferences.h:
| Method | description |
|---|---|
RoutePreferences& setRoundtripParameters(uint32_t range, ERangeType rangeType, uint32_t randomSeed = 0) | Set the roundtrip parameters |
uint32_t getRoundtripRange() const | Get the currently set roundtrip range |
gem::ERangeType getRoundtripRangeType() const | Get the currently set roundtrip range type |
uint32_t getRoundtripRandomSeed() const | Get the currently set random seed value |
Usage
Create a Preferences object and set the range and rangeType parameters, as appropriate. A range value greater than zero is what defines a routing call as a roundtrip request.
Make sure that the value chosen for the range is appropriate for the range units used; e.g.
Then, call RoutingService::calculateRoute as usual, with at least one waypoint and with a greater-than-zero range value in the preferences object.
As with any other routing call, the calculation will happen asynchronously and notifyComplete will be called on the ProgressListener when finished. As always, be sure to check the return code; because of the random nature of the roundtrip generation algorithm it can sometimes happen that multiple calls with identical parameters will sometimes succeed and other times fail.
When the user has selected a roundtrip and wants to start navigating it, the generated route should first be converted to an OnTrack route! This is so that re-routing will work correctly when the user deviates from their route and wants to return to it. Otherwise, because of the nondeterministic nature of the generation algorithm, it can happen than after a recalculation a different route will result.
Here is an example of how to convert a route to an OnTrack route:
Landmark wpt;
RouteBookmarks::setWaypointTrackData( wpt, roundtripRoute.getPath() );
Route newRoute;
RoutesList routesList;
routesList.push_back(newRoute);
auto preferencesWithoutRoundtrip = RoutePreferences(routePreferences).setRoundtripParameters(0, gem::ERangeType::Default);
RoutingService().calculateRoute( routesList, { wpt }, preferencesWithoutRoundtrip, listener);
In the notifyComplete handler of that final calculateRoute you would then have the route to call gem::NavigationService().startNavigation() on.