2010-10-06 16 views
8

Czy ktoś już to przybił? Przeczytałem wiele wpisów na forum i nadal nie mogę stwierdzić, czy jest to rozstrzygnięte pytanie ...Ostateczny algorytm określania najdokładniejszego zwrotu z iPhone CoreLocation?

Biorąc pod uwagę, że metoda didUddateToLocation() może zwracać buforowane lub niedokładne informacje, w jaki sposób można stwierdzić, kiedy są dokładne naprawić?

Po ustawieniu żądanej dokładności na kCLLocationAccuracyNearestTenMeters, HundredMeters, Kilometer, ThreeKilometers, wydaje się oczywiste, że można porównać poziomą dokładność zwracanych punktów z pożądaną dokładnością, aby zdecydować, kiedy zaakceptować punkt.

Ale wartości kCLLocationAccuracyBestForNavigation i kCLLocationAccuracyBest są odpowiednio -2 i -1, więc skąd mam wiedzieć, kiedy mam pożądaną dokładność?

Obecnie sprawdzam wiek poprawki i odrzucam wszelkie poprawki, które są zbyt "stare" w czasie. Następnie sprawdzam, czy dokładność pozioma jest ujemna, i odrzuć ją, jeśli tak jest. Jeśli otrzymam dodatnią wartość dokładności pionowej, to zazwyczaj używam tej poprawki, ponieważ odpowiednia dokładność pozioma jest również dobra.

Ale kontrole te były stosowane, kiedy nie patrząc pod kątem dokładności w 10-100s metrów ... nie wiem co, jeśli coś by sprawdzić kiedy biegnę ... AccuracyBestForNavigation lub ... AccuracyBest ?? Czy mam założyć, że menedżer locationManager stale działa i nigdy nie spodziewam się go wyłączyć i nie filtrować żadnych wyników?

Ktoś mądrzejszy niż ja z odpowiedzią?

Dzięki

Odpowiedz

3

to naprawdę nie jest ostateczne, doskonały algorytm (wątpię, istnieje jeden dla tego zadania, z powodu warunków zewnętrznych, to znaczy, można spróbować dostać ur lokalizację na zwykłym polu lub wewnątrz grobowca) to jest doraźne i działa dla mnie.

zrobiłem otoki dla LocationManager, jak

@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 

Realizacji

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

Kod nie jest doskonała (ani formatowania), ale pomysł, myślę, jest prosty i przejrzysty, zdobądź pierwszą lokalizację, wyrzuć ją, jest buforowana, wykonaj maksymalnie 3 próby dla najdokładniejszej lokalizacji. Może to zająć dużo czasu i jeśli użytkownik czeka (tak jak w moim przypadku), zdefiniuj limit czasu. Jeszcze raz działa to dla mojej aplikacji, ale możesz ją poprawić lub zastosować inne podejście.

+0

ok to mniej więcej to, co wymyśliłem. Nie mam tego zapakowanego w klasę, ale wygląda na to, że obejmowałem wszystko, co zaimplementowałeś. Dzięki za odpowiedź. – morgman

+0

@morgman można go głosować następnie;) – fspirit

2

Wiem, że to stary wątek, który wracam, ale natknąłem się na to pytanie, ponieważ również szukałem najdokładniejszego rozwiązania, a po przeczytaniu twojego rozwiązania fspirit, bardzo mi się podoba. Podobnie jak Morgman, ja też prawie myślałem coś podobnego, ale po prostu umieszczasz nasze myśli w kodzie, lol. Lubię również twoje myślenie wielowątkowe;)

Ale tak naprawdę mam pytanie/sugestię, jeśli zechcesz. Kiedy próbuję uzyskać dane o lokalizacji na iPhonie, otrzymuję co najmniej 3 zestawy współrzędnych o takiej samej dokładności poziomej, tuż poza kodem. Tak więc duża liczba prób musiałaby być większa niż 4. Jednak pytanie, czy liczba prób jest dobra?

Sugeruję więc, że zamiast zmieniać liczbę prób, możemy wprowadzić drobne poprawki do kodu, aby liczba liczników prób wzrosła o tylko wtedy, gdy dokładność pozioma jest znacznie mniejsza niż poprzednia lub mniejsza. niż najdokładniejszy, coś takiego. Po prostu głośno tu myślę. Ponieważ przyjrzałem się wszystkim danym dotyczącym lokalizacji, które dostałem z mojego iPhone 4 (i nie jestem pewien, jak to działa na innych urządzeniach), i sądząc po tym, co zobaczyłem, lokalizacja jest ciągle aktualizowana dość stale, a dokładność pozioma pozostaje na tym samym poziomie przez kilka pierwszych aktualizacji, po czym nagle po chwili skacze z poziomu 400 do 100, a następnie po drugiej lub dwóch kolejnych skokach znowu spada do około 30. Wszystko to jest w toku około 30-50 aktualizacji, więc w tej sytuacji maksymalna liczba prób 4 może nie działać, chyba że liczysz tylko skoki. Co wy myślicie?

Powiązane problemy