WouterJD / FortiusANT

FortiusANT enables a pre-smart Tacx trainer (usb- or ANT-connected) to communicate with TrainerRoad, Rouvy or Zwift through ANT or Bluetooth LE.
GNU General Public License v3.0
153 stars 78 forks source link

Hi Guys! Golden Cheetah and c++ #171

Closed WouterJD closed 3 years ago

WouterJD commented 3 years ago

Hi Guys!

The world contains a disaster of old obsolete tacx trainers. I don't own a tacx trainer so can't debug or investigate actual issues, but I wouldn't mind if these things became un-obsolete. I've been trying to get Mick up and running in golden cheetah slope mode and from what I can tell the stuff in golden cheetah isn't working, it appears from Mick's data that the tacx interface's built in 'slope mode' doesn't work like golden cheetah (or fec) expects.

Micky pointed me at your manual and I was pleasantly surprised. You guys noticed some serious limitations of the fortius and have a bunch of cool mitigations.

It seems like you are always running the devices in ergo mode, driving the brake yourselves, so I tried that in golden cheetah too.

https://github.com/GoldenCheetah/GoldenCheetah/pull/3725

The change sends a 'resistanceWatts' hint whenever a controller is given a gradient. Since its fully parameterized by the physics it should be accurate estimate of watts needed to maintain current (virtual riding) state.

Because I don't have a tacx trainer I can't really test any of this, and there are too many devices to count - I'd like to know how to best adapt your technology into golden cheetah. Of course it would be possible to ask people to get ant dongles and go the fec route, but seems absurd when gc could just set the load directly.

You guys appear to be the current public authority on how to drive all these janky old trainers. What do you think is the best way for gc to utilize your stuff? Is it possible you will ever create a c++ interface to the fortius devices that avoids the ANT stuff?

Thanks!

Originally posted by @ericchristoffersen in https://github.com/WouterJD/FortiusANT/issues/168#issuecomment-748327476

WouterJD commented 3 years ago

you are always running the devices in ergo mode

That's not exactly the case (or I do not know what you mean) ERGmode = fixed Target power regardless cadence ==> resistance varies. GradeMode = fixed resistance ==> required power increases with speed

When I receive TargetPower or TargetGrade it's always translated into a resistance; the only parameter that can be sent to a USB Trainer

WouterJD commented 3 years ago

that avoids the ANT stuff

People want to Zwift/Rouvy/Trainer Road and those CTP's talk wireless (ANT or Bluetooth).

What would your usecase for C++ be?

WouterJD commented 3 years ago

ever create a c++ interface

First reaction: Unlikely... But that's what I thought when the community asked for...well all these other fun-options. So why not.

Two questions you could help with:

WouterJD commented 3 years ago

trying to get Mick...

Great, who is Mick (edit: @mickyduck55 ๐Ÿ˜‰) and ... Tell some more about yourself if you like. Welcome to the FortiusANT community anyway๐Ÿ‘


I'm always curious to know who I communicate with, where FortiusANT is used and what configuration is used (non in your case๐Ÿค”)

WouterJD commented 3 years ago

I wouldn't mind if these things became un-obsolete

We do our best. And since new trainers are sold out; we hope Tacx won't be offended.

If you can help - be our guest

ericchristoffersen commented 3 years ago

you are always running the devices in ergo mode

That's not exactly the case (or I do not know what you mean) ERGmode = fixed Target power regardless cadence ==> resistance varies. GradeMode = fixed resistance ==> required power increases with speed

When I receive TargetPower or TargetGrade it's always translated into a resistance; the only parameter that can be sent to a USB Trainer

Right I misspoke. You're controlling the brake level in slope mode.

Use case for c++:

I totally understand that its super important to enable every app to support these old devices. Is much more practical than trying to convince everyone in the world, now and forever, to add good fortius support.

But... the golden cheetah code is open source and c++ and already speaks directly to fortius. What is needed is a way to express 'good semantics' to the fortius from gc. AKA: Fix the bugs in how gc talks to fortius.

You guys have investigated the problem and all the translation and look like you are making great progress.

For example here is the gc fortius code that creates the 'load' command. In this snippet the 'load' variable means watts:

{
    //qDebug() << "send load " << load;

    qToLittleEndian<int16_t>((int16_t)(13 * load), &ERGO_Command[4]);
    ERGO_Command[6] = pedalSensor;

    qToLittleEndian<int16_t>((int16_t)(130 * brakeCalibrationFactor + 1040), &ERGO_Command[10]);

    retCode = rawWrite(ERGO_Command, 12);
}

