Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Power curve support Tacx Flow&Magic T2020 #153

Closed
jurgen-iflow opened this issue Nov 26, 2020 · 167 comments
Closed

Power curve support Tacx Flow&Magic T2020 #153

jurgen-iflow opened this issue Nov 26, 2020 · 167 comments
Labels
power curve Questions and issues regarding the power curve under investigation Being studied for implementation in next version

Comments

@jurgen-iflow
Copy link

hello Wouter , is it possible to have a correct powercurve for the Tacx Flow T2250 , the current powercurve is far off and i could not find a good way to adjust it to my Garmin vector 2 powermeter reading

What i noticed , see screenshot is that the calibration of my Flow motor give an error during initialization
"calibration stopped because of unexpected resistance value
tacxflow-fortiusant
by FortiusAnt

grt jurgen

@cyclingflow
Copy link

cyclingflow commented Nov 26, 2020

You have to switch off calibration (-n)

We are working on the power curve.
I have a fork, with adapted power curves for i-Flow and i-Magic
https://github.com/cyclingflow/FortiusANT/releases
You might want to try that.
Please, use the included .bat files, they will specify the correct command line parameters.

Discussion is in https://github.com/WouterJD/FortiusANT/issues/143

BTW. I have recently increased the tire resistance to prevent slipping.
(mine now has a calibration factor of 5 on the manual control unit)
so, the curves are calibrated a bit above the normal low settings of your flow.
Of course it depends on your tire pressure and knob setting.

@WouterJD
Copy link
Owner

@jurgen-iflow Welcome to the FortiusANT community


I'm always curious to know who I communicate with, where FortiusANT is used and what configuration is used.
Please tell me what brake and what head unit do you use, the bundle apparently=T2250?
Where are you from?


Thanks @cyclingflow; a Flow-compatible version will be available shortly.

Jurgen, I see you have a powermeter and that will be great to do some tests.
Will be back soon

@WouterJD WouterJD added power curve Questions and issues regarding the power curve under investigation Being studied for implementation in next version labels Nov 26, 2020
@WouterJD
Copy link
Owner

WouterJD commented Nov 26, 2020

@jurgen-iflow Please try the version in https://github.com/WouterJD/FortiusANT/tree/%23143-Powercurve-iMagic
The correct title for the branche would be "Magnetic brake"; but what's in a name.

@cyclingflow This version implements formula's instead of tables

@BikeBeppe64 Perhaps you can do a testride with the uploaded version.

See uploaded manual for description; also "FortiusANT - Powercurve.xlsm" has a tab for the Magnetic Brake.

@cyclingflow
Copy link

I hope @BikeBeppe64 will enjoy the experience!

And it is great to have automatic detection of the brake unit.

@WouterJD
I have some comments regarding your manual and implementation that i will put in another thread.

@WouterJD WouterJD changed the title Power curve support Tacx Flow T2020 Power curve support Tacx Flow&Magic T2020 Nov 29, 2020
@Mk2mark
Copy link

Mk2mark commented Nov 30, 2020

Thanks for you message. Yes I do have a power meter.

@jurgen-iflow
Copy link
Author

I'm always curious to know who I communicate with, where FortiusANT is used and what configuration is used.
Please tell me what brake and what head unit do you use, the bundle apparently=T2250?
Brake 1901 headunit 1932
Where are you from?
Netherlands ( near Eindhoven )

i will try the power curve-Imagic tonight

@WouterJD
Copy link
Owner

WouterJD commented Nov 30, 2020

@Mk2mark, @jurgen-iflow

... adjust it to my Garmin vector 2 powermeter reading ...
... Yes I do have a power meter ...

To know the relation between resistance and power, I would really appreciate it if you would execute the following test:

The test is performed as follows:

  • Start FortiusANT with the following command-line parameters: -a -g -d127 -r -m (autostart, gui, logfile, resistance, manual power)

  • FortiusANT is operated in manual mode (-m flag), modifying the target power from 10...4000 in 50 Watt steps (read next step!).

  • The power as selected is transferred directly to the trainer (Resistance = TargetPower) without intermediate formula. (The -r flag is created for this purpose). The assumption is that the allowed resistance for the i-Flow ranges from 1000…4000 and that is not Watts!

  • The data from FortiusANT is saved as json-file (-d127 flag, creating a full logfile).

  • Use your bicycle with power meter and Garmin Edge, registering speed and power (and cadence, heartrate). This data is available as FIT file and converted to TCX.

  • FortiusANT and Garmin Edge are started.

  • Initial TargetPower in FortiusANT is 100Watt (--> Resistance = 100)

  • Start cycling at 12km/hr.

  • Increase TargetPower on the headunit every few seconds until 4000 (or that your maximum power is reached). This will take 79 steps = less than 10 minutes.

  • Reduce TargetPower to 1000 (I think that is around the minimum resistance value, which we will see from the first test). Note that the head unit is sampled every 250ms, so you can press two times per second only! (It’s not as fast as a keyboard).

  • Redo the test at 24 and 36 km/hr.

  • Stop FortiusANT and Garmin Edge and save .log, .json and .fit files.

  • Respond to this post and attach .log .json and .fit

Would be very helpful

@Mk2mark
Copy link

Mk2mark commented Nov 30, 2020

Will try to do that tomorrow.
Do I need a newer version of the code?

Today on Zwift I was overtaken by J Wouter as approaching London Bridge - was that you?

@WouterJD
Copy link
Owner

WouterJD commented Nov 30, 2020

The version in the current branch is good to execute this test.

Mind to use the version in https://github.com/WouterJD/FortiusANT/tree/%23143-Powercurve-iMagic
The correct title for the branche would be "Magnetic brake"; but what's in a name.

Further developments can be done with described test-results, upon which the power curve will be based.
Succes!

No; that was not me. Currently either riding outside or Trainer Road for structured training. See you on strava

@jurgen-iflow
Copy link
Author

Hi , i got stucked on increasing Targetpower on the headunit , looks like my headunit is not responding only on "cancel"
as you can see i installed the "version3.9 with the parameters -a -g -d127 -r -m , but could not select targetpower ?
please guide me were to do that

image

@cyclingflow
Copy link

cyclingflow commented Nov 30, 2020

I dont see it. It does say 'manual power' but the power display suggests "grade mode".
Something is off.

Well may be. Just to be sure: did you use lowercase -m switch? case makes a difference

@cyclingflow
Copy link

cyclingflow commented Nov 30, 2020

I planned on commenting on some of the progress, but i came across an issue this afternoon that really puzzled me.
May be well well know by you guys.

1932 unit issue: wrong configuration.

The program was not working correctly at all, which i did not understand, until i remebered i switched 1932 head-units.
Luckely i wrote down the serial numbers given by the interface, so i could check.

What was really confusing:
It turns out, i got an used 1932 with an i-flow, that says 'fortius' on the back, and is working perfectly well with the flow.
Incidentally, i got an used 1932 with the Fortius motorbrake without powersupply that says 'VR-interface' on the back.

This one gave the wrong results. Speed was too low, and some resistance values also seemd off. Power was more off, than just the difference in speed could explain.

So apparently, you can setup these 1932 devices for any of the brakes, but you have to do so first. I presume through the original software. I'am not aware if i can do so through FortiusAnt.

Makes sense, because for example the motorbrake has a different roll-diameter, than the magnetic brake..

Just wanted to note that this may account for some of the users getting strange results.
Please fill me in, if i have missed something obvious.

@switchabl
Copy link
Contributor

@cyclingflow That is very strange. I have never seen anything to suggest that TTS configures the brake type in any way in the USB traffic. As far as I am aware, 1) the head unit detects the magnetic brake from the 50/60Hz input on pin 4 and 2) the software requests the brake serial/version and knows that a magnetic brake is connected if it gets all zeroes (the magnetic brake is completely analog and can not send a serial number). That being said, I only have a T1932 labelled "Fortius". It was included with an i-Flow bundle and works fine with either magnetic or motor brakes. Maybe they have different firmware versions? The head unit firmware version is sent over USB, but I am not sure if FortiusANT displays it.

@switchabl
Copy link
Contributor

