CLLocationManager capacidad de respuesta

Tengo una aplicación que gira alnetworkingedor del GPS del dispositivo y la información que proviene de él. Es importante que los datos de location sean precisos y estén actualizados. Sé que el dispositivo está limitado por su GPS y los límites del GPS, pero me preguntaba si hay algo que pueda hacer para modificar o mejorar el performance del iPhone GPS, especialmente en el área de velocidad. Debido a que las actualizaciones de location se retrasan unos 3-5 segundos detrás de la location en time real del dispositivo, la velocidad informada por el administrador de location también está muy por detrás del valor en time real. En mi caso, eso es simplemente demasiado largo. Entiendo que puede que no haya nada que pueda hacer, pero ¿alguien ha tenido éxito en mejorar la capacidad de respuesta del iPhone GPS? Cada bit hace la diferencia.

Editar 1:

Mi administrador de location está dentro de una class singleton, como recomienda Apple.

Dentro de SingletonDataController.m:

static CLLocationManager* locationManager; locationManager = [CLLocationManager new]; locationManager.distanceFilter = kCLDistanceFilterNone; locationManager.headingFilter = kCLHeadingFilterNone; if(([[UIDevice currentDevice] batteryState] == UIDeviceBatteryStateCharging) || ([[UIDevice currentDevice] batteryState] == UIDeviceBatteryStateFull)) { locationManager.desinetworkingAccuracy = kCLLocationAccuracyBestForNavigation; } else { locationManager.desinetworkingAccuracy = kCLLocationAccuracyBest; } [shanetworkingSingleton setLocationManager:locationManager]; [locationManager release]; 