I don't even know if that '*13' is reasonable.

The slope code side of this, which appears busted is:

else if (mode == FT_SSMODE)
{
    qToLittleEndian<int16_t>((int16_t)(650 * gradient), &SLOPE_Command[4]);
    SLOPE_Command[6] = pedalSensor;
    SLOPE_Command[9] = (unsigned int)weight;

    qToLittleEndian<int16_t>((int16_t)(130 * brakeCalibrationFactor + 1040), &SLOPE_Command[10]);

    retCode = rawWrite(SLOPE_Command, 12);
    // qDebug() << "Send Gradient " << gradient << ", Weight " << weight << ", Command " << QByteArray((const char *)SLOPE_Command, 12).toHex(':');
}

I didn't see any mention of slope mode in your code. Do you know its history? Did it ever work? ๐Ÿ‘

ericchristoffersen commented 3 years ago

trying to get Mick...

Great, who is Mick and ... Tell some more about yourself if you like. Welcome to the FortiusANT community anyway๐Ÿ‘

I'm always curious to know who I communicate with, where FortiusANT is used and what configuration is used (non in your case๐Ÿค”)

Sorry! I'm ERIC!! I'm some dog on the internet. Mick is some guy on some other FA issue thread that was having trouble getting GC to work with FA.

I've got a kickr. I spend time to improve golden cheetah to help it do what I want.

For fun I implemented the virtual power on gc, modelled trainer inertia, bicycle physics, interpolation, etc.

ericchristoffersen commented 3 years ago

Here's the thread with Mick:

https://github.com/WouterJD/FortiusANT/issues/168

WouterJD commented 3 years ago

Yeah I figured that out! Hi Eric & Mick!๐Ÿ‘

WouterJD commented 3 years ago

I think you can find the answers in usbTrainer.py. I tried to make the interface as readable as possible.

Power2Resistance() Grade2Power() do the math the USB interface is defined using TotalReverse' specs

WouterJD commented 3 years ago

SLOPE_Command is not something i recall from TotalReverse's specs; reason why it's not used.

Mickyduck55 commented 3 years ago

HI Wouter Im Mickyduck55.....Mick Drake hence the "duck" long retired TT cyclist I have a Fortrius with T1932 head unit and a steerer frame. a first generation Look Carbon with aluminium lugs on the trainer with Camapg groupset. I still have a working copy of TTS4 along with all the required backup files to keep it alive but like the data bits of GC. Also have a Concept 2 Rowing machine so log that in gc as well but the data is a bit ridiculous Sped = 13-14 kph on a good day I sent a link to my site so you can see some of my cycling bits Lands end to John o Groats on a small wheel folder (1000 miles) and been up ventoux on the same bike I also have a tandem. My partner has an iMagic which she loves but she is not interested in data at all !!! www.mickdrake.com Used your calibration tonight thought it was never going to stop..... Brilliant thanks

On Fri, 18 Dec 2020 at 22:41, Wouter Dubbeldam notifications@github.com wrote:

SLOPE_Command is not something i recall from TotalReverse's specs; reason why it's not used.

โ€” You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/WouterJD/FortiusANT/issues/171#issuecomment-748353977, or unsubscribe https://github.com/notifications/unsubscribe-auth/AFLPPTLCSBNKVAWOBR5WZR3SVPLADANCNFSM4VBW73QA .

mattipee commented 3 years ago

Hi, @ericchristoffersen @Mickyduck55 !

I'd be happy to contribute to GC's Fortius backend. I've got a Fortius and also a GC fork (I added ability to import Strava Routes as workouts).

As @WouterJD said, it's all in the Power2Resistance() etc functions. There are a few constants we define to convert to and from trainer's units for force and speed, but otherwise it's all just straightforward maths.

switchabl commented 3 years ago

@ericchristoffersen As far as we know, there are three modes, determined by byte 8: STOP (0x00), FORCE (0x02) and CALIBRATE (0x03). There is neither a power nor a slope mode, you have to implement this yourself.

Both your slope command and your ergo command set FORCE mode. The target (bytes 4-5) specifies a force, not a power (a value of 137 is ~ 1N). So I don't think you ergo mode is implemented properly either.

I have thought of writing up a more detailed specification of all the legacy Tacx trainers in one place. Almost everything is already reverse-engineered, you just have to piece it together. Most of what you need for the Fortius can be found here: https://github.com/totalreverse/ttyT1941/wiki#newer-usb-1264-bytes-protocol

Btw I am a happy GC user myself, although I only use the analysis portion.

ericchristoffersen commented 3 years ago

