Working on advanced running metrics (GCT, Vertical Oscillation, Vertical Ratio, Step Length) — help us cover more devices before we ship it

First observations:

Cadence could optionally be display in spm

This update is really helpful for Stryd users. Only missing vertical_oscillation_balance, leg_spring_stiffness_balance and impact_loading_rate_balance for the full Stryd Duo set.

For Garmin

Impact Loading Rate, Step Speed Loss and Step Speed loss % are missing.

Overall analyses: Only niche metrics are missing. As a Stryd Duo user i would love to have it all, but i understand your choosing.

Thank you.

Using Stryd: Impact Loading Rate, i am getting no values

{
      icu.activity.average_impact_loading_rate
}

nor intervals ILR nor icu.streams.impact_loading_rate

correction:

1 Like

Using my streams checker

with a HRM600

:gem_stone: STREAMS VARIABLES CHECK |

Variable Name | Length | Type | Status |---------------------------------|--------|-----------|-------- |

| cadence_row 7270 | Array | :white_check_mark:

| vertical_oscillation_row | 7270 | Array | :white_check_mark:

| stance_time | 7270 | Array | :white_check_mark:

| vertical_ratio | 7270 | Array | :white_check_mark:

| step_length_row | 7270 | Array | :white_check_mark:

| stance_time_balance | 7270 | Array | :white_check_mark:

| stance_time_percent | 7270 | Array | :white_check_mark:

| vertical_speed | 0 | Array | :cross_mark:

| impact_loading_rate. | 0 | Array | :cross_mark:

| leg_spring_stiffness. | 0 | Array | :cross_mark:

With a Garmin Watch and a Stryd Duo:

| cadence_row | 10898 | Array | :white_check_mark:
| vertical_oscillation_row | 10898 | Array | :white_check_mark:
| stance_time | 10898 | Array | :white_check_mark:
| vertical_ratio | 10898 | Array | :white_check_mark:
| step_length_row | 10898 | Array | :white_check_mark:
| stance_time_balance | 10898 | Array | :white_check_mark:
| stance_time_percent | 10898 | Array | :white_check_mark:
| vertical_speed | 0 | Array | :cross_mark:
| impact_loading_rate | 0 | Array | :cross_mark:
| leg_spring_stiffness | 10898 | Array | :white_check_mark:

I would also love to see more data coming from my Apple Watch

Apologies if I should know this but who is ‘we’ in this context? Is this for intervals.icu improvement?

I have lots of examples from various devices / watches - just not clear who is asking and what is being developed

@david , @eva and @ryandev is the dev team.
If one of them mentions ‘We’, they mean the official icu devs.

1 Like

Thank You @MedTechCD

i can supply FIT files from Suunto with Stryd and Garmin with Stryd (Duo / v5)

And Coros if you need it (I believe running dynamics are from the pod, not watch / wrist based)

Created a Activity Chart named “New Running Streams” for you to check which streams are available to you, don’t forget to reprocess activity before use.

This is great new addition, thanks.

I also analyze the Flight Time in my sessions, it depends on the cadence and GCT.

I explain it in the post: https://forum.intervals.icu/t/all-fields-from-garmin-activity/28097

Flight Time (FlightTime): Flight Time is the amount of time you spend off the ground between strides when running. It needs Ground Contact Time (GCT) custom activity field created. Script activity.GCT > 0 ? (60 / (activity.average_cadence * 2) * 1000) - activity.GCT : NaN

There is a limited collection of metrics from Coros wrist based, on the newer devices with latest firmware.

For Coros new watches, wrist based have at least the following streams available:

| cadence | 2567 | Array | :white_check_mark:
| vertical_oscillation. | 2567 | Array | :white_check_mark:
| stance_time | 2567 | Array | :white_check_mark:. GCT,
| vertical_ratio | 2567 | Array | :white_check_mark:
| step_length | 2567 | Array | :white_check_mark:
| stance_time_balance | 0 | Array | :cross_mark:
| stance_time_percent | 0 | Array | :cross_mark:
| vertical_speed | 0 | Array | :cross_mark:

Flight time is a valuable metric inversely correlated with Duty Factor (DF)—the biomechanics literature standard that corresponds directly to Garmin’s stance_time_percent metric expressed as a ratio:

In running dynamics literature, Duty Factor is widely used to classify runners along the aerial–terrestrial continuum:

  • Aerial Pattern (Low DF): Characterized by longer flight times, lower ground contact times, and higher leg stiffness. At a standard speed of 12 km/h, runners exhibiting a DF≤0.25–0.27 (Garmin stance_time_percent ≤25–27%) are classified as strongly aerial.

  • Terrestrial Pattern (High DF): Characterized by longer stance times and shorter flight times to optimize energy expenditure via forward propulsion rather than vertical displacement. At 12 km/h, runners with DF≥0.28–0.30 (Garmin stance_time_percent ≥28–30%) are classified as terrestrial.

Duty Factor & stance_time_percent Thresholds @ 12 km/h

The Duty Factor (DF) classification at 12 km/h breaks down into clear motor-profile zones:

Motor Profile Duty Factor (DF) Garmin stance_time_percent Flight Ratio (1 - DF)
Strongly Aerial <= 0.25 <= 25.0% >= 75.0%
Aerial 0.25 - 0.27 25.0% - 27.6% 72.4% - 75.0%
Transition Zone 0.27 - 0.28 27.7% - 28.7% 71.3% - 72.3%
Terrestrial 0.28 - 0.30 28.8% - 30.0% 70.0% - 71.2%
Strongly Terrestrial > 0.30 > 30.0% < 70.0%

:books: Primary References in Literature

1. Patoz et al. (2019) “Duty Factor Is a Viable Measure to Classify Spontaneous Running Forms”Sports, 7(7), 174.

➔ Identified Duty Factor at 12 km/h as a reliable, objective metric to classify runners into aerial (DF≤27.6%) versus terrestrial (DF≥28.8%) groups.

2. Lussiana et al. (2017) “Biomechanical comparison of running economy and global running patterns in aerial and terrestrial runners”Journal of Biomechanics, 60, 185-192.

➔ Established the biomechanical framework linking lower Duty Factor to increased elastic energy storage/recoil in aerial runners.

3. Gindre et al. (2016) “Aerial and terrestrial patterns: A new concept in running economy”International Journal of Sports Medicine, 37(03), 202-209.

➔ Introduced the original Volodalen® aerial-terrestrial motor profile concept.
Garmin’s stance_time_percent divided by 100 is literally Duty Factor. A score below 0.25–0.27 at 12 km/h means you’re an aerial runner; higher means you’re terrestrial.

Could you send me this fit file?

Did that by DMS

COROS-Pace4-Optical and added a Apple Watch Ultra 3 file

1 Like

So your streams are working great. :grinning_face:
exception: icu.streams.impact_loading_rate

Apple Watch Ultra 3 has the following streams:

Can you share your Apple Watch activity output from miguell’s “New Running Streams” activity chart?

1 Like

That’s a great explanation, thank you @pepe.

Also for Apple watch and Coros watch and others that have icu.streams.cadence and icu.streams.stance_time` there is the Duty Factor and Stance Time Percent Customs Streams and Fields i created.

Tests if stance_time_percent exists if not calculates it.

Duty Factor is just a percentage, it shows your balance and efficiency but hides critical data.

Flight Time provides the exact milliseconds you are airborne, revealing if you are gliding or bouncing. Two runners can share the same Duty Factor percentage but have completely different (perhaps unsafe) flight times.

Flight time is a useful metric, but looking at it in isolation leaves out how force is actually applied. Spring-mass mechanics, leg stiffness, and impact loading depend primarily on Ground Contact Time and the ratio of airtime to ground time (the Flight Ratio, which is simply (1 / dutyFactor) - 1;

Ground Contact Time is where force production, tendon energy storage, and deceleration actually happen; Flight Time is just the passive ballistic trajectory that results from that contact phase.

Looking at Flight Time without Ground Contact Time is like measuring how high a ball bounced without knowing how hard it hit the ground. Pairing Duty Factor (or Ground Contact Time) with Flight Time, gives the full picture.