In [1]:
#fitdecode from https://pypi.org/project/fitdecode/
import fitdecode

#for online use point this to the location of the fit file to analyze
fit_file = 'rob0-2020-12-04-glassy-95960008.fit'

g = 9.81           #gravity in m/s^2
m = 79.4 + 1       #rider + bike mass in kg with 1kg more simulating the wheel's rotational intertia
Crr = 0.005        #approximate rolling resistance
CdA = 0.324        #approximate CdA in m^2 - hands on hoods elbows bent - can be varied
Rho = 1.225        #air density sea level STP
dt = 1             #time step from the fit file; will be updated below
speed_total = 0    #add up all the speeds, later divide by total steps to get average
Vi = 0             #initialize the starting speed at 0  
count = 0          #used to average the speed

time_prev = None   #last fit message time, for edge cases when not just 1 second intervals
total_time = 0     #length of the ride in seconds

with fitdecode.FitReader(fit_file) as fit:
    for frame in fit:
        if isinstance(frame, fitdecode.FitDataMessage) and frame.has_field('power'):
            time_current = frame.get_field('timestamp').value
            if time_prev:
                dt = (time_current-time_prev).seconds
                total_time += dt
            
            p=(frame.get_field('power').value)
            Vf = ((-dt*(CdA*Rho*Vi**3-2*p+2*Crr*Vi*g*m)+Vi**2*m)/m)**.5
            speed_total += Vf
            count += 1
            Vi = Vf
            time_prev = time_current

v = speed_total* 2.23694/count #convert from m/s to mph and average        
t = total_time/3600

print ("Average Speed: {:.2f} mph - Time: {:.2f} hours - Distance: {:.2f} miles".format(v,t,(v*t)))
Average Speed: 20.48 mph - Time: 1.33 hours - Distance: 27.30 miles
In [ ]: