Jump to content
TheHarvesteR

A fix for Full Axis throttle mapping

Recommended Posts

Hello,

Just wanted to share with everyone the solution I came up with for mapping the entire range of the throttle slider to the analogue throttle control in ArmA.

So this was the problem: ArmA does not read the full range of a joystick axis. It will only read either the bottom half or the top half of any axis (as in Joystick slider + or Joystick slider -). This isn't a problem for the usual stick movements, like pitch up/down and roll left/right, because these are axes that always return to center, and each half of the range is assigned to it's respective direction.

This is a problem with throttles though, because ArmA is assuming that the bottom half of the throttle range should be the airbrakes, and that's not realistic. The brakes should be activated by another button or a separate axis if one is available, and the Thrust (analogue) action should be controlled by the entire travel of the joystick's throttle axis.

So, how to get around this limitation? This is what I did:

Instead of mapping my throttle axis directly into the Thrust (analogue) command in ArmA, I'm using GlovePIE and PPJoy to correct the input before it reaches the ArmA command mapping.

So, this is how it works:

GlovePIE is a programmable input emulator. It can read input from devices like keyboard, mice and joysticks, then 'write' input to other devices, as keyboards, mice and virtual joysticks.

So that's where PPJoy comes in. It is a virtual joystick driver that lets you set up a virtual game controller as if you had it plugged into an USB port... except it's not.. it only exists in windows. (PPjoy is to your joystick what Daemon tools is for you DVD-RW unit)

So, how does all that help with ArmA? well the concept is as follows:

Basically since ArmA will only read half an axis, we will give it half an axis to read, but this half axis will be controlled by a full axis from the physical joystick. like this:

.
.    1 | --------------- | ---------------- |  1
.      |                 |                  |  Thrust (analogue)
.      |                 |                  |
.   0  |        ________ | ---------------- |  0
.      |       /         |                  |
.      |      /          |                  | Dead range
.   -1 | ____/           |                  | -1
.
.  joystick           PPjoy                ArmA
.  throttle            Axis              Throttle

So how does this happen? that's where GlovePIE does it's magic. We create a (really simple) script in it that tells it to write to the top half of a PPjoy device axis the value it is reading from the full range of your physical joystick throttle axis.

Don't worry about the axis not being the same... It won't matter if your throttle axis (z) is remapping to PPjoy axis Rx, since it's all the same to ArmA...

So let's get to that: First we should install and configure PPjoy to create a virtual device. If you have it installed you should see a 'Configure Virtual Joysticks' item in your Start Menu. From there, you can create new devices. (PPjoy won't create new devices automatically on install, you have to do it yourself)

So create a new device, and give it the next available device number. This depends on how many joysticks you have plugged in (If you got 2 joysticks, you should create a PPjoy device with device number 3, since it's the next number available). All other settings are fine to leave as default. You can play with them later if you're feeling good about all this.

You can check if PPjoy is installed correctly by going into Control Panel -> Game Controllers and checking if there is a device called PPjoy Virtual Device # there. (the # is the number you gave it). We'll come back here later, so just check that your device is listed there and let's move on.

Now we go into GlovePIE.

The first thing you see when you open GlovePIE is a blank screen with a few lines that say 'write your script here'... yes, there is some scripting in GlovePIE (actually PIE stands for programmable-input-emulator, so it pretty much a given that you will be doing some scripting), but don't worry it's quite easy.

This is the command that does all the magic:

PPJoy#.analog2 = (MapRange(-Joystick.slider, -1, 1, 0, 1))

Where # is the device number you gave your PPjoy device when you created it, and Joystick.slider is a reference to the slider axis of your joystick.

Now, most joysticks define their throttle as 'slider', but that varies from stick to stick... On the X52 Pro the throttle is the 'Z' axis, so you may need to do some searching to find your throttle axis (or whatever axis you're trying to get)

For that, the simplest way is to write this just before the command you just wrote:

debug = Joystick.someAxis

where someAxis is the joystick axis you want to try... on GlovePIE, everytime you press the . [period] key after Joystick, it gives you a list of all possible options... so you can try them until you find your throttle axis... Good candidates are .Z, .Rx, .slider, .roll, .pitch... try those as well as others to find your axis.

This debug line will enable a small text field next to the 'Run' button on GlovePIE... there you will see a number (which probably will read zero)... run the script and move your axis around to see if this number changes... if it does, you've found your axis.

So what's going on there exactly? Well, what this script is doing is basically saying that the PPjoy axis called analog2 will be equal to Joystick.slider with some corrections... the four numbers that follow Joystick.slider define that correction. Let's look at that line again... this is what each element means:

AxisToSet = (MapRange(AxisToRead, minInput, maxInput, minOutput, maxOutput))

So the first 2 numbers after Joystick.slider represent the range of input, while the last two represent the output after the correction... so what this means is that a value ranging from -1 to 1 will be scaled into a value that ranges from 0 to 1.

Now, here is why ArmA only reads half axes... normal joystick axes center at zero. Imagine the stick's X axis, the left/right movement is defined as -1 at full left, zero when centered, and 1 when deflected fully to the right...

So all joystick axes are centered at zero... but this is a problem when handling the throttle axis, since that is an axis without a center... it ranges freely from none to full, but is read as ranging from -1 to 1 anyway... so ArmA only reads either the positive or the negative range of it... Hence our contraption here to counter that.

So what this script is doing is feeding the full travel of your throttle (-1 to 1) into only the positive range of the PPjoy axis (0 to 1). so when your throttle is pulled all the way back, PPjoy will be at 50% (0), and when you push your throttle to full power, PPjoy will be at 100% (1), which is the full range inside ArmA, so now you can control your throttle using the entire range of your throttle slider/lever/handle.

So, now let's test if it worked. Open up Game Controllers on control panel again, and choose the PPjoy device, hit Properties, and go into the 'Test' tab. You should see the joystick axes there, along with some buttons...

Now, ensure GlovePIE is running the script (and that it doesn't show a red line on the script screen, as that means a syntax error), and that the Test screen of your PPjoy device has focus (it won't update if another window is in front of it).

Now move your throttle a bit... you should see the PPjoy device move one of it's axes. If it doesn't, you'll have to tweak your GlovePIE script to ensure you're actually reading the throttle axis, and double check everything until you see movement there...

You can also write debug = joystick#.z to check that this device really is receiving what you are giving it. Here '#' is the number of your PPjoy device, and 'z' is the same as ppjoy's 'analog' 2

Ok. so let's assume everything worked fine and move on. The next step is to map this PPjoy axis into ArmA as your throttle axis. This should be very straighforward... just go into the control settings in the game and for 'Thrust (Analogue)', move your throttle axis... you should see that both your physical joystick's throttle as well as the PPjoy axis were detected... that's both normal and good. Just delete the physical joystick mapping from there and let the thrust mapping be controlled by only the PPjoy device.

This is all... now you should have a full range of throttle input.

But that leaves a question... what about braking? that's not an issue on helicopters, but fixed-wing craft need help slowing down... and we just killed the part of the throttle range that was doing that...

Well, that's in part a good thing, because no aircraft in the world has it's airbrakes on the same lever as the throttle... but we do need to have brakes... so you can either map another another axis to be your brakes (if you have axes to spare) or just map a button for it.

If you choose to map an axis, you can use GlovePIE to do just what we did there to the throttle axis again for the airbrakes axis... if you're going for a button, ArmA will let you map a key or joy button as 'Brakes'

Here are links to download both apps:

PPjoy 0.8.4.6 - http://drop.io/ppjoy0846testrelease (Win XP/Vista/7 x86 and x64)

Here's an alternative link to PPJoy in case the one above doesn't work.

GlovePIE 0.43 - http://glovepie.org/poiuytrewq.php (get the one without Emotiv Support)

Well, I think this pretty much covers it... I hope I made it clear enough... if you have any questions, thoughts or free money, just drop a line here ;)

Best of luck to all :)

Cheers

HarvesteR

Edited by TheHarvesteR
  • Like 1

Share this post


Link to post
Share on other sites

I've tried this before with no luck. I might have the wrong versions of Glove and PPJOY. Everything looked fine from GlovePIE debug but after mapped analogue throttle ( and unmapped inc/dec thrust). My throttle only seemed to work at 100%.

I'll probably give it another try after work tonight.

Quick question though...

Shouldn't this:

PPJoy#.analog2 = (MapRange(-Joystick.slider, -1, 1, 0, 1))

Be this:

PPJoy#.analog2 = (MapRange(Joystick.slider, -1, 1, 0, 1))

Share this post


Link to post
Share on other sites

You can also use glovepie to make "flying profile" like for me I used it to make a arma 2 profile for all flying things and a specific profile for flying the MV-22 Osprey... In which the trigger button is my brakes instead of firing weapons. and on my Arma 2 profile it is firing weapons instead of brakes. I have also reduced the rudder input needed to turn the osprey around and i have decreased that sensitivity in my arma 2 profile for turning a huey around so it doesn't go out of control.

It needs some tweeking but it is a great solution to the arma 2 analog throttle problem.

EDIT*** it is dependent on how your specific joystick is reporting the axis to determine if you need to reverse them by adding the - in front of joystick.slider

Share this post


Link to post
Share on other sites

I finally figured out my issue.

What ever you do, don't calibrate the PPJoy joystick through the control panel.

If you do it by accident there is a reset to default on on the property of the PPJoy joystick.

Removing and adding it back in doesn't help, Windows still keeps the calibration data in the registry, you have to reset it.

Share this post


Link to post
Share on other sites
I finally figured out my issue.

What ever you do, don't calibrate the PPJoy joystick through the control panel.

If you do it by accident there is a reset to default on on the property of the PPJoy joystick.

Removing and adding it back in doesn't help, Windows still keeps the calibration data in the registry, you have to reset it.

What do you mean by calibrate it in the control panel? I was using the control panel to see the GlovePIE outputs.

edit: Nevermind, I figured it out. Coffee fixes all problems. It's been so long since I calibrated a joystick!

Edited by Max Power

Share this post


Link to post
Share on other sites

Quick question though...

Shouldn't this:

PPJoy#.analog2 = (MapRange(-Joystick.slider, -1, 1, 0, 1))

Be this:

PPJoy#.analog2 = (MapRange(Joystick.slider, -1, 1, 0, 1))

This depends on your joystick.. my X52 Pro needed being reversed... other sticks might not need it...

And yes, the almighty GlovePIE is perfect for absolute control customization... This full axis fix is just a small adjustment I made for now... later when I have the time (if ever :P), I'm going to script my entire control scheme in GloveScript... and leave the Saitek SST completely empty and arma at it's default settings.

I did this for the Orbiter space sim... but it was a lengthy procedure that took me almost 4 hours to get it to my liking... but it's so complete it actually speaks! (it tells me what mode I'm on in the voice of Microsoft Anna :D)

Nothing beats having your joystick call out 'orbital controls engaged' in a digital feminine voice :cool:

Cheers

Share this post


Link to post
Share on other sites

This is awesome, finaly i can use my G940 Throttle the way it needs to be

I use this script to read the G940 Throttle (right one):

PPJoy5.analog2 = (MapRange(-Joystick2.x, -1, 1, 0, 1))

Ingame its PPJoy Z Axis... Had a mixup with the analog2 code. Should be analog1 for us G940 users. but i was to lazy... :D

Great work :) Thanks

Share this post


Link to post
Share on other sites
This is awesome, finaly i can use my G940 Throttle the way it needs to be

I use this script to read the G940 Throttle (right one):

PPJoy5.analog2 = (MapRange(-Joystick2.x, -1, 1, 0, 1))

Ingame its PPJoy Z Axis... Had a mixup with the analog2 code. Should be analog1 for us G940 users. but i was to lazy... :D

Great work :) Thanks

Yes, PPjoy's analog2 will remap to PPjoy Z, since it is the third axis on the device (0: X, 1: Y, 2: Z)...

And it doesn't really matter if the axes on PPjoy don't match the ones on your physical joystick, since it's all the same after it's mapped in ArmA... (unless you have some serious OCD about these things :D )

Does the G940 report the throttle as a separate device? I see you got joystick2.x there...

Anyway, glad to hear that it worked!

Cheers

Edited by TheHarvesteR

Share this post


Link to post
Share on other sites
This depends on your joystick.. my X52 Pro needed being reversed... other sticks might not need it...

And yes, the almighty GlovePIE is perfect for absolute control customization... This full axis fix is just a small adjustment I made for now... later when I have the time (if ever :P), I'm going to script my entire control scheme in GloveScript... and leave the Saitek SST completely empty and arma at it's default settings.

