0

I have yet to find useful information on GPS sample/output rate in iPhones. Please direct me to any useful and relevant articles I missed. Also please let me know how to make my post more clear.

Actual behavior: iPhone XR outputs GPS samples at slow rates, around one sample every 6 seconds, but occasionally with two samples in a more rapid succession (e.g. 1.5 seconds, although very seldomly). This occurs when sitting still, when quickly walking and shaking phone around around, and with various different assignments for CLLocationManager.desiredAccuracy.

Expected/optimistic behavior: Quicker GPS sample outputs from my iPhone XR, like those in this video right here. I am aware that this video is from 2017, although I don't know what makes this significant. https://www.youtube.com/watch?v=XyncTJdXbbw&t=5m20s

Discussion: I need GPS samples for a project, and I'd ideally like it to be sampled at 1.0+ Hz. I have written programs on Swift and downloaded apps which log and graph my iPhone XR's GPS data, but my sampling rate of my GPS data seems to be inconsistent and very slow, around one measurement every 6 seconds.

I have a lot of questions, which include:

  • Does iPhone XR have a well-defined GPS output rate?
  • What factors affect it?
  • Where can I find this information better documented?
  • How can I increase the output rate of the GPS?

I am new to working with iOS as well as knowing through what methods iPhones calculate GPS coordinates. I have heard that iPhone GPS can output data at 1 Hz, although I haven't found this officially documented yet.

I am aware I can specify the desiredAccuracy and distanceFilter in my Swift program, but the desiredAccuracy parameter seems not to have much effect on my coordinate precision or my output rate. My iPhone XR is on iOS 13.4.1, and my 128 GB phone is almost completely full with photos in case that makes some weird difference. I'm removing those photos just to clean up now.

I included my Swift program below. It is very basic, and I don't know how to code in Swift, so feel free to inform me if I'm doing things incorrectly. At the last time I ran it successfully (two days ago), my iPhone was on iOs 13.3 or so, Mac OS on 10.13 or so. The Swift program should be as basic as possible, single-view app with storyboard UI. If necessary, I can provide updates on newer OS/iOS/Xcode versions once I clean my phone and get some stuff to work.

I can't find my console output text file, so I'll upload something once I am able to. I suppose answer with the assumption that my output occurs every 6 +/- 0.05 seconds.

//
//  ViewController.swift
//  CoreMotionExample
//
//  Created by COVID-19 on 11/17/19
//  Copyright © 2019 COVID N. Teen. All rights reserved.
//
import UIKit
import CoreMotion
import CoreLocation

class ViewController: UIViewController {

    let motionManager = CMMotionManager()
    let locationManager = CLLocationManager()
    var timer: Timer!
    let start = Date()
    var time_prev = 0.0
    var elapsedTime = 0.0

    let verbose = false;


    override func viewDidLoad() {

        super.viewDidLoad()

        motionManager.startAccelerometerUpdates()
        motionManager.startGyroUpdates()
        motionManager.startMagnetometerUpdates()
        motionManager.startDeviceMotionUpdates()

        locationManager.requestAlwaysAuthorization()
        locationManager.delegate = self
        locationManager.desiredAccuracy = kCLLocationAccuracyBest
        locationManager.distanceFilter = kCLDistanceFilterNone
        locationManager.startUpdatingLocation()


        timer = Timer.scheduledTimer(timeInterval: 0.01, target: self, selector: #selector(ViewController.update), userInfo: nil, repeats: true)

        }



    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {

            if let location = locations.first
            {
                if(true)
                {
                    print(location.coordinate, "\n")
                    elapsedTime = time_prev - start.timeIntervalSinceNow
                    print("Time elapsed: ", elapsedTime, "\n")
                    time_prev = start.timeIntervalSinceNow
                }
            }
    }



    @objc func update() {


//      IMU/MARG/INS data:

        if let accelerometerData = motionManager.accelerometerData
        {
            if(verbose)
            {
                print("Accelerometer data:\n",accelerometerData, "\n")
            }
        }

        if let gyroData = motionManager.gyroData
        {
            if(verbose)
            {
                print("Gyroscope data:\n", gyroData,"\n")
            }
        }

        if let magnetometerData = motionManager.magnetometerData
        {
            if(verbose)
            {
                print("Magnetometer data:\n", magnetometerData,"\n")
            }
        }

        if let deviceMotion = motionManager.deviceMotion
        {
            if(verbose)
            {
                print("deviceMotion data:\n", deviceMotion,"\n")
            }
        }

        //GPS/Location data:
        //Nothing successful here, see above

    }


}

extension ViewController: CLLocationManagerDelegate {
  // handle delegate methods of location manager here, also nothing here
}

1 Answer 1

1

There's no way of explicity setting the update rate of your location. Note that you're not "communicating" directly with a GPS, but rather receiving location updates from Core Location that could come from a GPS source, but also from other sources.

Remember that the location updates are filtered to conserve power. This means that you only get updates when the phone has actually moved a certain distance - and the number of updates can be affected by external factors such as whether or not the phone is set in the power save state. Also remember to test this while outside and moving about. You won't get great positioning indoors.

You should ensure to set the distance filter to an appropriate distance for your application (you currently have it set to none), and also to set the correct activity (i.e. you currently have it set to other, but if you want to do for example automotive navigation, then set it to that).

In your attached source code, you only look at the first location given to you in didUpdateLocations. You normally don't want to do that. The newest location is the last one in the array, so I would at least change it to look at the last one.

As you are interested in having more locations over a time period, remember to look at all the updates in the array. There might be more than one in each update.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .