rall Trust

The trust contract

How we measure, and how confident we are.

Rallo claims numbers. Knee bend in degrees. Contact height in centimetres. Racket-head speed in km/h. Every one of those numbers carries an error band, a set of capture conditions it depends on, and a reference we validate against. This page is the engineering contract behind those numbers, in plain language. If a metric is missing here, it is not in the app.

The matrix below is the public face of docs/metrics_matrix.yaml, the file the app, the engine, and our release CI all read from. The two are kept in sync. When the matrix changes, this page changes; we list every change at the bottom.

01 /What we measure

Three confidence tiers. High-confidence metrics are published as a number with a tight band. Medium-confidence metrics are published with a wider band or as a qualitative bucket. The third tier is the list of numbers we will not show you, and the reasons.

High confidence Number with band

Rendered as a number with its error band. The band is anchored to a reference — goniometer, mocap, radar gun, or a tape measure on a calibrated court. If the capture conditions for a metric fail, the metric is hidden and the app says why.

Metric Units Error band Capture required
Knee bend at loading degrees ± 5° SIDE_VIEW
Trophy elbow angle degrees ± 5° SIDE_VIEW
Knee joint angle (general) degrees ± 5° controlled, ± 8° peak SIDE_VIEWPLAYER_IN_FRAME
Elbow joint angle degrees ± 5° controlled, ± 8° peak SIDE_VIEWPLAYER_IN_FRAME
Shoulder elevation angle degrees ± 5° controlled, ± 8° peak SIDE_VIEW
Wrist layback angle degrees ± 5° controlled, ± 8° peak SIDE_VIEW
Body rotation at contact degrees ± 5° AUDIO_FIDELITY
Racket path angle degrees, low to high ± 5° SIDE_VIEWFRAMERATE_120+
Racket drop depth cm below top of head ± 5 cm SIDE_VIEW
Racket drop dwell time ms ± 16 ms (1 frame at 60 fps) FRAMERATE_60+
Contact height above shoulder cm, court-calibrated ± 5 cm COURT_CALIBRATEDSIDE_VIEW
Forward contact distance cm in front of lead hip ± 5 cm COURT_CALIBRATEDSIDE_VIEWAUDIO_FIDELITY
Contact lateral position cm from body midline ± 5 cm AUDIO_FIDELITY
Toss height cm above contact ± 5 cm COURT_CALIBRATED
Toss lateral placement cm from center mark ± 5 cm COURT_CALIBRATEDBEHIND_FENCE
Vertical hip displacement cm ± 2 cm at typical 6–8 m, ± 1 cm at tight 4 m COURT_CALIBRATEDSIDE_VIEW
Forward weight transfer cm of CoM travel ± 5 cm COURT_CALIBRATEDSIDE_VIEW
Balance offset cm ± 5 cm SIDE_VIEW
Player position on court (x, y) m on court surface ± 5 cm COURT_CALIBRATED
Ball placement at bounce court coordinates, in/out ± 10–20 cm COURT_CALIBRATED
Outgoing ball speed km/h ± 5 km/h vs radar reference COURT_CALIBRATEDFRAMERATE_120+
Contact timing (audio anchored) ms ≤ 5 ms RMS vs hand label, ≤ 2 ms vs mocap AUDIO_FIDELITY
Stroke phase boundaries frame index per phase ≤ 2 frames at 60 fps (~33 ms) PLAYER_IN_FRAME
Split-step timing ms vs opposing-stroke-end ± 1 frame at 60 fps PLAYER_IN_FRAME
Racket tip 2D trajectory pixels per frame, 1080p ≤ 8 px error, ≥ 95 % detection on unoccluded frames SHUTTER_LOCKED_FAST
Racket tip court-plane trajectory (x, y) m on court ≤ 5 cm RMS during groundstroke phases, ≤ 10 cm at peak swing COURT_CALIBRATEDSHUTTER_LOCKED_FAST
Volley backswing length cm, target < 10 cm ± 3 cm SIDE_VIEW
Volley followthrough length cm, target < 25 cm ± 3 cm SIDE_VIEW
Volley wrist-angle variation degrees through contact ± 3° FRAMERATE_120+
Choke-up grip detection cm of palm above grip butt ± 1 cm SIDE_VIEW
Grip type categorical: continental, eastern, semi-western, western ≥ 90 % correct, contact frame SIDE_VIEWPLAYER_IN_FRAME
Stroke type identification 12-class (serve flat / slice / kick, FH topspin / slice, BH 1H / 2H / slice, volleys, smash) macro F1 ≥ 0.92 on internal benchmark PLAYER_IN_FRAME
Backhand handedness (1H vs 2H) categorical ≥ 95 % correct in contact ± 100 ms window PLAYER_IN_FRAME
Court calibration status categorical: ok / degraded / failed RMSE < 2 cm on the singles court INTRINSICS_PRESENT

