I've discovered an issue with how an iPhone give location information to apps, an issue that can have a dramatic impact on the accuracy of location data. The impact is either really good or really bad, depending on what the app (and you) want to use the location information for.
The issue is that the iPhone can get into a mode where instead of providing apps with your location directly from its normal location-tracking methods (GPS/GLONASS, WiFi and cell-tower signal strength), it “snaps” the location to the center of the nearest road it knows about. I call this “snap to road”; internally at Apple, I hear it's called “map matching”.
I can imagine that this feature is really useful for apps providing turn-by-turn driving directions.
It's not so wonderful for how I use location-aware apps: for tracking my cycling activity, and for geoencoding photos, both of which are harmed by this road-snap effect.
Unfortunately, an app developer (and hence an app user) can not control which kind of data the app gets. I've submitted the bug to Apple (“CoreLocation: location snap-to-road can't be controlled by the developer”).
If you are a user of apps, or a developer, you can do some things to mitigate the issue, so that's what this blog post is about.
First, here's an illustration of the effect in action: the two colors of the track in the image below are parts of the same continuous track. The part colored red is the first half, an upside-down “L” loop, done without the road-snap effect. You can see that it more or less tracks the outside edge of the road for the whole loop.
colored into two halves, the red without road snapping, the blue with
Then, I did something on the phone that turned on the road-snapping effect, and drove the exact same loop again. This part of the track is colored blue. The blue line perfectly matches the centers of the roads, and though you can't tell from looking, it's actually the same loop with both “out” and “back” segments.... they just overwrite each other on their perfectly-straight road-center lines.
If I were using this track to geoencode photos, I would certainly want to differentiate photos taken on one side of the road from the other, but this “snap to road” feature destroys the true data, and I lose that ability.
Here's another example, from this cycling trip. Here, the location track reported to the app is shown in blue. I added the red line to indicate where I actually rode the bicycle:
The elevation between a road-side path and the road can be quite different, so besides giving the incorrect history, it can contribute to incorrect ride-climb data.
This road-snapping feature can also create artificial speed and distance numbers, which contributes to inflated distance and speed calculations for fitness apps. In the image above, as the road curves away from my actual path, the distance it's saying I'm covering is longer than the straight-line path I'm actually taking. Longer distance covered in the same amount of time means that both the speed and distance are reported incorrectly.
As a cyclist, the only thing worse than mistakes that shortchange my achievements are mistakes that inflate them.
Then in the middle you can see the track suddenly jig to the left. The road it was snapping my location to has now drifted too far away, so it decides to snap me onto a closer road that I'm also not on. That jump sees me suddenly accelerate to 87 kph for the one second required to make the adjustment, then return to the ~30kph speed I was actually traveling at.
Then there's some weirdness that happens as you near intersections... sometimes the road-snapping stuff can't decide which road you're on, and so it throws you around. You can see it near the top of the screenshot with one data point jutting out to the right. I was on the riverside path, down an embankment from the road, but as my location came close to the intersection above, it snapped me momentarily from one road to another, making it seem that I accelerated to ~130kph (80mph) on my bicycle for two seconds then immediately returned to a more human pace.
Another common manifestation of this problem is seen when stopping at a traffic light, as illustrated here:
Travel is north to south on the image-right side of the road.
Red line is the actual path traveled.
As I traveled from the north, I had to stop at the intersection (on the north-east side of the intersection; this is Japan, where traffic flows on the left) to wait for the light. While standing still, one expects a location drift from a consumer-grade GPS/GLONASS unit, but the snap-to-road “feature” can turn it into spiky ordered disorder.
Actual travel is north to south on the image-right side of the road.
The spike in the top half is manufactured by the road-snap “feature”
There's another wrinkle to the road-snapping issue: it seems to happen only when traveling above a
certain speed threshold,
around 20~30kph (12~19mph)
[Update: as reported in this followup post, it
turns on at 20kph].
This can be inferred in “Stopping at an Intersection” example above. As I traveled at speed from north to south, the location was snapped to the center of the road until I reached the intersection and had to stop. I didn't accelerate quickly enough from the intersection to suffer the road snapping, so that part of the track shows the actual path traveled.
Yet, how does this explain the craziness while stopped at the intersection, or while stopped in front of a building in the example immediately above? If you're not moving, you should be below the speed threshold. My guess is that the non-precise variability found in consumer-grade GPS/GLONASS units (as illustrated here, and especially when the unit doesn't have a good satellite fix, as illustrated here) creates data points that meander around your actual location, and if one meanders far enough away, it can appear to an unsophisticated algorithm as if the actually-stationary phone has suddenly moved far enough away (which means fast-enough away) to invoke the road-snapping thing, and in its desperate attempt to match that point to the center of some road, we see these spikes that make the “non-precise variability” so much worse.
A cyclist would suffer this problem the most, as it's easy to exceed the threshold. Runners likely won't suffer it directly so much, except for the “non-precise variability” that can strike when paused.
So, what causes this problem to be turned on in the first place?
When an app tells the iPhone that it wants location information, it has four choices to indicate what type of app it is. Apple's developer documentation on this is woefully lacking details on the ramifications of the choice, but one can read something into the four names:
It turns out that this “road snap” feature is enabled except when using “Other Navigation”, which the docs say is intended for non-automotive navigation, e.g. planes, trains, boats, snowmobiles, etc.
On the surface this makes no sense, because one would think that road snapping would apply to only “Automotive Navigation”, and certainly explicitly not apply to “Fitness” (predominately walking, running, and cycling) or “Other”, where one can't make any assumptions on the use of location information.
When one digs in, it makes even less sense. It turns out that if any app requests something other than “Other Navigation”, all apps get the road-snapped data.
This means that if you don't want this “road snap” feature, you must run only apps that use “Other Navigation”.
Unfortunately, it seems that fitness tracking apps unsurprisingly tend to use the “Fitness” activity type when registering for location information, so they suffer this problem. I've tested Strava, Wahoo Fitness, and Runmeter (aka Cyclemeter and Walkmeter), and all invoke road snapping. To be fair, some users may consider this a feature, or consider it a feature at times and less desirable other times. It'd be nice if an app gave the user explicit control over this, but none of them do.
The only app I've found that does not invoke road snapping is Galileo Offline Maps, an app I've been recommending for years for its ability to use high-quality maps while completely offline. In testing this issue over the last month, the developer has made special builds of his app available to me, so I'd like to think him for help in pinning this issue down.
I'm a geek about my data (as made obvious here) so I used to keep tracks of my cycling with multiple apps. I felt I got the best location track from Galileo Offline Maps, but Runmeter included temperature data and Wahoo Fitness included bicycle speed and cadence. And on top of that I used GeoTagr as a backup because other apps tended to spontaneously stop recording my track.
But now I can't use any of them because, as mentioned above, the use of any app with road snapping infects even non-snapped apps like Galileo Offline Maps. I can't even open up Google Maps, because it too (this time unsurprisingly), gets the road snapping. So to keep a pure tracklog, I can run only Galileo and no others.
The bug has been submitted to Apple. The bug number is #23737784, implying that there are 23.7 million other bugs submitted before me, so I don't hold much hope for a response, but it'd be very nice if
- Apple documented for developers the exact ramifications of the various CoreLocation activity types.
- Apple made the road-snapping feature something an app could explicitly turn on and off.
- Apple removed the ability for random other apps to influence the data you get.
I won't hold my breath, but until it's resolved I'll stick with Galileo Offline Maps. It's a bummer, but I've removed the Wahoo Fitness cadence/speed unit from my bike because I haven't found an app that can read its data without destroying my cycling track.
UPDATE: I've added some details in "More Details on the Insidious iOS Snap-to-Road “Feature”".