Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CoreLocation Accuracy Woes

I have a program with a location manager set up like this:

self.locationManager = [[CLLocationManager alloc] init];
[locationManager startUpdatingLocation];
locationManager.delegate = self;
locationManager.distanceFilter = kCLDistanceFilterNone; 
locationManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters;

I need the accuracy to within ten meters, however, it takes a few calls of the didUpdateToLocation delegate method to find the location at that accuracy. How would I go about delaying the call of this method or just indicate when the desired accuracy is achieved in order to proceed with the program.

Right now it tries proceeds with the first location returned. Even the second location update is not as accurate as expected.

Thanks in advance!

like image 564
Ben Harris Avatar asked Jul 20 '09 03:07

Ben Harris


2 Answers

Since each delegate call includes an accuracy figure, simply return from the method until your desired accuracy is reached (warning: that may never happen).

You can't simply jump to a ten meter result - there's a reason why it's called "desired" accuracy and not mandatory accuracy. You have to give it time to calculate more exact positions.

like image 147
Kendall Helmstetter Gelner Avatar answered Sep 19 '22 01:09

Kendall Helmstetter Gelner


I've recently tackled this problem and discovered, by cleverly reading the documentation at long last, that CoreLocation runs in a separate thread, so you can start it up and then retrieve events as it updates. It's in the documentation under the rubric "Getting the User's Location". So here's where you start updating:

- (void)startStandardUpdates
{
    if (nil == locationManager)
        locationManager = [[CLLocationManager alloc] init];
    locationManager.delegate = self;
    locationManager.desiredAccuracy = kCLLocationAccuracyBest;
    locationManager.distanceFilter = none;
    [locationManager startUpdatingLocation];
}

If you make the delegate "self", it will send events to the same class where the start method is defined, so then you just have to add the following to retrieve the events:

- (void)locationManager:(CLLocationManager *)manager
    didUpdateToLocation:(CLLocation *)newLocation
    fromLocation:(CLLocation *)oldLocation
{
    if (newLocation.horizontalAccuracy < 30.0)
    {
        NSLog(@"latitude %+.6f, longitude %+.6f\n",
                newLocation.coordinate.latitude,
                newLocation.coordinate.longitude);
        [manager stopUpdatingLocation];
    }
}

This way it will keep receiving events and then turn off the GPS receiver to save energy. Of course it needs a time out and some way to store and accept the location with the best horizontal accuracy if it times out, but I haven't figured out how to do that yet.

like image 45
mutatron Avatar answered Sep 18 '22 01:09

mutatron