Wednesday, April 14, 2021

Speed vs power in Zwift

This may be of interest to a relatively small number of readers, but it seems worth documenting that the relationship between power and equilibrium flat speed in the cycling simulator Zwift can be quite accurately summarised via 

P =  1.86e-02 w.v - 5.37e-04 v^3 + 2.23e-05 w.v^3 + 1.33e-05 h.v^3

where v is the velocity in kph, w is the rider weight in kg, and h is the rider height in cm.

The linear term in v can be thought of as arising through rolling resistance (which also varies with w), with the three cubic terms due to air resistance. These cubic terms can be thought of as the dominant terms in a Taylor series expansion of a single term that looks like A.f(w,h).v^3 where f is a function of weight and height that modifies the resistance (eg though changing the cross sectional area). At first I was trying to work out what f was, but an important realisation that only came to me while doing this analysis is that I don't actually need to know its form as the values of w and h only deviate moderately from their mean values for the practical range of riders I'm interested in (ie ± 10% the most part, 20% at worst). Therefore this linearisation approach (with coefficients fitted through linear regression) is plenty good enough and I don't need any of my model-fitting tricks. More engineering than science but nevertheless useful!

To do the model fitting, I did a bunch of flying laps of the volcano circuit at constant power, with different physical parameters and varying power level each time. This route is fairly flat but not perfectly so, which means the average speed here will be a little bit lower than that achieved on truly flat ground, but probably typical of many flattish routes on Zwift such as Watopia's Waistband or Greater London Flat. I estimate the elevation/disequilibrium effect here to be around 0.5kph, so speeds achieved on Tempus Fugit may be about that much quicker than indicated here (or conversely, you'll hit a target pace with a bit less power than this formula suggests). Some of the riders in my data set are real, others imaginary. I've focussed mostly on women, first because I've been DS for my wife's team for a while, and also because through being a large reasonably fit man I can generate their racing power fairly comfortably for long enough to get a fix on their speeds. (Yes, I know there are software approaches to simulating the power. But it's something else to set up, and I don't really want to get into the world of power bots, you never know where it might lead...) Calculating the power needed for a large rider at high speed requires a bit of an extrapolation and may get less reliable. Bike is the Tron, I started out testing different bikes (to check on what zwiftinsider says) but the differences were too trivial to pursue. Specifically, the Canyon Aeroad 2021 with Zipp 808 wheels which I used to use a lot was just one second slower than the Tron. That's 0.1kph, equivalent to less than 2W.

The black lines in the plot below are the model predictions for each rider, with the crosses marking the data points that I used to fit the model. Each line has 3 data points except for the top one which is my own physics. If someone wants to do a flying lap of the volcano at 450W (using my physical parameters) I'd love to know the result :-) The rest are mostly based around a women's team with jules being the bottom line. Few cyclists of either gender lie outside the range of our parameters! The model-data residuals are about 1.5W on average (RMS error) which is basically the magnitude of measurement error on the speed which is only precise to 0.1kph. This level of precision is plenty good enough for practical use, it's difficult to hit a power target more closely than about 5W anyway.

A conclusion that may be drawn is that for a medium-sized cyclist riding around 42kph, an extra 1kg of weight requires 2.5W more power to maintain the same speed (or alternatively, 1kg less saves 2.5W of power). For an additional 1cm of height, it's around 1W. These numbers aren't far from what I'd estimated through experience, it's nice to have them confirmed in a more careful calculation.


jules said...

I am the bottom line! hurrah!

William M. Connolley said...

It seems like you didn't need to mention j was the bottom...

Tim Andrews said...

Hi James,

Are you on ZwiftPower? Loads of data on there. See for the volcano circuit forward (which is what I presume what you did?). It has a population average of:

Time: 06:06
Power: 252w
Weight: 75.6kg
Watts/kg: 3.3wkg
Speed: 40.1kmh

Which seems to fit, but you can filter by weight, power etc. or even plot the time versus w/kg. Though I guess you'd never know if they rode in a bunch or solo, which would make a very big difference. In fact you need to do your tests again with a TT bike rather than AeroRoad to ensure there was no drafting from anyone else on screen... ;-)


James Annan said...

Yes ZP is an interesting source for population-wide stats but as you say the draft issue is a big one. Just looking at TT events could work but even then temporal changes in power will affect the results. And I want the calculation calibrated for normal bikes (but no draft, as in the front rider of a TTT team).

I did all my runs solo by setting up a private meet-up that the other person didn't attend - I was the only bike on screen. Precisely for this reason :-)

Tim Andrews said...

Ah well done that’s a good control set up! ZP data probably more useful for climbing then, when speeds low enough to ignore draft. For example I used it recently to figure out how what w/kg to hold when aiming for a sub hour Alpe.

Simon said...

I was just fiddling around with my TTT spreadsheet and thinking that someone out there *must* have worked out the relationship between power and speed on the flat. And here it is! Many thanks.

Simon said...

For my TTT simulator, I want to compute speed (on the flats) given a specific target power so I really want the inverse of your equation. I think I can just use a couple of iterations of Newton's method with a starting v in the right ballpark (e.g. 40km/h for a TT), i.e. a couple of repetitions of:

v1 = v0 - (awv + (-b + cw + dh) v^3 - P) / (aq + 3(-b + cw + dh) v^2),

where a, b, c, and d are the 4 constants in your expression.

But a closed form expression would be even better and, given that your initial thought was that the power was a function of v^3, which would have a simple inverse, did you try the fit without that wv term? Any thoughts welcome. Thanks again!

James Annan said...

Thanks for comments. No direct inverse, though you could approximate quite well in various ways. If you are trying to give pull targets then just using 2.5W/kg and 1W/cm (as deviations from the team mean) is probably good enough really. The fit without the linear term is a lot worse.

I just put in the speed and adjust it until the pulls look about right for the team members (who have been vary a lot from week to week). Seems to work pretty well.

Simon said...

Thanks! I ended up just coding up a google sheets custom function to estimate the inverse. Three iterations of Newton's method is more than enough to get within 0.1 km/h. I've attached my function here in case it's of interest to anyone else!

const a = 1.86e-02;
const b = -5.37e-04;
const c = 2.23e-05;
const d = 1.33e-05;

function SPEEDTOPOWER(speed, weight, height) {
return a * weight * speed + (b + c * weight + d * height) * speed * speed * speed;

function POWERTOSPEED(power, weight, height) {
let speed = 40; // Initial guess - about right for TTT
const A = a * weight;
const B = b + c * weight + d * height;
// Use Newton's method to find a root of f = A * speed + B * speed^3 - P
for (i = 0; i < 3; ++i) {
speed = speed - (A * speed + B * speed * speed * speed - power) / (A + 3 * B * speed * speed)
return speed;