Medium confidence Number with caveat, or qualitative bucket

Either the band is wider than coaching needs, the signal isn't fully validated yet, or a physics floor (camera frame rate, motion blur) caps the achievable accuracy. Where the band exceeds what a coach would call useful, the app drops the number and shows a qualitative bucket instead.

Metric Units Error band Capture required
Kinematic sequence (2D, v1 path) verdict: proper / partial / inverted / insufficient, with adjacent lead-gap (ms) verdict only; pipeline runs end-to-end on bundled pro side-view canaries (Federer FH, Sinner BH); per-clip mocap cross-check is v1.1 work SIDE_VIEWPLAYER_IN_FRAME
Hip–shoulder separation (X-factor) degrees, 3D ± 5°, peak timing ± 1 frame at 60 fps SIDE_VIEW
Hip–shoulder separation timing ms ± 1 frame at 240 fps (~4 ms), audio-anchored FRAMERATE_240AUDIO_FIDELITY
Stance class categorical: open / semi-open / neutral / closed ≥ 80 % on internal labelled set COURT_CALIBRATEDSIDE_VIEW
Racket-head speed (groundstrokes 60–120 km/h) km/h ± 8–12 km/h (240 fps sampling-rate floor) FRAMERATE_240SHUTTER_LOCKED_FASTAUDIO_FIDELITYCOURT_CALIBRATED
Racket-head speed (serves 120–200 km/h) km/h, or qualitative bucket if band > 15 km/h ± 10–15 km/h (sampling-rate floor) FRAMERATE_240SHUTTER_LOCKED_FASTAUDIO_FIDELITYCOURT_CALIBRATED
Racket face orientation at contact degrees from vertical ± 8°, hidden if motion blur > 8 px or racket edge-on FRAMERATE_240SHUTTER_LOCKED_FASTAUDIO_FIDELITY
Brush distance (topspin) cm of vertical racket-tip travel through contact ± 10 cm FRAMERATE_240AUDIO_FIDELITY
Spin classification categorical: topspin / flat / slice ≥ 90 % on internal labelled set AUDIO_FIDELITY
Contact timing (visual fallback, no audio) ms ± 16–33 ms (visual frame quantum at 30–60 fps) PLAYER_IN_FRAME
Foot-fault check categorical with cm-over-line if true ± 15 cm boundary uncertainty (ankle-only) COURT_CALIBRATEDBEHIND_FENCETRIPOD
Forehand late-contact catch position categorical: late / on-time / out-front qualitative bucket; no degree band claimed PLAYER_IN_FRAME
Forehand hip rotation (load → contact) degrees, image-plane ± 10° on side-view; behind-fence reads attenuated PLAYER_IN_FRAME
Forehand shoulder rotation (load → contact) degrees, image-plane ± 10° on side-view PLAYER_IN_FRAME
Backhand late-contact catch position categorical: late / on-time / out-front qualitative bucket PLAYER_IN_FRAME
Backhand shoulder rotation (load → contact) degrees, image-plane ± 10°; 1H BH band 95–130°, 2H BH band 80–110° PLAYER_IN_FRAME

What we don't claim Hidden in v1

A single phone on a tripod cannot recover every measurement a biomechanics lab can. Where the physics or the licensing block a credible number, we hide the metric and tell you why instead of fudging it. These are the lines we will not cross to look more impressive.

