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

Full virtual shifting (front/rear) #120

Closed
switchabl opened this issue Oct 28, 2020 · 29 comments
Closed

Full virtual shifting (front/rear) #120

switchabl opened this issue Oct 28, 2020 · 29 comments
Labels
enhancement New feature or request implemented

Comments

@switchabl
Copy link
Contributor

I really liked the idea of having a virtual gear box, so now I keep the physical gear fixed and the trainer can run at an optimal speed all the time. This solves the stuttering problem with the Fortius at low speeds and I suppose it also enables lower-end trainers to simulate higher gradients. I decided to take this a little further and simulate a full 2x11 group set to have the same gear range as on a real bike.

You can take a look at my code here: https://github.com/switchabl/FortiusANT/tree/shifting
It also contains some other modifications and definitely needs more work if it is to be merged into the main branch:

Everything is hard-coded right now: there should probably be options to change the number of gears and the chain rings/cassette, as well as the physical gearing ("ReferenceGearRatio"). Maybe it is time for a configuration file (json/yaml)?

I made the text box a little larger to show front/rear teeth, but left the graphical representation basically as is. Graphical representation of the chain rings may be nice to have, but it is probably fine as-is.

Backward-compatibility/default setting for people who don't want full simulation could be done by configuring a single chain ring in front and an appropriate cassette.

I stole the cancel button for front shifting, I don't know if this is a problem. I hated it anyway after hitting it accidentally twice.

@WouterJD WouterJD added the enhancement New feature or request label Oct 28, 2020
@WouterJD
Copy link
Owner

Please show picture of UI

@switchabl
Copy link
Contributor Author

switchabl commented Oct 28, 2020

Very basic, but works for me:
Screenshot 2020-10-28 204331
I don't know if the graphic should be offset like that or if I broke something?

@WouterJD
Copy link
Owner

WouterJD commented Oct 28, 2020

The "virtual gear" enables to increase/decrease the resistance when riding up/down a slope.

If you ride up and the resistance is too high, press down and the resistance will decrease. You can maintain the same cadence and because you produce a lower power-output; Zwift will calculate a lower speed.

The up/down goes with +10%/-10% which matches the steps on a cassette: 10 -> 11 = 10% and 32 -> 36 is also (approx) 10%.

It's a bit like the knob on the sportschool trainer: turn left/right for lighter/heavier. Not precise but we did not care.

I understand you want to have two shifters for your double and the cassette to see the 50/34 versus 10/11/.../36 numbers. Perhaps it is also neat when you select 50x36 or 34x10 that the derailleur ticks and the chain cracks and complains. And that after some time the chain gets dry and starts to sqeeck (joking).

But the question is: why?
My thought on implementing was: I ride Zwift, it goes uphill at 20% and I cannot do that at the speed that the Fortius still works well. Since I have a bike with a 50/34 x 15/25 gearing, I cannot ride uphill 20% anyway.
So I implemented a reductionfactor (after far more complicated options) and visualized the factor (0.1 ... 1 ... 10) not an abstract number, but as the number of teeth on the cassette. (As if riding with a 1x11 setup)

The factor is -10% steps up/down and nothing else.

I understand you want to simulate two shifters. Even also want to show it graphically.
Question is: why? What does it bring.

(Other than the fun of programming)

@WouterJD
Copy link
Owner

I don't know if the graphic should be offset like that or if I broke something?

This is how the standard is; so it's a bit offset.
Some work to be done to have the textbox well aligned and level with the graph.
:-)

Slide14

@switchabl
Copy link
Contributor Author

switchabl commented Oct 28, 2020

Well, essentially I wanted to solve the same problem. When I ride up a steep climb on Zwift the Fortius can not do it. The idea with the virtual gear box is nice. But then I have to adjust something else while riding and the physical gears on my bike are not the same as in the real world anymore. So I decided to go fully virtual with the shifting. I leave the real bike always in the same gear for the entire ride (and FortiusANT knows which one). And then just simulate all the gears. Essentially what the Neo Bike or the KICKR BIKE do. They don't even have physical gears, just buttons and simulate the rest.

