CoreLocation capturing speed - ios

I am capturing location data using CLLocationManager. I am less concerned about horizontal accuracy, but I want the speed to be as accurate as possible.
Anyone know if kCLLocationAccuracyThreeKilometers will be sufficient for my use case or do I have to use kCLLocationAccuracyBest to get the most accurate speed?
Thanks.

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)

I stuck in same issue in one of my Map Based application and i solved this way ( while traveling through Delhi Metro even i tested) and its working fine :
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
//Get Current Location
let location = locations.last! as CLLocation
let userLocation:CLLocation = locations[0] as CLLocation
// For getting speed
let speed = location.speed * 2.23694
lblSpeed.text = (location.speed<0) ? "-- \n mph" : String(format: "%d \n mph", Int(speed))
locationManager.startUpdatingHeading()
}
Accuracy is perfect in kCLLocationAccuracyBest
locationManager.desiredAccuracy = kCLLocationAccuracyBest
Feel free to provide your feedback after using this code . Hope it solve your issue . Keep Coding

TLDR; kCLLocationAccuracyBest is the way to go.
For details, see https://stackoverflow.com/a/737968/190599

Related

Shorter time interval for location updates

My app is highly based on CLLocation timestamp. I found that CLLocationManager updates location in ~1s intervals. It's not enough for my app. Is it possible to configure CLLocationManager to update location in shorter intervals or should I look for other approach (timers + ask manually for location)?
locationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation
locationManager.allowsBackgroundLocationUpdates = true
locationManager.distanceFilter = kCLDistanceFilterNone
if #available(iOS 11.0, *) {
locationManager.showsBackgroundLocationIndicator = true
}
locationManager.startUpdatingLocation()
timer + requestLocation() doesn't work.
You cannot change frequency of updates. But you probably don't need that. You can calculate phone position by using CMMotionManager framework and you can get the user location using CLLocationManager framework.
Use accelerometer to calculate device movement. From didAccelerate method you can get x, y and z of move, so by applying this to detected user location you can calculate new device position.
Hope this helps and good luck.
You cannot change the frequency of location update. The location service will only update if the value of distanceFilter is exceeded.
If you want to force location update, try changing the value of distanceFilter (in meters, double data type). You can use kCLDistanceFilterNone as a value for distanceFilter.
Try like:
locationManager.distanceFilter = kCLDistanceFilterNone
This code will force the location service to notify you if there is any small change in location or every movement.

Is geofence accuracy dependent on locationManager’s accuracy or distance filter?

Is geofence accuracy dependent on locationManager’s accuracy or distance filter? Or they are independent of each other because geofence is managed by the OS and uses Wifi/Cell tower info?
For example:
locationManager
locationManager.distanceFilter = 1250;
locationManager.desiredAccuracy = kCLLocationAccuracyKilometer;
region
let title = "Lorrenzillo's"
let coordinate = CLLocationCoordinate2DMake(37.703026, -121.759735)
let regionRadius = 550.0
let region = CLCircularRegion(center: CLLocationCoordinate2D(latitude: coordinate.latitude,
longitude: coordinate.longitude), radius: regionRadius, identifier: title)
The 550 (radius) is less than kCLLocationAccuracyKilometer...so would the geofence trigger as expected?
From what I understand the distanceFilter has no effect on the geofence’s accuracy.
I’m just not sure if the desiredAccuracy of the manager would affect geofence’s accuracy.
The question makes no sense; you are comparing apples and tigers. Geofencing and your app's location manager have nothing at all to do with each other.
Geofencing using a circular region is performed for you by the system. Your location manager doesn't do any geofence-related locating. The system does not use, and knows nothing of, your app's location manager or its settings; indeed, your app will probably not even be running.
(You will, of course, need a location manager in order to have a location manager delegate so that you can receive callbacks from the system when the user crosses the geofence boundary, but your location manager is still not doing any locating related to geofencing.)

how to get the most accurate user speed on iOS

