code:
import cv2
from filterpy.kalman import KalmanFilter
from ultralytics import YOLO
import numpy as np
import pandas as pd
from sktime.datatypes._panel._convert import from_2d_array_to_nested
from pickle import load
from sktime.datatypes._panel._convert import from_nested_to_2d_array
from sktime.datatypes import check_raise
#from sktime.datatypes._panel._concat import concat

model = YOLO('/Users/surabhi/Documents/kalman/best.pt')

kf = KalmanFilter(dim_x=4, dim_z=2)
kf.x = np.array([0, 0, 0, 0]) # initial state estimate
kf.P = np.eye(4) * 1000 # initial error covariance matrix
kf.F = np.array([[1, 0, 1, 0],
                 [0, 1, 0, 1],
                 [0, 0, 1, 0],
                 [0, 0, 0, 1]]) # state transition matrix
kf.H = np.array([[1, 0, 0, 0],
                 [0, 1, 0, 0]]) # measurement matrix
kf.R = np.diag([0.1, 0.1]) # measurement noise covariance matrix
kf.Q=  np.diag([0.1, 0.1, 0.1, 0.1])
dt = 1.0
u = np.zeros((4, 1))

cap = cv2.VideoCapture("1_1.mp4")
frame_num = 0
predicted_points = []
bounce_detected = False 
last_bounce_frame = -5
test_df = pd.DataFrame(columns=[ 'x', 'y', 'V'])

