Rattasõidu Võimsuse Valemid

Bike Analyticsi Mõõdikute Matemaatiline Vundament

Rakendamise Juhend

See leht pakub kopeeritavaid valemeid ja samm-sammult arvutusmeetodeid kõigi Bike Analyticsi mõõdikute jaoks. Kasuta neid kohandatud rakenduste, kontrollimise või võimsuspõhise treeningu sügavama mõistmise jaoks.

⚠️ Rakendamise Märkused

  • Kõik võimsuse väärtused on vattides (W), aeg sekundites, kui pole märgitud teisiti
  • FTP ja CP on individuaalsed läved—universaalsed väärtused puuduvad
  • Valideeri alati sisendeid mõistlike vahemike suhtes (0-2000W tüüpiline)
  • Käsitle erijuhte (jagamine nulliga, negatiivne võimsus)
  • Võimsusandmed vajavad täpsuse huvides 1-sekundilist salvestusintervalli

Põhilised Sooritusvõime Mõõdikud

1. Training Stress Score (TSS)

Valem:

TSS = (kestus_sekundites × NP × IF) / (FTP × 3600) × 100
kus IF = NP / FTP

Näide:

Stsenaarium: 2-tunnine sõit, NP = 235W, FTP = 250W

  1. Arvuta IF: IF = 235 / 250 = 0.94
  2. Kestus sekundites: 2 tundi × 3600 = 7200 sekundit
  3. TSS = (7200 × 235 × 0.94) / (250 × 3600) × 100
  4. TSS = 1,590,720 / 900,000 × 100 = 176.7 TSS

Tõlgendus: Raske treening (>150 TSS), eelda 2-3 päeva taastumist

JavaScript Rakendus:

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

// Example usage:
const tss = calculateTSS(7200, 235, 250);
// Returns: 177

2. Normalized Power (NP)

Algoritm (30-sekundiline libisev keskmine):

1. Arvuta 30-sekundiline libisev keskmine võimsus kogu sõidule
2. Tõsta iga 30-sek väärtus astmesse 4
3. Võta kõigi nende ^4 väärtuste keskmine
4. Võta sellest keskmisest neljas juur
NP = ⁴√(keskmine([30s_avg^4]))

Miks Neljas Aste?

Nelik- (neljas aste) suhe peegeldab varieeruvate pingutuste mittelineaarset füsioloogilist kulu. Sööstude ja taastumistega sõit kulutab rohkem energiat kui ühtlane võimsus sama keskmise juures.

Näide:

  • Ühtlane sõit: 200W 1 tund → NP = 200W, Keskmine = 200W
  • Varieeruv sõit: Vahelduv 300W/100W → Keskmine = 200W, NP = 225W

Sama keskmine võimsus, kuid varieeruval sõidul on 12% kõrgem NP sööstude füsioloogilise kulu tõttu

JavaScript Rakendus:

function calculateNormalizedPower(powerData) {
  // powerData is array of 1-second power values

  // Step 1: Calculate 30-second rolling averages
  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);
  }

  // Step 2: Raise to 4th power
  const powered = rollingAvgs.map(p => Math.pow(p, 4));

  // Step 3: Average of 4th powers
  const avgPowered = powered.reduce((sum, p) => sum + p, 0) / powered.length;

  // Step 4: Take 4th root
  const np = Math.pow(avgPowered, 0.25);

  return Math.round(np);
}

// Example usage:
const powerData = [/* 1-second power array */];
const np = calculateNormalizedPower(powerData);
// Returns: NP in watts

3. Intensity Factor (IF)

Valem:

IF = NP / FTP

Tõlgendamise Vahemikud:

IF Vahemik Pingutuse Tase Näidistreening
< 0.75 Taastav / Kerge Aktiivne taastussõit, Tsoon 1-2
0.75 - 0.85 Vastupidavus Pikk ühtlane sõit, aeroobne baas
0.85 - 0.95 Tempo Sweet spot treening, tempointervallid
0.95 - 1.05 Lävi (Threshold) FTP intervallid, eraldistart
1.05 - 1.15 VO₂max 5-minutilised intervallid, kriteerium
> 1.15 Anaeroobne Lühikesed sprindid, rünnakud, MTB sööstud

Arvutuse Näide:

Stsenaarium: NP = 235W, FTP = 250W

IF = 235 / 250 = 0.94

