Corelocation User Speed

CoreLocation User Speed

Core Location will give you a negative value for speed if the device isn't moving, or is moving slowly enough that the math doesn't make sense.

https://developer.apple.com/library/ios/documentation/CoreLocation/Reference/CLLocation_Class/#//apple_ref/occ/instp/CLLocation/speed

CoreLocation capturing speed

AFAIK kCLLocationAccuracyThreeKilometers‍ works using cell towers (and doesn't use GPS), which doesn't give you every second's information (that's why it's good for battery), nor it uses core Motion. Without GPS or coreMotion any speed calculated won't be considered accurate

So to answer your question, no it won't give you an accurate speed, but just to be on the safe side, just jump into a car and start logging. (Though remember to turn location services off for all other apps, because sometimes other apps with better accuracy could increase your app's accuracy)

Average speed and top speed of array CoreLocation

You just have to save all speed updates into an array yourself, which should be defined as a class instance property and you can define both average speed and top speed as computed properties so you don't need to update them manually every time you receive location updates.

let manager = CLLocationManager()
var speeds = [CLLocationSpeed]()
var avgSpeed: CLLocationSpeed {
return speeds.reduce(0,+)/Double(speeds.count) //the reduce returns the sum of the array, then dividing it by the count gives its average
}
var topSpeed: CLLocationSpeed {
return speeds.max() ?? 0 //return 0 if the array is empty
}

func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
let location = locations[0]
...

speeds.append(contentsOf: locations.map{$0.speed}) //append all new speed updates to the array

// m/s to km/h
let kmt = location.speed * (18/5)
let kmtLabel = Int(kmt)
statusLabel.text = "\(kmtLabel)"

// Top Speed
topSpeedLabel.text = "\(topSpeed)"

// Average speed
averageSpeed.text = "\(avgSpeed)"
}

Bear in mind that I didn't change the unit of either avgSpeed or topSpeed to km/h, if you need that, you can either do it before writing them to labels or rather before appending them to the array.

How can I get Swift to continuously update the speed

Use delegate's method https://developer.apple.com/reference/corelocation/cllocationmanagerdelegate

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

guard let speed = manager.location?.speed else { return }
speedLabel.text = speed < 0 ? "No movement registered" : "\(speed)"
}

Also you are calling this twice locationManager.startUpdatingLocation(), so you can remove one call

Displaying the speed the device is travelling at using CLLocationSpeed

I found this here on SO by @Leo

Swift: Exception while trying to print CLLocationSpeed "unexpectedly found nil while unwrapping an Optional value"
:

import UIKit
import CoreLocation
class ViewController: UIViewController, CLLocationManagerDelegate {
let locationManager = CLLocationManager()

override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
locationManager.delegate = self
if NSString(string:UIDevice.currentDevice().systemVersion).doubleValue > 8 {
locationManager.requestAlwaysAuthorization()
}
locationManager.desiredAccuracy=kCLLocationAccuracyBest
}

func locationManager(manager: CLLocationManager!, didUpdateLocations locations: [AnyObject]!) {
var speed: CLLocationSpeed = CLLocationSpeed()
speed = locationManager.location.speed
println(speed);
}

func locationManager(manager: CLLocationManager!, didChangeAuthorizationStatus status: CLAuthorizationStatus) {
if status != CLAuthorizationStatus.Denied{
locationManager.startUpdatingLocation()
}
}
}

then in your viewDidLoad, or wherever, you can make the label:

      myLabel = UILabel()
myLabel.text = "MySpeed: \(speed)"
self.addChild(myLabel)

Just make sure the 'speed' variable is in scope wherever you are trying to use it (I didn't demonstrate).

It compiled for me. Hope this helps. I haven't used it before, but with the Search function I'm confident I can learn most anything here :D

CLLocation speed

How about the code below which works from the delegate method.
Alternatively, if you did want to poll, then keep your previous location and check the distance changed from the last poll and use the manual method (also shown below) to calculate the speed.

Speed is calculated/provided in m/s so multiply by 3.6 for kmph or 2.23693629 for mph.

-(void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
//simply get the speed provided by the phone from newLocation
double gpsSpeed = newLocation.speed;

// alternative manual method
if(oldLocation != nil)
{
CLLocationDistance distanceChange = [newLocation getDistanceFrom:oldLocation];
NSTimeInterval sinceLastUpdate = [newLocation.timestamp timeIntervalSinceDate:oldLocation.timestamp];
double calculatedSpeed = distanceChange / sinceLastUpdate;

}
}

calculate the speed in kilometer/hour using core location framework

It looks like you are dividing meters to seconds, giving you meters per second.
Convert meters to KMS, and seconds to hours

double calculatedSpeed = (distanceChange / 1000) / (sinceLastUpdate / 60 / 60)


Related Topics



Leave a reply



Submit