mirror of
https://github.com/sstent/GarminSync.git
synced 2026-01-25 08:35:02 +00:00
79 lines
3.2 KiB
Markdown
79 lines
3.2 KiB
Markdown
# Cycling FIT Analysis Implementation Plan
|
||
|
||
## Overview
|
||
Extend the existing GarminSync FIT parser to calculate cycling-specific metrics including power estimation and singlespeed gear ratio analysis for activities without native power data.
|
||
|
||
|
||
**Key Components:**
|
||
- **Environmental factors**: Air density, wind resistance, temperature
|
||
- **Bike specifications**: Weight (22 lbs = 10 kg), aerodynamic drag coefficient
|
||
- **Rider assumptions**: Weight (75 kg default), position (road bike)
|
||
- **Terrain analysis**: Gradient calculation from GPS elevation data
|
||
|
||
**Core Algorithm:**
|
||
```python
|
||
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"""
|
||
# Power = (Rolling + Gravity + Aerodynamic + Kinetic) / Efficiency
|
||
```
|
||
|
||
**Power Components:**
|
||
1. **Rolling resistance**: `P_roll = Crr × (m_bike + m_rider) × g × cos(θ) × v`
|
||
2. **Gravitational**: `P_grav = (m_bike + m_rider) × g × sin(θ) × v`
|
||
3. **Aerodynamic**: `P_aero = 0.5 × ρ × Cd × A × v³`
|
||
4. **Acceleration**: `P_accel = (m_bike + m_rider) × a × v`
|
||
|
||
### 2.2 Peak Power Analysis
|
||
**Methods:**
|
||
- 1-second, 5-second, 20-second, 5-minute peak power windows
|
||
- Normalized Power (NP) calculation using 30-second rolling average
|
||
- Training Stress Score (TSS) estimation based on NP and ride duration
|
||
|
||
## Singlespeed Gear Ratio Analysis
|
||
|
||
### Gear Ratio Calculator
|
||
|
||
**Strategy:**
|
||
- Analyze flat terrain segments (gradient < 3%)
|
||
- Use speed/cadence relationship to determine gear ratio
|
||
- Test against common singlespeed ratios for 38t and 46t chainrings
|
||
- Calculate confidence scores based on data consistency
|
||
|
||
**Core Algorithm:**
|
||
```python
|
||
class SinglespeedAnalyzer:
|
||
def __init__(self):
|
||
self.chainring_options = [38, 46] # teeth
|
||
self.common_cogs = list(range(11, 28)) # 11t to 27t rear cogs
|
||
self.wheel_circumference_m = 2.096 # 700x25c tire
|
||
|
||
def analyze_gear_ratio(self, speed_data, cadence_data, gradient_data):
|
||
"""Determine most likely singlespeed gear ratio"""
|
||
# Filter for flat terrain segments
|
||
# Calculate gear ratio from speed/cadence
|
||
# Match against common ratios
|
||
# Return best fit with confidence score
|
||
```
|
||
|
||
**Gear Metrics:**
|
||
- **Gear ratio**: Chainring teeth ÷ Cog teeth
|
||
- **Gear inches**: Gear ratio × wheel diameter (inches)
|
||
- **Development**: Distance traveled per pedal revolution (meters)
|
||
|
||
### 3.2 Analysis Methodology
|
||
1. **Segment filtering**: Identify flat terrain (gradient < 3%, speed > 15 km/h)
|
||
2. **Ratio calculation**: `gear_ratio = (speed_ms × 60) ÷ (cadence_rpm × wheel_circumference_m)`
|
||
3. **Ratio matching**: Compare calculated ratios against theoretical singlespeed options
|
||
4. **Confidence scoring**: Based on data consistency and segment duration
|