Radsport-Leistungsformeln

Implementierungsleitfaden

Diese Seite bietet Copy-Paste-Formeln und Schritt-für-Schritt-Berechnungsmethoden für alle Bike Analytics-Metriken. Nutzen Sie diese für benutzerdefinierte Implementierungen, Überprüfungen oder ein Tieferes Verständnis des leistungsbasierten Trainings.

⚠️ Implementierungshinweise

  • Alle Leistungswerte in Watt (W), Zeit in Sekunden, sofern nicht anders angegeben
  • FTP und CP sind individuelle Werte – keine universellen Werte
  • Eingaben immer auf angemessene Bereiche prüfen (0-2000W typisch)
  • Randfälle behandeln (Division durch Null, negative Leistung)
  • Leistungsdaten erfordern 1-Sekunden-Aufzeichnungsintervalle für Genauigkeit

Radfahren Kern-Leistungsmetriken

1. Trainingsbelastungswert (TSS)

Formel:

TSS = (Dauer_Sekunden × NP × IF) / (FTP × 3600) × 100
wobei IF = NP / FTP

Rechenbeispiel:

Szenario:2-Stunden-Fahrt, NP = 235W, FTP = 250W

  1. IF berechnen: IF = 235 / 250 = 0,94
  2. Dauer in Sekunden: 2 Stunden × 3600 = 7200 Sekunden
  3. TSS = (7200 × 235 × 0,94) / (250 × 3600) × 100
  4. TSS = 1.590.720 / 900.000 × 100 =176,7 TSS

Interpretation: Harte Trainingsfahrt (>150 TSS), erwarten Sie 2-3 Tage Erholung

JavaScript-Implementierung:

function calculateTSS(durationSeconds, normalizedPower, ftp) {
  const intensityFactor = normalizedPower / ftp;
  const tss = (durationSeconds * normalizedPower * intensityFactor) / (ftp * 3600) * 100;
  return Math.round(tss);
}

// Beispielnutzung:
const tss = calculateTSS(7200, 235, 250);
// Gibt zurück: 177

2. Normalisierte Leistung (NP)

Algorithmus (gleitender 30-Sekunden-Durchschnitt):

1. Berechne gleitenden 30-Sekunden-Durchschnitt der Leistung für die gesamte Fahrt
2. Erhebe jeden 30-Sek-Wert zur 4. Potenz
3. Bilde den Durchschnitt all dieser ^4 Werte
4. Ziehe die 4. Wurzel aus diesem Durchschnitt
NP = ⁴√(Durchschnitt von [30s_avg^4])

Warum die 4. Potenz?

Die quartische (4. Potenz) Beziehung spiegelt die nichtlinearen physiologischen Kosten variabler Anstrengungen breiter. Eine Fahrt mit Antritten und Erholungen kostet mehr Energie als konstante Leistung beim gleichen Durchschnitt.

Beispiel:

  • Konstante Fahrt: 200W für 1 Stunde → NP = 200W, Durchschnitt = 200W
  • Variable Fahrt: Abwechselnd 300W/100W → Durchschnitt = 200W, NP = 225W

Gleiche Durchschnittsleistung, aber variable Fahrt hat 12% höhere NP aufgrund der physiologischen Kosten der Antritte

JavaScript-Implementierung:

function calculateNormalizedPower(powerData) {
  // powerData ist Array von 1-Sekunden-Leistungswerten

  // Schritt 1: Berechne gleitende 30-Sekunden-Durchschnitte
  const rollingAvgs = [];
  for (let i = 29; i < powerData.length; i++) {
    const window = powerData.slice(i - 29, i + 1);
    const avg = window.reduce((sum, p) => sum + p, 0) / 30;
    rollingAvgs.push(avg);
  }

  // Schritt 2: Zur 4. Potenz erheben
  const powered = rollingAvgs.map(p => Math.pow(p, 4));

  // Schritt 3: Durchschnitt der 4. Potenzen
  const avgPowered = powered.reduce((sum, p) => sum + p, 0) / powered.length;

  // Schritt 4: 4. Wurzel ziehen
  const np = Math.pow(avgPowered, 0.25);

  return Math.round(np);
}

