WhiteMagic / JoystickGremlin

A tool for configuring and managing joystick devices.
http://whitemagic.github.io/JoystickGremlin/
GNU General Public License v3.0
313 stars 45 forks source link

[Class MergeAxis] Initial self.axis_values causing inconsistent vJoy outputs #478

Open Drakehinst opened 1 year ago

Drakehinst commented 1 year ago

Hi!

I've been using Joystick Gremlin (R13.3) for around 6 months and helping people configuring a wide variety a peripherals, and I have noticed an issue faced by many users with the Merge Axis feature, with inconsistent output values using either merge operations. I am personally using a Thrustmaster T.Flight Rudder Pedals and will be describing the issue for this model specifically, but the issue so far occurred for several other models.

A. Reproducing the issue

  1. Using the Thrustmaster T.Flight Rudder Pedals, configure the Merge Axis as follows:
    • Lower Half: T-Rudder / Y Axis
    • Upper Half: T-Rudder / X Axis
    • Merge Axis: vJoy Device 1 / X Axis
    • Operation: Average
  2. Activate the profile
  3. Open the Input Viewer. In T-Rudder show Axes - Current and in vJoy Device # 1 show Axes - Current.
  4. Before pressing any pedal, the viewer shows:
    • T-Rudder - Axis 1 = 100%
    • T-Rudders - Axis 2 = 100%
    • vJoy Device # 1 - Axis 1 = 0%
  5. Press the right pedal (T-Rudder - X Axis) down as far as it will go.
  6. The viewer now shows:
    • T-Rudder - Axis 1 = -100%
    • T-Rudders - Axis 2 = 100%
    • vJoy Device # 1 - Axis 1 = 50% . However, the expected average value would be [100% - (-100%)] / 2 = 100%, i.e. the maximum forward throttle
  7. Keep the right pedal pressed down, and slightly press the left pedal (T-Rudder - Y Axis). The value of vJoy Device # 1 - Axis 1 jumps (!) from 50% to ~99%, the expected average value.
  8. Keep the right pedal pressed down, and press down the left pedal down as far as it will go. The expected outcome is a standstill of the vehicle.
  9. The viewer now shows:
    • T-Rudder - Axis 1 = -100%
    • T-Rudders - Axis 2 = -100%
    • vJoy Device # 1 - Axis 1 = 0% . This is the expected average value [-100% - (-100%)] / 2 = 0%

B. Workaround

The pedals need to be reset each time after activating a profile by pressing down both pedals before the game is loaded. Otherwise, wrong outputs values will be sent by the merged axis on the vJoy upon the first use in-game. Failure to perform this manual reset may cause, in games like Star Citizen, ship crashes in hangars when pressing the right pedal down (throttle forward) to move forward, then trying to slow down by pressing left pedal down (throttle backward) which makes the throttle suddenly bump up to 100%.

I could reproduce the issue with a Thrustmaster Pendular Rudder, and a Star Citizen streamer using a Thrustmaster T3PA Pro seems to be having the same issue and the same workaround. Similar issues occur when using the other merge operations.

C. Suggested Solution

I could narrow down the issue to the class gremlin.code_runner.MergeAxis, and more specifically in the line responsible for the axis values initialization in __init__(): self.axis_values = [0.0, 0.0]

These values do not match the actual values observed on the axes of the physical rudder before any press on the pedals. For both tested rudder models, the merge would only work if the initial axis values were: self.axis_values = [1.0, 1.0]

I wrote a plugin that reproduces exactly the behavior of the Merge Axis feature, with initial axes values at 100%, and the issue was solved.

Would it be possible to add a form field in the Merge Axis menu to specify the released values for either axis of the lower and upper half?

Thanks a lot in advance for your consideration, and thank you even more for creating such an awesome piece of software! :)

WhiteMagic commented 1 year ago

That's a generally hard issue to address in a general way, mainly because I cannot reliably ensure to know the state of axes upon launch. For that reason, the merge system assumes an initial value that, for many devices, might represent an "at rest" position. Pedals and throttles are a major exception to these assumed values, though even there it is often not clear what value would be a valid "at rest" value.

Technically adding the field is possible, however, as I'm not updating the R13 code base anymore, this won't happen from my side. In R14, there won't be (hopefully) this arbitrary split of certain actions into their own menus, so the entire merge axis aspect will be reworked. What this means for default initial values is still unclear, but it will at least adhere to whatever the global behavior in Gremlin.

Drakehinst commented 1 year ago

Thanks for your answer! I totally understand why this would be tricky to attempt unifying all possible use cases for axes merging, and that working on R13 would be counterproductive since you are introducing important architectural changes in R14.

I would actually be interested in getting to know your code better, so I may perhaps contribute to the project in the future. And even though R14 is the way forward, I would find it interesting to be able to try my hand at "modding" R13 so to speak, beyond the development of plugins. So far, however, I have been unable to get a working python environment for building R13. Would you be able to share with me a requirements.txt file and the Python version you have been using? (I'm assuming it's 3.7)

WhiteMagic commented 1 year ago

Some of the components used are

I don't remember the exact version and for Python 3.7 might work. One aspect to remember though is that this needs to be a 32bit Python version as at that time I was still using 32bit libraries for backwards compatibilities. The pypiwin package also could be troublesome at times. These packages and their prerequisites should be most of what is needed and usually if not the import error should give a rather clear hint as to what is missing.

Drakehinst commented 1 year ago

Thanks for the additional details! I eventually managed to get an environment working with Python 3.6.8 and could add fields for Initial Axis Values for each physical device in the Settings tab.

So far it solved the issue for a few users, I am letting more people test it out before calling it a fix. :)