skateable.skateable.

PopSense

Your wrist. Your skate. Your stats.

New in 2.0 · wrist-on, pocket-on tracking

What you landed today, not just what you skated.

PopSense is the newest part of skateable. It reads the motion of your wrist (and the board underneath it) and stacks it into a session: pops, air time, rotation, tricks, slams, distance, heart rate. No tapping mid-skate. Nothing leaving your device for some third-party cloud to guess at.

Live in skateable. 2.0

Two sensors, one session.

PopSense reads accelerometer and gyroscope samples at 50 Hz from the watch (wrist) or the phone (in your pocket), plus Apple Health's workout data (route, heart rate, calories, distance). Everything else, the trick calls and the pop count, is derived on your device.

Per event, PopSense now captures a full 3-axis snapshot: user acceleration, gravity, and rotation rate on all three axes. The latest GPS fix (speed + altitude) and a CMAltimeter pressure sample ride along, plus the heart-rate reading nearest the landing. These feed the trick classifier below and stay on the row for future deeper classifiers.

Waveform window ±250 ms around each landing ─ 50 Hz sampling = 25 samples × 9 axes (accel xyz, gravity xyz, gyro xyz). ~2.5 KB per event, stored as jsonb.

The pop signature

A pop is the airborne window right after you pop the tail: you and the board leave the ground together, the wrist briefly feels weightless, then the landing lands as a sharp spike.

Pop detection (simplified) airborne = |anet(t)| < 0.3 g for 120 ms ≤ Δt ≤ 700 ms landing = |anet(t + Δt)| > 1.8 g within 50 ms pop air time = Δt rotation = ∫ ωyaw dt over Δt

A slam is the same shape with a harder landing (> 3.5 g), a chaotic motion window on the back of it (you tumbling), and usually a much shorter airborne window in front.

What else lands

Three layers, one card per trick.

Your watch stays a sensor. It counts pops and slams and captures air time, rotation, and impact; it never tries to name the trick while you're skating. When you step off and end the session on your iPhone, PopSense groups your pops into trick cards ("Kickflip × 3", "Frontside 180 × 2") so you can confirm, correct, or toss them. The candidate list is a blended weighted vote from three sources, all running on your phone.

your labelled pops (weight 3) ─┐ calibration samples (+2x multiplier) ├─> weighted kNN ─> top-3 candidates ─> cluster ─> card global opt-in pool (weight 1) │ ⬆ rule classifier (weight 0.5) ─┘ └─ combo if < 1.5 s gap

Each candidate is scored with a weighted z-score over a richer feature vector than the original three summary stats. Air time, rotation, and impact still carry the most weight; post-impact chaos, stance, detection source (watch vs phone-pocket), and session-level context (average heart rate, distance, elevation) nudge scores where a pop sits right on the edge between two clusters.

Five extra features come out of the per-event waveform: peak y-axis rotation rate, rotation-axis ratio (separates board flips from body rotations), spin signedness (frontside vs backside), pre-impact tilt, and landing jerk. Those plus per-event heart rate, speed, and altitude also feed the distance metric. Raw waveforms stay on the row for future non-kNN classifiers (DTW, 1D CNN); the kNN itself only consumes the derived summary stats.

In the wild

PopSense sees a pop with 420 ms of air and 10° of rotation, regular stance. Four of your last five kickflips sit in the same feature-space sphere, so the card comes out as Kickflip at 72 % confidence. The rule classifier would have called it an Ollie (which always has a slightly higher prior), but your own history outvotes it.

Clustering

Consecutive pops that share the same top candidate and sit within ±25 % of each other in feature space collapse into one card with a landed count. You see a summary of what you did, not a pop-by-pop transcript.

Combos

Two pops less than 1500 ms apart link up into one combo card. You can edit either half from the card's detail sheet.

Unsure

When the top candidate scores below 0.4, PopSense shows a single “?” card instead of guessing. Label the whole group at once, split it, or skip it. Honest beats confident-but-wrong.

Heads-up. Rotation and slam detection are Apple Watch only. A pocketed phone tumbles with every push and weight shift, so gyro-based rotation buckets would be noise, and the 50 Hz filtered DeviceMotion feed isn't sharp enough for reliable slam classification. Phone-pocket pops are treated as “straight pop / shove” with a ~30 % confidence penalty. A future native Swift module can unlock both.

Five tricks to teach PopSense your style.

Before your first session you can run a 5-trick calibration: Ollie, Pop Shuv-it, Frontside 180, Backside 180, Kickflip. Each one gets tagged is_calibration = true in the motion event log, which doubles its weight in the kNN prior. Clean calibration means cleaner labels, which means better predictions for you (and, if you opt in, for everyone else in the pool).

Phone-pocket placement

On the phone path, lock the phone into a front or back pocket where it can't flop around. Detection needs the phone moving with your body, not bouncing on its own.

No need to roll away

PopSense is listening for the pop, not the landing. Bail, sketch it, slap a foot down · the classifier still gets a clean motion signature off the attempt. If a trick is out of your range, skip it; the kNN happily works with three or four calibration samples instead of five.

Skipping it

You don't have to. The rule classifier covers the cold start, and every trick you confirm at the end of a session feeds straight back into your personal kNN for next time.