What we don't show Why
Spin in RPM Optical RPM measurement of a tennis ball from a single phone is not solved at consumer hardware. Phones can't deliver > 1000 fps consistently; specialised radar or Doppler is required. We show qualitative spin (topspin / flat / slice) instead.
Pose-derived ball speed in mph as a precise number Pose-only estimation lands at roughly ± 8 % accuracy. That's not a number to put next to a radar gun. Outgoing ball speed comes from ball tracking with court calibration (high confidence, see above), not from the player's pose. Anything called "swing speed" without ball tracking gets a qualitative bucket.
Clinical 3D internal joint angles at impact A single monocular camera cannot recover hidden depth at peak velocities. Published floors for monocular methods sit around 4.8° rotational MAE under good conditions; that is not clinical grade. Bert AI and OnCourtAI display these anyway. We don't.
Joint torques and kinetic-chain power Requires force plates or instrumented insoles. Camera-only ML estimation that approaches lab grade is research-licence-only and cannot ship in a commercial app.
Internal shoulder rotation and pronation at impact Occluded and motion-blurred even at 240 fps from a side-view phone. An optional racket-butt IMU sensor add-on is on the v2 path.
3D string-bed normal at impact The racket is edge-on, blurred, or occluded at impact. A 3-frame illustration is not a continuous 3D measurement and will not be shown as one.
Ground reaction force No camera-only path. Needs force plates or instrumented insoles.
Foot-strike pattern (heel vs toe) Requires heel and first-metatarsal keypoints. The pose stack we use has ankle only, no foot keypoints. Documented as a known gap, not silently substituted. v2 path adds a small targeted foot-keypoint detector.
Foot pronation 3D foot orientation requires foot keypoints with depth. Single-phone monocular cannot resolve this reliably. Same v2 path.
Sub-cm foot-fault precision Sub-cm requires foot extent (toe and heel), not just ankle. v1 ships a coarse near-baseline / past-baseline read with a ± 15 cm buffer. We will not say "out by 3 cm" until the foot detector ships.
Injury-risk diagnosis Out of scope. Clinical claims unsupported by single-phone biomechanics, with liability we will not assume.
Match-play analysis v1 is practice only. Match play violates the capture contract: handheld phone, no tripod, no consistent court calibration, no locked exposure. The app refuses to enter metric mode under those conditions instead of silently degrading. Match analysis returns as a v2+ feature once the on-tripod product is shipped and trusted.
"AI tennis coach used by ATP players" or similar global accuracy claims Marketing language without external validation. We will not put it next to a metric until pro-canary results plus independent coach review pass for two release cycles.

02 /How we validate

Each band above is anchored to a reference. The references are mocap, goniometers, hand labels, radar, and pro-clip canaries. The anchor for each metric is in the matrix file; the categories below are the references we use most.

Reference What it validates
Vicon mocap (150 Hz, full marker protocol) Joint angles at peak motion, kinematic-sequence ordering, racket-head speed, leg-drive timing. The reference for everything that makes a degrees-or-millimetres claim.
Goniometer comparison Slow controlled swings: knee flexion, elbow angle, shoulder elevation, wrist layback. The reference for our ± 5° controlled bands.
Radar-gun cross-check (100 strokes) Outgoing ball speed in km/h. The radar reading and the ball-tracking reading must agree within ± 5 km/h.
Tape-measured court points Court calibration RMSE. ITF court dimensions are exact, so a tape measure on the lines is a hard reference.
Hand-labelled benchmarks Stroke ID (~ 2000 strokes, balanced classes). Phase boundaries (200 strokes). Stance class (500 strokes). Grip type (200 contacts, cross-checked with a USPTA coach). Forehand and backhand defect labels (30-clip recreational set + bundled pro side-view clips).
Pro-clip canaries Bundled Djokovic serve, Sinner forehand, and Alcaraz backhand fixtures. Every release run on these clips before ship. The serve must read at ≥ 180 km/h racket-head speed; the forehand canary must read at ≥ 145 km/h with X-factor present. Aggregate score floor is 90 / 100. Canary failure blocks release.
Public datasets Training and validation use public-only data: THETIS for stroke ID, AthletePose3D and Tennis-MoCap for 3D pose, RacketVision for racket keypoints and ball, AthleticsPose and COCO-Wholebody for pose pretraining. Held-out splits validate the same metrics. We don't lean on proprietary clips — outsiders can reproduce the numbers.

