golf_tracking / some_math.py
rehctiw25's picture
Upload folder using huggingface_hub
013216e verified
import numpy as np
from scipy.optimize import curve_fit
import matplotlib.pyplot as plt
class TrajectoryFitter:
def __init__(self, gravity=9.81):
self.g = gravity
def trajectory_model(self, t, v0, theta, h0):
"""
Physics model for projectile motion
Parameters:
t: time points
v0: initial velocity
theta: launch angle (in degrees)
h0: initial height
Returns:
(x, y) coordinates at each time t
"""
# Convert angle to radians
theta_rad = np.radians(theta)
# Initial velocities in x and y directions
v0x = v0 * np.cos(theta_rad)
v0y = v0 * np.sin(theta_rad)
# Position equations
x = v0x * t
y = h0 + v0y * t - 0.5 * self.g * t**2
return np.column_stack((x, y))
def fit_trajectory(self, points, times=None):
"""
Fit trajectory to user-selected points
Parameters:
points: array of (x, y) coordinates
times: optional array of timestamps for each point
Returns:
(v0, theta, h0): initial velocity, launch angle, initial height
trajectory: predicted points along entire path
"""
points = np.array(points)
# If times not provided, estimate based on x positions
if times is None:
times = (points[:, 0] - points[0, 0]) / np.linalg.norm(
points[1] - points[0]
)
# Initial guesses
initial_height = points[0, 1]
# Estimate initial angle and velocity from first two points
if len(points) >= 2:
dx = points[1, 0] - points[0, 0]
dy = points[1, 1] - points[0, 1]
initial_theta = np.degrees(np.arctan2(dy, dx))
initial_v0 = np.sqrt(dx**2 + dy**2) / (times[1] - times[0])
else:
initial_theta = 45
initial_v0 = 50
# Fit physics model to points
try:
params, covariance = curve_fit(
lambda t, v0, theta: self.trajectory_model(
t, v0, theta, initial_height
),
times,
points,
p0=[initial_v0, initial_theta],
bounds=([0, -90], [1000, 90]), # Reasonable bounds for golf
)
v0_fit, theta_fit = params
# Generate smooth trajectory for visualization
t_smooth = np.linspace(min(times), max(times), 100)
trajectory = self.trajectory_model(
t_smooth, v0_fit, theta_fit, initial_height
)
return {
"initial_velocity": v0_fit,
"launch_angle": theta_fit,
"initial_height": initial_height,
"trajectory": trajectory,
"times": t_smooth,
"covariance": covariance,
}
except RuntimeError as e:
print(f"Fitting failed: {e}")
return None
def calculate_metrics(self, fit_results):
"""Calculate additional metrics from the fit"""
v0 = fit_results["initial_velocity"]
theta = fit_results["launch_angle"]
h0 = fit_results["initial_height"]
# Maximum height
theta_rad = np.radians(theta)
v0y = v0 * np.sin(theta_rad)
max_height = h0 + (v0y**2) / (2 * self.g)
# Total distance (range)
t_total = (v0y + np.sqrt(v0y**2 + 2 * self.g * h0)) / self.g
total_distance = v0 * np.cos(theta_rad) * t_total
# Flight time
flight_time = t_total
return {
"max_height": max_height,
"total_distance": total_distance,
"flight_time": flight_time,
"initial_velocity_mph": v0 * 2.237, # Convert m/s to mph
}
def plot_trajectory(self, points, fit_results):
"""Visualize the fitted trajectory and original points"""
plt.figure(figsize=(12, 6))
# Plot original points
points = np.array(points)
plt.scatter(points[:, 0], points[:, 1], color="red", label="Selected Points")
# Plot fitted trajectory
trajectory = fit_results["trajectory"]
plt.plot(trajectory[:, 0], trajectory[:, 1], "b-", label="Fitted Trajectory")
plt.grid(True)
plt.xlabel("Distance (m)")
plt.ylabel("Height (m)")
plt.title("Golf Ball Trajectory Fit")
plt.legend()
plt.axis("equal")
plt.show()
# Example usage:
if __name__ == "__main__":
# Sample points (x, y) in meters
points = [
(0, 0), # Starting point
(50, 20), # Some point during flight
(100, 0), # Landing point
]
fitter = TrajectoryFitter()
results = fitter.fit_trajectory(points)
if results:
metrics = fitter.calculate_metrics(results)
print("\nFitted Parameters:")
print(
f"Initial Velocity: {results['initial_velocity']:.1f} m/s ({metrics['initial_velocity_mph']:.1f} mph)"
)
print(f"Launch Angle: {results['launch_angle']:.1f} degrees")
print(f"Max Height: {metrics['max_height']:.1f} m")
print(f"Total Distance: {metrics['total_distance']:.1f} m")
print(f"Flight Time: {metrics['flight_time']:.1f} s")
fitter.plot_trajectory(points, results)