flightpathr

Tools to analyze aircraft and flight path data.
git clone https://git.eamoncaddigan.net/flightpathr.git
Log | Files | Refs | README | LICENSE

distanceFromPath.R (3566B)


      1 #' Calculate the distance of a flight trajectory from a flight path.
      2 #'
      3 #' @param trajectory A \code{flighttrajectory} object (or an object that can be
      4 #'   coerced into one) indicating the trajectory of an aircraft.
      5 #' @param path A \code{flightpath} object (or an object that can be coerced into
      6 #'   one) indicating the ordered waypoints a pre-defined flight path.
      7 #' @return A data.frame containing two columns representing the distance between
      8 #'   the aircraft and its planned flight path (in feet): \code{horizontal}
      9 #'   indicates the horizontal distance and \code{vertical} indicates the
     10 #'   vertical distance.
     11 #'
     12 #' @export
     13 distanceFromPath <- function(trajectory, path) {
     14   # Check inputs and get 3D coordinates
     15   trajectoryCoords <- get3dCoords(as.flighttrajectory(trajectory))
     16   pathCoords <- get3dCoords(as.flightpath(path))
     17 
     18   numLegs <- nrow(pathCoords)-1
     19 
     20   # Given n points and m legs, store horizontal and vertical distance in an
     21   # n x m arrays
     22   hDistanceToLeg <- array(NA, dim = c(nrow(trajectoryCoords), numLegs))
     23   vDistanceToLeg <- array(NA, dim = c(nrow(trajectoryCoords), numLegs))
     24 
     25   # And the squared "slant range" (euclidean distance) in an n x m array
     26   slantToLeg <- array(NA, dim = c(nrow(trajectoryCoords), numLegs))
     27 
     28   for (legIdx in seq_len(numLegs)) {
     29     # For each pair of adjascent waypoints, calculate the horizontal distance
     30     # from the great circle defined by the pair and all points in the
     31     # trajectory.
     32     hDistanceToLeg[, legIdx] <- geosphere::dist2gc(pathCoords[legIdx, c(1,2)],
     33                                               pathCoords[legIdx+1, c(1,2)],
     34                                               trajectoryCoords[, c(1,2)],
     35                                               r = 20925646)
     36 
     37 
     38     if (is.na(pathCoords[legIdx, 3]) || is.na(pathCoords[legIdx+1, 3])) {
     39       # When a waypoint has an altidue of NA, we don't care about its altitude.
     40       # Therefore, the "vertical deviation" is meaningless. Use 0.
     41       vDistanceToLeg[, legIdx] <- 0
     42     } else if (pathCoords[legIdx, 3] == pathCoords[legIdx+1, 3]) {
     43       # If the waypoints are at the same altitude, just calculate the deviation
     44       # from this altitude. Easy.
     45       vDistanceToLeg[, legIdx] <- trajectoryCoords[, 3] - pathCoords[legIdx, 3]
     46     } else {
     47       # When waypoints have different altitudes, a flight has "deviated" when
     48       # it's above the higher altitude or below the lower altitude.
     49       vDistanceToLeg[, legIdx] <- 0
     50       deviationAbove <- trajectoryCoords[, 3] - max(pathCoords[c(legIdx, legIdx+1), 3])
     51       deviationBelow <- trajectoryCoords[, 3] - min(pathCoords[c(legIdx, legIdx+1), 3])
     52       vDistanceToLeg[deviationAbove > 0, legIdx] <- deviationAbove[deviationAbove > 0]
     53       vDistanceToLeg[deviationBelow < 0, legIdx] <- deviationBelow[deviationBelow < 0]
     54     }
     55 
     56     # Squared euclidean distance
     57     slantToLeg[, legIdx] <- hDistanceToLeg[, legIdx]^2 + vDistanceToLeg[, legIdx]^2
     58   }
     59 
     60   # Figure out which leg is closer to each point in the trajectory.
     61   # Note: I can imagine a tortuous path that would result in the closest path
     62   # alternating between legs. This would need to be rewritten to handle that.
     63   closestLeg <- apply(slantToLeg, 1, which.min)
     64 
     65   # Return the horizontal and vertical distance to the flight path (distance to
     66   # the closest leg) as a data.frame.
     67   distanceToPath <- data.frame(horizontal = hDistanceToLeg[cbind(1:nrow(trajectoryCoords), closestLeg)],
     68                                vertical = vDistanceToLeg[cbind(1:nrow(trajectoryCoords), closestLeg)])
     69   return(distanceToPath)
     70 }