2010-06-22 16 views
4

Je développe une application qui calcule la distance parcourue par l'utilisateur. J'utilise la classe CLLocationManager pour le faire, mais j'obtiens les données mises en cache initialement et aussi la variable de distance augmente à un rythme soudain. S'il vous plaît aidez-moi ... J'ai utilisé le code suivant ....Corelocation distances incorrectes

Note: la distance est une variable statique. ici

- (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); 

} 

La console affiche les données suivantes .......

précision 0 oldd (null) < nouvelle 28,62114850, 77,37001021> +/- 80.00m (vitesse -1.00 mps/cours -1,00) @ 2010-06-22 19:21:59 0530 Distance 0,000000

précision 0 oldd < 28,62114850, +77.37001021> +/- 80.00m (vitesse -1.00 mps/cours -1.00) @ 2010-06-22 19:21:59 +0530 nouveau < 28,61670485, 77,37068155> +/- 80.00m (vitesse -1.00 mps/cours -1,00) @ 2010-06-22 19:22:00 0530 la distance 498,211345

précision 0 oldd < 28,61670485, +77.37068155> +/- 80.00m (vitesse -1.00 mps/cap -1.00) @ 2010-06-22 19:22:00 +0530 nouveau < +28.62112748, +77.36998540> +/- 80.00m (vitesse -1.00 mps/course -1.00) @ 2010-06-22 19:23:02 +0530 distance 994.432508

Répondre

7

Il est normal d'obtenir au départ un emplacement en antémémoire. Vous pouvez ignorer les anciennes données mises en cache en regardant le timestamp du CLLocation.

Vous imprimez incorrectement la précision, utilisez% f et non% d, le type est double non int.

L'emplacement peut changer rapidement lorsque le GPS démarre pour la première fois car vous disposez d'un emplacement de faible précision à partir de la triangulation des cellules. Lorsque vous obtenez l'acquisition GPS, vous obtenez un emplacement plus précis. Ceux-ci peuvent être éloignés (1000m) et il semble que vous ayez déménagé loin en quelques secondes mais seule la précision a changé. N'utilisez pas deux emplacements qui ont une précision très différente pour la distance de calcul parcourue.

EDIT Exemple de code ajouté, comment ignorer les anciennes données de localisation. Vous décidez de l'âge à ignorer, j'ai utilisé 60 secondes ici:

- (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 
    ... 
} 
+0

merci progrmr mais pouvez-vous me dire exactement comment supprimer les données mises en cache en utilisant les horodatages ........ et si l'approche ci-dessus pour calculer la distance est fausse alors comment dois-je procéder ...... est-il tout autre moyen de calculer la distance ..... coz j'ai vu de nombreuses applications dans l'App Store qui font le même travail comme le calcul de la distance, la vitesse etc.pls me donner vos suggestions précieuses. – Siddharth

+1

J'ai ajouté un exemple de code pour montrer comment supprimer les anciennes données en cache, mais vous le faites déjà dans votre code. – progrmr

2

Vous vous assurez déjà que les mises à jour de votre emplacement ont moins de cinq secondes. C'est ce que cette ligne de code fait:

if (locationAge > 5.0) return; 

Comme indiqué par progrmr, la question clé ici est presque certainement que vous comptez sur les estimations initiales de localisation qui sont de faible précision et donc l'emplacement est semblant se déplacer rapidement car il obtient une meilleure solution sur votre emplacement. Ce que vous devez faire, c'est d'abord vous assurer que oldLocation n'est défini que lorsque vous avez un correctif d'emplacement initial précis, puis comparez newLocations à oldLocation uniquement s'ils ont également une résolution acceptable.

Par exemple, vous pourriez avoir quelque chose comme ceci:

- (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 avec le code ci-dessus vous ne souhaitez pas la méthode computeDistanceFrom: :, et aussi tO la self.newLocat de propriété n'est pas réellement nécessaire, à moins dans cette section de code.