I am developing an application which computes the distance traveled by the user. I am using CLLocationManager class to do so, but I am getting the cached data initially and also the distance variable is increasing at a sudden rate. Please help me out... I have 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 is displaying the following data.......
accuracy 0 oldd (null) new <+28.62114850, +77.37001021> +/- 80.00m (speed -1.00 mps / 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.00m (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.00m (speed -1.00 mps / course -1.00) @ 2010-06-22 19:23:02 +0530 distance 994.432508
It is normal to initially get a cached location from before. You can ignore older cached data by looking at the timestamp of the CLLocation.
You are printing the accuracy incorrectly, use %f not %d, type is double not int.
Location can change quickly when GPS first starts because you have a low accuracy location from cell triangulation, then as you get GPS acquisition you get a higher accuracy location. Those can be far apart (1000m) and it appears that you moved far in a few seconds but only the accuracy has changed.
Don't use two locations that have very different accuracy for computing distance traveled.
EDIT Added code sample, how to ignore old location data. You decide how old 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
...
}
You are already ensuring that your location updates are less than five seconds old. That is what this line of code does:
if (locationAge > 5.0) return;
As stated by progrmr, the key issue here is almost certainly that you're relying on initial estimates of location that are of low accuracy and so the location is appearing to move rapidly as it gets a better fix on your location. What you need to do is first ensure that oldLocation only gets set when you have an accurate initial location fix, and then only compare newLocations to that oldLocation if they also are of acceptable resolution.
For instance, you could 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 with the code above you do not require the method computeDistanceFrom:tO:, and also the property self.newLocat is not actually required, at least in this section of code.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With