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:

TSS = (varaktighet_sekunder × NP × IF) / (FTP × 3600) × 100
där IF = NP / FTP

Arbetat exempel:

Scenario:2 timmars resa, NP = 235W, FTP = 250W

  1. Beräkna IF: IF = 235 / 250 = 0,94
  2. Varaktighet i sekunder: 2 timmar × 3600 = 7200 sekunder
  3. TSS = (7200 × 235 × 0,94) / (250 × 3600) × 100
  4. 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):

1. Beräkna 30-sekunders rullande medeleffekt för hela åkturen
2. Höj varje 30-sekunders värde till 4:e potens
3. Ta medelvärdet av alla dessa ^4 värden
4. Ta 4:e roten av det genomsnittet
NP = ⁴√(genomsnitt av [30s_avg^4])

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:

IF = NP / FTP

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:

VI = NP / medeleffekt

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:

Tid = W' / (Power - CP)
Omarrangerad: Effekt × Tid = CP × Tid + W'

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:

Utgifter (när P > CP):
W'exp(t) = ∫(P(t) - CP) dt
Återställning (när P < CP):
W'rec(t) = W' × (1 - e^(-t/τ))
där τ = 546 × e^(-0,01 × ΔCP) + 316
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):

CTL_today = CTL_yesterday + (TSS_today - CTL_yesterday) / 42
ATL_today = ATL_yesterday + (TSS_today - ATL_yesterday) / 7
TSB_today = CTL_yesterday - ATL_yesterday

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
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:

W/kg = Effekt (watt) / Kroppsmassa (kg)

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 (m/h) = Höjdförstärkning (m) / Tid (timmar)

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:

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

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:

P_total = P_aero + P_gravity + P_rolling + P_kinetic

Komponentformler:

Aerodynamisk dragkraft:
P_aero = CdA × 0,5 × ρ × V³
Gravitation (klättring):
P_gravity = m × g × sin(θ) × V
Rullmotstånd:
P_rolling = Crr × m × g × cos(θ) × V
Kinetisk (acceleration):
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:

  1. P_aero= 0,22 × 0,5 × 1,225 × 11,11³ =185W
  2. P_gravitation= 0W (plan väg)
  3. P_rullande= 0,004 × 83 × 9,81 × 11,11 =36W
  4. P_kinetisk= 0W (konstant hastighet)
  5. 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