This has some other benefits as well:

  • I can choose whatever gearing I like (maybe a cassette with 32 sprocket for a long climbing session? or try how a 1x groupset would work?)
  • the trainer never really goes to very high wheel speeds either, so not as loud on a downhill
  • the wheel speed (and thus temperature) doesn't vary too widely, so power reading will be more consistent

And some disadvantages:

  • cassette will wear out faster (probably I should switch the real "reference" gear occasionally)
  • doesn't feel quite as realistic as real shifting
  • shifting down 3 gears quickly with the head unit buttons is not that great, but that is why I added the remote control

Overall it feels really good and realistic now on Zwift, even on the steepest climbs.

@mattipee
Copy link
Contributor

My only contribution at this point is that, intending to use GoldenCheetah primarily, I would like to also broadcast a corrected speed - a function of the "actual wheel speed" and "virtual gear". Zwift indeed only uses power from the trainer to calculate its own in-game speed. But I think if we're talking about virtual gearing, virtual speed in FortiusANT still matters, particularly if using software such as GoldenCheetah.

I don't think my changes to split "VirtualSpeed" and "ActualSpeed" made it into your code Wouter, so if not, I'd be happy to reproduce it for discussion when I get set up again.

Any combination of front/rear shifting simply results in a gear ratio. The easy solution is that for a given gear ratio, the relationship between actual speed and virtual speed is linear, taking care to implement the numerical functions using the appropriate speed value at each stage. Also, the suggestion of an equivalent correction to the virtual flywheel value is probably important here too... not something I had picked up on before.

There is then the potential for a further tweak to make the actual/virtual speed relationship for a given gear ratio non-linear at low wheel speeds, to eliminate low-speed stuttering, but I'll leave that subject well alone just now.

@switchabl
Copy link
Contributor Author

From what I have seen, it already works this way. The virtual speed is calculated using the virtual gear ratio and this is the one that is broadcast and used for the grade2power calculation. The speed reported by FortiusANT is also very close to the one in Zwift (at least on climbs), so I think this is a good sign.

I am really only interested in the linear version, so I use:

GearRatio = (VirtualTeethFront / VirtualTeethRear) / (RealTeethFront / RealTeethRear)

This, along with the inertia correction, should give a faithful simulation of riding in the virtual gear (provided the real gears used physically on the bike are set correctly). I can now e.g. ride a 15% climb with (virtual) 34/28 and it feels a lot like it would on the road (while actually having the bike on 50/17, so the Fortius has no trouble coping). And I can ride back down in virtual 50/11 without the wheel getting crazy fast and loud.

Unless I missed something, I think the physics part is probably ok now. What remains to be done to merge this feature is maybe:

  • add configuration options for chain rings/cassette and real bike gear instead of having it hard-coded (BONUS: determine real gear automatically from cadence and wheel speed)
  • fix the UI quirks (BONUS: add graphics for front chain rings)
  • some clean-up
    If @WouterJD is interested in merging this, I am happy to do some work on that. Otherwise I would probably just leave it as it is now and ride with it.

@mattipee
Copy link
Contributor

mattipee commented Oct 29, 2020

From what I have seen, it already works this way.

Indeed, I had too quickly looked at the wrong file last night.

@WouterJD
Copy link
Owner

Well guys. Please convince me that this is usefull for the FortiusANT community.
I do understand WHAT you make.
I do NOT understand WHY you want it; I have the impression it is a very complex way of implementing a Increase/Decrease option while being in GradeMode.

@switchabl
Copy link
Contributor Author

switchabl commented Oct 29, 2020

Let me put it this way: you remarked earlier that the virtual gear box was meant as a "not precise" knob to turn up/down resistance. This is the precise knob. Instead of "decrease the resistance, the Fortius can't do this" I can say "make it feel exactly like I am riding 34/25 on the road".

