Jump to content

Joystick Control Feedback - 1.3.306


71 replies to this topic

#41 Foust

    Member

  • PipPipPipPipPipPip
  • Legendary Founder
  • Legendary Founder
  • 394 posts
  • LocationKentucky

Posted 16 July 2014 - 12:13 PM

View PostevilC, on 16 July 2014 - 11:46 AM, said:

axis position is effectively a percentage of available deflection. They are one and the same.


I disagree. Axis position is a specific value. You can translate that value to a percentage of that axis, but there is a specific value. My joystick reports a value from 0 to 16383. Round that to 16000. Centered my stick would report 8000.

With absolute position we get a x and y value out of the stick, that translates to a x and y value for the cross hair. It is like using a touch screen, where you put your finger is where the cursor is.

Let's say we know the value of a centered torso cursor position, say 0,0. We know that my centered stick has a value of 8000,8000. We have mapped a centered screen of 0,0 to my centered sticks values of 8000,8000. This is the current behavior under absolute positioning. If I move my stick such that I am now reporting 12000,0 that is going to translate to a screen position, and the rate of traversal for the mech will determine how fast the cross hair moves to that position.

Right now it seems like the sensitivity slider is acting as you are describing, as a linear adjustment to the range of the axis. It is behaving exactly as your math indicates such that you either lose torso movement or waste deflection. We agree that this is bad.

What I want to see instead is the sensitivity slider acting as a variable to the rate of traversal.

#42 evilC

    Member

  • PipPipPipPipPipPipPipPip
  • Legendary Founder
  • Legendary Founder
  • 1,298 posts
  • LocationLondon, UK

Posted 16 July 2014 - 12:47 PM

OK, I see what you are saying, though I don't think it would work the way you think it would.
I am pretty sure that they implemented this, it would only make the input feel laggy, it would not change how sensitive it felt.

BTW, your stick will report 0-65535, as all joystick values in windows are represented by a 16-bit number, regardless of how many bits accuracy your joystick uses internally.

Edited by evilC, 16 July 2014 - 12:50 PM.


#43 Foust

    Member

  • PipPipPipPipPipPip
  • Legendary Founder
  • Legendary Founder
  • 394 posts
  • LocationKentucky

Posted 16 July 2014 - 01:18 PM

It would at least match the rotation speed of the mech, so a jenner is going to feel more sensitive than an atlas. With this you would only be able to turn down the sensitivity, you would be locked in at the mechs maximum. The big advantage is consistency. You know that if the stick if full right, once the torso catches up, your full right. Depending on the mech and the engine, rate/s matches torso rotation. This would just allow you to tone down that spin if its a bit much to take.

You are right, TARGETs device analyzer shows the 16383 as the raw values, and the 65535 on the combined axis.

Sorry it took so long to get my point across.

#44 Jayson Youngblood

    Member

  • Pip
  • Ace Of Spades
  • Ace Of Spades
  • 13 posts

Posted 17 July 2014 - 01:24 AM

Thanks for your work on the joystick controls, Nikolai. I'm also experiencing trouble with the deadzone not being adjustable. And yes, it seems like it's stuck at a value that is a bit to low for me. I'm using my joystick as throttle on the y-axis and entire mech turning on the x-axis. The throttle now has more deadzone than it used to. but the turning is too sensitive, where without meaning to turn, it easily turns. Adjusting the deadzone in the UI does nothing.

#45 Grits N Gravy

    Member

  • PipPipPipPipPipPip
  • 287 posts

Posted 17 July 2014 - 08:49 PM

DirectInput is capable of reporting any range of motion for a joystick and translating it. Thus it's possible for 8 bit stick, (range 0 to 255), to report in a 16 bit format unsigned ( 0 to 65,535,) or signed format ( -32768 to 32,768)

http://msdn.microsof...v=vs.85%29.aspx

The way the system should work, is that each integer of joystick output should correspond to a position of the mech's torso. Thus, in a 16 bit unsigned reporting system, with a mech that is capable of rotating 90 degrees to each side. A joystick reporting a value 65,535, should cause the mech's torso to rotate 90 degrees. A report of 49151.34, should rotate the torso to 45 degrees. With a report of 32767.5 being center.


Each degree of rotation per joystick reporting number, is a function of the mech's total possible amount of rotation. Thus a mech which can move it's torso 180 degrees, would move more degrees per joystick reporting number than a mech which can only rotate 90 degrees

49151.34 = 45 degrees of mech rotation; for a mech capable of a total rotation of 90 degrees
49151.34 = 90 degrees of mech rotation; for a mech capable of a total rotation of 180 degrees


546.12 = 1 degree of rotation; for a mech capable of a total rotation of 90 degrees
273.06 = 1 degree of rotation; for a mech capable of a total rotation of 180 degrees

At a joystick report of 10,000:

180 degree rotation capable mech
36.62 degree rotation of the torso

90 degree rotation capable mech
18.31 degree rotation of the torso

The major problem with the system now is that, joystick outputs are not proportional to torso movements. A half deflection of the stick does not correspond to half the torso twist of the mech. Which is the true definition of absolute input control. This is a function of Cryengine reading the reporting position as very large numbers and not handling them well or scaling them proportionally.

What happens is cryengine is setup to read a number as max input. It's probably very low. Thus any report over the max is read as maximum. Which is a problem if sticks are reporting in a 16 bit format via Directinput. As a one third deflection of the stick reports a position of 43,580.11 or 21,953.88 (depending on a left or right defelection) Which from my cursory testing is over the max input in cryengine, thus resulting in a full rotation of the mech's torso.

Even with the large deadzone, that seem to be implemented now, movements from full deflection to half are not possible due to the discrepancy between what cryengine reads as max and what the stick reports as max.

Changing the sensitivity doesn't make the system more useable because it simply caps the max output. The sensitivity setting simply applies a transformation which multiplies the output by a decimal to reduce the reporting position, f(x)=(x*.a), where a is the sensitivity setting.

Thus a sensitivity setting of .02 transforms a joystick output of 65,535 to 1,310.7 and one third deflection of the stick, which reports 43,580.77, is transformed 871.61. So it gives the appearance of increase control-ability, but in fact just mitigates the cryengine position reporting discrepancy by reducing the reported postion to an interger which is within the cryengine reporting range. The same behavior is exhibited by the mouse too, increasing the DPI of the mouse and changing the sensitivity results in the same behavior.

The problem seems fixable though. You would have to get into the C of the CryInput though and maybe tweak the input listener too, in order to adjust the reporting range. Or find away to bypass cryInput and work through DirectInput.

Though, even with a working absolute system, you will need more than a "sensitivity" setting to make absolute inputs work well. The first and probably most important would be what's called a non linearity setting. This would transform the output of stick to a more non linear response by means of a power law. Thus one would have a finer control around the center of the stick, while position reports toward the edge of the joystick would result in greater movement of the mech torso. This function works well f(x) = a*x^3 + (1-a)*x . Where a is the power of the curve set by the player. A works best when is less than 0, and 0 results a normal linear response.


Another input adjustment that will allow players to tweak an absolute control to their own liking would be an axis saturation control. Which is a transformation that functions to alter the min and max input outputs of a the stick. It differs from a sensitivity setting which limits the output to a fixed number.

For example, a mech which can turn 180 degrees. With a sensitivity setting of .5, if the joystick is fully deflected, say to a reporting position of 256, The mech will only turn 90 degrees, as the sensitivity adjustment caps the output to 128. A saturation setting of 2, means that at 128 reporting position of the stick turns the mech 180 degrees. As the 128 is transformed to 256. It's a simple multiplicative transformation. f(x)=(x*a) where a is the saturation setting chosen by the player.

This can be helpful because it means one doesn't full deflect the stick to rotate the mech. Which would be uncomfortable for running a light mech that's either constantly turning it's torso or has the torso constantly fully rotated.

Also be forewarned about testing with a xbox 360 controller as it use XInput which differs from DirectInput and is really only used with 360 Controller. You may need to check how cryinput is interfacing the joysticks too. If it's using Xinput than pretty much everything other than a 360 contronller won't work. Though you can use both API's simultaneously.
http://msdn.microsof...v=vs.85%29.aspx

Hope this helpful I was going to get into how to handel traverse speeds but this is getting long, (hint, use f(x) = a*x^3 + (1-a)*x; where f(x)=Rotation speed and a is derived on the diffrence in the joystick postion between 2 reports. )

EDITED: to correct signed 16 bit integers.

Edited by Grits N Gravy, 18 July 2014 - 02:48 PM.


#46 Grits N Gravy

    Member

  • PipPipPipPipPipPip
  • 287 posts

Posted 18 July 2014 - 12:10 AM

A bit of further testing tonight yielded some interesting results.

Utilizing "cl_joystick_gain=" in user.cfg makes the system a bit more usable, especially in 3'rd person. Settings between .4 and .5 seemed to yield the best results. Though there is an anomaly with the behavior. It seems when in cockpit view / first person, that setting has no effect. Though this setting also seems to limit total torso traverse when in 3'rd person.

So it seems, that gain may be functioning similar to the saturation settings I described in my post above. With a gain of .5, in 3'rd person, position of the torso seemed to mimic the position of the stick well. I'm not sure if this is a function of the gain setting limiting the total outputs of the joystick to something that is readable by cryengine. Or, if the setting simply provides a finer control by adjusting the output put of the stick via a power law transformation. Though I'm inclined to believe it's the former, due to the loss of range of motion on lower gain settings and using a negative setting causes the axis to invert.

The main issue remains fine control and this was unachievable with any setting or view point. Here you're dealing with the function of the Mech's rotation and its relation to joystick outputs. Simply put, very small displacements of the stick are needed to control the fine accuracy necessary for aiming, to small for what is achievable by most players and current hardware.

Based on a 16 bit reporting system and a mech which can rotate 90 degrees; For a player to move their torso 1 degree they would need to cause the stick to change reporting positions by 546.12, or roughly 1 percent of the sticks range of motion. That type of fine control isn't available due to noise in the electronics and player skill.

This issue is especially prevalent in the pitch angles due to the much lower rotation, thus micro deflections of the stick are needed to have control which is measurable in degrees. The problem is made worse by the fact that the smallest dead-zone setting of .01 often means that nothing gets reported till the stick is a position of 656. Which due to the low range of motion of the mech is full pitch. Thus you always tend to end up max pitch up or down.

To make the system useable you have to take the stick position and transform it into at least a 3 digit decimal. Where x=Reported position / maximum possible. Then apply the function f(x) = a*x^3 + (1-a)*x. Where x= Reported position/Max possible and a=power of transformation. Due to the nature of small range of motion and need for fine control you would need an "a" that is close to 1 and have the ability to set the curve power of at least 3 decimal places. ie .936. After the transformation has been applied, multiply that number by 32,767 to get the transformed position. Thus with an "a" of .936. a report of 43,580.77 ( a one third defection of the stick) is transformed to a reporting position of 34,208.747. Or for a mech capable of rotating 90 degrees, moving the stick a third of its defection would cause the mech to rotate 2.64 degrees.

As,
(43,580.77 - 32,767) / (65,535 - 32,767.5)
.936*.33^3 + (1-.9.36)*.33 = .044
1.044*32767.5 = 34208.747

Thus with an "a" of .972 and a mech that is capable of rotating 90 degrees; You get a control factor of individual degrees within the first third of the stick deflection.

Other than building look up tables for every mech that seems the only way to provide the necessary control to make absolute joysticks useable. and to have it scalable so that each mech can be tuned by the player.

EDITED: to correct signed 16 bit integers.

Edited by Grits N Gravy, 18 July 2014 - 12:14 PM.


#47 evilC

    Member

  • PipPipPipPipPipPipPipPip
  • Legendary Founder
  • Legendary Founder
  • 1,298 posts
  • LocationLondon, UK

Posted 18 July 2014 - 07:12 AM

FYI, AFAIK Windows stick inputs are 16-bit, but UNSIGNED 16-bit. -65535 to +65535 is a 32-bit range.

So 0 is full left, 32768 is middle and 65535 is full right.
That is not to say that signed integers are not the way to go - if you wish perform modifications on the axis values, it is much easier to center the scale on 0 (ie -32767 ... +32767)

Also be aware that most sticks are not 16-bit. Use the Joytester2 software to analyze your stick outputs - many cheaper sticks are only 8-bit resolution.
The highest resolution sticks I know of are 12-bit.
.

Edited by evilC, 18 July 2014 - 07:15 AM.


#48 Foust

    Member

  • PipPipPipPipPipPip
  • Legendary Founder
  • Legendary Founder
  • 394 posts
  • LocationKentucky

