Compatible Coordinate Systems
Trackframe only supports Cartesian (or Euclidean) coordinate systems, i.e., systems in which coordinates describe locations on a flat plane using perpendicular northing (y) and easting (x) axes, and units represent consistent physical distances in all directions.
As long as the coordinates are Cartesian, trackframe supports both: georeferenced data, wherein the coordinates explicitly represent locations on the Earth’s surface; and non-georeferenced data, wherein the coordinates do not explicitly or necessarily represent locations on the Earth’s surface.
Georeferenced data
For georeferenced coordinates (i.e., coordinates that represent
locations on the Earth’s surface), trackframe requires that
they be projected, e.g., UTMs rather than latitute-longitude.
For sf objects (move2 and
sftrack objects), trackframe identifies the
coordinate system using sf::st_crs. For non-sf objects, you
have to specify the coordinate reference system with the
crs argument in as.trackframe. If your data
has non-Cartesian georeferenced coordinates, for example, latitude and
longitude, you will need to first project your data before converting it
to to a trackframe object. For this reason, trackframe may not be
appropriate for studying movement processes that cross large enough
distances that distortion from projected coordinates causes meaningful
measurement inaccuracies (e.g., long-distance migration).
Take this example, using a move2 object:
library(move2)
# Load a move2 object using the move2 package
fisher_move2 <- mt_read(mt_example())
# Check the coordinate reference system
sf::st_crs(fisher_move2)## Coordinate Reference System:
## User input: EPSG:4326
## wkt:
## GEOGCRS["WGS 84",
## ENSEMBLE["World Geodetic System 1984 ensemble",
## MEMBER["World Geodetic System 1984 (Transit)"],
## MEMBER["World Geodetic System 1984 (G730)"],
## MEMBER["World Geodetic System 1984 (G873)"],
## MEMBER["World Geodetic System 1984 (G1150)"],
## MEMBER["World Geodetic System 1984 (G1674)"],
## MEMBER["World Geodetic System 1984 (G1762)"],
## MEMBER["World Geodetic System 1984 (G2139)"],
## ELLIPSOID["WGS 84",6378137,298.257223563,
## LENGTHUNIT["metre",1]],
## ENSEMBLEACCURACY[2.0]],
## PRIMEM["Greenwich",0,
## ANGLEUNIT["degree",0.0174532925199433]],
## CS[ellipsoidal,2],
## AXIS["geodetic latitude (Lat)",north,
## ORDER[1],
## ANGLEUNIT["degree",0.0174532925199433]],
## AXIS["geodetic longitude (Lon)",east,
## ORDER[2],
## ANGLEUNIT["degree",0.0174532925199433]],
## USAGE[
## SCOPE["Horizontal component of 3D system."],
## AREA["World."],
## BBOX[-90,-180,90,180]],
## ID["EPSG",4326]]
The objects coordinate reference system is WGS 84 (i.e.,
crs = 4326 or EPSG:4326), i.e., the standard
decimal latitude-longitude. These are, thus, not Cartesian coordinates.
If we attempt to directly convert this object to a
trackframe object, it will fail…
# Convert to trackframe (ERROR since non-Cartesian coordinates)
fisher_tf <- as.trackframe(data = fisher_move2)## Error in `derive_crs_type()`:
## ! Expected projected coordinates, got geographic coordinates. Please project into an appropriate crs.
Note the instruction in the error message: “Please project into an appropriate crs.”
There are several packages and approaches for projecting
georeferenced data. In the following example, we use the
st_transform function from the sf package.
# Project the coordinates into the appropriate UTM zone (in this case,
# UTM zone 38S, or EPSG: 32738), and then convert to trackframe object
fisher_tf <- fisher_move2 |>
sf::st_transform(crs = 32738) |>
as.trackframe()
# Extract the input crs EPSG code from the tf object's transformation_info
crs(fisher_tf)## [1] "EPSG:32738"
In the following example, we convert a data.frame object
to a trackframe object. The dataframe doesn’t contain any
georeferencing metadata (i.e., a crs), but let’s say that we know that
these data were collected in southern Germany and that the coordinates
are already projected (i.e., they’re in UTM zone 32N, or ESPG:32632). In
this case, you can simply tell as.trackframe what the crs
is, using the crs argument or
tf_options("crs").
# Create some example data
df <- data.frame(
time_col = rep(as.POSIXct(Sys.time() + 1:5), times = 5),
easting_col = runif(25, 0, 10),
northing_col = runif(25, 0, 10),
id = rep(1:5, each = 5)
)
# Specify the crs when converting to trackframe
tf <- as.trackframe(df, crs = "EPSG:32632")
# Extract the input crs EPSG code from the tf object
crs(tf)## [1] "EPSG:32632"
# Set crs globally using `tf_options`
tf_options("crs", "EPSG:32632")
tf <- as.trackframe(df)
# Global crs is applied to tf
crs(tf)## [1] "EPSG:32632"
Non-georeferenced data
For non-georeferenced coordinates, i.e., those that do not represent
locations on the Earth’s surface, the crs argument in
as.trackframe should be set to NA. This may
apply to, for example, data pertaining to simulations (i.e.,
representing locations on a virtual plane) or captive animal locations
(i.e., representing locations in an enclosure, measured relative to some
reference point in or near the enclosure). Note that even
non-georeferenced coordinates should still be Cartesian, but
trackframe has no way of verifying this or alerting if this
is not the case.
Where as.trackframe does not inherit metadata specifying
the crs from the input object (for example, when the input
object is a dataframe), the crs must be
provided either as an argument or via tf_options("crs").
Otherwise as.trackframe will throw an error.
# Create some example data
df <- data.frame(
time_col = rep(as.POSIXct(Sys.time() + 1:5), times = 5),
easting_col = runif(25, 0, 10),
northing_col = runif(25, 0, 10),
id = rep(1:5, each = 5)
)
# Convert df to trackframe without specifying crs (ERROR since no crs given)
tf_non_gr <- as.trackframe(df)
# Convert df to trackframe with non-georeferenced crs
tf_non_gr <- as.trackframe(df, crs = NA)
# Extract the crs from the tf object
crs(tf_non_gr)## [1] NA
# Set crs globally using `tf_options`
tf_options("crs", NA)
tf <- as.trackframe(df)
# Global crs is applied to tf
crs(tf)## [1] NA