Have you tried using a Kalman filter:
import numpy as npimport matplotlib.pyplot as pltg = 9.81e = 0.8t_step = 0.01# Initial actual ball trajectory dataactual_x = np.array([7.410000e-03, 9.591000e-02, 2.844100e-01, 5.729100e-01, 9.614100e-01, 1.449910e+00, 2.038410e+00, 2.726910e+00, 3.373700e+00, 4.040770e+00, 4.800040e+00, 5.577610e+00, 6.355180e+00, 7.132750e+00, 7.910320e+00, 8.687900e+00, 9.465470e+00, 1.020976e+01, 1.092333e+01, 1.163690e+01, 1.235047e+01, 1.306404e+01, 1.377762e+01, 1.449119e+01])actual_y = np.array([2.991964, 2.903274, 2.716584, 2.431894, 2.049204, 1.568514, 0.989824, 0.313134, 0.311512, 0.646741, 0.88397, 1.0232, 1.064429, 1.007658, 0.852887, 0.600116, 0.249345, 0.232557, 0.516523, 0.702488, 0.790454, 0.78042, 0.672385, 0.466351])# Initial state (position & velocity)initial_state = np.array([0, 2, 10 * np.cos(np.radians(45)), 10 * np.sin(np.radians(45))]) # [x, y, vx, vy]# State transition matrixdt = t_stepF = np.array([[1, 0, dt, 0], [0, 1, 0, dt], [0, 0, 1, 0], [0, 0, 0, 1]])# Measurement matrixH = np.array([[1, 0, 0, 0], [0, 1, 0, 0]])# Process noise covarianceQ = np.eye(4) * 0.001# Measure noise covarianceR = np.eye(2) * 0.01# Initial covariance matrixP = np.eye(4)def predict(state, P): state_pred = F @ state P_pred = F @ P @ F.T + Q return state_pred, P_preddef update(state_pred, P_pred, measurement): y = measurement - H @ state_pred S = H @ P_pred @ H.T + R K = P_pred @ H.T @ np.linalg.inv(S) state_upd = state_pred + K @ y P_upd = (np.eye(4) - K @ H) @ P_pred return state_upd, P_upd# Initialize state & covariancestate = initial_statetrajectory = [state[:2]]time = 0# Do Kalman filtering with actual measurementsfor i in range(len(actual_x)): # Predict state_pred, P_pred = predict(state, P) # Measure measurement = np.array([actual_x[i], actual_y[i]]) # Update state, P = update(state_pred, P_pred, measurement) # Save trajectory.append(state[:2])# Convert trajectory to np array for plottingtrajectory = np.array(trajectory)# Plot trajectoryplt.figure(figsize=(10, 5))plt.plot(trajectory[:, 0], trajectory[:, 1], label="Predicted trajectory", color='r')plt.scatter(actual_x, actual_y, label="Actual trajectory", color='b')plt.xlabel("Horizontal distance")plt.ylabel("Vertical distance")plt.title("Trajectory of bouncing ball with Kalman filter")plt.legend()plt.grid(True)plt.show()
This code uses the Kalman filter to refine the trajectory prediction iteratively as more actual data points become available.