How to calculate Cross-Track error (GPS/Core Location) - iphone

Does anyone know how to determine determine the "Cross-Track Error"?
For those who are unfamiliar: You are driving along a line from Point "A" to point "B". When in transit, when you veer off that line, the distance from your current position to the line is the cross-track error.
I have a simple algorithm now which works, using basic geometry with the latitude and longitude of the three points - the problem is that it does not take "great circle" calculations into account (i.e. actual meters-per-degree longitude varies depending on your latitude, and does not equal that of the latitude).
In other words - if you know of a "great circle" formula for determining this, please let me know - but it is not a straight Cartesian geometry problem.

Brad,
I'm not sure which ellipsoid model you are using since you don't say. If you aren't using an ellipsoid model in you current calculations, you may find this helpful:
http://www.movable-type.co.uk/scripts/latlong-vincenty.html
The Vincenty algorithm is more accurate that the Haversine algorithm.
Once you have accurate distances for A-B, A-C and B-C, it should be straightforward to determine your distance from C to the line A-B. Something like a binary search of the distances from points on A-B to C, looking for the shortest value.
James

This is this text from the link to the accepted answer - should it go dead:
Here’s a new one: I’ve sometimes been asked about distance of a point from a great-circle path (sometimes called cross track error).
Formula: dxt = asin( sin(δ13) ⋅ sin(θ13−θ12) ) ⋅ R
where:
δ13 is (angular) distance from start point to third point
θ13 is (initial) bearing from start point to third point
θ12 is (initial) bearing from start point to end point
R is the earth’s radius
JavaScript:
var δ13 = d13 / R;
var dXt = Math.asin(Math.sin(δ13)*Math.sin(θ13-θ12)) * R;
Here, the great-circle path is identified by a start point and an end point – depending on what initial data you’re working from, you can use the formulas above to obtain the relevant distance and bearings. The sign of dxt tells you which side of the path the third point is on.
The along-track distance, from the start point to the closest point on the path to the third point, is:
Formula: dat = acos( cos(δ13) / cos(δxt) ) ⋅ R
where:
δ13 is (angular) distance from start point to third point
δxt is (angular) cross-track distance
R is the earth’s radius
JavaScript:
var dAt = Math.acos(Math.cos(δ13)/Math.cos(dXt/R)) * R;

If dealing with latitude and longitude, the forumla you're looking for is the "Haversine" formula. It takes into account the curvature of the earth's surface.
http://en.wikipedia.org/wiki/Haversine_formula
Good luck.

The CLLocation API provides
- (CLLocationDistance)distanceFromLocation:(const CLLocation *)location
Which uses a formula (it does not specify whether is it Haversine or
Vincenty or other) that takes into account the curvature of the earth. This returns the distance in meters between the 2 CLLocations but does not account for any difference in altitude.

Related

How to find if a point is inside of a polygon using Racket

