2010-10-06 4 views
8

Est-ce que quelqu'un a déjà cloué cela? J'ai lu beaucoup d'affichages de forum et je ne peux toujours pas dire si c'est une question réglée ...Algorithme définitif pour déterminer le plus précis renvoyé par iPhone CoreLocation?

Étant donné que didUpdateToLocation() peut renvoyer des informations cachées ou inexactes comment pouvez-vous dire quand vous avez une précision réparer? Lorsque vous définissez la précision souhaitée sur kCLLocationAccuracyNearestTenMeters, HundredMeters, Kilometer, ThreeKilometers, il semble évident que vous pouvez comparer la précision horizontale des points renvoyés avec la précision souhaitée pour décider quand accepter un point. Mais les valeurs de kCLLocationAccuracyBestForNavigation et de kCLLocationAccuracyBest sont respectivement -2 et -1, alors comment savoir quand j'ai la précision désirée?

Je vérifie actuellement l'âge du correctif et rejette toute correction qui est trop "ancienne" dans le temps. Je vérifie ensuite si la précision horizontale est négative et rejette si c'est le cas. Si j'obtiens une précision verticale positive, j'utilise généralement cette correction car la précision horizontale correspondante est également bonne.

Mais ces vérifications ont été utilisées lorsque je recherchais la précision dans les 10-100s de mètres ... Je ne sais pas quoi vérifier si je cours ... AccuracyBestForNavigation ou ... AccuracyBest ?? Suis-je censé niveler le locationManager en permanence et ne jamais s'attendre à le fermer et ne pas filtrer les résultats ??

Quelqu'un de plus sage que moi avec une réponse ??

Merci

Répondre

3

Ce n'est pas vraiment un algorithme définitif, parfait (je doute qu'il y en a une pour cette tâche, en raison des conditions extérieures, je veux dire, vous pouvez obtenir ur emplacement sur le terrain plaine ou dans une tombe), c'est un ad hoc, et ça marche pour moi.

J'ai fait un wrapper pour LocationManager, comme

@protocol LocationManagerWrapperDelegate <NSObject> 

@required 

- (void) locationUpdated: (CLLocation *) locationUpdate; 
- (void) errorOccured: (NSError *) error; 

@end 

@interface LocationManagerWrapper : NSObject <CLLocationManagerDelegate> 
{ 
    CLLocationManager *locationManager; 
    id delegate; 
    CLLocation *mostAccurateLocation; 
    int updatesCounter; 
    BOOL m_acceptableTimePeriodElapsed; 
} 

@property (nonatomic, retain) CLLocationManager *locationManager; 
@property (nonatomic, retain) CLLocation *mostAccurateLocation; 
@property (nonatomic, assign) id <LocationManagerWrapperDelegate> delegate; 

- (void) startUpdatingLocation; 

- (void) locationManager: (CLLocationManager *) manager 
    didUpdateToLocation: (CLLocation *) newLocation 
      fromLocation: (CLLocation *) oldLocation; 

- (void) locationManager: (CLLocationManager *) manager 
    didFailWithError: (NSError *) error; 

+ (LocationManagerWrapper *) sharedInstance; 

@end 

mise en œuvre

#define NUMBER_OF_TRIES 4 
#define ACCEPTABLE_TIME_PERIOD 15.0 

- (void) startUpdatingLocation 
{ 
NSAssert(self.delegate != nil, @"No delegate set to receive location update."); 

updatesCounter = 0; 
self.mostAccurateLocation = nil; 
m_acceptableTimePeriodElapsed = NO; 
[NSTimer scheduledTimerWithTimeInterval:ACCEPTABLE_TIME_PERIOD 
           target:self 
           selector:@selector(acceptableTimePeriodElapsed:) 
           userInfo:nil 
           repeats:NO]; 
[self.locationManager startUpdatingLocation]; 
} 