I did this for the Orbiter space sim... but it was a lengthy procedure that took me almost 4 hours to get it to my liking... but it's so complete it actually speaks! (it tells me what mode I'm on in the voice of Microsoft Anna :D)

Nothing beats having your joystick call out 'orbital controls engaged' in a digital feminine voice :cool:

Cheers

Yeah, I totally forgot that with the X52 throttle top half is the Z- axis.

I don't even use any of the Saitek software any more, not even the driver.

I had calibration problems with driver, and the only fix based on the Saitek forums was to unplug the stick and delete some registry entries. I found that using the driver that ships with Vista works flawlessly, and I can even recalibrate at any time through the control panel.

I'm not sure if the Pro version has the same issues.

I had some issues using:


debug = Joystick.someAxis

As an alternative you can use the following:


var.throttle = Joystick.z

Then you can set the value of the var.throttle on the Variables tab.

You can change throttle to anything and Joystick.z to the axis you want.

GlovePIE is just plain awesome. With GlovePIE it's possible to apply deadzones, adjust sensitivity, map buttons to anything you want.

Anyone know off hand if I can pass scripts through the command line?

I would like to able to setup shortcuts for different scripts.

Share this post


Link to post
Share on other sites
Does the G940 report the throttle as a separate device? I see you got joystick2.x there... Cheers

Hey, yep, G940 has 3 different devises... Joystick, Throttle and Rudder Paddels.

Now with the G940 working properly now, i can start mounting the joystick the way, i can use em right...

Thanks again.

Maybe add the different axis names for the different joysticks to the first post... meight help others... :yay:

Ah yeah, is it realy needed to have glovepie all the time running? Isnt there a way to make this permanent? Sucks to have to start it and stop (but its nice to change things on the go :))

Share this post


Link to post
Share on other sites

Anyone know off hand if I can pass scripts through the command line?

I would like to able to setup shortcuts for different scripts.

Ah yeah, is it realy needed to have glovepie all the time running? Isnt there a way to make this permanent? Sucks to have to start it and stop (but its nice to change things on the go :))

These two question have the same answer:

Make a shortcut to GlovePie, and after the target name (GlovePIE.exe), add:

/run <pathToYourScript>.pie /tray /r <pathToArmA>.exe

so the line will read something like this:

"C:\Program Files\GlovePIE\GlovePIE.exe" /run "C:\scripts\myScript.PIE" /tray /r "C:\Program Files\ArmA 2\ArmA 2.exe"

this will open up glovePIE, run the specified script, minimize itself to tray, then launch ArmA. :yay:

there are more command line arguments for glovePIE, but sadly, the documentation is very sparse... but you can get a list of them by running GlovePIE with the /? parameter (a message window pops up)

On my setup I have the /r parameter set to my ArmA launcher... so i can set up my mods before I start.

Optionally you could point it to a .bat file, and from there load up any other apps you may need, like TrackIR, TS or ventrilo... this would make it a one-click deal... and launch 4 or 5 apps all at once :D

Hope this helps

Cheers

Edited by TheHarvesteR

Share this post


Link to post
Share on other sites

has anyone tried this with a HOTAS yet?

Edited by GOOSE63

Share this post


Link to post
Share on other sites

@Goose36 (nice to see you here too ;))

Well, you mean any HOTAS joysticks? Well i use the G940, which is a Hand on throttle and stick... It works on every Analog Throttle :yay: Works like a charm.

Thanks for the Auto Start of the thing. Thanks.

Share this post


Link to post
Share on other sites

Dont know if anybody tried it yet, but what Glovepie does, is recording the inputs from the axes, and does with that data whatever the scripts tells it.

What you want to know is the name of the throttle axis and if the cougar Hotas are two seperate inputdevices.

Im sure this would work with the Cougar hotas too, because there is no dependancy on any driver. As long the joystick still works, ppjoy will record the data and convert it for you.

best regards

Share this post


Link to post
Share on other sites

With GlovePie you can do a lot. Here a script for ArmA1, when multiple joysticks were no possible at all. ArmA.pie

I then switched to AutoHotkey for ArmA2, because of some annoying bugs, and found a library to interface AHK to PPjoy. It works great! A2Joy.ahk

Share this post


Link to post
Share on other sites