Tõlgendus: Kõrge tempo / sub-läve pingutus, jätkusuutlik 2-3 tundi

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

// Example:
const if_value = calculateIF(235, 250);
// Returns: 0.94

4. Variability Index (VI)

Valem:

VI = NP / Keskmine Võimsus

Tõlgendus Distsipliinide Kaupa:

Distsipliin Tüüpiline VI Tähendus
Mnt Eraldistart / Ühtlane 1.00 - 1.05 Väga ühtlane võimsus, optimaalne tempo
Mnt Grupisõit 1.05 - 1.10 Mõned sööstud, üldiselt ühtlane
Kriteerium 1.10 - 1.20 Sagedased kiirendused ja rünnakud
Maastikuratas (MTB XC) 1.15 - 1.30+ Väga varieeruv, pidevad sööstud

Arvutuse Näide:

Mnt Grupisõit: NP = 240W, Avg Power = 230W

VI = 240 / 230 = 1.04 (ühtlane tempo)

MTB Võistlus: NP = 285W, Avg Power = 235W

VI = 285 / 235 = 1.21 (väga varieeruv, sööstlik pingutus)

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

// Example:
const vi_road = calculateVI(240, 230);  // Returns: 1.04
const vi_mtb = calculateVI(285, 235);   // Returns: 1.21

Critical Power & W' (Anaeroobne Võimekus)

5. Critical Power (CP) - Lineaarne Mudel

Valem:

Aeg = W' / (Võimsus - CP)
Ümberkorraldatult: Võimsus × Aeg = CP × Aeg + W'

Arvutamine Mitme Pingutuse Põhjal:

Nõuab 2-4 maksimaalset pingutust erinevatel kestustel (nt 3, 5, 12, 20 minutit)

Näidisandmed:

Kestus Võimsus (W) Kogutöö (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

Kasutades lineaarregressiooni (Töö = CP × Aeg + W'):

  • CP = 270W (regressioonijoone tõus)
  • W' = 18.5 kJ (y-telje lõikepunkt)

JavaScript Rakendus:

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

  // Linear 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,      // watts
    Wprime: Math.round(Wprime * 10) / 10  // kJ
  };
}

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

const result = calculateCP_Linear(efforts);
// Returns: { CP: 270.0, Wprime: 18.5 }

6. W' Bilanss (W'bal) - Diferentsiaalvõrrandi Mudel

Valemid:

Kulu (kui P > CP):
W'exp(t) = ∫(P(t) - CP) dt
Taastumine (kui P < CP):
W'rec(t) = W' × (1 - e^(-t/τ))
kus τ = 546 × e^(-0.01 × ΔCP) + 316
ja ΔCP = (CP - P(t))

Reaalse Maailma Näide:

Ratturi näitajad: CP = 270W, W' = 18.5 kJ

Stsenaarium 1 - Tugev Rünnak:

  • Rattur kiirendab 400W peale 30 sekundiks
  • W' kulu: (400 - 270) × 30 = 3,900 J = 3.9 kJ
  • W'bal jääk: 18.5 - 3.9 = 14.6 kJ

Stsenaarium 2 - Taastumine:

  • Pärast rünnakut langeb 200W peale (70W alla CP) 2 minutiks
  • ΔCP = 270 - 200 = 70W
  • τ = 546 × e^(-0.01 × 70) + 316 = 588 sekundit
  • Taastumine 120s jooksul: 18.5 × (1 - e^(-120/588)) = 3.5 kJ taastatud
  • Uus W'bal: 14.6 + 3.5 = 18.1 kJ

JavaScript Rakendus:

function calculateWbalance(powerData, CP, Wprime) {
  // powerData = array of {time: seconds, power: watts}
  let wbal = Wprime * 1000; // Convert to joules
  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) {
      // Expenditure above CP
      const expenditure = (power - CP) * dt;
      wbal -= expenditure;
    } else {
      // Recovery below 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;
    }

    // Ensure W'bal doesn't exceed max or go negative
    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;
}

// Example usage:
const powerData = [
  {time: 0, power: 200},
  {time: 1, power: 210},
  // ... rest of ride data
];

const wbalHistory = calculateWbalance(powerData, 270, 18.5);
// Returns array of W'bal values over time

Sooritusvõime Haldamise Graafik (PMC)

7. CTL, ATL, TSB Arvutused

Valemid (Eksponentsiaalselt Kaalutud Libisevad Keskmised):

