This chapter will show you how to configure Syzygy to work with your input devices.
New in Syzygy 1.2: This section is now relevant to running programs in Standalone Mode as well as in Cluster Mode (see Cluster Mode); applications can now load input device drivers in Standalone Mode, provided the Syzygy libraries were built as dynamic-link libraries.
As discussed in Syzygy System Configuration, a Syzygy parameter or 'dbatch' file contains two types of parameters, local (computer-specific) and global. Input devices typically have both. You define a global input device parameter that specifies which device driver module(s) to load and any filtering to be performed on the outputs. Then you define local input device parameters on the computer that the device is hooked up to that contain necessary configuration information for each driver module. Finally, you add an input map specification (another local parameter) to a virtual computer definition that makes the device definition a part of the virtual computer.
arTrackCalFilterfor correcting tracker position data based on a lookup table, and the
arConstantHeadFiltersubstitutes a fixed position for the user's tracked head position. They are basically obsolete, replaced by the PForth filter.
<pforth>field of the input device record. As an example, gamepads and joysticks on Linux typically report values between 0 and 64000, whereas on Windows they can report either [-32000,32000] or [0,64000]. Furthermore, the numbering of the buttons and joystick axes may vary between platforms or may simply be inconvenient. Syzygy applications expect a standardized joystick input:
This sort of standardization is easy to achieve with a PForth filter.
Many input devices require additional parameters. For example, devices that connect via serial interface may require e.g.:
When you want to load an input device in Standalone Mode, you must set the variable SZG_STANDALONE/input_config in the parameter file to the name of a global input device definition record. Note that currently if you specify an input device the Input Simulator is deactivated.
Finally, you add an input map specification to a virtual computer definition. This resembles a local parameter; it says that a particular global input device parameter will run on a particular computer in the context of the current virtual computer.
Input data in Syzygy comes in the form of a stream of events. There are currently three types of events. Matrix events, which usually represent the position and orientation (referred to in combination as the placement) of a tracking sensor. Axis events contain a floating-point number representing the state of a continuously-varying input. Button events contain an integer, usually representing a binary on-off input device. Within each class, events are identified by a 0-based index; in applications, a particular event type and index is generally associated with a particular function, for example matrix event #0 is generally assumed to represent the position and orientation of the sensor attached to the user's head. All three event types have a default value that will be returned whenever an application requests an event outside the range of existing indices; for matrices this is the identity matrix, for the other two types it is 0.
For a HowTo about getting your tracker data mapped in to Syzygy coordinates, see Tracker Coordinate Conversion
If your program isn't getting input, verify
DeviceServer is running on all computers connected to
lists all DeviceServers running on the cluster. If one is missing, check that computer's console for error messages.
If all DeviceServers are running and you're still not getting input events,
DeviceClient diagnostic program as described in
Syzygy Input Framework: Practical Examples.
As an example of an input device configuration record, here's the device definition for the wireless gamepad used in the Beckman Institute Cube. This gamepad has a 2-D joystick and 8 buttons. The device configuration record specifies the driver module to be loaded ('arJoystickDriver') and applies a PForth filter to re-scale the values returned by the joystick to the range [-1,1] (axis event #0 represents the left/right position of the joystick, while axis event #1 represents its front/back position):
<param> <name> cube_joystick </name> <value> <szg_device> <input_sources> arJoystickDriver </input_sources> <input_sinks></input_sinks> <input_filters></input_filters> <pforth> define filter_axis_0 getCurrentEventAxis 0.000031 * setCurrentEventAxis enddef define filter_axis_1 getCurrentEventAxis -0.000031 * setCurrentEventAxis enddef </pforth> </szg_device> </value> </param>
Note that if you combine two input sources in a single record, and they both provide some of the same kinds of events (e.g. both provide button events), then the event indices of the second input source follow those of the first. For example, if in this example we followed arJoystickDriver with another device which had two buttons, then the original gamepad's buttons would still have indices 0-7 but the new one's buttons would be 8 and 9.
Configuration records for tracking devices are generally the most complex. Here's the device definition for the MotionStar Wireless tracker we use in the Cube. The PForth filter aligns the tracker coordinate system with the Cube's structure, uses a lookup-table procedure to correct the distortions in the tracker data, compensates for the different ways the two sensors are mounted on the LCD goggles and on the gamepad, and applies a simple IIR filter to the vertical component of the head position to suppress the rather excessive noise:
<param> <name> cube_tracker </name> <value> <szg_device> <input_sources> arMotionstarDriver </input_sources> <input_sinks></input_sinks> <input_filters></input_filters> <pforth> initTrackerCalibration initIIRFilter /* Define stuff to rotate & remap positional coordinates and rotate orientation by 135 degrees around Y */ matrix yTransRotMatrix -45. yaxis yTransRotMatrix rotationMatrix vector oldLo vector oldHi vector newLo vector newHi 1.2 -5. 1.2 oldLo vectorStore 10.4 5. 10.4 oldHi vectorStore -5. 0. -5. newLo vectorStore 5. 10. 5. newHi vectorStore vector oldRange vector newRange oldHi oldLo 3 oldRange arraySubtract newHi newLo 3 newRange arraySubtract vector newOldRatio newRange oldRange 3 newOldRatio arrayDivide vector position define rescale_position position oldLo 3 position arraySubtract position newOldRatio 3 position arrayMultiply position newLo 3 position arrayAdd enddef matrix yRotMatrix -135 yaxis yRotMatrix rotationMatrix matrix inputMatrix matrix rotMatrix matrix transMatrix /* Apply transformations that are common to all sensors */ define filter_all_matrices inputMatrix getCurrentEventMatrix /* Extract translation, rotate it by 45 degrees about y */ inputMatrix position extractTranslation yTransRotMatrix position position vectorTransform /* Rescale position coords */ rescale_position /* Rotate rotation component about Y */ inputMatrix rotMatrix extractRotationMatrix yRotMatrix rotMatrix rotMatrix matrixMultiply /* Recombine translational and rotational components */ position transMatrix translationMatrixV transMatrix rotMatrix inputMatrix matrixMultiply /* Apply tracker-calibration lookup table */ inputMatrix inputMatrix doTrackerCalibration inputMatrix setCurrentEventMatrix enddef /* Fix rotational matrix components (depends on how sensors are mounted) */ matrix headZRotMatrix matrix wandZRotMatrix matrix wandTweakMatrix /* Head sensor is mounted sideways */ -90 zaxis headZRotMatrix rotationMatrix /* Wand sensor is mounted upside-down */ -180 zaxis wandZRotMatrix rotationMatrix /* Wand sensor points upwards by about 20 degrees with gamepad held subjectively level (actually tilted up slightly, but it feels right) */ -20. xaxis wandTweakMatrix rotationMatrix matrix wandRotMatrix wandZRotMatrix wandTweakMatrix wandRotMatrix matrixMultiply /* Head-specific filter (applied after generic, above) */ define filter_matrix_0 inputMatrix getCurrentEventMatrix inputMatrix inputMatrix doIIRFilter inputMatrix headZRotMatrix inputMatrix matrixMultiply inputMatrix setCurrentEventMatrix enddef /* Hand-specific filter (applied after generic) */ define filter_matrix_1 inputMatrix getCurrentEventMatrix inputMatrix wandRotMatrix inputMatrix matrixMultiply inputMatrix setCurrentEventMatrix enddef </pforth> </szg_device> </value> </param>