]> git.mxchange.org Git - flightgear.git/blob - docs-mini/README.Joystick
Updated to latest revision.
[flightgear.git] / docs-mini / README.Joystick
1 Users Guide to FGInput - Joystick And Keyboard Bindings For FlightGear
2 Or
3 "The document formerly know as The Users Guide to Joystick Usage Under
4 FlightGear Flight Simulator"
5
6 version 0.7.7.1 06/25/2001
7 Author John Check <j4strngs@rockfish.net>
8
9 This document is written with versions of FlightGear 0.7.7 and greater
10 in mind. It assumes a working joystick present on your system. It
11 is written from the perspective a Linux user, but the information presented
12 is valid on other platforms. The most current version can be found at:
13
14 http://rockfish.net/shell/aboutFGInput.txt
15
16 Thanks to David Megginson, who aside from actually implementing FGFS XML
17 features, lets me rip off his descriptions of how stuff works so I can look
18 smart.
19
20 Some History:
21 ------------
22 Earlier versions of FGFS had assignments of joystick axis/buttons
23 and key bindings hard coded. If you had a joystick that did not use
24 the default channel assignments, or wanted different key bindings
25 you had to edit the source code and recompile.
26
27 Fortunately, around about v0.7.5 a "property manager" was implemented,
28 which facilitated being able to set the parameters for the joystick at runtime.
29 Version 0.7.7 saw an expanded role for the property manager and the
30 addition of a "command manager" that allows for binding of events to commands.
31 The code that does this is known as FGInput and is used to configure
32 keyboard command bindings as well as joysticks.
33
34 Storing alternate keyboard or joystick bindings can be done in a variety of ways.
35 The order of precedence for options is thus:
36
37 Source          Location                Format                 Scope
38 ------          --------                ------                 -----
39 command line    STDIN                   see examples           session
40 .fgfsrc         Users home directory.   command line options   single user
41 system.fgfsrc   $FG_ROOT                command line options   system wide
42 joystick.xml    $FG_ROOT                XML property list      system wide
43 keyboard.xml    $FG_ROOT                XML property list      system wide
44
45 First Things First
46 ------------------
47 I will cover joysticks first and save the keyboard stuff for later.
48 FGInput treats things in a generic enough way that the line between
49 joystick buttons and keyboard events starts to blur.
50
51 About XML
52 ---------
53 In case you were wondering, XML stands for eXtensible Markup Language.
54 It looks a lot like HTML, except you get to define your own tags. Well,
55 in the case of FGFS we defined the tags you need to configure things.
56 It is well suited for describing hierarchically organized structures, such as
57 the property tree FGFS uses to expose the it's innards to external applications.
58 Your XML configuration files for FGFS must start and end with the following
59 pair of tags.
60      <PropertyList>
61        <!-- this is a comment, See I told you it was like HTML -->
62      </PropertyList>
63
64 Determining your joystick output:
65 --------------------------------
66 FlightGear ships with a utility called js_demo. It will report
67 the number of joysticks attached to a system and their capabilites.
68 By observing the output of js_demo while working your joystick you can
69 determine what controls are where.
70 It should be noted that, at least on UNIX, numbering generally starts with
71 zero. In the following example the system has 1 joystick (js0) connected.
72 The output shown is from an analog Gravis BlackHawk with four buttons and
73 a throttle.
74
75 Typical output of js_demo:
76
77 Joystick test program.
78 ~~~~~~~~~~~~~~~~~~~~~~
79 Joystick 1 not detected              <!-- remember we start at 0 -->
80 Joystick 2 not detected
81 +---------------JS.0-----------------+
82 | Btns Ax:0 Ax:1 Ax:2                |
83 +------------------------------------+
84 | 0000 +0.0 +0.0 -1.0   .    .    .  |
85
86 The buttons are handled internally as a binary number in which bit 0 (the
87 least significant bit) represents button 0, bit 1 represents button 1, etc.,
88 but this number is displayed on the screen in hexadecimal notation, so:
89   0001 => button 0 pressed
90   0002 => button 1 pressed
91   0004 => button 2 pressed
92   0008 => button 3 pressed
93   0010 => button 4 pressed
94   0020 => button 5 pressed
95   0040 => button 6 pressed
96   ... etc. up to ...
97   8000 => button 15 pressed
98   ... and ...
99   0014 => buttons 2 and 4 pressed simultaneously
100   ... etc.
101
102
103 Default Joystick properties:
104 ----------------------------
105
106 Axis 0   = Aileron
107 Axis 1   = Elevator
108 Axis 2   = Rudder
109 Axis 3   = Throttle
110 Button 0 = All brakes
111 Button 1 = Elevator trim (up)
112 Button 2 = Elevator trim (down)
113
114
115 Okay, Now what?
116 ---------------
117 Now that you know what the output of the devices connected to the joystick
118 port (or USB port joystick devices) is, you probably want to dive straight
119 in and to start connecting to FGInput. If you are familiar with configuring
120 the joystick on versions of FGFS prior to 0.7.7 you can skip down to the
121 section "The Command Manager".
122 If you are a new FGFS user, you should at least skim the next bit since it
123 explains some concepts you may or may not know. It also covers some legacy
124 joystick options which have not been implemented yet in the context of the
125 command manager.
126
127
128 Modifiers For Raw Joystick Values
129 ---------------------------------
130 These concepts are expressed by supplying arguments to the joystick bindings.
131 The raw values coming from the joystick axes may not be suitable to use directly.
132 For that matter not all joysticks are created equal so understanding the basic
133 concepts should save you some time when experimenting to get the best performance.
134
135 The full order of precedence for axis properties is
136
137 1. The raw axis value ...
138 2. is adjusted to dead-band, ... deadband is implemented outside the command manager
139 3. then adjusted to offset, ...
140 4. then multiplied by factor, which ...
141 5. is assigned to the FlightGear control property.
142
143 Put another way....
144
145         cooked_value = (( raw_value > dead-band ) + offset) * factor
146
147
148 Axis properties:
149
150         dead-band
151
152 -1          0          1
153  .......................
154 -1         | |         1
155             ^
156         dead-band
157
158
159 This is an area where signals are ignored. It is used to compensate
160 for noise or potentiometers of dubious quality by creating a threshold
161 below which any signal is ignored.
162
163 The default of 0.1 for elevators and ailerons is very forgiving. A lower
164 number results in a tighter feel. In some cases such as throttle you may
165 wish to not set a deadband. Use a value of 0.0 in this case.
166
167
168
169         offset
170
171 -1  0                  1
172  .......................
173 -1  ^                  1
174  offset
175
176 Used to maximize a controls use of it's axis, as in the case of a
177 throttle where zero would be a minimum and not a center point like in the case
178 of a rudder. Typical value -1.0.
179
180
181         factor
182
183 Controls sensitivity of an axis. If the factor is too low it results in
184 control not reaching its maximum possible limit. Negating the number will result in
185 the control moving counter to the default. The default value is 1.0, think unity gain.
186
187 In my case, throttle behavior was inverted from what I preferred.
188 I set this value to -1.0 and everything was groovy.
189
190
191 The Command Manager
192 -------------------
193 Previous versions of FGFS allowed joystick output to be bound directly
194 to the property manager. This has changed for FGFS v0.7.7 and now events
195 are bound to commands. Commands *must* be specified for a binding to have
196 an effect. The current list of commands is broken down here into two
197 categories, mainly for my convenience.
198
199 Visual And File Related:
200
201 command            options          used for
202 -------            -------          --------
203 null               none             useful for clearing a previous binding
204 exit               none             Exiting FGFS
205 load               file name*       Load a saved flight
206 save               file name*       Save current flight
207 load-panel         path **          Change/reload panel
208 load-preferences   path **          Load preferences ***
209 screen-capture     none             Save a screenshot to ./fgfs-screen.ppm
210 view-cycle         none             Change the direction of the pilots view
211
212 *Saved/loaded relative to current working directory.
213 **The path includes the filename you wish to load and is relative to $FG_ROOT,
214   which is the location of the installed base package. The default for load-panel
215   is the value of /sim/panel/path (from preferences.xml) or if that is unset
216   Panel/Default/default.xml. The default for load preferences is preferences.xml.
217 ***This might make a good first binding to experiment with, since it's not currently
218    bound to anything. Reloading preferences will allow you to test settings
219    without having to sit through a restart of FGFS for every edit. You can
220    always (re)move it later.
221
222 Flight Control:
223 command         options                effect
224 -------         -------                ------
225 property-toggle property               toggle the property full on
226 property-assign "" "", value           targets a property for action
227 property-adjust "" "", step            Increment size for changes
228 property-swap   "" ""[0], "" ""[1]     Set values in a switch
229 property-scale  "" "", offset, factor  Processes the raw joystick value
230
231
232 Bindings
233 --------
234 A command may have more than one binding.  By default, the examples below
235 use just /binding or <binding>, but /binding[0] or <binding n="0"> is implied.
236 When bindings are specified in XML the indices are created automagically. If
237 you wish to avoid XML you must supply the index number for multiple bindings
238 in your command line formatted options.
239 Multiple properties in a single binding must have the index specified. For 
240 example if you build a switch that loads alternate panels the XML form
241 must be written thusly:
242
243 <command>property-swap</command>
244 <property n="0">/sim/panel/path=foo</property>
245 <property n="1">/sim/panel/path=bar</property>
246
247
248
249 Joystick Axes
250 -------------
251
252 Here's a sample Joystick axis declaration in XML:
253
254   <axis n="0">                        <!-- target an axis -->
255    <desc>Aileron</desc>               <!-- descriptive name (optional) -->
256    <binding>                          <!-- open a container for the binding -->
257     <command>property-scale</command>           <!-- pick a command -->
258     <property>/controls/aileron</property>      <!-- target a property -->
259    </binding>                                   <!-- closing tag for binding -->
260   </axis>                                       <!-- closing tag for axis -->
261
262 Remember how I said the property tree was a hierarchy? Thoughtful readers
263 will notice how the nested tags keep things organized.
264 This binding appears in the context /input/joysticks/js/, so the
265 command-line option equivalent of this declaration (leaving out the
266 'desc', which isn't strictly necessary), is
267
268   --prop:/input/joysticks/js[0]/axis[0]/binding/command=property-scale
269   --prop:/input/joysticks/js[0]/axis[0]/binding/property=/controls/aileron
270
271 Do you see how the command line versions uses a path to represent the hierarchy?
272 Cool! You should read README.xmlpanel next, working with FGFS XML configuration
273 system is easy and it's fun for the whole family! ( not sold in stores. excludes
274 tax and title. void where prohibited by law.)
275
276 Ok, back to business. The 'property-scale' command also recognizes 'offset' and
277 'factor' arguments. The "type" arguments shown in the following example are
278 specifying a double precision floating point number. A double has more discrete
279 steps and gives a smoother action than a plain float.
280
281   <axis n="2">
282    <desc>Throttle</desc>
283    <!-- See important note about dead-band below -->
284    <binding>
285     <command>property-scale</command>
286     <property>/controls/throttle</property>
287     <offset type="double">-1.0</offset>
288     <factor type="double">-0.5</factor>
289    </binding>
290   </axis>
291
292 or
293
294   --prop:/input/joysticks/js[0]/axis[2]/binding/command=property-scale
295   --prop:/input/joysticks/js[0]/axis[2]/binding/property=/controls/throttle
296   --prop:/input/joysticks/js[0]/axis[2]/binding/offset=-1.0
297   --prop:/input/joysticks/js[0]/axis[2]/binding/factor=-0.5
298
299 *Important Note About dead-band*
300 --------------------------------
301 You may recall from the section about raw axis value modifiers that dead-band
302 is implemented outside the command manager. This means that if you want to apply
303 a dead-band, the tag *must* precede the binding tag. If you are using the command
304 line format you must omit the 'binding' part like so:
305
306   --prop:/input/joysticks/js[0]/axis[2]/dead-band=0.005
307
308 Joystick Button Properties
309 --------------------------
310 Buttons, being boolean by nature, can use a little help. By this I mean that there
311 are times when you need momentary action, times where you need a repeating action
312 and sometimes you just want a plain old toggle. In order to facilitate this need
313 we have some tags that modify the actions of buttons.
314
315 <repeatable>
316  <!-- Will be either true or false. If it is true, holding down a button (or key) will
317       cause repeated events, say, for moving the trim; if false (the default), pressing
318       a key will cause only a single event. -->
319
320 <step>
321  <!-- The property-adjust command takes a 'step' argument specifying the
322       amount of the adjustment for each event. In the following example, the elevator
323       trim moves 0.1% for each event (without automatic repetition, you'd
324       have a pretty sore finger). -->
325
326 <value>
327  <!-- Use value on non-repeatables to supply the value for each consecutive press-->
328
329 <mod-up>
330  <!-- This stands for "modifier up", my favorite I think. This is used to set up a binding
331       for when you *release* a key. As you'll see, it comes in handy -->
332
333 Here's a sample joystick button declaration in XML:
334
335   <button n="1">                         <!-- target a button -->
336    <desc>Elevator trim up</desc>         <!-- optional description -->
337    <repeatable>true</repeatable>    <!-- Ok, repeatable is outside the command manager too -->
338    <binding>                             <!-- Open the "binding" node of the tree-->
339     <command>property-adjust</command>           <!-- pick a command type to bind -->
340     <property>/controls/elevator-trim</property> <!-- target a property -->
341     <step type="double">0.001</step>
342    </binding>
343   </button>
344
345 In command-line option syntax, this would appear as
346
347   --prop:/input/joysticks/js[0]/button[1]/repeatable=true     <!-- See? no 'binding' -->
348   --prop:/input/joysticks/js[0]/button[1]/binding/command=property-adjust
349   --prop:/input/joysticks/js[0]/button[1]/binding/property=/controls/elevator-trim
350   --prop:/input/joysticks/js[0]/button[1]/binding//step=0.001
351
352
353 Here's a slightly fancier declaration, that applies the left (differential) brakes
354 when button 4 is pressed, and releases them automatically when the user releases the
355 button:
356
357   <button n="4">
358    <desc>Left brake</desc>
359    <binding>
360     <command>property-assign</command>
361     <property>/controls/brakes[0]</property>
362     <value type="double">1.0</value>    <!-- brakes are a toggle so 1.0 represents on -->
363    </binding>
364    <mod-up>                    <!-- it's not a parking brake so we need to release it -->
365     <binding>
366      <command>property-assign</command>
367      <property>/controls/brakes[0]</property>
368      <value type="double">0.0</value>       <!-- 1.0 is on so 0.0 is off, right? -->
369     </binding>
370    </mod-up>
371   </button>
372
373 The first binding is straight-forward: when the button is pressed, the
374 'property-assign' command assigns the value 1.0 (i.e. full) to the left brake
375 property.  The second binding, however, is nested inside a 'mod-up' element,
376 it will be fired when the user *releases* the button, and will use the
377 'property-assign' command to assign the value 0.0 (i.e. none) to the left brake
378 property.  Repetition is left at the default value of false, so that the same
379 value will not be assigned over and over again.
380
381 Here's the command-line equivalent:
382
383   --prop:/input/joysticks/js[0]/button[4]/binding/command=property-assign
384   --prop:/input/joysticks/js[0]/button[4]/binding/property=/controls/brakes[0]
385   --prop:/input/joysticks/js[0]/button[4]/binding/value=1.0
386   --prop:/input/joysticks/js[0]/button[4]/mod-up/binding/command=property-assign
387   --prop:/input/joysticks/js[0]/button[4]/mod-up/binding/property=/controls/brakes[0]
388   --prop:/input/joysticks/js[0]/button[4]/mod-up/binding/value=0.0
389
390 Remember that more than one binding can be included in each context. Here's a
391 very hairy example from the default bindings that fires all three brakes when
392 button 0 is pressed, and releases all three when button 0 is released:
393
394   <button n="0">
395    <desc>Brakes</desc>
396    <binding>
397     <command>property-assign</command>
398     <property>/controls/brakes[0]</property>
399     <value type="double">1.0</value>
400    </binding>
401    <binding>
402     <command>property-assign</command>
403     <property>/controls/brakes[1]</property>
404     <value type="double">1.0</value>
405    </binding>
406    <binding>
407     <command>property-assign</command>
408     <property>/controls/brakes[2]</property>
409     <value type="double">1.0</value>
410    </binding>
411    <mod-up>
412     <binding>
413      <command>property-assign</command>
414      <property>/controls/brakes[0]</property>
415      <value type="double">0.0</value>
416     </binding>
417     <binding>
418      <command>property-assign</command>
419      <property>/controls/brakes[1]</property>
420      <value type="double">0.0</value>
421     </binding>
422     <binding>
423      <command>property-assign</command>
424      <property>/controls/brakes[2]</property>
425      <value type="double">0.0</value>
426     </binding>
427    </mod-up>
428   </button>
429
430 For people who take pleasure in avoiding XML, here's the command-line
431 equivalent (note the subscripts to distinguish multiple bindings; the
432 XML will handle this automatically):
433
434   --prop:/input/joysticks/button[0]/binding[0]/command=property-assign
435   --prop:/input/joysticks/button[0]/binding[0]/property=/controls/brakes[0]
436   --prop:/input/joysticks/button[0]/binding[0]/value=1.0
437   --prop:/input/joysticks/button[0]/binding[1]/command=property-assign
438   --prop:/input/joysticks/button[0]/binding[1]/property=/controls/brakes[1]
439   --prop:/input/joysticks/button[0]/binding[1]/value=1.0
440   --prop:/input/joysticks/button[0]/binding[2]/command=property-assign
441   --prop:/input/joysticks/button[0]/binding[2]/property=/controls/brakes[2]
442   --prop:/input/joysticks/button[0]/binding[2]/value=1.0
443   --prop:/input/joysticks/button[0]/mod-up/binding[0]/command=property-assign
444   --prop:/input/joysticks/button[0]/mod-up/binding[0]/property=brakes[0]
445   --prop:/input/joysticks/button[0]/mod-up/binding[0]/value=0.0
446   --prop:/input/joysticks/button[0]/mod-up/binding[1]/command=property-assign
447   --prop:/input/joysticks/button[0]/mod-up/binding[1]/property=brakes[1]
448   --prop:/input/joysticks/button[0]/mod-up/binding[1]/value=0.0
449   --prop:/input/joysticks/button[0]/mod-up/binding[2]/command=property-assign
450   --prop:/input/joysticks/button[0]/mod-up/binding[2]/property=brakes[2]
451   --prop:/input/joysticks/button[0]/mod-up/binding[2]/value=0.0
452
453
454 This is a good time to remind you that command line formatted options are used
455 in your .fgfsrc file. You can put them in $FG_ROOT/system.fgfsrc to make them
456 global.
457
458
459 Keyboard Bindings
460 -----------------
461
462 Keyboard bindings are almost exactly identical to joystick-button
463 bindings, as in the following example (the context is
464 /input/keyboard):
465
466   <key n="1">
467    <name>Ctrl-A</name>
468    <desc>Toggle autopilot altitude lock.</desc>
469    <binding>
470     <command>property-toggle</command>
471     <property>/autopilot/locks/altitude</property>
472    </binding>
473   </key>
474
475 There are a few gotcha's though.  First, the index of the key
476 specifies the key code that you're binding; in the above example, '1'
477 corresponds to Ctrl-A (as mentioned in the friendly comment).  Regular
478 key codes go up to 255; codes from 256 up represent special keys like
479 function and arrow keys (you can get the value from include/GL/glut.h,
480 but adding 256 to the special key code).  Here is the command-line
481 equivalent of the above, leaving out the documentation properties:
482
483   --prop:/input/keyboard/key[1]/binding/command=property-toggle
484   --prop:/input/keyboard/key[1]/binding/property=/autopilot/locks/altitude
485
486 (The 'property-toggle' command switches a boolean value between true and
487 false, so it needs no arguments except for the property name.)  DON'T
488 LEAVE OUT THE INDEX!!!
489
490 The second gotcha is that keys can take more modifiers than joystick
491 buttons.  In addition to mod-up (representing the key release), a key
492 may use any combination of nested 'mod-alt', 'mod-ctrl', and
493 'mod-shift' modifiers, as in the following example:
494
495   <key n="49">
496    <name>1</name>
497    <mod-shift>
498      <desc>Look back left</desc>
499      <binding>
500       <command>property-assign</command>
501       <property>/sim/view/goal-offset</property>
502       <value type="double">135</value>
503      </binding>
504    </mod-shift>
505   </key>
506
507 In this example, the '1' key combined with shift causes the view to
508 switch to back left.  Note that this will work only with the keypad 1,
509 since pressing shift+1 on the regular keyboard will give a '!'
510 character instead.
511
512 The input module tries to be smart about supplying control and shift
513 modifiers automatically where they make sense -- note that it wasn't
514 necessary to use a nested 'mod-ctrl' element for the ctrl-A binding
515 earlier, since a keycode less that 32 implies a control character
516 anyway.
517
518 With the new input module, the key-up events can also be detected for
519 the keyboard, so it's possible to have touch-sensitive brakes (etc.)
520 just as with the joystick:
521
522   <key n="44">
523    <name>,</name>
524    <desc>Left brake</desc>
525    <binding>
526     <command>property-assign</command>
527     <property>/controls/brakes[0]</property>
528     <value type="double">1.0</value>
529    </binding>
530    <mod-up>
531     <binding>
532      <command>property-assign</command>
533      <property>/controls/brakes[0]</property>
534      <value type="double">0.0</value>
535     </binding>
536    </mod-up>
537   </key>
538
539 Now here is a different way to bind a brake. In this example, there is
540 no <mod-up> tag, so it *does* work like a parking brake.
541
542 <key n="66">
543   <name>B</name>
544   <desc>Toggle parking brake on or off</desc>
545   <binding>
546    <command>property-toggle</command>
547    <property>/controls/brakes[0]</property>
548   </binding>
549   <binding>
550    <command>property-toggle</command>
551    <property>/controls/brakes[1]</property>
552   </binding>
553   <binding>
554    <command>property-toggle</command>
555    <property>/controls/brakes[2]</property>
556   </binding>
557  </key>
558