I'm new to iOS developing. Can please anyone tell me the most accurate way to get the user speed in iOS. CLLocation speed doesn't seem to be correct.
Here is my code to get the speed
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
var speed: CLLocationSpeed = CLLocationSpeed()
speed = (locationManager.location?.speed)!
print("speed - ", speed * 3.6)
Moving speed calculated using 'CLLocation' won't be accurate since you need the location to be updated continuously which would take a lot of resources. Hence, CLLocation updates the location based on intervals.
If, for whatever reason, you want the speed to be updated continuously, you need to look into Accelerometer and Gyroscope. By using the values from both and with some data manipulation, you can get a more reasonable value for the current speed.
NOTE
Keep in mind that doing so will take a toll on your device's resources and is not the best approach.

kCLLocationAccuracyBestForNavigation vs kCLLocationAccuracyBest

I am building a speedometer app that shows the current speed a user is traveling. I would like to display the most accurate speed possible and therefore I am trying to figure out if I should use kCLLocationAccuracyBestForNavigation or kCLLocationAccuracyBest.
According to Apple's documentation, kCLLocationAccuracyBestForNavigation uses the highest possible accuracy and combine it with additional sensor data while kCLLocationAccuracyBest uses the highest level of accuracy but has no mention of sensor data. Does anyone know what this additional sensor data is and if it is used for calculating a more accurate speed?
I'm getting the speed from a CLLocation object.
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
for location in locations {
let speed = location.speed
...
}
}
kCLLocationAccuracyBestForNavigation uses accelerometer, gyro, wifi and cell towers.
As you are aiming to get best precision of speed I suggest you to use this constant.
Remember that this is also the most battery consuming.
Your callback seems correct to what you're expecting.
I have a suspicion!
My GPS tracker is using kCLLocationAccuracyBestForNavigation (with CLActivityTypeOther). To me it seems like kCLLocationAccuracyBestForNavigation would cause the location manager to also look up map data. When I ride my bike, the location manager sometimes reports locations that match the road beside me. But I am a not riding on that road...
Next I'll try kCLLocationAccuracyBest and see, whether or not this constant stops that rubbish.

Accuracy of "Region Monitoring" on iOS 6

