Pyöräilyn tehokaavat
Pyöräanalyysin mittareiden matemaattinen perusta
Käyttöönottoopas
Tällä sivulla on kopioi-liitä -kaavat ja vaiheittaiset laskentamenetelmät kaikille Bike Analytics -mittareille. Käytä näitä mukautettuihin toteutuksiin, todentamiseen tai tehopohjaisen koulutuksen syvempään ymmärtämiseen.
⚠️ Toteutusohjeet
- Kaikki tehoarvot watteina (W), aika sekunteina, ellei toisin mainita
- FTP ja CP ovat yksilökohtaisia kynnysarvoja – ei universaaleja arvoja
- Tarkista aina tulot kohtuullisilla alueilla (tyypillisesti 0-2000 W)
- Käsittele reunatapauksia (jako nollalla, negatiivinen potenssi)
- Tehotiedot vaativat 1 sekunnin tallennusvälin tarkkuuden vuoksi
Pyöräily Suorituskyvyn perustiedot
1. Harjoittelun stressipisteet (TSS)
Kaava:
Toiminut esimerkki:
Skenaario:2 tunnin ajo, NP = 235W, FTP = 250W
- Laske IF: IF = 235 / 250 = 0,94
- Kesto sekunteina: 2 tuntia × 3600 = 7200 sekuntia
- TSS = (7200 × 235 × 0,94) / (250 × 3600) × 100
- TSS = 1 590 720 / 900 000 × 100 =176.7 TSS
Tulkinta: Kova harjoitusajo (>150 TSS), odota 2–3 päivän palautumista
JavaScriptin toteutus:
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: 1772. Normalisoitu teho (NP)
Algoritmi (30 sekunnin liukuva keskiarvo):
Miksi neljäs voima?
Kvarttinen (4. potenssi) suhde heijastaa muuttuvien ponnistelujen epälineaarista fysiologista hintaa. Ajo, jossa on jännitteitä ja palautumia, maksaa enemmän energiaa kuin tasainen teho samalla keskiarvolla.
Esimerkki:
- Tasainen ajo: 200 W 1 tunnin ajan → NP = 200 W, keskiarvo = 200 W
- Muuttuva ajo: Vuorotteleva 300W/100W → Keskiarvo = 200W, NP = 225W
Sama keskimääräinen teho, mutta vaihtelevalla ajonopeudella on 12 % korkeampi NP ylijännitteiden fysiologisten kustannusten vuoksi
JavaScriptin toteutus:
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 watts3. Intensity Factor (IF)
Kaava:
Tulkinta-alueet:
| IF valikoima | Pyyntiponnistustaso | Esimerkkiharjoitus |
|---|---|---|
| < 0,75 | Palautuminen / Helppo | Aktiivinen palautusajo, vyöhyke 1-2 |
| 0,75 - 0,85 | Kestävyys | Pitkä tasainen matka, aerobinen pohja |
| 0,85 - 0,95 | Tempo | Sweet spot -harjoittelu, tempovälit |
| 0,95 - 1,05 | Kynnys | FTP intervallit, aika-ajoponnistus |
| 1,05 - 1,15 | VO₂max | 5 minuutin väliajat, kriteerikilpailu |
| > 1,15 | Anaerobinen | Lyhyet sprintit, hyökkäykset, MTB-purskeet |
Laskentaesimerkki:
Skenaario:NP = 235 W, FTP = 250 W
IF = 235 / 250 =0,94
Tulkinta: Korkeatempoinen / kynnyksen alapuolella oleva ponnistus, kestävä 2-3 tuntia
function calculateIF(normalizedPower, ftp) {
return (normalizedPower / ftp).toFixed(2);
}
// Example:
const if_value = calculateIF(235, 250);
// Returns: 0.944.Vaihtuvuusindeksi (VI)
Kaava:
Tulkinta tieteenalojen mukaan:
| Kuri | Tyypillinen VI | Merkitys |
|---|---|---|
| Tie TT / Tasainen ponnistus | 1,00 - 1,05 | Erittäin tasainen teho, optimaalinen tahdistus |
| Maantieajo | 1,05 - 1,10 | Joitakin jännitteitä, yleensä tasaisia |
| Kriteeri | 1,10 - 1,20 | Toistuvat kiihdytykset ja hyökkäykset |
| Maastopyörä XC | 1,15 - 1,30+ | Erittäin vaihtelevat, jatkuvat jännitteet |
Laskentaesimerkki:
Road Race:NP = 240 W, keskimääräinen teho = 230 W
VI = 240 / 230 =1,04(tasainen tahdistus)
MTB Race:NP = 285 W, keskimääräinen teho = 235 W
VI = 285 / 235 =1,21(erittäin vaihteleva, purskeet)
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.21Critical Power & W' (anaerobinen kapasiteetti)
5. Kriittinen teho (CP) - Lineaarinen malli
Kaava:
Laskelma useista yrityksistä:
Vaatii 2–4 maksimiponnistusta eri kestoisin (esim. 3, 5, 12, 20 minuuttia)
Esimerkkitiedot:
| Kesto | Teho (W) | Työ yhteensä (kJ) |
|---|---|---|
| 3 min (180s) | 400W | 72 kJ |
| 5 min (300 s) | 365W | 109,5 kJ |
| 12 min (720 s) | 310W | 223,2 kJ |
| 20 min (1200s) | 285W | 342 kJ |
Lineaarista regressiota käyttämällä (työ = CP × aika + W'):
- CP = 270 W(regressioviivan kaltevuus)
- W' = 18,5 kJ(y-leikkaus)
JavaScriptin toteutus:
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' Balance (W'bal) - Differentiaaliyhtälömalli
Kaavat:
W'exp(t) = ∫(P(t) - CP) dt
W'rec(t) = W' × (1 - e^(-t/τ))
ja ΔCP = (CP - P(t))
Tosimaailman esimerkki:
Pyöräilijän tiedot:CP = 270 W, W' = 18,5 kJ
Skenaario 1 - Kova hyökkäys:
- Rider nousee 400 W:iin 30 sekunniksi
- W'-kulut: (400 - 270) × 30 = 3 900 J = 3,9 kJ
- W'bal jäljellä: 18,5 - 3,9 =14,6 kJ
Skenaario 2 – Palautuminen:
- Hyökkäyksen jälkeen se laskee 200 W:iin (70 W alle CP:n) 2 minuutiksi
- ΔCP = 270 - 200 = 70 W
- τ = 546 × e^(-0,01 × 70) + 316 = 588 sekuntia
- Palautuminen 120 sekunnissa: 18,5 × (1 - e^(-120/588)) =3,5 kJ talteen
- Uusi W'bal: 14,6 + 3,5 =18,1 kJ
JavaScriptin toteutus:
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 timeSuorituskyvyn hallintakaavio (PMC) Pyöräilyä varten
7. CTL, ATL, TSB laskelmat
Kaavat (eksponentiaalisesti painotetut liukuvat keskiarvot):
Metrinen määritelmät:
- CTL (krooninen harjoituskuorma):42 päivän eksponentiaalisesti painotettu keskiarvo - edustaa kuntoa
- ATL (akuutti harjoituskuorma):7 päivän eksponentiaalisesti painotettu keskiarvo - edustaa väsymystä
- TSB (harjoittelun stressitasapaino):Muoto = Kunto - Väsymys
Työstetty esimerkki (7 päivän koulutusjakso):
| Päivä | TSS | CTL | ATL | TSB | Tila |
|---|---|---|---|---|---|
| ma | 100 | 75,0 | 80,0 | -5,0 | Koulutus |
| Ti | 50 | 74,4 | 75,7 | -1,3 | Takaisinperintä |
| ke | 120 | 75,5 | 82,0 | -6,5 | Kova koulutus |
| to | 0 | 73,7 | 70,3 | +3,4 | Lepopäivä |
| pe | 80 | 73,8 | 71,7 | +2,1 | Kohtalainen |
| la | 150 | 75,6 | 82,9 | -7,3 | Pitkä matka |
| Aurinko | 40 | 74,8 | 76,8 | -2,0 | Takaisinperintä |
TSB Tulkinta:
| TSB valikoima | Tila | Toimenpide |
|---|---|---|
| < -30 | Suuri riski | Ylikuntovaroitus - vähennä kuormitusta |
| -30 - -10 | Harjoittelu kovaa | Kuntoilun rakentaminen, palautumisen seuranta |
| -10 - +5 | Optimaalinen | Normaali harjoitusalue |
| +5 - +15 | Kilpailu valmiina | Huippumuoto - kilpailu tänä viikonloppuna |
| > +25 | Koulutuksen lopettaminen | Kunnon menetys - lisää kuormaa |
JavaScriptin toteutus:
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 dayTeho-paino- ja kiipeilymittarit
8.Tehon ja painon suhde
Kaava:
FTP W/kg Vertailuarvot:
| Taso | Uros W/kg | Naaras W/kg | Luokka |
|---|---|---|---|
| Virkistys | 2,5 - 3,5 | 2,0 - 3,0 | Kuntosali |
| Kilpailukykyinen | 3,5 - 4,5 | 3,0 - 4,0 | Cat 3-4, ikäluokan kilpailija |
| Edistynyt | 4,5 - 5,5 | 4,0 - 5,0 | Kissa 1-2, vahva amatööri |
| Elite Amatööri | 5,5 - 6,0 | 5,0 - 5,5 | Kansallinen taso |
| Ammattilainen | 6,0 - 7,0+ | 5,5 - 6,5+ | World Tour, Grand Tour GC |
Laskentaesimerkki:
Skenaario:Pyöräilijä, jossa FTP = 275W, paino = 70kg
W/kg = 275 / 70 =3,93 W/kg
Tulkinta: Kilpailukykyinen taso, kykenevä mäkisiin kilpailuihin
function calculateWattsPerKg(power, bodyMassKg) {
return (power / bodyMassKg).toFixed(2);
}
// Example:
const wpkg = calculateWattsPerKg(275, 70);
// Returns: 3.939. VAM (Velocità Ascensionale Media)
Kaava:
VAM-vertailuarvot:
| VAM (m/h) | Taso | Esimerkki |
|---|---|---|
| 600 - 900 | Virkistys | Klubin ratsastaja paikallisessa nousussa |
| 900 - 1200 | Kilpailukykyinen | Hyvä amatööri Alpe d'Huezissa |
| 1200 - 1500 | Elite Amatööri | Kansallisen tason kiipeilijä |
| 1500 - 1800 | Ammattilainen | World Tour kotimainen |
| > 1800 | Grand Tour -voittaja | Pogačar, Vingegaard avainkiipeilyissä |
Laskentaesimerkki:
Skenaario:Alpe d'Huez -kiipeily
- Korkeusnousu: 1100 metriä
- Aika: 55 minuuttia = 0,917 tuntia
- VAM = 1100 / 0,917 =1200 m/h
Tulkinta: Kilpailutason kiipeilysuoritus
function calculateVAM(elevationGainMeters, timeMinutes) {
const hours = timeMinutes / 60;
return Math.round(elevationGainMeters / hours);
}
// Example:
const vam = calculateVAM(1100, 55);
// Returns: 1200 m/h10. VAM to W/kg arvio
Kaava:
Laskentaesimerkki:
Skenaario:Kiipeä 8 %:n keskigradientilla, VAM = 1200 m/h
W/kg = 1200 / 100 / (8 + 3)
W/kg = 12 / 11 =4,36 W/kg
Ristitarkastus: 70 kg painavalla kuljettajalla → 305 W jatkuvaa tehoa nousussa
function estimateWkgFromVAM(vam, gradientPercent) {
return (vam / 100 / (gradientPercent + 3)).toFixed(2);
}
// Example:
const wkg = estimateWkgFromVAM(1200, 8);
// Returns: 4.36Aerodynaaminen tehoyhtälö
11. Kokonaistehotarve
Täydellinen kaava:
Komponenttikaavat:
P_aero = CdA × 0,5 × ρ × V³
P_painovoima = m × g × sin(θ) × V
P_rullaus = Crr × m × g × cos(θ) × V
P_kineettinen = m × a × V
Vakiot ja muuttujat:
- CdA= Vastuskerroin × etupinta-ala (m²)
- Tyypilliset maantiepyörän suojukset: 0,35-0,40 m²
- Pisarat: 0,32-0,37 m²
- TT-sijainti: 0,20-0,25 m²
- ρ= Ilman tiheys (1,225 kg/m³ merenpinnan tasolla, 15°C)
- V= Nopeus (m/s)
- m= Kokonaismassa (ajaja + pyörä, kg)
- g= Painovoima (9,81 m/s²)
- θ= Gradienttikulma (radiaaneja tai asteita muunnettu)
- Crr= Vierintävastuskerroin (~0,004 hyville maantierenkaille)
- a= Kiihtyvyys (m/s²)
Työstetty esimerkki (tasainen tie TT):
Skenaario:
- Nopeus: 40 km/h = 11,11 m/s
- CdA: 0,22 m² (hyvä TT-asento)
- Kokonaismassa: 75kg (ratsastaja) + 8kg (pyörä) = 83kg
- Tasainen tie (kaltevuus = 0°)
- Vakionopeus (kiihtyvyys = 0)
Laskenta:
- P_aero= 0,22 × 0,5 × 1,225 × 11,11³ =185W
- P_painovoima= 0W (tasainen tie)
- P_rolling= 0,004 × 83 × 9,81 × 11,11 =36W
- P_kineettinen= 0W (vakionopeus)
- P_yhteensä= 185 + 0 + 36 + 0 =221W
Tulkinta: Tarvitsee 221 W nopeuden ylläpitämiseen 40 km/h TT-asennossa tasaisella tiellä
JavaScriptin toteutus:
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 }Aputoiminnot
Yksikkömuunnosapuohjelmat
JavaScriptin toteutus:
// 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)Toteutusresurssit
Kaikki tällä sivulla olevat kaavat ovat tuotantovalmiita ja validoituja tieteellisen kirjallisuuden ja todellisten tehomittaritietojen perusteella. Käytä niitä mukautettuihin analytiikkatyökaluihin, todentamiseen tai tehopohjaisten harjoittelulaskelmien syvempään ymmärtämiseen.
💡 Parhaat käytännöt
- Vahvista syötteet:Tarkista kohtuulliset tehoalueet (0-2000W), positiiviset kestoajat
- Kahvan reunakotelot:Jako nollalla, nolla/määrittämätön data, puuttuu FTP
- Pyöristä asianmukaisesti:CTL/ATL/TSB 1 desimaalin tarkkuudella, TSS kokonaislukuina, W/kg 2 desimaalin tarkkuudella
- Tallennustarkkuus:Säilytä täysi tarkkuus tietokannassa, pyöreä vain näyttöä varten
- Aikavyöhykkeet:Käsittele UTC vs.paikallista aikaa johdonmukaisesti usean päivän analyysiä varten
- Tehomittarin kalibrointi:Muistuta käyttäjiä nolla-offsetista ennen ajoa
- FTP-vahvistus:Ilmoita epäilyttävät FTP-arvot (>500W tai <100W aikuisille)
- Testaa perusteellisesti:Käytä tunnettuja ajotiedostoja vahvistaaksesi laskelmat
