Map matching: very difficult to get a route with coordinates
Hello,
I have a backend where I can trace a route with OSRM. I receive in my iOS app a list of coordinates, from the first to the last location, with all intermediates locations between them.
I calculate the route like this:
func calculateRoute(locations: [CLLocationCoordinate2D],
completion: @escaping (Route?, Error?) -> ()) {
let matchOptions = NavigationMatchOptions(coordinates: locations, profileIdentifier: .automobile)
matchOptions.includesSteps = true
matchOptions.waypointIndices = IndexSet([0, locations.count - 1])
matchOptions.distanceMeasurementSystem = .metric
Directions.shared.calculateRoutes(matching: matchOptions) { (waypoint: [Waypoint]?, routes: [Route]?, error: Error?) in
completion(routes?.first, error)
}
}
But nearly every time, I don't receive any route matching the coordinates:
routes = nil
Error Domain=MBDirectionsErrorDomain Code=-1 "No matching found" UserInfo={NSLocalizedFailureReason=No matching found}
I succeeded one time to receive a valid route (every location perfectly placed on a main street or a road). And when everything seems ok, it often fails.
Is there something i'm doing wrong? Any chances to increase a margin or something else to match a location if it's not perfectly located?
When I calculate routes with waypoints, all works fine but since all waypoints are considered as a place to visit, It's not a workaround for me.
Here is a list of coordinates with an error for the route calculation:
1. 48.846413943401 2.3445725440979
2. 48.86271029257 2.313244342804
3. 48.8592281 2.2671622
4. 48.859844609102 2.1876311302185
5. 48.8733692 2.1689624
6. 48.875098 2.1686524
7. 48.816726632755 2.0635628700256
8. 48.688778988723 2.0142531394958
9. 48.6463299 1.8187715
10. 48.4048011 2.6885733
I'm looking for a workaround and maybe the issue is that the option radiuses is missing in the request sent by Directions.shared.calculateRoutes.
This option is available in the Android SDK. https://www.mapbox.com/android-docs/api/mapbox-java/libjava-services/3.0.0/com/mapbox/api/matching/v5/MapboxMapMatching.Builder.html
Is it a omission?
Update:
I have created a variant of NavigationMatchOptions to set the maximum (49 meters) for each location's coordinateAccuracy, used to set radiuses in the request (the existing NavigationMatchOptions set coordinateAccuracy to -1 to ignore radiuses in the request, I don't know why):
open class BLNavigationMatchOptions: MatchOptions {
/**
Initializes a navigation route options object for routes between the given waypoints and an optional profile identifier optimized for navigation.
- SeeAlso:
[MatchOptions](https://www.mapbox.com/mapbox-navigation-ios/directions/0.19.0/Classes/MatchOptions.html)
*/
@objc public required init(waypoints: [Waypoint], profileIdentifier: MBDirectionsProfileIdentifier? = .automobileAvoidingTraffic) {
super.init(waypoints: waypoints.map {
$0.coordinateAccuracy = 49
return $0
}, profileIdentifier: profileIdentifier)
includesSteps = true
routeShapeResolution = .full
attributeOptions = [.congestionLevel, .expectedTravelTime]
includesSpokenInstructions = true
locale = Locale.nationalizedCurrent
distanceMeasurementSystem = Locale.current.usesMetricSystem ? .metric : .imperial
includesVisualInstructions = true
}
}
And I use it like this:
var waypoints: [Waypoint] = []
for loc in locations {
let wp = Waypoint(coordinate: loc)
waypoints.append(wp)
}
let matchOptions = BLNavigationMatchOptions(waypoints: waypoints, profileIdentifier: .automobile)
matchOptions.includesSteps = true
matchOptions.waypointIndices = IndexSet([0, 1, locations.count - 1])
matchOptions.distanceMeasurementSystem = .metric
Directions.shared.calculateRoutes(matching: matchOptions) { (waypoint: [Waypoint]?, routes: [Route]?, error: Error?) in
completion(routes?.first, error)
}
But it still doesn't work!
The response returns route=nil and this error:
Error Domain=MBDirectionsErrorDomain Code=-1 "No matching found" UserInfo={NSLocalizedFailureReason=No matching found}
Here are my coordinates:
0. 48.56918 2.32506
1. 48.404897375554 2.6886409521103
2. 48.402379742784 2.6968270540237
Why is it impossible to get a route matching?
the existing
NavigationMatchOptionssetcoordinateAccuracyto -1 to ignore radiuses in the request, I don't know why
I think the expectation is that NavigationMatchOptions’ coordinates would come directly from Core Location, which sets CLLocation.coordinateAccuracy automatically but somewhat unreliably. But I don’t think we meant to clear out an accuracy that’s set manually. −1 is normally a placeholder value indicating that the option is unset. (For example, this library needs to bridge to Objective-C, which means we can’t make any CLLocationDistance-typed property optional.)
So the coordinateAccuracy should be unset further up the call chain, in NavigationMatchOptions(locations:profileIdentifier:) or Waypoint(location:), or preferably in whatever calls NavigationMatchOptions(locations:profileIdentifier:).
So the
coordinateAccuracyshould be unset further up the call chain, inNavigationMatchOptions(locations:profileIdentifier:)orWaypoint(location:), or preferably in whatever callsNavigationMatchOptions(locations:profileIdentifier:).
mapbox/mapbox-navigation-ios#1907
There’s a simpler workaround in https://github.com/mapbox/mapbox-navigation-ios/issues/1907#issuecomment-448808887, by the way.
@1ec5 I answered you on this issue. The workaround is here: https://github.com/mapbox/mapbox-navigation-ios/issues/1907#issuecomment-460666967