2010-10-06 10 views
8

Qualcuno l'ha ancora inchiodato? Ho letto molti post sul forum e non riesco ancora a capire se questa è una domanda risolta ...Algoritmo definitivo per determinare la maggior precisione restituita da iPhone CoreLocation?

Dato che didUpdateToLocation() può restituire informazioni memorizzate nella cache o imprecise, come si fa a dire quando si dispone di un'accurata risolvere?

Quando si imposta la precisione desiderata su kCLLocationAccuracyNearestTenMeters, HundredMeters, Kilometer, ThreeKilometers, sembra ovvio che sia possibile confrontare l'accuratezza orizzontale dei punti restituiti rispetto alla precisione desiderata per decidere quando accettare un punto.

Ma i valori di kCLLocationAccuracyBestForNavigation e kCLLocationAccuracyBest sono rispettivamente -2 e -1, quindi come faccio a sapere quando ho la precisione desiderata?

Attualmente controllo l'età della correzione e rifiuto qualsiasi correzione che è troppo "vecchia" a tempo. Poi controllo se la precisione orizzontale è negativa e la rigetto se lo è. se ottengo un'Accuratezza verticale positiva, generalmente utilizzo quella correzione poiché anche la precisione orizzontale corrispondente è buona.

Ma questi controlli sono stati utilizzati quando ho cercato la precisione nei 10-100s di metri ... ?? Suppongo di livellare costantemente il locationManager e non pretendere mai di spegnerlo e non filtrare alcun risultato ??

Qualcuno più saggio di me con una risposta ??

Grazie

risposta

3

Non è proprio un algoritmo perfetto definitiva (dubito che c'è uno per questo compito, a causa delle condizioni esterne, voglio dire, si può provare Get Ur posizione sul campo di pianura o all'interno di una tomba), è un caso ad hoc, e funziona per me.

ho fatto un wrapper per LocationManager, come

@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 

Attuazione

#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]; 
    } 
} 
} 

Il codice non è eccellente (non formattazione è), ma l'idea, credo, è semplice e chiaro, ottenere la prima posizione, buttarla fuori, è una cache, fare 3 tentativi max per una posizione più precisa. Può richiedere molto tempo e se l'utente è in attesa (come nel mio caso), definire un limite di tempo. Ancora una volta, funziona per la mia app, ma sentitevi liberi di modificarlo o adottare un altro approccio.

+0

ok questo è più o meno quello che mi è venuto in mente. Non ce l'ho in una classe ma sembra che abbia coperto tutto ciò che hai implementato. Grazie per la risposta. – morgman

+0

@morgman puoi votarlo allora;) – fspirit

2

So che questo è un vecchio thread che sto riportando indietro, ma mi sono imbattuto in questa domanda perché stavo anche cercando una soluzione più accurata, e dopo aver letto la tua soluzione fspirit, mi piace molto. Come Morgman, stavo anche pensando qualcosa di simile, ma hai semplicemente messo i nostri pensieri in codice, lol. Mi piace anche il tuo pensiero multi-thread in avanti;)

Ma in realtà ho una domanda/suggerimento, se vuoi. Quando cerco di ottenere i dati sulla posizione sull'iPhone, ottengo almeno 3 serie di coordinate con la stessa precisione orizzontale a partire dal pipistrello. Quindi un buon numero di tentativi dovrebbe essere superiore a 4. Ma la domanda allora è: quanti tentativi è buono?

Quindi suggerisco che invece di modificare il numero di tentativi, possiamo apportare un piccolo aggiustamento al codice, in modo che il numero di contatore dei tentativi salga Solo se l'accuratezza orizzontale è significativamente inferiore alla precedente, o meno di quello più accurato, qualcosa del genere. Sto solo pensando ad alta voce qui. Perché ho dato un'occhiata a tutti i dati sulla posizione che ho ricevuto dal mio iPhone 4 (e non sono sicuro di come funziona su altri dispositivi) e, a giudicare da quello che ho visto, la posizione viene aggiornata abbastanza costantemente e l'accuratezza orizzontale rimane relativamente lo stesso per il primo paio di aggiornamenti, poi dopo un po 'salta improvvisamente da dire, da 400 a 100, e poi dopo un secondo o due, salta nuovamente a circa 30. Tutto questo è nel corso del circa 30-50 aggiornamenti, quindi in questa situazione un numero massimo di tentativi di 4 potrebbe non funzionare, a meno che non stiate solo contando i salti. Che cosa ne pensate?

Problemi correlati