What do horizontalAccuracy and verticalAccuracy of a CLLocation refer to? - ios

I've been working on a location based app recently and am noticing some strange values for CLLocation. I often get a horizontalAccuracy of 1414 and a verticalAccuracy of -1. Any clue what this indicates? As far as I can tell, these points are often very accurate. What is the difference between verticalAccuracy and horizontalAccuracy?

The -1 for verticalAccuracy indicates that the altitude in the CLLocation is not valid. You only get altitude with a 3D GPS position.
The 1414 for horizontalAccuracy indicates that the horizontal (lat/lon) position could be up to 1414m off (this is just an estimated error). This is probably a location determined by cell tower triangulation or WiFi location data. GPS locations usually report 100m or better.
To get a higher accuracy location (300m or better) you need to set desiredAccuracy and wait for the GPS receiver to lock onto at least 3 satellites (or 4 for a 3D fix). Until that happens CLLocationManager will give you the best it has which is WiFi or Cell tower triangulation results.

Related

How to show an iBeacon in a map

Once an app finds a beacon is possible to show both in a map (the device that found the beacon and the beacon itself)? If so how can i do that? I tried work with the distance bit with no success so far.
Unfortunately, you can't just find the exact location of an iBeacon once it's detected. You can only estimate its distance away from the device.
The proximity property tells you the relative distance (far, immediate, or close) that the beacon is away from the device while the accuracy property tells you how accurate that value is; so you can use proximity in combination with accuracy to get a general approximation of the distance. You could also potentially use these properties in combination with the RSSI, i.e. the received signal strength of the beacon, to further approximate the relative distance.
The device on the other hand can be mapped easily by turning on the map's showsUserLocation property.
I suppose your map is a MKMapView. If you know the precise location of the beacon (by having use a GPS to get the coordinates of the beacon when you have installed it) you can add an annotation on your MKMapView.
Take a look at MKMapView - (void)addAnnotation:(id < MKAnnotation >)annotation method for that.
If you don't have a database where to fetch the GPS coordinates of your beacons, there is no way to display them on a map as a beacon knows nothing about its surroundings.
By the way the accuracy property of a CLBeacon object isn't reliable enough for positioning.

Estimating distance to iBeacon on iOS

I'm trying to estimate the distance from an iOS device to an iBeacon. I am aware that distance estimation is not super accurate, and I am also aware of this formula:
https://electronics.stackexchange.com/questions/83354/calculate-distance-from-rssi
I have found, through some research, that an iBeacon's BLE advertisement in fact contains data that represents the calibration value. That is to say, the RSSI determined at 1 meter away is actually broadcast by the beacon for all to see.
Now, I think the iOS must internally use this information to determine the Near, Far, Immediate, and Unknown categorizations of distance but I am not aware of any way to access this 1-meter RSSI directly.
My question is simply: Is there a way to get the distance estimate between an iOS device and a beacon WITHOUT having the 1-meter calibration value saved on the iOS device beforehand?
Some people say that the 'accuracy' field of the CLBeacon class is, in fact, the distance measurement to the beacon. The documentation does not support this statement, here's what it says:
accuracy The accuracy of the proximity value, measured in meters from
the beacon. (read-only)
#property (readonly, nonatomic) CLLocationAccuracy accuracy;
Discussion Indicates the one sigma horizontal accuracy in meters. Use
this property to differentiate between beacons with the same proximity
value. Do not use it to identify a precise location for the beacon.
Accuracy values may fluctuate due to RF interference.
A negative value in this property signifies that the actual accuracy
could not be determined.
There is a new iBeacon Document released by Apple on June 2, 2014 that states:
When building an application that uses either GPS or
beacon, it is important to consider this accuracy. The values
reported by the Core Location objects (the
horizontalAccuracy property in the CLLocation class, or
the accuracy property in the CLBeacon class) indicate this
level of uncertainty, or the margin of error. Both are
measured in meters. The higher the value, the lower the
certainty of the position of the device or beacon. Keep in
mind that depending on the physical surroundings a low
accuracy may not be possible.
I suspect that's Apple's 'confidence' metric when reading their CLProximity values. I interpret that as obtaining something like:
CLProximityNear with an accuracy value of 5; Apple pinpoints your position within a 5m margin of error.
The general sentiment I'm getting from my general analysis of sources is that using beacon technology for distance approximation is probably not the strength of the technology.
EDIT: Chaise Hocking from Shine Technologies in Melbourne has an insightful blog post that has some experiments and results regarding the accuracy property.
Is there a way to get the distance estimate between an iOS device and a beacon WITHOUT having the 1-meter calibration value saved on the iOS device beforehand?
YES, you simply read the CLBeacon accuracy field as you suspected. This is an estimate of the distance to the beacon in meters.
This estimate uses an undocumented calculation that is based on the RSSI measurements (likely a 30 second running average, perhaps discarding outliers) combined with the 1-meter RSSI calibration value embedded in the iBeacon advertisement. A port of this calculation to Android is shown here.
And, no, there is no way to read the calibration value from an app. It is obscured by iOS, which disallows seeing the details of iBeacon Bluetooth LE advertisements. See here for a detailed explanation.

