flightpathr

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

test_distanceFromPath.R (4692B)


      1 library(flightpathr)
      2 context("distanceFromPath")
      3 
      4 numPoints <- 5
      5 
      6 fakeTrajectory <- function(waypoints, n = numPoints) {
      7   coordList <- vector("list", 2*nrow(waypoints)-1)
      8   coordList[[1]] <- waypoints[1, ]
      9   for (i in seq(2, nrow(waypoints))) {
     10     coordList[[(i-1)*2]] <- geosphere::gcIntermediate(waypoints[i-1, ],
     11                                                       waypoints[i, ], n)
     12     coordList[[(i-1)*2+1]] <- waypoints[i, ]
     13   }
     14   coordMat <- do.call(rbind, coordList)
     15   return(createTrajectory(longitude = coordMat[, "lon"],
     16                           latitude = coordMat[, "lat"],
     17                           altitude = 0))
     18 }
     19 
     20 # Flying from 17N to KACY with a stop over N81. Flying VFR at 3500 msl
     21 pathMat <- matrix(c(-75.0268, 39.7065,
     22                     -74.7577, 39.6675,
     23                     -74.5722, 39.4513),
     24                   nrow = 3, byrow = TRUE,
     25                   dimnames = list(c("17N", "N81", "KACY"),
     26                                   c("lon", "lat")))
     27 path <- createPath(longitude = pathMat[, "lon"], latitude = pathMat[, "lat"])
     28 trajectory <- fakeTrajectory(pathMat)
     29 trajectoryLength <- length(trajectory$longitude)
     30 
     31 test_that("non-deviating paths have small distances for all input types", {
     32   expect_equal(distanceFromPath(trajectory, path)$horizontal,
     33                rep(0, trajectoryLength),
     34                tolerance = 1)
     35 
     36   # data.frame
     37   expect_equal(distanceFromPath(data.frame(trajectory$longitude, trajectory$latitude),
     38                                 data.frame(path$longitude, path$latitude))$horizontal,
     39                rep(0, trajectoryLength),
     40                tolerance = 1)
     41 
     42   # matrix
     43   expect_equal(distanceFromPath(cbind(trajectory$longitude, trajectory$latitude),
     44                                 cbind(path$longitude, path$latitude))$horizontal,
     45                rep(0, trajectoryLength),
     46                tolerance = 1)
     47 
     48   # SpatialPoints
     49   expect_equal(distanceFromPath(sp::SpatialPoints(cbind(trajectory$longitude, trajectory$latitude)),
     50                                 sp::SpatialPoints(cbind(path$longitude, path$latitude)))$horizontal,
     51                rep(0, trajectoryLength),
     52                tolerance = 1)
     53 })
     54 
     55 test_that("small horizontal deviations look OK", {
     56   flownPathMat <- rbind(pathMat[1:2, ],
     57                         KORDE = c(-74.0948, 39.0976),
     58                         pathMat[3, , drop = FALSE])
     59   flownTrajectory <- fakeTrajectory(flownPathMat)
     60   flownPath <- createPath(flownPathMat[, 1], flownPathMat[, 2])
     61   trajectoryDistance <- distanceFromPath(flownTrajectory, path)$horizontal
     62   farthestPoint <- which.max(abs(trajectoryDistance))
     63 
     64   expect_equal(farthestPoint, numPoints*2+3)
     65   expect_equal(maxDistanceFromPath(flownTrajectory, path)["horizontal"],
     66                c(horizontal = 42015.6),
     67                tolerance = 1)
     68   expect_equal(maxDistanceFromPath(flownTrajectory, flownPath)["horizontal"],
     69                c(horizontal = 0),
     70                tolerance = 1)
     71 })
     72 
     73 test_that("simple altitude deviation is handled", {
     74   flownPath1 <- createPath(pathMat[, "lon"], pathMat[, "lat"], 3500)
     75   flownPath2 <- createPath(pathMat[, "lon"], pathMat[, "lat"], c(3500, 4500, 3500))
     76   flownPath3 <- createPath(pathMat[, "lon"], pathMat[, "lat"], c(3500, 5500, 3500))
     77   flownPath4 <- createPath(pathMat[, "lon"], pathMat[, "lat"], c(3500, 5500, 5500))
     78   flownTrajectory <- createTrajectory(trajectory$longitude, trajectory$latitude,
     79                                       c(seq(3500, 5500,
     80                                             length.out = numPoints+2),
     81                                         seq(5500, 3500,
     82                                             length.out = length(trajectory$longitude)-(numPoints+2))))
     83 
     84   expect_equal(maxDistanceFromPath(flownTrajectory, flownPath1)["vertical"],
     85                c("vertical" = 2000), tolerance = 1)
     86   expect_equal(maxDistanceFromPath(flownTrajectory, flownPath2)["vertical"],
     87                c("vertical" = 1000), tolerance = 1)
     88   expect_equal(maxDistanceFromPath(flownTrajectory, flownPath3)["vertical"],
     89                c("vertical" = 0000), tolerance = 1)
     90   expect_equal(maxDistanceFromPath(flownTrajectory, flownPath4)["vertical"],
     91                c("vertical" = -2000), tolerance = 1)
     92 })
     93 
     94 test_that("reproducing geosphere vignette example", {
     95   LA <- c(-118.40, 33.95)
     96   NY <- c(-73.78, 40.63)
     97   MS <- c(-93.26, 44.98)
     98   flownTrajectory <- fakeTrajectory(rbind(LA, MS, NY), n = 1000)
     99   plannedPathMat <- rbind(LA, NY)
    100   plannedPath <- createPath(plannedPathMat[, 1], plannedPathMat[, 2], 0)
    101   feetToMeters <- 0.3048
    102 
    103   expect_equal(maxDistanceFromPath(flownTrajectory, plannedPath)["horizontal"]*feetToMeters,
    104                c("horizontal" = 547448.8),
    105                tolerance = 1)
    106 })