mirror of
https://github.com/sstent/GarminSync.git
synced 2026-01-25 16:42:20 +00:00
45 lines
1.9 KiB
Python
45 lines
1.9 KiB
Python
import numpy as np
|
|
|
|
class PowerEstimator:
|
|
def __init__(self):
|
|
self.bike_weight_kg = 10.0 # 22 lbs
|
|
self.rider_weight_kg = 75.0 # Default assumption
|
|
self.drag_coefficient = 0.88 # Road bike
|
|
self.frontal_area_m2 = 0.4 # Typical road cycling position
|
|
self.rolling_resistance = 0.004 # Road tires
|
|
self.drivetrain_efficiency = 0.97
|
|
self.air_density = 1.225 # kg/m³ at sea level, 20°C
|
|
|
|
def calculate_power(self, speed_ms, gradient_percent,
|
|
air_temp_c=20, altitude_m=0):
|
|
"""Calculate estimated power using physics model"""
|
|
# Validate input parameters
|
|
if not isinstance(speed_ms, (int, float)) or speed_ms < 0:
|
|
raise ValueError("Speed must be a non-negative number")
|
|
if not isinstance(gradient_percent, (int, float)):
|
|
raise ValueError("Gradient must be a number")
|
|
|
|
# Calculate air density based on temperature and altitude
|
|
temp_k = air_temp_c + 273.15
|
|
pressure = 101325 * (1 - 0.0000225577 * altitude_m) ** 5.25588
|
|
air_density = pressure / (287.05 * temp_k)
|
|
|
|
# Convert gradient to angle
|
|
gradient_rad = np.arctan(gradient_percent / 100.0)
|
|
|
|
# Total mass
|
|
total_mass = self.bike_weight_kg + self.rider_weight_kg
|
|
|
|
# Power components
|
|
P_roll = self.rolling_resistance * total_mass * 9.81 * np.cos(gradient_rad) * speed_ms
|
|
P_grav = total_mass * 9.81 * np.sin(gradient_rad) * speed_ms
|
|
P_aero = 0.5 * air_density * self.drag_coefficient * self.frontal_area_m2 * speed_ms ** 3
|
|
|
|
# Power = (Rolling + Gravity + Aerodynamic) / Drivetrain efficiency
|
|
return (P_roll + P_grav + P_aero) / self.drivetrain_efficiency
|
|
|
|
def estimate_peak_power(self, power_values, durations):
|
|
"""Calculate peak power for various durations"""
|
|
# This will be implemented in Phase 3
|
|
return {}
|