The mocap and audio-anchored kinematic sequence (the high-confidence version that uses 240 fps + impact-onset audio as t=0) is staged for v1.5. The 2D kinematic sequence at medium confidence ships now using the bundled pro canaries as its reference; a wider mocap cross-check is planned for v1.1.

03 /Capture conditions

The bands above hold when the capture meets the conditions below. The app evaluates these every session and tells you when a metric is hidden because a condition failed. Practice sessions only. No match play in v1 — the conditions can't be met handheld, courtside, mid-rally.

PLAYER_IN_FRAME

Player visible across the stroke

At least 90 % of player keypoints present in every frame across the stroke arc. If the player walks out of frame mid-swing, that stroke is flagged low confidence.

COURT_CALIBRATED

Court calibration locked

The on-device court detector or a 4-tap court anchoring pass solves the camera pose against the court geometry. RMSE under 2 cm on the singles court. Re-evaluated continuously; if the tripod bumps and the calibration drifts, the affected metrics pause until you tap to recalibrate.

SIDE_VIEW

Side view (parallel to baseline)

Required for joint angles, racket drop depth, contact height, and most kinetic-chain reads. The app's first-frame view classifier flags the angle and selects the per-angle metric set.

BEHIND_FENCE

Behind fence (perpendicular to baseline)

Required for serve toss lateral placement, foot-fault check, and the behind-fence half of the serve report. We support both views; the report uses whichever angles are present.

FRAMERATE_120+

120 fps or better

Required for outgoing ball speed and any frame-quantised timing claim tighter than 33 ms. Below 120 fps, those metrics are hidden.

FRAMERATE_240

240 fps (slow-mo)

Required for racket-head speed at impact, body rotation timing in milliseconds, and brush distance through contact. iPhone 14 Pro and newer can sustain 240 fps; older devices fall back to 120 fps and the affected metrics are hidden.

SHUTTER_LOCKED_FAST

Shutter locked at 1/500 s or faster

Locked exposure, ISO, and shutter at recording start. Without this, the racket motion-blurs to a streak at impact and the keypoint detector can't read it.

AUDIO_FIDELITY

Audio impact band clean

Phone built-in microphone, RMS in the 3–5 kHz transient band above floor. The audio onset gives sub-frame contact timing. If the wind or distance kills the impact transient, contact timing falls back to a wider visual-only band and the app says so.

TRIPOD

Tripod-class stability

IMU-measured orientation noise under 0.1°. Stable handheld is supported with widened bands; wobbly capture is review-only and the metric layer is silent. Foot-fault detection always requires tripod.

04 /What we changed

The trust contract changes. When it does, we list the change here and date it. No silent revisions.

2026-05-07
Added the 2D kinematic sequence verdict at medium confidence as the v1 path. The high-confidence audio-anchored version (240 fps + impact onset as t=0) waits on v1.5. The 2D version reports a verdict (proper / partial / inverted / insufficient) plus per-adjacent-pair lead-gap in milliseconds; no degrees-per-second number is published.
2026-04-28
Revised racket-head speed bands from "± 5 % vs lab mocap" to per-stroke-class bands: ± 8–12 km/h on groundstrokes, ± 10–15 km/h on serves. The change reflects the sampling-rate floor at 240 fps for fast impacts: a single video frame at 150 km/h moves the racket tip about 17 cm, and finite-difference velocity is bounded by that regardless of model quality. If the band exceeds 15 km/h we drop the number and show a hard / medium / soft bucket instead.
2026-04-28
Narrowed v1 use-case scope to practice sessions only — drills, ball machine, basket feeding, serve practice, cooperative rallies, lessons. Match play moved out of v1 because the capture conditions can't be met handheld, courtside, mid-rally. Match analysis returns as a v2+ feature once the on-tripod product is shipped and validated.
2026-04-28
Vertical hip displacement band split by capture distance: ± 2 cm at the typical 6–8 m setup, ± 1 cm only at tight 4 m framing. The original "≤ 1 cm" claim assumed every clip was tight-framed; pixel-per-cm math at 1080p, 6 m, ~73° HFOV is the binding constraint.