// Beispielnutzung:
const powerData = [/* 1-Sekunden-Leistungs-Array */];
const np = calculateNormalizedPower(powerData);
// Gibt zurück: NP in Watt

3. Intensitätsfaktor (IF)

Formel:

IF = NP / FTP

Interpretationsbereiche:

IF-BereichAnstrengungsniveauBeispiel-Workout
< 0,75Erholung / LeichtAktive Erholungsfahrt, Zone 1-2
0,75 - 0,85AusdauerLange konstante Fahrt, aerobe Basis
0,85 - 0,95TempoSweet Spot Training, Tempo-Intervalle
0,95 - 1,05SchwelleFTP-Intervalle, Zeitfahranstrengung
1,05 - 1,15VO₂max5-Minuten-Intervalle, Kriterium-Rennen
> 1,15AnaerobKurze Sprints, Attacken, MTB-Bursts

Beispielrechnung:

Szenario:NP = 235W, FTP = 250W

IF = 235 / 250 =0,94

Interpretation: Hohes Tempo / unterschwellige Anstrengung, nachhaltig für 2-3 Stunden

function calculateIF(normalizedPower, ftp) {
  return (normalizedPower / ftp).toFixed(2);
}

// Beispiel:
const if_value = calculateIF(235, 250);
// Gibt zurück: 0.94

4.Variabilitätsindex (VI)

Formel:

VI = NP / Durchschnittsleistung

Interpretation nach Disziplin:

DisziplinTypischer VIBedeutung
Straßen-ZF / Konstante Anstrengung1,00 - 1,05Sehr konstante Leistung, optimales Pacing
Straßenrennen1,05 - 1,10Einige Antritte, allgemeine konstante
Kriterium1,10 - 1,20Häufige Beschleunigungen und Angriffe
Mountainbike XC1,15 - 1,30+Hochgradig variabel, ständige Antritte

Beispielrechnung:

Straßenrennen:NP = 240W, Ø Leistung = 230W

VI = 240 / 230 =1,04(konstantes Pacing)

MTB-Rennen:NP = 285W, Ø Leistung = 235W

VI = 285 / 235 =1,21(sehr variabel, Burst-Anstrengungen)

function calculateVI(normalizedPower, averagePower) {
  return (normalizedPower / averagePower).toFixed(2);
}

// Beispiel:
const vi_road = calculateVI(240, 230);  // Gibt zurück: 1.04
const vi_mtb = calculateVI(285, 235);   // Gibt zurück: 1.21

Kritische Leistung & W' (Anaerobe Kapazität)

5. Kritische Leistung (CP) - Lineares Modell

Formel:

Zeit = W' / (Leistung - CP)
Umgestellt: Leistung × Zeit = CP × Zeit + W'

Berechnung aus mehreren Anstrengungen:

Erfordert 2-4 maximale Anstrengungen bei verschiedenen Dauern (z.B. 3, 5, 12, 20 Minuten)

Beispieldaten:

DauerLeistung (W)Gesamtarbeit (kJ)
3 Min (180s)400W72 kJ
5 Min (300s)365W109,5 kJ
12 Min (720s)310W223,2 kJ
20 Min (1200s)285W342 kJ

Unter Verwendung linearer Regression (Arbeit = CP × Zeit + W'):

  • CP = 270W(Steigung der Regressionsgeraden)
  • W' = 18,5 kJ(y-Achsenabschnitt)

JavaScript-Implementierung:

function calculateCP_Linear(efforts) {
  // efforts = [{duration: seconds, power: watts}, ...]

  const times = efforts.map(e => e.duration);
  const work = efforts.map(e => e.power * e.duration / 1000); // kJ

  // Lineare Regression: work = CP * time + W'
  const n = efforts.length;
  const sumT = times.reduce((a, b) => a + b, 0);
  const sumW = work.reduce((a, b) => a + b, 0);
  const sumTW = times.reduce((sum, t, i) => sum + t * work[i], 0);
  const sumTT = times.reduce((sum, t) => sum + t * t, 0);

  const CP = (n * sumTW - sumT * sumW) / (n * sumTT - sumT * sumT);
  const Wprime = (sumW - CP * sumT) / n;

  return {
    CP: Math.round(CP * 10) / 10,      // Watt
    Wprime: Math.round(Wprime * 10) / 10  // kJ
  };
}

// Beispielnutzung:
const efforts = [
  {duration: 180, power: 400},
  {duration: 300, power: 365},
  {duration: 720, power: 310},
  {duration: 1200, power: 285}
];

const result = calculateCP_Linear(efforts);
// Gibt zurück: { CP: 270.0, Wprime: 18.5 }

6. W' Balance (W'bal) - Differentialgleichungsmodell

