My House
My House

Reputation: 759

Calculating total distance traveled not accurate

Using the below code the distance traveled is always lower than the actual distance traveled by 20-40% when traveling at least a couple of miles. This is traveling in a large city with strong cell and GPS signal the entire trip so I know that is not the issue. I verified the actual distance using Google Maps and MapMyHike. Any Ideas? Relevant parts of the code pasted below:

let metersToMiles: Double = 0.000621371
var startLocation: CLLocation!
var lastLocation: CLLocation!
var distanceTraveled: Double = 0


override func viewDidLoad() {
    super.viewDidLoad()

    self.locationManager.requestAlwaysAuthorization() // Location permission for background
    self.locationManager.requestWhenInUseAuthorization() // Location permission for foreground

    if CLLocationManager.locationServicesEnabled() {
        locationManager.delegate = self
        locationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation
        locationManager.distanceFilter = kCLDistanceFilterNone
        locationManager.activityType = CLActivityType.Fitness
        locationManager.pausesLocationUpdatesAutomatically = false
    }
}

func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
    if startLocation == nil {
        print("startLocation is null")
        startLocation = locations.first
    } else {
        let lastLocation = locations.last
        let distance = startLocation.distanceFromLocation(lastLocation!)
        startLocation = lastLocation
        distanceTraveled += distance
    }
    updateDistanceTraveledText()
}

func updateDistanceTraveledText() {
    let distanceTraveledString = "\(String(format:"%.1f", distanceTraveled * metersToMiles))"
    distanceTraveledText.text = distanceTraveledString
}

I also tried all types of desiredAccuracy like kCLLocationAccuracyBest and kCLLocationAccuracyNearestTenMeters, etc. and not setting activityType at all, and also setting it to AutomotiveNavigation/Fitness all to no avail.

Upvotes: 0

Views: 308

Answers (1)

Paul Cantrell
Paul Cantrell

Reputation: 9324

It’s possible you’re getting a string of location updates as it zeros in on your precise location. Those updates indicate a change in precision, not actual motion — but it looks like your code is going to register them as motion anyway. This can happen no matter how high you set desiredAccuracy because it’s a maximum accuracy, not a minimum.

You could debug this by logging the horizontalAccuracy and verticalAccuracy properties of the CLLocations as they come in.

If the problem is indeed that you’re getting reports with varying accuracy, some possible solutions are:

  • Use the distace filter on CLLocationManager to ignore small travel.
  • Discard any CLLocation that isn’t accurate enough, according to some threshold you set.
  • If the latest location falls within the accuracy circle of the previous one (and thus may not represent actual motion), replace the last location instead of adding the new one.
  • Use some sort of sophisticated Bayesian inference to find the path of maximum likelihood through all reported points.

I’d do #1 or #2 if this is casual, #3 if you really care, and #4 only if maximum accuracy is essential … and you know more about the math than I do.

Upvotes: 1

Related Questions