Input device

From FlightGear wiki
(Redirected from Joystick)
Jump to navigation Jump to search

Could you imagine a pilot in his or her Cessna controlling the machine with a keyboard alone? For getting the proper feeling of flight you will need a joystick/yoke plus rudder pedals, right?

FlightGear has integrated joystick support, which automatically detects any joystick, yoke, or pedals attached. Just try it! If this does work for you, lean back and be happy! You can see what FlightGear has detected your joystick as in the Help > Joystick Configuration dialog from the menu.

Unfortunately, for the above mentioned versatility, chances are your joystick does not work out of the box. This article explains you how to make FlightGear recognise your device

Joystick or yoke?

CH Products Fighterstick USB Saitek Pro Flight Cessna Yoke
CH Products Fighterstick USB Saitek Pro Flight Cessna Yoke

The two most common control devices on aircraft are the joystick (left picture) and yoke (right picture). Joysticks can be found on military fighters, helicopters and Airbus airliners, while yokes are used on almost all other fixed wing aircraft, including Boeing airliners.

Joysticks are generally a lot cheaper, starting at $10. Yokes start at $100. When you are new to flightsimming, buying a cheap (ca. $20) joystick might be a good way to find out if it's something for you.

The following table should help you decide which one is best suited for you:

Joystick Yoke
Price $10+ $100+
General aviation No Yes
Gliders Yes No
Helicopter Yes No
Fighters Yes No
Most airliners including Boeing No Yes
Airbus Yes No

It should be noted that any type of input device (be it a joystick, a yoke or even a gamepad) will work with all aircraft in FlightGear and that the table above only suggests which ones are more suited to specific types of aircraft given how they are flown in real life.

Some reviews of flight simulation hardware can be found in Category:Hardware reviews.

Built-in joystick support

In order for joystick auto-detection to work, a joystick bindings xml file must exist for each joystick. This file describes what axes and buttons are to be used to control which functions in FlightGear. The associations between functions and axes or buttons are called "bindings".

FlightGear includes a large number of such bindings files for a variety of manufacturers. Chances are high that your joystick will be recognised straight away, so let's try that first. You can confirm whether it was recognised by looking in the File > Joystick Configuration dialog. "Used for" should contain a name/description of your joystick. It will contain "default" when FlightGear did not recognise your joystick.

Most of the time when your joystick is not recognised, it is because of a missing name definition in the respective bindings file. Because FlightGear is used on all kind of operating systems, names vary a lot. You can find the files under $FG_ROOT/Input/Joysticks/ (despite the name, yokes and pedals are also found here!). For example, if you have a CH Products joystick, look in the folder $FG_ROOT/Input/Joysticks/CH for a file that might work for your joystick. When such a file exists, do the following:

  1. Launch FlightGear with the joystick connected.
  2. Look under File > Joystick Configuration and check the name behind "Joystick #0:".
  3. Open your joystick's bindings file in a XML editor and add the following code to the file, below the already-present <name> tags.
  4. <name>The EXACT name you found under step 2; including spaces, capitals etc.</name>
    
  5. Please report this name at our forum, so it can be added to the official file (and next releases).

Please note that the latest config files are always to be found at fgdata/Input/Joysticks. This link may contain additional binding files that were not included in the latest stable release.

If there is no file for your joystick, you will have to create such a file. We will discuss that in a later section, by cutting and pasting bindings from the examples that are included with FlightGear.

Multiple devices on Windows

In case you have two USB devices (for instance a yoke plus pedals) to a Windows computer, there may be cases, where the same driver name is reported twice. In this case, you can get at least the yoke to work by assigning it number 0 (out of 0 and 1), by adding a line to $FG_ROOT/joystick.xml like:

<js n="0" include="Input/Joysticks/Saitek/ST290-Pro.xml"/>

if you also have pedals (or another joystick), just add more lines, similar to:

<js n="1" include="Input/Joysticks/Saitek/Pro-Flight-Rudder-Pedals.xml"/>