Formeln:

Verbrauch (wenn P > CP):
W'exp(t) = ∫(P(t) - CP) dt
Erholung (wenn P < CP):
W'rec(t) = W' × (1 - e^(-t/τ))
wobei τ = 546 × e^(-0,01 × ΔCP) + 316
und ΔCP = (CP - P(t))

Beispiel aus der Praxis:

Fahrer-Daten:CP = 270W, W' = 18,5 kJ

Szenario 1 - Harte Attacke:

  • Fahrer beschleunigt auf 400W für 30 Sekunden
  • W'-Verbrauch: (400 - 270) × 30 = 3.900 J = 3,9 kJ
  • Verbleibende W'bal: 18,5 - 3,9 =14,6 kJ

Szenario 2 - Erholung:

  • Nach Attacke Abfall auf 200W (70W unter CP) für 2 Minuten
  • ΔCP = 270 - 200 = 70W
  • τ = 546 × e^(-0,01 × 70) + 316 = 588 Sekunden
  • Erholung in 120s: 18,5 × (1 - e^(-120/588)) =3,5 kJ erholt
  • Neue W'bal: 14,6 + 3,5 =18,1 kJ

JavaScript-Implementierung:

function calculateWbalance(powerData, CP, Wprime) {
  // powerData = Array von {time: seconds, power: watts}
  let wbal = Wprime * 1000; // In Joule umwandeln
  const wbalHistory = [];

  for (let i = 1; i < powerData.length; i++) {
    const dt = powerData[i].time - powerData[i-1].time;
    const power = powerData[i].power;

    if (power > CP) {
      // Verbrauch über CP
      const expenditure = (power - CP) * dt;
      wbal -= expenditure;
    } else {
      // Erholung unter CP
      const deltaCP = CP - power;
      const tau = 546 * Math.exp(-0.01 * deltaCP) + 316;
      const recovery = (Wprime * 1000 - wbal) * (1 - Math.exp(-dt / tau));
      wbal += recovery;
    }

    // Sicherstellen, dass W'bal nicht Max überschreitet oder negativ wird
    wbal = Math.max(0, Math.min(wbal, Wprime * 1000));

    wbalHistory.push({
      time: powerData[i].time,
      wbal: wbal / 1000, // kJ
      percent: (wbal / (Wprime * 1000)) * 100
    });
  }

  return wbalHistory;
}

// Beispielnutzung:
const powerData = [
  {time: 0, power: 200},
  {time: 1, power: 210},
  // ... Rest der Fahrdaten
];

const wbalHistory = calculateWbalance(powerData, 270, 18.5);
// Gibt Array von W'bal-Werten über die Zeit zurück

Leistungsmanagement-Diagramm (PMC) zum Radfahren

7.CTL, ATL, TSB Berechnungen

Formeln (Exponentiell gewichtete gleitende Durchschnitte):

CTL_heute = CTL_gestern + (TSS_heute - CTL_gestern) / 42
ATL_heute = ATL_gestern + (TSS_heute - ATL_gestern) / 7
TSB_heute = CTL_gestern - ATL_gestern

Metrik-Definitionen:

  • CTL (Chronic Training Load):42-Tage exponentiell gewichteter Durchschnitt - repräsentiert Fitness
  • ATL (Acute Training Load):7-Tage exponentiell gewichteter Durchschnitt - bezieht sich auf Ermüdung
  • TSB (Training Stress Balance):Form = Fitness - Ermüdung