Posted 18 July 2014 - 07:14 AM

T16000M and Warthog are 16-bit

#49 evilC

    Member

  • PipPipPipPipPipPipPipPip
  • Legendary Founder
  • Legendary Founder
  • 1,298 posts
  • LocationLondon, UK

Posted 18 July 2014 - 07:19 AM

From the TM Website (http://www.thrustmas...roducts/t16000m)

Quote


Offer precision levels 256 times greater than current systems (i.e. a resolution attaining 16,000 x 16,000 values!)


Open to interpretation, but that sounds like 14-bit to me.
16000 x 16000 = 16000 per axis.

I guess they mean 16384, which is 14-bit.

But still, more than I thought it was.

Edited by evilC, 18 July 2014 - 07:20 AM.


#50 evilC

    Member

  • PipPipPipPipPipPipPipPip
  • Legendary Founder
  • Legendary Founder
  • 1,298 posts
  • LocationLondon, UK

Posted 18 July 2014 - 07:23 AM

However, the warthog does seem to be 16 bit:

http://www.thrustmas...s/hotas-warthog

16-bit resolution (65536 x 65536 values)

But the throttles are 14-bit

#51 Lightfoot

    Member

  • PipPipPipPipPipPipPipPipPipPip
  • Bad Company
  • Bad Company
  • 6,612 posts
  • LocationOlympus Mons

Posted 18 July 2014 - 08:08 AM

So Absolute would be for like Rudder Pedals?

Rudder deadzone equals Mech Turn?

My setup is to have RZ=Twist, X=Turn, Y=Tilt. With just the joystick controlling everything. That's the old standard setup from previous MechWarrior games and allows you to circle-strafe while aiming the torso.

The Sensitivity Slider for Controllers works very well. Finally able to aim with Turning the mech which was always very jumpy before. Turn is still a little stronger than the other Axii, but do-able.

#52 evilC

    Member

  • PipPipPipPipPipPipPipPip
  • Legendary Founder
  • Legendary Founder
  • 1,298 posts
  • LocationLondon, UK

Posted 18 July 2014 - 09:13 AM

The way to understand Absolute input is to think of it like this:

Absolute: Each position of the stick corresponds to exactly one position of the mech torso. Stick 50% to the right means the torso is twisted 50% to the right.

Relative: Each position of the stick corresponds to one twist rate. Stick 50% to the right means "please twist right at 50% speed".

So with relative, if you hold the stick 50% right, you will keep twisting right at 50% twist rate until the mech hits full right twist.

With Absolute, if you hold the stick 50% right, the torso will twist at full rate until it hits 50% of max twist right (ie 45deg right if in a mech with 90deg torso twist) and then stop.

Steering is a different matter.
There is no "max turn amount" as it were, as you can keep turning in any one direction for ever.

Thus, there is only relative mode for leg steering, as absolute would not make any sense.



The reason you want absolute mode with torso twist is this:

Target is to right of + crosshair - you twist right to aim at them - for both relative and absolute, the stick would be moved to right of center.

The Target then moves (or you twist a bit too much to the right), such that they are now to the left of the + crosshair.

Relative: You must move the stick PAST CENTER so that it is deflected left, in order to make the torso start twisting left.

Absolute: You only need to move the stick LESS RIGHT (ie move it a little bit to the left) to make the torso turn a little left.

So with relative, your input is "laggy" - the travel distance of the stick is way higher to alter the direction you are twisting.

This is the reason that stick aimers cannot possibly compete with mouse aimers without absolute stick aiming.

Edited by evilC, 18 July 2014 - 09:22 AM.


#53 Grits N Gravy

    Member

  • PipPipPipPipPipPip
  • 287 posts

Posted 18 July 2014 - 11:07 AM

View PostevilC, on 18 July 2014 - 07:12 AM, said:

FYI, AFAIK Windows stick inputs are 16-bit, but UNSIGNED 16-bit. -65535 to +65535 is a 32-bit range.

So 0 is full left, 32768 is middle and 65535 is full right.
That is not to say that signed integers are not the way to go - if you wish perform modifications on the axis values, it is much easier to center the scale on 0 (ie -32767 ... +32767)

Also be aware that most sticks are not 16-bit. Use the Joytester2 software to analyze your stick outputs - many cheaper sticks are only 8-bit resolution.
The highest resolution sticks I know of are 12-bit.
.

You're right about the signed, I went back and cleaned up the post. Though I think its best to handle any axis modification as a function. Probably in the order of sensitivity, saturation, and non linearity, other wise you would get a really wonky and unpredictable response out of the stick.

Edit:You're right about the signed be much easier to preform transforms on, Having gone through the previous post, some tweaking to the transformation is necessary to get it to spit out useful numbers in a unsigned format. Transformations are much easier to implement in a signed format.

Wouldn't 65,535 to -65353 be a 17 bit signed integer too? As 2^17 = 131072, and 65,535 * 2= 131072

The Saitek X-55 is also a 16 bit stick. Better micro controllers and the availability of hall sensor have really opened the market for 16 bit sticks. It's even possible to get a teensy 3.1 to use 16 bit resolutions, but do to voltage noise it's a not 100% accurate.

Edited by Grits N Gravy, 18 July 2014 - 12:20 PM.


#54 evilC

    Member

  • PipPipPipPipPipPipPipPip
  • Legendary Founder
  • Legendary Founder
  • 1,298 posts
  • LocationLondon, UK

Posted 18 July 2014 - 06:19 PM

View PostGrits N Gravy, on 18 July 2014 - 11:07 AM, said:

Wouldn't 65,535 to -65353 be a 17 bit signed integer too? As 2^17 = 131072, and 65,535 * 2= 131072

Hmm, I think you are right.
I am not that great at maths - by the sound of it, you are better than me :D
I only know what I know about this stuff through coding UJR - but that seems to work fine. If you are at all interested, here is the part of the source code where I do sensitivity adjustments etc. Any comments on the quality of my calculations gratefully received :D

#55 Grits N Gravy

    Member

  • PipPipPipPipPipPip
  • 287 posts

Posted 19 July 2014 - 12:47 PM

View PostevilC, on 18 July 2014 - 07:12 AM, said:

FYI, AFAIK Windows stick inputs are 16-bit, but UNSIGNED 16-bit. -65535 to +65535 is a 32-bit range.

The reporting format of the joystick is dependent on two factors. First is the HID descriptors of the device, which tells windows the reporting format of the stick, they can be signed or unsigned and in any integer. The next is via API used by the program to read the drivers and get the joystick data. The API can be DirectInput, RawInput, or Xinput.

DierctInput is configurable so that it can translate the formatting from the HID descriptors to whatever format the programer desires. When properly configured, with DirectInput, it's possible for an 8 bit stick to report in a 16 bit format, or any other that programer desires. The output from the API is ultimately what positional data the program gets.

In the case of cryengine there is another layer called CryInput, which is supposed to provide an abstraction and make it easier to handle input devices, but really seems to be the source of most of the troubles. The documentation of the feature is terrible, so lord knows what's going on with it. It causes all kinds of weird behavior as noted in my testing. CryInput was really just setup to make it easy for a developer to support controllers and very basic joystick functionality. The solution is either to dig into files and see how it works, or bypass it and use DirectInput directly. I'm pretty sure Star Citizen ended up bypassing CryInput. Input and netcode are really considered the main weaknesses of Cryengine.




View PostevilC, on 18 July 2014 - 07:12 AM, said:

Also be aware that most sticks are not 16-bit. Use the Joytester2 software to analyze your stick outputs - many cheaper sticks are only 8-bit resolution.
The highest resolution sticks I know of are 12-bit.
.

Because DirectInput allows one to set the reporting format of the stick. We do not need our in game positional format to match the native resolution of the stick. If we're using a 16 bit signed format to derive mech torso postion; All we have to do is, make sure that in DirectInput, our device is configured to output in the same format. So a 8 bit unsigned format would automatically converted into a 16 bit signed. It's very simple when you configure the device all you have to do is set the reporting range, no need for conversion formulas, the command is a "new InputRange(min,max)". This was done by microsoft so that there would be universal compatibility with all sticks no matter what the resolution or reporting range was to set by the HID.

Links:
HID Descriptors.

HID intro and Tutorial
http://eleccelerator...rt-descriptors/

Practical HID Exercise, changing a game port Stick to a USB HID device.
http://helmpcb.com/e...cs/usb-joystick

USB.org HID Descriptor Tool
http://www.usb.org/d...scriptor%20Tool

Direct Input
DirectInput Documentation From Microsoft
http://msdn.microsof...v=vs.85%29.aspx

Capturing Devices (how to set reporting range)
http://msdn.microsof...v=vs.85%29.aspx

Programing Guide:
http://msdn.microsof...v=vs.85%29.aspx

Raw Input:
http://msdn.microsof...v=vs.85%29.aspx

CryInput
Documentation:
http://docs.cryengin...DKDOC4/CryInput

Understanding movement in Cry Engine.
http://technicalgame...ode-moving.html

Vehicle movement Parameters:
http://docs.cryengin...-MovementParams

Edited by Grits N Gravy, 20 July 2014 - 06:12 PM.


#56 Lightfoot

    Member

  • PipPipPipPipPipPipPipPipPipPip
  • Bad Company
  • Bad Company
  • 6,612 posts
  • LocationOlympus Mons

Posted 20 July 2014 - 09:04 PM

Switched to Absolute inputs for my Logitech 3d Force Pro and it works very well. It didn't affect the tracking sensitivity I had set up, but it made the aiming alot steadier by eliminating some of the over-shoot that was there before. Tracking moving targets is a bit easier. Is this what is supposed to happen?

And one question. Which axis is Rudder? Turn or Twist?

Edit: Okay, actually I put the new user.cfg file I made in the wrong folder. In the right folder it makes the joystick move to whatever point the Joystick is set at, but this is too inaccurate for just a joystick, at least for me.

Edited by Lightfoot, 26 July 2014 - 02:28 PM.


#57 Hammerhai

    Member

  • PipPipPipPipPipPipPip
  • Bad Company
  • Bad Company
  • 999 posts

Posted 23 July 2014 - 08:36 AM

I read the first few posts and can only concur. As is it is unusable. And always will be due to your insistence on mouse e sports.

Battlegrid does not read my rudder input leading to the mech default to throttle z on the warthog and spinning in place.

On top of that using text input still halts my mech completely

Frankly, to have to have waited a year for this implementation. You might as well not have bothered... That earns a firm good grief what were you thinking.

Lightfoot it should be rZ for rudder. You can check with POSWDM which will tell you what axes your devices use.
In MWO it would be turn on the lower right hand side of the options screen

Edited by Hammerhai, 23 July 2014 - 08:44 AM.


#58 Hammerhai

    Member

  • PipPipPipPipPipPipPip
  • Bad Company
  • Bad Company
  • 999 posts

Posted 23 July 2014 - 08:50 AM

On a technical note. Using a signed integer drops the reported range from 0-65535 to +/- 32678, so both are 16 bit, just signed and unsigned respectively. (one bit gets sacrificed to be the sign flag, thus you lose one power of 2 on the result.)The next higher resolution would be 32 bit in nature if integer in most modern compilers

Edited by Hammerhai, 23 July 2014 - 09:13 AM.


#59 Hammerhai

    Member

  • PipPipPipPipPipPipPip
  • Bad Company
  • Bad Company
  • 999 posts

Posted 23 July 2014 - 09:09 AM

@Matthew Craig: I apologise for the tone of my feedback as I see you take making this better seriously. Thank you for that. +1

#60 evilC

    Member

  • PipPipPipPipPipPipPipPip
  • Legendary Founder
  • Legendary Founder
  • 1,298 posts
  • LocationLondon, UK

Posted 23 July 2014 - 10:55 AM

View PostHammerhai, on 23 July 2014 - 08:50 AM, said:

On a technical note. Using a signed integer drops the reported range from 0-65535 to +/- 32678, so both are 16 bit, just signed and unsigned respectively. (one bit gets sacrificed to be the sign flag, thus you lose one power of 2 on the result.)The next higher resolution would be 32 bit in nature if integer in most modern compilers

A signed integer does not use a bit solely to represent the sign.
One of the bits does *indicate* the sign, but that is simply because all numbers "above" a certain amount are signed the other way.

http://msdn.microsof...y/exx3b86w.aspx

short: 0-65535 (655,36 numbers including 0)

ushort: -32,768 to 32,767 (32768 + 32767 = 65535, plus 0 = 655,36 numbers)

Edited by evilC, 23 July 2014 - 10:59 AM.






5 user(s) are reading this topic

0 members, 5 guests, 0 anonymous users