I'm trying to make a location-based app that requires constant updating of the location after opening. I was looking for a way to keep the location in the background when the app is closed and I found that is not the best way because it would drain the battery very quickly from any iPhone.
To cut a long story short I found with the "Region Monitoring" as I have understood they are the same as Apple uses for their App "Reminders" that also works with location. Then I used that option to test my app and I realize that in the simulator "never" enters the method "didEnterRegion" despite it is correctly created:
-(void) locationManager: (CLLocationManager *) manager didEnterRegion: (CLRegion *) region
{
NSLog (# "entering the region");
CLLocation * location1 = manager.location;
CLLocation * location2 = [[CLLocation alloc] initWithLatitude: latitud.doubleValue longitude: longitud.doubleValue];
}
I finally realized that the method is called but only when I walked away much of the area and I was back to the area, indicating that it did not work because I was already in that location (all this in the simulator), the strange thing is that it was not, the location of the simulator was miles from the region to monitor! Which leads me to think it is problem of accuracy, despite creating the region with 50 or 100 meter radius was spreading the 3 or 4 km, so I was useless.
Has anyone experienced this knows if iOS 6 simulator has this error or if precision problem? I don't have a Developer Licence yet to test it directly on my iPhone and I do not want to buy it yet because my app is far from finished, I appreciate any help on this topic.
Thanks in advance.
I would suggest doing actual ground testing. Region monitoring accuracy varies a lot depending on the test location.
Second option is to use region monitoring to just wake up the app and start standard location service. To do this you need permission to run the app in background. Apple may not approve this. Our app got rejected using this approach.
DidEnterRegion and ExitRegion is not very accurate. Around +, - 150m accuracy.
But -(void) locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
is very accurate. Use this to find out your regions have coordinates/current location
CLLocation *currentLocation = [locations lastObject];
if ([self.ARegionYouSetBeforeHand containsCoordinate:currentLocation.coordinate])
{
//you arrived at this region!!
}
Region monitoring works (generally) on the same basis as the "significant location change" location service. That is, it uses cell tower location; Apple suggests you can usually expect accuracy around 1km, but warns that actual accuracy will vary with the density of cell towers in your area. You can find more background on this topic in the WWDC videos on Core Location.
It might be feasible -- I haven't tried -- to use Region Monitoring to (wake up your app and) get a general guess at the user's location, then use a higher accuracy mode in CLLocationManager to get a more precise fix.
At finish I realize that the accuracy of Region Monitoring is good enought for the most purposes, but in the simulator can be tricky because it not have GPS or cellphone hardware, anyway when I used "region monitoring" in my device even in a simulation route the function works correctly.
And for more accuracy even, I invoked the method "startUpdatingLocation" of the CLLocationManager into the method "didEnterRegion", that works okey for me.
I have experienced the same issue with Region Monitoring on iPhone 5C with cellular tower mobile data, disabling the WiFi, I was used to get didEnterRegion called very soon, when I was 1.95 Km away from the monitoring point for which I kept region radius of 100.0 meters. Which is too early.
Apple has some Threshold value determined by the hardware and the location technologies that are currently available. So for me it might be around 1800 meters early value.
I suggest to keep radius minimum (say 25.0 for 500.0 region) OR if it is so precious notification, use didUpdateLocations delegate method and determine your region and notify the same.
Regards,
Kaushik
I found that the built in region monitoring wasn't accurate enough for my needs. If you need higher accuracy, first set your accuracy appropriately, and then you can use something like this:
(Uses the same method as #coolcool1994, but a little more in-depth and using Swift 2.1. Remember to set up CLLocationManager and its Delegate (where the functions below would reside), and start receiving location updates)
var activeRegions = Set<String>()
var monitoredRegions = [
CLCircularRegion(center: CLLocationCoordinate2D(latitude: 0.0, longitude: 0.0),
radius: 300, identifier: "Region1"),
CLCircularRegion(center: CLLocationCoordinate2D(latitude: 0.0, longitude: 0.0),
radius: 300, identifier: "Region2")
]
func manuallyUpdateActiveRegionsFromLocation(location: CLLocation){
// Optionally explicitly reject unwanted location updates
// Setting the location manager delegate's desiredAccuracy should be enough
let maxOldTime = 300 //5 minutes
let minAccuracy = 300 //300 metres
if abs(location.timestamp.timeIntervalSinceNow) > maxOldTime
|| location.horizontalAccuracy > minAccuracy {
return
}
for monitoredRegion in monitoredRegions {
if monitoredRegion.containsCoordinate(location.coordinate) {
activeRegions.insert(monitoredRegion.identifier)
} else {
activeRegions.remove(monitoredRegion.identifier)
}
}
}
func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
if let location = locations.last {
manuallyUpdateActiveRegionsFromLocation(location)
}
}
Pre-Defined GPS Accuracy on MK MapView
kCLLocationAccuracyBestForNavigation – Uses the highest possible
level of accuracy augmented by additional sensor data.
kCLLocationAccuracyBest – The highest recommended level of
accuracy for devices running on battery power.
kCLLocationAccuracyNearestTenMeters - Accurate to within 10 meters.
CLLocationAccuracyHundredMeters – Accurate to within 100 meters.
kCLLocationAccuracyKilometer – Accurate to within one kilometer.
kCLLocationAccuracyThreeKilometers – Accurate to within three
kilometers.
Usage:
var locationManager: CLLocationManager = CLLocationManager()
//MapView Location
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters
locationManager.requestWhenInUseAuthorization()
locationManager.startUpdatingLocation()
locationManager.startUpdatingHeading()

Resources