-
-
Notifications
You must be signed in to change notification settings - Fork 79
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
Steering #207
Steering #207
Conversation
… with or without steering interface
…t doesn't update the values correctly when sending them together
Hi - nice to see that it is now possible to send steering data to zwift. Am I correct that extracting steering information from e.g. the blacktrack still needs to be implemented? Or is that already in the code somewhere? |
Hi @trygvelu, yes you are correct. Currently the steering data is only fetched from the Tacx head unit itself. I see the blacktrack communicates over ANT+, so i think that can be added as a next step. I don't own a blacktrack personally, but i'm sure we can get this working as a community. |
I have a Blacktrack (came with my Genius). The ANT protocol for that is really simple, so I don't think it will take me long to implement. We will need to re-think calibration a bit though. The resistance calibration is only done for the Fortius while the Blacktrack can be used with any trainer. Actually the wired steering frame can be used with the Flow, too, and that doesn't have calibration (yet) either. |
I have a blacktrack myself (also with Genius), but I'm not that familiar with the ANT profiles/protocol. I can assist with testing, if needed. Ideally I would think that steering could be implemented independent of the type of trainer hardware being used. |
I suppose implementation would be in line how head-units buttons from the Vortex are integrated. |
@WouterJD Yes, pretty much the same. There is a single page with the steering angle and we need to send a keep-alive every few seconds so it doesn't turn off. As far as I know you can have channel numbers up to 255 as long as you don't enable more than 8 at the same time. I have never used that many before though. |
Simply test to modify the channel numbers and see what happens |
@marcoveeneman Great work there! Thanks a lot for implementing the steering for Zwift. I did test the steering implementation today with my steering frame (not the Blacktrack obviously) on the Raspberry and it seems to work really well. I will keep testing an send you feedback in case I run into some bugs. |
@marcoveeneman sorry for the intermediate upgrade to 5.1 causing conflicts. Could you please look into that? |
Is it a correct understanding that this PR will enable Zwift steering for my T1901/T1932/T1905 (steering frame) setup, i.e. Flow Multiplayer T2220 bundle? And it will communicate via the already established USB/FortiusANT interface? |
Yes that is correct; it can be used with Zwift only - other CTP's do not support steering. |
As a follow up: Having a RPi 3b+ not being used, with some java/git experience (although totally unfamiliar with python), I have done an attempt to achieve my goal for testing the steering functionality for my T1901/T1932/T1905 setup against Zwift. Making a fork of the latest @WouterJD branch, implementing and modifying the @marcoveeneman code for steering (both the "as is" code for CalibratedSupported trainers as well as trying to implement code for my trainer not CalibratedSupported). Comparing with @WouterJD branch, there are no merge conflicts. So, following the raspberry installation from manual, using my customised branch, I apparently have something going on, but not quite:
For anyone interested, willing to comment/help, please have a look at my modified FortiusANT repository: EDIT Calibrated/setup steering successfully in Zwift. However, even if steering is shown as ON in Zwift, there is no steering response while riding. EDIT2 EDIT3 See from log file that initial calibration works as intended, providing actual values for calibrating right/middle (e.g. 788/949). Then the Tacx2Dongle function calls calibration once again, and as the criterias for steering calibration are not met the second time, default values (i.e. 0/0) are set and steering angle remains at 0. Solved by making the calibration variables global, enabling storing calibration values - now Zwifting with steering (although challenging to maintain smooth steering while riding...). |
Yet another update on my behalf, having played around with the steering functionality of my T1901/T1932/T1905 setup. Now believe I have something working satisfactory, based on @marcoveeneman initial steering code, rebasing to latest @WouterJD branch, implementing steering calibration/functionality for non-calibration trainers. Please have a look and see if valid to implement: As a note: The potmeter readings (at least for T1905) proves to be non-linear, so the updated code is introducing an additional calibration value for steering left (in addition to steering right and middle) to set steering angle in the range -45/45 degrees based on potmeter reading. |
@switchabl What is the status on the Blacktrack VR implementation? Would be awesome! Maybe I can help or test? How did you reverse engineer the Blacktrack VR protocol? |
@marcoveeneman it seems that @switchabl has disappeared from github since March. |
@frankhommers Sorry, life got in the way and this hasn't been much of a priority for me since I've been riding outdoors anyway. The protocol for the Blacktrack is here: https://gist.github.com/switchabl/75b2619e2e3381f49425479d59523ead (all the way at the bottom). But I'm afraid Zwift has changed the steering protocol in order to lock out third-party implementations (https://www.dcrainmaker.com/2021/06/zwift-hardware-tidbits-breaking-steering-apple-tv-2021-updates-new-non-supported-trainers-list.html). So @marcoveeneman 's branch is probably broken right now. I think I've more or less managed to crack their new authentication mechanism. So I am cautiously optimistic that it can be done but more work needed. There's also the chance that they will just break it again in a few months time. I'm not sure how keen I am on playing cat-and-mouse with them. |
@switchabl ah yes, life is more important than a few lines of code ;-) I have read DCRainmakers' blog post. And I understand your opinion about cat and mouse. So I guess I am out of luck here... Maybe I'll just buy an Elite Sterzo Smart in order to be able to steer in a supported way. |
I assume the USB trainer class will be enhanced with AxisLeft AxisMiddle AxisRight and Angle (in addition to Axis) |
I am not sure if this is a good idea. If there is some interference or something which causes a value to spike, you'll have wrong steering for the whole session. I would opt for a separate step during the startup sequence. |
@WouterJD Not quite, the trainer class currently gets an added @frankhommers Yes, this is one thing I am worried about, too. I use a median filter to pre-process the values. That should hopefully take care of spikes. If it doesn't work in practice, another alternative would be to use the first reasonably high/low value that is stable for ~1s for calibration. But if you mess it up, you would have to restart. I also think that a separate step during start-up would be a clean solution. The problem is, I have thought about it long and hard and I'm not sure how to do it without completely restructuring the [Eventually, |
I admit that the main loop has grown from antifier into what it is now; knowing all interfaces and requirements from the start would certainly have led to a cleaner design. But as we all know, this happens and redoing is a lot of work AND requires a lot of testing, possibly with an extended period of issues. The T1905 does not require too much intervention
@switchabl How does the blacktrack interface work? Is that an ANT-device to be paired and the interface to be translated to BLE? |
@WouterJD Yes, with the current (dynamic) calibration approach it is not a problem. The modifications to the main loop are minimal. Most of the steering code is in a separate module. And yes, the BlackTrack is an ANT device that needs to be translated to BLE. I have now improved the calibration routine somewhat. The calibration status is now shown on the console as suggested. Also, the new calibration is only applied if the axis value has been reasonably stable for a bit. It will need some more tweaks for sure. The source is still available here: https://github.com/switchabl/FortiusANT/tree/steering Most importantly, there is now a binary package for Windows as well to facilitate testing. It bundles a version of Node.js (and dependencies) so you can mostly ignore the usual instructions for BLE. Still, there are a couple of steps that may be required to run it:
Also, this will not work on Windows 7 (because Node v14 does not), Windows 8.1 or higher is required. To enable steering, select "wired" (for T1905) or "Blacktrack" in the settings (or use the Known issues:
Let me know if you encounter any additional problems. |
@switchabl Does this mean I can take that code and try it out? |
Hi @switchabl I have read through the new code and it looks fine. Would you be so kind to do two things:
Thanks, seem a solid piece of work. As soon as done, I will add the -S to the json code and interactive settings; always a bit of a hassle to have three locations to define the settings, but that's what it is now :-) |
PS. Regarding your last comment on the .exe for testing. There have been several questions "why did you not make an installer". The answer is the number of platforms and options, that alll have to be maintained. From that point of view I'm a bit carefull to integrate more, you already mentioned the remaining "prereqs" for it to work. |
I do not see anything specific in the code in steering.py, especially since the module only handles pages from its own channel. |
Why would that be? Too much processing?? |
@frankhommers Yes, it has been mostly working for a while. You may still have some problems with the Blacktrack (because of the ANT packet drops), I am not sure how bad it is in practice. Not sure about setting everything up on the Raspberry Pi but I guess you already have the normal version of FortiusANT running anyway? @WouterJD Thanks for taking a look. I still need to fix a few things, so it is not quite ready anyway. But the overall structure is unlikely to change now. I admit I never look at the version comments (I find using git to compare and check changes much easier) but I will add them when I am done and then create a clean pull request. The binary package is basically the best thing I could make without making an installer. Think of it as the Windows exe but with all the Bluetooth stuff already included. So the prerequisites are more or less the same as with the normal exe. But it is not meant to be merged into master. It is just a way to let people easily test experimental versions without installing multiple GB of Node.js-related things. But you are right, I was thinking about an installer. An installer would get rid of all the prerequisites (except for the WinUSB-driver for BLE, unfortunately). And the work I have already done on the binary package should be quite helpful. More still to be done though. I have seen the FA-Link. In general, I think selling hardware appliances is very much a legitimate way to monetize open-source projects. I would probably be somewhat worried about it becoming a support nightmare (how to debug problems? how to deploy updates/bug-fixes? and so on). But you have probably thought about this a lot more than I have. I do see the appeal of a plug-and-play solution. I had considered designing a replacement head-unit with ANT/BLE built-in at one point (not based on FortiusANT, custom hardware and firmware). Of course that is a much more ambitious project and in the end I concluded that it would probably not be commercially viable. |
I think the ANT code gets overwhelmed with too many packets (the dongle itself can handle it fine, it is just the implementation). So the problem is not with the steering code directly, rather it exposes problems with the ANT dongle code. I have had a closer look and there are actually multiple issues that can potentially result in dropping data:
1 is trivial. 2, 3 and 4 can all be fixed by having a thread running in the background, reading into a buffer. And then just having Read take bytes from that buffer. It is what everyone else does. I'll take a stab at it this weekend. I suspect that 2 may explain some of the CYCPLUS problems as well, if the CYCPLUS has a smaller buffer and doesn't handle overflow.
The calibration routine looks at the last 5 values. Usually that is about 1.25s but with -A it is much shorter, so calibration may be updated even if the angle is not stable. I still need to implement a dynamic window length. |
Well practice shows it's plug-and-play and no worries after. |
I hope following observations help
This is not necessarily true; FortiusAnt data is transmitted every QuarterSecond, the ANTdongle is read every cycle of the main loop. The main loop runs at 0.02s or 0.25s interval, depending on the PedalStrokeAnalysis. I think I have not seen the 1000bytes being filled. If more data than 900 bytes is received a message is given, which I never see happening. Also when incomplete messages are received, a warning is printed on the console, something I do not see either. Dongle.Read messages:
In the comment on Regarding the program's architecture; the loop has evolved from antifiers loop, which was single threaded. John/antifier would certainly recognize the setup, even though it has changed a lot. Creating FortiusAnt caused me to learn ANT and python, perhaps with today's knowledge I would build differently. But hey, isn't that always the case. Since the code works on the systems and platforms we support, I would be shy to redesign.
I would certainly agree to that. |
I hope following observations help
This is not necessarily true; FortiusAnt data is transmitted every QuarterSecond, the ANTdongle is read every cycle of the main loop. The main loop runs at 0.02s or 0.25s interval, depending on the PedalStrokeAnalysis. I think I have not seen the 1000bytes being filled. If more data than 900 bytes is received a message is given, which I never see happening. Also when incomplete messages are received, a warning is printed on the console, something I do not see either. In the comment on "def __ReadAndRetry(self, timeout):" I see I have been studing the subject resulting in the current settings. I doubt a separate thread (with the required overhead) would help. Regarding the program's architecture; the loop has evolved from antifiers loop, which was single threaded. John/antifier would certainly recognize the setup, even though it has changed a lot. Creating FortiusAnt caused me to learn ANT and python, perhaps with today's knowledge I would build differently. But hey, isn't that always the case. Since the code works on the systems and platforms we support, I would be shy to redesign.
I would certainly agree to that. |
Perhaps this is the key thing; how many packets does the Blacktrack send? It should NOT cause a big stream of packets, as far as I understand ANT, from the nature of the protocol. |
@WouterJD The Blacktrack natively sends 16Hz which made it completely unusable. I have actually reduced the channel to 4Hz already, so it only receives every 4th message. Now I only have occasional drops if an ANT trainer is used at the same time. Without an ANT trainer the Blacktrack works fine. So it is a question of traffic. (This is all with a Garmin ANTUSB-m.) I am aware that the main loop can run faster (with pedal stroke analysis) but I believe the ANT dongle is still only read every 0.25s. That is only part of the problem though. I have seen your comments about the time-out and that you have found 20ms to work. On your PC it might even work with a Vortex and Blacktrack (or not). On mine it doesn't. The point is that there is no guarantee. There may be a Windows Update tomorrow that breaks it for you. The libusb-win32 documentation states:
As a solution they suggest:
Option 1 is not available in Python. Option 2 is what I usually see in other software that uses libusb. I am very confident an extra thread would resolve the problem and improve overall stability. I don't see a good alternative either. And it is not as bad as you might think. There will be no change to the main loop and the overall architecture, only antDongle.py. The read buffer size: yes, I have only seen the "too much data" error 2-3 times ever. But it is easy to change, so might as well do it right now. If you run the debug version of libusb-win32, it actually produces a warning message about this on every read. I understand why FortiusANT is the way it is and I can relate (I also admit is is sometimes frustrating). I believe it is not just a question of experience, it also grew a lot bigger than was originally intended. That sort of thing happens a lot. As a rule, I try to improve things I need to change anyway but not make unnecessary breaking changes elsewhere. I am happy to hear that the FAlink is working out for you. My ultimate goal is to make the Windows version almost as easy to use. But that is in the future. |
@switchabl thanks for detailed response. You may probably be right, there should be a thread that's permanently be available to receive data from ANT. FortiusAnt is now headunit-centric, with main loop to read data from the head unit. Even when there is no head unit. The ANTloop is active only when the Fortius calibration is completed. Adding an ANT thread would be correct for the ANTdevice, but actually a bigger redesign of the main loop would be required. Happy to read your ideas on the subject, perhaps finalize steering first (knowing the loop could be improved) so we have a stable baseline and the concentrate on the ANTloop only in a next step. I would recommend not to do it in this update, which is open for 10 months now |
Of course ANT-handing improvement remains on my mind. How would the ANT-loop look like, if not as below?
#341 created to further discuss the subject |
Hi @switchabl do you plan finalizing steering? Can I assist here? Would be a nice Xmas present to release it. |
Agree, no rush. Thanks for the hard work and stay healthy👍 |
Hi @switchabl, can we do something to get this stuff merged? I am kind of lost now ;-) |
@frankhommers does the branch from @switchabl work? |
I haven't tried yet. If I do, will that speed things up? |
It sure would; knowing that the steering device works for you is always an advantage. |
I have merged switchabl's branch into your master branch. I don't know what I need to do to make it work. I don't see the message "Tacx BlackTrack connected" appearing at all. |
Perhaps it's not the github correct way of working, and appologies for that if so. Therefore this PR is closed, I will create a new PR for the steering branch. Guys thanks for the work and support! |
Steering interface on BLE
This pull request adds initial support for steering in Zwift as described in #152.
Start FortiusANT with the
--steering
option on the command line. FortiusANT will advertise a steering characteristic which Zwift can connect to. When calibrating the rolling resistance, the steering interface is also calibrated, you get hints from the GUI. After you started pedalling, the GUI tells you to steer right, then middle.Please review my changes and comment where needed.