# Add route options Enhancing the functionality of your routing application involves offering a variety of `RouteOptions` tailored to different user needs. This section explores the diverse range of routing capabilities available, enabling you to create more personalized and efficient routing experiences. ## Supported transport modes The HERE SDK supports the following route types: * **Car route directions:** Car routes use real-time and historical traffic information. Car routes follow roads that cars can enter and avoid areas where cars aren't allowed, such as pedestrian zones. Additionally, road restrictions like one-way streets and time-based road access like seasonal closures are taken into consideration. * **Taxi route directions:** In addition to the features available for car routes, taxi routes take into account taxi-restricted lanes as well as lanes reserved for exclusive taxi access. * **Truck route directions**: In addition to the features available for car routes, such routes take into account truck-related restrictions and other user-specified truck options. * **Routes for electric vehicles (EVs):** EV routes can track the energy consumption of the vehicle. When EV routes are calculated, charging stations can be added to the route to ensure that the user reaches their destination without running out of energy. At the same time, the route is optimized for the shortest overall travel and charging time. * **Bus route directions** with support for bus-only and bus-restricted lanes. * **Private bus route directions**: For privately operated bus companies that can't use bus-only streets in cities but might have permissions to use them as passenger pick-up or drop-off points. Bus-only streets are used only when a waypoint is placed on such a street. * **Pedestrian route directions** * **Scooter route directions:** A "scooter" is a low-power, two-wheeler vehicle, mainly used for in-city travel and transportation. Routes for scooters avoid highways and roads with travel speeds that exceed 60 km/h. Only `OptimizationMode.FASTEST` is supported. Dedicated scooter lanes are not yet supported. * **Bicycle route directions:** Bicycle routing is a mode designed for occasional cyclists to navigate within cities. Outdoor lanes and road surface information are not supported. Only car and pedestrian attributes are used, so, for example, roads with bicycle lanes are not prioritized. Riding against the traffic direction and on pedestrian segments outside of parks is not allowed. Bicycle routing uses the pedestrian road network, where roads are considered to be open for cycling if either of the following conditions apply: * The roads are open for both cars and pedestrians. * They are pedestrian roadways in a park. * The roads are closed for cycling, but the cyclist can dismount and carry the bicycle. This transition is represented by a change of `SectionTransportMode` from bicycle to pedestrian. * **Public transit routes**: Based on WGS-84 compliant start and end points, such routes make use of all available transit modes in a given city or metropolitan area. The transit options are highly customizable using the `TransitRoutingEngine`. * **Ferries and car shuttle trains** are used only for parts of a route if using them ensures following an optimal path. Changes in the used mode of transport are represented by a change of `SectionTransportMode`. > #### Note (HERE SDK for Android Navigate) > > All transport modes are available for online route calculation with the `RoutingEngine`. Some transport modes are also available for offline route calculation on cached map data or downloaded offline maps with the `OfflineRoutingEngine`. An overview of the supported offline modes can be seen [here](https://docs.here.com/here-sdk/docs/introduction-feature-list). The HERE SDK supports two-wheeler capabilities only for scooters and bicycles. For motorcycles, it is recommended to use car mode with customized `AvoidanceOptions` - to avoid highways for example. Not all transport modes allow to use EV options. Each route type is determined by the `RoutingOptions` class, which provides a unified way to configure route calculations for all transport modes. The desired transport mode is set via `routingOptions.transportSpecification.transportMode`. These options are passed to the `calculateRoute()` method of the `RoutingEngine`. The following transport modes can be set via `RoutingOptions`: * `TransportMode.CAR` to calculate car routes: `route.getRequestedTransportMode()` returns `TransportMode.CAR`. This is the default. * `TransportMode.TRUCK` to calculate truck routes: `route.getRequestedTransportMode()` returns `TransportMode.TRUCK`. * `TransportMode.PEDESTRIAN` to calculate routes for pedestrians: `route.getRequestedTransportMode()` returns `TransportMode.PEDESTRIAN`. * `TransportMode.CAR` or `TransportMode.TRUCK` with `ElectricVehicleOptions` set via `RoutingOptions.evOptions` to calculate routes for electric vehicles. * `TransportMode.SCOOTER` to calculate routes for scooters: `route.getRequestedTransportMode()` returns `TransportMode.SCOOTER`. * `TransportMode.BICYCLE` to calculate routes for bicycles: `route.getRequestedTransportMode()` returns `TransportMode.BICYCLE`. * `TransportMode.TAXI` to calculate routes for taxis: `route.getRequestedTransportMode()` returns `TransportMode.TAXI`. * `TransportMode.BUS` to calculate routes for buses: `route.getRequestedTransportMode()` returns `TransportMode.BUS`. * `TransportMode.PRIVATE_BUS` to calculate routes for private buses: `route.getRequestedTransportMode()` returns `TransportMode.PRIVATE_BUS`. * `TransitRouteOptions` to calculate routes for public mass transit (only available via `TransitRoutingEngine`): `route.getRequestedTransportMode()` returns `TransportMode.PUBLIC_TRANSIT`. The `TransportMode` is set by the routing engine after route calculation has been completed - while `getRequestedTransportMode()` determines the transport mode from the route options, each `Section` of a `Route` can have a different transport mode: `route.getSectionTransportMode()` provides the actual `SectionTransportMode` that has to be used for a particular section - in addition to the transport modes from above, it lists also transport modes such as `ferry` and `carShuttleTrain`. 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 and transport modes. Sections act as a route leg that break a route into several logical parts. Find more about this [here](#insert-multiple-waypoints). Although the main transport mode is specified by the user before calculating the route, the final transport modes are set by the routing engine per `Section`. > #### Note > > A `Route` can contain more than one `SectionTransportMode`. In such a case, the route will split into another `Section` to indicate the change of the transport mode. Basically, changing the mode of transport requires a stop on a journey, for example, when leaving the car to take a ferry. However, multimodal routing (or intermodal routing) is not supported: if a car route includes as destination a sightseeing spot in a park then the last waypoint will be map-matched to the last location before the park that is reachable by car - and the route will not contain a pedestrian section. > > Such gaps can be detected by comparing the `mapMatchedCoordinates` with the `originalCoordinates` of a `RoutePlace` object: an application can decide to fill the distance between these two coordinates with a new route calculation using a suitable transport mode as fallback - such modal routes can be composed with many different options as some users may prefer taking a taxi or public transit instead of taking a walk. Note that the HERE SDK supports such modal routes only as separate requests, so the application needs to implement the fallback logic. As an alternative, consider to use the [Intermodal Routing API](/transit/docs/readme). > > Note that all geographic coordinates along a route are map-matched (also known as snap-to-road). If additional `Waypoints` are added, they will be also map-matched and their original coordinates can be compared with the map-matched location inside a `RoutePlace` that is indicating the beginning and the end of a `Section`. All of the available 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. > #### Note > > 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, the 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. As a result, it is possible to prefer the red or blue route instead of the yellow route, even though both are slightly longer. Let's explore the other two options. When comparing the blue and the red route, the routing algorithm may recommend the blue route as the shortest 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 longer. The routing algorithm penalizes turns and many other road properties, such as traffic lights or rail crossings that can slow a driver down. > #### Note > > 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 via `VehicleSpecification` to find only the suitable routes where your truck would fit - considering parameters such as road width or tunnel height. Vehicle-specific restrictions for all transport modes can be set via `VehicleSpecification` on `RoutingOptions.transportSpecification`. 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 cases, setting additional waypoints may be a good idea. Find an example below. ## Insert multiple waypoints By default, when setting 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). Note that the online `RoutingEngine` supports only a limited number of waypoints of around 200 waypoints at most. 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. ```java Java Waypoint waypoint1 = new Waypoint(createRandomGeoCoordinatesInViewport()); Waypoint waypoint2 = new Waypoint(createRandomGeoCoordinatesInViewport()); List waypoints = new ArrayList<>(Arrays.asList(new Waypoint(startGeoCoordinates), waypoint1, waypoint2, new Waypoint(destinationGeoCoordinates))); routingEngine.calculateRoute( waypoints, new RoutingOptions(), new CalculateRouteCallback() { @Override public void onRouteCalculated(@Nullable RoutingError routingError, @Nullable List routes) { if (routingError == null) { // Handle the results. } } }); ``` ```kotlin Kotlin val waypoint1 = Waypoint(createRandomGeoCoordinatesAroundMapCenter()) val waypoint2 = Waypoint(createRandomGeoCoordinatesAroundMapCenter()) val waypoints = arrayListOf(Waypoint(startGeoCoordinates), waypoint1, waypoint2, Waypoint(destinationGeoCoordinates)) routingEngine?.calculateRoute( waypoints, RoutingOptions(), object : CalculateRouteCallback { override fun onRouteCalculated(routingError: RoutingError?, routes: List?) { if (routingError == null) { // Handle the results. } } }) ``` 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. > #### Note > > 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: ```java Java // estimatedTravelTimeInSeconds includes traffic delay. long estimatedTravelTimeInSeconds = route.getDuration().getSeconds(); long estimatedTrafficDelayInSeconds = route.getTrafficDelay().getSeconds(); int lengthInMeters = route.getLengthInMeters(); ``` ```kotlin Kotlin // estimatedTravelTimeInSeconds includes traffic delay. val estimatedTravelTimeInSeconds: Long = route.duration.seconds val estimatedTrafficDelayInSeconds: Long = route.trafficDelay.seconds val lengthInMeters: Int = route.lengthInMeters ``` Travel time and length are also available for each `Section`: ```java Java private void logRouteSectionDetails(Route route) { DateFormat dateFormat = new SimpleDateFormat("HH:mm"); for (int i = 0; i < route.getSections().size(); i++) { Section section = route.getSections().get(i); Log.d(TAG, "Route Section : " + (i + 1)); Log.d(TAG, "Route Section Departure Time : " + dateFormat.format(section.getDepartureLocationTime().localTime)); Log.d(TAG, "Route Section Arrival Time : " + dateFormat.format(section.getArrivalLocationTime().localTime)); Log.d(TAG, "Route Section length : " + section.getLengthInMeters() + " m"); Log.d(TAG, "Route Section duration : " + section.getDuration().getSeconds() + " s"); } } ``` ```kotlin Kotlin private fun logRouteSectionDetails(route: Route) { val dateFormat: DateFormat = SimpleDateFormat("HH:mm", Locale.getDefault()) for (i in route.sections.indices) { val section: Section = route.sections.get(i) Log.d(TAG, "Route Section : " + (i + 1)) Log.d(TAG, "Route Section Departure Time : " + dateFormat.format(section.departureLocationTime!!.localTime) ) Log.d(TAG, "Route Section Arrival Time : " + dateFormat.format(section.arrivalLocationTime!!.localTime) ) Log.d(TAG, "Route Section length : " + section.lengthInMeters + " m") Log.d(TAG, "Route Section duration : " + section.duration.seconds + " s") } } ``` 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. > #### Note > > An `stopover`-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 entire polyline directly from the `Route` object. ### Get map-matched waypoints For calculating a route, you can use any desired location as start, destination or as intermediate `STOPOVER` or `PASS_THROUGH` waypoint - even if it is off-road. The resulting route may, however, not exactly pass through the specified waypoint. The routing algorithm will attempt to come as close to the specified coordinates as possible. To achieve this, the HERE SDK incorporates an advanced technique to find the nearest route segment for each set of coordinates - taking various parameters such as the specified transportation mode into account. This process is called map matching. The route shape, however, consists only of map-matched waypoints. For each `Section` of a `Route` you can access a `RoutePlace` at the beginning (departure place) of a section and at the end (arrival place). A `Routeplace` contains `mapMatchedCoordinates` and `originalCoordinates` that were passed as parameters. Both can be equal or different. If they are different, it means that the `originalCoordinates` do not lie on a road. A `RoutePlace` contains more information that might be useful to assist you on your trip. For example, you can access `chargingStation` information along with `chargeInKilowattHours` - useful for electric vehicles (see below) - and the `sideOfDestination` of the original waypoint. Imagine you are traveling along the route and as a stopover, you have specified a sightseeing spot which is off the road. When you reach the corresponding map matched waypoint - while staying on the road and heading towards your destination along the route, the `sideOfDestination` field will indicate whether your sightseeing spot (or restaurant as illustrated above) is on the left or on the right side of the street you are currently traveling on. In some cases, a specified stopover may also be in front of you, above or even below your current location - in such a case, the `sideOfDestination` field will indicate the location as `UNDEFINED` - for example, if you are attempting to reach a lake and the road ends right in front of it. ### Set a place as waypoint A `Place` obtained from the `SearchEngine` may contain one or more access points. For example, a large warehouse can have multiple entrances, while the center of the warehouse may not be directly reachable. Note that access points are meant to be reachable by vehicles. For routes it is recommended to navigate to one of the available access points (if any), whereas the `sideOfStreetHint` should be set to the geographic coordinates of the place. The list is empty when no access points are known or when the place is directly reachable. ```java List accessPoints = place.getAccessPoints(); Waypoint destinationWaypoint = new Waypoint(place.getGeoCoordinates()); if (!accessPoints.isEmpty()) { // Set the first access point of a place as route destination. destinationWaypoint.coordinates = accessPoints.get(0); // When reaching destination provide a hint on the actual location of the place. destinationWaypoint.sideOfStreetHint = place.getGeoCoordinates(); } ``` A `RoutePlace` on the resulting `Route` object contains a `RoutePlaceType` which is set to `ACCESS_POINT` when a waypoint was set to an access point. Take a look at the above illustration to see how the `sideOfStreetHint` will impact the `SideOfDestination` of a `RoutePlace`. Note that if a place contains multiple access points, the user is responsible for selecting an appropriate one. ### Set a waypoint as starting point When starting a trip it may help to provide the `RoutingEngine` additional hints to choose the appropriate start direction - for example, to enforce necessary u-turns. For example, you can specify the initial heading direction like this: ```swift startWaypoint.headingInDegrees = location.bearingInDegrees; ``` If a user is moving, the bearing value can help to improve the route calculation. Note that the `Location` object contains a bearing value when it is taken from a positioning source and the user was already moving. Otherwise, it may not be set. Such a scenario may be more common during guidance, for example, when it is necessary to recalculate a route after a user has deviated from the proposed path. ### Optimize the waypoint order (HERE SDK for Android Navigate) The `OfflineEngine` (see above) also allows offline waypoint sequencing to support the [traveling salesman](https://en.wikipedia.org/wiki/traveling_salesman_problem) use case. Note that the feature is not yet supported for the online `RoutingEngine`. Multiple stopover `Waypoint` items along a `Route` can be ordered automatically by setting the `RouteOptions.optimizeWaypointsOrder`: if set to `true`, the `OfflineRoutingEngine` will try to optimize the waypoints order to reach the destination faster or to make the route shorter - while ensuring that all set waypoints of type `stopover` are reached. The specified `OptimizationMode` determines if the reordering results in a faster or shorter route. At least 5 or more waypoints (including starting point and destination) need to be set in order to see an effect on the route calculation. If needed, the reshuffled waypoints can be identified by comparing the `originalCoordinates` of each `RoutePlace` with the user-defined coordinates. `RoutePlace` objects are provided for each `Section` of a `Route` object as each stopover splits the route into sections. During navigation the `MilestoneStatus` event informs if a user-defined waypoint has been reached. ## Avoid road features Use `AvoidanceOptions` to exclude tunnels, highways, low emission zones (LEZ), areas, ferries, toll costs and other road features, like harsh turns. You can pass a list of `RoadFeatures`, `ZoneCategory`, `GeoBox`, `CountryCode` elements and more. `RoadFeatures` contains road specific features like tunnels or toll roads. For example, to exclude all highways from your journey, add `CONTROLLED_ACCESS_HIGHWAY` to the list of features. `AvoidanceOptions` can be set together with other route options including localization and unit options via `RoutingOptions.avoidanceOptions`. These options are then read when calculating a route and the engine will try to avoid the listed features. If it is not possible to avoid the set options, for example, when a route starts in a blocked area, you can inspect such violations in the provided `SectionNotice` elements. If these are set, you can decide to reject such a route. ## Avoid road segments You can avoid certain segments of the route by using `AvoidanceOptions`. To avoid a segment, use `SegmentReference`. Each `Span` of the `Route` contains a `SegmentReference` for the respective `Span`. The following example demonstrates how to avoid a segment of the route using `AvoidanceOptions`: ```java SegmentReference segmentReference = new SegmentReference(); // The segmentId and tilePartitionId can be obtained from each span of the Route object. // For example, the segmentId and tilePartitionId used below is part of the route created by above start and destination coordinates. String segmentId = "here:cm:segment:807958890"; long tilePartitionId = 377894441; segmentReference.segmentId = segmentId; segmentReference.tilePartitionId = tilePartitionId; AvoidanceOptions avoidanceOptions = new AvoidanceOptions(); avoidanceOptions.segments = Arrays.asList(segmentReference); routingOptions.avoidanceOptions = avoidanceOptions; ``` ### Retrieve a SegmentReference (only available for the Navigate) A `SegmentReference` can also be retrieved via [SegmentDataLoader](https://docs.here.com/here-sdk/docs/access-map-data-on-the-fly). For implementation details, see the [RoutingWithAvoidanceOptions](https://github.com/heremaps/here-sdk-examples) example app. ## Get toll costs You can get possible toll costs along the individual sections of a route. This includes also information on payment details for vignettes such as window sticker or road taxes. > #### Note > > For users of the `OfflineRoutingEngine` this is a beta release of this feature, so there could be a few bugs and unexpected behaviors. The `OfflineRoutingEngine` is available for licenses such as Navigate. For users of the `RoutingEngine` the feature is stable. The `routeOptions.enableTolls` flag must be set to get toll costs. It is set to `false` by default. When this flag is enabled, toll data is requested for toll applicable transport modes as defined in the API Reference. Get toll costs via `section.getTolls()` which provides a `PaymentMethod`, `TollFare` & general `Toll` information. ```java Java private void logTollDetails(Route route) { for (Section section : route.getSections()) { // The spans that make up the polyline along which tolls are required or // where toll booths are located. List spans = section.getSpans(); List tolls = section.getTolls(); if (!tolls.isEmpty()) { Log.d(TAG, "Attention: This route may require tolls to be paid."); } for (Toll toll : tolls) { Log.d(TAG, "Toll information valid for this list of spans:"); Log.d(TAG, "Toll systems: " + toll.tollSystems); Log.d(TAG, "Toll country code (ISO-3166-1 alpha-3): " + toll.countryCode); Log.d(TAG, "Toll fare information: "); for (TollFare tollFare : toll.fares) { // A list of possible toll fares which may depend on time of day, payment method and // vehicle characteristics. For further details please consult the local // authorities. Log.d(TAG, "Toll price: " + tollFare.price + " " + tollFare.currency); for (PaymentMethod paymentMethod : tollFare.paymentMethods) { Log.d(TAG, "Accepted payment methods for this price: " + paymentMethod.name()); } } } } } ``` ```kotlin Kotlin private fun logTollDetails(route: Route) { for (section in route.sections) { // The spans that make up the polyline along which tolls are required or // where toll booths are located. val tolls: List = section.tolls if (tolls.isNotEmpty()) { Log.d(TAG, "Attention: This route may require tolls to be paid.") } for (toll in tolls) { Log.d(TAG, "Toll information valid for this list of spans:") Log.d(TAG, "Toll systems: " + toll.tollSystems) Log.d(TAG, "Toll country code (ISO-3166-1 alpha-3): " + toll.countryCode) Log.d(TAG, "Toll fare information: ") for (tollFare in toll.fares) { // A list of possible toll fares which may depend on time of day, payment method and // vehicle characteristics. For further details please consult the local // authorities. Log.d(TAG, "Toll price: " + tollFare.price + " " + tollFare.currency) for (paymentMethod in tollFare.paymentMethods) { Log.d(TAG, "Accepted payment methods for this price: " + paymentMethod.name) } } } } } ``` > #### Note (HERE SDK for Android Navigate) > > During navigation - while following a route - you can use a `RoadAttributesListener` that informs on new road attributes including `isTollway` to know if the current road may require to pay a toll. In addition, a `TollStopWarningListener` provides events on upcoming toll booths. ## Get public transit routes Use the `TransitRoutingEngine` to calculate public transit routes from A to B with a number of waypoints in between. You can find a "PublicTransit" example app, provided in both [Java](https://github.com/heremaps/here-sdk-examples/tree/master/examples/latest/navigate/android/Java/PublicTransit) and [Kotlin](https://github.com/heremaps/here-sdk-examples/tree/master/examples/latest/navigate/android/Kotlin/PublicTransitKotlin) example app on [GitHub](https://github.com/heremaps/here-sdk-examples) that shows how to do this. ## 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, `RoutingOptions` allows you to set `VehicleSpecification` via `transportSpecification` to specify the dimensions of your truck, and more, that can be optionally applied to take the vehicle weight and other parameters into account. More information (only for Navigate) on turn-by-turn navigation for trucks can be found in the [Truck Guidance](https://docs.here.com/here-sdk/docs/navigation-truck) section. ## Get route labels Route labels provide information about the major street names or route numbers (such as highway identifiers) that a calculated route passes through. This feature is particularly useful when calculating multiple route alternatives, as route labels help users differentiate between them. Each alternative route is characterized by its key roads and highways, and `route.getRouteLabels()` automatically extracts the most important names and route numbers that make each path unique. This gives users immediate context about the major roads each route follows, enabling them to make more informed decisions based on their familiarity with local roads. To include route labels in the route response, you must enable the feature by setting `routeOptions.enableRouteLabels` to `true` before calculating the route. By default, this option is set to `false`. ```java RoutingOptions routingOptions = new RoutingOptions(); routingOptions.routeOptions.enableRouteLabels = true; ``` Once route labels are enabled, you can retrieve them from the calculated route using `route.getRouteLabels()`. Each `RouteLabel` contains two key pieces of information: * `name`: A `LocalizedText` object containing the street name or route number. * `type`: A `RouteLabelType` that indicates whether the label represents a street name or a route number. The following example demonstrates how to access and log route label information: ```java private void logRouteLabels(Route route) { // Get the list of the street names or route numbers through which the route is going to pass. // Make sure to enable this feature via routeOptions.enableRouteLabels. List routeLabels = route.getRouteLabels(); if (routeLabels.isEmpty()) { Log.d(TAG, "No route labels found for this route."); return; } for (RouteLabel routeLabel : routeLabels) { LocalizedText name = routeLabel.name; RouteLabelType routeLabelType = routeLabel.type; Log.d(TAG, "Route label: " + name.text + ", Type: " + routeLabelType.name()); } } ``` Example output: ```java Route label: Schönhauser Allee, Type: STREET_NAME Route label: Torstraße, Type: STREET_NAME ``` > #### Note > > If route labels are not enabled via `routeOptions.enableRouteLabels`, the `getRouteLabels()` method will return an empty list. ### Use RoutingOptions The unified `RoutingOptions` class is used for all transport modes. Below is an example showing how to configure `RoutingOptions` for a car route: ```java public void calculateVehicleRoute() { List waypoints = new ArrayList<>(Arrays.asList(new Waypoint(startGeoCoordinates), new Waypoint(destinationGeoCoordinates))); routingEngine.calculateRoute(waypoints, getCarVehicleOptions(), new CalculateRouteCallback() { @Override public void onRouteCalculated(@Nullable RoutingError routingError, @Nullable List routes) { if (routingError == null && routes != null && !routes.isEmpty()) { Route route = routes.get(0); ... } else { showDialog("Error while calculating route:", String.valueOf(routingError)); } } }); } private RoutingOptions getCarVehicleOptions() { RoutingOptions routingOptions = new RoutingOptions(); routingOptions.routeOptions.optimizationMode = OptimizationMode.FASTEST; // Default transportMode is CAR; we are setting it here explicitly for clarity. // Optionally, you can set VehicleSpecification, for example, if your car is having unusual dimensions. routingOptions.transportSpecification.transportMode = TransportMode.CAR; return routingOptions; } ``` `RoutingOptions` offers a vehicle-agnostic way to define both the vehicle specifications and, for example, the cargo being transported. Below you can find an example, how to use a vehicle specification which could be used to define properties for a truck. ```java // Builds a vehicle specification for truck, which would be used during route calculation for specific vehicle types. private VehicleSpecification buildTruckSpecification() { WeightPerAxleGroup axleGroup = new WeightPerAxleGroup(); axleGroup.singleAxleGroupInKilograms = 9000; axleGroup.tandemAxleGroupInKilograms = 17000; axleGroup.tripleAxleGroupInKilograms = 23000; return new VehicleSpecification.TruckBuilder() .withHeightInCentimeters(400) .withWidthInCentimeters(255) .withLengthInCentimeters(1800) .withAxleCount(6) .withTruckCategory(TruckCategory.TRACTOR) .withTrailerCount(1) .withTrailerAxleCount(3) .withGrossWeightInKilograms(44000) .withCurrentWeightInKilograms(40000) .withWeightPerAxleGroup(axleGroup) .withIsCommercial(true) .build(); } ... RoutingOptions routingOptions = new RoutingOptions(); routingOptions.transportSpecification.transportMode = TransportMode.TRUCK; routingOptions.transportSpecification.vehicleSpecification = buildTruckSpecification(); ```