To make sure that the first input device is indeed the yoke, rotate the yoke (aileron control) and observe the Help > Joystick Configuration dialog. If the aileron value does not change, you have to make the yoke the preferred device first. For doing so, enter the Windows "Control panel", open "Game controllers" and select the "Advanced" button. Here you can select the yoke as the "Preferred" device. Afterwards you can check that assignment by restarting FlightGear. The yoke should now control the aileron.

Adding support for your joystick

Verifying your joystick is working

Linux

Reboot your system and immediately enter on the command line

dmesg | grep Joystick

which pipes the boot message to grep which then prints every line in the boot message that contains the string “Joystick”. When you do this with a Saitek joystick attached, you will see a line similar to this one:

input0: USB HID v1.00 Joystick [SAITEK CYBORG 3D USB] on usb2:3.0

This line tells us that a joystick has identified itself as SAITEK CYBORG 3D USB to the operating system. It does not tell us that the joystick driver sees your joystick. You can verify that the joystick driver sees the joystick by entering:

js_demo

If your joystick is not recognized by the driver, you may have to manually load the joystick device module with the command:

modprobe joydev

Windows

Go to Start > Control Panel > Game Controller and see whether the dialog displays (and responses) on your joystick.

Confirming that the driver recognizes your joystick

FlightGear ships with a utility called js_demo. It will report the number of joysticks attached to a system, their respective "names" and their capabilities. Under Linux, you can run js_demo from the folder /FlightGear/bin as follows:

$ cd /usr/local/FlightGear/bin 
$ js_demo

Under Windows, open a command shell (Start > All Programs > Accessories > Command Prompt), go to the FlightGear binary folder and start the program as follows (given FlightGear is installed under C:/Program Files/Flightgear)

C:
cd /Program Files/FlightGear/bin/win32 
js_demo.exe


On our system, the first few lines of output are (stop the program with C if it is quickly scrolling past your window!) as follows:

Joystick test program. 
Joystick 0: “CH PRODUCTS CH FLIGHT SIM YOKE USB ” 
Joystick 1: “CH PRODUCTS CH PRO PEDALS USB” 
Joystick 2 not detected 
Joystick 3 not detected 
Joystick 4 not detected 
Joystick 5 not detected 
Joystick 6 not detected 
Joystick 7 not detected 
+——————–JS.0———————-+——————–JS.1———————-+ 
| Btns Ax:0 Ax:1 Ax:2 Ax:3 Ax:4 Ax:5 Ax:6 | Btns Ax:0 Ax:1 Ax:2 | 
+———————————————-+———————————————-+ 
| 0000 +0.0 +0.0 +1.0 -1.0 -1.0 +0.0 +0.0 . | 0000 -1.0 -1.0 -1.0 . . . . . |

First note that js demo reports which number is assigned to each joystick recognized by the driver. Also, note that the “name” each joystick reports is also included between quotes. We will need the names for each bindings file when we begin writing the binding xml files for each joystick.

Identifying the numbering of axes and buttons

Axis and button numbers can be identified using js demo as follows. By observing the output of js demo while working your joystick axes and buttons you can determine what axis and button numbers are assigned to each joystick axis and button. It should be noted that numbering generally starts with zero.

The buttons are handled internally as a binary number in which bit 0 (the least significant bit) represents button 0, bit 1 represents button 1, etc., but this number is displayed on the screen in hexadecimal notation, so:

  • 0001 ⇒ button 0 pressed
  • 0002 ⇒ button 1 pressed
  • 0004 ⇒ button 2 pressed
  • 0008 ⇒ button 3 pressed
  • 0010 ⇒ button 4 pressed
  • 0020 ⇒ button 5 pressed
  • 0040 ⇒ button 6 pressed
  • ... etcp to ...
  • 8000 ⇒ button 15 pressed
  • ... and ...
  • 0014 ⇒ buttons 2 and 4 pressed simultaneously
  • ... etc.

For Linux users, there is another option for identifying the “name” and the numbers assigned to each axis and button. Most Linux distributions include a very handy program, “jstest”. With a CH Product Yoke plugged into the system, the following output lines are displayed by jstest:

jstest /dev/js3 
Joystick (CH PRODUCTS CH FLIGHT SIM YOKE USB ) has 7 axes and 12 buttons. Driver version is 2.1.0 
Testing…(interrupt to exit) 
Axes: 0: 0 1: 0 2: 0 3: 0 4: 0 5: 0 6: 0 Buttons: 0:off 1:off 2:off 3:on 4:off 5:off 6:off 7:off 8:off 9:off 10:off 11:off

Note the “name” between parentheses. This is the name the system associates with your joystick.

When you move any control, the numbers change after the axis number corresponding to that moving control and when you depress any button, the “off” after the button number corresponding to the button pressed changes to “on”. In this way, you can quickly write down the axes numbers and button numbers for each function without messing with binary.

In most modern repositories, there is a graphical version of this program, called "jstest-gtk", where you are given a list of attached devices to choose from, and then get a graphical representation of all axes and buttons.

Calibration

For many/most joysticks this step might not be necessary. If either, the centre position of the joystick does not yield near-zero values for relevant axes, or if the maximum value for an axis cannot be reached, or is reached too early, you need to calibrate the joystick. (Note that some calibration problems can be fixed with the flighgear joystick configuration files, but not all, e.g. if the maximum value is reached too early)

Linux

The program "jscal" (install from repositories if not already available on your system) provides a calibration routine for joysticks. You need to know or find out the device name of your joystick (usually /dev/js0 or /dev/input/js0 - instead of 0 a different number might need to be used, look at output of js_demo to figure out which). For example to calibrate the joystick with device name /dev/input/js0, execute

jscal -c /dev/input/js0

and follow instructions. The calibration is retained until the joystick is unplugged, or the computer rebooted. In order to save it for future use, execute

jscal -p /dev/input/js0

which will print the command that needs to be entered to restore the calibration, for example

jscal -s 6,1,0,8171,8171,65936,65374,1,0,8166,8166,65928,65494,1,0,128,128,4194176,4227201,1,0,128,128,4194176,4227201,1,0,0,0,536854528,536854528,1,0,0,0,536854528,536854528 /dev/input/js0

Copy the command you obtained into your startup script in order to restore calibration automatically.

Recent versions of jscal have this simplified, you can store and restore your calibration settings. After calibration store the settings:

jscal-store /dev/input/js0

Then in your startup script recall the settings for the given device:

jscal-restore /dev/input/js0

However if you have multiple controllers connected, they might be renumbered on pluging/repluging. Best way to insure you get the correct calibration is to create a custom udev rule-set that you put into /etc/udev/rules.d/00-joystick.rules, similar to the following example:

#joystick rules to make the names persistent and reload the stored calibration profile
ACTION!="add|change", GOTO="joystick_end"
SUBSYSTEM!="input", GOTO="joystick_end"

KERNEL=="js*", ATTRS{idProduct}=="a02f", ATTRS{idVendor}=="12bd", SYMLINK+="input/joystick" RUN+="/etc/udev/scripts/joycal.sh"
KERNEL=="js*", ATTRS{name}=="Logitech Logitech Racing Wheel", SYMLINK+="input/logiwheel" RUN+="/etc/udev/scripts/wheelcal.sh"

LABEL="joystick_end"

Then the scripts called would be as follows:

  • /etc/udev/scripts/joycal.sh:
#!/bin/sh
jscal-restore /dev/input/joystick
  • /etc/udev/scripts/wheelcal.sh
#!/bin/sh
jscal-restore /dev/input/logiwheel

Now each time you plug/replug your joysticks/controllers they will get the persistent device names, and will get the correct calibration profile restored.


The calibration is even more comfortable using the program "jstest-gtk", also available from most repositories. Starting this you are given a list of all attached joysticks with their device names. Pick the one you wish to inspect or calibrate and click 'Properties', then calibrate. This calibration tool offers the possibility to fine-tune the calibration by editing the numbers. The program manipulates the same internals as jscal so you can use jscal to save the calibration information for later use, as before.

Writing or editing joystick binding xml files

At this point, you have confirmed that the operating system and the joystick driver both recognize your joystick(s). You also know of several ways to identify the joystick “name” your joystick reports to the driver and operating system. You will need a written list of what control functions you wish to have assigned to which axis and button and the corresponding numbers.