Body metrics sync

In Settings → PopSense, tap Sync body metrics to let PopSense read your date of birth, height, weight, and resting HR from Apple Health. Nothing is read until you tap the tile; the values land on your skateable. profile and stay RLS-scoped to your account. They are used to narrow the global opt-in pool to skaters with similar body dimensions and to derive a per-event intensity zone for your own sessions.

See where your pops cluster.

The PopSense tab shows your labelled pops scattered in feature space so you can see which tricks land in tight, predictable clusters and which sprawl across the chart. Clusters that sit far apart are easy to call; clusters that overlap are where the predictor will ask “kickflip or heelflip?” at the end of a session.

range chips Day · Week · Month · All-time ─> filter by created_at projection chips Air·Rot · Air·Impact · Rot·Impact · PCA ─> pick 2 axes or top-2 PCs global overlay (opt-in gated) ─> faint background dots legend tap ─> highlight one cluster dot tap ─> tooltip with features + date

The card also runs a leave-one-out self-check over your labelled rows: for each pop, it holds that row out, runs the full prediction path against the rest, and records whether the top candidate matches your confirmed label. The rolling percentage under the chart is an honest reliability score · it goes up as you label more tricks and your clusters tighten.

Not a medical device. Not a video recorder.

Skateboarders helping skateboarders.

PopSense gets sharper the more labelled tricks it sees. If you opt in (Settings → PopSense → Help train PopSense), the motion features from tricks you've labelled drop into an anonymised pool that other opted-in skaters' predictions can draw from. Opt in, opt out, any time.

What joins the pool

What doesn't

Only opted-in users' labels are queryable, and identifying columns are stripped before any result reaches the app. Turn the toggle off and your data stops entering the pool immediately; anything already anonymised stays as an unidentifiable feature vector with no link back to you.

Bucketing is how the pool personalises neighbour selection without exposing identifying body data. Picking a 5-year age band rather than an exact age means a user in the 25-29 band is indistinguishable from any other skater in the same band, while the predictor can still prefer their cluster over the 55-59 band when deciding a trick call.

See the privacy policy for the full list.

Here's where it breaks.

PopSense is live in 2.0 on iOS (iPhone alone or paired with an Apple Watch) and on Android as a phone-only path backed by Health Connect. The table below shows which signals each device can produce.

Signal Apple Watch iPhone (pocket) Android (pocket)
Pop count Good Good Good
Air time Good Okay Okay
Rotation degrees Good Apple Watch only · pocket gyro too noisy Not in v1 · same pocket-gyro problem, no Wear OS companion yet
Kickflip vs heelflip Needs user history · disambiguated by spin-axis signedness when 3-axis capture is on Needs user history Needs user history
Heart rate at event HR sample nearest the landing Not captured Health Connect, when permitted
Speed at event CLLocation.speed Not captured FusedLocationProvider.speed (opt-in)
Altitude + pressure GPS altitude + CMAltimeter Not captured GPS altitude only · no pressure API parity
Slam detection Good Apple Watch only · 50 Hz filtered feed too coarse for chaos analysis Not in v1 · same constraint, no watch companion yet
Distance + route Apple Health Core Location (opt-in) Fused Location (opt-in)
Body metrics sync HealthKit · date of birth, height, weight, resting HR Health Connect · height, weight, resting HR (no DOB record type)
Model self-check (LOO) Reads back in the PopSense tab Reads back in the PopSense tab Reads back in the PopSense tab
Intensity zone Derived from max HR via Karvonen Derived from max HR via Karvonen Derived from max HR via Karvonen

The board spins but your wrist mostly doesn't, so flips that share a straight-pop signature (kickflip, heelflip, varial, hardflip) look the same from the wrist alone. The personal kNN leans on what you've actually been landing to bias toward the flip you do.

Out of scope for Android v1

Where your data actually lives.

Delete a session and everything tied to it is removed at the same time. Anything already anonymised into the training pool before deletion stays as an unidentifiable feature vector with no link back to you (see the opt-in section above).

What's in 2.0

The first shipping version of PopSense, live on iOS in skateable. 2.0.

What it's built on.

Apple Developer Documentation view ›

HealthKit + WorkoutKit

Source of the session bookends (start, end, duration), the distance and route polyline, the heart rate series, and the active-energy estimate. PopSense reads from HealthKit; it never writes untruthful workouts back.

Apple Developer Documentation view ›

CMMotionManager

The 50 Hz accelerometer + gyroscope source powering pop detection. Calibration, stance inference, and rotation integration all run off Device Motion.

Fix, E. & Hodges, J. L. (1951) view ›

Discriminatory analysis, nonparametric discrimination

The original k-nearest-neighbours paper. PopSense's prediction blend uses a weighted kNN over normalised motion features, with per-source weights chosen to prioritise the user's own labels above the global pool.

Karvonen, M. J., Kentala, E. & Mustala, O. (1957) view ›

The effects of training on heart rate

Source of the heart-rate reserve formula PopSense uses to derive per-event intensity zones (1 through 5) from your synced max HR and resting HR. The zone rides along on each labelled pop so the classifier can factor fatigue into neighbour selection.

skateable. Privacy Policy

/docs/privacy

Full disclosure of what we collect, where it lives, and what leaves your device.