8.3 KiB
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.
Phase 1: Core Infrastructure Setup
1.1 Database Schema Extensions
File: garminsync/database.py
-
Extend existing
PowerAnalysistable with cycling-specific fields:# Add to PowerAnalysis class: peak_power_1s = Column(Float, nullable=True) peak_power_5s = Column(Float, nullable=True) peak_power_20s = Column(Float, nullable=True) peak_power_300s = Column(Float, nullable=True) normalized_power = Column(Float, nullable=True) intensity_factor = Column(Float, nullable=True) training_stress_score = Column(Float, nullable=True) -
Extend existing
GearingAnalysistable:# Add to GearingAnalysis class: estimated_chainring_teeth = Column(Integer, nullable=True) estimated_cassette_teeth = Column(Integer, nullable=True) gear_ratio = Column(Float, nullable=True) gear_inches = Column(Float, nullable=True) development_meters = Column(Float, nullable=True) confidence_score = Column(Float, nullable=True) analysis_method = Column(String, default="singlespeed_estimation")
1.2 Enhanced FIT Parser
File: garminsync/fit_processor/parser.py
- Extend
FITParserto extract cycling-specific data points:def _extract_cycling_data(self, message): """Extract cycling-specific metrics from FIT records""" # GPS coordinates for elevation/gradient # Speed and cadence for gear analysis # Power data (if available) for validation # Temperature for air density calculations
Phase 2: Power Estimation Engine
2.1 Physics-Based Power Calculator
New file: garminsync/fit_processor/power_estimator.py
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:
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:
- Rolling resistance:
P_roll = Crr × (m_bike + m_rider) × g × cos(θ) × v - Gravitational:
P_grav = (m_bike + m_rider) × g × sin(θ) × v - Aerodynamic:
P_aero = 0.5 × ρ × Cd × A × v³ - 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
Phase 3: Singlespeed Gear Ratio Analysis
3.1 Gear Ratio Calculator
New file: garminsync/fit_processor/gear_analyzer.py
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:
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
- Segment filtering: Identify flat terrain (gradient < 3%, speed > 15 km/h)
- Ratio calculation:
gear_ratio = (speed_ms × 60) ÷ (cadence_rpm × wheel_circumference_m) - Ratio matching: Compare calculated ratios against theoretical singlespeed options
- Confidence scoring: Based on data consistency and segment duration
Phase 4: Integration with Existing System
4.1 FIT Processing Workflow Enhancement
File: garminsync/fit_processor/analyzer.py
- Integrate power estimation and gear analysis into existing analysis workflow
- Add cycling-specific analysis triggers (detect cycling activities)
- Store results in database using existing schema
4.2 Database Population
Migration strategy:
- Extend existing migration system to handle new fields
- Process existing FIT files retroactively
- Add processing status tracking for cycling analysis
4.3 CLI Integration
File: garminsync/cli.py
- Add new command:
garminsync analyze --cycling --activity-id <id> - Add batch processing:
garminsync analyze --cycling --missing - Add reporting:
garminsync report --power-analysis --gear-analysis
Phase 5: Validation and Testing
5.1 Test Data Requirements
- FIT files with known power data for validation
- Various singlespeed configurations for gear ratio testing
- Different terrain types (flat, climbing, mixed)
5.2 Validation Methodology
- Compare estimated vs. actual power (where available)
- Validate gear ratio estimates against known bike configurations
- Test edge cases (very low/high cadence, extreme gradients)
5.3 Performance Optimization
- Efficient gradient calculation from GPS data
- Optimize power calculation loops for large datasets
- Cache intermediate calculations
Phase 6: Advanced Features (Future)
6.1 Environmental Corrections
- Wind speed/direction integration
- Barometric pressure for accurate altitude
- Temperature-based air density adjustments
6.2 Machine Learning Enhancement
- Train models on validated power data
- Improve gear ratio detection accuracy
- Personalized power estimation based on rider history
6.3 Comparative Analysis
- Compare estimated metrics across rides
- Trend analysis for fitness progression
- Gear ratio optimization recommendations
Implementation Priority
High Priority:
- Database schema extensions
- Basic power estimation using physics model
- Singlespeed gear ratio analysis for flat terrain
- Integration with existing FIT processing pipeline
Medium Priority:
- Peak power analysis (1s, 5s, 20s, 5min)
- Normalized Power and TSS calculations
- Advanced gear analysis with confidence scoring
- CLI commands for analysis and reporting
Low Priority:
- Environmental corrections (wind, pressure)
- Machine learning enhancements
- Advanced comparative analysis features
- Web UI integration for visualizing results
Success Criteria
- Power Estimation: Within ±10% of actual power data (where available for validation)
- Gear Ratio Detection: Correctly identify gear ratios within ±1 tooth accuracy
- Processing Speed: Analyze typical FIT file (1-hour ride) in <5 seconds
- Data Coverage: Successfully analyze 90%+ of cycling FIT files
- Integration: Seamlessly integrate with existing GarminSync workflow
File Structure Summary
garminsync/
├── fit_processor/
│ ├── parser.py (enhanced)
│ ├── analyzer.py (enhanced)
│ ├── power_estimator.py (new)
│ └── gear_analyzer.py (new)
├── database.py (enhanced)
├── cli.py (enhanced)
└── migrate_cycling_analysis.py (new)
This plan provides a comprehensive roadmap for implementing cycling-specific FIT analysis while building on the existing GarminSync infrastructure and maintaining compatibility with current functionality.