1. Introducción.

En este cuaderno se desarrolla el procesamiento de los datos obtenidos por GPS al recorrer un espacio dentro del campus de la sede Bogota de la Universidad Nacional de Colombia, para eventualmente, realizar la graficación de factores como la altitud y velocidad del GPS.

2. Código inicial.

library(XML)
library(OpenStreetMap)
library(lubridate)
## 
## Attaching package: 'lubridate'
## The following objects are masked from 'package:base':
## 
##     date, intersect, setdiff, union
library(ggmap)
## Loading required package: ggplot2
## Google's Terms of Service: https://cloud.google.com/maps-platform/terms/.
## Please cite ggmap if you use it! See citation("ggmap") for details.
library(ggplot2)
library(raster)
## Loading required package: sp
library(sp)

3. Definimos una función que desplaza los vectores convenientemente.

shift.vec <- function (vec, shift) {
  if(length(vec) <= abs(shift)) {
    rep(NA ,length(vec))
  }else{
    if (shift >= 0) {
      c(rep(NA, shift), vec[1:(length(vec)-shift)]) }
    else {
      c(vec[(abs(shift)+1):length(vec)], rep(NA, abs(shift))) } } }
col1 <- seq(0,100,5)

col2 <- seq(200, 100, -5)

my_df <- data.frame(c1= col1, c2= col2)

my_df
##     c1  c2
## 1    0 200
## 2    5 195
## 3   10 190
## 4   15 185
## 5   20 180
## 6   25 175
## 7   30 170
## 8   35 165
## 9   40 160
## 10  45 155
## 11  50 150
## 12  55 145
## 13  60 140
## 14  65 135
## 15  70 130
## 16  75 125
## 17  80 120
## 18  85 115
## 19  90 110
## 20  95 105
## 21 100 100
my_df$nc1 <- shift.vec(my_df$c1, -1)
my_df$nc2 <- shift.vec(my_df$c2, -1)
my_df
##     c1  c2 nc1 nc2
## 1    0 200   5 195
## 2    5 195  10 190
## 3   10 190  15 185
## 4   15 185  20 180
## 5   20 180  25 175
## 6   25 175  30 170
## 7   30 170  35 165
## 8   35 165  40 160
## 9   40 160  45 155
## 10  45 155  50 150
## 11  50 150  55 145
## 12  55 145  60 140
## 13  60 140  65 135
## 14  65 135  70 130
## 15  70 130  75 125
## 16  75 125  80 120
## 17  80 120  85 115
## 18  85 115  90 110
## 19  90 110  95 105
## 20  95 105 100 100
## 21 100 100  NA  NA

4. Procesar el archivo GPX.

options(digits=10)
pfile <- htmlTreeParse(file = "C:/Users/GERARDO/Desktop/GB2022/datos/Garmin/Datos_Garmin/GPX/freud.gpx", error = function(...) {
}, useInternalNodes = T)
elevations <- as.numeric(xpathSApply(pfile, path = "//trkpt/ele", xmlValue))
times <- xpathSApply(pfile, path = "//trkpt/time", xmlValue)
coords <- xpathSApply(pfile, path = "//trkpt", xmlAttrs)

str(coords)
##  chr [1:2, 1:29] "4.6357615851" "-74.0844536573" "4.6357523650" ...
##  - attr(*, "dimnames")=List of 2
##   ..$ : chr [1:2] "lat" "lon"
##   ..$ : NULL
lats <- as.numeric(coords["lat",])
lons <- as.numeric(coords["lon",])
geodf <- data.frame(lat = lats, lon = lons, ele = elevations, time = times)
rm(list=c("elevations", "lats", "lons", "pfile", "times", "coords"))
head(geodf)
##           lat          lon     ele                 time
## 1 4.635761585 -74.08445366 2573.81 2022-05-04T16:56:06Z
## 2 4.635752365 -74.08444209 2573.42 2022-05-04T16:56:21Z
## 3 4.635733003 -74.08443161 2573.47 2022-05-04T16:56:23Z
## 4 4.635580620 -74.08432231 2572.98 2022-05-04T16:56:33Z
## 5 4.635070497 -74.08406197 2572.41 2022-05-04T16:56:48Z
## 6 4.634966897 -74.08400891 2573.41 2022-05-04T16:56:53Z

5. Calculamos las distancias entre posiciones sucesivas y la velocidad respectiva en este segmento.