Make the following table from what you learned from js demo or jstest above (pencil and paper is fine). Here we assume there are 5 axes including 2 axes associated with the hat.

Axis Button
elevator = 0 view cycle = 0
rudder = 1 all brakes = 1
aileron = 2 up trim = 2
throttle = 3 down trim = 3
leftright hat = 4 extend flaps = 4
foreaft hat = 5 retract flaps = 5
decrease RPM = 6
increase RPM = 7

We will assume that our hypothetical joystick supplies the “name” QUICK STICK 3D USB to the system and driver. With all the examples included with FlightGear, the easiest way to get a so far unsupported joystick to be auto detected, is to edit an existing binding xml file. Look at the xml files in the sub-folders of /FlightGear/Input/Joysticks/. After evaluating several of the xml binding files supplied with FlightGear, we decide to edit the file $FG_ROOT/Input/Joysticks/Saitek/Cyborg-Gold-3d-USB.xml.

This file has all the axes functions above assigned to axes and all the button functions above assigned to buttons. This makes our editing almost trivial.

Before we begin to edit, we need to choose a name for our bindings xml file, create the folder for the QS joysticks, and copy the original xml file into this directory with this name.

$ cd /usr/local/FlightGear/Input/Joysticks 
$ mkdir QS 
$ cd QS 
$ cp /usr/local/FlightGear/Input/Joysticks/Saitek/ 
Cyborg-Gold-3d-USB.xml QuickStick.xml

Here, we obviously have supposed a Linux/UNIX system with FlightGear being installed under /usr/local/FlightGear. For a similar procedure under Windows with FlightGear being installed under C:/Program Files/FlightGear, open a command shell and type

C: 
cd /Program Files/FlightGear/Input/Joysticks 
mkdir QS 
cd QS 
copy /Program Files/FlightGear/Input/Joysticks/Saitek/ 
Cyborg-Gold-3d-USB.xml QuickStick.xml

Next, open QuickStick.xml with your favorite editor. Before we forget to change the joystick name, search for the line containing <name>. You should find the line

<name>SAITEK CYBORG 3D USB</name>

and change it to

<name>QUICK STICK 3D USB</name>

This line illustrates a key feature of xml statements. They begin with a <tag> and end with a </tag>.

You can now compare your table to the comment table at the top of your file copy. Note that the comments tell us that the Saitek elevator was assigned to axis 1. Search for the string

<axis n="1">

and change this to

<axis n="0">

Next, note that the Saitek rudder was assigned to axis 2. Search for the string

<axis n="2">

and change this to

<axis n="1">

Continue comparing your table with the comment table for the Saitek and changing the axis numbers and button numbers accordingly. Since QUICKSTICK USB and the Saitek have the same number of axes but different number of buttons, you must delete the buttons left over. Just remember to double check that you have a closing tag for each opening tag or you will get an error using the file.

Finally, be good to yourself (and others when you submit your new binding file to a FlightGear developers or users archive!), take the time to change the comment table in the edited file to match your changed axis and button assignments. The new comments should match the table you made from the js demo output. Save your edits.

Several users have reported that the numbers of axes and buttons assigned to functions may be different with the same joystick under Windows and Linux. The above procedure should allow one to easily change a binding xml file created for a different operating system for use by their operating system.

You can tell how FlightGear has interpretted your joystick setup by selecting Help > Joystick Configuration from the menu.

Joystick support via .fgfsrc entries

Fortunately, there is a tool available now, which takes most of the burden from the average user who, maybe, is not that experienced with XML, the language which these files are written in.

For configuring your joystick using this approach, open a command shell (command prompt under windows, to be found under Start|All programs|Accessories). Change to the directory $FG_ROOT/bin via e.g. (modify to your path)

cd C:/Program Files/FlightGear/bin

and invoke the tool fgjs via

./fgjs --fg-root=$FG_ROOT

on a UNIX/Linux machine, or via

fgjs --fg-root=$FG_ROOT

on a Windows machine. The program will tell you which joysticks, if any, were detected. Now follow the commands given on screen, i.eṁove the axis and press the buttons as required. Be careful, a minor touch already “counts” as a movement. Check the reports on screen. If you feel something went wrong, just re-start the program.

