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

Cykling 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äckviddAnsträngningsnivåExempel träning
< 0,75Återhämtning / LättAktiv återhämtningsritt, zon 1-2
0,75 - 0,85UthållighetLång stadig resa, aerob bas
0,85 - 0,95TempoSweet spot träning, tempointervaller
0,95 - 1,05TröskelFTP intervaller, tidskörning
1,05 - 1,15VO₂max5-minutersintervaller, kriteriumlopp
> 1,15AnaerobKorta 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:

DisciplinTypiskt VIMenande
Road TT / Stadig ansträngning1.00 - 1.05Mycket konsekvent kraft, optimal pacing
Road Racing1,05 - 1,10Vissa överspänningar, i allmänhet stadiga
Kriterium1.10 - 1.20Frekventa accelerationer och attacker
Mountainbike XC1.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:

VaraktighetEffekt (W)Totalt arbete (kJ)
3 min (180s)400W72 kJ
5 min (300s)365W109,5 kJ
12 min (720s)310W223,2 kJ
20 min (1200 s)285W342 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) för cykling

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

DagTSSCTLATLTSBStatus
mån10075,080,0-5,0Utbildning
tis5074,475,7-1.3Återhämtning
ons12075,582,0-6,5Hård träning
tors073,770,3+3,4Vilodag
fre8073,871,7+2.1Måttlig
15075,682,9-7.3Lång åktur
Sol4074,876,8-2,0Återhämtning

TSB Tolkning:

TSB RäckviddStatusHandling
< -30Hög riskVarning för överträning - minska belastningen
-30 till -10Träna hårtBygg kondition, övervaka återhämtningen
-10 till +5OptimalNormal träningszon
+5 till +15Klar för tävlingToppform - lopp i helgen
> +25AvträningFö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/kgHona W/kgKategori
Rekreation2,5 - 3,52,0 - 3,0Fitness ryttare
Konkurrenskraftig3,5 - 4,53,0 - 4,0Katt 3-4, åkare i åldersgrupp
Avancerad4,5 - 5,54,0 - 5,0Katt 1-2, stark amatör
Elitamatör5,5 - 6,05,0 - 5,5Nationell nivå
Professionell6,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 - 900RekreationKlubbryttare på lokal klättring
900 - 1200KonkurrenskraftigBra amatör på Alpe d'Huez
1200 - 1500ElitamatörKlätterare på nationell nivå
1500 - 1800ProfessionellWorld Tour inrikes
> 1800Vinnare av Grand TourPogač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