# Palomino - Control Module

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

- Index
- Overview
- Control of Aircraft (Current Craft)
- Joystick
- Command Events
- Replay
- Lua Scripting

## 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 Aircraft in response to joystick events. The control module no longer needs to be involved in keyboard handling (see Lua Scripting).

- Defines the "current" Aircraft
- Controls the current Aircraft by joystick (if enabled).
- Defers processing of button events to listeners (asymmetrically, control handles axis events).
- Has joystick configuration.

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

## Control of Aircraft (Current 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 Aircraft::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 Aircraft::Rotate().

## Joystick

[2008/01..2009/11]

There are two unrelated Joystick classes: input::JoystickDevice and control::Joystick.
This documents control::Joystick.

control::Joystick is the higher-level joystick class. It is a client of the low-level input::JoystickDevice. Input::JoystickDevice is basic: it enqueues joystick events but does no final actions. control::Joystick contains 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 (Lua scripts).

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 Aircraft in a `Command` object. The Aircraft class broadcasts control actions (rotation, throttle, brakes, etc) in events containing a Command object. Conversely, a Command object can apply a command to a Aircraft.

For example, Replay listens for Command events for a particular Aircraft and stores Commands in a container. To do a replay, Command::Execute(Aircraft) 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 Aircraft. 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(Aircraft).

### 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 Aircrafts 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 Aircraft 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 Aircraft, which begin with a time-stamp field (milliseconds), then the serialized Command. When recording first starts, the current state of the Aircraft 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:

- Replay
- ReplayRecorder
- ReplayPlayer
- ReplayPath (data class)
- ReplayPath::Step (Command with time-stamp)
- ReplayPath::Cursor (tracks current set of steps in animation path)
- Command (affects a Aircraft)

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: Wed Feb 10 15:23:55 CST 2010