首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >CLLocationManager响应性

CLLocationManager响应性
EN

Stack Overflow用户
提问于 2012-03-17 10:15:50
回答 3查看 10.7K关注 0票数 12

我有一个应用程序,它围绕着设备的GPS和来自它的信息。位置数据必须准确和最新,这一点很重要。我知道这款设备受到其全球定位系统和全球定位系统的限制,但我想知道是否可以做些什么来调整/提高iPhone全球定位系统的性能,特别是在速度方面。由于位置更新比设备的实时位置延迟约3-5秒,因此位置管理器报告的速度也远远落后于实时值。在我的例子中,这实在是太长了。我知道我可能无能为力,但有人成功地提高了iPhone全球定位系统的响应能力吗?每一小点都会有所不同。

编辑1:

正如Apple推荐的那样,我的位置管理器位于单例类中。

在SingletonDataController.m中:

代码语言:javascript
复制
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中(实际使用位置管理器):

代码语言:javascript
复制
- (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:

代码语言:javascript
复制
- (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,我发现在我的iPhone 4上执行整个locationManager:didUpdateToLocation:fromLocation: (不仅仅是标签更新方法)花费的时间从来不会超过8ms;换句话说,数据处理不是问题。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2012-03-31 15:40:06

好的,有几件事可以改善你的滞后。首先,始终使用kCLLocationAccuracyBestForNavigation。它和kCLLocationAccuracyBest之间没有真正的电池使用差异,它们都以最快的速度使用全球定位系统。主要的区别在于Apple所做的后处理。

其次,不需要过滤速度== 0。苹果已经在做这种过滤:如果你的GPS速度降到某个阈值以下(大约4公里/小时),操作系统就会假设你静止不动,并用相同的位置值替换所有后续的样本。它会一直这样做,直到它认为你再次移动。我假设他们这样做是为了避免当你站着不动时地图上的“抖动”。事实上,对于一个“静止”值序列的最后一个实际值,速度已经降到了0,所以如果你对速度== 0进行过滤,那么你就会错过一个真实的==样本。

不幸的是,他们没有办法避免这种滤波,并获得真正的GPS样本。我和苹果谈过这件事,他们的反应是他们不会改变这种行为。与kCLLocationAccuracyBest相比,kCLLocationAccuracyBestForNavigation的过滤要少得多,所以最好使用它。

第三,您可能已经在这样做了,但请确保在视图上从"didUpdateFromLocation:“调用"setNeedsDisplay”,以确保地图确实被重新绘制。

如果你做了所有这些,你应该会有大约1秒的延迟。如果你想提高1秒,你可以尝试使用预测技术。根据前两个位置和给定的速度,您可以计算下一个位置可能在哪里,并且已经显示了该位置。我对此的结果好坏参半。它适用于不会突然改变速度的快速移动,如驾驶汽车。对于慢速运动,如步行或骑自行车,它的效果就不太好。

票数 28
EN

Stack Overflow用户

发布于 2012-03-31 16:18:11

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

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

我们可以通过这两种方法中的任何一种来配置位置服务,但这取决于应用程序的要求。如果应用程序是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硬件获得多高的精度。它使用一些预定义的常量作为-

代码语言:javascript
复制
kCLLocationAccuracyBestForNavigation
kCLLocationAccuracyBest
kCLLocationAccuracyNearestTenMeters
kCLLocationAccuracyHundredMeters
kCLLocationAccuracyKilometer
kCLLocationAccuracyThreeKilometers

distanceFilter是你必须定义距离的参数,意味着你想让GPS硬件发送位置更新的距离间隔有多大。

在您的例子中,您处理的是速度参数,所以我猜它与导航有关。所以你应该使用Standard Location Services。我认为你也在这么做,但你面临的问题是位置更新之间的滞后。在这里,我建议您将desiredAccuracydistanceFilter值修改为以下值-

setDesiredAccuracy:kCLLocationAccuracyNearestTenMeters;locationManager locationManager setDistanceFilter:10.0f;

通过将值设置为此值,如果您正在驾驶,您将在不到1秒内获得位置更新。

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

代码语言:javascript
复制
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.
票数 6
EN

Stack Overflow用户

发布于 2012-05-31 11:13:24

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

这需要大量的数学计算、测试和调整,但它确实允许您获得用户认为比传感器提供的简单数据更好的结果。

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

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/9746675

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档