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))
}
})
}
})
}
}
}
}
}

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions