This is my first time posting a question here, but I have found a lot of help from other people's questions.
My question refers to the -distanceFromLocation: function in CLLocation. I had assumed that finding the distance between point A and point B would be the same as that between point B and point A, but I have found that it is not. I have tested this in a very simple case:
CLLocation *test1 = [[CLLocation alloc] initWithLatitude:37.529530 longitude:-122.259232];
CLLocation *test2 = [[CLLocation alloc] initWithLatitude:47.900002 longitude:-103.495102];
NSLog(#"%f vs %f",[test2 distanceFromLocation:test1],[test1 distanceFromLocation:test2]);
[test1 release];
[test2 release];
The output to this was 1907269.942754 vs 1908105.959114, a difference of almost 900 meters.
Though 900 meters may be a small percentage, I am trying to determine if the user is closer to something than an annotation and 900 meters can change that.
My question is, which one of these values, if any, is correct? Also if which location I test against is important, do I need to always test against the same location (e.g. user to destination and annotation to destination rather than destination to user and annotation to destination)?
Sorry that the sample is a bit out of context, as my project is rather large and this illustrates my problem. Any help would be appreciated as this has caused me quite a bit of confusion and frustration.
The error you're observing is 1 part in 2000. Presumably the algorithm used in this method is optimized for speed, so sorting a list of locations on distance is fast, rather than accurate to the millimeter.
If you need accurate results, don't use these methods but find another way. If you need reproducible results, order the arguments in a defined way, e.g. always start with the lower latitude.
Related
I'm trying to find out what's wrong but it seems like the mentioned method is just returning wrong values. I'm setting coordinates in simulator, then just print them and calculate distance:
(lldb) p location.coordinate
(CLLocationCoordinate2D) $1 = (latitude = 51, longitude = 0.10000000000000001)
(lldb) p _oldLocation.coordinate
(CLLocationCoordinate2D) $2 = (latitude = 51, longitude = 0)
Now I'm calculating distance:
distance = (CGFloat)[location distanceFromLocation:_trackEndLocation];
And when I print it i get:
(lldb) po self.trackDistance
7019.76758
Now, the problem is that users tell me that app returns too big distance. As I wanted to debug it, I've checked the distance at page to calculate distance between two points.
The results are as following:
As you can notice, the distance according to the webpage is 6.997km while Apple method tells me 7.019km. I wonder who is incorrect, Apple or the webpage and what to do with this matter. The difference isn't big, but when you accumulate it between few points it can be disturbing.
The Apple doc page for distanceFromLocation says this:
This method measures the distance between the two locations by tracing a line between them that follows the curvature of the Earth. The resulting arc is a smooth curve and does not take into account specific altitude changes between the two locations.
I suspect Google Maps does consider the terrain between the two points, and that's why you saw a 0.3% difference in your test. However, I doubt your customers are complaining about that level of error. It's more likely the error is from a different cause.
Without knowing more about your algorithm it's hard to say, but if you're tracking distance traveled, the error might be caused by jitter in the phone's GPS coordinates. (That would cause a straight line path to look like a zigzag, which would yield a longer distance.) You could record some real data from your app to see for sure.
The problem was that I was checking the accuracy and filtered some results out if the accuracy was bad. That's why sometimes the distance was wrong. I've fixed the accuracy filtration and everything is working fine.
Hello I'm a little confused about the answer I found here. The answer says that by increasing the length of the string you can increase the accuracy, which I understand. What I don't understand is how he is getting the numbers for the accuracy that he gets. He goes from a 110km x 110km to a 10km x 10km area by adding a digit. I want to get a 5m x 5m area. Can some give a more in depth explanation of how he got these figures.
Basically, he is talking about the accuracy of a specified point.
For example if we have a Location which we are interested, and we have two points defining that same location
- point1(156.34,-23.34), and
- Point2(156.342,-23.343)
So effectively the first point is somewhere between Latitude (156.335 - 156.344), Logitude (-23.335 - -23.344), and the second point Latitude (156.3415 - 156.3424) and Logitude (-23.3425 - -23.3434).
Basically normal GPS might get to near that 5 meter accuracy, though most often its anyway going to be less accurate, thus, what you need to to, is simply to use the whole value you get from the positioning module.
I'm wondering if there is a way to check if a user is actually at a specific location or not (or maybe within 50-100 feet of it). I have a CLLocationCoordinate2D defined and I know I can check my mapView.userLocation.coordinate.latitude and mapView.userLocation.coordinate.longitude, but I'm not sure what the best way to check this would be.
Basically you just have to compare the lat lon and calculate the distance. Luckily, iOS has a built-in method for that inside the CLLocation class.
Here is a simple way to do it.
CLLocation* location = [[CLLocation alloc] initWithLatitude:marker.coordinate.latitude longitude:marker.coordinate.longitude];
CLLocationDistance distance = [location distanceFromLocation:userLocation];
the returned value is in meters which you can then easily convert to feet or any other unit of measurement that you are interested in.
Here is the documentation for reference
So I have some code that gets the user's location from the phone as a CLLocation, then I do a reverse geocode on it. The problem is that the resulting MKPlacemark has 0 for altitude, despite the fact that the CLLocation had a value in the altitude field.
It makes sense that if I just ask for the address of some coordinates, I don't necessarily get altitude (as that would require topographic logic). Most of the questions on here suggest calling out to a topo service.
I am wondering why the reverse geocoder would not just preserve the altitude, and also asking people what their preferred solution has been to this problem. It's not like it's hard to figure out: I can pass the altitude in separately and then just jam it into my ultimate object (my own address class), but that's ugly.
This is indeed the state of these classes at this time. Probably a bug report with Apple is in order.
I'm trying to call a function in case the distance traveled since last checked is > 30 m. Based on the Class description of CLLocationDistance the value returned is in m.
I use this code:
[locationManager startUpdatingLocation];
if (!startingLocation)
startingLocation = locationManager.location;
// NSLog(#"Latitude:%f Longitude:%f", startingLocation.coordinate.latitude, startingLocation.coordinate.longitude);
updatedLocation = locationManager.location;
CLLocationDistance distance = [updatedLocation distanceFromLocation:startingLocation];
if (distance > 30) {
NSLog(#"%f",distance);
NSLog(#"Latitude:%f Longitude:%f", updatedLocation.coordinate.latitude, updatedLocation.coordinate.longitude);
[self stop];
The console output with NSLog returns 7946754.993111, and I did not even touch the phone.
Any suggestions are appreciated!
8000 km between two points? I'll bet the first point is 0, 0 and you're about 8000 km from there, right?
In any case be sure to only use valid locations by checking to make sure the horizontalAccuracy is >=0 before using the location coordinates. Invalid locations have a negative horizontalAccuracy.
Also, you should probably discard any cached locations by checking the age of the location data and don't use it if it is more than a few seconds old.
See the sample code here that does these checks.
Another thing to watch out for is that you can get locations that show false motion due to changes in accuracy. See this answer for details.
Is it possible that because you are calling startUpdatingLocation then getting that location then immediately asking for an update that the location is still trying to figure out exactly where it is, hence the big movement.
Try calling startUpdatingLocation from another method then implement the delegate method from CLLocationManager locationManager:didUpdateToLocation:fromLocation to get the movement.