heremaps / here-sdk-examples

Android, iOS and Flutter example apps for the HERE SDK 4.x (Lite Edition, Explore Edition, Navigate Edition)
https://developer.here.com/products/here-sdk
Apache License 2.0
176 stars 135 forks source link

Traffic not display on route when navigation started. #237

Closed RahulFate closed 1 year ago

RahulFate commented 1 year ago

Hello Team,

I have implemented Here Map Navigate SDK version 4.13.4 in one of my application. When I calculate route and draw on mapview that time traffic on route is display. But after starting navigation traffic on route is not display. I have did all required changes to show traffic on route in navigation mode.

Following are things I did to show traffic on route.

`func onLoadScene(mapError: MapError?) { guard mapError == nil else { print("Error: Map scene not loaded, (String(describing: mapError))") return } enableTrafficVisualization() }

private func enableTrafficVisualization() {
    // Once these layers are added to the map, they will be automatically updated while panning the map.
    mapView.mapScene.enableFeatures([MapFeatures.trafficFlow : MapFeatureModes.trafficFlowWithFreeFlow])
    // MapFeatures.trafficIncidents renders traffic icons and lines to indicate the location of incidents.
    mapView.mapScene.enableFeatures([MapFeatures.trafficIncidents: MapFeatureModes.defaultMode])
}`

` // This renders the traffic flow on top of the route as multiple MapPolylines per span.
 func showTrafficOnRoute(_ route: Route) {
     BluetoothService.shared.write(text: "\n\n" + Date().description(with: Locale.current) + "\n" + "\n" + "show traffic on route ", to: "Navigation")
    if route.lengthInMeters / 1000 > 5000 {
      print("Skip showing traffic-on-route for longer routes.");
      return
    }

    for section in route.sections {
        for span in section.spans {
            let trafficSpeed = span.trafficSpeed
            guard let lineColor = getTrafficColor(trafficSpeed.jamFactor) else {
                // Skip rendering low traffic.
                continue
            }
            // A polyline needs to have two or more coordinates.
            guard let spanGeoPolyline = try? GeoPolyline(vertices: span.polyline) else {
                print("Error: Initialization of GeoPolyline failed.")
                return
            }
            let trafficSpanMapPolyline = MapPolyline(geometry: spanGeoPolyline,
                                                     widthInPixels: 10,
                                                     color: lineColor)
            mapView.mapScene.addMapPolyline(trafficSpanMapPolyline)
            mapPolylineList.append(trafficSpanMapPolyline)
    }
  }
}`

` // Define a traffic color scheme based on the route's jam factor.
// 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.
// Returns nil in case of no or light traffic.
private func getTrafficColor(_ jamFactor: Double?) -> UIColor? {
    guard let jamFactor = jamFactor else {
        return nil
    }
    if jamFactor < 4 {
        return nil
    } else if jamFactor >= 4 && jamFactor < 8 {
      return UIColor(red: 1, green: 1, blue: 0, alpha: 0.63) // Yellow
    } else if jamFactor >= 8 && jamFactor < 10 {
      return UIColor(red: 1, green: 0, blue: 0, alpha: 0.63) // Red
    }
    return UIColor(red: 0, green: 0, blue: 0, alpha: 0.63) // Black
}`

` static func getRouteForDestination(sourceLocation: PlaceLocation, destinationLocation: PlaceLocation, completionHandler: @escaping ((CustomRoute?,Route?)->())) {
    if routingEngine == nil {
        //self.initializeHERESDK()
        do {
            try routingEngine = RoutingEngine()
        } catch let engineInstantiationError {
            fatalError("Failed to initialize the HERE SDK. Cause: \(engineInstantiationError)")
        }
    }
    let sourceLocation = Waypoint(coordinates: GeoCoordinates(latitude: sourceLocation.lat, longitude: sourceLocation.lng))
    let destinationLocation = Waypoint(coordinates: GeoCoordinates(latitude: destinationLocation.lat, longitude: destinationLocation.lng))

    var scooterOptions = ScooterOptions()
    var routeOptions = RouteOptions()
    routeOptions.enableTrafficOptimization = true
    var routeTextOptions = RouteTextOptions()
    var avoidanceOptions = AvoidanceOptions()
    avoidanceOptions.roadFeatures = [.ferry,.controlledAccessHighway, .tollRoad]
    scooterOptions.allowHighway = true
    scooterOptions.routeOptions = routeOptions
    scooterOptions.textOptions = routeTextOptions
    scooterOptions.avoidanceOptions = avoidanceOptions

    routingEngine?.calculateRoute(with: [sourceLocation, destinationLocation], scooterOptions: scooterOptions, completion: { routingError, routes in
        if let error = routingError {
            completionHandler(nil,nil)
            return
        }
        FileLogger.write(text: "\n\(Date().description(with: Locale.current))")
        let route = routes?.min(by: {$0.duration < $1.duration})
        let durationTimeStamp = Int(route?.duration ?? 0)
        let distanceInMeter = Double(route?.lengthInMeters ?? 0)
        let customRoute = CustomRoute(travelDuration: durationTimeStamp, travelDistance: distanceInMeter)
        completionHandler(customRoute,route)
        routingEngine = nil
    })
}`

// For Start Navigation 

` private func startGuidance(route: Route) {
    do {
        // Without a route set, this starts tracking mode.
        try visualNavigator = VisualNavigator()
    } catch let engineInstantiationError {
        fatalError("Failed to initialize VisualNavigator. Cause: \(engineInstantiationError)")
    }

    visualNavigator?.cameraBehavior = DynamicCameraBehavior()
    // This enables a navigation view including a rendered navigation arrow.
    visualNavigator?.startRendering(mapView: mapView)

    // Hook in one of the many listeners. Here we set up a listener to get instructions on the maneuvers to take while driving.
    // For more details, please check the "Navigation" example app and the Developer's Guide.
    visualNavigator?.maneuverNotificationDelegate = self
    visualNavigator?.destinationReachedDelegate = self
    visualNavigator?.routeProgressDelegate = self
    visualNavigator?.speedWarningDelegate = self
    visualNavigator?.speedLimitDelegate = self
    visualNavigator?.routeDeviationDelegate = self

    // Set a route to follow. This leaves tracking mode.
    visualNavigator?.route = route
    //  var herePositioningProvider = HEREPositioningProvider()
    // Sets delegate to receive locations from HERE Positioning.
   //   herePositioningProvider.startLocating(locationDelegate: visualNavigator!, accuracy: .navigation)
    //   HEREPositioningProvider.sharedInstance.startLocating(locationDelegate: visualNavigator!, accuracy: .navigation)

    // VisualNavigator acts as LocationDelegate to receive location updates directly from a location provider.

    // Any progress along the route is a result of getting a new location fed into the VisualNavigator. - use below for simulte location
    setupLocationSource(locationDelegate: visualNavigator!, route: route)
}`

After getting route from calculate route function I am doing following actions to draw route 

` self.showRouteOnMap(route: route)
    self.showTrafficOnRoute(route)`

    Please help me to fix this issue.  Thanks
HERE-SDK-Support-Team commented 1 year ago

Hi @RahulFate, this is expected as you render the route with the VisualNavigator. Set navigator.routeVisible = false and you will see the route you have added yourself to the map. Hope this helps.

RahulFate commented 1 year ago

Hi Team, I render route using VisualNavigator and start navigation. Could you please explain in detail where I can set navigator.routeVisible = false

HERE-SDK-Support-Team commented 1 year ago

Hi @RahulFate, this can be set any time, even during ongoing rendering / tbt navigation. Hope this helps.

RahulFate commented 1 year ago

Hi, I quite confused here. I have to use visualNavigator for starting navigation or anything else. could you please share some sample code here to understand how I can achieve this and show traffic on route also.

is I need to set visualNavigator?.isRouteVisible = false ?

HERE-SDK-Support-Team commented 1 year ago

Yes, correct. Here is a link to the API: https://developer.here.com/documentation/ios-sdk-navigate/api_reference/content/Classes/VisualNavigator.html#/s:7heresdk15VisualNavigatorC14isRouteVisibleSbvp

This will not render any route when you call visualNavigator.startRendering(). If you have already added a route on the map with custom traffic formatting like shown in the dev guide, then you will see this route.

RahulFate commented 1 year ago

MicrosoftTeams-image

Hi, still After setting visualNavigator?.isRouteVisible = false traffic not display on route. Please check attached image. I need same type of traffic data on route while navigation.

HERE-SDK-Support-Team commented 1 year ago

Hi @RahulFate, just to be clear: The screenshot shows the route with the traffic you render on your own using our code snippet from the dev guide using jam factor.

That means isRouteVisible works as expected.

What you are asking now is that you see a difference between the traffic flow that is rendered on the map and the traffic on route?

This is answered in our dev guide, too. Unfortunately, this is expected:

The jamFactor indicating TrafficSpeed is calculated linear from the ratio of trafficSpeedInMetersPerSecond / baseSpeedInMetersPerSecond - without taking road types and other parameters into account. Therefore, the provided jamFactor does not necessarily match exactly the traffic flow visualization on the map view (if enabled). On top, the RoutingEngine uses predictive location services to predict upcoming traffic while traversing the route - whereas the traffic flow visualization represents only the current point in time.

Alternatively, you can give the route less width to let the traffic flow shine through, but this is not recommended, the traffic jam provides the latest traffic update based on travel time of the route.

RahulFate commented 1 year ago

Hi ,

I have attached screen shot from your here we go application for your reference. it is not display in my application using jam factor when navigation started.

HERE-SDK-Support-Team commented 1 year ago

Ok, can you show the code where you call visualNavigator?.isRouteVisible = false ?

Maybe you call it when visualNavigator is null.

RahulFate commented 1 year ago

` private func startGuidance(route: Route) { do { // Without a route set, this starts tracking mode. try visualNavigator = VisualNavigator() } catch let engineInstantiationError { fatalError("Failed to initialize VisualNavigator. Cause: (engineInstantiationError)") }

    visualNavigator?.cameraBehavior = DynamicCameraBehavior()
    // This enables a navigation view including a rendered navigation arrow.
    visualNavigator?.startRendering(mapView: mapView)

    // Hook in one of the many listeners. Here we set up a listener to get instructions on the maneuvers to take while driving.
    // For more details, please check the "Navigation" example app and the Developer's Guide.
    visualNavigator?.maneuverNotificationDelegate = self
    visualNavigator?.destinationReachedDelegate = self
    visualNavigator?.routeProgressDelegate = self
    visualNavigator?.speedWarningDelegate = self
    visualNavigator?.speedLimitDelegate = self
    visualNavigator?.routeDeviationDelegate = self
    visualNavigator?.isRouteVisible = false

    // Set a route to follow. This leaves tracking mode.
    visualNavigator?.route = route
    setupLocationSource(locationDelegate: visualNavigator!, route: route)
}`
HERE-SDK-Support-Team commented 1 year ago

It looks expected. And can you describe what you see? No route? Or the route you have rendered on your own?

RahulFate commented 1 year ago

after calculating route I draw route that time traffic display on route. But when I call startGuidance after that navigation start and on that route traffic not display.

HERE-SDK-Support-Team commented 1 year ago

Can you make sure this is not the expected route? For example, render the entire route in red. You should see the red route after starting guidance. It could be that when starting the route there is no traffic ...

RahulFate commented 1 year ago

Hi, Now I am able to see traffic on route in navigation mode. But now one another issue raised traversed route path colour is not changing. Please suggest how can I resolve this issue ?

HERE-SDK-Support-Team commented 1 year ago

Hi, can you explain what you mean by "traversed route path colour is not changing"? I think you are referring to the route-eat-up functionality.

Indeed, this is rendered by the VisualNavigator. When you render the route on your own, you have to use mapPolyline.progress = myProgress. You can also define the progress colors via MapPolyline if you do not like the default ones.

RahulFate commented 1 year ago

I would like to show gray colour for travelled route and blue colour for upcoming route.

HERE-SDK-Support-Team commented 1 year ago

Yes, this can be achieved when you set mapPolyline.progress and you can also define two progress colors.

RahulFate commented 1 year ago

Hi,

could you please suggest where and how I can set different colour for travelled route and upcoming route

HERE-SDK-Support-Team commented 1 year ago

Hi,

if you are using multiple MapPolyline objects to render the traffic jam factor on the route, then you need to calculate the lengths per polylines. Secondly, you need to do this relative for the polyline that is currently being traversed.

The HikingDiary app contains a code snippet you can use to calculate the length per polyline:

In order to know which polyline is currently being traversed, you can compare the map-matched location you get from the VisualNavigator instance with the points of the polyline.

RahulFate commented 1 year ago

Hi, When I set visualNavigator?.isRouteVisible = false then traffic display on route in navigation mode. But traversed path is not display in gray colour. When I set visualNavigator?.isRouteVisible = true then traversed path display in gray colour but traffic not display in route.

// This renders the traffic flow on top of the route as multiple MapPolylines per span.
     func showTrafficOnRoute(_ route: Route) {
         BluetoothService.shared.write(text: "\n\n" + Date().description(with: Locale.current) + "\n" + "\n" + "show traffic on route ", to: "Navigation")
        if route.lengthInMeters / 1000 > 5000 {
          print("Skip showing traffic-on-route for longer routes.");
          return
        }

        for section in route.sections {
            for span in section.spans {
                let trafficSpeed = span.trafficSpeed
                guard let lineColor = getTrafficColor(trafficSpeed.jamFactor) else {
                    // Skip rendering low traffic.
                    continue
                }
                // A polyline needs to have two or more coordinates.
                guard let spanGeoPolyline = try? GeoPolyline(vertices: span.polyline) else {
                    print("Error: Initialization of GeoPolyline failed.")
                    return
                }
                let trafficSpanMapPolyline = MapPolyline(geometry: spanGeoPolyline,
                                                         widthInPixels: 10,
                                                         color: lineColor)
                mapView.mapScene.addMapPolyline(trafficSpanMapPolyline)
                mapPolylineList.append(trafficSpanMapPolyline)
        }
      }
    }

    // Define a traffic color scheme based on the route's jam factor.
    // 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.
    // Returns nil in case of no or light traffic.
    private func getTrafficColor(_ jamFactor: Double?) -> UIColor? {
        guard let jamFactor = jamFactor else {
            return nil
        }
        if jamFactor < 4 {
            return nil
        } else if jamFactor >= 4 && jamFactor < 8 {
          return UIColor(red: 1, green: 1, blue: 0, alpha: 0.63) // Yellow
        } else if jamFactor >= 8 && jamFactor < 10 {
          return UIColor(red: 1, green: 0, blue: 0, alpha: 0.63) // Red
        }
        return UIColor(red: 0, green: 0, blue: 0, alpha: 0.63) // Black
    }

I am using above code to show traffic on route. Please suggest how to show traversed route by different colour

HERE-SDK-Support-Team commented 1 year ago

Hi @RahulFate, please see our previous answer that describes the algorithm how this can be achieved. As an alternative, for a future release of the HERE SDK, we plan to provide an automatic adaption of the route width per zoom level, so that the traffic flow and route can be seen together even at higher zoom levels.