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:
Rechenbeispiel:
Szenario:2-Stunden-Fahrt, NP = 235W, FTP = 250W
- IF berechnen: IF = 235 / 250 = 0,94
- Dauer in Sekunden: 2 Stunden × 3600 = 7200 Sekunden
- TSS = (7200 × 235 × 0,94) / (250 × 3600) × 100
- 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: 1772. Normalisierte Leistung (NP)
Algorithmus (gleitender 30-Sekunden-Durchschnitt):
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 Watt3. Intensitätsfaktor (IF)
Formel:
Interpretationsbereiche:
| IF-Bereich | Anstrengungsniveau | Beispiel-Workout |
|---|---|---|
| < 0,75 | Erholung / Leicht | Aktive Erholungsfahrt, Zone 1-2 |
| 0,75 - 0,85 | Ausdauer | Lange konstante Fahrt, aerobe Basis |
| 0,85 - 0,95 | Tempo | Sweet Spot Training, Tempo-Intervalle |
| 0,95 - 1,05 | Schwelle | FTP-Intervalle, Zeitfahranstrengung |
| 1,05 - 1,15 | VO₂max | 5-Minuten-Intervalle, Kriterium-Rennen |
| > 1,15 | Anaerob | Kurze 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.944.Variabilitätsindex (VI)
Formel:
Interpretation nach Disziplin:
| Disziplin | Typischer VI | Bedeutung |
|---|---|---|
| Straßen-ZF / Konstante Anstrengung | 1,00 - 1,05 | Sehr konstante Leistung, optimales Pacing |
| Straßenrennen | 1,05 - 1,10 | Einige Antritte, allgemeine konstante |
| Kriterium | 1,10 - 1,20 | Häufige Beschleunigungen und Angriffe |
| Mountainbike XC | 1,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.21Kritische Leistung & W' (Anaerobe Kapazität)
5. Kritische Leistung (CP) - Lineares Modell
Formel:
Berechnung aus mehreren Anstrengungen:
Erfordert 2-4 maximale Anstrengungen bei verschiedenen Dauern (z.B. 3, 5, 12, 20 Minuten)
Beispieldaten:
| Dauer | Leistung (W) | Gesamtarbeit (kJ) |
|---|---|---|
| 3 Min (180s) | 400W | 72 kJ |
| 5 Min (300s) | 365W | 109,5 kJ |
| 12 Min (720s) | 310W | 223,2 kJ |
| 20 Min (1200s) | 285W | 342 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:
W'exp(t) = ∫(P(t) - CP) dt
W'rec(t) = W' × (1 - e^(-t/τ))
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ückLeistungsmanagement-Diagramm (PMC) zum Radfahren
7.CTL, ATL, TSB Berechnungen
Formeln (Exponentiell gewichtete gleitende Durchschnitte):
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):
| Tag | TSS | CTL | ATL | TSB | Status |
|---|---|---|---|---|---|
| Mo | 100 | 75,0 | 80,0 | -5,0 | Training |
| Di | 50 | 74,4 | 75,7 | -1,3 | Erholung |
| Mi | 120 | 75,5 | 82,0 | -6,5 | Hartes Training |
| Do | 0 | 73,7 | 70,3 | +3,4 | Ruhetag |
| Fr | 80 | 73,8 | 71,7 | +2,1 | Moderat |
| Sa | 150 | 75,6 | 82,9 | -7,3 | Lange Fahrt |
| So | 40 | 74,8 | 76,8 | -2,0 | Erholung |
TSB-Interpretation:
| TSB-Bereich | Status | Aktion |
|---|---|---|
| < -30 | Hohes Risiko | Übertrainingswarnung - Belastung reduzieren |
| -30 bis -10 | Hartes Training | Fitness aufbauen, Erholung überwachen |
| -10 bis +5 | Optimal | Normale Trainingszone |
| +5 bis +15 | Rennbereit | Spitzenform - Rennen an diesem Wochenende |
| > +25 | Detraining | Fitnessverlust - 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ückLeistungsgewicht & Kletter-Metriken
8. Leistungsgewicht (Power-to-Weight Ratio)
Formel:
FTP W/kg Benchmarks:
| Niveau | Männer W/kg | Frauen W/kg | Kategorie |
|---|---|---|---|
| Freizeit | 2,5 - 3,5 | 2,0 - 3,0 | Fitness-Fahrer |
| Wettkampf | 3,5 - 4,5 | 3,0 - 4,0 | Kat 3-4, Altersklassen-Rennfahrer |
| Fortgeschritten | 4,5 - 5,5 | 4,0 - 5,0 | Kat 1-2, stärker Amateur |
| Elite Amateur | 5,5 - 6,0 | 5,0 - 5,5 | Nationales Niveau |
| Profi | 6,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.939. VAM (Velocità Ascensionale Media)
Formel:
VAM Benchmarks:
| VAM (m/h) | Niveau | Beispiel |
|---|---|---|
| 600 - 900 | Freizeit | Clubfahrer am lokalen Anstieg |
| 900 - 1200 | Wettkampf | Guter Amateur an Alpe d'Huez |
| 1200 - 1500 | Elite Amateur | Kletterer auf nationalem Niveau |
| 1500 - 1800 | Profi | World Tour Helfer |
| > 1800 | Grand Tour Sieger | Pogač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/h10. VAM zu W/kg Schätzung
Formel:
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.36Aerodynamische Leistungsgleichung
11. Gesamtleistungsbedarf
Vollständige Formel:
Komponentenformeln:
P_aero = CdA × 0,5 × ρ × V³
P_Schwerkraft = m × g × sin(θ) × V
P_rolling = Crr × m × g × cos(θ) × V
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:
- P_aero= 0,22 × 0,5 × 1,225 × 11,11³ =185W
- P_gravity= 0W (flache Straße)
- P_rolling= 0,004 × 83 × 9,81 × 11,11 =36W
- P_kinetic= 0W (konstante Geschwindigkeit)
- 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
