我有一个应用程序,围绕设备的GPS和来自它的信息。重要的是,位置数据必须准确并且是最新的。我知道该设备受到GPS和GPS限制的限制,但我想知道我是否可以采取任何措施来调整/改善iPhone GPS的性能,特别是在速度区域。由于位置更新滞后于设备实时位置约3-5秒,因此位置管理器报告的速度也远远落后于实时值。就我而言,这太长了。我知道可能没有什么我可以做的,但有没有人在提高iPhone GPS的响应能力方面有任何成功?每一点点都有所不同。
编辑1:
我的位置管理员在Apple推荐的单身课程中。
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内部(实际使用位置管理器):
- (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和NSLogs,我发现整个locationManager:didUpdateToLocation:fromLocation:
(不仅仅是标签更新方法)的执行在我的iPhone 4上的持续时间不会超过8毫秒;换句话说,数据处理不是问题。
答案 0 :(得分:27)
好的,有几件事可以改善你的滞后。首先,始终使用kCLLocationAccuracyBestForNavigation。它与kCLLocationAccuracyBest之间没有真正的电池使用差异,它们都以最高速度使用GPS。主要区别在于Apple的后处理。
其次,没有必要过滤速度== 0.苹果已经进行过滤:如果你的GPS速度低于某个阈值(约4公里/小时),操作系统假设你站着不动,并且它为所有后续样本替换相同的位置值。这样做直到它认为你再次移动。我假设他们这样做是为了避免当你站着不动时在地图上“抖动”。实际上,对于一系列“静止”值的最后一个实际值,速度已降至0,因此如果您在速度= = 0时过滤而不是丢失一个真实的GPS样本。
不幸的是,他们无法避免过滤并获得真实的GPS样本。我和Apple谈过这件事,他们的反应是他们不会改变这种行为。 kCLLocationAccuracyBestForNavigation执行的过滤比kCLLocationAccuracyBest更少,因此最好使用它。
第三,你可能已经这样做了,但要确保你在“didUpdateFromLocation:”的视图上调用“setNeedsDisplay”,以确保实际重绘了地图。
如果你做了所有这些,你应该有大约1秒的滞后。如果你想在1秒内改进,你可以尝试使用预测技术。从最后两个位置和给定的速度,您可以计算下一个位置可能的位置,并且已经显示该位置。我的结果好坏参半。它适用于快速移动,不会像驾驶汽车那样突然改变速度。对于像步行或骑自行车这样的慢速运动,它的效果较差。
答案 1 :(得分:6)
在iPhone中,我们可以通过两种方法配置位置服务 -
Standard Location Services
,即卫星GPS,为您提供更准确的数据。Significant Location Changes
或通过wi-fi获取定位数据较少的位置。我们可以通过这两种方法中的任何一种来配置位置服务,但这取决于应用程序的要求。
如果应用是navigation app
或location tracking app
,那么我们应该使用Standard Location Services
,但在使用标准服务之前,我们要记住,如果您想要更准确的数据,那么您必须使用{{ 1}}。
如果应用不需要更频繁地更新位置以及battery consume more quickly
,那么我们应accuracy doesn't matter
,因为与标准位置服务相比,Significant Location Changes
会消耗。
标准位置服务使用save a lot of battery
和desiredAccuracy
值来确定是否以及何时投放活动。
distanceFilter
是您可以定义GPS硬件所需精度的参数。它使用一些预定义的常量作为 -
desiredAccuracy
kCLLocationAccuracyBestForNavigation
kCLLocationAccuracyBest
kCLLocationAccuracyNearestTenMeters
kCLLocationAccuracyHundredMeters
kCLLocationAccuracyKilometer
kCLLocationAccuracyThreeKilometers
是您必须定义距离的参数,表示您要求GPS硬件发送位置更新的距离差距。
在你的情况下,你正在处理速度参数,所以我猜它的东西与导航有关。所以你应该使用distanceFilter
。我认为你也是这样做的,但你所面临的问题是位置更新之间的滞后。在这里,我建议您将Standard Location Services
和desiredAccuracy
值修改为此 -
[locationManager setDesiredAccuracy:kCLLocationAccuracyNearestTenMeters]; [locationManager setDistanceFilter:10.0f];
通过设置值,如果您正在驾驶,您将在不到1秒内获得位置更新。
还有一件事需要记住,当您获得位置更新时,应检查其distanceFilter
值以忽略旧的位置更新。这是因为当您通过拨打timestamp
启动locationManager
时,您获得的第一个位置可能是您的旧位置。此外,您还必须检查startUpdatingLocation
值,因为您获得的前几个位置更新始终不准确,并且可能具有1000或更多的准确性,而您并不需要。因此,您必须检查其值以忽略不准确的位置更新。
horizontalAccuracy
答案 2 :(得分:1)
除了如何使用核心位置的其他好例子之外,还要记住从Kalman Filtering的不太好的传感器(例如智能手机定位服务)获得良好运动学结果的一般技术。 / p>
这是一个很多数学,测试和调整,但它确实让你得到用户认为比传感器提供的简单数据更好的结果。
这是用于航空电子设备和雷达处理系统的东西。