3D Visualization & Replay Studio
The padelkit.viz module provides an interactive Three.js 3D court visualizer, multi-camera inspector, and synthetic pass viewer (RGB, Semantic Segmentation, Depth, and 17 Court Landmarks) powered by a unified temporal state contract (MatchTimeline).
Operating Modes
- Name
1. CSV / Timeline Replay Mode- Type
- MatchTimeline.from_csv()
- Description
Load any saved match or rally CSV file and scrub through time at
0.25x–2.0xspeed, switch betweenCamerapresets, or drag-and-drop a.csvfile directly into the browser window.
- Name
2. Real-Time Live Streaming Mode- Type
- visualizer.serve()
- Description
Launch a local HTTP + Server-Sent Events (SSE) server and push
FrameStateobjects in real time from a Python simulation loop or live tracking pipeline usingvisualizer.push_frame(frame).
- Name
3. Standalone HTML & Jupyter Mode- Type
- visualizer.export_html()
- Description
Export a self-contained
.htmlfile that runs in any browser with zero server dependencies, or render the 3D studio directly inside a Jupyter / Google Colab notebook cell.
Quickstart: Generate a Rally CSV & Launch the 3D Studio
MatchTimeline.demo_rally() generates a complete 60 FPS 3D rally with realistic ball parabolas, floor and glass-wall rebounds, and 4 articulated players moving and swinging rackets. You can export it to CSV and inspect it in 3D immediately.
CSV Replay & HTML Export
from padelkit import Court, MatchTimeline, PadelVisualizer
court = Court(
dimensions=Court.fip_standard().dimensions,
turf_color="blue",
)
# 1. Generate a 3D rally timeline and save it to CSV
timeline = MatchTimeline.demo_rally(court=court, fps=60.0)
timeline.to_csv("demo_rally.csv")
# 2. Load the CSV into the Three.js 3D Visualizer
# (optionally pass animation_library_dir for Mixamo .glb strokes)
viz = PadelVisualizer.from_csv(
"demo_rally.csv",
court=court,
animation_library_dir="../padelkit-animator/data/animations",
)
# 3. Export standalone HTML or launch interactive server
viz.export_html("padel_studio.html")
# viz.serve(port=8765, open_browser=True)
Real-Time Streaming Mode
When running viz.serve(background=True), your Python code can stream live FrameState updates to all connected browser tabs in real time.
FrameState Properties
- Name
timestamp- Type
- float
- Description
Elapsed time in seconds.
- Name
ball_position- Type
- tuple[float, float, float]
- Description
3D ball coordinates
(X, Y, Z)in meters.
- Name
ball_velocity- Type
- tuple[float, float, float]
- Description
3D linear ball velocity
(vx, vy, vz)inm/s. Exposes.ball_speed_kmh.
- Name
ball_spin- Type
- tuple[float, float, float]
- Description
3D angular velocity
(wx, wy, wz)inrad/s. Exposes.ball_spin_rpmand drives 3D ball seam rotation in the studio.
- Name
players- Type
- dict[str, PlayerPose]
- Description
Dictionary mapping
"P1".."P4"to theirPlayerPose(player_id, x, y, z, yaw_deg, animation, team, swing_phase).
- Name
score- Type
- str
- Description
Formatted match score string displayed on the 3D HUD.
- Name
event- Type
- str | None
- Description
Optional event tag (
"serve","bounce_floor","bounce_glass","shot_smash").
Live Streaming
import time
from padelkit import PadelVisualizer, FrameState, PlayerPose
viz = PadelVisualizer()
viz.serve(port=8765, open_browser=True, background=True)
for step in range(120):
t = step / 60.0
viz.push_frame(
FrameState(
timestamp=t,
ball_position=(0.0, -5.0 + 5.0 * t, 1.2),
players={
"P1": PlayerPose("P1", x=1.8, y=-6.5, yaw_deg=0.0, team="A"),
"P2": PlayerPose("P2", x=-2.0, y=-3.0, yaw_deg=0.0, team="A"),
"P3": PlayerPose("P3", x=-2.2, y=7.0, yaw_deg=180.0, team="B"),
"P4": PlayerPose("P4", x=2.2, y=7.0, yaw_deg=180.0, team="B"),
},
score="0-0 | 15-0 *",
event="live_tracking",
)
)
time.sleep(1 / 60)