# Directions

The HERE SDK provides a full-fledged route engine to calculate the best route directions from A to B, including multiple waypoints and localizable maneuver instructions for each turn. You can also specify your preferences by setting the desired route type (fastest or shortest) and various route options (such as speed profiles, route restrictions, vignette options, and more).

## Get Routes

The HERE SDK supports the following route types:

• Online car route directions.
• Online pedestrian route directions.
• Online truck route directions with highly customizable truck options.
• Online routes for electric vehicles to find the nearest charging stations (based on the calculated energy consumption and battery specifications).

Each route type is determined by one of the available route options: CarOptions, PedestrianOptions, TruckOptions, EVCarOptions and EVTruckOptions. These options can be set to the available overloads of the route engine's calculateRoute() method.

try {
routingEngine = new RoutingEngine();
} catch (InstantiationErrorException e) {
throw new RuntimeException("Initialization of RoutingEngine failed: " + e.error.name());
}


Creating a new RoutingEngine instance can throw an error that we have to handle as shown above. Such an error can happen, when, for example, the HERE SDK initialization failed beforehand.

Note: It is not possible to initialize this engine during the Application's onCreate() method. Any other point in time is fine. For example, a good place to initialize this engine may be in an Activity's onCreate()-method.

As a next step, you can calculate the route based on two waypoints - a starting location and a destination (both of type Waypoint that holds a GeoCoordinates instance). Below we set default CarOptions to calculate a route that is optimized for cars:

Waypoint startWaypoint = new Waypoint(startGeoCoordinates);
Waypoint destinationWaypoint = new Waypoint(destinationGeoCoordinates);

List<Waypoint> waypoints =
new ArrayList<>(Arrays.asList(startWaypoint, destinationWaypoint));

routingEngine.calculateRoute(
waypoints,
new CarOptions(),
new CalculateRouteCallback() {
@Override
public void onRouteCalculated(@Nullable RoutingError routingError, @Nullable List<Route> routes) {
if (routingError == null) {
Route route = routes.get(0);
showRouteDetails(route);
showRouteOnMap(route);
} else {
showDialog("Error while calculating a route:", routingError.toString());
}
}
});


You can call calculateRoute() multiple times, for example, to calculate routes with different routing options in parallel.

Each route calculation will be performed asynchronously. You will get a Route list or a RoutingError that holds a possible error when completed. If all goes well, it is null. In case of an error, the route list is null. For example, the engine cannot calculate routes if a route is not feasible for the specified mode of transportation.

If there is no error, the route list will contain only one result. By specifying the number of route alternatives via the route options, you can request additional route variants. By default, a route will be calculated with no route alternatives.

The showRouteDetails()-method from the code snippet above is used to show more route details including maneuver instructions. You can find the full source code in the accompanying example app. Maneuver instructions are also explained in greater detail below. The showRouteOnMap()-method contains an example, how to render a route on the map. We will explain this shortly in the section below.

## Use Route Options for Each Transport Mode

For the example above, we have set a new CarOptions instance to calculate a car route. You can calculate routes for other transport modes by using dedicated route options for each transport mode. The following route options exist:

• CarOptions to calculate car routes.
• TruckOptions to calculate truck routes.
• PedestrianOptions to calculate routes for pedestrians.

All of these route options allow you to further specify several parameters to optimize the route calculation to your needs.

Each of the above options contains a field that holds a common RouteOptions object. This option allows you to specify common options such as the number of route alternatives or the OptimizationMode to find the optimal route based on travel time and route length.

By default, a route will be calculated using the FASTEST route mode.

Alternatively, you can change the algorithm. For example, if you want to reach your destination quickly and the length of the route is less important to you, select the FASTEST route mode via RouteOptions. Select SHORTEST if you prefer a shorter route, and time is not so important.

To find the best route for you, the routing algorithm takes into account many different parameters. This does not mean the algorithm will always provide the absolute shortest or fastest route. For example, consider the following road network:

When you plan a trip from A to B, you may have the choice between four different roads. Let's assume that the green route represents a highway, then this road may be the fastest route, although it is longer than any of the other routes that would guide you through a city.

If you prefer to take the shortest route instead, then the route algorithm may favor the blue route, although the yellow and the red routes are shorter. Why is this so? The yellow road is the shortest route, of course, but it has to cross a river where a ferry has to be taken. This could be regarded by the algorithm as time-costly. Therefore -as a result- it is possible to prefer the red or blue route over the yellow route, although both are slightly longer.