I don't have my Flow unit here right now (haven't used it in years), so I can't do any measurements myself. But I was playing a bit with TTS and simulating the brake by feeding a 50Hz signal and a wheel speed signal from a function generator into the head unit. I was trying to reconstruct the power curves used by TTS, but the results are ... confusing. So I cannot share those (yet) without more tests without maybe having to retract something later.

But I did find some interesting bits of information:

  • Because I could control the wheel speed signal directly (and very accurately), I can confirm that the correct factor for the speed in km/h is indeed 289.75 (knowing that there are 4 pulses per revolution and assuming the spindle has a diameter of 29mm).
  • The bytes 36-37 (totalreverse: "average real load") and 38-39 ("current real load") appear to be identical in all cases with magnetic brake. My guess is that on the Fortius, rather than being some average, this is related to the flywheel. But I have not verified this yet.
  • The "load" values correspond approximately to the brake force in units of 0.01 N. It does not include include rolling resistance and the speed-dependence of the force. Those are calculated in software. I guess that some linearization is done using a look-up-table (probably the reason why there are discrete, irregularly spaced values only).
  • The target values and the force values do not live on the same scale:
    target_force
    So for example if you set the target to 1559 (one of the discrete values) you still get 1039. You would have to program something like 2145 to get 1559. This was already noted by @cyclingflow, but unless I am missing something, the current code in the iMagic branch does not take this into account.

@cyclingflow
Copy link

cyclingflow commented Nov 30, 2020

I thought it did, last time i looked. Have not looked at latest version perhaps.
@WouterJD was using part of my implementation/antifier using tables with these discrete values. Note that there is a difference between the scale of the values send, and returned.
(And just i minor note: it only changes these values to say 1559, if there is wheelspeed. Otherwise it appears to stay at 1039)

I can confirm that the correct factor for the speed in km/h is indeed 289.75

I agree. I have only used a different value for backwards compatability with antifiers tables. And changed my bike computer accordingly. Comparison with the T1682 would suggest the same.

It does not include include rolling resistance and the speed-dependence of the force. Those are calculated in software.

I think this is a crucial point. I have mathematical ideas for adding an additonal term to the model, and some possibly nice results. However, i'am not sure @wouter would like to go along a more complicated route, if the current models give reasonable results. I might be on my own there. NP.

All models can be expressed as a hierarchical series of of models, have a few more or less parameters. They are either all right or all wrong, conceptually. And they are also the same as the legacy approach. There are just some differences in accuracy, due to using more parameters/terms. Same goes for slight differences in estimation procedures. IF everything would perfect, the solutions would coincide. No new data will change these mathematical facts. Moreover, it is hard to conceive of measurement errors such that resampling would break the emerging patterns.

Adding a new term however, might be very relevant.
The big issue IMHO is, that the actual tire resistance gives hugely different results. For me, between sessions, but also between me and other users. It also makes it impossible to truly interpret any differences between users, because resistance is unknown.
We do need some calibration factor/procedure.

For example, the table i'm planning to provide to @WouterJD with, that includes all my calibration runs, is already outdated for my use, because i have increased tire resistance.

Therefor, for the immediate future, i'am working on getting the powerreadings out of the T1682. Tedious job. But it gets rid of any differences between sessions and users, due to tire resistance. Once you have set the unit to a particular calibration factor, readings are consistent, whether you deflate the tire or not, as long as the bikewheel is driving the trainer.
This will proceduce a table of speeds vs power, for all resistance levels.

We may acquire readings for more than one calibration level, and some hints how to setup you trainer and bike, such that once you have completed a run-off, we know what table to use, that can be reasonably reproduced by current models/formula's.
This should give users power estimates within the same range of accuracy as the non-usb trainers. Well, maybe :-)

I'am thinking of something more intricate, but that's for my fun.

@switchabl
Copy link
Contributor

I also have some conceptual thoughts that can maybe help clear some things up. From what I can see, this is the model that is currently being considered:

if Resistance < 1819: Factor = Factor - (1819 - Resistance) / 15
return int( ( (SpeedKmh / Factor) + (1 / Offset) ) * Resistance)