Hi, @ericchristoffersen @Mickyduck55 !

I'd be happy to contribute to GC's Fortius backend. I've got a Fortius and also a GC fork (I added ability to import Strava Routes as workouts).

As @WouterJD said, it's all in the Power2Resistance() etc functions. There are a few constants we define to convert to and from trainer's units for force and speed, but otherwise it's all just straightforward maths.

Hi Mattipee,

I saw your github history and hoped you would reply. I happen to be an old timey compiler back end guy.

I just checked power2resistance, love that there's example quotes of what gc does. I think it'd be great to get this working right in gc. I mean, its ok to ask everyone to buy an ant+ dongle but as a wireless kickr user I sure wish I had a wired connection...

The pr I just made for gc computes the load based on current sim state. That should work great but looks like the gc formula to convert load to brake is wrong.

The core that we need seems to be:

            # ref https://github.com/WouterJD/FortiusANT/wiki/Power-calibrated-with-power-meter-(iMagic)
            rtn = (self.TargetPower - 2.2 * self.SpeedKmh) / \
                    (self.SpeedKmh * self.SpeedKmh / 648 + \
                    self.SpeedKmh / 5411 + 0.1058)

Great research to generate that expression.

What is really needed is someone with one of these tacx devices to actually validate the changes, even better if you can make them too! :)

GC has no calibration implemented for fortius. The framework is there to run a spindown but nobody has typed it.

switchabl commented 3 years ago

@ericchristoffersen That is for the iMagic (magnetic brake) with the old T1902 head-unit , the relevant part for the Fortius is easier:

rtn = self.TargetPower * self.PowerResistanceFactor / self.WheelSpeed

I think you are basically on the right track and if you fix power->load/force conversion it should basically work (minus calibration). Be careful though if your target power calculation includes inertia effects (i.e. acceleration/decceleration). The Fortius already simulates this internally (that is what the weight parameter is for), so your simulation should only include stationary contributions (gravity, rolling resistance and drag).

I am curious where exactly this comes from, by the way:

self.PowerResistanceFactor = 128866         # TotalReverse

From the totalreverse information I would expect 137 289.75 3.6 ~= 142905. Maybe I am missing something (or this explains my Fortius reading 10-20% high).

ericchristoffersen commented 3 years ago

I think you are basically on the right track and if you fix power->load/force conversion it should basically work (minus calibration). Be careful though if your target power calculation includes inertia effects (i.e. acceleration/decceleration). The Fortius already simulates this internally (that is what the weight parameter is for), so your simulation should only include stationary contributions (gravity, rolling resistance and drag).

Its pretty great to suddenly meet all these people that speak trainer.

The watts value I'm providing are exactly the watts needed to maintain current simulation state aka: same speed at this slope at this altitude, etc.

GC with simspeed is like zwift in that we only see watts from the trainer, speed is computed from watts and state (mass, slope, altitude, cda, etc.)

ericchristoffersen commented 3 years ago

@ericchristoffersen As far as we know, there are three modes, determined by byte 8: STOP (0x00), FORCE (0x02) and CALIBRATE (0x03). There is neither a power nor a slope mode, you have to implement this yourself.

Both your slope command and your ergo command set FORCE mode. The target (bytes 4-5) specifies a force, not a power (a value of 137 is ~ 1N). So I don't think you ergo mode is implemented properly either.

I have thought of writing up a more detailed specification of all the legacy Tacx trainers in one place. Almost everything is already reverse-engineered, you just have to piece it together. Most of what you need for the Fortius can be found here: https://github.com/totalreverse/ttyT1941/wiki#newer-usb-1264-bytes-protocol

Btw I am a happy GC user myself, although I only use the analysis portion.

Wow. Awesome. Now load becomes newtons and suddenly it isn't so magical any more.

Yeah, so looks like the load calc is wrong too. Is wonderful that this can be made right.

switchabl commented 3 years ago

The watts value I'm providing are exactly the watts needed to maintain current simulation state aka: same speed at this slope at this altitude, etc.

Yes, I had a quick look. That is some fancy simulation you got there. ;-) Anyway, your WattsForV seems to be exactly what is needed. I think

double wattsForV = m_constants.m_Cm * v * (CdARho / 2 * (v + W)*(v + W) + Frg + v * CrVn);

should have (v + W) * abs(v + W) though? Otherwise a stronger tail wind will add drag at some point instead of pushing you. Not a common case for training of course.

Wow. Awesome. Now load becomes newtons and suddenly it isn't so magical any more.