Let's explore the other two options. The routing algorithm may recommend the blue route as the shortest when comparing the blue and the red route, although it is slightly longer than the red route: several turns are typically not beneficial to a driver. In this case, the red route contains more turns than the blue route, but the blue route may be the preferred route as it is only slightly shorter. The routing algorithm penalizes turns and many other road properties, such as traffic lights or rail crossings that can slow a driver down.

Along with the common routing options, the HERE SDK offers specialized options for the various supported transport modes, such as truck routing, where you can specify, for example, the dimensions of your truck to find only the suitable routes where your truck would fit - considering parameters such as road width or tunnel height.

While the resulting routes are optimized based on certain criteria, there may be situations where you don't want to rely on that. Imagine a city trip through Berlin - finding the fastest or shortest route may not be an option if you want to experience many sightseeing spots the city has to offer. In such a case, setting additional waypoints may be a good idea. Find an example below.

## Get Truck Routes

The HERE SDK supports different transport modes (see above) for route calculation. Similar to the example above that shows how to calculate a route optimized for cars, you can also calculate routes for other transport types such as trucks.

While you can already get a route optimized for trucks by setting the default options, there are many more options available to find the best routes for a truck.

For example, TruckOptions contains additional fields such as TruckSpecifications to specify the dimensions of your truck or a SpeedProfile that can be optionally applied to take the vehicle weight into account.

## Shape the Route with Additional Waypoints

By default, when passing only start and destination waypoints, the resulting route will contain only one route Section. Each route object can contain more route sections depending on the number of set waypoints. Sections act as a route leg that break a route into several logical parts.

Waypoints are coordinates that can be set by the user to determine more sections or the shape the route (which can be useful if you want to make sure you cross a river with a ferry, for example).

There can be two types of waypoints:

• STOPOVER: The default waypoint type. It is guaranteed that this point will be passed, therefore it appears in the list of maneuver instructions, and splits the route into separate route sections.
• PASS_THROUGH: May not appear in the maneuver instructions list and is rather treated as a hint to shape the route, for example, as a result of a touch input. This type will not split the route into separate sections.

When creating a new Waypoint object, the STOPOVER type is set by default - and this must be the type used for the first and the last waypoint. With just two waypoints acting as the start and destination, a route might look like below:

The RoutingEngine can handle multiple waypoints. The underlying algorithm will try to find the best path to connect all waypoints while respecting the order of the provided List - as well as the WaypointType. Each STOPOVER-waypoint is passed between the starting location and the destination, which are the first and last item of the waypoint list respectively.

Waypoint waypoint1 = new Waypoint(createRandomGeoCoordinatesInViewport());
Waypoint waypoint2 = new Waypoint(createRandomGeoCoordinatesInViewport());
List<Waypoint> waypoints = new ArrayList<>(Arrays.asList(new Waypoint(startGeoCoordinates),
waypoint1, waypoint2, new Waypoint(destinationGeoCoordinates)));

routingEngine.calculateRoute(
waypoints,
new CarOptions(),
new CalculateRouteCallback() {
@Override
public void onRouteCalculated(@Nullable RoutingError routingError, @Nullable List<Route> routes) {
if (routingError == null) {
Route route = routes.get(0);
showRouteDetails(route);
showRouteOnMap(route);
} else {
showDialog("Error while calculating a route:", routingError.toString());
}
}
});


By adding two additional STOPOVER-waypoints to the route using the code snippet above, we now have three route sections between the starting point and the destination as seen in the illustration below.

Please note that the waypoints list order defines the order in which they are going to be passed along the route.

Additional information on the route - such as the estimated time it takes to travel to the destination and the total length of the route in meters - can be retrieved from the Route object as shown below:

long estimatedTravelTimeInSeconds = route.getDurationInSeconds();
int lengthInMeters = route.getLengthInMeters();


Travel time and length are also available for each Section. Without additional STOPOVER-waypoints, the route will contain only one Section. If additional STOPOVER-waypoints are provided, the route is separated into several route sections between each waypoint, as well as from the starting point to the first waypoint and from the last waypoint to the destination.

By default, an additional waypoint splits a route into separate sections and forces the route to pass this point and to generate a maneuver instruction for it.

Each Section contains the shape of the route in form of a GeoPolyline - represented as an array of coordinates where the first coordinate marks the starting point and the last one the destination.

This can be useful to visualize the route on the map by using, for example, map polylines in a different color for each Section. However, you can also get the polyline directly from the Route object. Below is a code snippet that shows how this could be implemented by using a MapPolyline that is drawn between each waypoint including the starting point and the destination:

