Inspiration
Rhabdomyolysis happens when overworked muscle breaks down and floods the blood with proteins that can wreck the kidneys. It hits marathoners, military recruits, people pushing through hot runs and beginners who go too hard, and it's often caught too late. Every runner already wears a watch that tracks their heart. We asked: why doesn't it say anything when that heart starts telling a dangerous story?
The hard part is that a body in trouble and a body working hard look almost identical on a wrist sensor. A heart rate of 175 is fine on a hill sprint and worrying on a gentle jog. That gap is what we set out to close.
What it does
R1 is a Galaxy Watch app that runs in the background during a run and alerts you when your body stops responding normally to the effort.
- Expected-effort model: R1 predicts what your heart rate should be from your pace, cadence, arm movement and time into the run, and calibrates to you in the first few minutes. When your heart rate climbs above that while your pace stays flat or drops, that's the red flag.
- Multi-signal risk score: it combines that heart-rate gap with % of max heart rate, heart-rate recovery at stops, sudden heart-rate jumps, rhythm checks while your wrist is still, skin-temperature trend and pulse strength. Each signal only counts if it persists (about 2 minutes), so one bad reading doesn't set it off. The result is one 0–100% score.
- Tiered alerts:
- Caution (≥ 30%): a gentle buzz: "Ease up. Slow down and drink some water."
- Warning (≥ 50%): a strong buzz and a full-screen "Stop and walk".
- Urgent: a sudden heart-rate jump, or heart rate far above expected while you slow down, skips straight to "Stop now".
- Symptom check: four yes/no questions (unusual muscle pain or swelling, weakness, dark urine, dizziness / confusion / chest pain). Any "yes" tells you to stop and get medical care.
- Automatic drink logging: when you grab a cup at a water station, R1 recognizes the raise-and-tip motion together with your slowdown, buzzes, plays a ding and shows "Sip Detected!" with one-tap undo. It compares what you drink against estimated sweat loss and warns about both dehydration and over-drinking (hyponatremia).
- Works with your usual app: R1 can auto-start when you begin a run in another workout app such as Strava, and it learns your resting heart rate in the background, so there's nothing to type in.
Everything runs on the watch. No phone or internet connection is needed for an alert.
How we built it
- Watch app: Kotlin on Wear OS with Jetpack Compose. A foreground service tied to a Health Services exercise session keeps R1 running with the screen off. A passive Health Services listener handles auto-start and resting heart rate.
- Sensors: Health Services for heart rate, cadence and GPS speed; the accelerometer for motion and drink gestures. The Samsung Health Sensor SDK adds beat-to-beat intervals, skin temperature and raw PPG. It's optional, and the app falls back to fewer signals without it.
- Data: there is no labeled rhabdo wearable data anywhere, and you can't ethically create it. So we built a simulator: 30 virtual runners, each with their own fitness, resting and max heart rate, running warm-ups, intervals, hills, stops and cool-downs. It renders raw 25 Hz wrist PPG (with arm-swing motion artifacts and strap shifts), a 3-axis accelerometer, skin temperature and noisy GPS. We injected six danger scenarios into the underlying physiology before rendering, so the pipeline has to find them in the raw signals: heart-rate drift, heat stress, slow recovery, a sudden SVT-like jump, a weakening pulse and an irregular rhythm.
- Model: signal quality → features → expected-HR regression → sub-scores → risk score, in Python (NumPy, SciPy, scikit-learn, Matplotlib). We tuned on 15 runners and evaluated on 15 it never saw.
- One brain, two languages: we ported the scoring engine line by line from Python to Kotlin. An automated parity test feeds six recorded scenarios through both and checks they give the same alert at the same second. The watch reads its parameters from the Python export, so the two can't drift apart.
- Drink gesture: rules on the wrist accelerometer: forearm raised 38–80°, held 0.9–6 s, steady, tipping back as the cup empties, and a pace drop at the same time. A debug-only gesture recorder collects labeled accelerometer + gyroscope clips (drink, wipe sweat, adjust hat, check watch) so we can train a proper classifier next.
- Demo replay mode: feeds a recorded danger scenario through the exact same background service and engine as a live run, so you can watch the risk ring climb and the alert fire on stage.
Challenges we ran into
- Exercise hides the danger: a racing heart, low heart-rate variability and heat are all normal on a hard run. Fixed thresholds like "heart rate over 200" either miss real danger or buzz constantly. Switching to "how far from expected for this effort" was the breakthrough.
- Hills look like trouble: on a climb your heart rate rises while your pace falls, which is exactly the danger pattern. Hills are still our main source of false alarms; adding the barometer to measure slope is the planned fix.
- Motion artifacts: running motion corrupts the PPG signal, and wrist heart rate can lock onto your step rate. We added a signal-quality gate so rhythm checks only run when the wrist is still, and R1 holds the last good heart rate when it detects step-rate lock.
- Blood pressure isn't available mid-run: our original plan relied on the Galaxy Watch's blood-pressure feature. It turned out to be a calibrated spot check at rest that other apps can't trigger. We switched to pulse-strength changes as an experimental, low-weight stand-in.
- No ground-truth data: we had to build a realistic simulator and be honest that the same team built the simulator and the detector, which makes our numbers optimistic.
- Sharing the watch: Wear OS allows only one workout session at a time, so starting ours would end the runner's Strava workout. R1's companion mode follows the other app's workout instead of starting its own.
Accomplishments that we're proud of
- The expected-effort approach works in simulation. On 15 held-out simulated runners, R1 caught 78% of injected danger scenarios (139 of 179) at the Caution level, with 0.26 false alarms per hour on a runner's first run and 0.16 once it has learned from their past runs. A fixed heart-rate threshold at a similar false-alarm rate caught only 23%; tuned to catch as much as R1, it raised 2.8 false alarms per hour, over 10× more.
- No urgent false alarms: across 46 hours of normal simulated running, nothing triggered the top tier. A sudden heart-rate jump was flagged in a median of 18 seconds.
- A complete watch app, not just a notebook: background service, risk ring, tiered alerts, symptom check, drink logging, replay mode, auto-start with other workout apps, metric and imperial units. Verified end to end on the Wear OS emulator.
- Python and Kotlin agree to the second on every exported scenario, enforced by an automated test.
- Warning about over-drinking as well as dehydration, which most hydration trackers ignore.
What we learned
- Context matters more than raw thresholds in health signals. The same heart rate can be fine or alarming depending on effort.
- What wearable platforms actually let apps read varies enormously, and the real limits (like at-rest-only blood pressure) only show up once you dig into the SDKs.
- How to build useful synthetic data when real medical data doesn't exist, and how to be honest about its limits.
- Designing alerts is its own problem: too many and users ignore them, too few and they miss the one that matters. Persistence rules and hysteresis mattered as much as the model.
What's next for R1
- A real run on a physical Galaxy Watch, with the Samsung sensor kit, plus battery measurements over a full marathon.
- Train the drink classifier on the gesture clips we're recording.
- Barometer slope correction to cut false alarms on hills.
- Save run history so the personalized model (which lowered false alarms from 0.26 to 0.16 per hour in simulation) works in the app.
- Race medical integration: when a runner hits the urgent level, alert the nearest medical tent with their location.
- Clinical validation with sports-medicine partners, comparing R1 scores against CK (creatine kinase) blood tests after long races.
- Ports to other watches such as Garmin, and calibration for cycling, hiking and team sports.
Built With
- android-foreground-service
- galaxy-watch
- health-services
- jetpack-compose
- kotlin
- matplotlib
- numpy
- ppg-dalia
- python
- samsung-health-sensor-sdk
- scikit-learn
- scipy
- tensorflow-lite
- wear-os