while True:
    ret, frame = cap.read()
    if ret is False:
        break
    bbox = model(frame, show=True)
    frame_num += 1
    for boxes_1 in bbox:
        result = boxes_1.boxes.xyxy
        if len(result) == 0:
            print("not detected")
        else:
            cx = int((result[0][0] + result[0][2]) / 2)
            cy = int((result[0][1] + result[0][3]) / 2)
            centroid = np.array([cx, cy])
            kf.predict()
            kf.update(centroid)
            next_point = (kf.x).tolist()
            predicted_points.append((int(next_point[0]), int(next_point[1])))
            if len(predicted_points) > 2:
                p1 = np.array(predicted_points[-2])
                p2 = np.array(predicted_points[-1])
                ball_vector = p2 - p1
                ball_speed = np.linalg.norm(ball_vector)
                if ball_speed > 0:
                    ball_direction = ball_vector / ball_speed
                    frame_boundary = np.array([frame.shape[1], frame.shape[0]])
                    to_boundary = (frame_boundary - p2) / ball_direction
                    bounce_point = p2 + ball_direction * to_boundary.min()
                    if not np.all(frame_boundary > bounce_point) or not np.all(bounce_point > 0):
                        bounce_point = p2
                    print("Bounce Point:", tuple(map(int, bounce_point)))
                    cv2.circle(frame, tuple(map(int, bounce_point)), 5, (0, 0, 0), 10)
            V=np.sqrt(kf.x[2]**2 + kf.x[3]**2)
            test_df = test_df.append({ 'x': next_point[0], 'y': next_point[1], 
                                                    'V': np.sqrt(kf.x[2]**2 + kf.x[3]**2)}, 
                                                   ignore_index=True)
            print(test_df)
            print("ENTER LOOP")
            for i in range(20, 0, -1): 
                test_df[f'lagX_{i}'] = test_df['x'].shift(i, fill_value=0)
                for i in range(20, 0, -1): 
                    test_df[f'lagY_{i}'] = test_df['y'].shift(i, fill_value=0)
                for i in range(20, 0, -1): 
                    test_df[f'lagV_{i}'] = test_df['V'].shift(i, fill_value=0)

            test_df.drop(['x', 'y', 'V'], 1, inplace=True)
            print(test_df)

            Xs = test_df[['lagX_20', 'lagX_19', 'lagX_18', 'lagX_17', 'lagX_16',
            'lagX_15', 'lagX_14', 'lagX_13', 'lagX_12', 'lagX_11', 'lagX_10',
            'lagX_9', 'lagX_8', 'lagX_7', 'lagX_6', 'lagX_5', 'lagX_4', 'lagX_3',
            'lagX_2', 'lagX_1']]
            Xs = from_2d_array_to_nested(Xs.to_numpy())

            Ys = test_df[['lagY_20', 'lagY_19', 'lagY_18', 'lagY_17',
                    'lagY_16', 'lagY_15', 'lagY_14', 'lagY_13', 'lagY_12', 'lagY_11',
                    'lagY_10', 'lagY_9', 'lagY_8', 'lagY_7', 'lagY_6', 'lagY_5', 'lagY_4',
                    'lagY_3', 'lagY_2', 'lagY_1']]
            Ys = from_2d_array_to_nested(Ys.to_numpy())

            Vs = test_df[['lagV_20', 'lagV_19', 'lagV_18',
                    'lagV_17', 'lagV_16', 'lagV_15', 'lagV_14', 'lagV_13', 'lagV_12',
                    'lagV_11', 'lagV_10', 'lagV_9', 'lagV_8', 'lagV_7', 'lagV_6', 'lagV_5',
                    'lagV_4', 'lagV_3', 'lagV_2', 'lagV_1']]
            Vs = from_2d_array_to_nested(Vs.to_numpy())

            X = pd.concat([Xs, Ys, Vs])
            X = X.apply(pd.to_numeric, errors='coerce')
            #X = X.dropna()
            #X_2d = from_nested_to_2d_array(X)
            check_raise(X, mtype='pd.DataFrame')

            # load the pre-trained classifier  
            clf = load(open('clf.pkl', 'rb'))
            print("X:",X)
            predcted = clf.predict(X)
            idx = list(np.where(predcted == 1)[0])
            print("**************************************")
            print(idx)
            idx = np.array(idx) - 10
            print(idx)
                        

            if len(predicted_points) > 10:
                predicted_points.pop(0)

            if not bounce_detected and frame_num - last_bounce_frame > 10:
                if round(V)==19 or round(V)==22 : # If Y acceleration is less than the negative threshold, say -15
                    bounce_detected = True
                    last_bounce_frame = frame_num
                    print("Bounce detected")
                    
            print("next_point", next_point)
            print("frame_number", frame_num)
            cv2.putText(frame, f'Frame: {frame_num}', (10, 50), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2)
            cv2.circle(frame, (cx, cy), 5, (0,0,255), 5)
            cv2.circle(frame, (int(next_point[0]), int(next_point[1])), 5, (255, 0, 0), 10)
            for i, p in enumerate(predicted_points):
                color = (255,255,255)
                cv2.circle(frame, p, 5, color, 2)
            if bounce_detected:
                cv2.putText(frame, 'Bounce Detected', (10, 350), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2)
            if kf.x[3] > 0: # After a bounce is detected, wait until acceleration is above the threshold, say -5, to detect the bounce again
                bounce_detected = False
        
           # test_df_1=pd.DataFrame({'frame': frame_num , 'x': next_point[0], 'y':next_point[1], 'vx':vx,'vy':vy ,'V': V}, index=[0])
            #test_df.concat(test_df_1)
            #test_df=pd.concat([test_df,test_df_1], ignore_index=True)
            #test_df.to_csv('file.csv')
            cv2.imshow('raw', frame)
            #test_df=pd.DataFrame()
           # test_df=pd.concat([test_df,test_df_1], ignore_index=True)
           # print(trajectory_df)
            test_df.to_csv('file.csv')
            #test_df_1=pd.DataFrame({'frame': frame_num , 'x': next_point[0], 'y':next_point[1], 'vx':vx,'vy':vy ,'V': V}, index=[0])
            # Uncomment the following lines to save the output video
            # out.write(frame)
            # if cv2.waitKey(1) & 0xFF == ord('q'):
            #     break
cap.release()
cv2.destroyAllWindows()

error:
X:     0
0 NaN
0 NaN
0 NaN
Traceback (most recent call last):
  File "/Users/surabhi/Documents/kalman/b1.py", line 110, in <module>
    predcted = clf.predict(X)
               ^^^^^^^^^^^^^^
  File "/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/site-packages/sklearn/pipeline.py", line 480, in predict
    Xt = transform.transform(Xt)
         ^^^^^^^^^^^^^^^^^^^^^^^
  File "/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/site-packages/sktime/transformations/base.py", line 536, in transform
    Xt = self._transform(X=X_inner, y=y_inner)
         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/site-packages/sktime/transformations/panel/compose.py", line 305, in _transform
    t_idx = np.concatenate(t_idx)
            ^^^^^^^^^^^^^^^^^^^^^
  File "<__array_function__ internals>", line 180, in concatenate
ValueError: need at least one array to concatenate