Now can someone figure out how to set this up with a toggle so I can turn it on for choppers, off for jets

Share this post


Link to post
Share on other sites

Dunno about Saitek, but CH Products supports multiple modes on a number of their controllers - like the fighterstick. So it's quite possible to toggle modes to enable a specific config for choppers and another for jets.

Share this post


Link to post
Share on other sites
Now can someone figure out how to set this up with a toggle so I can turn it on for choppers, off for jets

You can... It just takes some scripting, and a button or key you're willing to spare for that.

This is good also for creating a 'collective' mode where pulling is up and pushing is down, as opposed to the default setting for fixed wing

The Saitek X52 as well as many other joysticks have a mode switch that allows you to create different mappings for each button. (for Saitek that is done through the SST app)

I don't know what joystick you have, but I'll relate what I did with my X52, and maybe you can understand the principle and apply it to your setup.

Well first things first... Saitek's SST monopolizes the mode switch, so if you have the profiler up, you can't use the mode switch for anything other than switching SST modes, so what do we do?

One solution would be to completely uninstall the SST software, but that might not be such a good idea if you already have a bunch of profiles for other games...

So the other solution is to create a new profile, and in there remove all modes except the default one (which is impossible to remove)... also make sure no button is mapped to anything, so that this profile is as blank as we can have it... Save and apply, good, let's move on.

Now that there are no more modes, the buttons behind the mode switch become available for GlovePIE... that is, all except the button for mode 1, which is still stuck as a mode in SST because we can't delete it... but that's not a problem, and here's why:

Since the mode switch is a 3-position switch, if the buttons for mode 2 and 3 are not pressed, then we must be in mode 1. so we can use that to check for our modes.

For the saitek X52, the buttons for each mode are:

Mode 1: button 27 (explicitly unreachable)

Mode 2: button 28

Mode 3: button 29

Explicitly unreachable means that we can't directly read it in GlovePIE, but we can implicitly check that it is pressed, simply by checking that the other 2 buttons are not pressed.

with that, you can write a simple script to map your axes and button depending on what mode is set on the X52...

unfortunately I'm at work right now, and I can't post an example script, since my own script is at my home rig... later tonight I'll post how you can check for buttons (and modes) in GlovePIE

Now for those without mode switches, if you wanto to have a button for toggling, all you need is a variable inside glovePIE to be your toggle.

This variable can be true or false (for 2 modes) or a number that you can cycle around for as many modes as you wish.

in GlovePIE you can set/read a variable like this:

// for binary modes
var.toggle = true

// for many many modes
var.mode = 0

note that the variable name (in this case 'toggle' or 'mode') can be anything you want, just as long as it's preceded by var.

So, later you can toggle your mode like this:


if (Joystick.button1 and not var.b1isPressed) then
   //for toggle vars
   var.toggle = not var.toggle

   //or for numbers
   var.mode = (var.mode + 1) % numberOfModes

   var.b1isPressed = true
else
   var.b1isPressed = false
endif

The code above says that if button 1 on your joystick is pressed, then it should switch to the next mode, or toggle it if it's true or false...

note that there is also a b1isPressed variable there... that is to prevent something called state oscillation... let me explain:

Imagine that the GlovePIE script is running in an endless loop (which it, in fact, is)... that is, once it gets to the end, it stats all over again and keeps doing that until you stop the script. So the problem with that is that this loop is very fast, and will probably loop around a few times in the time it takes to press and release a button... so what happens then? well, if there were no b1isPressed, the script would detect that the button is pressed probably some 5 times before you could release it, and instead of just hopping forth to mode 2, you would fly through all modes and land god knows where... so this b1isPressed is a control var doing something called 'debouncing', which is preventing that the code inside the 'if' block gets executed again after the first time the button was pressed... it only resets beack once the button is let loose again.

I hope that was clear enough.... now moving on:

note that strange expression there for var.mode... what this is saying basically is to first increment the value of var.mode by one, then constrain it to the number of modes using the 'mod' operator (which gives out the remainder in a division). this is to ensure that your mode is always a valid mode value

For instance, if you have 3 modes (as in mode 0, 1 and 2), if you just increment it by one, you'll eventually get to 3, which is not a valid mode anymore... so the 'mod' statement tells is to loop back to zero once it gets to three (provided that numberOfModes is 3)...