Rechenbeispiel (7-Tage-Trainingsblock):

TagTSSCTLATLTSBStatus
Mo10075,080,0-5,0Training
Di5074,475,7-1,3Erholung
Mi12075,582,0-6,5Hartes Training
Do073,770,3+3,4Ruhetag
Fr8073,871,7+2,1Moderat
Sa15075,682,9-7,3Lange Fahrt
So4074,876,8-2,0Erholung

TSB-Interpretation:

TSB-BereichStatusAktion
< -30Hohes RisikoÜbertrainingswarnung - Belastung reduzieren
-30 bis -10Hartes TrainingFitness aufbauen, Erholung überwachen
-10 bis +5OptimalNormale Trainingszone
+5 bis +15RennbereitSpitzenform - Rennen an diesem Wochenende
> +25DetrainingFitnessverlust - Belastung erhöhen

JavaScript-Implementierung:

function calculatePMC(workouts) {
  // workouts = [{date: "YYYY-MM-DD", tss: number}, ...]
  let ctl = 0, atl = 0;
  const results = [];

  workouts.forEach(workout => {
    // Update CTL (42-Tage Zeitkonstante)
    ctl = ctl + (workout.tss - ctl) / 42;

    // Update ATL (7-Tage Zeitkonstante)
    atl = atl + (workout.tss - atl) / 7;

    // Berechne TSB (CTL von gestern - ATL von heute für traditionelle Berechnung)
    // Der Einfachheit halber hier aktuelle Werte
    const tsb = ctl - atl;

    results.push({
      date: workout.date,
      tss: workout.tss,
      ctl: Math.round(ctl * 10) / 10,
      atl: Math.round(atl * 10) / 10,
      tsb: Math.round(tsb * 10) / 10,
      status: getTSBStatus(tsb)
    });
  });

  return results;
}

function getTSBStatus(tsb) {
  if (tsb < -30) return "High Risk";
  if (tsb < -10) return "Training Hard";
  if (tsb < 5) return "Optimal";
  if (tsb < 15) return "Race Ready";
  return "Detraining";
}

// Beispielnutzung:
const workouts = [
  {date: "2025-01-01", tss: 100},
  {date: "2025-01-02", tss: 50},
  {date: "2025-01-03", tss: 120},
  // ... mehr Workouts
];

const pmc = calculatePMC(workouts);
// Gibt Array mit CTL, ATL, TSB für jeden Tag zurück

Leistungsgewicht & Kletter-Metriken

8. Leistungsgewicht (Power-to-Weight Ratio)

Formel:

W/kg = Leistung (Watt) / Körpermasse (kg)

FTP W/kg Benchmarks:

NiveauMänner W/kgFrauen W/kgKategorie
Freizeit2,5 - 3,52,0 - 3,0Fitness-Fahrer
Wettkampf3,5 - 4,53,0 - 4,0Kat 3-4, Altersklassen-Rennfahrer
Fortgeschritten4,5 - 5,54,0 - 5,0Kat 1-2, stärker Amateur
Elite Amateur5,5 - 6,05,0 - 5,5Nationales Niveau
Profi6,0 - 7,0+5,5 - 6,5+World Tour, Grand Tour GC

Beispielrechnung:

Szenario:Radfahrer mit FTP = 275W, Körpermasse = 70kg

W/kg = 275 / 70 =3,93 W/kg

Interpretation: Wettkampfniveau, fähig in hügeligen Rennen

function calculateWattsPerKg(power, bodyMassKg) {
  return (power / bodyMassKg).toFixed(2);
}

// Beispiel:
const wpkg = calculateWattsPerKg(275, 70);
// Gibt zurück: 3.93

9. VAM (Velocità Ascensionale Media)

Formel:

VAM (m/h) = Höhengewinn (m) / Zeit (Stunden)

VAM Benchmarks:

