Finding location points where travel angle changes using R?

I want to use R to find out the point locations at which my vehicle (equiped with GPS) started to turn. The data contains coordinates and time information. I have sort my data based on time sequence:

time_stamp <- as.POSIXct(paste(field\$Date, field\$Time), format="%d/%m/%Y %H:%M:%S")
field <- data.frame(field,time_stamp)
field <- field[order(field\$time_stamp),]

Then I borrow the codes from post below to calculate the angles of each three sequential points: https://stackoverflow.com/questions/11184381/calculating-angle-from-latitude-and-longitude

And modified it a little bit.

# define coordinates

coordinates(field) <- c("Longitude", "Latitude")
proj4string(field) <- CRS("+init=epsg:4326")

# calculate angles

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))]
}

ang <- trackAngle(field@coords)

# Just to make it the same length as my dataset
# I inserted the first and the last angles to the vector

ang <- c(ang,ang,ang)

Now I am thinking to use if-else statement, says if at this point the angle is bigger than 20 degree compared the last point, then this point will be classified as the point of turning.

new_df <- data.frame(field,ang1)
new_column <- 1:nrow(new_df)

for(i in 1:nrow(new_df))
{
angle_changes <- ang1[i+1]-ang1[i]
if (angle_changes>20)
{new_column[i] <- 'turn'}
else
{new_column[i] <- 'not_turn'}
}
Error in if (angle_changes > 20) { :
missing value where TRUE/FALSE needed

Is there a simpler and faster way of achieving this, without calculating all angles first?

For reproducible example, I selected the first 20 rows. The raw dataset has ~63,000 obs.

field1
Longitude  Latitude
49221   175.723 -37.82931
49222   175.723 -37.82931
49223   175.723 -37.82931
49230   175.723 -37.82931
49248   175.723 -37.82931
49272   175.723 -37.82931
49309   175.723 -37.82932
49324   175.723 -37.82932
49337   175.723 -37.82932
49347   175.723 -37.82932
49357   175.723 -37.82932
49367   175.723 -37.82932
49380   175.723 -37.82932
49389   175.723 -37.82932
49393   175.723 -37.82932
49400   175.723 -37.82932
49411   175.723 -37.82932
49417   175.723 -37.82932
49430   175.723 -37.82932
49434   175.723 -37.82932

I compared trip package trackAngle with the defined trackAngle. The former output 18 results NA NA 172.0851 174.9314 179.6634 172.2936 170.6603 178.0629 176.5133 178.0556 178.0443 173.4078 177.9946 179.6743 178.1043 178.5513 177.2740 177.2740,

the later output 180.0000 180.0000 172.0851 174.9314 179.6634 172.2936 170.6603 178.0629 176.5133 178.0556 178.0443 173.4078 177.9946 179.6743 178.1043 178.5513 177.2740 177.2740.

• You can use diff(ang) to avoid looping, and fwiw there is an equivalent trip::trackAngle function – mdsumner Sep 10 '16 at 12:08
• thanks, I wonder why trip::trackAngle generates 2429 NA's for my dataset while the defined trackAngle function doesn't. @mdsumner – Gorden Jiang Sep 11 '16 at 23:10
• reproducible example? – mdsumner Sep 12 '16 at 4:27
• Please find my edited question @mdsumner – Gorden Jiang Sep 13 '16 at 2:54