Page 1 of 1

joystick centering

Posted: Wed Sep 03, 2008 6:52 pm
by CmdrLUke
My crappy joystick is always slghtly off center, which makes flying frustrating. Calibrating with the OS control panel doesn't help. It frequently is 5-6% off center, and the center changes. I applied a fix that seems to work great for me, in file PlayerEntityControls.m, function

Code: Select all

- (void) pollFlightArrowKeyControls:(double)delta_t
in if clause:

Code: Select all

	else if(numSticks)

Code: Select all

		// consider any value within between -0.06 and 0.06 as centered
		// but only when both axes are centered
		// 
		// 
		if ( ((virtualStick.x > -0.06) && (virtualStick.x < 0.06)) &&
		     ((virtualStick.y > -0.06) && (virtualStick.y < 0.06)) )
		{
			virtualStick.x = 0.0;
			virtualStick.y = 0.0;
		}
It works great, I'm MUCH happier now.

The best thing to do would be to wrap this up in a real game option in the menu system and read the epsilon centering value from a .plist file. If someone could point me at the code for the game menu system I could take a shot at doing this.

Awesome Game == Awesome. Open Source Awesome Game == The Best There is. Thanks to all for making oolite available and open source!

Posted: Thu Sep 04, 2008 2:14 pm
by Cmdr Wyvern
I too suffer from the joystick centering issue, a bug which has been around since at least version 1.65. It seems the bug only affects oolite on windows; the joystick centers perfectly in Linux, yet drifts uncontrollably in windows. The bug is a pet peeve, more irritating than trumbles in the pantry.

I admit I don't know the code too well, yet am eager to incorporate your patch and squash the lack-of centering bug once and for all.

Where and how exactly did you insert this string of code?
Examples, please. TIA!

Posted: Thu Sep 04, 2008 2:33 pm
by another_commander
I'm not even sure this is about the same thing (tough to tell when one cannot check any changes in code), but in PlayerEntityControls.m, there is the - (void) pollFlightArrowKeyControls:(double)delta_t method. This method contains this code at the beginning:

Code: Select all