Dentro de MapView.m (donde se usa realmente el administrador de location):

 - (id)initWithNibName:(NSString*)nibNameOrNil bundle:(NSBundle*)nibBundleOrNil { //setup [SingletonDataController shanetworkingSingleton].locationManager.delegate = self; //more setup } - (void)batteryChanged { if(([[UIDevice currentDevice] batteryState] == UIDeviceBatteryStateCharging) || ([[UIDevice currentDevice] batteryState] == UIDeviceBatteryStateFull)) { [SingletonDataController shanetworkingSingleton].locationManager.desinetworkingAccuracy = kCLLocationAccuracyBestForNavigation; } else { [SingletonDataController shanetworkingSingleton].locationManager.desinetworkingAccuracy = kCLLocationAccuracyBest; } } - (void)viewDidLoad { //setup [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(batteryChanged) name:UIDeviceBatteryStateDidChangeNotification object:nil]; //other setup } 

El event handling datos ocurre dentro de locationManager:didUpdateToLocation:fromLocation: No creo que la ineficiencia aquí sea la causa del retraso.

locationManager:didUpdateToLocation:fromLocation: llama a este método para actualizar la UI:

 - (void)setLabels:(CLLocation*)newLocation fromOldLocation:(CLLocation*)oldLocation { //set speed label if(iterations > 0) { if(currentSpeed > keyStopSpeedFilter) { if(isFollowing) { [mapViewGlobal setRegion:MKCoordinateRegionMake([newLocation coordinate], mapViewGlobal.region.span)]; } NSString* currentSpeedString; if(isCustomary) { currentSpeedString = [[NSString alloc] initWithFormat:@"%.1f miles per hour", (currentSpeed * 2.23693629f)]; } else { currentSpeedString = [[NSString alloc] initWithFormat:@"%.1f km per hour", (currentSpeed * 3.6f)]; } [speedLabel setText:currentSpeedString]; [currentSpeedString release]; } else { speedLabel.text = @"Not moving"; } } //set average speed label if(iterations > 4 && movementIterations > 2) { NSString* averageSpeedString; if(isCustomary) { averageSpeedString = [[NSString alloc] initWithFormat:@"%.1f miles per hour", (float)((speedAverages / (long double)movementIterations) * 2.23693629f)]; } else { averageSpeedString = [[NSString alloc] initWithFormat:@"%.1f km per hour", (float)((speedAverages / (long double)movementIterations) * 3.6f)]; } [averageSpeedLabel setText:averageSpeedString]; [averageSpeedString release]; } //set elapsed time label NSInteger seconds = [[NSDate date] timeIntervalSinceDate:dataObject.locationManagerStartDate]; NSInteger minutes = seconds / 60; NSInteger hours = minutes / 60; //get remainder seconds %= 60; NSString* timeString; NSString* secondsString; NSString* minutesString; NSString* hoursString; if((seconds % 60) < 10) { secondsString = [[NSString alloc] initWithFormat:@"0%i", seconds]; } else { secondsString = [[NSString alloc] initWithFormat:@"%i", seconds]; } if((minutes % 60) < 10) { minutesString = [[NSString alloc] initWithFormat:@"0%i", minutes]; } else { minutesString = [[NSString alloc] initWithFormat:@"%i", minutes]; } if((hours % 60) < 10) { hoursString = [[NSString alloc] initWithFormat:@"0%i", hours]; } else { hoursString = [[NSString alloc] initWithFormat:@"%i", hours]; } timeString = [[NSString alloc] initWithFormat:@"%@:%@:%@", hoursString, minutesString, secondsString]; [elapsedTimeLabel setText:timeString]; [timeString release], timeString = nil; [secondsString release], secondsString = nil; [minutesString release], minutesString = nil; [hoursString release], hoursString = nil; NSString* totalDistanceString; if(isCustomary) { totalDistanceString = [[NSString alloc] initWithFormat:@"Total: %.2f mi", (float)distance * 0.000621371192f]; } else { totalDistanceString = [[NSString alloc] initWithFormat:@"Total: %.2f km", (float)distance / 1000.0f]; } [customTopBar setTitle:totalDistanceString]; [totalDistanceString release]; } 

Con un par de NSDates y NSLogs he encontrado que la ejecución de todo el locationManager:didUpdateToLocation:fromLocation: (no solo el método de actualización de la label) nunca tarda más de 8 ms en mi iPhone 4; En otras palabras, el event handling datos no es el problema.

OK, un par de cosas podrían mejorar tu retraso. Antes que nada, use kCLLocationAccuracyBestForNavigation siempre. No existe una diferencia real de uso de la batería entre kCLLocationAccuracyBest y ambos, usan el GPS a máxima velocidad. La principal diferencia está en el postprocesamiento que hace Apple.

En segundo lugar, no hay necesidad de filtrar la velocidad == 0. Apple ya hace ese filtrado: si su velocidad desde el GPS cae por debajo de un cierto umbral (aproximadamente 4 km / h), el SO supone que está parado, y lo sustituye el mismo valor de location para todas las muestras posteriores. Hace eso hasta que piensa que te estás moviendo de nuevo. Supongo que hacen eso para evitar "fluctuar" en el map cuando estás parado. De hecho, la velocidad cae a 0 ya para el último valor real de una secuencia de valores "quietos", por lo que si filtra en la velocidad == 0 de lo que le falta a una muestra real de GPS.

Desafortunadamente, no hay manera de evitar ese filtrado y get muestras reales de GPS. Hablé con Apple sobre eso, y su respuesta fue que no van a cambiar el comportamiento. kCLLocationAccuracyBestForNavigation realiza un filtrado less agresivo que kCLLocationAccuracyBest, por lo que es mejor usar eso.

En tercer lugar, es probable que ya esté haciendo esto, pero asegúrese de llamar "setNeedsDisplay" en su vista directamente desde "didUpdateFromLocation:", para asegurarse de que el map se vuelva a dibujar.

Si haces todo eso, deberías tener un retraso de aproximadamente 1 segundo. Si quieres mejorar en 1 segundo, puedes intentar usar técnicas pnetworkingictivas. Desde las últimas dos ubicaciones, y la velocidad dada, puede calcular dónde es probable que se encuentre la próxima location y mostrar esa location. He tenido resultados mixtos con eso. Funciona bien para un movimiento rápido que no cambia la velocidad de repente, como conducir un automobile. Funciona less bien para movimientos más lentos, como caminar o andar en bicicleta.

En iPhone, podemos configurar los services de location por dos methods:

  1. Mediante el uso de Standard Location Services , es decir, un GPS por satélite que le proporciona datos más precisos.
  2. Al usar Significant Location Changes que utilizan A-GPS o get location a través de wi-fi que proporcionan datos less precisos.

Podemos configurar los services de location por cualquiera de estos dos methods, pero depende de cuál sea el requisito de la aplicación. Si la aplicación es una navigation app o una location tracking app , deberíamos utilizar los Standard Location Services pero antes de utilizar los services estándar, tenemos en mente que si desea get datos más precisos, tendrá que sufrir con battery consume more quickly . Si la aplicación no requiere actualización de location con más frecuencia y también la accuracy doesn't matter mucho, entonces deberíamos realizar Significant Location Changes porque save a lot of battery consumida, en comparación con el Servicio de location estándar.

El service de location estándar utiliza la desinetworkingAccuracy y el valor de distanceFilter filter para determinar cuándo y cuándo entregar el evento.

desinetworkingAccuracy es el parámetro en el que puede definir la cantidad de precisión que desea del hardware de GPS. Utiliza algunas constantes pnetworkingefinidas como:

 kCLLocationAccuracyBestForNavigation kCLLocationAccuracyBest kCLLocationAccuracyNearestTenMeters kCLLocationAccuracyHundnetworkingMeters kCLLocationAccuracyKilometer kCLLocationAccuracyThreeKilometers 

distanceFilter es el parámetro en el que debe definir la distancia, significa cuánto espacio de distancia desea solicitar al hardware GPS para enviar una actualización de location.

En su caso, se trata del parámetro de velocidad, así que supongo que es algo relacionado con la navigation. Por lo tanto, debe utilizar los Standard Location Services . Creo que también estás haciendo eso, pero el problema que enfrentas es el retraso entre las actualizaciones de location. Aquí te sugiero que modifiques el valor de desinetworkingAccuracy y distanceFilter desinetworkingAccuracy a esto:

[locationManager setDesinetworkingAccuracy: kCLLocationAccuracyNearestTenMeters]; [locationManager setDistanceFilter: 10.0f];

al establecer valores para esto, obtendrá la actualización de location en less de 1 segundo si está conduciendo.

Una cosa más que debes tener en count es que cuando obtengas la actualización de la location debes verificar el valor de la timestamp para ignorar las actualizaciones de location antiguas. Es porque al iniciar locationManager llamando a startUpdatingLocation , la primera location que obtienes puede ser tu location anterior. También debe verificar el valor de la horizontalAccuracy porque las primeras actualizaciones de location que obtiene siempre son incorrectas y pueden tener una precisión de 1000 o más que no esté buscando. Por lo tanto, debe verificar su valor para ignorar las actualizaciones inexactas de la location.

 Note: If you try with different accuracy and different distance filter value then you will be more clear about it how accurate data iPhone GPS hardware return. 

Aparte de los otros buenos ejemplos de cómo usar Core Location, también tenga en count la técnica general para get buenos resultados de cinemática de un sensor no muy bueno (por ejemplo, services de localización de teléfonos inteligentes) de Kalman Filtering .

Es una gran cantidad de matemáticas, testings y ajustes, pero le permite get lo que los usuarios considerarían mejores resultados de lo que proporcionan los datos simples del sensor.

Esto es lo que se usa en la aviónica y cosas como los sistemas de procesamiento de radar.