GeoPolyline routeGeoPolyline;
try {
routeGeoPolyline = new GeoPolyline(route.getPolyline());
} catch (InstantiationErrorException e) {
// It should never happen that a route polyline contains less than two vertices.
return;
}

float widthInPixels = 20;
MapPolyline routeMapPolyline = new MapPolyline(routeGeoPolyline,
widthInPixels,
Color.valueOf(0, 0.56f, 0.54f, 0.63f)); // RGBA



The first screenshot below shows a route without additional waypoints - and therefore only one route section. Starting point and destination are indicated by green-circled map marker objects. Note that the code for drawing the circled objects is not shown here, but can be seen from the example's source code, if you are interested.

The second screenshot shows the same route as above, but with two additional STOPOVER-waypoints, indicated by red-circled map marker objects. The route therefore, contains three route sections.

## Zoom to the Route

For some use cases, it may be useful to zoom to the calculated route. The camera class provides a convenient method to adjust the viewport so that a route fits in:

GeoBox routeGeoBox = route.getBoundingBox();
camera.lookAt(routeGeoBox, new MapCamera.OrientationUpdate());


Here we use the enclosing bounding box of the route object. This can be used to instantly update the camera: Zoom level and target point of the camera will be changed, so that the given bounding rectangle fits exactly into the viewport. Additionally, we can specify an orientation to specify more camera parameters - here we keep the default values. Note that calling lookAt() will instantly change the view.

## Get Maneuver Instructions

Each Section contains the maneuver instructions a user may need to follow to reach the destination. For each turn, an Maneuver object contains an action and the location where the maneuver must be taken. The action may indicate actions like "depart" or directions such as "turn left".

List<Section> sections = route.getSections();
for (Section section : sections) {
logManeuverInstructions(section);
}


And here is the code to access the maneuver instructions per section:

private void logManeuverInstructions(Section section) {
Log.d(TAG, "Log maneuver instructions per route section:");
List<Maneuver> maneuverInstructions = section.getManeuvers();
for (Maneuver maneuverInstruction : maneuverInstructions) {
ManeuverAction maneuverAction = maneuverInstruction.getAction();
GeoCoordinates maneuverLocation = maneuverInstruction.getCoordinates();
String maneuverInfo = maneuverInstruction.getText()
+ ", Action: " + maneuverAction.name()
+ ", Location: " + maneuverLocation.toString();
Log.d(TAG, maneuverInfo);
}
}


Additionally, an (optionally) HTML-formatted instruction is included. When logging the above maneuverInfo to the console, it may produce a result as printed below:

Turn <span class="direction">left</span> onto <span class="next-street">Pasewalker Straße</span>. <span class="distance-description">Go for <span class="length">1.1 km</span>.</span>,
Action: LEFT_TURN,
LatLon: LatLon{mLatitude=52.5790751,mLongitude=13.4288335}


This may be useful to easily build maneuver instructions lists describing the whole route in written form. For example, the ManeuverAction enum can be used to build your own unique routing experience.

## Find Traffic Along a Route

In addition to maneuvers (see above), each Section of a Route contains information of the traffic flow situation at the time when the route was calculated.

Each Section can contain a various amount of TrafficSpeed instances. These are valid along the sub sections of a section. The offset field indicates the index within the section's polyline which you can get as a list of GeoCordinates from the Section instance.

TrafficSpeed contains the baseSpeedInMetersPerSecond, which is the expected default travel speed. Note that this may not be the same as the current speed limit on a road - as a bad road condition may justify a slower travel speed. In addition, you can get the estimated actual travel speed based on the current traffic conditions with trafficSpeedInMetersPerSecond.

Similar to the color encoding used for the traffic flow layer, you can indicate the traffic along a route using a jamFactor that has a range from 0 (no traffic) to 10 (road is blocked). See the Traffic section for more details on the traffic features of the HERE SDK.

An example how this value can be mapped to a suitable color is shown below:

Usually, the jamFactor can be interpreted like this:

• 0 <= jamFactor < 4: No or light traffic.
• 4 <= jamFactor < 8: Moderate or slow traffic.
• 8 <= jamFactor < 10: Severe traffic.
• jamFactor = 10: No traffic, ie. the road is blocked.

Note that the jamFactor is not necessarily a linear result calculated from the ratio of trafficSpeedInMetersPerSecond / baseSpeedInMetersPerSecondas it additionally takes also the road type and other conditions into account.