Search code examples
swiftcore-location

swift altitude indoor not accurate


I am attempting to gather the altitude of my user as they go up and down the building they are in. I used guard let lastLocation = locations.last else {return} let altitude = lastLocation.altitude to gather the altitude with CoreLocation but the altitude seems to be very inaccurate. Anyone know of ways to gather this information more accurately?


Solution

  • GPS is not very accurate within buildings, particularly steel-frame construction buildings (which is very common in commercial construction). Even when its accuracy is good, "good" GPS accuracy for a cell phone is expected to be about 5m, or more than the common distance between floors. iPhones use various other techniques, like WiFi positioning, to improve on that. My own experience in development is that you can often get on the order of 3m accuracy.

    But those are horizontal. Altitude tends to less accurate than that because the angle changes are tiny. If you told me your measurements were 10m off vertically (~3 stories), that would surprise me at all. It sounds like you want deltas (change in altitude), but even that is very difficult in a building.

    WiFi positioning is a crucial part of this story. Google and Apple (and others) do a ton of correlation between GPS information and WiFi information. As users use their mapping products, they learn about numerous WiFi access points. They correlate information from the access point (such as RSSI signal strength) with GPS information from millions of phones and use that to work out where the access points are, and use that to create better location information, particularly inside. (Remember, the GPS satellites are about 20,000 km away, and you've surrounded yourself with a giant metal box. They're doing their best.) Making sure that there are stable WiFi access points throughout the location (and on a variety of floors) should over time help the system learn your building. That unfortunately is not a very reliable solution.

    The short answer of this very long answer is that the way you improve location information is to take a lot of readings and average them, compensating with inertial (acceleration) information to deal with movement. The OS already does this, but you can keep averaging more data points (both location and velocity) to try to gain greater accuracy over time.

    And of course use as high a location accuracy as you can get away with. kCLLocationAccuracyBest is generally the best you can get without plugging in (it of course is a power hog, so you can't run that all the time). If you have external power, you can use kCLLocationAccuracyBestForNavigation.

    Otherwise, you're just going to have to average a lot of measurements to decide when you believe you've really changed floors.