geodf$lat.p1 <- shift.vec(geodf$lat, -1)
geodf$lon.p1 <- shift.vec(geodf$lon, -1)
head(geodf)
##           lat          lon     ele                 time      lat.p1
## 1 4.635761585 -74.08445366 2573.81 2022-05-04T16:56:06Z 4.635752365
## 2 4.635752365 -74.08444209 2573.42 2022-05-04T16:56:21Z 4.635733003
## 3 4.635733003 -74.08443161 2573.47 2022-05-04T16:56:23Z 4.635580620
## 4 4.635580620 -74.08432231 2572.98 2022-05-04T16:56:33Z 4.635070497
## 5 4.635070497 -74.08406197 2572.41 2022-05-04T16:56:48Z 4.634966897
## 6 4.634966897 -74.08400891 2573.41 2022-05-04T16:56:53Z 4.634925406
##         lon.p1
## 1 -74.08444209
## 2 -74.08443161
## 3 -74.08432231
## 4 -74.08406197
## 5 -74.08400891
## 6 -74.08402660
geodf$dist.to.prev <- apply(geodf, 1, FUN = function (row) {
  pointDistance(c(as.numeric(row["lat.p1"]),
  as.numeric(row["lon.p1"])),
                c(as.numeric(row["lat"]), as.numeric(row["lon"])),
                lonlat = T)
})

head(geodf$dist.to.prev)
## [1]  1.321820268  1.311344560 13.060836991 32.989035998  6.718189025
## [6]  2.347842138
td <- sum(geodf$dist.to.prev, na.rm=TRUE)
print(paste("The distance run was ", td, " meters"))
## [1] "The distance run was  336.836508757948  meters"
geodf$time <- strptime(geodf$time, format = "%Y-%m-%dT%H:%M:%OS")

geodf$time.p1 <- shift.vec(geodf$time, -1)

geodf$time.diff.to.prev <- as.numeric(difftime(geodf$time.p1, geodf$time))

head(geodf$time.diff.to.prev, n=15) 
##  [1] 15  2 10 15  5  3  5 15  3  5  9 15  9  4  5
geodf$speed.m.per.sec <- geodf$dist.to.prev / geodf$time.diff.to.prev
geodf$speed.km.per.h <- geodf$speed.m.per.sec * 3.6
geodf$speed.km.per.h <- ifelse(is.na(geodf$speed.km.per.h), 0, geodf$speed.km.per.h)
geodf$lowess.speed <- lowess(geodf$speed.km.per.h, f = 0.2)$y
geodf$lowess.ele <- lowess(geodf$ele, f = 0.2)$y

6. Graficar elevación del GPS.

plot(geodf$ele, type = "l", bty = "n", xaxt = "n", ylab = "Elevación", xlab = "", col = "grey40")
lines(geodf$lowess.ele, col = "green", lwd = 3)
legend(x="bottomright", legend = c("Elevación de GPS", "Elevación más baja"),
       col = c("grey40", "green"), lwd = c(1,3), bty = "n")

7. Graficar la velocidad del GPS.

plot(geodf$speed.km.per.h, type = "l", bty = "n", xaxt = "n", ylab = "Velocidad (km/h)", xlab = "",
     col = "grey40")
lines(geodf$lowess.speed, col = "green", lwd = 3)
legend(x="bottom", legend = c("Velocidad de GPS", "Velocidad más baja"),
       col = c("grey40", "green"), lwd = c(1,3), bty = "n")
abline(h = mean(geodf$speed.km.per.h), lty = 2, col = "green")

8. Graficar trazo del GPS.

plot(rev(geodf$lon), rev(geodf$lat), type = "l", col = "red", lwd = 3, bty = "n", ylab = "Latitud", xlab = "Longitud")

library(ggmap)
lat <- c(min(geodf$lat), max(geodf$lat))
lat
## [1] 4.634200623 4.635761585
lon <- c(min(geodf$lon), max(geodf$lon))
lon
## [1] -74.08534029 -74.08400891
(bbox <- make_bbox(lon,lat))
##          left        bottom         right           top 
## -74.085406864   4.634122575 -74.083942344   4.635839633
b1 <- get_map(bbox,maptype="watercolor", source="stamen", zoom=10)
## Source : http://tile.stamen.com/terrain/10/301/498.png
ggmap(b1) + geom_point(data = geodf, 
           aes(lon,lat,col = ele), size=1, alpha=0.7) +
           labs(x = "Longitude", y = "Latitude",
           title="Track of one Sascha run through Stuttgart")

### 9. Bibliografía

“Lizarazo, I., 2022. Plotting GPS tracks with R. Available at https://rpubs.com/ials2un/gpx1