Incorrect distances in Corelocation

I am developing an application that calculates the distance traveled by a user. To do this, I use the CLLocationManager class, but first I get cached data, and also the distance variable increases at a sudden speed. Please help me ... I used the following code ....

Note: distance is a static var. here

- (void)viewDidLoad { [super viewDidLoad]; //bestEffortAtLocation = nil; oldLocat = [[CLLocation alloc]init]; newLocat = [[CLLocation alloc]init]; locationManager =[[CLLocationManager alloc]init]; locationManager.delegate = self; locationManager.distanceFilter = kCLDistanceFilterNone; locationManager.desiredAccuracy = kCLLocationAccuracyBest; [locationManager startUpdatingLocation]; } - (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation{ // test that the horizontal accuracy does not indicate an invalid measurement if (newLocation.horizontalAccuracy < 0) return; NSLog(@"accuracy %d",newLocation.horizontalAccuracy); // test the age of the location measurement to determine if the measurement is cached // in most cases you will not want to rely on cached measurements NSTimeInterval locationAge = -[newLocation.timestamp timeIntervalSinceNow]; //NSLog(@"time %d",locationAge); if (locationAge > 5.0) return; self.oldLocat = oldLocation; self.newLocat = newLocation; double latDegrees = newLocation.coordinate.latitude; NSString *lat = [NSString stringWithFormat:@"%1.5fΒ°",latDegrees]; latLabel.text = lat; double longDegrees = newLocation.coordinate.longitude; NSString *longt = [NSString stringWithFormat:@"%1.5fΒ°",longDegrees]; longLabel.text = longt; [self computeDistanceFrom:oldLocat tO:newLocat]; } -(void)computeDistanceFrom:(CLLocation *)oldL tO:(CLLocation *)newL { NSLog(@"oldd %@",oldL); NSLog(@"new %@",newL); distance = distance + [oldL getDistanceFrom:newL]; NSLog(@"distance %f",distance); } 

The console displays the following data:

accuracy 0 oldd (null) new <+28.62114850, +77.37001021> +/- 80.00m (speed -1.00 m / s / course -1.00) @ 2010-06-22 19:21:59 +0530 distance 0.000000

accuracy 0 oldd <+28.62114850, +77.37001021> +/- 80.00m (speed -1.00 mps / course -1.00) @ 2010-06-22 19:21:59 +0530 new <+28.61670485, +77.37068155> +/- 80.00 m (speed -1.00 mps / course -1.00) @ 2010-06-22 19:22:00 +0530 distance 498.211345

accuracy 0 oldd <+28.61670485, +77.37068155> +/- 80.00m (speed -1.00 mps / course -1.00) @ 2010-06-22 19:22:00 +0530 new <+28.62112748, +77.36998540> +/- 80.00 m (speed -1.00 mps / course -1.00) @ 2010-06-22 19:23:02 +0530 Distance 994.432508

+4
source share
2 answers

As a rule, you first need to get a cached location. You can ignore old cached data by viewing the timestamp CLLocation .

You are typing precision incorrectly, use% f not% d, type double is not int.

The location can quickly change when the GPS starts first, because you have a low accuracy location from the triangulation of the cell, and then when you get the GPS reception, you get a more accurate location. They can be far apart (1000 m), and it seems that you have advanced far in a few seconds, but only the accuracy has changed.

Do not use two locations with very different accuracy to calculate the distance traveled.

EDIT Added code sample on how to ignore old location data. You decide how many years to ignore, I used 60 seconds here:

 - (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation { NSTimeInterval ageInSeconds = -[newLocation.timestamp timeIntervalSinceNow]; if (ageInSeconds > 60.0) return; // data is too long ago, don't use it // process newLocation ... } 
+7
source

You already ensure that your location updates are less than five seconds. Here is what this line of code does:

 if (locationAge > 5.0) return; 

As progrmr pointed out, the key problem here almost certainly is that you rely on initial location estimates that have low accuracy, and therefore the location seems to move quickly, since it better corrects your location. You need to first make sure that oldLocation will only be set when you have the exact fix for the original location, and then compare newLocations with this oldLocation if they also have acceptable resolution.

For example, you might have something like this:

 - (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation{ // Ignore location updates that are less than 10m accuracy, or where the horizontalAccuracy < 0 // which indicates an invalid measurement. NSLog(@"New location accuracy %.0fm", newLocation.horizontalAccuracy); if ((newLocation.horizontalAccuracy < 0) || (newLocation.horizontalAccuracy > 10)) return; // Ignore location updates that are more than five seconds old, to avoid responding to // cached measurements. NSTimeInterval locationAge = -[newLocation.timestamp timeIntervalSinceNow]; if (locationAge > 5) return; if (self.oldLocat == NULL) { // For the first acceptable measurement, simply set oldLocat and exit. self.oldLocat = newLocation; return; } // A second location has been identified. Calculate distance travelled. // Do not set self.oldLocat from the oldLocation provided in this update, as we wish to // use the last place we calculated distance from, not merely the last place that was // provided in a location update. CLLocationDistance distance = [newLocation distanceFromLocation:self.oldLocat]; NSLog(@"Distance: %.0fm", distance); // This new location is now our old location. self.oldLocat = newLocation; } 

Note that with the code above, you do not need the computeDistanceFrom: tO: method, and the self.newLocat property is not actually required, at least in this section of the code.

+2
source

Source: https://habr.com/ru/post/1313521/


All Articles