Is it useful for the FortiusANT community? I can only say it is useful for me, because now I have a Fortius that can simulate realistically to 20% or more at basically any speed, the only difference is I have to shift with a button instead of the real shifters. @mattipee was interested in simulating shifting with a single-speed bike on the trainer. Maybe that's it, everyone else doesn't need it or thinks it is too complicated? (it maybe should not be on by default) If you think that is the case, it is fine with me. I made this for myself, if it is useful for someone else, I am happy to share. If not, I will just enjoy using it.

@mattipee
Copy link
Contributor

Overall, I think of it simply as giving the "PowercurveFactor" variable that you introduced (with a value range 0.1-3), some physical meaning, (which implies perhaps a more meaning full name could be sought for this variable - VirtualGearCorrectionFactor or something less obtuse).

Rather than the "useful range" of 0.1-3 with x1.1 increments, I think of it conceptually as conversion factor from "current physical gear ratio" to "desired virtual gear ratio". The maths remains the same, it is simply a reinterpretation of the value itself and how one comes to assign it. And the WHY is therefore probably just "conceptual realism".

Of course, with the 0.1-3 range, and the x1.1 modifier, this resulting step-values would indeed correspond to some conceptual virtual gear tooth counts given a particular physical gear, but such a scheme doesn't clearly resemble the concept in code itself. I agree it is more complex to produce these values based on virtual gearing, but that's the abstraction I think we're trying to make, at least in my mind.

In any case, I think the real subtlety is how one specifies or otherwise determines the "current physical gear ratio".

@WouterJD
Copy link
Owner

My view on this is the following:

Assume the usable combinations on a Compact / 11 speed are the bold/blue options as depicted below.
When shifting, steps are from 8...15%; at a certain moment a double-shift is required to move from the outer to the inner blade.

The current implementation in FortiusANT is that a step is always 10% and there is one shifter only, as if using a 1x11 setup.
Please explain why introducing the suggested complexity; two shifters (not implementable using the Fortius head-unit), external parameterization and graphical representation.

image

@WouterJD WouterJD removed the enhancement New feature or request label Oct 29, 2020
@mattipee
Copy link
Contributor

Part of my winter plan is that I'm intending to virtually ride previously ridden or planned GPX routes, probably adding wind resistance into GoldenCheetah for additional realism, and would like to be able to choose which of my bikes I do this with, depending on the route I'm training (also implying some new value overrides for wind and rolling resistance for TT, road and MTB).

For example, for a given fitness level (poor at the moment), training my local flat 5 or 10 mile TT as if on my singlespeed, and simulating a target front-chainring selection, given my FTP and target cadence. Or virtually training my local hill climbs and determining which gear I think I can sustain over different sections.

Range overlap is indeed a real thing, but I think we all agree most people won't want to care/know, so allowing an implementation to support multiple chainrings and yet have a default of a single is still consistent with the concept.

Anyway, that's my motivation for the "conceptual realism". Otherwise, it is absolutely because coding and conceptual abstraction is fun. And so is sharing. As @switchabl , I'm happy to share, but will otherwise just enjoy using it.

@switchabl
Copy link
Contributor Author

Ah, well, the same reason I prefer riding on Zwift to riding in ERG mode and looking at a wall. It feels more like riding a bike, more realistic and engaging and less boring.
Look at the effort Tacx put into the virtual shifting on their Smart Bike: https://www.dcrainmaker.com/2019/09/tacx-neo-bike-smart-in-depth-detailed-review.html#shifting-riding
They even simulate the dynamic behaviour where the resistance increases momentarily during the gear change.

@WouterJD
Copy link
Owner

Regarding GPX-rides I can certainly recommend Rouvy; not only can you ride your own GPX but also do "Enhanced reality" rides with video simulation showing you the real environment.

And indeed; when doing Trainer Road training, I watch a video - today the vuelta ride but Netflix is a good option as well, not talking about DVD's or whatever distracts from the Wattage and sweat.

And indeed, the Tacx Neo is very usuable for this kind of simulations; like gear shifting dynamics or even terrain (did you ever feel the riding over a bridge). I have thought of this, but: Tacx Fortius has an internal delay when changing power so that you gradually move from one block to the other; intervals of 10seconds are hard to realize for that reason.
Implementing gearshift power changes would not work.