The Fortius is rather straightforward in that respect. For the magnetic brakes (e.g. iMagic), the force/power is unfortunately a non-linear function of both load setting and wheel speed.

mattipee commented 3 years ago

@ericchristoffersen just took a look at the PR... I've been thinking about similar recently because I want to implement ANT+ remote virtual gearing on a single speed on a Bushido Smart - I know @switchabl has thoughts on the same.

Wouldn't using power and ergo completely decouple trainer wheel speed and gearing, and give a very unrealistic feel? Are there other use cases for simulate-slope-using-ergo, other than Fortius, which can certainly be fixed?

mattipee commented 3 years ago

should have (v + W) * abs(v + W) though? Otherwise a stronger tail wind will add drag at some point instead of pushing you. Not a common case for training of course.

@switchabl good spot! I made the same mistake recently, modelling a 25mph tailwind and wondering why my calculations came out wrong.

ericchristoffersen commented 3 years ago

@switchabl : Tailwind: ahh.. That is right. Wind isn't plumbed through today, no routes have it but but someday it'll be necessary for drafting virtual riders. Maybe never negative but you never know. Simulation fancy: yeah... its overboard but why not? It doesn't even show up on the profile. Did you look at what ::SampleSpeed actually does?

@mattipee: Singlespeed: I am primarily an 80kg singlespeed mountain biker and I haven't been on any trainer that feels like an actual bicycle when I'm climbing at a low cadence. Trainers simply don't have the necessary torque and they don't have the necessary inertia. I'm resigned to chasing the force at the pedal that feels right which typically requires a different ratio than I'd want in real life.

In practice I'm spinning on the trainer so gear ratio doesn't matter to me so much as getting proper pedal 'platform'.

Try it and see?

mattipee commented 3 years ago

@ericchristoffersen I've set up a new devenv for GC, and will set up the Fortius again later this evening - I've had it listed for sale, but I luckily still have it.

Mickyduck55 commented 3 years ago

Awesome, thanks for the update!

On Sat, 19 Dec 2020 at 17:59, mattipee notifications@github.com wrote:

@ericchristoffersen https://github.com/ericchristoffersen I've set up a new devenv for GC, and will set up the Fortius again later this evening - I've had it listed for sale, but I luckily still have it.

โ€” You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/WouterJD/FortiusANT/issues/171#issuecomment-748505082, or unsubscribe https://github.com/notifications/unsubscribe-auth/AFLPPTMPFCEIGWU2VOPIS7TSVTSWVANCNFSM4VBW73QA .

Brilliant...

ericchristoffersen commented 3 years ago

@ericchristoffersen I've set up a new devenv for GC, and will set up the Fortius again later this evening - I've had it listed for sale, but I luckily still have it.

Yeah! I think much easier to do this stuff with the actual unit. Mick tried the artifact from my pr yesterday and says it doesn't work. Says the power stays at around 50-80 no matter what he tries. He says golden cheetah's erg mode works fine, so I don't think its gc's primitive equation for brake load.

I had a model in my head of how to drive load but I guess it doesn't work and I'm not sure why.

Hopefully you can see the flaw in my reasoning.

What I was hoping would work is that rider could briefly over-drive the trainer's load setting, this increased power would be reported from trainer to simulation which would increase the sim speed and drive an increase in desired load. But something is blocking the feedback between trainer and the sim.

It could be our communication is busted somehow.

Another idea of why it fails is that the 'brake-load change latency' is significantly higher than the trainer's 'erg load response' latency. If that is the case then the trainer would adapt too quickly to the old load, the short power impulse would increase sim speed briefly before it coasted back down to the old erg setting. Sim sees the old power setting and drops speed back to where it was before, thus power stuck around the minimum.

The sim has slope, speed, load. Pretty much anything that can be imagined. But we need a natural way for load to increase on device as user pedals harder. Could be solution is to include the device wheel rpm in the load calc, we can use the device speed as a proxy for the sim speed for purposes of determining load.

Mickyduck55 commented 3 years ago

Delighted to see this may have some traction.. I did my best Eric and the good news is that I am away from tomorrow until after christmas so wont be able to do any testing ;) Seriously guys I'm quite attached to my Fortius and the move to a new trainer holds no fascination for me.. for a start my very old Look cycle would have to be replaced as its only 8 speed Campag so modern direct drive trainers are not compatible... and we have suffered a lot together LOL

On Sat, 19 Dec 2020 at 21:20, ericchristoffersen notifications@github.com wrote:

@ericchristoffersen https://github.com/ericchristoffersen I've set up a new devenv for GC, and will set up the Fortius again later this evening - I've had it listed for sale, but I luckily still have it.