I am working an a project that, given a specific latitude and longitude coordinate, outputs the neighborhood that the point resides in. I have the latitude and longitude coordinates that make up the boundaries of several neighborhoods within a city. I have to read the neighborhood data from a file, and also read the test-points from a file. I am using the Racket programming language.
So far I have been able to read the files and create a list of points for each neighborhood, and now I am stuck. I wanted to create a polygon for each neighborhood, and then have a method that checks to see if a point lies inside that polygon. However, I cannot figure out how to do that using Racket.
Can anyone help me find out how to solve if a point is inside that polygon, or perhaps a better way to go about solving the problem?
I won't post any code for now because I don't want to solve the homework/assignment. However, I'll post some hints.
Look at the following picture:
How can we know that C is between the edges OA and OB and D is outside? It simple: we compare some angles: if the angle between OC and OA is smaller than the angle between OB and OA then C is clearly closer to OA than OB is.
Now, how do we get the angle knowing only some vectors? We can use the cosine which is monotonous: it decreases with the increasing argument. Thus, the cosine of the angle between OC and OA is greater than the cosine of the angle between OB and OA which is in turn greater that the cosine of the angle between OD and OA.
Next step is to figure out how to compute the cosine. The vector dot product helps: it's value is cosine of angle times greater than the product of operand's lengths. That is:
cos(OC; OA) = dotproduct(OC; OA) / (length(OA) * length(OC))
The dotproduct in 2D is simple:
dotproduct(OC; OA) = (C.x - O.x) * (A.x - O.x) + (C.x - O.x) * (A.x - O.x)
Combining all of the above you should have a simple test to check whether your point is in the same situation as C or as D: closer to one edge than the previous edge or not.
Now, you'll have to repeat this for every edge of the polygon and you're done. You can do this with a fold if the test is a predicate.
Note: this only works if the polygon is convex. For a concave polygon you'll need to add more tests.
Second note: In the figure, what will happen if D or C or both are below the OA line? Think about this and check if it means some more changes to the above fold method.
Last note: In a few weeks I'll post a complete code for that, assuming the assignment is over. Also, at that time I'll answer the question in the above note.
You need to start by collecting the segments of your polygon.
For the point P, you need determine if the horizontal ray starting from the point P intersects the side (segment).
If you count how many segments the point's horizontal ray intersects, then an odd number will be inside, and an even number will be outside.
(define (point-in-polygon? point polygon)
(odd?
(for/fold ([c 0]) ([seg polygon])
(+ c (if (ray-cross-seg? point seg) 1 0))))))
I have a complete solution in https://github.com/StevenACoffman/lat-long-kata-racket
An alternative Ray Casting Algorithm in Racket is https://rosettacode.org/wiki/Ray-casting_algorithm#Racket as well as in 35 other programming languages.
A more detailed walkthrough is available: https://www.geeksforgeeks.org/how-to-check-if-a-given-point-lies-inside-a-polygon/

Dividing a geographic region

I have a certain geographic region defined by the bottom left and top right coordinates. How can I divide this region into areas of 20x20km. I mean in practial the shape of the earth is not flat it's round. The bounding box is just an approximation. It's not even rectangular in actual sense. It's just an assumption. Lets say the bottomleft coordinate is given by x1,y1 and the topright coordinate is given by x2,y2, the length of x1 to x2 at y1 is different than that of the length between x1 to x2 at y2. How can I overcome this issue
Actually, I have to create a spatial meshgrid for this region using matlab's meshgrid function. So that the grids are of area 20x20km.
meshgrid(x1:deltaY:x2,y1:deltaX:y2)
As you can see I can have only one deltaX and one deltaY. I want to choose deltaX and deltaY such that the increments create grid of size 20x20km. However this deltaX and deltaY are supposed to vary based upon the location. Any suggestions?
I mean lets say deltaX=del1. Then distance between points (x1,y1) to (x1,y1+del1) is 20km. BUt when I measure the distance between points (x2,y1) to (x2, y1_del1) the distance is < 20km. The meshgrid function above does creates mesh. But the distances are not consistent. Any ideas how to overcome this issue?
Bear in mind that 20km on the surface of the earth is a REALLY short distance, about .01 radians - so the area you're looking at would be approximated as flat for anything non-scientific. Assuming it is scientific...
To get something other than monotonic steps in meshgrid you should create a function which takes as its input your desired (x,y) and maps it relative to (x_0,y_0) and (x_max,y_max) in your units of choice. Here's an inline function demonstrating the idea of using a function for meshgrid steps
step=inline('log10(x)');
[x,y]=meshgrid(step(1:10),step(1:10));
image(255*x.*y)
colormap(gray(255))
So how do you determine what the function should be? That's hard for us to answer exactly without a little more information about what your data set looks like, how you're interacting with it, and what your accuracy requirements are. If you have access to the actual location at every point, you should vary one dimension at a time (if your data grid is aligned with your latitude grid, for example) and use a curve fit with model selection techniques (akaike/bayes criterion) to find the best function for your data.

Equation for distance between two points on the map using latitude and longitude iphone

I am trying to calculate the distance between two points (Pins) on the iPhone map.
Everything works fine however if you put one of the pin close to the left edge and the other one to the right edge of the map, distanceFromLocation method always returned the shortest distance between points (of course earth is not flat). I tried switching the CLLocations but it still shows me the shortest distance.
For my app I will need to calculate both, shortest and the longest distance between two pins.
The problem seems to be trivial but I can't come out with anything to solve it.
Any help or clues appreciated. Thanks!
There is a function MKCoordinateRegionForMapRect that returns a MKCoordinateRegion. Without having tried it, seems like all you would need to do is accurately specify the rect as the region bounded at one diagonal by one pin and the other diagonal by the other pin. You could use CGRectUnion twice giving the pin origins as rect origin and an arbitrarily small width and height.
Then the distance between the pins will be the square root of the distances represented by the latitudeDelta and longitudeDelta returned in the span squared and added. (i.e. Pythagoras theorem, the two side lengths are the horizontal and vertical sides of a triangle and the diagonal is a straight line between your points.)
Finding latitudeDelta in metres is easy, each degree of latitude is 111km.
To find meters for the longitudeDelta you need a little bit more code.
#define EARTH_EQUATORIAL_RADIUS (6378137.0)
#define WGS84_CONSTANT (0.99664719)
#define degreesToRadians(x) (M_PI * (x) / 180.0)
// accepts decimal degrees. Convert from HMS first if that's what you have
double lengthOfDegreeLongitude(double degrees) {
double tanDegrees = tanf(degreesToRadians(degrees));
double beta = tanDegrees * WGS84_CONSTANT;
double lengthOfDegree = cos(atan(beta)) * EARTH_EQUATORIAL_RADIUS * M_PI / 180.0;
return lengthOfDegree;
}
Give that function the longitude of the location you are interested in and multiply the result by the longitudeDelta in degrees to get a distance in meters. Then you have a horizontal distance and a vertical and you can find the diagonal which is what you were looking for.
Inaccuracy will get bad if you are looking for a distance which is very large in N-S as the length of a degree longitude will be varying over the calculation. And you can refine the 111km for a degree of latitude a bit too, that's just from memory.

How to determine if a latitude & longitude is within an ellipse

I have data describing a rotated ellipse (the center of the ellipse in latitude longitude coordinates, the lengths of the major and minor axes in kilometers, and the angle that the ellipse is oriented). I do not know the location of the foci, but assume there is a way to figure them out somehow. I would like to determine if a specific latitude longitude point is within this ellipse. I have found a good way to determine if a point is within an ellipse on a Cartesian grid, but don't know how to deal with latitude longitude points.
Any help would be appreciated.
-Cody O.
The standard way of doing this on a Cartesian plane would be with a ray-casting algorithm. Since you're on a sphere, you will need to use great circle distances to accurately represent the ellipse.
EDIT: The standard ray-casting algorithm will work on your ellipse, but its accuracy depends on a) how small your ellipse is, and b) how close to the equator it is. Keep in mind, you'd have to be aware of special cases like the date line, where it goes from 179 -> 180/-180 -> -179.
Since you already have a way to solve the problem on a cartesian grid, I would just convert your points to UTM coordinates. The points and lengths will all be in meters then and the check should be easy. Lots of matlab code is available to do this conversion from LL to UTM. Like this.
You don't mention how long the axes of the ellipse are in the description. If they are very long (say hundreds of km), this approach may not work for you and you will have to resort to thinking about great circles and so on. You will have to make sure to specify the UTM zone to which you are converting. You want all your points to end up in the same UTM zone or you won't be able to relate the points.
After some more research into my problem and posting in another forum I was able to figure out a solution. My ellipse is relatively small so I assumed it was a true (flat) ellipse. I was able to locate the lat lon of the foci of the ellipse then if the sum of the distances from the point of interest to each focus is less than 2a (the major axis radius), then it is within the ellipse. Thanks for the suggestions though.
-Cody

Coordinates from angle and distance in iPhone

In my iPhone app, suppose I have the coordinates of the current location. I want to know the coordinates of a point 10km from here, and 30° North East for example. How do I calculate it? Thanks.
After typing a bunch of formulae out, I realized there's a site that already has it down, so I'm just going to link that instead, Calculate distance and bearing between two Latitude/Longitude points. The section titled "Destination point given distance and bearing from start point" is what you want. Just convert the degrees to radians (your bearing) and you'll be all set