CLLocationManager响应

我有一个应用程序围绕着设备的GPS和来自它的信息。 位置数据准确和最新是非常重要的。 我知道设备受到GPS和GPS的限制,但是我想知道是否有什么可以调整/改善iPhone GPS的性能,特别是在速度方面。 由于位置更新滞后于设备实时位置约3-5秒,所以位置pipe理器报告的速度也落后于实时值。 就我而言,这太长了。 我明白,可能没有什么我可以做的,但有没有人在提高iPhone GPS的响应能力方面取得任何成功? 每一点点都有所作为

编辑1:

正如苹果推荐的,我的位置pipe理器是在单例类中。

在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]; 

在MapView.m中(实际使用位置pipe理器的地方):

 - (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 } 

数据处理发生在locationManager:didUpdateToLocation:fromLocation: 我不认为这里的低效率是滞后的原因。

locationManager:didUpdateToLocation:fromLocation:调用此方法更新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]; } 

有了NSDates和NSLog,我发现执行整个locationManager:didUpdateToLocation:fromLocation:不仅仅是标签更新方法)在我的iPhone 4上不会超过8ms; 换句话说,数据处理不是问题。

好的,有几件事可以改善你的滞后。 首先,始终使用kCLLocationAccuracyBestForNavigation。 与kCLLocationAccuracyBest之间没有真正的电池使用差异,他们都使用GPS在最高速度。 主要区别在于苹果公司的后处理。

其次,没有必要过滤速度== 0.苹果已经做了这样的过滤:如果你的速度从GPS下降到一定的阈值(约4公里/小时),操作系统假定你站在静止,它取代所有后续样本的相同位置值。 这样做,直到它认为你再次移动。 我假设他们这样做是为了避免在地图上“抖动”。 事实上,对于“静止”值序列的最后一个实际值,速度已经下降到0,所以如果按照速度== 0进行过滤,就会比缺less一个真实的GPS样本。

不幸的是,他们无法避免这种过滤并获得真正的GPS采样。 我跟苹果谈过这件事,他们的回应是他们不会改变这种行为。 kCLLocationAccuracyBestForNavigation不如kCLLocationAccuracyBest进行更积极的过滤,所以最好使用它。

第三,你可能已经在做这个了,但是确保你在你的视图上从“didUpdateFromLocation:”调用了“setNeedsDisplay”,以确保地图实际上被重画了。

如果你这样做,你应该有一个约1秒的滞后。 如果你想在1秒内改善,你可以尝试使用预测技术。 从最后两个位置,以及给定的速度,您可以计算下一个位置可能在哪里,并已经显示该位置。 我的结果和这个结果有好有坏。 对于不急于改变速度的快速运动,如驾驶汽车,效果很好。 对于像步行或骑自行车这样的慢速运动来说效果不太好。

在iPhone中,我们可以通过两种方法来configuration位置服务 –

  1. 通过使用Standard Location Services ,这是卫星GPS,为您提供更准确的数据。
  2. 通过使用使用A-GPS的Significant Location Changes或通过提供不太准确的数据的Wi-Fi获取位置。

我们可以通过这两种方法来configuration位置服务,但这取决于应用程序的需求。 如果应用程序是一个navigation applocation tracking app那么我们应该使用Standard Location Services但在使用标准服务之前,我们记住,如果你想要更准确的数据,那么你必须忍受battery consume more quickly 。 如果应用程序不需要更频繁地进行位置更新,而且accuracy doesn't matter那么我们应该进行Significant Location Changes因为与标准位置服务相比,它可以save a lot of battery消耗。

标准位置服务使用desiredAccuracydistanceFilter值来确定是否以及何时发送事件。

desiredAccuracy是您可以从GPS硬件定义多less准确度的参数。 它使用一些预定义的常量作为 –

 kCLLocationAccuracyBestForNavigation kCLLocationAccuracyBest kCLLocationAccuracyNearestTenMeters kCLLocationAccuracyHundredMeters kCLLocationAccuracyKilometer kCLLocationAccuracyThreeKilometers 

distanceFilter是您必须定义距离的参数,意味着您要求GPS硬件发送位置更新的距离差距有多大。

在你的情况下,你正在处理的速度参数,所以我想它的东西有关的导航。 所以你应该使用Standard Location Services 。 我认为你也是这样做的,但是你所面临的问题是位置更新之间的差距。 在这里,我build议你修改你desiredAccuracydistanceFilter值到这个 –

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

通过设置这个值,如果你正在驾驶,你将在1秒内得到位置更新。

还有一件事你必须记住,当你得到位置更新时,你应该检查它的timestamp值来忽略旧的位置更新。 因为当你通过调用startUpdatingLocation启动locationManager ,那么你得到的第一个位置可能是你的旧位置。 此外,你必须检查horizontalAccuracy值,因为你得到的前几个位置更新总是不准确,可能有1000个或更多的准确性,你不是在寻找。 所以你必须检查它的值来忽略不准确的位置更新。

 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. 

除了关于如何使用核心位置的其他很好的例子之外,还要记住从Kalman Filtering的一个不太好的传感器(例如智能手机位置服务)获得良好运动学结果的一般技术。

这是很多的math和testing和调整,但它确实可以让你得到比传感器提供的简单数据更好的结果。

这就是在航空电子设备和雷达处理系统中使用的东西。