Skip to content

from "Bring your own route" example with firebase server coordinates #237

Description

@Lutraki

I'm new to Mapbox, I'm developing apps like uber, so customer apps and driver apps
I would like on customer app to see the driver user move from his starting point to the customer's pickup point, reading the coordinates from a server in this firebase

Before the actual navigation, I was able to draw the 2 routes with navigationMapView

I was inspired by the example "Bring your own route" SDK version 2

However, in navigation turn-by.turn, after the LocationProvider override with the driver coordinates on the customer app it always returns me to the customer's position and not the driver's, instead I would like him to first navigate the driver and then the customer once the pickup is done

How can I do?
Below are some functions used

func calculateAllDirections() {
    
    let count = routeAllLocations.count
    
    let destination = CLLocationCoordinate2D(latitude: routeAllLocations[count-1].latitude, longitude: routeAllLocations[count-1].longitude)

    // Define bounding box
    let bounds = CoordinateBounds(
        southwest: CLLocationCoordinate2D(latitude: routeAllLocations[0].latitude, longitude: routeAllLocations[0].longitude),
        northeast: destination)

    // Center the camera on the bounds
    let camera = navigationMapView.mapView.mapboxMap.camera(for: bounds, padding: UIEdgeInsets(top: 50, left: 50, bottom: 50, right: 50), bearing: 0, pitch: 0)
    navigationMapView.mapView.mapboxMap.setCamera(to: camera)
    
    flag_driver = true
    
    routingProvider.calculateRoutes(options: routeAllOptions) { [weak self] result in
        switch result {
        case .failure(let error):
            print(error.localizedDescription)
        case .success(let indexedRouteResponse):
            guard let strongSelf = self else {
                return
            }
            
            let currentRoute = indexedRouteResponse.currentRoute
            
            strongSelf.indexedRouteResponse = indexedRouteResponse
            
            strongSelf.navigationMapView.show(indexedRouteResponse, remove_routes: false)
            strongSelf.navigationMapView.showWaypoints(on: currentRoute!)
            if let mainRoute = indexedRouteResponse.currentRoute {
                strongSelf.mapRouteAnnotationManager?.showRouteAnnotation(
                    mainRoute: mainRoute,
                    alternatives: indexedRouteResponse.parseAlternativeRoutes(),
                    false
                )
            }
            
            DispatchQueue.main.asyncAfter(deadline: .now() + 1) {  
                   strongSelf.startEmbeddedNavigation()
            }
        }
    }
    
    timerUpdateDriver = Timer.scheduledTimer(withTimeInterval: TimeInterval(Constants().TIME_UPDATE_DRIVER_SECONDS), repeats: true) { [self] timer in
        
        print("old routeAllLocations[0]", routeAllLocations[0])
        
        getDriverLocation() { [self] myloc in
            print("old routeAllLocations lastDriverLocation", lastDriverLocation?.coordinate as Any)
            print("new routeAllLocations myloc", myloc?.coordinate as Any)
            
            if lastDriverLocation?.coordinate != myloc?.coordinate {
                lastDriverLocation = myloc

                print("new routeAllLocations[0]", routeAllLocations[0])

                updateMappa(location: lastDriverLocation!)
            }
        }
    }
}