- (void) pollFlightArrowKeyControls:(double)delta_t
{
	MyOpenGLView	*gameView = [UNIVERSE gameView];
	NSPoint			virtualStick = NSZeroPoint;
	double			reqYaw = 0.0;
#define			kDeadZone 0.02  <<<<<<< HEY! Check this out!
	
	// TODO: Rework who owns the stick.
	if(!stickHandler)
	{
		stickHandler=[gameView getStickHandler];
	}
	numSticks=[stickHandler getNumSticks];
Can any of you owners of both SVN access and joystick controllers, try changing the kDeadZone define from 0.02 to maybe 0.06 and report how it performs? It could be just that simple, you know.

Posted: Thu Sep 04, 2008 5:41 pm
by CmdrLUke
another_commander wrote:
I'm not even sure this is about the same thing (tough to tell when one cannot check any changes in code), but in PlayerEntityControls.m, there is the - (void) pollFlightArrowKeyControls:(double)delta_t method. This method contains this code at the beginning:

Code: Select all

- (void) pollFlightArrowKeyControls:(double)delta_t
{
	MyOpenGLView	*gameView = [UNIVERSE gameView];
	NSPoint			virtualStick = NSZeroPoint;
	double			reqYaw = 0.0;
#define			kDeadZone 0.02  <<<<<<< HEY! Check this out!
	
	// TODO: Rework who owns the stick.
	if(!stickHandler)
	{
		stickHandler=[gameView getStickHandler];
	}
	numSticks=[stickHandler getNumSticks];
Can any of you owners of both SVN access and joystick controllers, try changing the kDeadZone define from 0.02 to maybe 0.06 and report how it performs? It could be just that simple, you know.
DOH! How did I miss that? Indeed changing just

Code: Select all

#define			kDeadZone 0.02

to

Code: Select all

#define			kDeadZone 0.06
works just as well as my change, and it's much smaller & simpler, too.

Cmdr Wyvern, this fix requires building from the source code. If you're already set up to do that, just apply to above change of "kDeadZone" in the file PlayerEntityControls.m and rebuild, it should be that simple.

Posted: Fri Sep 05, 2008 1:14 am
by Cmdr Wyvern
I'm using an SVN build, but not the latest. The latest would start, run a few seconds, then quit itself, leaving no reason for the auto-quit in the sderr file.

In the build I'm using, tweaking kdeadzone had no noticeable effect at all. I tweaked it all the way to 10.0 before I gave up that direction and put it back on 0.02.

Here's the working solution I landed on.

In JoystickHandler.h:

Code: Select all

#define STICK_NORMALDIV 40960
That reduces the joystick axis sensitivity by 25%. It works out well; recent builds seem to be very oversensitive to joystick inputs compared to version 1.65.

In PlayerEntityControls.m, a variation of Luke's deadzone code, which works. Note I applied the code to the yaw axis as well; I have a 4-axis HOTAS stick, and I use "wing commander" flight control settings - pitch and yaw on the stick, roll on the rudder rocker, and speed on the throttle.

Code: Select all

	else if(numSticks)
	{
		virtualStick=[stickHandler getRollPitchAxis];
		if(virtualStick.x == STICK_AXISUNASSIGNED ||
		   virtualStick.y == STICK_AXISUNASSIGNED)
		{
			// Not assigned - set to zero.
			virtualStick.x=0;
			virtualStick.y=0;
		}
		if ( ((virtualStick.x > -0.04) && (virtualStick.x < 0.04)) &&
           ((virtualStick.y > -0.04) && (virtualStick.y < 0.04)) )
        {
         virtualStick.x = 0.0;
         virtualStick.y = 0.0;
        } 
		else if(virtualStick.x != 0 ||
				virtualStick.y != 0)
		{
			// cancel keyboard override, stick has been waggled
			keyboardRollPitchOverride=NO;
		}
		// handle yaw separately from pitch/roll
		reqYaw = [stickHandler getAxisState: AXIS_YAW];
		if(reqYaw == STICK_AXISUNASSIGNED)
		{
			reqYaw=0;
		}
		if ( ((reqYaw > -0.04) && (reqYaw < 0.04)) )
        {
         reqYaw = 0.0;
        } 
These alterations virtually eliminated the drift. My joystick software kills what tiny bit remains with slight axis trim settings.

Posted: Fri Sep 05, 2008 1:47 am
by CmdrLUke
Glad you got rid of your drift. It was killing the game for me so I'm glad I was able to pach it.

Posted: Sun Sep 07, 2008 3:09 am
by CmdrLUke
DOH! How did I miss that? Indeed changing just

Code: Select all

#define			kDeadZone 0.02

to

Code: Select all

#define			kDeadZone 0.06
works just as well as my change, and it's much smaller & simpler, too.

Cmdr Wyvern, this fix requires building from the source code. If you're already set up to do that, just apply to above change of "kDeadZone" in the file PlayerEntityControls.m and rebuild, it should be that simple.
It turns out changing the deadZone #define is not sufficient to fix joystick drift. The deadZone check must be applied before any change in pitch/roll is done. My original changes were in the correct place -- I reenabled them, and added some code to print the joystick position in the FPS hud, and I could see that without my fix, joystick center drift would end up moving the ship, while with my code, the ship position stayed rock solid centered.

Posted: Sun Sep 07, 2008 8:52 am
by another_commander
OK, in this case, I am thinking of modyfying the pollFlightArrowKeyControls method as follows:

Code: Select all

- (void) pollFlightArrowKeyControls:(double)delta_t
{
	MyOpenGLView	*gameView = [UNIVERSE gameView];
	NSPoint		virtualStick = NSZeroPoint;
	double		reqYaw = 0.0;
	double		kDeadZone = STICK_DEADZONE;
	
	// TODO: Rework who owns the stick.
	if(!stickHandler)
	{
		stickHandler=[gameView getStickHandler];
	}
	numSticks=[stickHandler getNumSticks];
	
	/*	DJS: Handle inputs on the joy roll/pitch axis.
	 Mouse control on takes precidence over joysticks.
	 We have to assume the player has a reason for switching mouse
	 control on if they have a joystick - let them do it. */
	if(mouse_control_on)
	{
		virtualStick=[gameView virtualJoystickPosition];
		double sensitivity = 2.0;
		virtualStick.x *= sensitivity;
		virtualStick.y *= sensitivity;
	}
	else if(numSticks)
	{
		virtualStick=[stickHandler getRollPitchAxis];
		if((virtualStick.x == STICK_AXISUNASSIGNED ||
		   virtualStick.y == STICK_AXISUNASSIGNED) ||
		   (virtualStick.x > -kDeadZone && virtualStick.x < kDeadZone) &&
		   (virtualStick.y > -kDeadZone && virtualStick.y < kDeadZone))
		{
			// Not assigned or deadzoned - set to zero.
			virtualStick.x=0;
			virtualStick.y=0;
		}
		else if(virtualStick.x != 0 ||
				virtualStick.y != 0)
		{
			// cancel keyboard override, stick has been waggled
			keyboardRollPitchOverride=NO;
		}
		// handle yaw separately from pitch/roll
		reqYaw = [stickHandler getAxisState: AXIS_YAW];
		if((reqYaw == STICK_AXISUNASSIGNED) || (reqYaw > -kDeadZone && reqYaw < kDeadZone))
		{
			// Not assigned or deadzoned - set to zero.
			reqYaw=0;
		}
		else if(reqYaw != 0)
		{
			// cancel keyboard override, stick has been waggled
			keyboardYawOverride=NO;
		}
	}
<<<<<< Rest of method snipped >>>>>>>
STICK_DEADZONE is now a #define in JoystcikHandler.h defaulting to 0.05. Can you guys please test it and let me know if it works well like this? If it is OK, it will go on SVN for 1.72.

Posted: Sun Sep 07, 2008 9:54 am
by CmdrLUke
OK, the deadZone check is in the right place. Using my hack to put the virtualStick.x and virtualStick.y values in the "FPS" (shift-F) HUD, I see that 0.05 should work for me. If I tap my joystick in the Y axis VERY lightly I get a value stuck at just over 0.06 sometimes, but I don't usually tap the stick that lightly, and 0.05 should work for me fine I think.

Wouldn't it be best, though, to let a value from the player entitty (from the player file) ovreride the default deadzone in case he has a crappier joystick than mine?

Posted: Sun Sep 07, 2008 9:56 am
by another_commander
CmdrLUke wrote:
Wouldn't it be best, though, to let a value from the player entitty (from the player file) ovreride the default deadzone in case he has a crappier joystick than mine?
Definitely, but let's just take it one step at a time ;-)

Posted: Sun Sep 07, 2008 2:41 pm
by Cmdr Wyvern
CmdrLUke wrote:
Wouldn't it be best, though, to let a value from the player entitty (from the player file) ovreride the default deadzone in case he has a crappier joystick than mine?
The issue has little or nothing to do with the quality of the joystick. You could plug the same stick into a Linux box or a Mac, and find it has perfect - or nearly so - centering.

The center drift issue only affects windows, and it wouldn't matter if the stick is a budget model or a top of the line CH Flightstick system, it would drift in Oolite. I suspect the issue has something to do with the way SDL interacts with the M$ (buggy) implementation of HAL, and/or (buggier) directinput.

However, I do agree that softcoded, user-adjustable sensitivity and deadzone settings would be a good thing.

Posted: Sun Sep 07, 2008 4:38 pm
by CmdrLUke
Cmdr Wyvern wrote:
CmdrLUke wrote:
Wouldn't it be best, though, to let a value from the player entitty (from the player file) ovreride the default deadzone in case he has a crappier joystick than mine?
The issue has little or nothing to do with the quality of the joystick. You could plug the same stick into a Linux box or a Mac, and find it has perfect - or nearly so - centering.

The center drift issue only affects windows, and it wouldn't matter if the stick is a budget model or a top of the line CH Flightstick system, it would drift in Oolite. I suspect the issue has something to do with the way SDL interacts with the M$ (buggy) implementation of HAL, and/or (buggier) directinput.
This subject has piqued my professional curiosity :). My problem exists outside of SDL, I see the unreliable center in the joystick calibration dialog when I turn on "show raw data". The only thing that I see that could differentiate centering behavior between different OS/controller software is if the controller software builds in a larger or smaller deadZone itself. Since this must be a very common problem with joysticks, maybe that's how Mac/Linux do it, or how MS doesn't.

Posted: Fri Sep 19, 2008 11:31 am
by 0235
my joystick has the controll collum (with 15 buttons) and a seperate throttle, (with 15 buttons) will it work with Oolite v 1.65, and how do i get it to work?