Yeah! I think much easier to do this stuff with the actual unit. Mick tried the artifact from my pr yesterday and says it doesn't work. Says the power stays at around 50-80 no matter what he tries. He says golden cheetah's erg mode works fine, so I don't think its gc's primitive equation for brake load.

I had a model in my head of how to drive load but I guess it doesn't work and I'm not sure why.

Hopefully you can see the flaw in my reasoning.

What I was hoping would work is that rider could briefly over-drive the trainer's load setting, this increased power would be reported from trainer to simulation which would increase the sim speed and drive an increase in desired load. But something is blocking the feedback between trainer and the sim.

It could be our communication is busted somehow.

Another idea of why it fails is that the 'brake-load change latency' is significantly higher than the trainer's 'erg load response' latency. If that is the case then the trainer would adapt too quickly to the old load, the short power impulse would increase sim speed briefly before it coasted back down to the old erg setting. Sim sees the old power setting and drops speed back to where it was before, thus power stuck around the minimum.

The sim has slope, speed, load. Pretty much anything that can be imagined. But we need a natural way for load to increase on device as user pedals harder. Could be solution is to include the device wheel rpm in the load calc, we can use the device speed as a proxy for the sim speed for purposes of determining load.

โ€” You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/WouterJD/FortiusANT/issues/171#issuecomment-748526716, or unsubscribe https://github.com/notifications/unsubscribe-auth/AFLPPTIRDGCO4CJTWFFJJDDSVUKIZANCNFSM4VBW73QA .

mattipee commented 3 years ago

Posted on gc-users... any ideas here: "could not clear/halt ep 130: Protocol error"? I'm getting an ergo load set ok on the trainer (T1932) which I can manually adjust in the GUI, but getting nothing but usb read errors.

ericchristoffersen commented 3 years ago

I'm not seeing your post. On google groups 'golden cheetah user group'?

What os are you building on?

Mickyduck55 commented 3 years ago

I have no programming knowledge at all ... so there have been some changes to the Fortius interface recently (ish) so get a recent version (you probably have already) The previous versions had a lot of USB issues but usually Error 43 which I believe was a disconnect... I will go away now as I cannot really add anything useful and watch with interest...

On Sat, 19 Dec 2020 at 21:46, mattipee notifications@github.com wrote:

Posted on gc-users... any ideas here: "could not clear/halt ep 130: Protocol error"? I'm getting an ergo load set ok on the trainer (T1932) which I can manually adjust in the GUI, but getting nothing but usb read errors.

โ€” You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/WouterJD/FortiusANT/issues/171#issuecomment-748529700, or unsubscribe https://github.com/notifications/unsubscribe-auth/AFLPPTJ37BX6IRASRJVZRGDSVUNMLANCNFSM4VBW73QA .

mattipee commented 3 years ago

I'm not seeing your post. On google groups 'golden cheetah user group'?

The thread on golden-cheetah-users - just joined, post pending approval perhaps.

What os are you building on?

Debian 10.7

ericchristoffersen commented 3 years ago

Sorry I don't know anything about linux setup.

In other news I finally looked at the load equation in gc. First, the difference between gc ergo and slope modes for fortius is that erg mode sets 'weight' to the minimum which is '0xa', and slope mode sets weight to rider mass in kg. This is supposed to approximate a flywheel mass so that should be good.

Now that I've read the totalreverse I don't understand how even current erg code can work though apparently it does? How can resistance be correct if it isn't dividing by wheel speed? I think the entire thing needs a thorough roto-rooting but someone that actually has one of these trainers.

switchabl commented 3 years ago

@ericchristoffersen It shouldn't work. But assuming you are riding at 25-30 km/h anyway, you might still end up in the right ballpark depending on the scale. Of course, if you dropped down to 10km/h or something, you would probably notice it isn't actually ergo-mode.

ericchristoffersen commented 3 years ago

Ok, I updated the pr with resistance now calculated like fortant does. But really I need to stop messing with it because I've got no way to test.

https://github.com/GoldenCheetah/GoldenCheetah/pull/3725

mattipee commented 3 years ago

@ericchristoffersen I've commented on the PR. The value of FortiusANT's PowerResistanceFactor is required here.

It would be good to get constants/variable units reflected in code at some point. Similarly, nice when I can get my trainer working so I can test and contribute. :/

ericchristoffersen commented 3 years ago

I posted your question to user group:

https://groups.google.com/g/golden-cheetah-users/c/zR82tifVFHU

mattipee commented 3 years ago

I posted your question to user group:

https://groups.google.com/g/golden-cheetah-users/c/zR82tifVFHU

@ericchristoffersen it has just occurred to me it might be caused by forwarding the USB device from host to a VM...

switchabl commented 3 years ago

Ok, I updated the pr with resistance now calculated like fortant does. But really I need to stop messing with it because I've got no way to test.

I hear you! I am currently trying to add a new trainer (Tacx Bushido) without being able to test it myself. But a couple of commits in, I think we are getting close. And if it stops perfectly working trainers from going to the landfill just because Garmin/Tacx decided to turn off the software... at a time when lots of people want to do indoor training because of COVID, but cannot afford a new one (if it's not sold out that is). The Bushido is the last of the legacy Tacx trainers that was missing in FortiusANT.

It made me think about having simulated versions of the trainers for testing. It doesn't really help with the more subtle quirks (unless they are based on very thorough reverse-engineering), but it would sure help to make sure you got the big picture right. And add some confidence that you didn't inadvertently break something without needing phsyical access to all supported trainers.

mattipee commented 3 years ago

@ericchristoffersen A single line in LibUsb::OpenFortius() is the cause of my issues: rc = usb_set_altinterface(udev, alternate);

mattipee commented 3 years ago

I've become SO unfit... I like the fact that software development/testing and physical exertion overlap, but I'm done for night! :)

ericchristoffersen commented 3 years ago

I've become SO unfit... I like the fact that software development/testing and physical exertion overlap, but I'm done for night! :)

Very nice. I'm so sorry you had a usb issue as your intro to gc fortius.

Is so great to pull this fortius support out of the dark ages. I'm really eager to hear if gc slope mode now works on fortius.

mattipee commented 3 years ago

I've become SO unfit... I like the fact that software development/testing and physical exertion overlap, but I'm done for night! :)

Very nice. I'm so sorry you had a usb issue as your intro to gc fortius.

Is so great to pull this fortius support out of the dark ages. I'm really eager to hear if gc slope mode now works on fortius.

@ericchristoffersen Thankfully, the usb issue required no pedalling. ๐Ÿ˜‚ However, it did require some persistence.

Mickyduck55 commented 3 years ago

Hi Gents I feel for you Mattipee re testing I was on and off the bike quite a few times over the weekend ... fortunately it was apparent fairly early into any ride that it was not right. Iโ€™m โ€œalmostโ€disappointed that I am not at home so cannot help with the testing ... I will be on my bike the day I get back to give this a go ... thank you all so much for your effort..

On Mon, 21 Dec 2020 at 04:22, mattipee notifications@github.com wrote:

I've become SO unfit... I like the fact that software development/testing and physical exertion overlap, but I'm done for night! :)

Very nice. I'm so sorry you had a usb issue as your intro to gc fortius.

Is so great to pull this fortius support out of the dark ages. I'm really eager to hear if gc slope mode now works on fortius.

@ericchristoffersen https://github.com/ericchristoffersen Thankfully, the usb issue required no pedalling. ๐Ÿ˜‚ However, it did require some persistence.

โ€” You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/WouterJD/FortiusANT/issues/171#issuecomment-748748494, or unsubscribe https://github.com/notifications/unsubscribe-auth/AFLPPTK7243AQCPLY2KMICLSV3EPJANCNFSM4VBW73QA .

mattipee commented 3 years ago

@Mickyduck55 it's a pleasure. I hope you enjoy your break, and hope you will also enjoy the results on your return. ๐Ÿ‘

The next step for me is some data capture to help to characterise the Fortius's inability to cope with high torque at low speed, so that we can experiment with resistance limiting as a function of wheel speed.

I should be aware, however, that as I'm starting training again "from the couch", I don't want to injure myself with repeated high intensity efforts. Need to make sure I'm warmed up. ๐Ÿ˜‚

Mickyduck55 commented 3 years ago

As does the Fortius ๐Ÿ˜€๐Ÿ˜€๐Ÿ˜€๐Ÿ˜€

On Mon, 21 Dec 2020 at 09:44, mattipee notifications@github.com wrote:

@Mickyduck55 https://github.com/Mickyduck55 it's a pleasure. I hope you enjoy your break, and hope you will also enjoy the results on your return. ๐Ÿ‘

The next step for me is some data capture to help to characterise the Fortius's inability to cope with high torque at low speed, so that we can experiment with resistance limiting as a function of wheel speed.

I should be aware, however, that as I'm starting training again "from the couch", I don't want to injure myself with repeated high intensity efforts. Need to make sure I'm warmed up. ๐Ÿ˜‚

