mapbox / mapbox/mapbox-navigation-ios-examples
from "Bring your own route" example with firebase server coordinates
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
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- 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