Palomino - Control Module

©2004,2008  Jim E. Brooks   http://www.palomino3d.org


Contents


Overview

[2008/05]

The control module is a higher-level module (Mediator class) that handles system-neutral input propagated by the lower-level input module. control module has the joystick configuration. If the joystick is enabled, control will manipulate the current Craft in response to joystick events. The control module no longer needs to be involved in keyboard handling (see Lua Scripting).

+----------------+
|   application  |
+----------------+
| control module |
+----------------+
|   input module |
+----------------+
| device drivers |
+----------------+


Control of Craft

[2008/01]

An aircraft's rate-of-roll/pitch/yaw is computed by the physics code. The joystick/keyboard handlers in the control module rotate the "current craft" by calling Craft::PhysicalRotate(). Args passed are the level of control input (0.0,..,1.0 : 1.0 is all-the-way) and the frequency of polling control input. Internally, PhysicalRotate() computes an absolute/graphical degree that is passed to Craft::Rotate().


Joystick

[2008/01]

There are two unrelated Joystick classes (Singletons): input::Joystick and control::Joystick.
This documents control::Joystick.

control::Joystick is the higher-level joystick class. It is a client of the low-level input::Joystick. Note that input::Joystick is very simple: it enqueues raw axis/button values, and nothing else. Therefore, control::Joystick contains most of the higher-level joystick functionality. It does enabling, configuring, remapping, calibrating, and some handling of events. It handles axis events by controlling the current Craft. But it defers button events to listeners in the application.

control::Joystick is based on a joystick with 4 logical axises (roll/pitch/yaw/throttle). Joystick configuration is defined by joystick.conf. The configuration defines the mapping between logical and physical axises, and axis calibration.

Logical joystick axises

The higher-level joystick code is based on 4 logical axises.

0 = roll  (left/right)  joy X by convention
1 = pitch (up/down)     joy Y by convention
2 = yaw
3 = throttle            

Command Events

[2008/08]

The simulator abstracts control of a Craft in a Command object. The Craft class broadcasts control actions (rotation, throttle, brakes, etc) in events containing a Command object. Conversely, a Command object can apply a command to a Craft.

For example, Replay listens for Command events for a particular Craft and stores Commands in a container. To do a replay, Command::Execute(Craft) is called for every stored Command.

Command events could be used to network simulators.


Replay

[2008/09]

Replay registers a listener for Command events (roll, throttle, brakes, gear-down, etc) from a particular Craft. Replay stores Command objects with a time-stamp (Step class) in a STL container. To do a replay, the commands are replayed by calling Command::Execute(Craft).

Control Replay vs. Graphical Replay

Control replay means replaying events from input while being affected by the physics model. Graphical replay means replaying transformations. For example, recording a replay while piloting a F-15 Eagle, then applying a graphical replay to Spitfire would be unrealistic. But, a stored replay for Crafts with similar performance may be useful. Therefor, Replay records both types of data, but can replay either type (or a mixture) as needed.

Implementation

To save space, the replay data is compressed by zlib, rotations are stored as quaternions, and only steps that change (keyframes) are stored. Since graphical coordinates vary according to different missions, the position of a Craft converted to geo coordinates before storing. Replay::Play() can be passed a parameter to animate replays in different geo positions..

Replay data is saved to a file compressed using zlib (replay.dat.gz). Writing is done using gzstream. The format is human-readable. The first line is the version info (replay format). The following few lines provide other info and initial state. The bulk of the lines are commands to control a Craft, which begin with a time-stamp field (milliseconds), then the serialized Command. When recording first starts, the current state of the Craft is saved (the lines with milliseconds=0). In physics replay mode, phyRot (rotate using physics) are applied while qaut (graphical rotation) are ignored.

version 3
craft F18Aircraft
world flat
0 pos 8007 -15527.5 -528.25 
0 quat 0.710016 0.0154926 0.015358 0.703847  
0 throt 0 
0 kph 0 
0 gear 1 
0 brake 0 
363 throt 0.0629749 
396 pos 7997 -15697 -528.25 
443 kph 2.33392 
458 throt 0.988189
3842 pos 7987.05 -15630.4 -528.25 
3945 quat 0.70991 0.0527554 0.0520474 0.700383  

Replay is factored as these classes:

The class Replay is the interface. ReplayRecorder and ReplayPlayer both contain shared pointer to a ReplayPath. After recording, the player is given the shared pointer to the recorded path.

ReplayPath::Cursor naturally tracks the current step in the animation path. But it also will lookahead to future steps that control position/rotation. Cursor maintains a pair of position/rotation steps that the player will interpolate to smooth animation across timer-ticks that occur late (if program is running slow).


Lua Scripting

[2008/05]

The control module once had keyboard handling, but was eliminated after keyboard handlers were implemented by Lua scripts which directly use InputQueue.

The joystick C++ code in the control module survives because it's faster than Lua and its handling of axis events remains appropriate. But handling of button events is mission-specific, so the lua_bind module (sim.Joystick in Lua) registers a listener and provides an interface for Lua scripts to poll for button events. In summary, the control::Joystick interface remains the same as in previous versions but is used differently for Lua scripting.


Last modified: Tue Sep 23 09:06:52 EDT 2008