โ€” You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/WouterJD/FortiusANT/issues/171#issuecomment-748878376, or unsubscribe https://github.com/notifications/unsubscribe-auth/AFLPPTMZOWRTTZUUV35H3VDSV4KGZANCNFSM4VBW73QA .

WouterJD commented 3 years ago

Fortius's inability to cope with high torque at low speed

My solution to this is redefining the problem-statement into "low wheel speed". If you always cycle in a high gear, you always generate enough wheelspeed to make the Fortius run smoothly.

In GradeMode, the virtualgear is used to reduce the VirtualWheelSpeed and require less power. Not doing so, the required power would be unachievable.

In my opinion, the physical wheel speed is irrelevant; unless you want to see the wheel turn the same speed as Zwift shows on the screen. In that case do not buy a direct-drive trainer: there is no wheel :-)

mattipee commented 3 years ago

@Mickyduck55 I'll take a look at calbration in GC too.

@Wouter with direct drive, there is no wheel, true, but there is always an implied simulation of a 700c wheel (or whatever is configured). So speed/distance is a function of cadence, physical/virtual gear ratios, and either an actual or a simulated wheel diameter. So there definitely IS a relationship - FortiusANT effectively encodes wheel diameter in the constant used in WheelToSpeed() and SpeedToWheel() - you could change the value of that constant to simulate different wheel diameters to effect a virtual gearing of sorts, in much the same way we apply PowerResistanceFactor to simulate virtual gearing - in effect, it's all the same - the maths is all equivalent, it's just how you interpret it and what implied properties the constants encode. But you can't calculate required power for a given grade without a known/simulated speed, and you can't calculate a simulated speed without an implied wheel size.

VirtualGear (ie PowerResistanceFactor) is used to change the relationship so that the TargetPowerToResistance() function returns a lower force value to be sent to the trainer, requiring the physical wheel to run faster than the "simulated speed" to achieve the TargetPower - great. The benefit of this approach is the known relationship between virtual speed and wheel speed. In terms of conceptual interpretation, you can think of it as an arbitrary make-it-easier-or-harder button, or changing the gear ratio to something known, or changing the wheel diameter - it's all pretty much the same maths in the end. But it's always a compromise with such a gear change... you lose top end, or you lose bottom end, so it's there to be changed at runtime. Just like real gears. (Therein lies the thought of a non-linear relationship at the bottom end for the virtual gearing to overcome the low-wheel-speed issue, which I'll only mention, as it's not the approach of either FortiusANT or GC).

