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
What PopSense measures
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.
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.
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
-
Distance + route from HealthKit's
HKWorkoutRoute(watch path) or Core Location (phone path, when you permit it). - Heart rate from HealthKit. We down-sample to 2000 points max so the app doesn't stall on multi-hour sessions.
- Active energy (kcal) and duration from HealthKit.
- Stance and wrist from your profile. These gate rotation direction and per-trick priors.
How trick prediction works
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.
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.
Calibration
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.
Model visualiser
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.
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.
What PopSense does not do
Not a medical device. Not a video recorder.
- We don't record audio or video.
- We don't sell motion data. Ever. The revenue model is the membership, not a pipeline.
- PopSense is not a medical device. Heart rate and calorie figures come straight from Apple Health and inherit Apple's accuracy disclaimers.
- Trick detection is experimental. It will miss tricks. It will mis-call tricks. You always have the last word on what actually landed.
- Location sharing is opt-in per session. You can log a sesh with the route hidden.
- Body metrics (date of birth, height, weight, resting HR) are read from Apple Health only when you tap the sync tile in Settings. They stay on your own profile row under RLS and are never joined into a session you share. The global opt-in pool sees only 5-year age, 5-cm height, and 5-kg weight buckets; individual values never leave your account.
The opt-in training pool
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
- Air time, rotation degrees, impact peak g.
- Post-impact chaos (a normalised 0-1 motion-variance score).
- Waveform-derived summaries: peak y-axis rotation rate, rotation-axis ratio, spin signedness, pre-impact tilt, landing jerk.
- Speed at event, altitude at event, derived intensity zone.
- The trick name you confirmed, and your stance.
- Whether the sample came from calibration.
- Your anthropometric bucket: 5-year age band, 5-cm height band, 5-kg weight band. Only populated if you've synced body metrics from Apple Health; skipped otherwise.
What doesn't
- No user id, no session id, no timestamps.
- No location, no route.
- No raw sensor timeseries. The ±250 ms waveform snapshot is stored only on your own row; it's never part of the anonymised pool.
- No per-event heart rate, no video, no audio.
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.
Accuracy + limits
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
- Wear OS companion app (parity with Apple Watch).
- Samsung Health and Garmin Connect direct integrations. Health Connect already aggregates these upstream.
- Date-of-birth sync (no Health Connect record type exists).
- Slam and rotation detection. These are already Apple Watch only on iOS · a pocketed phone's gyro and filtered accelerometer feed aren't sharp enough on either platform.
Data footprint
Where your data actually lives.
- On your device. Apple Health keeps your workouts, route, heart rate, and energy. skateable. reads from Apple Health when you authorise it; nothing gets copied anywhere else without you logging it. The offline queue that keeps the app working without a network also lives on your device.
- Your skateable. account. When you log a session, skateable. keeps the summary you chose to share (park, duration, rating, pop count, distance, HR averages) plus the per-pop motion features (air time, rotation, impact) that make future predictions better for you.
- Per-event waveform snapshot (~2.5 KB per pop). A ±250 ms slice of 3-axis accelerometer, gravity, and gyroscope readings around every landing, plus the HR / speed / altitude / pressure at that instant. Stored only on your own account row; not included in the anonymised training pool.
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).
Versions
What's in 2.0
The first shipping version of PopSense, live on iOS in skateable. 2.0.
- Watch and phone detection paths.
- End-of-session trick cards with a top-3 shortlist, catalogue autocomplete, and combo builder.
- Three-layer prediction blend (your history, global opt-in pool, rule classifier).
- Calibration flow (Ollie, Pop Shuv-it, FS 180, BS 180, Kickflip).
- Offline session queue survives airplane mode and app quits.
- HealthKit re-import for sessions that never made it off the watch.
References
What it's built on.
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.
CMMotionManager
The 50 Hz accelerometer + gyroscope source powering pop detection. Calibration, stance inference, and rotation integration all run off Device Motion.
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.
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.
Full disclosure of what we collect, where it lives, and what leaves your device.