- (void) acceptableTimePeriodElapsed: (NSTimer *) timer 
{ 
@synchronized(self) 
{ 
    m_acceptableTimePeriodElapsed = YES; 
    // TODO: if period is set by user - check we have mostAccurateLocation at this point 
    [self.delegate locationUpdated:self.mostAccurateLocation]; 
    [self.locationManager stopUpdatingLocation]; 
} 
} 

- (void) locationManager: (CLLocationManager *) manager 
    didUpdateToLocation: (CLLocation *) newLocation 
      fromLocation: (CLLocation *) oldLocation 
{ 
@synchronized(self) 
{ 
    if (m_acceptableTimePeriodElapsed) return; 
    NSLog([NSString stringWithFormat:@"lat: %@, long: %@, acc: %@", 
      [ [NSNumber numberWithDouble:newLocation.coordinate.latitude] stringValue], 
      [ [NSNumber numberWithDouble:newLocation.coordinate.longitude] stringValue], 
      [ [NSNumber numberWithDouble:newLocation.horizontalAccuracy] stringValue] ]); 

    updatesCounter++; 
    // ignore first returned value 
    if (updatesCounter <= 1) return; 
    if (self.mostAccurateLocation == nil || 
     self.mostAccurateLocation.horizontalAccuracy > newLocation.horizontalAccuracy) 
    { 
     self.mostAccurateLocation = newLocation; 
    } 
    if (updatesCounter >= NUMBER_OF_TRIES) 
    { 
     [self.delegate locationUpdated:self.mostAccurateLocation]; 
     [self.locationManager stopUpdatingLocation]; 
    } 
} 
} 

Le code n'est pas excellent (ni formatage), mais l'idée, je pense, est simple et claire, Obtenez le premier emplacement, jetez-le, c'est un caché, faites 3 essais maximum pour un endroit le plus précis. Cela peut prendre beaucoup de temps, et si l'utilisateur attend (comme dans mon cas), définissez une limite de temps. Une fois de plus, cela fonctionne pour mon application, mais n'hésitez pas à la modifier ou à adopter une autre approche.

+0

ok c'est plus ou moins ce que j'ai trouvé aussi. Je ne l'ai pas enveloppé dans une classe mais il semble que j'ai couvert tout ce que vous avez mis en œuvre. Merci pour une réponse. – morgman

+0

@morgman vous pouvez voter alors;) – fspirit

2

Je sais que c'est un vieux fil que je ramène, mais je suis tombé sur cette question parce que je cherchais aussi une solution plus précise, et après avoir lu votre solution fspirit, je l'aime beaucoup. Comme morgman, je pensais aussi à peu près à quelque chose de similaire, mais vous venez de mettre nos pensées dans le code, lol. Aussi j'aime votre pensée avant-multi-threaded;)

Mais j'ai réellement une question/suggestion, si vous voulez. Lorsque j'essaie d'obtenir des données de localisation sur l'iPhone, j'obtiens au moins 3 jeux de coordonnées avec la même précision horizontale dès le départ. Un bon nombre d'essais devrait donc être supérieur à 4. Mais la question est alors de savoir combien d'essais sont bons?Donc je suggère qu'au lieu de changer le nombre d'essais, nous pouvons faire un léger ajustement au code, de sorte que le nombre de tentatives de compteur augmente. Seulement si la précision horizontale est significativement inférieure à la précédente, ou moins que le plus précis, quelque chose comme ça. Je pense juste à voix haute ici. Parce que j'ai regardé toutes les données de localisation de mon iphone 4 (et je ne sais pas comment cela fonctionne sur d'autres appareils), et d'après ce que j'ai vu, l'emplacement est mis à jour assez régulièrement, et la précision horizontale reste relativement le même pour le premier couple de mises à jour, puis après un certain temps, il saute soudainement de dire, 400 à 100, puis après une seconde ou deux de plus, il redescend à environ 30. Tout cela est au cours de environ 30-50 mises à jour, donc dans cette situation, un nombre maximum d'essais de 4 peut ne pas fonctionner, sauf si vous ne comptez que les sauts. Qu'en pensez-vous?

Questions connexes