The cycle of death implementation, the lower-end resistance-value fiddle, in FortiusANT, and the proposed max-resistance-as-a-function-of-speed for GC (same things really, it's just what the graph looks like) do however break that known relationship between wheel speed and simulated speed.

But it's all good... if you're using power over time to calculate a virtual speed based on kinetic energy, as do Zwift, Rouvy, GC, etc, there's no practical downside to decoupling physical wheel speed from simulated speed, as long as it feels good and doesn't stutter.

Keen to hear if I'm thinking through this correctly, or not.

Mickyduck55 commented 3 years ago

@mattipee Calibration availability would solve one of the main issues people have with the demise of TTS. (hope I have tagged you correctly.. not used thai before)

On Mon, 21 Dec 2020 at 12:55, mattipee notifications@github.com wrote:

@Mickyduck55 https://github.com/Mickyduck55 I'll take a look at calbration in GC too.

@wouter https://github.com/wouter with direct drive, there is no wheel, true, but there is always an implied simulation of a 700c wheel (or whatever is configured). So speed/distance is a function of cadence, physical/virtual gear ratios, and either an actual or a simulated wheel diameter. So there definitely IS a relationship - FortiusANT effectively encodes wheel diameter in the constant used in WheelToSpeed() and SpeedToWheel() - you could change the value of that constant to simulate different wheel diameters to effect a virtual gearing of sorts, in much the same way we apply PowerResistanceFactor to simulate virtual gearing - in effect, it's all the same - the maths is all equivalent, it's just how you interpret it and what implied properties the constants encode. But you can't calculate required power for a given grade without a known/simulated speed, and you can't calculate a simulated speed without an implied wheel size.

VirtualGear (ie PowerResistanceFactor) is used to change the relationship so that the TargetPowerToResistance() function returns a lower force value to be sent to the trainer, requiring the physical wheel to run faster than the "simulated speed" to achieve the TargetPower - great. The benefit of this approach is the known relationship between virtual speed and wheel speed. In terms of conceptual interpretation, you can think of it as an arbitrary make-it-easier-or-harder button, or changing the gear ratio to something known, or changing the wheel diameter - it's all pretty much the same maths in the end. But it's always a compromise with such a gear change... you lose top end, or you lose bottom end, so it's there to be changed at runtime. Just like real gears. (Therein lies the thought of a non-linear relationship at the bottom end for the virtual gearing to overcome the low-wheel-speed issue, which I'll only mention, as it's not the approach of either FortiusANT or GC).

The cycle of death implementation, the lower-end resistance-value fiddle, in FortiusANT, and the proposed max-resistance-as-a-function-of-speed for GC (same things really, it's just what the graph looks like) do however break that known relationship between wheel speed and simulated speed.

But it's all good... if you're using power over time to calculate a virtual speed based on kinetic energy, as do Zwift, Rouvy, GC, etc, there's no practical downside to decoupling physical wheel speed from simulated speed, as long as it feels good and doesn't stutter.

Keen to hear if I'm thinking through this correctly, or not.

โ€” You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/WouterJD/FortiusANT/issues/171#issuecomment-748959275, or unsubscribe https://github.com/notifications/unsubscribe-auth/AFLPPTLMXKDRQW7DPTEWP53SV5ASTANCNFSM4VBW73QA .

Mickyduck55 commented 3 years ago

Obviously not LOL... Oh well You will get the message

On Mon, 21 Dec 2020 at 13:14, Mick Drake mickyduck55@gmail.com wrote:

@mattipee Calibration availability would solve one of the main issues people have with the demise of TTS. (hope I have tagged you correctly.. not used thai before)

On Mon, 21 Dec 2020 at 12:55, mattipee notifications@github.com wrote:

@Mickyduck55 https://github.com/Mickyduck55 I'll take a look at calbration in GC too.

@wouter https://github.com/wouter with direct drive, there is no wheel, true, but there is always an implied simulation of a 700c wheel (or whatever is configured). So speed/distance is a function of cadence, physical/virtual gear ratios, and either an actual or a simulated wheel diameter. So there definitely IS a relationship - FortiusANT effectively encodes wheel diameter in the constant used in WheelToSpeed() and SpeedToWheel() - you could change the value of that constant to simulate different wheel diameters to effect a virtual gearing of sorts, in much the same way we apply PowerResistanceFactor to simulate virtual gearing - in effect, it's all the same - the maths is all equivalent, it's just how you interpret it and what implied properties the constants encode. But you can't calculate required power for a given grade without a known/simulated speed, and you can't calculate a simulated speed without an implied wheel size.

VirtualGear (ie PowerResistanceFactor) is used to change the relationship so that the TargetPowerToResistance() function returns a lower force value to be sent to the trainer, requiring the physical wheel to run faster than the "simulated speed" to achieve the TargetPower - great. The benefit of this approach is the known relationship between virtual speed and wheel speed. In terms of conceptual interpretation, you can think of it as an arbitrary make-it-easier-or-harder button, or changing the gear ratio to something known, or changing the wheel diameter - it's all pretty much the same maths in the end. But it's always a compromise with such a gear change... you lose top end, or you lose bottom end, so it's there to be changed at runtime. Just like real gears. (Therein lies the thought of a non-linear relationship at the bottom end for the virtual gearing to overcome the low-wheel-speed issue, which I'll only mention, as it's not the approach of either FortiusANT or GC).

The cycle of death implementation, the lower-end resistance-value fiddle, in FortiusANT, and the proposed max-resistance-as-a-function-of-speed for GC (same things really, it's just what the graph looks like) do however break that known relationship between wheel speed and simulated speed.

But it's all good... if you're using power over time to calculate a virtual speed based on kinetic energy, as do Zwift, Rouvy, GC, etc, there's no practical downside to decoupling physical wheel speed from simulated speed, as long as it feels good and doesn't stutter.

Keen to hear if I'm thinking through this correctly, or not.

โ€” You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/WouterJD/FortiusANT/issues/171#issuecomment-748959275, or unsubscribe https://github.com/notifications/unsubscribe-auth/AFLPPTLMXKDRQW7DPTEWP53SV5ASTANCNFSM4VBW73QA .

Mickyduck55 commented 3 years ago

@mattipee @ericchristoffersen Good morning gents.. I am just about ready to get on my bike to have a little test.. (trip cut short due to new Covid restrictions).. is there a "new" version of GC for me to download or is this the latest Build ID 4002 Dec 21? TIA

mattipee commented 3 years ago

I would appreciate a test of https://github.com/GoldenCheetah/GoldenCheetah/pull/3731, but I don't know if there are build artefacts available for Windows or not.