There are several reasons to believe that, even if you manage to fit this reasonably well to a limited data set, it may not generalize well to different speeds and other people's trainers.

  • The "1 / Offset" term is troubling because it necessarily gives non-zero power at zero speed; and potentially negative power at low speeds. I also can't come up with a sensible physical interpretation.
  • On the other hand, what is missing is a term that could account for the rolling resistance properly. This will be a main source of variability between trainers and certainly between sessions. In fact this may be a reason why the piecewise first line is needed in the first place: in the lower resistance ranges, the relative contribution of the rolling resistance is greater. If the rolling resistance is included properly, this could possibly be dropped.

If I wanted to build a model for this, I would start from the basic physics: we can express the power in terms of the wheel speed and the various forces acting on the wheel

power = speed * (brake force + rolling resistance + flywheel force)

(The flywheel force is non-zero only when accelerating and deccelerating. It should eventually be included, but ignore for now.)

The rolling resistance is usually assumed to be independent of speed, but it is highly dependent on the tyre used, the tyre pressure and unfortunately temperature (both through the tyre material and because the pressure increases when it gets hot). Every wheel-on smart trainer I am aware of uses some form of run-down calibration to calculate this. A typical value might be ~2.5N, but this can vary a lot.

The brake force is where it gets complicated. Eddy current brakes are notoriously hard to model, in particular across large speed ranges. So some sort of approximation is needed. The crudest possible one would be to assume that it is constant for each resistance setting. This seems to be what TTS does for higher speeds:

power (W) = speed (km/h) / 3.6 * (raw force (bytes 38-39) / 100 + rolling resistance (in N))

I am not entirely sure what TTS does for low speeds. It looks like it could come from a calibration table.