CTL_täna = CTL_eile + (TSS_täna - CTL_eile) / 42
ATL_täna = ATL_eile + (TSS_täna - ATL_eile) / 7
TSB_täna = CTL_eile - ATL_eile

Mõõdikute Definitsioonid:

  • CTL (Krooniline Treeningkoormus): 42-päeva eksponentsiaalselt kaalutud keskmine - esindab vormi (Fitness)
  • ATL (Akuutne Treeningkoormus): 7-päeva eksponentsiaalselt kaalutud keskmine - esindab väsimust (Fatigue)
  • TSB (Treeningstressi Bilanss): Värskus (Form) = Vorm - Väsimus

Arvutuse Näide (7-Päevane Treeningtsükkel):

Päev TSS CTL ATL TSB Staatus
E 100 75.0 80.0 -5.0 Treening
T 50 74.4 75.7 -1.3 Taastumine
K 120 75.5 82.0 -6.5 Raske Treening
N 0 73.7 70.3 +3.4 Puhkepäev
R 80 73.8 71.7 +2.1 Mõõdukas
L 150 75.6 82.9 -7.3 Pikk Sõit
P 40 74.8 76.8 -2.0 Taastumine

TSB Tõlgendus:

TSB Vahemik Staatus Tegevus
< -30 Kõrge Risk Ületreeningu hoiatus - vähenda koormust
-30 kuni -10 Treenimas Kõvasti Vormi ehitamine, jälgi taastumist
-10 kuni +5 Optimaalne Normaalne treeningtsoon
+5 kuni +15 Võistlusvalmis Tippvorm - võistle sel nädalavahetusel
> +25 Vormi Langus (Detraining) Vormi kadu - tõsta koormust

