JoystickGremlin
JoystickGremlin copied to clipboard
Altering virtual axis input via plugins
I am trying to create a plugin that works as a kind of moving deadzone to counter the at times unstable output of my X56 rotaries. I based this on a previous edit of yours being a moving average, however I cannot seem to find a way about "catching" the unwanted signals before they are already put out. From my very limited understanding of Python (C# guy), I can hook onto the callback of an axis input and spawn a thread that regularly updates the value. Even with an update rate of 10 milliseconds the unwanted signal gets through still. Is there any way to alter a physical axis input before it reaches the virtual output axis?
I'm not really clear what you actually want to do, but some information.
- physical events are only forwarded if you instruct Gremlin to do so
- spawning a thread in response to axis input seems like a horrible idea that likely results in tons of threads fighting each other
- if you attempt to "overwrite" values cause by noise then this will never work, you will have to have a single callback that receives all physical input and decides what to do, trying to suppress, outpace, or similar ideas will not work
So my problem is that I have a physical input that occasionally starts to jitter within a very small margin of +- 0.02, which is extremely annoying when binding it to e.g. the in-game zoom. What I would like to achieve is to have a plugin detect and smooth out this jittering before the physical input is processed to the virtual axis.
Upon another inspection of my setup I think I have identified the issue: While using the attached script to filter the physical Z axis to the virtual one, I still had the physical z axis set up to remap to the virtual z axis, so I assume my moving deadzone plugin was fighting with the remapped input. The code below now seems to do as I wished for.
from gremlin.user_plugin import *
mode = ModeVariable("Mode", "The mode in which to use this mapping")
virtual_axis = VirtualInputVariable(
"Virtual output axis",
"The vJoy axis to send the filtered output to.",
[gremlin.common.InputType.JoystickAxis]
)
physical_axis = PhysicalInputVariable(
"Physical input axis",
"The physical input axis being filtered.",
[gremlin.common.InputType.JoystickAxis]
)
deadzone = IntegerVariable(
"Deadzone size",
"Size of the deadzone around the cached value.",
5,
0,
100
)
# Decorator for the physical axis
dec_physical_axis = physical_axis.create_decorator(mode.value)
# Global variables
# The cached physical input
g_cached_value = 0.0
# The current input
g_current_value = 0.0
g_vjoy = gremlin.joystick_handling.VJoyProxy()
def apply_deadzone():
global g_current_value, g_cached_value
if(abs(g_current_value - g_cached_value) > deadzone.value/100):
g_cached_value = g_current_value
return g_cached_value
def update_vjoy():
global g_vjoy
g_vjoy[virtual_axis.vjoy_id].axis(virtual_axis.input_id).value = apply_deadzone()
@dec_physical_axis.axis(physical_axis.input_id)
def axis_cb(event):
global g_current_value
g_current_value = event.value
update_vjoy()