For low speeds, it is known that the brake force grows linearly with speed (-> power grows quadratically). Potential models to try that include this effect:

  • piece-wise linear with two parts: one below ~10km/h that grows linearly and then a ~constant part
  • something that interpolates between a linear growth and the 1/speed dependency that eventually happens at very high speeds (but we may not ever reach this), as suggested by Wouterse (https://doi.org/10.1049/IP-B.1991.0019 ; sorry about the pay-wall, but the paper itself is probably not too helpful anyway)
F = F_e * 2 / (v / v_k + v_k / v)

With F_e dependent on bytes 38-39 and a parameter v_k.

  • for us something that interpolates between linear and constant may be better:
F = F_e * 2 / (1 + v_k / v)

I would love to experiment with this to see what works, but I would need the data for this. I have looked in the other issue and @cyclingflow seems to have done a lot of work there, but I didn't find any raw data (maybe I missed something?). It would be good to have not only power readings for all the resistance settings, but also at least some with a detailed set of different speeds.

@switchabl
Copy link
Contributor

switchabl commented Nov 30, 2020

Therefor, for the immediate future, i'am working on getting the powerreadings out of the T1682. Tedious job. But it gets rid of any differences between sessions and users, due to tire resistance. Once you have set the unit to a particular calibration factor, readings are consistent, whether you deflate the tire or not, as long as the bikewheel is driving the trainer.
This will proceduce a table of speeds vs power, for all resistance levels.

Yes, this is what I tried to do with TTS4. It's less tedious because you can just automate it. I have collected a relatively large dataset, but some it looks quite messy, so either something went wrong or the Tacx implementation is just weird. I would not be totally surprised if it is, but in that case it may be less useful than we hope.

I should also stress that I am not in favour of introducing many new parameters and look-up-tables (even if it does turn out Tacx did). That will work perfectly for exactly one session. I am interested in a model that is as simple as possible (but no simpler) and allows for a single parameter run-down calibration to account for tyre pressure etc. so it will work reasonably well for everyone.

@Mk2mark
Copy link

Mk2mark commented Dec 1, 2020

  • Start FortiusANT with the following command-line parameters: -a -g -d127 -r -m (autostart, gui, logfile, resistance, manual power)
  • FortiusANT is operated in manual mode (-m flag), modifying the target power from 10...4000 in 50 Watt steps (read next step!).
  • The power as selected is transferred directly to the trainer (Resistance = TargetPower) without intermediate formula. (The -r flag is created for this purpose). The assumption is that the allowed resistance for the i-Flow ranges from 1000…4000 and that is not Watts!
  • Initial TargetPower in FortiusANT is 100Watt (--> Resistance = 100)

When i do this it always starts up at 2% grade and the headhunt up/down has no effect. The readout gives back power as pedalled.
I have tried various flag settings (-m / -M / -n) and they all behave exactly the same.

@WouterJD
Copy link
Owner

WouterJD commented Dec 1, 2020

@Mk2mark please provide logfile, so I can check.
Also mind that there are no CTP's (Zwift, Rouvy, Trainer Road) active; they might send commands.

@WouterJD
Copy link
Owner

WouterJD commented Dec 1, 2020

but could not select targetpower

Use the headunit: UP/DOWN buttons

@WouterJD
Copy link
Owner

WouterJD commented Dec 1, 2020

All; thanks for the enthusiastic participation in this thread. I am convinced we will get to a clear implementation.
I'm reading all posts and will do my best to integrate.

Some points from my side:

  • Ignore the formula for the T1901/T1932 - it's not good. I should not have implemented that without test-results.
  • Who can explain why there are 14 distinct resistance values? Is that also true for the T1902 (legacy) headunit?
  • Let's create a measured power curve first: what power is required for the TargetResistance (at some speed)?

@Mk2mark
Copy link

Mk2mark commented Dec 1, 2020

Log files attached. There is no CTP connected.
FortiusANT.2020-12-01 09-59-30.log
FortiusAntGUI.2020-12-01 09-59-31.log
cannot attach json file.

@WouterJD
Copy link
Owner

WouterJD commented Dec 1, 2020

The head unit firmware version is sent over USB, but I am not sure if FortiusANT displays it.

Since recent, I detect motor brake version and display it on console and in the logfile.

@switchabl
Copy link
Contributor

switchabl commented Dec 1, 2020

* Who can explain why there are 14 distinct resistance values? Is that also true for the T1902 (legacy) headunit?

To remove any doubt: it sends only 14 different values to the brake too, it is not just what it reports back. I checked with an oscilloscope. This means we really only need to test 14 different settings when collecting data and nothing in between!
Why? We will never be sure. Technically the brake itself could do anything in between. My guess: the head unit has a calibration table. It uses the closest resistance where it knows the calibrated force value to return. If they did this well, it could make our work a bit easier (because what we get is already somewhat calibrated). If not: big mess...

I don't have a T1902. But from the curve in the manual it seems to change continuously? So, no? Maybe I can load the T1902 firmware onto my old T1942 and test with that.

* Let's create a measured power curve first: what power is required for the TargetResistance (at some speed)?

Yes, I think we can all agree on this. The phsyics can give us a starting point, suggest some sensible things to try (and reject bad ones). But without data, there is nothing more I can do right now either.

@switchabl
Copy link
Contributor

A couple of notes on the test protocol:

  • There really needs to be a 5-10 minutes warm-up at the start. This is really important. Otherwise tyres will warm up during the test and the power will drift.
  • The test can be made faster by going through the relevant values only (already suggested earlier by @cyclingflow I think). Start with a resistance of 1885, increase by 130 each time, last one is 3705. That's 15 because the middle one is there twice, but keeps it simple.
  • Include one spin-down from 35-40km/h to 0 at lowest resistance setting. That is very little effort, but may help us a lot with comparing different datasets later.
  • More speed values would be nice (at least for a few select resistance settings). But maybe we do this later.

@WouterJD
Copy link
Owner

WouterJD commented Dec 9, 2020

Yes, sorry, I'll try to make my thoughts more clear:

  • I think the default should be: we try to simulate the slope as requested, no factors, shifts or anything. I think we are in agreement here? If you buy a Vortex Smart and send 5% it gives you 5% and if you send 20% it can't do that, it just does as much as it can. But no adjustments.
  • Normally it should be the job of the CTP to deal with this. Zwift has a setting for that and so for Zwift this default is just fine.
  • But this is not a great experience with a magnetic brake if the CTP does not have this (like Rouvy apparently?), so for those users we allow them to apply this in FortiusANT instead.
  • The question is how exactly? After working it through more carefully, I think a good way is to use the same algorithm Zwift does, because it makes sense physically and it seems to work for a lot of people.
if antSlope > 0:
    targetSlope = slopeFactor * antSlope
else:
    targetSlope = slopeFactor * downhillFactor * antSlope

They scale down the slope for uphill by some factor, to fit a larger range of gradients.
They reduce the slope for downhill some more, because brakes have more limited range in downhill (even motor brakes). This is often not mentioned when people talk about Zwift trainer resistance, but it is there and it makes sense.
So code is correct, I should have explained more.

  • By default we leave slopeFactor = downhillFactor = 1
  • For Rouvy etc users, they can set slopeFactor = 0.5, downhillFactor = 0.5 then they get the same feeling someone would get in Zwift with default settings

Advantage is also it is very simple to implement: code can be the same for all brakes (because with default values doesn't change anything). The current "uphill" option is also included automatically. Just set downhillFactor = 0.

OK - This is what I will implement. Give me some time.

@WouterJD
Copy link
Owner

WouterJD commented Dec 9, 2020

Ok, I did a new fit using all three datasets combined (with equal weight and separate rolling resistance parameters).

Thanks for detailed investigation.
My impression is that this will nicely fit the measurements we now have; not necessarily true for other datafiles though.
I'm happy to implement these factors; but let's decide then on it and keep them.


For documentation purpose - and to understand what we're doing:
in Speed * (ScaleFactor * Resistance * Speed / (Speed + CriticalSpeed) + RollingResistance)

the part Speed * (ScalingFactor * Resistance) is the basis of the formula Power = Speed * Torque * constant
the addition + RollingResistance is the addition for the basic resistance when the magnetic brake is off

could you please explain in human language what the correction (Speed / (Speed + CriticalSpeed)) means?
If I understand right, at low speed [2.5 / (2.5 + 4.85) = 0.34] the resistance is relatively lower than and at high speed [10 / (10 + 4.85) = 0,673]. What should I think of this term "CriticalSpeed"; other than an arbitrarily chosen point?

Thanks for taking time to explain.

@switchabl
Copy link
Contributor

switchabl commented Dec 9, 2020

Sure, I'll try to explain in (mostly) words:

  • The basic formula is Power = Speed * Force (this is just basic pysics, you might even say it is just the definition of power)
  • We assume the Force = Brake force + Rolling resistance force, i.e. the force on the wheel has two parts
  1. The braking force due to the magnetic brake: this depends on the resistance setting and the speed
  2. The rolling resistance of the tire, due to the tire deforming continuously as it turns: this would be there even if we removed the magnets in the brake and turned it off. It is largely independent of speed, but can vary a lot with different tire material, size and pressure and the knob setting on the trainer. It is different for everyone and may be different today than it is tomorrow if you forget to pump up your tire.
  • We model the braking force itself as Brake force = ScalingFactor * Resistance value * (Speed / (Speed + Critical Speed)
  1. The ScalingFactor just translates the resistance value from the head unit into units of force (unit N = Newton)
  2. The brake cannot deliver the same braking force at all speeds. We assume that at as you pedal faster, it increases linearly at first and eventually reaches a constant value (this is an approximation). That is what the factor Speed / (Speed + CriticalSpeed) does. The CriticalSpeed determines where the (gradual) change from linear force to constant force happens. For speeds significantly higher than the critical speed, the factor becomes = 1, so at high speeds the brake force is just ScalingFactor * Resistance value.
    These two parameters depend on the geometry of the eddy current brake, the strength and positioning of the magnets, the electric current in the coils, the head unit firmware, and so on. We assume they are fixed and more or less the same for all brakes.

Note that this is all formulated in terms of "force" (and speed etc). You could also write it in terms of "torque" and "angular velocity". That would be completely equivalent but more complicated in this case, so I don't do that.

I hope this is reasonably clear, if not please let me know. Thanks for your patience with the more technical stuff! I think it is a very good thing that you are making the extra effort and document it properly.

@WouterJD
Copy link
Owner

WouterJD commented Dec 9, 2020

OK ... achievements today for "Fortius Antifier v3.9.e #153"

-G factor/factorDH implemented; default = 1/1; recommended for Rouvy = -G2
new constants for ScaleFactor = 0.0149, CriticalSpeed = 4.85, RollingResistance remains15
manual updated
FortiusAnt.exe
This is the final version; please test. If no issues found I will merge this week.

@switchabl thanks for quick reaction; did update excel but not py :-)

Repository owner deleted a comment from switchabl Dec 9, 2020
WouterJD pushed a commit that referenced this issue Dec 9, 2020
WouterJD pushed a commit that referenced this issue Dec 9, 2020
@switchabl
Copy link
Contributor

For what it's worth, looks good to me!

If I am allowed to nit-pick, it probably makes sense to allow float for the grade/downhill factor. For a Fortius (or if you don't ride steep hills) for example, something like G1.5 might make sense. Or someone might decide 2 is not quite enough. But 3 is already quite extreme! Anyway, I think this is not particularly urgent, so maybe we just keep it in mind for the next version.

@WouterJD
Copy link
Owner

I will change to float to avoid future changes.


To avoid decimals I decided to use a divider instead of a multiplier:

  • -G 2 for Grade = antGrade / 2 instead of -G 0.5 for Grade = antGrade * 0.5.
  • -G 2/2 for Grade = antGrade / 2 / 2 (downhill) instead of -G 0.5/0.5 for Grade = antGrade * 0.5 * 0.5 (downhill).

Please react: what do you prefer: -G 2/2 or -G 0.5/0.5

@switchabl
Copy link
Contributor

Ah, I see. I have no real strong feelings about this, but would probably prefer multiplier. The most useful range is probably 0.4-1.0 and that feels more intuitive to me than 1/1.0-1/2.5. But maybe just in percent then? So -G 50/50? No decimal points, plenty of fine-adjustment and added bonus -G 100/0 "no downhill mode" (deprecate --uphill eventually?) and -G 0/0 "no hills, feeling lazy mode". Does that make sense?

@Mk2mark
Copy link

Mk2mark commented Dec 10, 2020

Just did a Zwift ride in standard (slope) mode and with no flags set.. Immediate reaction is massively better accuracy and feel. Will try ERG mode tomorrow.
By observation (not accurate measurement) Power about right at 80W gradually diverges to overread by 10% at 200w then reduces to about right at 300W and 10% under at 450W. But thats not real data - just an observation.
If we can make that better by setting appropriate flags as you are discussing that will be a really good solution.
Overall though I would say we have achieved satisfactory usability already.

@WouterJD
Copy link
Owner

@Mk2mark great news.
Note that

  • the -c RollingResistance flag will (may) improve accuracy for you (11.6 suggested here)
  • the -G flag will not affect accuracy but the effective range (in GradeMode)

@WouterJD
Copy link
Owner

Ah, I see. I have no real strong feelings about this, but would probably prefer multiplier. The most useful range is probably 0.4-1.0 and that feels more intuitive to me than 1/1.0-1/2.5. But maybe just in percent then? So -G 50/50? No decimal points, plenty of fine-adjustment and added bonus -G 100/0 "no downhill mode" (deprecate --uphill eventually?) and -G 0/0 "no hills, feeling lazy mode". Does that make sense?

I have been looking at deprecation of -u so that we also simplify and not only complicate the command line

Others please react!
Define percentage (I agree)?
After that I publish I will not change units and/or divider/multiplier anymore to avoid confusion.

So current suggestion: defined integer percentage as a multiplier.

@WouterJD
Copy link
Owner

Wauw. We exchanged more than 228 messages in #143 and #153 to achieve the FortiusAnt 3.9 version with the changes as described on the wiki. I like the implementation as is realized now; it did not rework FortiusAnt but amended it. Thanks all for cooperation so far.
Fascinating to do a git compare and see how few code changes were required after all to reach this point.

@Mk2mark
Copy link

Mk2mark commented Dec 10, 2020

👍Shows you had the structure right to start with - just needed a bit more real world data to tweak it properly. Well done.

@switchabl
Copy link
Contributor

👍 Some things remain to be done (clean-up and share my code for fitting the model, rolling resistance calibration, port things over to T1902), but that is for another day. I need a break from this brake!

Also consider this: I can hopefully finish the Genius support over the weekend. And the Bushido should be easy after that (it is almost the same). So this was probably the last really tough problem we needed to solve to get all the legacy Tacx trainers working!

@WouterJD
Copy link
Owner

port things over to T1902

It already popped-up in my mind; there is one dataset (see manual) and that could be a basis to fit the formula.

I need a break from this brake!

Absolutely!

And if you like too exchange some christmas wishes; ping me on Strava or Messenger; after all this hard work would be nice to meet&greet.

@BikeBeppe64
Copy link

BikeBeppe64 commented Dec 10, 2020

Hi Group, just to say, as first impression, it's all over estimated with 3.9e
I tested as for the last route biked and:

Slopes
From -2/0% +5% w
From 0/+2% +10%w
From +2/+10% +25%w
From 10% to ... +10/15%w
Anyway untill 0% or negative slopes watts are acceptable, over that slopes are not anceptable in a Rouvy ride, from my point of view because you joke with friends.
I prefer 3.9d version is more real in a ride/race and in peace with yourself

@switchabl
Copy link
Contributor

@BikeBeppe64 There is a command line parameter (-c) to change the calibration value. Start with -c 15 (the default) and try to adjust it down a bit. If it was exactly right for you in 3.9d that was sheer luck. Everyone's value will be different depending on tire pressure and knob setting and so on. Eventually there will be an automated calibration routine I guess, but for now if you want better accuracy you have to tune it by hand.

@WouterJD
Copy link
Owner

from my point of view because you joke with friends.

Good idea! Ride with -c20 and amaze your friends

@SwitchMcBlade
Copy link

I've been following the thread with interest and as it seemed like you were nearing the end I downloaded this branch 3.9e version to try it out with Zwift.

I don't have a power meter to be sure if it is accurate, but TBH that doesn't bother me as much as being repeatable so I can at least directly compare myself from ride to ride. Previously even a few % change up and down I was having to fiddle with the virtual gearbox to try and get the resistance in an area that I can actually put power down. So I could never be sure from ride to ride if I'd gone up or down the same amount on the virtual gearbox at the same point in the ride.

The new version is so much better, at no point did I feel the need to touch the virtual gearbox. The resistance changes felt natural and I could happily feel like I could manage the resistance changes using the bike gears alone. I'm definitely happy with the experience of installing and riding without worrying about flags or anything else.

Thank you so much to everyone who worked in any way for this improvement, you've transformed my old Flow back into a useful trainer from an ornament in the garage.

@BikeBeppe64
Copy link

@WouterJD @switchabl @cyclingflow and all of you, thanks indeed for your time & Job done for free, I do appreciate it

@WouterJD
Copy link
Owner

Thank you so much to everyone who worked in any way for this improvement, you've transformed my old Flow back into a useful trainer from an ornament in the garage.

Thanks for evaluation; this is what it's all about!
(And yes, we sure liked the theory and formula's to get this far)

@Mk2mark
Copy link

Mk2mark commented Dec 11, 2020

Just to add to the general mood of positivity, and following my successful Zwift Slope mode ride yesterday:-
Today I created a custom workout (ERG mode) testing increasing power levels from 80-450W.
Zwift was driven entirely from FortiusAnt with "-c11.6" set as recommended - power, cadence, speed etc.
I connected bike sensors to Garmin only.

Firstly the Power output followed the target really well - significantly better than it used to with TTS4 - GREAT RESULT.
The power as measured by Garmin was also close - really good up to about 270W then it started to flatline until I realised that since 200w I had been using a constant gear & cadence and had reached the limit of the brake at that speed. I was surprised at how quickly I hit this limitation of the hardware, so worth keeping in mind that the T1901 brake needs high wheel speed to get the higher power outputs.

Once I upped the wheel speed the power then tracked ok - started to underread from 410W as opposed to over yesterday so I may need to tweak the -c flag a bit. However, in my practical 'working' range of 150-350W it was really good.

I am a very happy user. Thanks so much everyone for what you have achieved.

@WouterJD
Copy link
Owner

Thanks all for the positive feedback

@WouterJD
Copy link
Owner

Version 4.0 released :-)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
power curve Questions and issues regarding the power curve under investigation Being studied for implementation in next version
Projects
None yet
Development

No branches or pull requests

8 participants