核心位置的准确性

Posted

技术标签:

【中文标题】核心位置的准确性【英文标题】:Accuracy of Core Location 【发布时间】:2014-09-12 03:00:36 【问题描述】:

我目前正在开发一个位置跟踪应用程序,但我的 CLLocationManager 位置更新不准确时遇到了困难。这会导致我的应用程序跟踪距离,这实际上只是由不准确的 GPS 读数引起的。

我什至可以在我的应用打开的情况下将我的 iPhone 放在桌子上,并且在几分钟内我的应用就因为这个缺陷跟踪了数百米的距离。

这是我的初始化代码:

- (void)initializeTracking 
    self.locationManager = [[CLLocationManager alloc] init];
    self.locationManager.delegate = self;
    self.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
    self.locationManager.distanceFilter = 5;

    [self.locationManager startUpdatingLocation];

提前致谢! :-)

【问题讨论】:

我面临同样的问题,你能更新你的代码如何解决这个问题吗?这对我们有好处 @Imran 我从来没有真正改变过- (void)initializeTracking。我只根据 progrmr 和 Max_Power89 的答案中的建议更改了- (void)locationManaged:didUpdateLocation。如果我现在必须做同样的事情,我不会再自己实现它。有一些 CocoaPods 解决了这个问题,例如INTULocationManager 感谢您的甜蜜回复。希望你能做到。你能告诉我你在 (void)locationManaged:didUpdateLocation 上做了什么改变吗?解决我的问题很容易 【参考方案1】:

我在类似应用程序中解决此问题的方法之一是丢弃位置更新,其中距离变化略小于该位置更新中报告的水平精度。

给定previousLocation,然后对于newLocation,计算与previousLocation 的距离。如果那个distance >= (horizontalAccuracy * 0.5),那么我们使用那个位置并且那个位置成为我们新的previousLocation。如果距离更小,我们会丢弃该位置更新,不要更改 previousLocation 并等待下一次位置更新。

这对我们的目的很有效,您可以尝试类似的方法。如果你仍然发现太多的更新是噪音,增加 0.5 因子,也许试试 0.66。

您可能还想防范刚开始修复时出现的情况,在这些情况下,您会收到一系列看似移动的位置更新,但实际情况是准确性正在显着提高。

我会避免以 > 70 米的水平精度开始任何位置跟踪或距离测量。对于 GNSS 来说,这些位置质量很差,尽管在城市峡谷、茂密的树冠或其他信号较差的条件下,您可能只能得到这些位置。

【讨论】:

谢谢,这种方法与另一篇文章中描述的基于准确性的过滤相结合,效果非常好。 :-) horiztonalAccuracy 会比desiredAccuracy 高吗?还是 CoreLocation 本身会过滤掉那些? @Honey 是的,horizontalAccuracy 可以高于或低于 desiredAccuracy。您将获得当时最准确的位置。您可以过滤我们不想使用的那些(较高的值 == 较差的准确性)。例如,通常一开始精度很差(1000m),然后在几秒钟或更长时间后变得更好,可以达到 5m 精度,而desiredAccuracy 设置为 50m。【参考方案2】:

我已使用此方法检索所需的位置精度(在 SWIFT 中)

let TIMEOUT_INTERVAL = 3.0
func locationManager(manager: CLLocationManager!, didUpdateLocations locations: [AnyObject]!) 
    let newLocation = locations.last as! CLLocation
    println("didupdateLastLocation \(newLocation)")
    //The last location must not be capured more then 3 seconds ago
    if newLocation.timestamp.timeIntervalSinceNow > -3 &&
        newLocation.horizontalAccuracy > 0 
            var distance = CLLocationDistance(DBL_MAX)
            if let location = self.lastLocation 
                distance = newLocation.distanceFromLocation(location)
            
            if self.lastLocation == nil ||
                self.lastLocation!.horizontalAccuracy > newLocation.horizontalAccuracy 
                    self.lastLocation = newLocation
                    if newLocation.horizontalAccuracy <= self.locationManager.desiredAccuracy 
                        //Desired location Found
                        println("LOCATION FOUND")
                        self.stopLocationManager()
                    
             else if distance < 1 
                let timerInterval = newLocation.timestamp.timeIntervalSinceDate(self.lastLocation!.timestamp)
                if timerInterval >= TIMEOUT_INTERVAL 
                    //Force Stop
                    stopLocationManager()
                
            
    

地点:

if newLocation.timestamp.timeIntervalSinceNow > -3 &&
        newLocation.horizontalAccuracy > 0 

检索到的最后一个位置不得超过 3 秒前被捕获,并且最后一个位置必须具有有效的水平精度(如果小于 1 表示它不是有效位置)。

然后我们要设置一个默认值的距离:

            var distance = CLLocationDistance(DBL_MAX)

计算从最后检索到的位置到新位置的距离:

if let location = self.lastLocation 
                distance = newLocation.distanceFromLocation(location)
            

如果我们的本地最后一个位置尚未设置,或者如果新位置的水平精度比实际位置更好,那么我们将我们的本地位置设置为新位置:

if self.lastLocation == nil ||
        self.lastLocation!.horizontalAccuracy > newLocation.horizontalAccuracy 
            self.lastLocation = newLocation

下一步是检查检索到的位置的准确性是否足够好。为此,我们检查位置的水平距离是否检索到它,以免达到所需的准确度。如果是这种情况,我们可以阻止我们的经理:

if newLocation.horizontalAccuracy <= self.locationManager.desiredAccuracy 
                        //Desired location Found
                        self.stopLocationManager()
                    

对于最后一个if,我们将检查与检索到的最后一个位置的距离是否小于新位置(这意味着这两个位置非常接近)。如果是这种情况,那么我们将获取从检索到的最后一个位置和检索到的新位置的时间间隔,并检查间隔是否超过 3 秒。如果是这种情况,这意味着我们没有收到更准确的本地位置的位置超过 3 秒,因此我们可以停止位置服务:

else if distance < 1 
                let timerInterval = newLocation.timestamp.timeIntervalSinceDate(self.lastLocation!.timestamp)
                if timerInterval >= TIMEOUT_INTERVAL 
                    //Force Stop
                    println("Stop location timeout")
                    stopLocationManager()
                
            

【讨论】:

如果您可以在目标 c 中转换此代码,那么获得您的观点会容易得多..谢谢 我将 kCLLocationAccuracyBest 用于desiredAccuracy,它是-1。如果我没记错的话,horizo​​ntalAccuracy 【参考方案3】:

这始终是卫星位置的问题。这是一个估计值,估计值可能会有所不同。每个新报告都是一个新的估计。您需要的是一个在没有运动时忽略值的位置钳。

您可以尝试使用传感器来了解设备是否真的在移动。查看加速度计数据,如果它没有变化,那么即使 GPS 说它是,设备也没有移动。当然,加速度计数据中存在噪声,因此您也必须将其过滤掉。

这是一个很难解决的问题。

【讨论】:

【参考方案4】:

要改善操作系统和您当前的接收效果,您确实没有太多可以做的事情。乍一看,您的代码似乎没有任何问题 - 当涉及到 ios 位置更新时,您确实受制于操作系统和您的服务。

您可以做的是控制您关注的位置。如果当您从操作系统获得带有新位置的回调时,我是您在我的 didUpdateLocations 函数中 - 您可以忽略水平精度大于某个预定义阈值(可能是 25m)的任何位置?您最终会使用更少的位置更新,但噪音会更少。

【讨论】:

他可以做很多事情,你可以看看其他坐在他桌子上不会增加​​距离计数的应用程序。 “增加距离计数”是什么意思?他正在寻找从操作系统获取更准确位置更新的方法 - 请随时分享更好的解决方案,我很想知道是否有。 图形显示他站在那条路上一动不动,或者坐在附近建筑物内的(办公室)办公桌前。在这两种情况下,距离累积都不应该提高,请再次阅读他的问题:他的目标是:“距离跟踪” 我害怕这个,我现在要试试你的建议。我还将 desiredAccuracy 更改为 kCLLocationAccuracyNearestTenMeters 并将 distanceFilter 更改为 20。您对这些值有任何首选配置吗?我想知道其他应用程序如何应对这种噪音,例如 Nike+ running。它与我的应用在同一台设备上运行,但总是以正确的位置数据结束,这怎么可能? 如果他们忽略所有精度低于 5m 的位置更新,可能是可能的,但我当然不知道他们是如何做到的。据我所知,没有办法限制噪音 - 您无法控制从操作系统获得的信息 - 只能控制您使用来自操作系统的信息所做的事情。

以上是关于核心位置的准确性的主要内容,如果未能解决你的问题,请参考以下文章

核心位置 - iphone sdk 中的准确性问题

如何使用核心位置检测准确度误差范围

核心位置的动态精度

停止核心位置更新,然后使用计时器重新启动它们

如何在 iOS 中使用核心图像准确检测图像中的人脸?

如何通过代码获取 iPhone 的当前位置?