Calculating angle from latitude and longitude - r

I have a set of latitudes and longitudes , so this is the data for an animal as it moves in time. what i want to do is to calculate turning angle, that is by what angle it turns between every movement. so say i have point 1, point 2 and point 3 with latitude and longitude value corresponding to each point(animal moves from point 1 to point 2 to point 3 and so on) and i want to calculate the angle between these 3 points, point 2 being the middle point. what should i do? my OS is windows and i am using R for analysis.
so here is my sample data:
longitude latitude
36.89379547 0.290166977
36.89384037 0.290194109
36.88999724 0.286821044
36.88708721 0.288339411
36.88650313 0.29010232
36.88563203 0.289939416
36.88545224 0.290924863
they are in decimal degrees

Using the function trackAzimuth in maptools:
library(maptools)
trackAngle <- function(xy) {
angles <- abs(c(trackAzimuth(xy), 0) -
c(0, rev(trackAzimuth(xy[nrow(xy):1, ]))))
angles <- ifelse(angles > 180, 360 - angles, angles)
angles[is.na(angles)] <- 180
angles[-c(1, length(angles))]
}
The trackAzimuth function is a simple loop wrapper around gzAzimuth. See ?gzAzimuth for references on calculating directions on the sphere.
Using your data:
x <- read.table(text = "longitude latitude
36.89379547 0.290166977
36.89384037 0.290194109
36.88999724 0.286821044
36.88708721 0.288339411
36.88650313 0.29010232
36.88563203 0.289939416
36.88545224 0.290924863", header = TRUE)
trackAngle(as.matrix(x))
[1] 10.12946 111.17211 135.88514 97.73801 89.74684
EDIT: I had to remove first/last angles from the function, something I was doing after the fact with this function elsewhere. Should be right now. :)
Also, the packages adehabitatLT and argosfilter contain functions to calculate track directions and angles.

Your data points vary over only a small range. We can look at one small patch of Earth's surface and pretend it's flat, two dimensional. You have to figure out the scale of how many km, meters, miles, whatever your favorite unit is, corresponds to one degree of latitude, and for one degree of longitude. The latter depends on latitude - it'll be the same as the scale for latitude when near the equator, but if you are standing within arm's length of the north pole, one step will take you through fifty degrees. Set up x,y coordinates where x=0 is at longitude 36.88000, and y=0 is latitude 0.29000.
So, now you have a series of (x,y) points. Take the differences from each point to the next: P2-P1, P3-P2, etc. These could be called "displacement vectors" but other terms may be used in other fields than where i'm from. Call them V1, V2, etc. Use dot products and norms: dot(V1,V2) = magnitude(V1)*magnitude(V2)*cos(a) where a is the angle by which V2 deviates from the direction of V1. Repeat for V3 and V2, and so on.
R has all the tools to do this, but I don't know enough syntax of R to give examples.

Related

Trying to find lat lon given original lat lon + 3 meters

I have this problem I have to solve.
I am given a coordinate lat/lon, and I need to find a random point within 3 meters of this original point. Approximations are good, but all I could find was this https://gis.stackexchange.com/questions/2951/algorithm-for-offsetting-a-latitude-longitude-by-some-amount-of-meters that has a 10 meter error. Thank you.
Not sure what "find" and "random" mean in this question.
The earth is about 10 million meters from equator to either pole (that's actually how they defined the size of the meter, at first; it's been modified slightly since). The width of latitude lines doesn't vary, so one meter north or south is always is one ten-millionth of 90 degrees, or 9e-6 degrees, so just multiply that by the north-south displacement in meters of your desired point from the initial point and you'll get the number to add to the initial point in degrees: delta_lat = y_meters * 9e-6.
The width of longitude lines does vary, but it works out as simply east-west displacement in meters * 9e-6 = delta_lon * cos(lat), which means you can use the distance from your initial point to figure the east-west difference in degrees: delta_lon = x_meters * 9e-6/cos(lat).
You'll have to be careful with that last part around the poles, because cos(lat) will approach zero. Navigational systems use quaternions to do these things because they don't have singularities in spherical coordinates.

R spatstat: Units of distances retrieved by nndist

I’m ashamed bothering you with a stupid (but very necessary to me) question. I’ve a bunch of lat/lon points distributed almost randomly within a rectangle of ca. two x three degrees (latitude x longitude).
I need to calculate the maximum distance to the second nearest neighbor as well as the maximum distance to the farthest neighbor. I calculated these using package spatstat,
d2 <- max(nndist(data[,2:3], k = 2)
dn <- max(nndist(data[,2:3], k=(nrow(data))-1))
, respectively, and the distances obtained were 0.3 to 4.2.
I need these distances in kilometers.
So, I supposed that distances provided by nndist where expressed in radians.
So, if θ = a /r, where θ is the subtended angle in radians, a is arc length, and r is Earth radius), then, to calculate a the equations becomes: a = θr.
However, the distances transformed in such a way ranged from:
a = 6371 * 0.3 = 1911.3, and
a= 6371 * 4.2 = 2650.2
This is evidently wrong; since the maximum distance measured using – for example – Qgis between the farthest points is just 480 km…
Can anybody indicate me where am I mistaken?
Thanks a lot in advance!!!
nndist is simply calculating the euclidean distance. It does no unit conversion. As such you have given it values in "degrees", and thus it will return a value whose units are degrees. (not radians).
Thus
6371*0.3*pi/180 = 33.36
will give an approximation of the distance between these points.
A better approach would be to use great circle distances (eg in geosphere or gstat packages or to project the lat/long coordinates onto an appropriate map projection. (rgdal::spTransform will do this) and then nndist will calculate your distances in metres.

Location calculation- is UTM appropriate?

I'm wanting to calculate the location of point D, based on the location of point A B and C where I know the angle of point A relative to D and D relative to B and c relative to D.
In real terms, points A B and C are 3 locations i have marked with my GPS and point D is the location of a radiocollared animal I'm attempting to get a GPS location on. The angles I gain by knowing in which direction the radio collared animal is relative to north.
I've written the algorithm, but I know I can't put GPS co-ordinates straight into it and will have to convert them in and then out again. I've been googling, and I'm a bit confused, is the usage of cartesian or UTM more appropriate for this?
How do I go about converting GPS to UTM? I've searched and I'm a bit confused. Some conversions talk of degrees minutes adn seconds, my GPS appears to give me an additional number to this, so its N 68.21.446 and `w 12.14.284
Incase its relevant, I've assumed that the area is 2d in my calculations to make things a bit simpler.
Here is the code though I'm not sure it's needed:
#10/09/2013
#Enter your points for locations A B and C
#AN and AW is your first GPS points AA is the angle
AN<-10
AW<-0
AA<-45
#BN and BW are your second
BN<-10
BW<-0
BA<-0
#CN and CW are your third
CN<-0
CW<-10
CA<-90
#Convert these to ?
#work out distance
#For each co ordinate and angle, you need to calculate y=mx+c to make a line
#From these 3 lines, you can work out where they intersect
#If the angle is 0 it wont work, so make it very close to 0.
if(AA==0) {AA<-0.00001}
if(BA==0) {BA<-0.00001}
if(CA==0) {CA<-0.00001}
#Convert all angles to radians
AAr<-(AA*pi)/180
BAr<-(BA*pi)/180
CAr<-(CA*pi)/180
#Calculate M which is 1/tan(b)
AM<-1/tan(AAr)
BM<-1/tan(BAr)
CM<-1/tan(CAr)
#Calculate C the equation constant
#c=y-m*x
AC<-AW-AM*AN
BC<-BW-BM*BN
CC<-CW-CM*CN
#Caclulate intersections
#A and B
XAB<-(AC-BC)/(BM-AM)
YAB<-(AM*XAB+AC)
#B and C
XBC<-(BC-CC)/(CM-BM)
YBC<-(BM*XBC+BC)
#C and A
XAC<-(CC-AC)/(AM-CM)
YAC<-(CM*XAC+CC)
#Work out average of these 3 points
(XofABC<-(XAB+XBC+XAC)/(3))
(YofABC<-(YAB+YBC+YAC)/(3))
#Convert this back into GPS coordinate
`
UTMs are handy for this sort of operation as they're based on a square mapping datum and are flat 2D x-y cartesian system.
But beware of their limitations especially towards higher latitudes. And be careful that the system you choose is relevant to your location – some datum systems will be very warped if you use the wrong one.
Not sure why this is tagged in R?
Code looks like it should be fine.
Coordinate system transformations are done using the spTransform function in the rgdal package. You'll need to convert your coordinates to decimal degrees before you can convert them to UTM coords.
So, what is your "N 68.21.446" in decimal degrees? Well I'm not sure. Its 68 + (21/60) but you need to find out what the last number is. It might be a) thousandths of a minute (and if the first digit of it is ever 6 or more then that would seem likely) or b) two digits for seconds and then tenths of seconds.
For a) N 68.21.446 is then 68 + (21/60) + (446/1000)/60 decimal degrees.
For b) N 68.21.446 is then 68 + (21/60) + (44/3600) + (6/36000) decimal degrees.
You'll have to use some string matching functions to split it up.
Once you've got decimal degrees, create a spatial points dataframe with those numbers, set its CRS to your GPS coordinate system (probably EPSG code 4326) and then use spTransform to convert to your UTM code - use the one appropriate for your longitude.
Unless its polar bears or emperor penguins and the distances are not tens of km then the UTM coordinates should be a good approximation to a regular square grid. The bigger source of error is going to be your angular measurements!
On that subject, I did start writing an R package for doing location finding from radio direction finding equipment, implementing some of the statistical methods in the literature. You'll find that here: https://github.com/barryrowlingson/telemetr
If you have any comments on that package, address them to me via that github site, and not here on StackOverflow.

Shortest path on a sphere direction descision

I'm trying to write an algorithm that does the following.
Given a current position (in Azimuth and Inclination) and a target position (again in A, I) in what direction should I travel to travel over the shortest path. The return value could be something like a vector A = -1, I = +0.5, that I can then scale for step size/time.
The shortest path can be found by using a great circle, this is easy to visualize, but it's hard to implement like above because my coordinate system isn't continuous.
My coordinate system is as followed (imagine standing in front of the sphere)
The azimuth is 0 ~ pi when traveling along the equator along the front side, it's 0 ~ -pi when traveling along the equator along the rear side.
The inclination is 0~+pi when traveling from the top to the bottom of the sphere.
So given this non-continuous coordinate system, how do I create a decision function that says 'increase A' to travel over the shortest path?
You have a couple of alternatives. The first is to use a Haversine formulation. There is some Javascript source code here. It requires using more traditional lat / lon where the equator is at 0 latitude and the poles are at +/- π or +/- 90° latitude (depending on your units) and longitude is in the range [-180°, 180°) or [-π, π) again depending on your units. You can repeatedly find the midpoint until you have an approximate path that suites your needs. The azimuth / inclination vector would just be the difference in lat / lon between two adjacent points, though over time this will likely induce an error if you repeatedly apply those lat / lon deltas to the location of your agent.
Another approach that may work well for you is to transform your spherical coordinates of your starting and ending location to cartesian coordinates, call them points ub and ue for beginning and end points. The normal vector v of the great circle connecting the two points is the cross product of the two (i.e. v = ub x ue) and the angle θ is just the arccosine of the normalized inner product (ie. θ = cos-1( (ue ∙ ue) / (|ub||ue)). You can then use quaternion rotation and iterate from 0 to θ about the vector v to actually navigate the path. With this approach, the actual instantaneous vector at some point p along the path is just the p x v, or you can just approximate this by using the cartesian difference between two adjacent points along the path.

Triangulating GPS coordinates

Say you have n GPS coordinates how could you work out the central GPS point between them?
In case it helps anyone now or in the future, here's an algorithm that's valid even for points near the poles (if it's valid at all, i.e. if I haven't made a silly math mistake ;-):
Convert the latitude/longitude coordinates to 3D Cartesian coordinates:
x = cos(lat) * cos(lon)
y = cos(lat) * sin(lon)
z = sin(lat)
Compute the average of x, the average of y, and the average of z:
x_avg = sum(x) / count(x)
y_avg = sum(y) / count(y)
z_avg = sum(z) / count(z)
Convert that direction back to latitude and longitude:
lat_avg = arctan(z_avg / sqrt(x_avg ** 2 + y_avg ** 2))
lon_avg = arctan(y_avg / x_avg)
Depends on what you mean by the central GPS point. You could simply take the average of all the points, as suggested by Stephen - but keep in mind that GPS coordinates are not continuous - this will fail spectacularly around discontinuities such as the poles.
In most cases you'll need to convert to a coordinate system that doesn't have this issue.
You could also look at all the points bounded by it, calculated all the distances to each GPS point, and minimize the sum of the distances to all the GPS points. You'll need to look into great circle calculations for this.
Further, each GPS might have a higher or lower degree of uncertainty, you should take that into account and weight them accordingly.
What exactly are you trying to find out?
-Adam

Resources