didEnterRegion called with larger radius (iOS)

I want didEnterRegion to be called with much precision, but I wasn't able to do so. Here is what I have done: I used the best values of distanceFilter and desiredAccuracy (most precise GPS settings according to Apple) and have a destination CLCircularRegion (Subclass of CLRegion).
self.locationManager.distanceFilter = kCLLocationAccuracyBestForNavigation;
self.locationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation;
#property (nonatomic, strong) CLCircularRegion *Destination;
self.Destination = [[CLCircularRegion alloc] initWithCenter:CLLocationCoordinate2DMake(43.907691, -69.963158) radius:5 identifier:#"Destination"];
[self.locationManager startMonitoringForRegion:self.Destination];
The problem is when I am like 150m away from this destination, didEnterRegion gets called. Also around similar distance away didExitRegion gets called. I want didEnter and didExit region to be called when I am 5 m away, not 150m away, as I have specified with initiation of CLCircularRegion. Does anyone have a solution? Precision is what I need, and 150m instead of 5m is too inaccurate for me. Thanks ton -
(I used iPhone 4S to Test)
While in theory accuracies of 5m are possible with the current GPS+ technical gear, it may be that Apple prevents such accuracy for region monitoring for various reasons.
One is that they always want a good user experience and the 5m accuracy you want is within the accuracy range you will often get from the GPS readings. Thus leaving such a small region could also be on account of lower accuracy readings while the user is still within the region. Apple does cover up for such errors by setting thresholds for posting regionEnter or regionExit notifications. From Apple documentation:
When testing your region monitoring code in iOS Simulator or on a device, realize that region events may not happen immediately after a region boundary is crossed. To prevent spurious notifications, iOS doesn’t deliver region notifications until certain threshold conditions are met. Specifically, the user’s location must cross the region boundary, move away from the boundary by a minimum distance, and remain at that minimum distance for at least 20 seconds before the notifications are reported.
The specific threshold distances are determined by the hardware and the location technologies that are currently available. For example, if Wi-Fi is disabled, region monitoring is significantly less accurate. However, for testing purposes, you can assume that the minimum distance is approximately 200 meters
Nevertheless since you can ask for high accuracy readings Apple should also take that into account. The alternative might be - as you commented - to use didUpdateLocation: and determine if inside or outside the region. That way you could include a test for location accuracy and only accept an exit/entry when horizontal accuracy is good enough.

Astronomical altitude from iOS device

How can I retrieve the astronomical altitude that an iOS device is pointed towards? The goal is to be able to point the devices camera at the sky and have it display the altitude.
Astronomical altitude is the angle between an object and the observer's local horizon. This is different then the altitude returned from the location manager. More info: http://en.wikipedia.org/wiki/Altitude_(astronomy)
There is no altitude or similar returned by a CLLocationManager.
What you need is CMMotionManager.
Start a timer with the readout frequency of your choice and read the attitude of your CMMotionManager. Remember to create only one instance of CMMotionManager.
The CMAttitude object has a property called pitch which gives you the rotation around a lateral axis that passes through the device from side to side. So basically it is the same as your desired altitude.

Check whether a CLLocation is based on GPS or cellular

With a 3G GPS device (i.e. iPad 3G) is there a way to know if a reported CLLocation is based on a GPS signal, and not the inaccurate cellular data?
The CLLocation class has a method called -horizontalAccuracy:. This will give you some idea of the radius of accuracy of that measurement. This is probably better than asking just "is it GPS" because GPS readings can also be pretty inaccurate, depending on receiving conditions and satellite visibility.

Resources