JavaScript Rakendus:

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

  workouts.forEach(workout => {
    // Update CTL (42-day time constant)
    ctl = ctl + (workout.tss - ctl) / 42;

    // Update ATL (7-day time constant)
    atl = atl + (workout.tss - atl) / 7;

    // Calculate TSB (yesterday's CTL - today's ATL for traditional calculation)
    // For simplicity here using current values
    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";
}

// Example usage:
const workouts = [
  {date: "2025-01-01", tss: 100},
  {date: "2025-01-02", tss: 50},
  {date: "2025-01-03", tss: 120},
  // ... more workouts
];

const pmc = calculatePMC(workouts);
// Returns array with CTL, ATL, TSB for each day

Võimsuse-Kaalu Suhe & Tõusumõõdikud

8. Võimsuse-Kaalu Suhe (W/kg)

Valem:

W/kg = Võimsus (vattides) / Kehamass (kg)

FTP W/kg Võrdlusnäitajad:

Tase Mehed W/kg Naised W/kg Kategooria
Harrastaja 2.5 - 3.5 2.0 - 3.0 Tervisesportlane
Võistleja 3.5 - 4.5 3.0 - 4.0 Cat 3-4, vanusegrupi võistleja
Edasijõudnud 4.5 - 5.5 4.0 - 5.0 Cat 1-2, tugev amatöör
Eliit-Amatöör 5.5 - 6.0 5.0 - 5.5 Rahvuslik tase
Proff 6.0 - 7.0+ 5.5 - 6.5+ World Tour, Grand Tour GC

Arvutuse Näide:

Stsenaarium: Rattur FTP = 275W, kehamass = 70kg

W/kg = 275 / 70 = 3.93 W/kg

Tõlgendus: Võistlustase, võimeline mägistel võistlustel

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

// Example:
const wpkg = calculateWattsPerKg(275, 70);
// Returns: 3.93

9. VAM (Velocità Ascensionale Media)

Valem:

VAM (m/h) = Tõusumeetrid (m) / Aeg (tundides)

VAM Võrdlusnäitajad:

VAM (m/h) Tase Näide
600 - 900 Harrastaja Klubisõitja kohalikul tõusul
900 - 1200 Võistleja Hea amatöör Alpe d'Huezil
1200 - 1500 Eliit-Amatöör Rahvusliku taseme ronija
1500 - 1800 Proff World Tour abisõitja
> 1800 Grand Tour Võitja Pogačar, Vingegaard võtmetõusudel

Arvutuse Näide:

Stsenaarium: Alpe d'Huezi tõus

  • Tõusumeetrid: 1100 meetrit
  • Aeg: 55 minutit = 0.917 tundi
  • VAM = 1100 / 0.917 = 1200 m/h

Tõlgendus: Võistlustasemel ronimisvõime

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

// Example:
const vam = calculateVAM(1100, 55);
// Returns: 1200 m/h

10. VAM-ist W/kg Ennustamine

Valem:

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

Arvutuse Näide:

Stsenaarium: Tõus 8% keskmise kaldega, VAM = 1200 m/h

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

W/kg = 12 / 11 = 4.36 W/kg

Kontroll: 70kg ratturiga → 305W jätkusuutlik võimsus tõusul

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

// Example:
const wkg = estimateWkgFromVAM(1200, 8);
// Returns: 4.36

Aerodünaamilise Võimsuse Võrrand

11. Koguvõimsuse Nõuded

Täielik Valem:

P_total = P_aero + P_gravity + P_rolling + P_kinetic

Komponentide Valemid:

Aerodünaamiline Takistus:
P_aero = CdA × 0.5 × ρ × V³
Gravitatsioon (Ronimine):
P_gravity = m × g × sin(θ) × V
Veeretakistus:
P_rolling = Crr × m × g × cos(θ) × V
Kineetiline (Kiirendus):
P_kinetic = m × a × V

Konstandid & Muutujad:

  • CdA = Takistustegur × ristlõikepindala (m²)
    • Tüüpiline maanteeratas käed linkidel: 0.35-0.40 m²
    • Käed sarvedel (Drops): 0.32-0.37 m²
    • TT asend: 0.20-0.25 m²
  • ρ = Õhutihedus (1.225 kg/m³ merepinnal, 15°C)
  • V = Kiirus (m/s)
  • m = Kogumass (rattur + ratas, kg)
  • g = Gravitatsioon (9.81 m/s²)
  • θ = Kaldenurk (radiaanides või kraadides teisendatud)
  • Crr = Veeretakistustegur (~0.004 headel maanteerehveidel)
  • a = Kiirendus (m/s²)

Arvutuse Näide (Tasane Eraldistart):

Stsenaarium:

  • Kiirus: 40 km/h = 11.11 m/s
  • CdA: 0.22 m² (hea TT asend)
  • Kogumass: 75kg (rattur) + 8kg (ratas) = 83kg
  • Tasane tee (kalle = 0°)
  • Konstantne kiirus (kiirendus = 0)

Arvutus:

  1. P_aero = 0.22 × 0.5 × 1.225 × 11.11³ = 185W
  2. P_gravity = 0W (tasane tee)
  3. P_rolling = 0.004 × 83 × 9.81 × 11.11 = 36W
  4. P_kinetic = 0W (konstantne kiirus)
  5. P_total = 185 + 0 + 36 + 0 = 221W

Tõlgendus: Vaja 221W, et hoida 40 km/h kiirust TT asendis tasasel teel

JavaScript Rakendus:

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 }

Abifunktsioonid

Ühikute Teisendamise Tööriistad

JavaScript Rakendus:

// 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 joulesTo kJ(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)

Rakendamise Ressursid

Kõik valemid sellel lehel on tootmisvalmis ja valideeritud teaduskirjanduse ning reaalsete võimsusandmete põhjal. Kasuta neid kohandatud analüütikatööriistade loomiseks, kontrollimiseks või võimsuspõhise treeningu sügavama mõistmise jaoks.

💡 Parimad Praktikad

  • Valideeri sisendeid: Kontrolli mõistlikke võimsusvahemikke (0-2000W), positiivseid kestusi
  • Käsitle erijuhte: Nulliga jagamine, null/määramata andmed, puuduv FTP
  • Ümarda sobivalt: CTL/ATL/TSB 1 komakohani, TSS täisarvuni, W/kg 2 komakohani
  • Säilita täpsus: Hoia andmebaasis täielik täpsus, ümarda ainult kuvamiseks
  • Ajavööndid: Käsitle UTC vs kohalikku aega järjepidevalt mitmepäevase analüüsi puhul
  • Võimsusanduri kalibreerimine: Tuleta kasutajatele meelde nullpunkti kalibreerimist (zero-offset) enne sõite
  • FTP valideerimine: Märgi kahtlased FTP väärtused (>500W või <100W täiskasvanutel)
  • Testi põhjalikult: Kasuta teadaolevalt häid sõidufaile arvutuste kontrollimiseks