CLLocationManager réactivité
J'ai une application qui tourne autour de l'appareil GPS et les informations qui en découle. Il est important que l'emplacement des données exactes et à jour. Je sais que l'appareil est limité par son GPS et le GPS est limite, mais je me demandais si il n'y a rien que je peux faire pour modifier/améliorer les performances du GPS de l'iPhone, en particulier dans la zone vitesse. Parce que l'emplacement des mises à jour de décalage d'environ 3 à 5 secondes derrière la localisation en temps réel de l'appareil, la vitesse signalée par le directeur des lieux est aussi à la traîne loin derrière la valeur en temps réel. Dans mon cas, qui est tout simplement trop long. Je comprends qu'il y a peut-être pas quelque chose que je peux faire, mais personne n'a jamais eu de succès dans l'amélioration de la réactivité du GPS de l'iPhone? Chaque petit geste fait une différence.
Edit 1:
Ma position manager est à l'intérieur d'une classe singleton, Apple recommande.
À L'Intérieur 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.desiredAccuracy = kCLLocationAccuracyBestForNavigation;
} else {
locationManager.desiredAccuracy = kCLLocationAccuracyBest;
}
[sharedSingleton setLocationManager:locationManager];
[locationManager release];
À L'Intérieur De MapView.m (où l'emplacement manager est en cours d'utilisation):
- (id)initWithNibName:(NSString*)nibNameOrNil bundle:(NSBundle*)nibBundleOrNil {
//setup
[SingletonDataController sharedSingleton].locationManager.delegate = self;
//more setup
}
- (void)batteryChanged {
if(([[UIDevice currentDevice] batteryState] == UIDeviceBatteryStateCharging) || ([[UIDevice currentDevice] batteryState] == UIDeviceBatteryStateFull)) {
[SingletonDataController sharedSingleton].locationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation;
} else {
[SingletonDataController sharedSingleton].locationManager.desiredAccuracy = kCLLocationAccuracyBest;
}
}
- (void)viewDidLoad {
//setup
[[NSNotificationCenter defaultCenter]
addObserver:self
selector:@selector(batteryChanged)
name:UIDeviceBatteryStateDidChangeNotification
object:nil];
//other setup
}
Le traitement des données se fait à l'intérieur locationManager:didUpdateToLocation:fromLocation:
. Je ne crois pas que l'inefficacité est ici la cause du lag.
locationManager:didUpdateToLocation:fromLocation:
appelle cette méthode pour mettre à jour l'INTERFACE utilisateur:
- (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];
}
Avec un couple de NSDates et NSLogs j'ai trouvé que l'exécution de l'ensemble locationManager:didUpdateToLocation:fromLocation:
(pas juste l'étiquette méthode de mise à jour) ne prend jamais plus de sujet de 8ms sur mon iPhone 4; en d'autres termes, le traitement des données n'est pas le problème.
Ajout d'un code. Je peux poster la suite si nécessaire.
3-5 secondes peut-être un peu exagéré; il est tard et de la plage de 3-5 juste sauté dans ma tête pour une raison quelconque. Demain, je vais faire quelques tests pour obtenir des chiffres exacts.
Rien d'étrange là. Que faites-vous dans locationManager:didUpdateToLocation:fromLocation: et comment êtes-vous déterminer que c'est à la traîne?
Désolé je ne peux pas aider avec le problème de latence. Mais je pense que vous pouvez simplifier l'initialisation de secondsString/minutesString/hoursString acheter à l'aide d'un @"%02i" pour formater automatiquement le nombre avec un 0 sans explicitement test pour "<10"
OriginalL'auteur eric.mitchell | 2012-03-17
Vous devez vous connecter pour publier un commentaire.
OK, un couple de choses pourraient améliorer votre gal. Tout d'abord, l'utilisation kCLLocationAccuracyBestForNavigation toujours. Il n'y a pas de véritable utilisation de la batterie différence entre cela et kCLLocationAccuracyBest, ils utilisent tous les deux le GPS à la vitesse supérieure. La principale différence est dans le post-traitement que fait Apple.
Deuxième, il n'y a pas besoin de filtre pour la vitesse == 0. Apple le fait déjà que le filtrage: si votre vitesse dans le GPS tombe en dessous d'un certain seuil (environ 4 km/h), le système suppose que vous êtes encore debout, et il remplace l'emplacement même valeur pour tous les échantillons. Il n'a que jusqu'à ce qu'elle pense de vous vous déplacez de nouveau. Je suppose qu'ils font ça pour éviter de "dérive" sur la carte lorsque vous êtes immobile. En fait, la vitesse tombe à 0 déjà pour la dernière vraie valeur d'une séquence de "permanent encore de" valeurs", donc, si vous filtrez sur la vitesse == 0 qu'il vous manque un vrai GPS de l'échantillon.
Malheureusement, ce n'est pas une façon d'éviter que le filtrage et obtenir un réel GPS échantillons. J'ai parlé à Apple à ce sujet, et leur réponse a été qu'ils ne vont pas changer le comportement. kCLLocationAccuracyBestForNavigation n'est moins agressif filtrage de kCLLocationAccuracyBest, il est donc préférable de l'utiliser.
Troisième, vous êtes probablement déjà le faire, mais assurez-vous que vous appelez "setNeedsDisplay" sur votre droit de vue de la "didUpdateFromLocation:", assurez-vous que la carte est en fait redessiné.
Si vous faites tout cela, vous devriez avoir un délai d'environ 1 seconde. Si vous voulez améliorer sur le second 1 que vous pouvez essayer d'utiliser des techniques de prédiction. Sur les deux derniers endroits, et la vitesse donnée, vous pouvez calculer où l'emplacement suivant est susceptible d'être, et déjà afficher votre localisation. J'ai eu des résultats mitigés. Il fonctionne bien pour le mouvement rapide, qui ne change pas de vitesse soudainement, comme conduire une voiture. Il fonctionne moins bien pour un mouvement plus lent, comme la marche ou le vélo.
kCLLocationAccuracyBestForNavigation
m'a vraiment aidé. L'emplacement délégué méthodes de fonctionner beaucoup plus rapidement maintenant 🙂ne ActivityType entrent en jeu avec exactitude à tous?
OriginalL'auteur fishinear
De l'iPhone, nous pouvons configurer les services de localisation par deux méthodes -
Standard Location Services
, c'est-satellite GPS qui vous fournir des données plus précises.Significant Location Changes
qui utilise le GPS ou obtenir la localisation par wi-fi qui fournissent des données moins précises.Nous pouvons configurer les services de localisation par l'une de ces deux méthodes, mais cela dépend de ce qui est l'exigence de l'application.
Si l'application est un
navigation app
ou unlocation tracking app
ensuite, il faut utiliserStandard Location Services
mais avant d'utiliser le standard de services que nous avons à l'esprit que si vous voulez des données plus précises, alors vous devez souffrir avecbattery consume more quickly
.Si l'application ne nécessite pas l'emplacement de mise à jour plus fréquemment et aussi la
accuracy doesn't matter
beaucoup, alors nous devrionsSignificant Location Changes
car il vasave a lot of battery
consommer que de les comparer à la Norme de Service de Localisation.Norme de Service de Localisation utilise
desiredAccuracy
etdistanceFilter
valeur de déterminer si et quand pour fournir de l'événement.desiredAccuracy
est le paramètre qui vous permet de définir la façon dont beaucoup de précision que vous voulez à partir du matériel GPS. Il utilise des constantes pré-définies comme -distanceFilter
est le paramètre où vous devez définir la distance, des moyens pour combien de distance de l'écart que vous voulez poser du matériel GPS pour envoyer un emplacement de mise à jour.Dans votre cas, vous avez affaire avec le paramètre de vitesse, donc je suppose que c'est quelque chose qui a trait à la navigation. Donc, vous devriez utiliser
Standard Location Services
. Je pense que vous êtes également le faire, mais le problème que vous rencontrez est le décalage entre l'emplacement des mises à jour. Ici je vous propose de modifier votredesiredAccuracy
etdistanceFilter
de la valeur à ce -[locationManager setDesiredAccuracy:kCLLocationAccuracyNearestTenMeters];
[locationManager setDistanceFilter:10.0 f];
par les valeurs de réglage de cela, vous obtenez l'emplacement de mise à jour en moins de 1 sec si votre conduite.
Une chose que vous avez à mettre dans votre esprit que lorsque vous obtenez l'emplacement de mise à jour, vous devriez vérifier son
timestamp
valeur d'ignorer ancien emplacement des mises à jour. Ses parce que quand vous commencezlocationManager
en appelantstartUpdatingLocation
puis le premier endroit que vous obtenez peut être votre ancien emplacement. Aussi, vous avez pour vérifier lahorizontalAccuracy
valeur parce que, d'abord quelques emplacement des mises à jour que vous obtenez ne sont pas toujours exactes et pourrait avoir de la précision dans 1000 ou plus que vous ne cherchez pas. Donc, vous avez pour vérifier sa valeur d'ignorer inexactes emplacement des mises à jour.OriginalL'auteur saadnib
Côté de l'autre, de bons exemples de la façon d'utiliser l'Emplacement de Noyau, aussi garder à l'esprit la technique générale pour obtenir de bons cinématique résultats d'un pas-si-grand capteur (par exemple, les services de localisation du smartphone) de Filtrage De Kalman.
C'est beaucoup de maths et de tests et de peaufinage, mais il ne vous permet pas d'obtenir ce que les utilisateurs devraient envisager de meilleurs résultats que de simples données du capteur fournit.
C'est ce qui est utilisé dans l'avionique et des choses comme le radar, les systèmes de traitement.
OriginalL'auteur Nate