使用核心位置时不准确的距离行驶值

时间:2017-06-20 20:11:43

标签: ios swift core-location

我对swift相对较新,我正在尝试为我的应用添加一项功能,该功能会跟踪在有限的时间内行进的距离。

然而,当我运行应用程序时,即使手机收到的纬度和经度准确,我也遇到了多个问题: 1.应用程序仅记录位置变化几秒钟 即使设备静止,该应用程序也会录制剧烈的动作。

感谢任何和所有帮助。这是我的代码:

import UIKit
import CoreLocation
import FirebaseAuth
import FirebaseDatabase

class MWTCountdownViewController: UIViewController, CLLocationManagerDelegate {

@IBOutlet weak var timerLabel: UILabel!
@IBOutlet weak var metersLabel: UILabel!
@IBOutlet weak var ConfirmTrialButton: UIButton!
var zeroTime = TimeInterval()
var timer : Timer = Timer()
var ref: DatabaseReference?

let locationManager = CLLocationManager()
var startLocation: CLLocation!
var lastLocation: CLLocation!
var distanceTraveled: Double = 0.0

override func viewDidLoad() {
    super.viewDidLoad()
    ConfirmTrialButton.isHidden = true
    ConfirmTrialButton.isEnabled = false
    locationManager.requestWhenInUseAuthorization()

    if CLLocationManager.locationServicesEnabled(){
        locationManager.delegate = self
        locationManager.desiredAccuracy = kCLLocationAccuracyBest
        distanceTraveled = 0.0
        startLocation = nil
        lastLocation = nil
        locationManager.startUpdatingLocation()
        locationManager.startMonitoringSignificantLocationChanges()
        locationManager.distanceFilter = 10

    } else {
        print("Need to Enable Location")
    }

    timer = Timer.scheduledTimer(timeInterval: 0.01, target: self, selector: #selector(MWTCountdownViewController.updateTime), userInfo: nil, repeats: true)
    zeroTime = Date.timeIntervalSinceReferenceDate


    ref = Database.database().reference()

}
func updateTime() {
    let currentTime = Date.timeIntervalSinceReferenceDate
    var timePassed: TimeInterval = currentTime - zeroTime
    let minutes = UInt8(timePassed / 60.0)
    timePassed -= (TimeInterval(minutes) * 60)
    let seconds = UInt8(timePassed)
    timePassed -= TimeInterval(seconds)
    let millisecsX10 = UInt8(timePassed * 100)

    let strMinutes = String(format: "%02d", minutes)
    let strSeconds = String(format: "%02d", seconds)
    let strMSX10 = String(format: "%02d", millisecsX10)

    timerLabel.text = "\(strMinutes):\(strSeconds):\(strMSX10)"

    if timerLabel.text == "06:00:00" {
        timer.invalidate()
        locationManager.stopUpdatingLocation()
        ConfirmTrialButton.isHidden = false
        ConfirmTrialButton.isEnabled = true
    }
}

func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
    if startLocation == nil {
        startLocation = locations.first as CLLocation!
    } else if let location = locations.last {
        let lastDistance = lastLocation.distance(from: location)
        distanceTraveled += lastDistance
        let trimmedDistance = String(format: "%.2f", distanceTraveled)
        metersLabel.text = "\(trimmedDistance) m"
    }

    lastLocation = locations.last as CLLocation!
}

1 个答案:

答案 0 :(得分:1)

你目前计算行走距离的策略是高估估计距离,可能会有很大的差距。

目前,您假设您始终可以将报告到locationManager(didUpdateLocations:)的最后位置与您的总行程距离相加。不幸的是,这不是一个安全的假设。

startUpdatingLocation的文档中,我们看到:

  

接收器主要在超出distanceFilter属性值时生成更新事件。但是,更新可能会在其他情况下提供。例如,如果硬件收集更准确的位置读数,接收器可以发送另一个通知。

设备的初始位置修复可能非常不准确。您收到的前几个位置更新可能并不表示设备的任何移动,而是指示越来越精确的测量。您至少应该考虑新位置的horizontalAccuracy,以确定您是否可以使用您收到的数据。例如。如果你得到10米相距10米的多次测量,但都精确到100米,你真的不知道设备是否移动了。

这里值得注意的是desiredAccuracy阻止了不准确位置的传递,它只是指明设备应该有多难以获得越来越准确的位置。

  

在请求高精度位置数据时,位置服务提供的初始事件可能没有您请求的准确性。定位服务尽快提供初始事件。然后,它会继续以您请求的准确度确定位置,并在数据可用时根据需要提供其他事件。

即使在最高精度下,CLLocation数据也会包含相当多的抖动。即使设备保持静止,计算每个报告位置之间的距离也会显示很多运动。相反,您可能希望收集所有报告的位置,并使用某种平滑或曲线拟合来估计实际的行进路径。

您想在这里使用的策略究竟取决于您可以对设备移动做出哪些假设。导航应用程序通常会将估计位置固定到已知道路。运行应用程序需要处理相当紧密的循环,以便它们可以跟踪在60米宽的轨道上运行。一个速降滑雪应用程序可能需要处理大量的横向移动,但能够在跑步过程中假设没有明显的上坡回溯。