So now later in your script you can write something like this:


if (var.mode == 0) then

   // axis mappings for mode one go here

endif
if (var.mode == 1) then

  // axis mapping for mode two go here

endif
//and so on

You must check if a variable is something or not using a double-equal sign (==), remember that a single equal tells the script that something should be equal to something else, and a double equal tells it to check whether it is equal or not

with that, you can have different modes in your glovePIE scripts, be it with a mode switch, or just a button...

I hope this was clear enough :)

Cheers

Edited by TheHarvesteR

Share this post


Link to post
Share on other sites

Finally gave this a go today. Its an X52 non pro that I have so I presume its the same as Your pro

I've got it mapped to ppjoy but when I try to map the new controller in the game I've only got parallel port stick z+ axis, no z- axis when I pull back the throttle so I can't map it to decrease thrust

Edited by PogMoThoin

Share this post


Link to post
Share on other sites
Finally gave this a go today. Its an X52 non pro that I have so I presume its the same as Your pro

I've got it mapped to ppjoy but when I try to map the new controller in the game I've only got parallel port stick z+ axis, no z- axis when I pull back the throttle so I can't map it to decrease thrust

Well, that just means you did it right :bounce3:

If you look again at the main concept behind this fix, you will see that there should be no stick z- axis to map.... that's what the fix does. We disable the bottom half of the virtual range (z- axis) so that we can have the remaining top range spread across the entire travel of the physical throttle lever.

So it's not wrong that there is no stick z- axis, that's ok, since ArmA will only detect an axis when it's moving away from center (be it into the negative or positive range). That means that you only get a z- axis when you move the axis past it's centerpoint and into the negative range. But the negative range is what we just disabled with the fix.

You seem to be using the increase/decrease thrust combo... those are for keyboard playing, and they have some sort of AI attached that does the throttling for ya. (that's why I hate it).

What you shoud do now is map your throttle into the Thrust (Analogue) command. (the single stick z+ mapping will do), and then your slider or some thumbbutton as Brakes (Analogue).

Check how that affects th handling on planes and choppers... it should already be working.

About the brakes, I have my rotaty 2 axis set as the airbrakes right now (and running the same fix on it), but I'm not too happy with that assignment... I think I'll remap mine to the clutch button, or just make a redundancy there for dive-braking and other cases. Right now it's a bit too much when doing a dive-bomb or strafing run... to pull out I have to retract the brakes, zoom out using the slider, and throttle up (and fly with my right hand)... a little too much stress on an already stressful situation ;)

Hope this helps (and makes sense)

Cheers

Edited by TheHarvesteR

Share this post


Link to post
Share on other sites

Understood, works perfectly, Thank You.

Now i'm gonna have a go at setting up the mode switch toggle

Share this post


Link to post
Share on other sites

Does anyone know if BIS plans on fixing this themselves? I really don't see how they can possibly be that ignorant with the easily available HOTAS options on the market today.

We shouldn't have to fix your game, Bohemia.

Share this post


Link to post
Share on other sites

I did post a bug report about this matter some time ago, but it didn't get a lot of attention... but I was already quite pleased when they added the Analogue Throttle in 1.5, which is what made all this possible, and that IIRC, was because of a user feature request.

IMO, BIS does right in worrying more about priority fixes, like random crashes and showstopper bugs, than petty improvements like this one, which can even be worked around by the community... I recall a number of developers who seemed to care more about these 'cosmetic' improvements than actually fixing broken content, because it's more visible than a catastrophic bug that only occurs in 5% of computers.

Cheers

Share this post


Link to post
Share on other sites

Apparently this issue has been going on for over a year. I noticed a problem the first day I got the game and went through Boot Camp, wondering why in the f*** the helicopter was so hard to control altitude with.

The current CIT "feature" request to fix this has sat in open mode for over a year, without an ETA or developer assigned to fix the problem. Color me thoroughly unimpressed.

And no, I don't really give a crap if someone else thinks it's a minor issue. It reeks of ignorance to create an analogue thrust control, and yet have the axis assignments only work when moving away from a centerpoint. The gas pedal in your car isn't your BRAKE pedal for the first 50% of it's motion, is it?

Common sense should've prevented this "bug" from ever existing in the first place.

Share this post


Link to post
Share on other sites

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now

×