mapbox / mapbox/mapbox-navigation-ios-examples

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

Open
#237 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Swift
Stars
63
Forks
32
Avg merge
5m
Merged PRs (30d)
1

Description

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

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by tracing calculateAllDirections(), startEmbeddedNavigation(), and updateMappa(), especially the LocationProvider override and router.updateRoute calls. Reproduce the flow with the Firebase driver coordinates and verify that the customer app follows the driver to pickup before switching to customer navigation.

Written by the indexing model from the issue text.

Assessment

Tech stack
firebase, swift
Domain
mobile
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.