func startEmbeddedNavigation() {
// For demonstration purposes, simulate locations if the Simulate Navigation option is on.
print("indexedRouteResponse", indexedRouteResponse as Any)

    //guard let indexedRouteResponse else { return }

    let navigationService = MapboxNavigationService(indexedRouteResponse: indexedRouteResponse!, customRoutingProvider: NavigationSettings.shared.directions, credentials: NavigationSettings.shared.directions.credentials, simulating: simulationIsEnabled ? .never : .never) //.onPoorGPS
   
    let navigationOptions = NavigationOptions(navigationService: navigationService)
    navigationViewController = NavigationViewController(for: indexedRouteResponse!, navigationOptions: navigationOptions)
    
navigationViewController.navigationMapView?.mapView.location.locationProvider.stopUpdatingLocation()

    // Render part of the route that has been traversed with full transparency, to give the illusion of a disappearing route.
    navigationViewController.routeLineTracksTraversal = true
    
    navigationViewController.delegate = self
    
    customLocationProvider = SimulatedLocationProvider(
        currentLocation: CLLocation(latitude: currentDriverLocation.lat, longitude: currentDriverLocation.lng))

    navigationViewController.navigationMapView?.mapView.location.overrideLocationProvider(with: customLocationProvider!)

    navigationViewController.navigationMapView?.mapView.location.locationProvider.setDelegate(self)
    
    var puckConfiguration = Puck2DConfiguration.makeDefault()
    puckConfiguration.pulsing = .default
    navigationViewController.navigationMapView?.mapView.location.options.puckType = .puck2D(puckConfiguration)
    
    navigationViewController.navigationMapView?.mapView.location.options.puckBearing = .course

    navigationViewController.navigationMapView?.mapView.mapboxMap.onNext(event: .mapLoaded) { [self] _ in
        //self.locationUpdate(newLocation: navigationMapView.mapView.location.latestLocation!)
        print("latestLocation", latestLocation?.coordinate as Any)
        print("navigationMapView.mapView.location.latestLocation!", navigationViewController.navigationMapView?.mapView.location.latestLocation!.coordinate as Any)
        self.locationUpdate(newLocation: Location(with: CLLocation(latitude: currentDriverLocation!.coordinate.latitude, longitude: currentDriverLocation!.coordinate.longitude)))
    }

    print("currentDriverLocation", currentDriverLocation.coordinate as Any)

    // Modify default `NavigationViewportDataSource` and `NavigationCameraStateTransition` to change
    // `NavigationCamera` behavior during free drive and when locations are provided by Maps SDK directly.
    let navigationViewportDataSource = CustomViewportDataSource(navigationMapView.mapView)
    navigationViewportDataSource.followingMobileCamera.zoom = 15.0
    navigationMapView.navigationCamera.viewportDataSource = navigationViewportDataSource
    
    navigationMapView.navigationCamera.cameraStateTransition = CustomCameraStateTransition(navigationMapView.mapView)
    
    // Make sure to set `transitioningDelegate` to be a current instance of `ViewController`.
    navigationViewController.transitioningDelegate = self
    
    // Modify default `NavigationViewportDataSource` and `NavigationCameraStateTransition` to change
    // `NavigationCamera` behavior during active guidance.
    if let mapView = navigationViewController.navigationMapView?.mapView {
        let customViewportDataSource = CustomViewportDataSource(mapView)
        navigationViewController.navigationMapView?.navigationCamera.viewportDataSource = customViewportDataSource
        
        let customCameraStateTransition = CustomCameraStateTransition(mapView)
        navigationViewController.navigationMapView?.navigationCamera.cameraStateTransition = customCameraStateTransition
    }
    
    addChild(navigationViewController)
    
    container.addSubview(navigationViewController.view)
    navigationViewController.view.translatesAutoresizingMaskIntoConstraints = false
    NSLayoutConstraint.activate([
        navigationViewController.view.leadingAnchor.constraint(equalTo: container.leadingAnchor, constant: 0),
        navigationViewController.view.trailingAnchor.constraint(equalTo: container.trailingAnchor, constant: 0),
        navigationViewController.view.topAnchor.constraint(equalTo: container.topAnchor, constant: 0),
        navigationViewController.view.bottomAnchor.constraint(equalTo: container.bottomAnchor, constant: 0)
    ])
    self.didMove(toParent: self)
    
    if let view = navigationViewController.navigationMapView {
        activeGuidanceRouteAnnotationManager = DriverRouteAnnotationManager(navigationMapView: view)
    }
}

extension DriverToCustomerMapbox: NavigationViewControllerDelegate {

func navigationViewController(_ navigationViewController: NavigationViewController, shouldRerouteFrom location: CLLocation) -> Bool {
    print("location shouldRerouteFrom", location.coordinate)
    return false
}

func updateMappa(location: LocationDex) {

    routeAllLocations[0] = location.coordinate
    
    navigationViewController.navigationMapView?.mapView.mapboxMap.setCamera(to: CameraOptions(center: location.coordinate, zoom: 11.0))

    // Here, we are simulating a custom server.
    let routeOptions = NavigationRouteOptions(waypoints: [Waypoint(location: CLLocation(latitude: location.lat, longitude: location.lng)), self.routeAllOptions.waypoints.last!])
    //let routeOptions = NavigationRouteOptions(coordinates: routeAllLocations, self.routeAllOptions.waypoints.last!)
    
    Directions.shared.calculate(routeOptions) { [weak self] (_, result) in
        switch result {
        case .failure(let error):
            print(error.localizedDescription)
        case .success(let response):
            guard let routeShape =
                    response.routes?.first?.shape else {
                return
            }
    
            //
            // ❗️IMPORTANT❗️
            // Use `Directions.calculateRoutes(matching:completionHandler:)` for navigating on a map matching response.
            //
            
            Task {
                 ...
                 let matchOptions = NavigationMatchOptions(coordinates: routeShape.coordinates)
                
                Directions.shared.calculateRoutes(matching: matchOptions, completionHandler: { [weak self] (_, result) in
                    switch result {
                    case .failure(let error):
                        print(error.localizedDescription)
                    case .success(let response):
                        guard !(response.routes?.isEmpty ?? true) else {
                            return
                        }
                        
                        // Convert matchOptions to `RouteOptions`
                        let routeOptions = RouteOptions(matchOptions: matchOptionsSemplificato)
                        
                        let myloc = location

                        // Set the route
                        self?.navigationViewController?.navigationService.router.updateRoute(with: .init(routeResponse: response, routeIndex: 0), routeOptions: routeOptions, completion: { success in
                            if success {
                                guard let strongSelf = self else {
                                    return
                                }
                                
                                strongSelf.customLocationProvider?.currentLocation = CLLocation(latitude: myloc.lat, longitude: myloc.lng)
                                strongSelf.customLocationProvider?.startUpdatingLocation()
                                
                                strongSelf.navigationViewController.navigationMapView?.moveUserLocation(to: CLLocation(latitude: myloc.lat, longitude: myloc.lng))

strongSelf.navigationViewController.navigationMapView?.mapView.mapboxMap.setCamera(to: CameraOptions(center: CLLocationCoordinate2D(latitude: myloc.lat, longitude: myloc.lng), zoom: 15.0))
}
})
}
})
}
}
}
}
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions