我目前正在使用位置跟踪应用,但我的 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];
}
提前致谢! : - )
答案 0 :(得分:18)
我在类似应用程序中解决此问题的方法之一是丢弃位置更新,其中距离变化略小于该位置更新中报告的水平精度。
给定previousLocation
,然后对于newLocation
,计算与previousLocation
的距离。如果distance >= (horizontalAccuracy * 0.5)
那么我们就使用了该位置,该位置就成了新的previousLocation
。如果距离较小,则我们会放弃该位置更新,请勿更改previousLocation
并等待下一次位置更新。
这对我们的目的很有用,你可能会尝试类似的东西。如果你仍然发现太多的噪音更新,请增加0.5因子,或者尝试0.66。
您可能还希望在刚刚开始获得修复时防范案例,在这些情况下,您会获得一系列似乎正在移动的位置更新,但实际上正在发生的是准确性正在显着提高。
我会避免以水平精度开始任何位置跟踪或距离测量> 70米。这些都是全球导航卫星系统的劣质位置,尽管这可能是你在城市峡谷,重型树冠或其他信号条件差的情况下得到的。
答案 1 :(得分:5)
我已经使用这种方法来检索所需的位置精度(在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()
}
}
答案 2 :(得分:1)
这始终是卫星位置的问题。这是一个估计,估计可能会有所不同。每份新报告都是一个新的估计。你需要的是一个位置钳,在没有运动时忽略数值。
您可能会尝试使用传感器来了解设备是否实际移动。查看加速度计数据,如果它没有变化,那么即使GPS显示它也不会移动设备。当然,加速度计数据上存在噪音,因此您必须对其进行过滤。
这是一个棘手的问题需要解决。
答案 3 :(得分:0)
您可以采取更多措施来改善操作系统和您当前的接收效果。首先看,你的代码看起来没有任何问题 - 当涉及iOS位置更新时,你真的受操作系统和服务的支配。
您可以做的是控制您要注意的位置。当你从具有新位置的OS获得回调时,如果我在你的didUpdateLocations函数中 - 你可以忽略任何水平精度大于某个预定义阈值的位置,可能是25m?您最终会使用较少的位置更新,但噪音较少。