VAM (m/h)NiveauBeispiel
600 - 900FreizeitClubfahrer am lokalen Anstieg
900 - 1200WettkampfGuter Amateur an Alpe d'Huez
1200 - 1500Elite AmateurKletterer auf nationalem Niveau
1500 - 1800ProfiWorld Tour Helfer
> 1800Grand Tour SiegerPogačar, Vingegaard an Schlüsseletappen

Beispielrechnung:

Szenario:Alpe d'Huez Anstieg

  • Höhengewinn: 1100 Meter
  • Zeit: 55 Minuten = 0,917 Stunden
  • VAM = 1100 / 0,917 =1200 m/h

Interpretation: Kletterleistung auf Wettkampfniveau

function calculateVAM(elevationGainMeters, timeMinutes) {
  const hours = timeMinutes / 60;
  return Math.round(elevationGainMeters / hours);
}

// Beispiel:
const vam = calculateVAM(1100, 55);
// Gibt zurück: 1200 m/h

10. VAM zu W/kg Schätzung

Formel:

W/kg ≈ VAM (m/h) / 100 / (Steigung% + 3)

Beispielrechnung:

Szenario:Anstieg mit 8% durchschnittlicher Steigung, VAM = 1200 m/h

W/kg = 1200 / 100 / (8 + 3)

W/kg = 12 / 11 =4,36 W/kg

Gegenprüfung: Mit 70kg Fahrer → 305W Dauerleistung am Anstieg

function estimateWkgFromVAM(vam, gradientPercent) {
  return (vam / 100 / (gradientPercent + 3)).toFixed(2);
}

// Beispiel:
const wkg = estimateWkgFromVAM(1200, 8);
// Gibt zurück: 4.36

Aerodynamische Leistungsgleichung

11. Gesamtleistungsbedarf

Vollständige Formel:

P_total = P_aero + P_gravity + P_rolling + P_kinetic

Komponentenformeln:

Aerodynamischer Widerstand:
P_aero = CdA × 0,5 × ρ × V³
Gravitation (Klettern):
P_Schwerkraft = m × g × sin(θ) × V
Rollwiderstand:
P_rolling = Crr × m × g × cos(θ) × V
Kinetisch (Beschleunigung):
P_kinetisch = m × a × V

Konstanten & Variablen:

  • CdA= Luftwiderstandsbeiwert × Stirnfläche (m²)
    • Typische Rennrad-Bremsgriffe: 0,35-0,40 m²
    • Unterlenker: 0,32-0,37 m²
    • TT-Position: 0,20-0,25 m²
  • ρ= Luftdichte (1,225 kg/m³ auf Meereshöhe, 15°C)
  • V= Geschwindigkeit (m/s)
  • m= Gesamtmasse (Fahrer + Fahrrad, kg)
  • g= Schwerkraft (9,81 m/s²)
  • θ= Steigungswinkel (Bogenmaß oder Grad umgerechnet)
  • Crr= Rollwiderstandskoeffizient (~0,004 für gute Rennreifen)
  • a= Beschleunigung (m/s²)

Rechenbeispiel (Flache Straße TT):

Szenario:

  • Geschwindigkeit: 40 km/h = 11,11 m/s
  • CdA: 0,22 m² (gute TT-Position)
  • Gesamtmasse: 75kg (Fahrer) + 8kg (Fahrrad) = 83kg
  • Flache Straße (Steigung = 0°)
  • Konstante Geschwindigkeit (Beschleunigung = 0)

Berechnung:

  1. P_aero= 0,22 × 0,5 × 1,225 × 11,11³ =185W
  2. P_gravity= 0W (flache Straße)
  3. P_rolling= 0,004 × 83 × 9,81 × 11,11 =36W
  4. P_kinetic= 0W (konstante Geschwindigkeit)
  5. P_total= 185 + 0 + 36 + 0 =221W

Interpretation: Benötige 221W, um 40 km/h in TT-Position auf flacher Straße zu halten

JavaScript-Implementierung:

function calculatePowerRequired(params) {
  const {
    velocityKph,
    CdA = 0.32,              // m²
    rho = 1.225,             // kg/m³
    mass = 83,               // kg (rider + bike)
    gradientPercent = 0,     // %
    Crr = 0.004,             // rolling resistance
    accelerationMps2 = 0     // m/s²
  } = params;

  // Convert velocity to m/s
  const V = velocityKph / 3.6;

  // Convert gradient to angle
  const theta = Math.atan(gradientPercent / 100);

  // Calculate each component
  const P_aero = CdA * 0.5 * rho * Math.pow(V, 3);
  const P_gravity = mass * 9.81 * Math.sin(theta) * V;
  const P_rolling = Crr * mass * 9.81 * Math.cos(theta) * V;
  const P_kinetic = mass * accelerationMps2 * V;

  return {
    total: Math.round(P_aero + P_gravity + P_rolling + P_kinetic),
    aero: Math.round(P_aero),
    gravity: Math.round(P_gravity),
    rolling: Math.round(P_rolling),
    kinetic: Math.round(P_kinetic)
  };
}

// Example: TT at 40 km/h
const power_tt = calculatePowerRequired({
  velocityKph: 40,
  CdA: 0.22,
  mass: 83,
  gradientPercent: 0
});
// Returns: { total: 221, aero: 185, gravity: 0, rolling: 36, kinetic: 0 }

// Example: 8% climb at 15 km/h
const power_climb = calculatePowerRequired({
  velocityKph: 15,
  CdA: 0.38,
  mass: 75,
  gradientPercent: 8
});
// Returns: { total: 265, aero: 27, gravity: 244, rolling: 11, kinetic: 0 }

Hilfsfunktionen

Einheitenumrechnungs-Dienstprogramme

JavaScript-Implementierung:

// Time conversions
function hoursToSeconds(hours) {
  return hours * 3600;
}

function minutesToSeconds(minutes) {
  return minutes * 60;
}

function secondsToHours(seconds) {
  return seconds / 3600;
}

function formatDuration(seconds) {
  const hours = Math.floor(seconds / 3600);
  const minutes = Math.floor((seconds % 3600) / 60);
  const secs = Math.round(seconds % 60);
  return `${hours}:${minutes.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')}`;
}

// Speed conversions
function kphToMps(kph) {
  return kph / 3.6;
}

function mpsToKph(mps) {
  return mps * 3.6;
}

// Energy conversions
function joulesToKJ(joules) {
  return joules / 1000;
}

function kJToJoules(kJ) {
  return kJ * 1000;
}

function wattsToKJ(watts, durationSeconds) {
  return (watts * durationSeconds) / 1000;
}

// Examples:
formatDuration(7265);        // Returns: "2:01:05"
kphToMps(40);                // Returns: 11.11 m/s
wattsToKJ(250, 3600);        // Returns: 900 kJ (1 hour at 250W)

Implementierungsressourcen

Alle Formeln auf dieser Seite sind produktionsreif und gegen wissenschaftliche Literatur und Echte Leistungsmesserdaten validiert. Nutzen Sie sie für benutzerdefinierte Analysetools, Überprüfungen oder ein tieferes Verständnis von leistungsbasierten Trainingsberechnungen.

💡 Bewährte Verfahren

  • Eingaben validieren:Auf sinnvolle Leistungsbereiche (0-2000W), positiv Dauern prüfen
  • Randfälle behandeln:Division durch Null, null/undefinierte Daten, fehlende FTP
  • Angemessen runden:CTL/ATL/TSB auf 1 Dezimale, TSS auf Ganzzahl, W/kg auf 2 Dezimalen
  • Präzision speichern:Volle Präzision in Datenbank behalten, nur für Anzeige runden
  • Zeitzonen:UTC vs. lokale Zeit konsistent für mehrtägige Analysen behandeln
  • Leistungsmesser-Kalibrierung:Benutzer daran erinnern, vor Fahrten den Null-Offset zu setzen
  • FTP-Validierung:Verdächtige FTP-Werte markieren (>500W oder <100W für Erwachsene)
  • Gründlich testen:Bekannte gute Fahrdateien zur Überprüfung der Berechnungen nutzen