In testing · v0.3.0 debug builds

MTB Dynamics for Karoo

Garmin-style trail analytics for the Hammerhead Karoo 2 and Karoo 3: Grit, Flow, jumps, cornering and descents, with RockShox Flight Attendant and SRAM AXS insights. When the ride ends, a summary arrives on your phone, and everything goes into the FIT file for intervals.icu.

Illustration: MTB Dynamics, Suspension Coach and jump alert (values from a synthetic ride)

What it measures

The definitions follow Garmin's FIT profile and are tuned to similar ranges. These are not Garmin's algorithms, so the numbers are not identical to an Edge's.

⛰️

Grit

Trail difficulty from gradient, turns and trail roughness. Shown for the ride, the last 60 s and the lap.

🌊

Flow

Smoothness: braking the trail did not ask for, in metres per 100 m. Lower is smoother.

🪂

Jumps

Take-off, airtime, landing: count, distance, height, landing g, rotations, and records per ride.

↪️

Cornering

Corners from the gyroscope: entry and apex speed, lateral g, radius, speed kept.

⬇️

Descending

Time, drop, speed, braking share, and Flow and Grit on descents.

🏅

MTB score

0–100 from difficulty, smoothness and airtime.

🗺️

Trail segments

The ride split into climbs, descents and flats, plus your laps, with every metric per segment.

⏬

Live descents new

A field for the descent you are on, and an alert at the bottom with time, drop, Flow and braking.

🏆

Trail personal bests new

Descents you ride again are recognised and timed between the trail's start and end: rank and PB.

🛑

Where Flow was lost new

The spots with the most unnecessary braking, comparable laps, and left vs right corners.

📍

Map layer new

Your jumps, marked moments and rough ground on the Karoo map.

🔩

Bike systems

Flight Attendant, AXS shifting and the power meter, joined with the terrain they were used on.

🛠️

Service tracker

Fork and shock hours, chain km, cog usage and battery history, with reminders when service is due.

📲

Ride summary on your phone

Sent over ntfy when the ride ends, through Wi-Fi, LTE or the companion app.

📈

FIT + intervals.icu

All values go into the FIT file. Copy-paste streams, fields and charts are included for intervals.icu, and with an API key the Karoo writes the summary into the activity.

🐍

Analysis tool

A Python script for HTML reports with maps and charts, CSV/JSON export, multi-ride history and intervals.icu sync.

On the Karoo

Twenty-two data fields, four of them graphical (three with cells you choose). Alerts after each jump, at the bottom of each descent (with your trail PB) and when the suspension stays locked on rough ground. A map layer, a "Mark moment" controller button, and a settings screen with a sensor test and a one-tap debug bundle.

Settings screen with the sensor test result on a Karoo 2
Sensor test: the accelerometer and gyroscope at 98 Hz
Bike-system alert switches and service tracker introduction
Bike alerts and the service tracker
Service items with hours used, interval and a Serviced button
Service items: usage, interval, "Serviced"

After the ride

A summary arrives on your phone. For a deeper look, the analysis tool turns any Karoo or Garmin FIT file into an interactive report. Both demos below come from synthetic rides.

ntfy · now
MTB Dynamics · Trail · Sun 27 Sep 09:30

🚵 MTB score 70 · difficulty 61 · smoothness 94 · air 37

⛰️ Grit 10.0 kGrit · avg 5.9/s · peak 60 s 10.6
🌊 Flow 0.4 (lower = smoother) · descents 0.8
🪂 4 jumps · 2.8 s total airtime
  • Longest: 0.83 s · 6.2 m · 27.0 km/h
↪️ 30 corners · max 0.79 g · speed kept 100%
⬇️ Descents 10:00 · 482 m ↓ · braking 21%

🏆 Descent 2 · Dragon's back: PB 5:07 (was 5:12) · run 6
⏱ Descent 1 · Trail 2: 5:12 · 3rd of 9 · best 4:58

Where Flow was lost
1. Descent 2 · at 6.3 km · 18.2 m braking · 32→18 km/h

🔩 Flight Attendant descents 93% open · climbs 100% lock · opens 22 s into descents
⚙️ 2 shifts (0.7/km) · cogs 18–32T · climbs 32T
💪 Power climbs 230 W (3.1 W/kg) · L/R 47/53
🔋 FA fork low ⚠️ · AXS derailleur good

🛠️ Fork lower-leg service due · 50.3 h since the last one

⏱ 28:00 · 📏 8.1 km · ↗ 393 m · ⚡ 17.4 km/h avg

Example message (synthetic ride; the bike and service lines appear when those parts are paired)

Bike systems: Flight Attendant, AXS, power

Pair the parts with the Karoo as usual; nothing else to set up. Every second the extension records power, cadence, balance, fork and shock state, effort zone and gear, and connects them to the trail.

MetricWhat it tells you
FA sharesOpen / Pedal / Lock % on climbs, descents and flats
Locked on roughSeconds in Lock at ≥ 0.9 g vibration: too firm a setting
Open on hard climbsOpen while pushing ≥ 200 W uphill: energy lost to bobbing
ReactionSeconds from the start of a descent until the fork opens
ShiftsPer km, under load (≥ 250 W), before vs. after a climb starts
Cog usageMinutes per cog and terrain, cogs never used
Steep climbingCadence, torque, time under 60 rpm on ≥ 6 %
Power by terrainW and W/kg, pedalling on descents, best 5 min, L/R
Suspension & gears chart: Flight Attendant state band with the rear cog, cog minutes per terrain, segment table with power and FA shares
Suspension & gears in the ride report Open →

Tested with a RockShox SID / SIDLuxe Ultimate Flight Attendant, SRAM XX SL Eagle Transmission and the XX SL power meter. It uses the Karoo's generic data types, so other Flight Attendant, AXS and power-meter setups should work. The Reverb AXS dropper is not exposed to extensions by the Karoo.

Install the test release

Works on Karoo 2 and Karoo 3 with any 2024+ firmware. Releases are signed, so the Karoo can update from one test release to the next.

  1. Get karoo-mtb.apk from the latest release

    Companion app: on your phone, long-press karoo-mtb.apk on the release page → Share → Hammerhead. The Karoo installs it and offers later releases as updates.
    USB: adb install -r karoo-mtb.apk

    A self-built APK, or one from a CI run, is signed with a different key and won't install over the release (or the other way round). Pull your ride folder first, then uninstall the old build. That also resets the settings, so note your ntfy topic.

  2. Set up ntfy

    Open MTB Dynamics from the app drawer. Scan the QR code with the ntfy app, then press Send test notification.

  3. Add data fields and ride

    Profiles → page → add field → MTB Dynamics. The extension records every ride, even with no field on screen.

  4. See it in intervals.icu

    A one-time setup of custom streams, fields and charts: follow the intervals.icu setup guide (5 minutes for the basics).

Prefer to build it yourself? See Building from source. Full documentation: README · intervals.icu setup · analysis tool

Help test it

The most useful bug report includes the extension log and, if you're willing, the ride folder.

# what the extension logged
adb logcat -s MtbExtension MtbRide MtbImu MtbHttp MtbNotifier

# ride data: per-second CSV, jumps, corners, shifts, summary
adb pull /sdcard/Android/data/io.github.angkyria.karoomtb/files/rides
adb pull /sdcard/Android/data/io.github.angkyria.karoomtb/files/service.json

# analyse a ride folder, replay the raw sensor log
python3 tools/mtb_analyze.py --karoo-dir rides/<ride> --html report.html --imu

Tuning jumps

Turn on Debug: save raw sensor data in the settings, ride a few known jumps and note their times. The --imu replay shows what each sensitivity would have detected.

Privacy

Ride folders and FIT files contain your GPS track. Share them privately, not in a public issue. The extension itself only sends data to your ntfy server; FIT files go wherever your Karoo uploads them.

Report a bug