After you are done with all the axis and switches, the directory above will hold a file called fgfsrc.js. If the FlightGear base directory FlightGear does not already contain an options file .fgfsrc (under UNIX)/system.fgfsrc (under Windows) mentioned above, just copy

fgfsrc.js into .fgfsrc (UNIX)/system.fgfsrc (Windows)

and place it into the directory FlightGear base directory FlightGear. In case you already wrote an options file, just open it as well as fgfsrc.js with an editor and copy the entries from fgfsrc.js into .fgfsrc/system.fgfsrc. One hint: The output of fgjs is UNIX formatted. As a result, Windows Editor may not display it the proper way. I suggest getting an editor being able to handle UNIX files as well, for example Notepad++.

The the axis/button assignment of fgjs should, at least, get the axis assignments right, its output may need some tweaking. There may be axes moving the opposite way they should, the dead zones may be too small etc. For instance, I had to change

--prop:/input/joysticks/js[1]/axis[1]/binding/factor=-1.0

into

--prop:/input/joysticks/js[1]/axis[1]/binding/factor=1.0

(USB CH Flightsim Yoke under Windows XP). Thus, here is a short introduction into the assignments of joystick properties.

Basically, all axes settings are specified via lines having the following structure:

--prop:/input/joysticks/js[n]/axis[m]/binding/command=property-scale 
--prop:/input/joysticks/js[n]/axis[m]/binding/property=/controls/steering option
--prop:/input/joysticks/js[n]/axis[m]/binding/dead-band=db
--prop:/input/joysticks/js[n]/axis[m]/binding/offset=os
--prop:/input/joysticks/js[n]/axis[m]/binding/factor=fa

where

n number of device (usually starting with 0)
m number of axis (usually starting with 0)
steering option elevator, aileron, rudder, throttle, mixture, pitch
dead-band range, within which signals are discarded; useful to avoid jittering for minor yoke movements
offset specifies, if device not centered in its neutral position
factor controls sensitivity of that axis; defaults to +1, with a value of -1 reversing the behavior

You should be able to at least get your joystick working along these lines. Concerning all the finer points, for instance, getting the joystick buttons working, John Check has written a very useful README being included in the base package to be found under FlightGear/Docs/Readme/Joystick.html. In case of any trouble with your input device, it is highly recommended to have a look into this document.

More about programming joystick XML files

General tips

  • When testing a new xml file it is best to start FlightGear via a command window (rather than the GUI interface). Any error messages will then be displayed in the terminal. Error messages will give both a message and a line number, helping you pinpoint any errors.
  • Errors can be detected on initial startup or at runtime. Both types of errors will be displayed in the terminal.
  • One of the most common errors is including a character that makes XML choke. Such characters include
    & < --
    These characters will cause problems even if simply included in comments or within scripts.
  • If your scripts contain any of these characters, you have to enclose the scripts in <script><![CDATA[...]]></script>. Alternatively, you can 'escape' the characters, ie "<" becomes "&lt;".
  • You can reload your edited joystick file without restarting FlightGear by selecting "Debug" > "Reload Input" from the main simulator window.
  • You can find many examples of different ways to program joysticks simply by examining the joystick xml files that are packaged with FlightGear. See the directory FlightGear/data/input/joysticks
  • Many advanced functions can be programmed using the Nasal scripting language. These scripts are enclosed in <script></script> tags in the XML file. Helpful:
  • You can explore the internal property tree to see many variables that can be altered using joystick buttons or axes (File/Browse Internal Properties)
  • You can test bits of Nasal code and do some other useful things using the Nasal Console (Debug/Nasal Console).
  • All Nasal code shares a common namespace, so it's possible to set a variable in one nasal binding, and to read it in another.

Useful hints for scripts

Some particularly useful ideas for programming scripts within joystick XML files:

  • getprop and setprop can be used for getting & setting properties from the internal properties tree:
var brake = !getprop("/controls/gear/brake-parking");
setprop("/controls/gear/brake-parking", brake);
  • You can also make your own values on the property tree:
setprop("/input/joysticks/js[0]/myjoystick-modifier", 1);
var mod = getprop("/input/joysticks/js[0]/myjoystick-modifier");
  • You can print to terminal using the print function. This is very useful for debugging.
print("Just", " a ", "test");
  • You can display info in FlightGear via a popup. This is useful for giving the user feedback about changes that may not be obvious via the panel. It can also be useful for debugging. Example:
gui.popupTip("Parking Brake ON");

Arguments for gui.popupTip must be strings, so if you want to display other types of variables they should be formatted with something like sprintf:

gui.popupTip(sprintf("Elevator trim: %d", 100 * getprop("/controls/flight/elevator-trim")));

Or

thv = getprop("/controls/engines/engine[0]/mixture");
gui.popupTip("Thrust vector " ~ int(thv * 120 - 20));
  • You can just start using variables, ie,
x = 10;

But for various reasons it is generally better to declare variables with the "var" statement:

var x = 10;

Note that "var" creates variables that are local in scope, but since all bindings for a joystick share the same scope, it will be seen across each script in the joystick file.

  • You can include a section of script that runs on startup to initialize variables, create functions, etc. Example:
<PropertyList>
  <name type="string">My joystick name</name>
  <name type="string">My joystick name #2</name>
  <nasal>
    <script>
       #initialize variables
       f1 = f2 = 0;
       left_brake = right_brake = 0;
       # create a function to be used with all buttons
       getmod = func { getprop("/input/joysticks/js[0]/t-flight-hotas-x-modifier" ) }
    </script>
  </nasal>
  • Sample code for firing weapons with the joystick is found on the Gun Effects page.


Multiple mice on Linux

On Linux, it is possible to make specific mice control specific Flightgear properties instead of the default flight controls.

You will need to know the Linux name and ID for the mouse. This can be done by running the command xinput --list which lists all connected input devices. (Extra information about a specific device can be found with xinput --list-props <id> or xinput --list-props <name>.)

Then create a file in fgdata/Input/Event/. The leafname doesn't matter, but for example it could be called fgdata/Input/Event/MouseExtra.xml. The contents of this file determine the properties that the mouse will control. For example:

<PropertyList>
  <name>Logitech Logitech USB Optical Mouse</name>
  <debug-events type="bool">false</debug-events>
  <grab type="bool">true</grab>
  <event>
    <desc>Y-Axis</desc>
    <name>rel-y-translate</name>
    <binding>
     <command>property-adjust</command>
     <property>/controls/flight/elevator</property>
     <factor type="double">-.002</factor>
     <min type="double">-1.0</min>
     <max type="double">1.0</max>
     <wrap type="bool">false</wrap>
    </binding>
  </event>
  <event>
    <desc>X-Axis</desc>
    <name>rel-x-translate</name>
    <binding>
     <command>property-adjust</command>
     <property>/controls/flight/aileron</property>
     <factor type="double">.002</factor>
     <min type="double">-1.0</min>
     <max type="double">1.0</max>
     <wrap type="bool">false</wrap>
    </binding>
  </event>
</PropertyList>

(Change <name>Logitech Logitech USB Optical Mouse</name> to match your mouse.)

It can be useful to tell X to ignore the mouse so that it doesn't affect the main X pointer. This can be done with: xinput --set-prop <id> "Device Enabled" 0. Normal X handling of the mouse can be restored with xinput --set-prop <id> "Device Enabled" 1. (One can also use the name of the mouse instead of <id>.)

On Devuan Linux, one can use a udev rule to ensure that the mouse can be read and written by flightgear (usually they are only accessible to root):

  • Create a file /etc/udev/rules.d/90-fgmouseextra.rules containing a single line KERNEL=="hidraw*", SUBSYSTEM=="hidraw", MODE="0666".
  • Reboot or run udevadm control --reload-rules.

[Note that i know almost nothing about udev, and it's entirely possible that this represents a huge security flaw, so use with caution.]

[The information above is based on the forum thread https://forum.flightgear.org/viewtopic.php?t=32750 and Torsten Dreyer's original email https://www.mail-archive.com/flightgear-devel@lists.sourceforge.net/msg23171.html.]

Related content

Wiki articles

Forum topics

External links