Computes one centre-of-pressure trajectory for each region mask, weighted
only by that region's sensors. Returns a list of pr_cop objects, so the
existing trajectory vocabulary — path length, mean and maximum velocity,
the x/y ranges pr_calc_cop_excursion() reports, and the 95% ellipse sway
area — is available per region with no further work.
Usage
pr_calc_cop_masked(trial, masks = NULL, threshold = 0, units = c("grid", "mm"))Value
A named list of pr_cop objects, one per mask, in the order the masks were given.
Details
A whole-mat COP is a single point that can sit in an unloaded gap between two loaded zones, and it moves whenever load shifts between zones. A per-region COP cannot: it stays inside its own region and reports how load migrated within it, which is what separates a saddle that rocks fore-and-aft from one that slides sideways.
Frames in which a region carries no load at all get NA for both axes,
exactly as pr_calc_cop() does for the whole mat. pr_cop() excludes
those frames from the trajectory metrics, so a region that is loaded only
intermittently still reports a meaningful path length — though one
measured across the gaps, not through them.
Units
units = "grid" (the default) returns grid index units: x is the
fractional sensor column, y the fractional sensor row, both 1-based, in
the convention of pr_calc_cop_grid(). This is always available.
units = "mm" returns the layout's physical x_mm / y_mm coordinates,
as pr_calc_cop() does. It is refused for a layout whose coordinates are
grid indices because no sensor pitch was ever published (see the Missing
physical scale section of pr_layout_from_index_map()) — millimetres
would be fabricated, and a path length in fabricated millimetres is worse
than none.
Note that a pr_cop object labels its fields mm regardless; under
units = "grid" they are grid indices, and the derived path length and
velocity are in index units and index units per second.
See also
pr_calc_cop() and pr_calc_cop_grid() for the whole mat,
pr_calc_cop_excursion() for the range summary.
Other regional symmetry functions:
pr_calc_regional_map(),
pr_calc_symmetry_map(),
pr_mask_mirror_balance(),
pr_mask_rowbands(),
pr_symmetry_sensitivity()
Examples
trial <- pr_example_trial("saddle_horse")
cops <- pr_calc_cop_masked(trial)
names(cops)
#> [1] "cranial_left" "cranial_right" "middle_left" "middle_right"
#> [5] "caudal_left" "caudal_right"
# Each region's COP stays inside its own rows:
round(vapply(cops, function(c) mean(c$y, na.rm = TRUE), numeric(1)), 2)
#> cranial_left cranial_right middle_left middle_right caudal_left
#> 3.80 3.79 8.50 8.49 13.25
#> caudal_right
#> 13.26
# The full pr_cop vocabulary works unchanged:
round(vapply(cops, function(c) c$path_length, numeric(1)), 3)
#> cranial_left cranial_right middle_left middle_right caudal_left
#> 72.419 84.384 104.211 119.473 75.375
#> caudal_right
#> 90.145
# This layout has a real sensor pitch, so millimetres are honest:
round(pr_calc_cop_masked(trial, units = "mm")$cranial_left$range_x, 1)
#> [1] 26.8