Formler för cykelkraft
Mathematical Foundation of Bike Analytics Metrics
Implementeringsguide
Den här sidan tillhandahåller kopiera-klistra-formler och steg-för-steg-beräkningsmetoder för alla Bike Analytics-mätvärden. Använd dessa för anpassade implementeringar, verifiering eller djupare förståelse för kraftbaserad utbildning.
⚠️ Anmärkningar om implementering
- Alla effektvärden i watt (W), tid i sekunder om inget annat anges
- FTP och CP är individspecifika trösklar – inga universella värden
- Validera alltid ingångar för rimliga intervall (0-2000W typiskt)
- Hantera kantfall (division med noll, negativ effekt)
- Effektdata kräver 1-sekunds inspelningsintervall för noggrannhet
Kärnprestandamått
1. Träningsstressresultat (TSS)
Formel:
Arbetat exempel:
Scenario:2 timmars resa, NP = 235W, FTP = 250W
- Beräkna IF: IF = 235 / 250 = 0,94
- Varaktighet i sekunder: 2 timmar × 3600 = 7200 sekunder
- TSS = (7200 × 235 × 0,94) / (250 × 3600) × 100
- TSS = 1 590 720 / 900 000 × 100 =176,7 TSS
Tolkning: Hård träningsresa (>150 TSS), räkna med 2-3 dagars återhämtning
JavaScript-implementering:
funktion beräknaTSS(durationSeconds, normalizedPower, FTP) {
const intensityFactor = normalizedPower / FTP;
const TSS = (durationSeconds * normalizedPower * intensityFactor) / (FTP * 3600) * 100;
return Math.round(TSS);
}
// Exempel på användning:
const TSS = beräknaTSS(7200, 235, 250);
// Returnerar: 177
2. Normaliserad effekt (NP)
Algoritm (30-sekunders rullande medelvärde):
Varför den 4:e makten?
Det kvartiga (4:e potens) förhållandet återspeglar den icke-linjära fysiologiska kostnaden för variabla ansträngningar. En tur med överspänningar och återhämtning kostar mer energi än jämn kraft vid samma genomsnitt.
Exempel:
- Stadig körning: 200W i 1 timme → NP = 200W, medelvärde = 200W
- Variabel körning: Alternerande 300W/100W → Genomsnitt = 200W, NP = 225W
Samma medeleffekt, men variabel körning har 12% högre NP på grund av fysiologiska kostnader för överspänningar
JavaScript-implementering:
function calculateNormalizedPower(powerData) {
// powerData är en matris med 1-sekunds effektvärden
// Steg 1: Beräkna 30-sekunders rullande medelvärden
const rollingAvgs = [];
for (låt i = 29; i < powerData.length; i++) {
const window = powerData.slice(i - 29, i + 1);
const avg = window.reduce((summa, p) => summa + p, 0) / 30;
rollingAvgs.push(avg);
}
// Steg 2: Höj till 4:e potens
const powered = rollingAvgs.map(p => Math.pow(p, 4));
// Steg 3: Genomsnitt av 4:e potenser
const avgPowered = powered.reduce((summa, p) => summa + p, 0) / powered.length;
// Steg 4: Ta 4:e roten
const np = Math.pow(avgPowered, 0,25);
return Math.round(np);
}
// Exempel på användning:
const powerData = [/* 1-sekunds power array */];
const np = calculateNormalizedPower(powerData);
// Returnerar: NP i watt
3. Intensitetsfaktor (IF)
Formel:
Tolkningsintervall:
| IF Räckvidd | Ansträngningsnivå | Exempel träning |
|---|---|---|
| < 0,75 | Återhämtning / Lätt | Aktiv återhämtningsritt, zon 1-2 |
| 0,75 - 0,85 | Uthållighet | Lång stadig resa, aerob bas |
| 0,85 - 0,95 | Tempo | Sweet spot träning, tempointervaller |
| 0,95 - 1,05 | Tröskel | FTP intervaller, tidskörning |
| 1,05 - 1,15 | VO₂max | 5-minutersintervaller, kriteriumlopp |
| > 1,15 | Anaerob | Korta spurter, attacker, MTB-skurar |
Exempel på beräkning:
Scenario:NP = 235W, FTP = 250W
IF = 235 / 250 =0,94
Tolkning: Högt tempo/undertröskelansträngning, hållbar i 2-3 timmar
function calculateIF(normalizedPower, FTP) {
return (normalizedPower / FTP).toFixed(2);
}
// Exempel:
const if_value = calculateIF(235, 250);
// Returnerar: 0,94
4. Variabilitetsindex (VI)
Formel:
Tolkning efter disciplin:
| Disciplin | Typiskt VI | Menande |
|---|---|---|
| Road TT / Stadig ansträngning | 1.00 - 1.05 | Mycket konsekvent kraft, optimal pacing |
| Road Racing | 1,05 - 1,10 | Vissa överspänningar, i allmänhet stadiga |
| Kriterium | 1.10 - 1.20 | Frekventa accelerationer och attacker |
| Mountainbike XC | 1.15 - 1.30+ | Mycket varierande, konstanta överspänningar |
Exempel på beräkning:
Road Race:NP = 240W, Genomsnittlig effekt = 230W
VI = 240 / 230 =1.04(jämnt tempo)
MTB-lopp:NP = 285W, Genomsnittlig effekt = 235W
VI = 285 / 235 =1.21(mycket varierande, explosiva ansträngningar)
function calculateVI(normalizedPower, averagePower) {
return (normaliserad Power / genomsnittlig Power).toFixed(2);
}
// Exempel:
const vi_väg = beräknaVI(240, 230); // Returnerar: 1,04
const vi_mtb = beräknaVI(285, 235); // Returnerar: 1,21
Critical Power & W' (anaerob kapacitet)
5. Kritisk kraft (CP) - Linjär modell
Formel:
Beräkning från flera försök:
Kräver 2-4 maximala ansträngningar vid olika varaktigheter (t.ex. 3, 5, 12, 20 minuter)
Exempeldata:
| Varaktighet | Effekt (W) | Totalt arbete (kJ) |
|---|---|---|
| 3 min (180s) | 400W | 72 kJ |
| 5 min (300s) | 365W | 109,5 kJ |
| 12 min (720s) | 310W | 223,2 kJ |
| 20 min (1200 s) | 285W | 342 kJ |
Använda linjär regression (Arbete = CP × Tid + W'):
- CP = 270W(lutningen på regressionslinjen)
- W' = 18,5 kJ(y-skärning)
JavaScript-implementering:
function calculateCP_Linear(ansträngningar) {
// ansträngningar = [{varaktighet: sekunder, effekt: watt}, ...]
const times = Efforts.map(e => e.duration);
const work = Efforts.map(e => e.power * e.duration / 1000); // kJ
// Linjär regression: arbete = CP * tid + W'
const n = ansträngningar.längd;
const sumT = times.reduce((a, b) => a + b, 0);
const sumW = work.reduce((a, b) => a + b, 0);
const sumTW = times.reduce((summa, t, i) => summa + t * arbete[i], 0);
const sumTT = times.reduce((summa, t) => summa + t * t, 0);
const CP = (n * summaTW - summaT * summaW) / (n * summaTT - summaT * summaT);
const Wprime = (summaW - CP * summaT) / n;
returnera {
CP: Math.round(CP * 10) / 10, // watt
Wprime: Math.round(Wprime * 10) / 10 // kJ
};
}
// Exempel på användning:
const ansträngningar = [
{varaktighet: 180, effekt: 400},
{duration: 300, power: 365},
{varaktighet: 720, effekt: 310},
{varaktighet: 1200, effekt: 285}
];
const result = calculateCP_Linear(ansträngningar);
// Returnerar: { CP: 270.0, Wprime: 18.5 }
6. W' Balance (W'bal) - differentialekvationsmodell
Formler:
W'exp(t) = ∫(P(t) - CP) dt
W'rec(t) = W' × (1 - e^(-t/τ))
och ΔCP = (CP - P(t))
Exempel från verkliga världen:
Specifikationer för cyklister:CP = 270W, W' = 18,5 kJ
Scenario 1 - Hård attack:
- Rider stiger till 400W i 30 sekunder
- W'-utgifter: (400 - 270) × 30 = 3 900 J = 3,9 kJ
- W'bal återstående: 18,5 - 3,9 =14,6 kJ
Scenario 2 - Återställning:
- Efter attack, sjunker till 200W (70W under CP) i 2 minuter
- ΔCP = 270 - 200 = 70W
- τ = 546 × e^(-0,01 × 70) + 316 = 588 sekunder
- Återhämtning på 120s: 18,5 × (1 - e^(-120/588)) =3,5 kJ återvunnen
- Ny W'bal: 14,6 + 3,5 =18,1 kJ
JavaScript-implementering:
function calculateWbalance(powerData, CP, Wprime) {
// powerData = array av {tid: sekunder, effekt: watt}
låt wbal = Wprime * 1000; // Konvertera till joule
const wbalHistory = [];
for (låt i = 1; i < powerData.length; i++) {
const dt = powerData[i].tid - powerData[i-1].tid;
const power = powerData[i].power;
IF (ström > CP) {
// Utgifter över CP
const utgifter = (kraft - CP) * dt;
wbal -= utgifter;
} annat {
// Återhämtning under CP
const deltaCP = CP - effekt;
const tau = 546 * Math.exp(-0,01 * deltaCP) + 316;
const recovery = (Wprime * 1000 - wbal) * (1 - Math.exp(-dt / tau));
wbal += återhämtning;
}
// Se till att W'bal inte överstiger max eller blir negativ
wbal = Math.max(0, Math.min(wbal, Wprime * 1000));
wbalHistory.push({
tid: powerData[i].tid,
wbal: wbal / 1000, // kJ
procent: (wbal / (Wprime * 1000)) * 100
});
}
returnera wbalHistory;
}
// Exempel på användning:
const powerData = [
{tid: 0, effekt: 200},
{tid: 1, effekt: 210},
// ... resten av åkdata
];
const wbalHistory = calculateWbalance(powerData, 270, 18,5);
// Returnerar array av W'bal-värden över tid
Resultatstyrningsdiagram (PMC)
7. CTL, ATL, TSB Beräkningar
Formler (exponentiellt vägda glidande medelvärden):
Metriska definitioner:
- CTL (kronisk träningsbelastning):42-dagars exponentiellt vägt medelvärde - representerar kondition
- ATL (akut träningsbelastning):7-dagars exponentiellt vägt medelvärde - representerar trötthet
- TSB (träning av stressbalans):Form = Fitness - Trötthet
Arbetat exempel (7-dagars träningsblock):
| Dag | TSS | CTL | ATL | TSB | Status |
|---|---|---|---|---|---|
| mån | 100 | 75,0 | 80,0 | -5,0 | Utbildning |
| tis | 50 | 74,4 | 75,7 | -1.3 | Återhämtning |
| ons | 120 | 75,5 | 82,0 | -6,5 | Hård träning |
| tors | 0 | 73,7 | 70,3 | +3,4 | Vilodag |
| fre | 80 | 73,8 | 71,7 | +2.1 | Måttlig |
| lö | 150 | 75,6 | 82,9 | -7.3 | Lång åktur |
| Sol | 40 | 74,8 | 76,8 | -2,0 | Återhämtning |
TSB Tolkning:
| TSB Räckvidd | Status | Handling |
|---|---|---|
| < -30 | Hög risk | Varning för överträning - minska belastningen |
| -30 till -10 | Träna hårt | Bygg kondition, övervaka återhämtningen |
| -10 till +5 | Optimal | Normal träningszon |
| +5 till +15 | Klar för tävling | Toppform - lopp i helgen |
| > +25 | Avträning | Förlust av kondition – öka belastningen |
JavaScript-implementering:
function calculatePMC(workouts) {
// träningspass = [{datum: "ÅÅÅÅ-MM-DD", TSS: nummer}, ...]
låt CTL = 0, ATL = 0;
const resultat = [];
workouts.forEach(workout => {
// Uppdatera CTL (42-dagars tidskonstant)
CTL = CTL + (träningspass.TSS - CTL) / 42;
// Uppdatera ATL (7-dagars tidskonstant)
ATL = ATL + (träningspass.TSS - ATL) / 7;
// Beräkna TSB (gårdagens CTL - dagens ATL för traditionell beräkning)
// För enkelhetens skull här med aktuella värden
const TSB = CTL - ATL;
results.push({
datum: workout.date,
TSS: träning.TSS,
CTL: Math.round(CTL * 10) / 10,
ATL: Math.round(ATL * 10) / 10,
TSB: Math.round(TSB * 10) / 10,
status: getTSBStatus(TSB)
});
});
returnera resultat;
}
function getTSBStatus(TSB) {
IF (TSB < -30) returnerar "Hög risk";
IF (TSB < -10) returnera "Tränar hårt";
IF (TSB < 5) returnera "Optimal";
IF (TSB < 15) returnerar "Race Ready";
returnera "Utbildning";
}
// Exempel på användning:
konstant träning = [
{datum: "2025-01-01", TSS: 100},
{datum: "2025-01-02", TSS: 50},
{datum: "2025-01-03", TSS: 120},
// ... fler träningspass
];
const PMC = beräknaPMC(träningspass);
// Returnerar array med CTL, ATL, TSB för varje dag
Kraft-till-vikt och klättring
8. Kraft-till-vikt-förhållande
Formel:
FTP W/kg Benchmarks:
| Nivå | Hane W/kg | Hona W/kg | Kategori |
|---|---|---|---|
| Rekreation | 2,5 - 3,5 | 2,0 - 3,0 | Fitness ryttare |
| Konkurrenskraftig | 3,5 - 4,5 | 3,0 - 4,0 | Katt 3-4, åkare i åldersgrupp |
| Avancerad | 4,5 - 5,5 | 4,0 - 5,0 | Katt 1-2, stark amatör |
| Elitamatör | 5,5 - 6,0 | 5,0 - 5,5 | Nationell nivå |
| Professionell | 6,0 - 7,0+ | 5,5 - 6,5+ | World Tour, Grand Tour GC |
Exempel på beräkning:
Scenario:Cyklist med FTP = 275W, kroppsvikt = 70 kg
W/kg = 275 / 70 =3,93 W/kg
Tolkning: Tävlingsnivå, kapabel i kuperade lopp
function calculateWattsPerKg(power, bodyMassKg) {
return (power / bodyMassKg).toFixed(2);
}
// Exempel:
const wpkg = calculateWattsPerKg(275, 70);
// Avkastning: 3,93
9. VAM (Velocità Ascensionale Media)
Formel:
VAM Benchmarks:
| VAM (m/h) | Nivå | Exempel |
|---|---|---|
| 600 - 900 | Rekreation | Klubbryttare på lokal klättring |
| 900 - 1200 | Konkurrenskraftig | Bra amatör på Alpe d'Huez |
| 1200 - 1500 | Elitamatör | Klätterare på nationell nivå |
| 1500 - 1800 | Professionell | World Tour inrikes |
| > 1800 | Vinnare av Grand Tour | Pogačar, Vingegaard på nyckelklättringar |
Exempel på beräkning:
Scenario:Alpe d'Huez klättring
- Höjdökning: 1100 meter
- Tid: 55 minuter = 0,917 timmar
- VAM = 1100 / 0,917 =1200 m/h
Tolkning: Klättringsprestanda på tävlingsnivå
function calculateVAM(elevationGainMeters, timeMinutes) {
const timmar = tidMinuter / 60;
return Math.round(elevationGainMeters / timmar);
}
// Exempel:
const vam = beräknaVAM(1100, 55);
// Returer: 1200 m/h
10. VAM till W/kg uppskattning
Formel:
Exempel på beräkning:
Scenario:Klättring med 8 % medelgradient, VAM = 1200 m/h
W/kg = 1200 / 100 / (8 + 3)
W/kg = 12 / 11 =4,36 W/kg
Cross-check: Med 70 kg förare → 305W bibehållen kraft vid stigning
function estimateWkgFromVAM(vam, gradientProcent) {
return (vam / 100 / (gradientPercent + 3)).toFixed(2);
}
// Exempel:
const wkg = uppskattningWkgFrånVAM(1200, 8);
// Avkastning: 4,36
Aerodynamisk effektekvation
11. Totala effektbehov
Komplett formel:
Komponentformler:
P_aero = CdA × 0,5 × ρ × V³
P_gravity = m × g × sin(θ) × V
P_rolling = Crr × m × g × cos(θ) × V
P_kinetisk = m × a × V
Konstanter och variabler:
- CdA= Drakoefficient × frontarea (m²)
- Typiska motorcykelhuvar: 0,35-0,40 m²
- Fall: 0,32-0,37 m²
- TT-läge: 0,20-0,25 m²
- ρ= Luftdensitet (1,225 kg/m³ vid havsnivå, 15°C)
- V= Hastighet (m/s)
- m= Total massa (ryttare + cykel, kg)
- g= Tyngdkraften (9,81 m/s²)
- θ= Gradientvinkel (radianer eller grader konverterade)
- Crr= Rullmotståndskoefficient (~0,004 för bra vägdäck)
- a= Acceleration (m/s²)
Arbetat exempel (Flat Road TT):
Scenario:
- Hastighet: 40 km/h = 11,11 m/s
- CdA: 0,22 m² (bra TT-läge)
- Total massa: 75 kg (ryttare) + 8 kg (cykel) = 83 kg
- Platt väg (lutning = 0°)
- Konstant hastighet (acceleration = 0)
Beräkning:
- P_aero= 0,22 × 0,5 × 1,225 × 11,11³ =185W
- P_gravitation= 0W (plan väg)
- P_rullande= 0,004 × 83 × 9,81 × 11,11 =36W
- P_kinetisk= 0W (konstant hastighet)
- P_total= 185 + 0 + 36 + 0 =221W
Tolkning: Behöver 221W för att klara 40 km/h i TT-läge på plan väg
JavaScript-implementering:
function calculatePowerRequired(params) {
const {
hastighet Kph,
CdA = 0,32, //m²
rho = 1,225, // kg/m³
massa = 83, // kg (ryttare + cykel)
gradientProcent = 0, // %
Crr = 0,004, // rullmotstånd
accelerationMps2 = 0 // m/s²
} = params;
// Konvertera hastighet till m/s
const V = hastighet Kph / 3,6;
// Konvertera gradient till vinkel
const theta = Math.atan(gradientPercent / 100);
// Beräkna varje komponent
const P_aero = CdA * 0,5 * rho * Math.pow(V, 3);
const P_gravity = massa * 9,81 * Math.sin(theta) * V;
const P_rolling = Crr * massa * 9,81 * Math.cos(theta) * V;
const P_kinetic = massa * accelerationMps2 * V;
returnera {
totalt: 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)
};
}
// Exempel: TT i 40 km/h
const power_tt = calculatePowerRequired({
hastighet Kph: 40,
CdA: 0,22,
vikt: 83,
gradientProcent: 0
});
// Returnerar: { totalt: 221, aero: 185, gravitation: 0, rullande: 36, kinetisk: 0 }
// Exempel: 8% klättring i 15 km/h
const power_climb = calculatePowerRequired({
hastighet Kph: 15,
CdA: 0,38,
vikt: 75,
gradientProcent: 8
});
// Returnerar: { totalt: 265, aero: 27, gravitation: 244, rullande: 11, kinetisk: 0 }
Hjälpfunktioner
Unit Conversion Utilities
JavaScript-implementering:
// Tidsomvandlingar
function hoursToSeconds(hours) {
returtimmar * 3600;
}
function minutesToSeconds(minutes) {
returminuter * 60;
}
function secondsToHours(sekunder) {
retur sekunder / 3600;
}
function formatDuration(sekunder) {
const timmar = Math.floor(sekunder / 3600);
const minuter = Math.floor((sekunder % 3600) / 60);
const secs = Math.round(sekunder % 60);
return `${timmar}:${minutes.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')}`;
}
// Hastighetsomvandlingar
function kphToMps(kph) {
retur kph / 3,6;
}
function mpsToKph(mps) {
returnera mps * 3,6;
}
// Energiomvandlingar
function joulesTo kJ(joules) {
retur joule / 1000;
}
function kJToJoules(kJ) {
retur kJ * 1000;
}
function wattsToKJ(watt, durationSeconds) {
retur (watt * durationSeconds) / 1000;
}
// Exempel:
formatDuration(7265); // Returnerar: "2:01:05"
kphToMps(40); // Avkastning: 11,11 m/s
wattToKJ(250, 3600); // Retur: 900 kJ (1 timme vid 250W)
Implementeringsresurser
Alla formler på denna sida är produktionsklara och validerade mot vetenskaplig litteratur och verkliga kraftmätaredata. Använd dem för anpassade analysverktyg, verifiering eller djupare förståelse för kraftbaserade träningsberäkningar.
💡 Bästa metoder
- Validera indata:Kontrollera om det finns rimliga effektområden (0-2000W), positiva varaktigheter
- Hantera kantfodral:Division med noll, noll/odefinierad data, saknas FTP
- Runda på lämpligt sätt:CTL/ATL/TSB till 1 decimal, TSS till heltal, W/kg till 2 decimaler
- Lagringsprecision:Håll full precision i databasen, endast rund för visning
- Tidszoner:Hantera UTC vs lokal tid konsekvent för flerdagarsanalys
- Kalibrering av effektmätare:Påminn användarna om att nollkompensera före åk
- FTP validering:Flagga misstänkta FTP-värden (>500W eller <100W för vuxna)
- Testa noggrant:Använd välkända körfiler för att verifiera beräkningar