BallPhysicsEngine
BallPhysicsEngine is the 9-Dimensional aerodynamic and multi-surface contact simulator in PadelKit. It integrates gravity, felt-adjusted quadratic air drag, and non-linear Spindt Magnus lift via 4th-order Runge-Kutta (RK4), and resolves collisions against the floor, stepped walls/fences, and catenary net of a Court.
Properties
- Name
court- Type
- Court
- Description
The
Courtgeometry defining floor bounds, stepped wall/glass heights (3mvs4m), metallic fences, and net profile.
- Name
ball- Type
- BallProperties
- Description
Physical ball specification (mass, radius, drag and felt fuzz coefficients). See
BallProperties.
- Name
environment- Type
- EnvironmentConditions
- Description
Atmospheric conditions (gravity, air density, temperature, altitude, wind velocity). See
EnvironmentConditions.
- Name
surfaces- Type
- SurfaceMaterials
- Description
Coefficients of restitution (
COR) and Coulomb friction (mu) for floor, glass, wall, fence, and net. SeeSurfaceMaterials.
Simulate a Trajectory
Integrates a BallState forward in time using RK4 (dt = 0.002s by default), resolving all court surface rebounds and recording every BounceEvent. Returns a BallTrajectory.
Arguments
- Name
initial_state- Type
- BallState
- Description
Initial 9D state
[x, y, z, vx, vy, vz, wx, wy, wz].
- Name
duration- Type
- float
- Description
Maximum simulation duration in seconds.
- Name
dt- Type
- float
- Description
Integration time step in seconds (
500 Hzdefault).
- Name
stop_on_net- Type
- bool
- Description
If
True, stops the simulation immediately after a net collision.
- Name
max_bounces- Type
- int | None
- Description
Optional maximum number of bounces before terminating early.
- Name
stop_below_speed- Type
- float
- Description
Stops simulation when ball speed drops below this threshold (
m/s) on the floor.
Usage
from padelkit import BallPhysicsEngine, BallState
engine = BallPhysicsEngine()
shot = BallState.from_shot(
position=(0.0, -7.0, 1.1),
velocity=(1.5, 19.0, 3.2),
topspin_rpm=2200.0,
)
trajectory = engine.simulate(shot, duration=2.5, max_bounces=3)
print(f"Samples: {len(trajectory.times)}, Bounces: {len(trajectory.bounces)}")
Output
Samples: 842, Bounces: 3
Vectorized Batch Simulation
Simulates N independent 9D ball trajectories simultaneously using vectorized NumPy arrays. Ideal for Monte Carlo shot dispersion analysis, reinforcement learning rollouts, and synthetic dataset generation.
Arguments
- Name
initial_states- Type
- np.ndarray | Sequence[BallState]
- Description
Array of shape
(N, 9)or sequence ofNBallStateinstances.
- Name
duration- Type
- float
- Description
Total simulation duration in seconds.
- Name
dt- Type
- float
- Description
RK4 integration time step in seconds.
Returns
- Name
times- Type
- np.ndarray
- Description
1D array of timestamps in seconds of shape
(T,).
- Name
states- Type
- np.ndarray
- Description
3D float64 tensor of shape
(N, T, 9)containing[x, y, z, vx, vy, vz, wx, wy, wz]for allNtrajectories across allTsteps.
Batch Simulation
import numpy as np
from padelkit import BallPhysicsEngine
engine = BallPhysicsEngine()
# 100 shots with randomized launch angles and topspin
n_shots = 100
states_0 = np.zeros((n_shots, 9), dtype=np.float64)
states_0[:, 1] = -8.0 # y0 = -8m
states_0[:, 2] = 1.2 # z0 = 1.2m
states_0[:, 4] = np.linspace(14.0, 22.0, n_shots) # vy
states_0[:, 5] = 3.5 # vz
states_0[:, 6] = 200.0 # topspin wx (rad/s)
times, batch_states = engine.simulate_batch(states_0, duration=2.0)
Output
# batch_states.shape
(100, 1001, 9)
Single-Step & Collision Primitives
For custom control loops or frame-by-frame interactive games, BallPhysicsEngine exposes its low-level physics primitives directly:
- Name
step(state, dt=0.002, t=0.0)- Type
- tuple[BallState, BounceEvent | None]
- Description
Advances a
BallStateby a single timestepdtusing RK4 and resolves any court surface collision.
- Name
compute_acceleration(velocity, angular_velocity)- Type
- np.ndarray
- Description
Computes the instantaneous 3D acceleration vector
(ax, ay, az)inm/s^2combining gravity, quadratic drag, and Spindt Magnus lift.
- Name
resolve_collision(velocity, angular_velocity, normal, surface)- Type
- tuple[np.ndarray, np.ndarray, ContactRegime]
- Description
Computes post-impact linear velocity
v', angular velocityw', andContactRegime(SLIDING,ROLLING, orDAMPED) against a unit surface normaln.
Low-Level Step
import numpy as np
from padelkit import BallPhysicsEngine, SurfaceType
engine = BallPhysicsEngine()
# Inspect post-bounce velocity & spin on turf floor
v_in = np.array([0.0, 15.0, -8.0])
w_in = np.array([-250.0, 0.0, 0.0]) # heavy backspin
normal = np.array([0.0, 0.0, 1.0])
v_out, w_out, regime = engine.resolve_collision(
v_in, w_in, normal, SurfaceType.FLOOR
)