Tacx sure has a good reason to build direct drive instead of the roller.
But we save a serious amount of money, bridging the new software to their old hardware - which is still good; whilst respecting the limitations.

Thanks for you enthusiasm!

@WouterJD WouterJD added enhancement New feature or request future development This is not on the backlog for the coming releases labels Nov 11, 2020
@ericchristoffersen
Copy link

Hi Guys.

Mattipee pointed me at this thread today. I just reimplemented virtual gears for golden cheetah after learning so much from fortius. I know the force I want so compute new gradient by first computing d(force)/d(gradient). The same approach might work for you?

GoldenCheetah/GoldenCheetah@62c6864

When I was testing it I realized another boo-boo - trainer inertia is wrong when simulated and device speed were different:

GoldenCheetah/GoldenCheetah@057adcd

Feels pretty good with both changes.

@switchabl
Copy link
Contributor Author

@ericchristoffersen Thanks for sharing! This seems like a sensible approach. Probably more so than my original idea which involved changing the wind speed. I guess gradient force calculation should be very consistent across trainers (I am less sure about wind resistance). I think I will try and implement this for the Tacx Genius (and Bushido) which doesn't support virtual shifting right now in FortiusANT.

The effective intertia with virtual shifting is something that came up with the FortiusANT implementation as well (#118).

@ericchristoffersen
Copy link

It works pretty well. There's a big difference in feel between computrainer and my kickr. The kickr feels awesome, like a real bike really pedalling. Virtual granny gear up a steep hill feels like a granny gear, no inertia...

The computrainer doesn't feel so good, I think is held back by its minimum power and some sort of adaptation under the covers, its not really possible to freewheel because of tire friction. And it really doesn't like mass being set to 1000kg...

I think trainer differences are what they are. They are supposed to emulate gradient but some don't do such a good job at it.

@switchabl
Copy link
Contributor Author

I think trainer differences are what they are. They are supposed to emulate gradient but some don't do such a good job at it.

I'm afraid so. Many older/lower-end trainers don't do realistic intertia simulation at all, let alone dynamically with virtual gears. The Fortius is excellent in this regard except for a slight delay in applying the gear change (I have used it for a while with a fixed physical gear and purely virtual shifting) because of the motor brake. Since the motor can actually drive the wheel as well, it can compensate for the tire resistance and go down to zero force (or even negative for downhill grades). That is why they get away without a physical flywheel and can simulate realistic intertia dynamically. I expect the Genius and the NEO to work just as well.

The Kickr has a rather large physical flywheel to give a realistic feeling under normal circumstances. Since you have good results with virtual shifting, I assume they supplement that with dynamic adjustments of the brake resistance to simulate higher or lower intertial mass than the flywheel provides by itself, depending on the user/bike weight requested (and for faster response times in ERG mode).

@WouterJD
Copy link
Owner

WouterJD commented Jan 5, 2021

I'm afraid so.

We extend "Old Tacx life" but unfortunately do not upgrade to modern hardware technology, indeed.

@switchabl
Copy link
Contributor Author

switchabl commented Jan 5, 2021

Ha, true, but in this specific case the old Fortius is quite a lot better than some of the newer options (and maybe no worse than a Kickr or NEO). It was the Computrainer that proved somewhat disappointing.

@ericchristoffersen
Copy link

Ha, true, but in this specific case the old Fortius is quite a lot better than some of the newer options (and maybe no worse than a Kickr or NEO). It was the Computrainer that proved somewhat disappointing.

As a happy kickr owner the Computrainer really is disappointing. I was gifted it so I'm not upset at all, but after playing a bit I read some online discussions about how people used it. Threads from 10 years ago where people accepted the need to adjust their virtual routes so they didn't exceed 5-6% because the computrainer can't handle it, both tire slip and brake overheating.

I am all about steep climbs at low cadence and by default the computrainer is just so unbelievably bad at that. The virtual gears make it possible to ride the 18% mortirolo in a 52x16, so I don't understand why they didn't do that before. Now I just keep adjusting intensity downward until I have the cadence I want. The wheel speed is high and the sim speed is 4kph, my cadence is 30. It doesnt feel like a granny gear on the computrainer because it simply doesnt have the chops to model that inertia, but on kickr the pedal kickr feels pretty good to me. I want to build a rocker plate!

@switchabl
Copy link
Contributor Author

@ericchristoffersen Interestingly enough TTS had some code for virtual shifting (in the assembly browser you can see that some methods take a virtual gearing factor as a parameter), but I don't think it was ever used. The current generation "smart bikes" all seem to use it though (and even simulate the "jolt" produced by the chain).

The Fortius doesn't do 10%+ at very low cadence either. With virtual shifting it is spot on though. Even at low cadence and 15% it feels pretty realistic. I have an ANT remote control that I can reach from the hoods for shifting and adjusted the shifting code so the available gears correspond to a real 2x11 group set.

BUT for this to work (well), you need a trainer with

  • very low (or zero) minimum resistance force and
  • adjustable simulated inertia (preferable with a wide range).
    The Fortius meets those criteria, as do newer high-end trainers, but most don't. E.g. with an iMagic it would be a disaster on both counts, with a small fixed flywheel and a minimum resistance setting that is barely adequate for simulating 0%.

These days I use a Tacx Genius as my main trainer and that one works fine at 15% out-of-the-box (maybe not quite as smooth as it is at lower grades, but for 100€ I can't complain), so I can mostly live without it.

@WouterJD WouterJD added under investigation Being studied for implementation in next version and removed future development This is not on the backlog for the coming releases labels Jan 8, 2021
@WouterJD
Copy link
Owner

WouterJD commented Jan 8, 2021

I think, this is what you like ... just a sneak preview - Under construction :-)

In holland we say: not because we have to - but because we can!

Demo120.mp4

@WouterJD WouterJD added implemented and removed under investigation Being studied for implementation in next version labels Jan 11, 2021
@WouterJD
Copy link
Owner

Version 5.1 Test III is available with this issue implemented.
(for details see wiki)

Please test

@mattipee
Copy link
Contributor

Question... @switchabl ... is this correct?

Weight = max(0x0a, int(self.PowercurveFactor * self.UserAndBikeWeight))

Should we not be balancing "½mv²"? Using v_virtual = PCF × v_actual:

  • ½ × m × v_actual² = ½ × UserAndBikeWeight × v_virtual²
  • ½ × m × v_actual² = ½ × UserAndBikeWeight × PCF² × v_actual²
  • m = UserAndBikeWeight × PCF²

So squaring the PowercurveFactor? Is this right, or have I missed something?

Weight = max(0x0a, int(self.PowercurveFactor * self.PowercurveFactor * self.UserAndBikeWeight))

@switchabl
Copy link
Contributor Author

@WouterJD That looks amazing, thanks! Now I only need to implement the shifting factor for the Genius so I can actually use it ;-)

@mattipee If you wanted to simulate the dynamics during the gear change itself, yes, you would need to preserve kinetic energy (simulating that short "jolt" during shifting). But simply changing the mass won't do that anyway, since the virtual flywheel is very likely implemented in terms of speed rather than kinetic energy.

For the more mundane task of having the correct resistance when accelerating again after the gear change is complete, the relevant formula is just F = m × a. There we want to simulate a_virtual = PCF × a_actual (since a is just the derivative of v), so m = UserAndBikeWeight × PCF will give the correct behaviour.

I think I have done a rigorous calculation in terms of torque and angular velocity/acceleration at the crank at one point (those are in a sense the fundamental quantities that will determine whether pedaling feels realistic or not). I can dig that out if you want more details.

@mattipee
Copy link
Contributor

Please, if you can find that - more I can understand the better.

@WouterJD
Copy link
Owner

Implemented in version 5.1 Test V

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request implemented
Projects
None yet
Development

No branches or pull requests

4 participants